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:
$L['my_err_msg'
] in connected language files, you can just pass 'my_err_msg' and localized message will be displayed to a user.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($tpl, $block = 'MAIN') 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);
In the begining of this page we learn how to use built-in filters for user data input. Besides it developer can add custom filters for own need.
Shows it as example. Let's say we have a form with users mobile number input and we mut check it to match some basic rules.
We can do it in 3 simple steps:
Creating filtration function, assume it would be a cell-phone number (we need mobile operator code and a phone number itself):
function mobilenum_filter($input_value, $name) { // clear all except digits $filtered = preg_replace("/[^\d]/", '', $input_value); // check for number length if (preg_match('/\d{10,12}/', $filtered)){ // if length is in range from 10 to 12 — assume it as a valid number // then returns last 10 symbols (3 for operator code and 10 for number) return substr($filtered, -10); } else { // if it too short or too long mark it as had not passed filtration — returning NULL return NULL; } }
As a $input_value
argument function gets «raw» user inputed data. With $name
we get name of input field.
After filtration function had been created we need to set it in «filter registry»:
$cot_import_filters['MOB'][] = 'mobilenum_filter';
$cot_import_filters
is a filter registry. It's a global variable, so useglobal
keyword to use it inside any function.Now we can use it to filter some user data:
$mob_number = cot_import('mobnum', 'P', 'MOB');
where 'mobnum' — is name of form input field and 'MOB' is a name of our custom filter.
Also we can define several filtration function for one filter (one filter name). It would be called one be one. And input value consider valid only if all filtration steps is passed.
Bedankt: 58 tijden
Респект!!! я оказывается не все видел))))
Bedankt: 175 tijden
Очень полезная информация, чем больше таких статей в документации тем активнее будет приток новых пользователей.
p.s. В последнем примере описано:
"Для добавления параметра безопасности в ссылку используется функция" cot_xp()
а в примере кода cot_xg()
Bedankt: 58 tijden
Да все-же опечатка, cot_xg() для добавления в url, а cot_xp() для добавления скрытого input со значением x в форму.
Bedankt: 181 tijden
Исправил. спасибо, что читаете доки!
Bedankt: 27 tijden
Хорошо бы расписать
Что именно должно быть в шаблоне, что это относится к ресурсам и что нужно добавить параметр $error а то важная мелочь :)
Bedankt: 181 tijden
CrazyFreeMan, сейчас в ядре этого нет. Т.е. сделать такой вывод можно только написав свой обработчик. `$src` используется системой для разделения ошибок внутри соответствующего массива.