From 201d5168fed8980edf8e6e2dd277c0663644acc8 Mon Sep 17 00:00:00 2001
From: Olivier PEREZ <olivier@olivierperez.fr>
Date: Sat, 11 Apr 2015 16:02:07 +0200
Subject: [PATCH] Refactor the input filter system

---
 admin/purge.php                               |  3 +-
 adminstuds.php                                | 19 ++++---
 .../Framadate/Services/InputService.php       | 29 +++++++++++
 app/inc/constants.php                         |  8 ++-
 create_poll.php                               | 49 +++++++++++--------
 studs.php                                     |  8 +--
 6 files changed, 78 insertions(+), 38 deletions(-)

diff --git a/admin/purge.php b/admin/purge.php
index c258353d..80b0f4e2 100644
--- a/admin/purge.php
+++ b/admin/purge.php
@@ -39,7 +39,8 @@ $securityService = new SecurityService();
 
 /* POST */
 /*-----*/
-$action = filter_input(INPUT_POST, 'action', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => NAME_REGEX]]);
+
+$action = $inputService->filterName($_POST['action']);
 
 /* PAGE */
 /* ---- */
diff --git a/adminstuds.php b/adminstuds.php
index 55918ad8..dc372a60 100644
--- a/adminstuds.php
+++ b/adminstuds.php
@@ -69,19 +69,19 @@ if (isset($_POST['update_poll_info'])) {
 
     // Update the right poll field
     if ($field == 'title') {
-        $title = strip_tags($_POST['title']);
+        $title = $inputService->filterTitle($_POST['title']);
         if ($title) {
             $poll->title = $title;
             $updated = true;
         }
     } elseif ($field == 'admin_mail') {
-        $admin_mail = filter_input(INPUT_POST, 'admin_mail', FILTER_VALIDATE_EMAIL);
+        $admin_mail = $inputService->filterMail($_POST['admin_mail']);
         if ($admin_mail) {
             $poll->admin_mail = $admin_mail;
             $updated = true;
         }
     } elseif ($field == 'description') {
-        $description = strip_tags($_POST['description']);
+        $description = $inputService->filterDescription($_POST['description']);
         if ($description) {
             $poll->description = $description;
             $updated = true;
@@ -117,14 +117,13 @@ if (isset($_POST['update_poll_info'])) {
             $updated = true;
         }
     } elseif ($field == 'name') {
-        $admin_name = filter_input(INPUT_POST, 'name', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => NAME_REGEX]]);
+        $admin_name = $inputService->filterName($_POST['name']);
         if ($admin_name) {
             $poll->admin_name = $admin_name;
             $updated = true;
         }
     } elseif ($field == 'hidden') {
-        $hidden = filter_input(INPUT_POST, 'hidden', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_REGEX]]);
-        $hidden = $hidden==null?false:true;
+        $hidden = isset($_POST['hidden']) ? $inputService->filterBoolean($_POST['hidden']) : false;
         if ($hidden != $poll->hidden) {
             $poll->hidden = $hidden;
             $updated = true;
@@ -153,7 +152,7 @@ if (!empty($_GET['vote'])) {
 // -------------------------------
 
 if (!empty($_POST['save'])) { // Save edition of an old vote
-    $name = filter_input(INPUT_POST, 'name', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => NAME_REGEX]]);
+    $name = $inputService->filterName($_POST['name']);
     $editedVote = filter_input(INPUT_POST, 'save', FILTER_VALIDATE_INT);
     $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
 
@@ -174,7 +173,7 @@ if (!empty($_POST['save'])) { // Save edition of an old vote
         }
     }
 } elseif (isset($_POST['save'])) { // Add a new vote
-    $name = filter_input(INPUT_POST, 'name', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => NAME_REGEX]]);
+    $name = $inputService->filterName($_POST['name']);
     $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
 
     if (empty($name)) {
@@ -232,8 +231,8 @@ if (isset($_POST['confirm_remove_all_votes'])) {
 // -------------------------------
 
 if (isset($_POST['add_comment'])) {
-    $name = filter_input(INPUT_POST, 'name', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => NAME_REGEX]]);
-    $comment = strip_tags($_POST['comment']);
+    $name = $inputService->filterName($_POST['name']);
+    $comment = $inputService->filterComment($_POST['comment']);
 
     if (empty($name)) {
         $message = new Message('danger', __('Error', 'The name is invalid'));
diff --git a/app/classes/Framadate/Services/InputService.php b/app/classes/Framadate/Services/InputService.php
index cf3b55ee..848f104e 100644
--- a/app/classes/Framadate/Services/InputService.php
+++ b/app/classes/Framadate/Services/InputService.php
@@ -50,4 +50,33 @@ class InputService {
         return in_array($value, $allowedValues, true) ? $value : null;
     }
 
+    public function filterTitle($title) {
+        return filter_var($title, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => TITLE_REGEX]]);
+    }
+
+    public function filterName($name) {
+        return filter_var($name, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => NAME_REGEX]]);
+    }
+
+    public function filterMail($mail) {
+        return filter_var($mail, FILTER_VALIDATE_EMAIL);
+    }
+
+    public function filterDescription($description) {
+        $description = str_replace("\r\n", "\n", $description);
+        return filter_var($description, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => DESCRIPTION_REGEX]]);
+    }
+
+    public function filterBoolean($boolean) {
+        return !!filter_var($boolean, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_TRUE_REGEX]]);
+    }
+
+    public function filterEditable($editable) {
+        return filter_var($editable, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => EDITABLE_CHOICE_REGEX]]);
+    }
+
+    public function filterComment($comment) {
+        return filter_var($comment, FILTER_SANITIZE_STRING);
+    }
+
 }
