Documentation

Documentation includes the basic principles of the system. Future corrections are possible, as MonoCMS continues to evolve.

Login and security

session_name('MON');
session_start();
if (session_name() == 'MON')
if ( !isset($_SESSION['username'])) {
 ...
The user identification starts with the session_start()function, which initiates a new or continues an existing session. The use of the name for one session is optional, but in our case it should be used so that the system can maintain a safe single user connection. PHP always stores a corresponding cookie in the browser of the user, which includes a unique ID. Similarly, the session must be distinct from any session that might exist on the same domain or website. In the second condition, we examine if the user has already been logged in by checking whether or not there is a stored username in the session. Since we use a session name it is ensured that the connection to the session is not affected by other sessions.

SimpleXML

Using SimpleXML is very common when working with xml files. MonoCMS is full of SimpleXML elements and objects like the one below:
$monousers = new simpleXMLElement('filesinfo/log.xml',null,true);
This way we gather up all user data to a SimpleXML element and continue to user identification and data saving in the log file. If the combination of username and password given by the user, exists in this element, the user is allowed to visit the control panel. Note that while the username is stored in the session and saved in the log file, the user's password is never stored, either in session or the log file. User identification is based on password_hash function.

Cryptography

Password_hash first appeared in PHP 5.5 and we use also it for password encryption.
password_verify($_POST['password'],$password);
The password hash is saved and compared to the hash of the password given by the user, using password_verify. Moreover, using password_needs_rehash, PHP checks whether or not password needs to be re-encrypted, which happens in two cases:
- When a different version of PHP, that has a different default encryption algorithm, has been installed.
- When set-cost.php gives us a different cost result than the current one. The cost is a parameter of password_hash and password_needs_rehash functions and regulates the complexity of encryption by delaying the execution of these functions. It is also written inside the hash itself, as an integer.
In the case of MonoCMS, it depends on the server performance. MonoCMS follows the PHP example of automatically finding a good cost. In case of a hardware upgrade or the system is transferred to another server, or even just a usual login, it is possible that the cost will change and force password_needs_rehash to re-hash the user password. This procedure is done while the user is logging in.
password_needs_rehash($password, PASSWORD_DEFAULT, ["cost" => $cost]);
In the line above, if the new value of $cost is not the same as the value of cost contained in $password, which is the hash already in use, then the password is going to be re-encrypted, using the new value.

Re-hashing starts in set-cost.php:
$phtime = 0.2; // 200 ms

for ($cost = 4; ; $cost++){

// password_hash speed test

...
Time is set at 200 milliseconds. We test password_hash speed, starting from cost = 4. If the test is completed in less than 200ms, the cost value increases by 1 and the test is repeated. If completion time is more than 200ms, the test is over and we get the result. This means that the user identification as well as the login process are going to last at least 200ms.

What if we use MonoCMS on a faster server? Does that mean that user login will also be faster?

The answear is, no. The login speed stays the same. The variable $phtime contents control the system login speed and this is the basic principle of the security system. Changing the cost is the adjustment that keeps MonoCMS login speed always the same.

So if the server is slow, we get a low cost. If it is fast, we get a high cost.

In other words, we want to give a constant level of performance for every web server, by setting a specific speed value, so that the server can not be charged with annoying delays and simultaneously be protected from attacks by malicious users.

If the speed limit is set over 200ms, the cost will increase, safety becomes better, but login speed will increase as well.

Note that the 200ms, is not the total time that is needed to login. It is actually the minimum. The total login duration is unknown and varies from 200ms to 1 second. If a password_hash test lasts more than 1 second, the cost and encrypted password, remain the same.
if (($finish-$start) > 1) {

$pass_info = password_get_info($password);
$cost = $pass_info[options][cost];
break;
}
Below is an example of manually applying a cost:
password_needs_rehash($password, PASSWORD_DEFAULT, ["cost" => 11]);

Redirect and exit() function.

exit() function is used with caution in data_connect.php. When a user is identified, a redirection is needed to sent the user to the control panel main page, but not the exit() function, because this might mess up the whole user identification operation. We can exit() though when a user without credentials is detected.
print '<script type="text/javascript">top.window.location = "login.php";</script>';
exit();
MonoCMS also blocks a user after a specific number of failed login attempts. This is also a situation when we want to use header() and exit().

User block

A user is blocked after a few failed login attempts. A blocked user doesn't have access to any of MonoCMS pages, including the login page. You can change the values of this function by modifiyng the next lines inside data_connect.php.
// Failed login attempts before blocking a user
$block = 10;

// Minutes passed to unblock a user
$unblock = 15;

Logging activity and data

We use /monofiles/filesinfo/log.xml, in several cases:

- To load general information. This information can be: The total number of posts, the total number of pages, the date of the last failed login attempt and the last modification date of any of the above. This line shows us how to get the total number of pages:
get_log('pages');

- To load personal account information. We do this by using either the username or the userID as a parameter. The userID is a unique code which is stored along with other account information:
get_account($_SESSION[userID])['rights'];
In the example above, we retrieve the the user's account type, using the userID that we have previously saved in the session. It should be noted that despite the fact that the userID is saved alongside the username, it doesn't work as a password and it doesn't grant any access to the user.

- To udate all of the above. For example, this is how we can change the total number of posts to 12:
update_log(posts,12);
This is how we update an account, if information is given:
update_account($id,'set');
We can also delete an account in a similar way:
update_account($id,'delete');
The $id variable contains the userID.


XML & HTM

Saving data in MonoCMS is done in three differrent ways:

- By writing to xml files,
- By writing to htm files,
- By caching in session.

Saving in session is mainly used for control panel needs and all data is deleted as soon as the user is logged out. Xml και htm files are useful when we want to store posts and pages data, like text, titles, images etc. We save most of the posts information inside xml files, except for the main body of a post, which is written using the text editor and is saved in a separate htm file. Xml is used for the majority of data storing such as user accounts info and logging activity.

Saving html code inside xml files is considered a bad practice in some cases, but it is not uncommon. In general we try to avoid storing html in xml.

SimpleXML helps us encode and decode html characters when we need to. Saving a large page full of html code though is going to result in a relatively large file. Next example shows us what happens when we save html code inside an xml file:

What the browser prints:
SimpleXML
The html code, saved in html file is 48 characters:
&nbsp;&nbsp;<a href="#section-1-1">SimpleXML</a>
  The html code , saved in a xml file is 68 characters:
&amp;nbsp;&amp;nbsp;&lt;a href="#section-1-1"&gt;SimpleXML&lt;/a&gt;
This happens because of some characters that must be encoded when saved in xml.

Posts xml

Every post's data is stored inside a xml file, together with a similar file that has the characters "nu" in front of the filename. i.e: 145829963.xml & nu145829963.xml. This way we can store two versions of a post, the one that is published and another one that can be modified while leaving the published version untouched.

The names of the xml files that store posts and pages data, are generated automatically, simply using the time() function.
<input type="text" id="uuid" name="uniqueid" value="<?php
if(isset($osbase))
    print $osbase;
else
 echo time()
?>" form="mainform" hidden>

User accounts

Account management allows multiple users to have access to MonoCMS control panel, using their personal username and password. There are two differrent types of accounts:

- Administrator,
- Author.

As an administrator, the user has complete access to control panel.
Authors can create their own posts and also have access to some personal account information modification.

In general:

- Only an administrator has access to account manager.
- Every administrator can create or delete accounts of other administrators and authors.
- An administrator account rights can be changed to author and backwards.
- Administrators can delete their own account as well.
- The last administrator account cannot be deleted or be converted to author.
- SInce version 3.0, an administrator can also be the website owner. This doesn't mean much, except that the owner's name and icon will appear as the website's host.


Visitor pages

Visitor pages are located in the home directory and the posts directory, they are based on theme files. These are the home page and the pages pattern.
- A page is a simple, usually a static content page, such as the aboutus or contact page. A post is part of the the home page blog style flow and usually contains the dynamically updated content of the website. Both pages and posts share the same pattern:

Next line is loading the website title:
load_settings()['title'];
Website description,
load_settings()['description'];
Navigation,
load_settings()['navigation'];
Set-general.php contains all the possible function parameters of load_settings():
$page_settings = array("title" => $set->general->title ,"description" => $set->general->description ,
"results-per-page" => $set->general->indexposts->results ,"lastmodified" => $set->general->indexposts->lastmod ,
"navigation" => $set->general->navigation ,"dates" => $set->general->dateshow );
en_code.php contains more functions to load strings, inside the control panel or a visitor's page.

Example of loading a page's meta description:
load_meta_description($des);
Loadhtml, from an xml file:
load_xml($str);
Load an htm file :
load_htm($file);
Simply remove tags:
remove_tags($str);

Other functions

load_navigation();
Using this function we can load the navigation menu of our website.


Formatting and appearance

The appearance of the public pages is affected by style.css and other css files

The date in index and control panel is shown in google style, showng how much time has passed since a post, instead of the actual date or time which is shown in a post.

We can relatively easy change the appearance of our website. Php code starts with '<?php ' and ends with  ' ?>'. If we leave those parts of the code intact, page functionality will not be affected. Of course every part of the page plays a specific role and a user should think very carefully before editing these pages. The next line is loading the website title:
<?php load_settings()['title']; ?>
We could easily add a container to a php generated element, like this:
<h1><?php load_settings()['title'] ?></h1>
or this:
<div id="heading"><h1><?php load_settings()['title'] ?></h1></div>
We can remove the php generated element completely and write our own title, like this:
<div id="heading"><h1>New title</h1></div>
It is good to remember that changing a theme file, changes the overall content, but changing content in the text editor affects a single page only.

Auto generated HTML

Auto generated code exists in more files than just the patterns. For example, in set-posts.php, the next piece of code is used to generate the posts flow in our home page:
print '<div class="post">'.$post_time.PHP_EOL.'<h2><a href="'.$path.$link.'">'.$title.'</a></h2>'.PHP_EOL.' <div class="content-text">'.$excerpt.'</div>'.PHP_EOL.'</div>';

Code that appears inside the control panel, is styled by monofiles/cmstyle.css.

Posts

The "New post" page contains the next elements: title, description, filename and text-editor.

The title is the post's <title></title> tag and is also used as the post's heading. Also remember that html elements are not allowed inside the title. This is how the title is loaded inside the posts:
echo load_settings()['title']

The description is used as the meta description of the post:
<meta name="description" content="A really short description">
Post filenames are automatically generated but it is good to write our own filename, to help our visitors understand our content. For example "about-us" or "contact-us" could be good choices.

The most important part of our website is our actual unique content. This is why we use the text editor to ensure the high quality of our content. Text editor uses a toggle button to change between code view and 'wysiwyg' mode. We can also use the text editor function to add some html elements or insert links and image files.

Backups

Most web servers keep a website's backup, but it is really easy with MonoCMS as well. More specifically:

/monofiles/autosaves/: Contains all posts details.

/monofiles/savedpages/: Contains all pages details.

/monofiles/filesinfo/: Contains all user accounts, log info and general settings.

Transfer system

Transfering MonoCMS files is as easy as copying files and folders from a directory to another.

Althought transfering is very easy, merging two different installations into one, is not possible. At least not without extra effort.

For safety reasons we suggest creating new user account, instead of manually merging the files containing the users info.


Althought there is no standard procedure for merging two systems into one, we could transfer the posts and pages files to their respective directories. There are two problems when trying to do that though:
First is that we might come accross with double filenames, which is rare but still possible and second problem is that the information of the total number of posts and pages must be manually changed.

Updating

Updating a MonoCMS to any newest version usually requires uploading only the files inside the"monofiles" folder.

Theme

There was a big change in MonoCMS 3.0 regarding themes. MonoCMS doesn't support multiple themes anymore, but only different layouts. This is a solid and straight solution that brings up the idea of concentrating on the content quality instead of appearance.

Last modified on June 9, 2017.