diff --git a/include/class.category.php b/include/class.category.php index 5f67c6ee5d182e1b837a4fdc8187f05d0bb40c66..e890b079ee3532ddb53bf6851ac3dc9a7ba167fa 100644 --- a/include/class.category.php +++ b/include/class.category.php @@ -30,7 +30,7 @@ class Category { .' WHERE cat.category_id='.db_input($id) .' GROUP BY cat.category_id'; - if (!($res=db_query($sql)) || !db_num_rows($res)) + if (!($res=db_query($sql)) || !db_num_rows($res)) return false; $this->ht = db_fetch_array($res); @@ -54,14 +54,14 @@ class Category { function isPublic() { return ($this->ht['ispublic']); } function getHashtable() { return $this->ht; } - + /* ------------------> Setter methods <--------------------- */ function setName($name) { $this->ht['name']=$name; } function setNotes($notes) { $this->ht['notes']=$notes; } function setDescription($desc) { $this->ht['description']=$desc; } /* --------------> Database access methods <---------------- */ - function update($vars, &$errors) { + function update($vars, &$errors) { if(!$this->save($this->getId(), $vars, $errors)) return false; @@ -81,7 +81,7 @@ class Category { if(db_query($sql) && ($num=db_affected_rows())) { db_query('DELETE FROM '.FAQ_TABLE .' WHERE category_id='.db_input($this->getId())); - + } return $num; diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php index 26e93d7fd776b82ebbe7ad93c238815ce2102c73..84080172d5a1ac82ca985256e76eeb9058b37aeb 100644 --- a/include/class.dynamic_forms.php +++ b/include/class.dynamic_forms.php @@ -153,8 +153,6 @@ class DynamicForm extends VerySimpleModel { function save($refetch=false) { if (count($this->dirty)) $this->set('updated', new SqlFunction('NOW')); - if (isset($this->dirty['notes'])) - $this->notes = Format::sanitize($this->notes); return parent::save($refetch); } diff --git a/include/class.forms.php b/include/class.forms.php index 770736e84355c8432d84c7e69aa1cc8d14b7c0ab..6d5e9cf63dbca1d9cbe6680732c597c7bb6f094c 100644 --- a/include/class.forms.php +++ b/include/class.forms.php @@ -747,6 +747,10 @@ class TextboxField extends FormField { if (!call_user_func($func[0], $value)) $this->_errors[] = $error; } + + function parse($value) { + return Format::striptags($value); + } } class PasswordField extends TextboxField { @@ -1153,6 +1157,13 @@ class ThreadEntryField extends FormField { return false; } + function getConfiguration() { + global $cfg; + $config = parent::getConfiguration(); + $config['html'] = (bool) ($cfg && $cfg->isHtmlThreadEnabled()); + return $config; + } + function getConfigurationOptions() { global $cfg; @@ -1829,6 +1840,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 { @@ -2085,8 +2111,8 @@ class SectionBreakWidget extends Widget { class ThreadEntryWidget extends Widget { function render($client=null) { - global $cfg; + $config = $this->field->getConfiguration(); ?><div style="margin-bottom:0.5em;margin-top:0.5em"><strong><?php echo Format::htmlchars($this->field->get('label')); ?></strong>:</div> @@ -2098,11 +2124,10 @@ class ThreadEntryWidget extends Widget { data-draft-namespace="ticket.client" data-draft-object-id="<?php echo substr(session_id(), -12); ?>" <?php } ?> - class="richtext draft draft-delete ifhtml" + class="<?php if ($config['html']) echo 'richtext'; ?> draft draft-delete ifhtml" cols="21" rows="8" style="width:80%;"><?php echo Format::htmlchars($this->value); ?></textarea> <?php - $config = $this->field->getConfiguration(); if (!$config['attachments']) return; @@ -2126,6 +2151,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.organization.php b/include/class.organization.php index f2c092d9d94b1a507f509563759a38a5ca2ddb3d..9e5bedb7553b92d4b2c4964be08dbcf915fdf49f 100644 --- a/include/class.organization.php +++ b/include/class.organization.php @@ -356,6 +356,7 @@ class Organization extends OrganizationModel { static function fromVars($vars) { + $vars['name'] = Format::striptags($vars['name']); if (!($org = Organization::lookup(array('name' => $vars['name'])))) { $org = Organization::create(array( 'name' => $vars['name'], diff --git a/include/class.team.php b/include/class.team.php index 11670c8537b843e3223c182ebc42d74dd81c574e..1ae093c9427b4e6d587abc146d8ca3de04311094 100644 --- a/include/class.team.php +++ b/include/class.team.php @@ -232,6 +232,7 @@ class Team { if($id && $vars['id']!=$id) $errors['err']=__('Missing or invalid team'); + $vars['name'] = Format::striptags($vars['name']); if(!$vars['name']) { $errors['name']=__('Team name is required'); } elseif(strlen($vars['name'])<3) { diff --git a/include/class.thread.php b/include/class.thread.php index c13014848800056842f7ab7f7df41bcb82c8e345..9f38f47f4f177d1ba3178ddc54fbb39cb2312da8 100644 --- a/include/class.thread.php +++ b/include/class.thread.php @@ -1434,7 +1434,14 @@ class ThreadBody /* extends SplString */ { } function getClean() { - return trim($this->body); + switch ($this->type) { + case 'html': + return trim($this->body, " <>br/\t\n\r") ? $this->body: ''; + case 'text': + return trim($this->body) ? $this->body: ''; + default: + return trim($this->body); + } } function __toString() { @@ -1476,6 +1483,13 @@ class ThreadBody /* extends SplString */ { return new ThreadBody($text); } } + + static function clean($text, $format=null) { + global $cfg; + $format = $format ?: ($cfg->isHtmlThreadEnabled() ? 'html' : 'text'); + $body = static::fromFormattedText($text, $format); + return $body->getClean(); + } } class TextThreadBody extends ThreadBody { @@ -1484,7 +1498,7 @@ class TextThreadBody extends ThreadBody { } function getClean() { - return Format::stripEmptyLines($this->body); + return Format::stripEmptyLines(parent::getClean()); } function display($output=false) { @@ -1527,7 +1541,7 @@ class HtmlThreadBody extends ThreadBody { } function getClean() { - return trim($this->body, " <>br/\t\n\r") ? Format::sanitize($this->body) : ''; + return Format::sanitize(parent::getClean()); } function getSearchable() { diff --git a/include/class.ticket.php b/include/class.ticket.php index e64c38f40a34cc8ec1a6962db411fc4126bc2ad2..1b4c2badf0737366918a18c23524daf4d6452b98 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -888,7 +888,7 @@ class Ticket { $thisstaff ?: 'SYSTEM'); $alert = false; - if ($comments) { + if (($comments = ThreadBody::clean($comments))) { $note .= sprintf('<hr>%s', $comments); // Send out alerts if comments are included $alert = true; @@ -2179,6 +2179,8 @@ class Ticket { if(!$cfg || !$thisstaff || !$thisstaff->canEditTickets()) return false; + $vars['note'] = ThreadBody::clean($vars['note']); + $fields=array(); $fields['topicId'] = array('type'=>'int', 'required'=>1, 'error'=>__('Help topic selection is required')); $fields['slaId'] = array('type'=>'int', 'required'=>0, 'error'=>__('Select a valid SLA')); @@ -2917,6 +2919,8 @@ class Ticket { if (!$thisstaff->canAssignTickets()) unset($vars['assignId']); + $vars['response'] = ThreadBody::clean($vars['response']); + $vars['note'] = ThreadBody::clean($vars['note']); $create_vars = $vars; $tform = TicketForm::objects()->one()->getForm($create_vars); $create_vars['cannedattachments'] diff --git a/include/client/open.inc.php b/include/client/open.inc.php index ea0a100e7f67eeab48c0d1e61df43e14eda47f28..5bd45eed8ca30fdc5a76f0ce411ce2780bd12f6d 100644 --- a/include/client/open.inc.php +++ b/include/client/open.inc.php @@ -72,7 +72,8 @@ if ($info['topicId'] && ($topic=Topic::lookup($info['topicId']))) { else { ?> <tr><td colspan="2"><hr /></td></tr> <tr><td><?php echo __('Email'); ?>:</td><td><?php echo $thisclient->getEmail(); ?></td></tr> - <tr><td><?php echo __('Client'); ?>:</td><td><?php echo $thisclient->getName(); ?></td></tr> + <tr><td><?php echo __('Client'); ?>:</td><td><?php echo + Format::htmlchars($thisclient->getName()); ?></td></tr> <?php } ?> </tbody> <tbody id="dynamic-form"> diff --git a/scp/tickets.php b/scp/tickets.php index a6dd4ce8b003d51047f1bf2843a442ce49d39b46..004dcc9ec97d86fb0d8337d4e2a27f5f625cb220 100644 --- a/scp/tickets.php +++ b/scp/tickets.php @@ -68,8 +68,10 @@ if($_POST && !$errors): if(!$thisstaff->canPostReply()) $errors['err'] = __('Action denied. Contact admin for access'); else { - - if(!$_POST['response']) + $vars = $_POST; + $vars['cannedattachments'] = $response_form->getField('attachments')->getClean(); + $vars['response'] = ThreadBody::clean($vars['response']); + if(!$vars['response']) $errors['response']=__('Response required'); //Use locks to avoid double replies if($lock && $lock->getStaffId()!=$thisstaff->getId()) @@ -80,10 +82,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'), @@ -200,6 +198,7 @@ if($_POST && !$errors): $attachments = $note_form->getField('attachments')->getClean(); $vars['cannedattachments'] = array_merge( $vars['cannedattachments'] ?: array(), $attachments); + $vars['note'] = ThreadBody::clean($vars['note']); $wasOpen = ($ticket->isOpen()); if(($note=$ticket->postNote($vars, $errors, $thisstaff))) { diff --git a/tickets.php b/tickets.php index c65e9b6fd92601612a54631692fa60858312e4c2..752a2416a8edfbb23a032de5f19bd1398781df93 100644 --- a/tickets.php +++ b/tickets.php @@ -69,16 +69,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'] = ThreadBody::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'];