Assainissement des données d'entrée
Ne faites jamais confiance à l’entrée utilisateur. Validez et assainissez toujours toutes les données d’entrée avant de les utiliser. XOOPS fournit la classe MyTextSanitizer pour assainir l’entrée de texte et diverses fonctions d’aide pour la validation.
Documentation associée
Section intitulée « Documentation associée »- Security-Best-Practices - Guide de sécurité complet
- CSRF-Protection - Système de jetons et classe XoopsSecurity
- SQL-Injection-Prevention - Pratiques de sécurité de base de données
La règle d’or
Section intitulée « La règle d’or »Ne jamais faire confiance à l’entrée utilisateur. Toutes les données de sources externes doivent :
- Être validées : Vérifier qu’elles correspondent au format et au type attendus
- Être assainies : Supprimer ou échapper les caractères potentiellement dangereux
- Être échappées : Lors de la sortie, échapper pour le contexte spécifique (HTML, JavaScript, SQL)
Classe MyTextSanitizer
Section intitulée « Classe MyTextSanitizer »XOOPS provides the MyTextSanitizer class (commonly aliased as $myts) for text sanitization.
Obtention de l’instance
Section intitulée « Obtention de l’instance »// Get the singleton instance$myts = MyTextSanitizer::getInstance();Assainissement de texte de base
Section intitulée « Assainissement de texte de base »$myts = MyTextSanitizer::getInstance();
// For plain text fields (no HTML allowed)$title = $myts->htmlSpecialChars($_POST['title']);
// This converts:// < to <// > to >// & to &// " to "// ' to 'Traitement du contenu de la zone de texte
Section intitulée « Traitement du contenu de la zone de texte »La méthode displayTarea() method provides comprehensive textarea processing:
$myts = MyTextSanitizer::getInstance();
$content = $myts->displayTarea( $_POST['content'], $allowhtml = 0, // 0 = No HTML allowed, 1 = HTML allowed $allowsmiley = 1, // 1 = Smilies enabled $allowxcode = 1, // 1 = XOOPS codes enabled (BBCode) $allowimages = 1, // 1 = Images allowed $allowlinebreak = 1 // 1 = Line breaks converted to <br>);Méthodes d’assainissement courantes
Section intitulée « Méthodes d’assainissement courantes »$myts = MyTextSanitizer::getInstance();
// HTML special characters escaping$safe_text = $myts->htmlSpecialChars($text);
// Strip slashes if magic quotes are on$text = $myts->stripSlashesGPC($text);
// Convert XOOPS codes (BBCode) to HTML$html = $myts->xoopsCodeDecode($text);
// Convert smileys to images$html = $myts->smiley($text);
// Make clickable links$html = $myts->makeClickable($text);
// Complete text processing for preview$preview = $myts->previewTarea($text, $allowhtml, $allowsmiley, $allowxcode);Validation des données d’entrée
Section intitulée « Validation des données d’entrée »Validating Integer Values
Section intitulée « Validating Integer Values »// Validate integer ID$id = isset($_REQUEST['id']) ? (int)$_REQUEST['id'] : 0;
if ($id <= 0) { redirect_header('index.php', 3, 'Invalid ID'); exit();}
// Alternative with filter_var$id = filter_var($_REQUEST['id'] ?? 0, FILTER_VALIDATE_INT);if ($id === false || $id <= 0) { redirect_header('index.php', 3, 'Invalid ID'); exit();}Validating Email Addresses
Section intitulée « Validating Email Addresses »$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
if (!$email) { redirect_header('form.php', 3, 'Invalid email address'); exit();}Validating URLs
Section intitulée « Validating URLs »$url = filter_var($_POST['url'], FILTER_VALIDATE_URL);
if (!$url) { redirect_header('form.php', 3, 'Invalid URL'); exit();}
// Additional check for allowed protocols$parsed = parse_url($url);$allowed_schemes = ['http', 'https'];if (!in_array($parsed['scheme'], $allowed_schemes)) { redirect_header('form.php', 3, 'Only HTTP and HTTPS URLs are allowed'); exit();}Validating Dates
Section intitulée « Validating Dates »$date = $_POST['date'] ?? '';
// Validate date format (YYYY-MM-DD)if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) { redirect_header('form.php', 3, 'Invalid date format'); exit();}
// Validate actual date validity$parts = explode('-', $date);if (!checkdate($parts[1], $parts[2], $parts[0])) { redirect_header('form.php', 3, 'Invalid date'); exit();}Validating Filenames
Section intitulée « Validating Filenames »// Remove all characters except alphanumeric, underscore, and hyphen$filename = preg_replace('/[^a-zA-Z0-9_-]/', '', $_POST['filename']);
// Or use a whitelist approach$allowed_chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';$filename = '';foreach (str_split($_POST['filename']) as $char) { if (strpos($allowed_chars, $char) !== false) { $filename .= $char; }}Handling Different Input Types
Section intitulée « Handling Different Input Types »String Input
Section intitulée « String Input »$myts = MyTextSanitizer::getInstance();
// Short text (titles, names)$title = $myts->htmlSpecialChars(trim($_POST['title']));
// Limit lengthif (strlen($title) > 255) { $title = substr($title, 0, 255);}
// Check for empty required fieldsif (empty($title)) { redirect_header('form.php', 3, 'Title is required'); exit();}Numeric Input
Section intitulée « Numeric Input »// Integer$count = (int)$_POST['count'];$count = max(0, min($count, 1000)); // Ensure range 0-1000
// Float$price = (float)$_POST['price'];$price = round($price, 2); // Round to 2 decimal places
// Validate rangeif ($price < 0 || $price > 99999.99) { redirect_header('form.php', 3, 'Invalid price'); exit();}Boolean Input
Section intitulée « Boolean Input »// Checkbox values$is_active = isset($_POST['is_active']) ? 1 : 0;
// Or with explicit value check$is_active = ($_POST['is_active'] ?? '') === '1' ? 1 : 0;Array Input
Section intitulée « Array Input »// Validate array input (e.g., multiple checkboxes)$selected_ids = [];if (isset($_POST['ids']) && is_array($_POST['ids'])) { foreach ($_POST['ids'] as $id) { $clean_id = (int)$id; if ($clean_id > 0) { $selected_ids[] = $clean_id; } }}Select/Option Input
Section intitulée « Select/Option Input »// Validate against allowed values$allowed_statuses = ['draft', 'published', 'archived'];$status = $_POST['status'] ?? '';
if (!in_array($status, $allowed_statuses)) { redirect_header('form.php', 3, 'Invalid status'); exit();}Request Object (XMF)
Section intitulée « Request Object (XMF) »When using XMF, the Request class provides cleaner input handling:
use Xmf\Request;
// Get integer$id = Request::getInt('id', 0);
// Get string$title = Request::getString('title', '');
// Get array$ids = Request::getArray('ids', []);
// Get with method specification$id = Request::getInt('id', 0, 'POST');$search = Request::getString('q', '', 'GET');
// Check request methodif (Request::getMethod() !== 'POST') { redirect_header('form.php', 3, 'Invalid request method'); exit();}Creating a Validation Class
Section intitulée « Creating a Validation Class »For complex forms, create a dedicated validation class:
<?phpnamespace XoopsModules\MyModule;
class Validator{ private $errors = [];
public function validateItem(array $data): bool { $this->errors = [];
// Title validation if (empty($data['title'])) { $this->errors['title'] = 'Title is required'; } elseif (strlen($data['title']) > 255) { $this->errors['title'] = 'Title must be 255 characters or less'; }
// Email validation if (!empty($data['email'])) { if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) { $this->errors['email'] = 'Invalid email format'; } }
// Status validation $allowed = ['draft', 'published']; if (!in_array($data['status'], $allowed)) { $this->errors['status'] = 'Invalid status'; }
return empty($this->errors); }
public function getErrors(): array { return $this->errors; }
public function getError(string $field): ?string { return $this->errors[$field] ?? null; }}Usage:
$validator = new Validator();$data = [ 'title' => $_POST['title'], 'email' => $_POST['email'], 'status' => $_POST['status'],];
if (!$validator->validateItem($data)) { $errors = $validator->getErrors(); // Display errors to user}Sanitizing for Database Storage
Section intitulée « Sanitizing for Database Storage »When storing data in the database:
$myts = MyTextSanitizer::getInstance();
// For storage (will be processed again on display)$title = $myts->addSlashes($_POST['title']);
// Better: Use prepared statements (see SQL Injection Prevention)$sql = "INSERT INTO " . $xoopsDB->prefix('mytable') . " (title) VALUES (?)";$result = $xoopsDB->query($sql, [$_POST['title']]);Sanitizing for Display
Section intitulée « Sanitizing for Display »Different contexts require different escaping:
$myts = MyTextSanitizer::getInstance();
// HTML contextecho $myts->htmlSpecialChars($title);
// Within HTML attributesecho htmlspecialchars($title, ENT_QUOTES, 'UTF-8');
// JavaScript contextecho json_encode($title);
// URL parameterecho urlencode($title);
// Full URLecho htmlspecialchars($url, ENT_QUOTES, 'UTF-8');Common Pitfalls
Section intitulée « Common Pitfalls »Double Encoding
Section intitulée « Double Encoding »Problem: Data gets encoded multiple times
// Wrong - double encoding$title = $myts->htmlSpecialChars($myts->htmlSpecialChars($_POST['title']));
// Right - encode once, at the appropriate time$title = $_POST['title']; // Store rawecho $myts->htmlSpecialChars($title); // Encode on outputInconsistent Encoding
Section intitulée « Inconsistent Encoding »Problem: Some outputs are encoded, some are not
Solution: Always use a consistent approach, preferably encoding on output:
// Template assignment$GLOBALS['xoopsTpl']->assign('title', htmlspecialchars($title, ENT_QUOTES, 'UTF-8'));Missing Validation
Section intitulée « Missing Validation »Problem: Only sanitizing without validating
Solution: Always validate first, then sanitize:
// First validateif (!preg_match('/^[a-z0-9_]+$/', $_POST['username'])) { redirect_header('form.php', 3, 'Username contains invalid characters'); exit();}
// Then sanitize for storage/display$username = $myts->htmlSpecialChars($_POST['username']);Best Practices Summary
Section intitulée « Best Practices Summary »- Use MyTextSanitizer for text content processing
- Use filter_var() for specific format validation
- Use type casting for numeric values
- Whitelist allowed values for select inputs
- Validate before sanitizing
- Escape on output, not on input
- Use prepared statements for database queries
- Create validation classes for complex forms
- Never trust client-side validation - always validate server-side
#security #sanitization #validation #xoops #MyTextSanitizer #input-handling