\ No newline at end of file
diff --git a/app/inc/constants.php b/app/inc/constants.php
index cada2f86..2c74a7f8 100644
--- a/app/inc/constants.php
+++ b/app/inc/constants.php
@@ -21,10 +21,14 @@
 const VERSION = '0.9';
 
 // Regex
-const POLL_REGEX = '/^[a-zA-Z0-9]+$/';
+const POLL_REGEX = '/^[a-z0-9]+$/i';
 const CHOICE_REGEX = '/^[012]$/';
 const NAME_REGEX = '/^[áàâäãåçéèêëíìîïñóòôöõúùûüýÿæœa-z0-9_ -]+$/i';
-const BOOLEAN_REGEX = '/^(on|off|true|false|1|0)$/';
+const TITLE_REGEX = '/^[áàâäãåçéèêëíìîïñóòôöõúùûüýÿæœa-z0-9\\/ &"\'(_)=~#{|`^@}$[\\]\\\\,;:!?.*-]+$/i';
+const DESCRIPTION_REGEX = "/^[áàâäãåçéèêëíìîïñóòôöõúùûüýÿæœa-z0-9\\/ &\"'(_)=~#{|`^@}$[\\]\\\\,;:!?.*\n-]+$/i";
+const COMMENT_REGEX = DESCRIPTION_REGEX;
+const BOOLEAN_REGEX = '/^(on|off|true|false|1|0)$/i';
+const BOOLEAN_TRUE_REGEX = '/^(on|true|1)$/i';
 const EDITABLE_CHOICE_REGEX = '/^[0-2]$/';
 
 // CSRF (300s = 5min)
diff --git a/create_poll.php b/create_poll.php
index e126e479..8682c74b 100644
--- a/create_poll.php
+++ b/create_poll.php
@@ -18,13 +18,22 @@
  */
 
 use Framadate\Form;
-use Framadate\Editable;
+use Framadate\Services\InputService;
 use Framadate\Utils;
 
 include_once __DIR__ . '/app/inc/init.php';
 
 const GO_TO_STEP_2 = 'gotostep2';
 
+
+/* Services */
+/*----------*/
+
+$inputService = new InputService();
+
+/* PAGE */
+/* ---- */
+
 if (!isset($_SESSION['form'])) {
     $_SESSION['form'] = new Form();
 }
