Input validation, error messages and exception handling the Cotonti way
As a PHP coder you might be used to $_GET, $_POST, $_COOKIE and such, but raw user input is not always good for your security and data integrity. That's why in Cotonti we import all data with cot_import() function:
function cot_import($name, $source, $filter, $maxlen = 0, $dieonerror = false, $buffer = false)
Parameters explained:
The returned value is either a value with a filter applied or NULL if validation failed and a user must enter another value instead. Here are some example calls:
$title = cot_import('title', 'P', 'TXT');
$code = cot_import('code', 'P', 'ALP');
$count = cot_import('count', 'P', 'INT');
$text = cot_import('text', 'P', 'HTM');
$notify = cot_import('notify', 'P', 'BOL');
After you have imported the values, you might want to check them against some value (first of all NULL which is returned if the input was not present or validation failed against the filter) and emit an error message.
In a verbose form you could do it like this:
if (is_null($count))
{
cot_error('Please enter a correct integer count', 'count');
}
cot_error() is a standard way to inform the system that something went wrong and to emit an error message that can be displayed later on. It has two parameters:
There is actually a shorter (and recommended) way to combine "if" and "cot_error()" call in case of error:
cot_check(is_null($count), 'Please enter a correct integer count', 'count');
cot_check() function has parameters:
You should check whether any errors have been found in the system before proceeding to action such as saving data in database using cot_error_found() function:
if (!cot_error_found())
{
// OK, we can save our data here because validation passed
}
This is it, now you know the basics of input validation in Cotonti.
Not all messages are error messages. You might as well inform the user that some operation ended successfully or warn him about something non-critical. Cotonti's messages API covers those cases too.
Here is the list of other Errors and Messages API functions:
Most of these functions are rather advanced and you will never have to use it in your modules or plugins. Let's have a look at the most common ones.
cot_message() function is similar to cot_error() but it is more generic. Here is the list of its parameters:
Use this function to inform the user about operation status when handling forms and returning back to the normal page:
cot_check($some_input != '', 'some_err_msg', 'some_input');
if (!cot_error_found())
{
// OK
// Save the data...
// ...
// Emit the message
cot_message('New item added successfully');
// Return to the interface
cot_redirect(cot_url('mymod', 'm=edit'));
}
Use cot_die() if something went wrong and you want to prevent further script execution:
if ($something_really_wrong)
{
// How did the user get here?
cot_die();
}
If that "something went wrong" is a standard situation that can be represented with a common HTTP error code and message, then use cot_die_message() function providing an error code:
if ($page_not_found)
{
// Print a standard 404 page with a correct HTTP code
cot_die_message(404);
}
You can also use cot_die_message() to handle non-standard errors and pass error page title and contents as 3rd and 4th arguments.
Now you can validate data and emit messages but how do you display them? Normally you need to add just two lines to add errors and messages display to your module or plugin.
The first one is in your template, add a line that includes standard template for messages output:
{FILE "{PHP.cfg.themes_dir}/{PHP.cfg.defaulttheme}/warnings.tpl"}
And the second one should be put in your PHP code somewhere before the MAIN is parsed, e.g.:
cot_display_messages($t);
The above example assumes that:
This assumption may be incorrect, so here is the explanation of cot_display_messages() parameters:
Now that you know the pieces of the puzzle, here is a complete picture of a real application for you:
// Connect language file with messages
require_once cot_langfile('mailout', 'plug');
if ($a == 'send' && $_SERVER['REQUEST_METHOD'] == 'POST')
{
// Handle form submission
$subject = cot_import('subject', 'P', 'TXT');
$limit = cot_import('limit', 'P', 'INT');
$content = cot_import('content', 'P', 'HTM');
// Input validation
cot_check(empty($subject), 'mailout_err_subject_empty', 'subject');
cot_check(empty($content), 'mailout_err_content_empty', 'content');
cot_check($limit <= 0, 'mailout_err_invalid_limit', 'limit');
if (!cot_error_found())
{
// Passed, save changes
$sql_limit = $limit > 0 ? "LIMIT $limit" : '';
$res = $db->query("SELECT user_name, user_email FROM $db_users $sql_limit");
$counter = 0;
foreach ($res->fetchAll() as $row)
{
$to = '"' . addslashes($row['user_name']) . '" <' . $row['user_email'] . '>';
cot_mail($to, $subject, $content, '', false, null, true);
$counter++;
}
// Emit success message
cot_message("$counter messages sent.");
}
// Redirect back to the original form and show messages there
cot_redirect(cot_url('admin', 'm=other&p=mailout', '', true));
}
// Display the user interface with the form
$t = new XTemplate(cot_tplfile('mailout.tools', 'plug'));
// Work with the template, assign tags and render blocks
// Don't forget to display the messages if they are present
cot_display_messages($t);
Thanks: 0
Thank you!
1. in the end of section 3 - add full function call reference:
I mean `cot_display_messages($tpl, $block = 'MAIN')` instead just `cot_display_messages()`. So «first time» user what we speak about next lines.
2. It would be usefull to write small example for uising custom filters with $cot_import_filters.
Total: 2, on page: 2
Thanks: 0
Me want to learn to program, thanks.