Files
btpxpress-frontend/utils/inputSanitizer.ts
2025-10-13 05:29:32 +02:00

132 lines
3.2 KiB
TypeScript

/**
* Utilitaires de sanitisation pour les entrées utilisateur côté frontend
*/
export class InputSanitizer {
/**
* Encode les entités HTML pour prévenir XSS
*/
static encodeHtml(input: string): string {
if (!input) return input;
const div = document.createElement('div');
div.textContent = input;
return div.innerHTML;
}
/**
* Supprime les balises HTML dangereuses
*/
static stripHtml(input: string): string {
if (!input) return input;
return input.replace(/<[^>]*>/g, '');
}
/**
* Sanitise un email
*/
static sanitizeEmail(email: string): string {
if (!email) return email;
return email.trim().toLowerCase();
}
/**
* Sanitise un nom/prénom
*/
static sanitizeName(name: string): string {
if (!name) return name;
// Supprimer les caractères dangereux
let sanitized = name.replace(/[<>'"&]/g, '');
// Garder seulement les lettres, espaces, tirets et apostrophes
sanitized = sanitized.replace(/[^a-zA-ZàáâäçéèêëíìîïñóòôöúùûüÿýÀÁÂÄÇÉÈÊËÍÌÎÏÑÓÒÔÖÚÙÛÜŸÝ\s'-]/g, '');
return sanitized.trim();
}
/**
* Sanitise un numéro de téléphone
*/
static sanitizePhone(phone: string): string {
if (!phone) return phone;
// Garder seulement les chiffres et le + au début
return phone.replace(/[^0-9+]/g, '');
}
/**
* Sanitise une adresse
*/
static sanitizeAddress(address: string): string {
if (!address) return address;
// Supprimer les caractères dangereux
let sanitized = address.replace(/[<>'"&]/g, '');
// Garder les caractères alphanumériques et ponctuation courante
sanitized = sanitized.replace(/[^a-zA-Z0-9àáâäçéèêëíìîïñóòôöúùûüÿýÀÁÂÄÇÉÈÊËÍÌÎÏÑÓÒÔÖÚÙÛÜŸÝ\s,.-]/g, '');
return sanitized.trim();
}
/**
* Valide qu'une entrée ne contient pas de code malveillant
*/
static isInputSafe(input: string): boolean {
if (!input) return true;
const dangerousPatterns = [
/<script[^>]*>.*?<\/script>/gi,
/javascript:/gi,
/vbscript:/gi,
/onload=/gi,
/onerror=/gi,
/onclick=/gi,
/onmouseover=/gi,
/eval\(/gi,
/expression\(/gi,
];
return !dangerousPatterns.some(pattern => pattern.test(input));
}
/**
* Sanitise une entrée générique
*/
static sanitize(input: string): string {
if (!input) return input;
// Supprimer les balises HTML
let sanitized = this.stripHtml(input);
// Encoder les entités HTML
sanitized = this.encodeHtml(sanitized);
return sanitized.trim();
}
}
/**
* Hook React pour la sanitisation automatique des inputs
*/
export function useSanitizedInput(initialValue: string = '') {
const [value, setValue] = React.useState(initialValue);
const setSanitizedValue = (newValue: string) => {
const sanitized = InputSanitizer.sanitize(newValue);
setValue(sanitized);
};
return [value, setSanitizedValue] as const;
}
// Import React pour le hook (si disponible)
let React: any;
try {
React = require('react');
} catch (e) {
// React non disponible, le hook ne sera pas utilisable
}