@@ -42,32 +51,30 @@ if (isset($_GET['type']) && $_GET['type'] == 'date' ||
 
 // We clean the data
 $goToStep2 = filter_input(INPUT_POST, GO_TO_STEP_2, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^(date|classic)$/']]);
-$title = filter_input(INPUT_POST, 'title', FILTER_SANITIZE_STRING);
-$name = filter_input(INPUT_POST, 'name', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => NAME_REGEX]]);
-$mail = filter_input(INPUT_POST, 'mail', FILTER_VALIDATE_EMAIL);
-$description = filter_input(INPUT_POST, 'description', FILTER_SANITIZE_STRING);
-$editable = filter_input(INPUT_POST, 'editable', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => EDITABLE_CHOICE_REGEX]]);
-$receiveNewVotes = filter_input(INPUT_POST, 'receiveNewVotes', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_REGEX]]);
-$receiveNewComments = filter_input(INPUT_POST, 'receiveNewComments', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_REGEX]]);
-$hidden = filter_input(INPUT_POST, 'hidden', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_REGEX]]);
+if ($goToStep2) {
+    $title = $inputService->filterTitle($_POST['title']);
+    $name = $inputService->filterName($_POST['name']);
+    $mail = $inputService->filterMail($_POST['mail']);
+    $description = $inputService->filterDescription($_POST['description']);
+    $editable = $inputService->filterEditable($_POST['editable']);
+    $receiveNewVotes = isset($_POST['receiveNewVotes']) ? $inputService->filterBoolean($_POST['receiveNewVotes']) : false;
+    $receiveNewComments = isset($_POST['receiveNewComments']) ? $inputService->filterBoolean($_POST['receiveNewComments']) : false;
+    $hidden = isset($_POST['hidden']) ? $inputService->filterBoolean($_POST['hidden']) : false;
+
+    // On initialise également les autres variables
+    $error_on_mail = false;
+    $error_on_title = false;
+    $error_on_name = false;
+    $error_on_description = false;
 
-
-// On initialise �galement les autres variables
-$error_on_mail = false;
-$error_on_title = false;
-$error_on_name = false;
-$error_on_description = false;
-
-
-if (!empty($_POST[GO_TO_STEP_2])) {
     $_SESSION['form']->title = $title;
     $_SESSION['form']->admin_name = $name;
     $_SESSION['form']->admin_mail = $mail;
     $_SESSION['form']->description = $description;
     $_SESSION['form']->editable = $editable;
-    $_SESSION['form']->receiveNewVotes = ($receiveNewVotes !== null);
-    $_SESSION['form']->receiveNewComments = ($receiveNewComments !== null);
-    $_SESSION['form']->hidden = ($hidden !== null);
+    $_SESSION['form']->receiveNewVotes = $receiveNewVotes;
+    $_SESSION['form']->receiveNewComments = $receiveNewComments;
+    $_SESSION['form']->hidden = $hidden;
 
     if ($config['use_smtp'] == true) {
         if (empty($mail)) {
diff --git a/studs.php b/studs.php
index f79eca72..aa0b25bd 100644
--- a/studs.php
+++ b/studs.php
@@ -118,7 +118,7 @@ if (!empty($_GET['vote'])) {
 // -------------------------------
 
 if (!empty($_POST['save'])) { // Save edition of an old vote
-    $name = filter_input(INPUT_POST, 'name', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => NAME_REGEX]]);
+    $name = $inputService->filterName($_POST['name']);
     $editedVote = filter_input(INPUT_POST, 'save', FILTER_VALIDATE_INT);
     $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
 
@@ -146,7 +146,7 @@ if (!empty($_POST['save'])) { // Save edition of an old vote
         }
     }
 } elseif (isset($_POST['save'])) { // Add a new vote
-    $name = filter_input(INPUT_POST, 'name', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => NAME_REGEX]]);
+    $name = $inputService->filterName($_POST['name']);
     $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
 
     if (empty($name)) {
@@ -178,8 +178,8 @@ if (!empty($_POST['save'])) { // Save edition of an old vote
 // -------------------------------
 
 if (isset($_POST['add_comment'])) {
-    $name = filter_input(INPUT_POST, 'name', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => NAME_REGEX]]);
-    $comment = strip_tags($_POST['comment']);
+    $name = $inputService->filterName($_POST['name']);
+    $comment = $inputService->filterComment($_POST['comment']);
 
     if (empty($name)) {
         $message = new Message('danger', __('Error', 'Name is incorrect'));
-- 
GitLab