From d136963b74d456877cb9e8ed82d8b24b6cbca2d8 Mon Sep 17 00:00:00 2001
From: Peter Rotich <peter@osticket.com>
Date: Mon, 16 Nov 2015 07:45:48 +0000
Subject: [PATCH] Textarea input cleanup

Let textarea widgets parse and clean input based on configured text format.
Add cleanup routine to ThreadEntryBody
Clean response/note inputs
---
 include/class.forms.php  | 42 +++++++++++++++++++++++++++++++++++++---
 include/class.thread.php | 21 ++++++++++++++++++--
 include/class.ticket.php |  3 ++-
 scp/tickets.php          | 11 +++++------
 tickets.php              |  9 +++++----
 5 files changed, 70 insertions(+), 16 deletions(-)

diff --git a/include/class.forms.php b/include/class.forms.php
index 7e092ad9a..6f6d3b409 100644
--- a/include/class.forms.php
+++ b/include/class.forms.php
@@ -1995,6 +1995,13 @@ class ThreadEntryField extends FormField {
         return $media;
     }
 
+    function getConfiguration() {
+        global $cfg;
+        $config = parent::getConfiguration();
+        $config['html'] = (bool) $cfg->isRichTextEnabled();
+        return $config;
+    }
+
     function getConfigurationOptions() {
         global $cfg;
 
@@ -3112,6 +3119,21 @@ class TextareaWidget extends Widget {
         </span>
         <?php
     }
+
+    function parseValue() {
+        parent::parseValue();
+        if (isset($this->value)) {
+            $value = $this->value;
+            $config = $this->field->getConfiguration();
+            // Trim empty spaces based on text input type.
+            // Preserve original input if not empty.
+            if ($config['html'])
+                $this->value = trim($value, " <>br/\t\n\r") ? $value : '';
+            else
+                $this->value = trim($value) ? $value : '';
+        }
+    }
+
 }
 
 class PhoneNumberWidget extends Widget {
@@ -3533,8 +3555,8 @@ class SectionBreakWidget extends Widget {
 
 class ThreadEntryWidget extends Widget {
     function render($options=array()) {
-        global $cfg;
 
+        $config = $this->field->getConfiguration();
         $object_id = false;
         if ($options['client']) {
             $namespace = $options['draft-namespace']
@@ -3548,12 +3570,11 @@ class ThreadEntryWidget extends Widget {
         ?>
         <textarea style="width:100%;" name="<?php echo $this->field->get('name'); ?>"
             placeholder="<?php echo Format::htmlchars($this->field->get('placeholder')); ?>"
-            class="<?php if ($cfg->isRichTextEnabled()) echo 'richtext';
+            class="<?php if ($config['html']) echo 'richtext';
                 ?> draft draft-delete" <?php echo $attrs; ?>
             cols="21" rows="8" style="width:80%;"><?php echo
             Format::htmlchars($this->value) ?: $draft; ?></textarea>
     <?php
-        $config = $this->field->getConfiguration();
         if (!$config['attachments'])
             return;
 
@@ -3577,6 +3598,21 @@ class ThreadEntryWidget extends Widget {
         $field->setForm($this->field->getForm());
         return $field;
     }
+
+    function parseValue() {
+        parent::parseValue();
+        if (isset($this->value)) {
+            $value = $this->value;
+            $config = $this->field->getConfiguration();
+            // Trim spaces based on text input type.
+            // Preserve original input if not empty.
+            if ($config['html'])
+                $this->value = trim($value, " <>br/\t\n\r") ? $value : '';
+            else
+                $this->value = trim($value) ? $value : '';
+        }
+    }
+
 }
 
 class FileUploadWidget extends Widget {
diff --git a/include/class.thread.php b/include/class.thread.php
index 7b5b94418..fb3e03acd 100644
--- a/include/class.thread.php
+++ b/include/class.thread.php
@@ -2132,6 +2132,22 @@ class ThreadEntryBody /* extends SplString */ {
             return new ThreadEntryBody($text);
         }
     }
+
+    static function clean($text, $format=null) {
+        global $cfg;
+
+        if (!$format && $cfg)
+            $format = $cfg->isRichTextEnabled() ? 'html' : 'text';
+
+        switch ($format) {
+        case 'html':
+            return trim($text, " <>br/\t\n\r") ? $text : '';
+        case 'text':
+            return trim($text) ? $text : '';
+        default:
+            return $text;
+        }
+    }
 }
 
 class TextThreadEntryBody extends ThreadEntryBody {
@@ -2140,7 +2156,8 @@ class TextThreadEntryBody extends ThreadEntryBody {
     }
 
     function getClean() {
-        return Format::stripEmptyLines($this->body);
+        return  Format::stripEmptyLines(
+                self::clean($this->body, $this->format));
     }
 
     function prepend($what) {
@@ -2187,7 +2204,7 @@ class HtmlThreadEntryBody extends ThreadEntryBody {
     }
 
     function getClean() {
-        return trim($this->body, " <>br/\t\n\r") ? Format::sanitize($this->body) : '';
+        return Format::sanitize(self::clean($this->body, $this->format));
     }
 
     function getSearchable() {
diff --git a/include/class.ticket.php b/include/class.ticket.php
index 3fe355de2..42d920f68 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -3420,7 +3420,8 @@ implements RestrictedAccess, Threadable {
         }
 
         // TODO: Deny action based on selected department.
-
+        $vars['response'] = ThreadEntryBody::clean($vars['response']);
+        $vars['note'] = ThreadEntryBody::clean($vars['note']);
         $create_vars = $vars;
         $tform = TicketForm::objects()->one()->getForm($create_vars);
         $create_vars['cannedattachments']
diff --git a/scp/tickets.php b/scp/tickets.php
index b8fc7ae44..fd07aeba5 100644
--- a/scp/tickets.php
+++ b/scp/tickets.php
@@ -82,8 +82,10 @@ if($_POST && !$errors):
                 $errors['err'] = __('Action denied. Contact admin for access');
             }
             else {
-
-                if(!$_POST['response'])
+                $vars = $_POST;
+                $vars['cannedattachments'] = $response_form->getField('attachments')->getClean();
+                $vars['response'] = ThreadEntryBody::clean($vars['response']);
+                if(!$vars['response'])
                     $errors['response']=__('Response required');
 
                 if ($cfg->getLockTime()) {
@@ -107,10 +109,6 @@ if($_POST && !$errors):
                     $errors['err']=__('Email is in banlist. Must be removed to reply.');
             }
 
-            //If no error...do the do.
-            $vars = $_POST;
-            $vars['cannedattachments'] = $response_form->getField('attachments')->getClean();
-
             if(!$errors && ($response=$ticket->postReply($vars, $errors, $_POST['emailreply']))) {
                 $msg = sprintf(__('%s: Reply posted successfully'),
                         sprintf(__('Ticket #%s'),
@@ -143,6 +141,7 @@ if($_POST && !$errors):
             $attachments = $note_form->getField('attachments')->getClean();
             $vars['cannedattachments'] = array_merge(
                 $vars['cannedattachments'] ?: array(), $attachments);
+            $vars['note'] = ThreadEntryBody::clean($vars['note']);
 
             if ($cfg->getLockTime()) {
                 if (!$lock) {
diff --git a/tickets.php b/tickets.php
index 2c80ec91a..1887ae500 100644
--- a/tickets.php
+++ b/tickets.php
@@ -71,16 +71,17 @@ if ($_POST && is_object($ticket) && $ticket->getId()) {
         if(!$ticket->checkUserAccess($thisclient)) //double check perm again!
             $errors['err']=__('Access Denied. Possibly invalid ticket ID');
 
-        if(!$_POST['message'])
-
-            $errors['message']=__('Message required');
+        $_POST['message'] = ThredEntryBody::clean($_POST['message']);
+        if (!$_POST['message'])
+            $errors['message'] = __('Message required');
 
         if(!$errors) {
             //Everything checked out...do the magic.
             $vars = array(
                     'userId' => $thisclient->getId(),
                     'poster' => (string) $thisclient->getName(),
-                    'message' => $_POST['message']);
+                    'message' => $_POST['message']
+                    );
             $vars['cannedattachments'] = $attachments->getClean();
             if (isset($_POST['draft_id']))
                 $vars['draft_id'] = $_POST['draft_id'];
-- 
GitLab