diff --git a/WHATSNEW.md b/WHATSNEW.md index 148918ee66b0446aa1a223904dc9411c015b6b00..cd03e65ce837b16d3fb34b45f30fbfe8c3592237 100644 --- a/WHATSNEW.md +++ b/WHATSNEW.md @@ -1,3 +1,23 @@ +osTicket v1.9.3 +=============== +### Enhancements + * Redactor link dialog has a few common links selectable (#1135) + +### Improvements + * Fix missing `%{recipient}` variable used in canned reply (filters) (#1047) + * Fix `%{ticket.close_date}` variable in email message templates (#1090) + * Fix timezone offset used in time drop down (#1103) + * Fix premature session expiration (#1111) + * Correctly tag emails with source `email` (#1104) + * Correctly handle custom data for help topics (#1105) + * Fix validation and display issues for email mailboxes with system default priority and department (#1114) + * Fix crash when rendering custom list drop-downs with retired list items (#1113) + * Avoid system alert notices bouncing and creating tickets (#1115) + * Redactor no longer shortens URLs (#1135) + +### Performance and Security + * Fix XSS vulnerability in user name (#1108, #1131) + osTicket v1.9.2 =============== ### Enhancements diff --git a/assets/default/about-custom-themes.md b/assets/default/about-custom-themes.md index eecf1bbbed3d3002d3d4abe686f8ec6d82717094..0c0ff4bb97018e27f0b8589b6db1ecb46f3c4a5b 100644 --- a/assets/default/about-custom-themes.md +++ b/assets/default/about-custom-themes.md @@ -1,4 +1,4 @@ -Customizng Your Theme +Customizing Your Theme ==== When modifying the default theme, it is recommended that you do not diff --git a/include/ajax.config.php b/include/ajax.config.php index 28ada22308fdd38fba64acca90ae403069a67b68..74ee115f08c1082fbb2013cafd0fb2d2c7ddd84b 100644 --- a/include/ajax.config.php +++ b/include/ajax.config.php @@ -59,5 +59,20 @@ class ConfigAjaxAPI extends AjaxController { return $config; } + + function templateLinks() { + $links = $this->json_encode(array( + array('name'=>'Select ...', 'url'=> false), + array('name'=>'Agent Ticket Link', 'url'=> '%{ticket.staff_link}'), + array('name'=>'Agent Login Page', 'url'=> '%{url}/scp'), + array('name'=>'End-User Ticket Link', 'url'=> '%{recipient.ticket_link}'), + array('name'=>'End-User Login Page', 'url'=> '%{url}/login.php'), + )); + + Http::cacheable(md5($links), filemtime(__file__)); + header('Content-Type: application/json; charset=UTF-8'); + + return $links; + } } ?> diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php index 4904163ec38452c570d708ab2138676d4f52abe3..0f313c433e0da7eb62846be9cca8fdd5e406c39c 100644 --- a/include/ajax.tickets.php +++ b/include/ajax.tickets.php @@ -388,15 +388,15 @@ class TicketsAjaxAPI extends AjaxController { if ($user) { if ($user->getId() == $ticket->getOwnerId()) $errors['err'] = sprintf(__('Ticket owner, %s, is a collaborator by default!'), - $user->getName()); + Format::htmlchars($user->getName())); elseif (($c=$ticket->addCollaborator($user, array('isactive'=>1), $errors))) { $note = Format::htmlchars(sprintf(__('%s <%s> added as a collaborator'), - $c->getName(), $c->getEmail())); + Format::htmlchars($c->getName()), $c->getEmail())); $ticket->logNote(__('New Collaborator Added'), $note, $thisstaff, false); $info = array('msg' => sprintf(__('%s added as a collaborator'), - $c->getName())); + Format::htmlchars($c->getName()))); return self::_collaborators($ticket, $info); } } @@ -425,7 +425,7 @@ class TicketsAjaxAPI extends AjaxController { return self::_collaborator($c ,$user->getForms($_POST), $errors); $info = array('msg' => sprintf('%s updated successfully', - $c->getName())); + Format::htmlchars($c->getName()))); return self::_collaborators($ticket, $info); } diff --git a/include/ajax.users.php b/include/ajax.users.php index 0dc54647f9a14df97280f18323954a8604b900ab..94f98c7fb5de96fb3e25a965b561a5e535fd3563 100644 --- a/include/ajax.users.php +++ b/include/ajax.users.php @@ -113,7 +113,7 @@ class UsersAjaxAPI extends AjaxController { Http::response(404, 'Unknown user'); $info = array( - 'title' => sprintf(__('Update %s'), $user->getName()) + 'title' => sprintf(__('Update %s'), Format::htmlchars($user->getName())) ); $forms = $user->getForms(); @@ -359,7 +359,8 @@ class UsersAjaxAPI extends AjaxController { Http::response(404, 'Unknown user'); $info = array(); - $info['title'] = sprintf(__('Organization for %s'), $user->getName()); + $info['title'] = sprintf(__('Organization for %s'), + Format::htmlchars($user->getName())); $info['action'] = '#users/'.$user->getId().'/org'; $info['onselect'] = 'ajax.php/users/'.$user->getId().'/org'; @@ -383,7 +384,7 @@ class UsersAjaxAPI extends AjaxController { } elseif ($orgId) $org = Organization::lookup($orgId); elseif ($org = $user->getOrganization()) { - $info['title'] = sprintf(__('%s — Organization'), $user->getName()); + $info['title'] = sprintf(__('%s — Organization'), Format::htmlchars($user->getName())); $info['action'] = $info['onselect'] = ''; $tmpl = 'org.tmpl.php'; } diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php index 45fc398c3a617a713c3f50010ef6b567bd509c3e..8f6bdfe75160a97aa6c6131dfc91339a4f05bfee 100644 --- a/include/class.dynamic_forms.php +++ b/include/class.dynamic_forms.php @@ -527,6 +527,7 @@ class DynamicFormEntry extends VerySimpleModel { var $_form; var $_errors = false; var $_clean = false; + var $_source = null; function getId() { return $this->get('id'); @@ -580,12 +581,21 @@ class DynamicFormEntry extends VerySimpleModel { function getFields() { if (!isset($this->_fields)) { $this->_fields = array(); - foreach ($this->getAnswers() as $a) - $this->_fields[] = $a->getField(); + foreach ($this->getAnswers() as $a) { + $T = $this->_fields[] = $a->getField(); + $T->setForm($this); + } } return $this->_fields; } + function getSource() { + return $this->_source ?: (isset($this->id) ? false : $_POST); + } + function setSource($source) { + $this->_source = $source; + } + function getField($name) { foreach ($this->getFields() as $field) @@ -776,8 +786,8 @@ class DynamicFormEntry extends VerySimpleModel { if (count($this->dirty)) $this->set('updated', new SqlFunction('NOW')); parent::save(); - foreach ($this->getAnswers() as $a) { - $field = $a->getField(); + foreach ($this->getFields() as $field) { + $a = $field->getAnswer(); if ($this->object_type == 'U' && in_array($field->get('name'), array('name','email'))) continue; @@ -1236,9 +1246,9 @@ class SelectionField extends FormField { foreach ($this->getList()->getItems() as $i) $this->_choices[$i->get('id')] = $i->get('value'); if ($this->value && !isset($this->_choices[$this->value])) { - $v = DynamicListItem::lookup($this->value); - $this->_choices[$v->get('id')] = $v->get('value') - . ' ' . __('(disabled)'); + if ($v = DynamicListItem::lookup($this->value)) + $this->_choices[$v->get('id')] = $v->get('value') + . ' ' . __('(disabled)'); } } return $this->_choices; diff --git a/include/class.email.php b/include/class.email.php index 2e3d62c59303b1031fc141366065a9c051f3d6cf..d38806f75f668c558872f2035208edeab924f2b2 100644 --- a/include/class.email.php +++ b/include/class.email.php @@ -293,10 +293,6 @@ class Email { $errors['mail_fetchfreq']=__('Fetch interval required'); if(!$vars['mail_fetchmax'] || !is_numeric($vars['mail_fetchmax'])) $errors['mail_fetchmax']=__('Maximum emails required'); - if(!$vars['dept_id'] || !is_numeric($vars['dept_id'])) - $errors['dept_id']=__('You must select a department'); - if(!$vars['priority_id']) - $errors['priority_id']=__('You must select a priority'); if(!isset($vars['postfetch'])) $errors['postfetch']=__('Indicate what to do with fetched emails'); diff --git a/include/class.format.php b/include/class.format.php index a45e043ad7cbce55cd3db818aaf063de7b5aaab8..0aa52abccbd6bdf91e98aa136b0bfd473fa9085d 100644 --- a/include/class.format.php +++ b/include/class.format.php @@ -269,13 +269,19 @@ class Format { } function htmlencode($var) { + + if (is_array($var)) + return array_map(array('Format', 'htmlencode'), $var); + $flags = ENT_COMPAT; if (phpversion() >= '5.4.0') $flags |= ENT_HTML401; - return is_array($var) - ? array_map(array('Format','htmlencode'), $var) - : htmlentities($var, $flags, 'UTF-8'); + try { + return htmlentities( (string) $var, $flags, 'UTF-8', false); + } catch(Exception $e) { + return $var; + } } function htmldecode($var) { diff --git a/include/class.forms.php b/include/class.forms.php index 98e7e7ea92c5adfa3b2fc1ea1141b51bd76be566..6173950092e0fe0414313f3a7d24fb6e5ed4e56a 100644 --- a/include/class.forms.php +++ b/include/class.forms.php @@ -664,7 +664,9 @@ class PhoneField extends FormField { function parse($value) { // NOTE: Value may have a legitimate 'X' to separate the number and // extension parts. Don't remove the 'X' - return preg_replace('/[^\dX]/', '', $value); + $val = preg_replace('/[^\dX]/', '', $value); + // Pass completely-incorrect string for validation error + return $val ?: $value; } function toString($value) { diff --git a/include/class.mailer.php b/include/class.mailer.php index a1f5bd1beab967141fbf533765ebf1e61047ed40..53a45eb7a2bba56cccd4eb76d065d4ea5b9855ee 100644 --- a/include/class.mailer.php +++ b/include/class.mailer.php @@ -25,11 +25,12 @@ class Mailer { var $ht = array(); var $attachments = array(); + var $options = array(); var $smtp = array(); var $eol="\n"; - function Mailer($email=null, $options=null) { + function Mailer($email=null, array $options=array()) { global $cfg; if(is_object($email) && $email->isSMTPEnabled() && ($info=$email->getSMTPInfo())) { //is SMTP enabled for the current email? @@ -46,6 +47,7 @@ class Mailer { $this->email = $email; $this->attachments = array(); + $this->options = $options; } function getEOL() { @@ -114,7 +116,12 @@ class Mailer { 'X-Mailer' =>'osTicket Mailer', ); - if ($this->getEmail() instanceof Email) + // Add in the options passed to the constructor + $options = ($options ?: array()) + $this->options; + + if (isset($options['nobounce']) && $options['nobounce']) + $headers['Return-Path'] = '<>'; + elseif ($this->getEmail() instanceof Email) $headers['Return-Path'] = $this->getEmail()->getEmail(); //Bulk. @@ -285,7 +292,7 @@ class Mailer { //Emails using native php mail function - if DB connection doesn't exist. //Don't use this function if you can help it. function sendmail($to, $subject, $message, $from) { - $mailer = new Mailer(); + $mailer = new Mailer(null, array('notice'=>true, 'nobounce'=>true)); $mailer->setFromAddress($from); return $mailer->send($to, $subject, $message); } diff --git a/include/class.organization.php b/include/class.organization.php index 757ba9476ea7c7746eaac8dc20843c39eca63b57..37cedebdf2dc395f13c06f0c857b9d50c2495e20 100644 --- a/include/class.organization.php +++ b/include/class.organization.php @@ -152,7 +152,11 @@ class Organization extends OrganizationModel { } function getInfo() { - $base = $this->ht; + + $base = array_filter($this->ht, + function ($e) { return !is_object($e); } + ); + foreach (array( 'collab-all-flag' => Organization::COLLAB_ALL_MEMBERS, 'collab-pc-flag' => Organization::COLLAB_PRIMARY_CONTACT, diff --git a/include/class.ostsession.php b/include/class.ostsession.php index 4c34fda98553e28907cab45577e0189179780a26..94df679d2792046fda2b7373e598851f147a501b 100644 --- a/include/class.ostsession.php +++ b/include/class.ostsession.php @@ -22,9 +22,7 @@ class osTicketSession { var $id = ''; function osTicketSession($ttl=0){ - $this->ttl =$ttl?$ttl:get_cfg_var('session.gc_maxlifetime'); - if(!$this->ttl) - $this->ttl=SESSION_TTL; + $this->ttl = $ttl ?: ini_get('session.gc_maxlifetime') ?: SESSION_TTL; // Set osTicket specific session name. session_name('OSTSESSID'); @@ -32,6 +30,9 @@ class osTicketSession { // Forced cleanup on shutdown register_shutdown_function('session_write_close'); + // Set session cleanup time to match TTL + ini_set('session.gc_maxlifetime', $ttl); + if (OsticketConfig::getDBVersion()) return session_start(); @@ -45,7 +46,7 @@ class osTicketSession { // Remote port specification, as it will make an invalid domain list($domain) = explode(':', $_SERVER['HTTP_HOST']); - session_set_cookie_params(86400, ROOT_PATH, $domain, + session_set_cookie_params($ttl, ROOT_PATH, $domain, osTicket::is_https()); //Set handlers. diff --git a/include/class.ticket.php b/include/class.ticket.php index 9d5cb0ba29de60c7b5fd613c8e8d01ebe9478c87..8fb7e873ca66a08c6a7a4a281ef87d9dbcc7f9dc 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -1287,10 +1287,10 @@ class Ticket { return $duedate; break; - case 'close_date'; + case 'close_date': $closedate =''; if($this->isClosed()) - $duedate = Format::date( + $closedate = Format::date( $cfg->getDateTimeFormat(), Misc::db2gmtime($this->getCloseDate()), $cfg->getTZOffset(), @@ -1717,7 +1717,11 @@ class Ticket { $signature=''; $msg = $this->replaceVars($msg->asArray(), - array('response' => $response, 'signature' => $signature)); + array( + 'response' => $response, + 'signature' => $signature, + 'recipient' => $this->getOwner(), + )); $attachments =($cfg->emailAttachments() && $files)?$response->getAttachments():array(); $options = array( @@ -2320,9 +2324,11 @@ class Ticket { if ($vars['topicId'] && ($topic=Topic::lookup($vars['topicId']))) { if ($topic_form = $topic->getForm()) { + $TF = $topic_form->getForm($vars); $topic_form = $topic_form->instanciate(); - if (!$topic_form->getForm()->isValid($field_filter('topic'))) - $errors = array_merge($errors, $topic_form->getForm()->errors()); + $topic_form->setSource($vars); + if (!$TF->isValid($field_filter('topic'))) + $errors = array_merge($errors, $TF->errors()); } } @@ -2351,6 +2357,9 @@ class Ticket { if(!Validator::process($fields, $vars, $errors) && !$errors['err']) $errors['err'] =__('Missing or invalid data - check the errors and try again'); + if ($vars['topicId'] && !$topic) + $errors['topicId'] = 'Invalid help topic selected'; + //Make sure the due date is valid if($vars['duedate']) { if(!$vars['time'] || strpos($vars['time'],':')===false) @@ -2449,7 +2458,6 @@ class Ticket { $form->setAnswer('priority', null, $topic->getPriorityId()); if ($autorespond) $autorespond = $topic->autoRespond(); - $source = $vars['source'] ?: 'Web'; //Auto assignment. if (!isset($vars['staffId']) && $topic->getStaffId()) @@ -2479,8 +2487,9 @@ class Ticket { if (!$priority || !$priority->getIdValue()) $form->setAnswer('priority', null, $cfg->getDefaultPriorityId()); $deptId = $deptId ?: $cfg->getDefaultDeptId(); - $topicId = $vars['topicId'] ?: 0; + $topicId = isset($topic) ? $topic->getId() : 0; $ipaddress = $vars['ip'] ?: $_SERVER['REMOTE_ADDR']; + $source = $source ?: 'Web'; //We are ready son...hold on to the rails. $number = Ticket::genRandTicketNumber(); diff --git a/include/class.user.php b/include/class.user.php index d7f56c42e0a9bfda542e351fe21dc5834f8328c4..52bf115e0126668d66e99568e783ffc19b4ebe1f 100644 --- a/include/class.user.php +++ b/include/class.user.php @@ -157,9 +157,9 @@ class User extends UserModel { list($name) = explode('@', $vars['email'], 2); $user = User::create(array( - 'name'=>$name, - 'created'=>new SqlFunction('NOW'), - 'updated'=>new SqlFunction('NOW'), + 'name' => Format::htmldecode(Format::sanitize($name, false)), + 'created' => new SqlFunction('NOW'), + 'updated' => new SqlFunction('NOW'), //XXX: Do plain create once the cause // of the detached emails is fixed. 'default_email' => UserEmail::ensure($vars['email']) @@ -247,7 +247,7 @@ class User extends UserModel { $info = array( 'id' => $this->getId(), - 'name' => (string) $this->getName(), + 'name' => Format::htmlchars($this->getName()), 'email' => (string) $this->getEmail(), 'phone' => (string) $this->getPhoneNumber()); @@ -478,12 +478,13 @@ class User extends UserModel { function updateInfo($vars, &$errors) { $valid = true; - $forms = $this->getForms($vars); + $forms = $this->getDynamicData(); foreach ($forms as $cd) { - if (!$cd->isValid()) + $cd->setSource($vars); + if (!$cd->isValidForClient()) $valid = false; - if ($cd->get('type') == 'U' - && ($form= $cd->getForm($vars)) + elseif ($cd->get('type') == 'U' + && ($form= $cd->getForm()) && ($f=$form->getField('email')) && $f->getClean() && ($u=User::lookup(array('emails__address'=>$f->getClean()))) diff --git a/include/i18n/en_US/help_topic.yaml b/include/i18n/en_US/help_topic.yaml index ee9e9aa40d338657fa74f4f4ce735bc1163d6fb2..d54cdf3d702e391fea43737d8d455595a00eedf1 100644 --- a/include/i18n/en_US/help_topic.yaml +++ b/include/i18n/en_US/help_topic.yaml @@ -18,7 +18,8 @@ # notes - (string) administrative notes (internally viewable only) # --- -- isactive: 1 +- topic_id: 1 + isactive: 1 ispublic: 1 dept_id: 1 priority_id: 2 diff --git a/include/staff/emails.inc.php b/include/staff/emails.inc.php index 7cc6d3ef6905e054cdd2176091b86d89bba42094..62900ab33f615399d02c50a1a92df8115f05fe7c 100644 --- a/include/staff/emails.inc.php +++ b/include/staff/emails.inc.php @@ -41,6 +41,10 @@ if($res && ($num=db_num_rows($res))) else $showing=__('No emails found!'); +$def_dept_id = $cfg->getDefaultDeptId(); +$def_dept_name = $cfg->getDefaultDept()->getName(); +$def_priority = $cfg->getDefaultPriority()->getDesc(); + ?> <div class="pull-left" style="width:700px;padding-top:5px;"> <h2><?php echo __('Email Addresses');?></h2> @@ -85,8 +89,9 @@ else <?php echo $sel?'checked="checked"':''; ?> <?php echo $default?'disabled="disabled"':''; ?>> </td> <td><span class="ltr"><a href="emails.php?id=<?php echo $row['email_id']; ?>"><?php echo Format::htmlchars($email); ?></a></span></td> - <td><?php echo $row['priority']; ?></td> - <td><a href="departments.php?id=<?php echo $row['dept_id']; ?>"><?php echo $row['department']; ?></a></td> + <td><?php echo $row['priority'] ?: $def_priority; ?></td> + <td><a href="departments.php?id=<?php $row['dept_id'] ?: $def_dept_id; ?>"><?php + echo $row['department'] ?: $def_dept_name; ?></a></td> <td> <?php echo Format::db_date($row['created']); ?></td> <td> <?php echo Format::db_datetime($row['updated']); ?></td> </tr> diff --git a/include/staff/templates/collaborators-preview.tmpl.php b/include/staff/templates/collaborators-preview.tmpl.php index e1d7beaabad20e91bea64320412aa2aaca5e9d9b..964c225e7db174f8e0a614889104378f14d7e312 100644 --- a/include/staff/templates/collaborators-preview.tmpl.php +++ b/include/staff/templates/collaborators-preview.tmpl.php @@ -8,7 +8,7 @@ if (($users=$ticket->getCollaborators())) {?> echo sprintf('<tr><td %s><i class="icon-%s"></i> %s <em><%s></em></td></tr>', ($user->isActive()? '' : 'class="faded"'), ($user->isActive()? 'comments' : 'comment-alt'), - $user->getName(), + Format::htmlchars($user->getName()), $user->getEmail()); } } else { diff --git a/include/staff/templates/collaborators.tmpl.php b/include/staff/templates/collaborators.tmpl.php index 22d01c8315f06d7439c0860714c334d2c8bd5ae1..d8d339c882dae25b1f5592f43a40c95420e76f66 100644 --- a/include/staff/templates/collaborators.tmpl.php +++ b/include/staff/templates/collaborators.tmpl.php @@ -27,7 +27,7 @@ if(($users=$ticket->getCollaborators())) {?> $user->getId(), $checked, $user->getId(), - $user->getName(), + Format::htmlchars($user->getName()), $user->getEmail(), $user->getId(), $user->getId()); diff --git a/include/staff/templates/user-account.tmpl.php b/include/staff/templates/user-account.tmpl.php index fcea3bd4de9881ec0c241fe706eff44f33961fbd..95509afc6cc5317af65af3575f168cc2f5b86a3f 100644 --- a/include/staff/templates/user-account.tmpl.php +++ b/include/staff/templates/user-account.tmpl.php @@ -39,7 +39,7 @@ if ($info['error']) { <td width="180"> <?php echo __('Name'); ?>: </td> - <td> <?php echo $user->getName(); ?> </td> + <td> <?php echo Format::htmlchars($user->getName()); ?> </td> </tr> <tr> <td width="180"> diff --git a/include/staff/templates/user-register.tmpl.php b/include/staff/templates/user-register.tmpl.php index 5834256d61ed7b53d94838b56918ee964609513c..6f5662ca213361fd8e163b3e3be43134a46bb3d2 100644 --- a/include/staff/templates/user-register.tmpl.php +++ b/include/staff/templates/user-register.tmpl.php @@ -29,7 +29,7 @@ if ($info['error']) { <div><p id="msg_info"><i class="icon-info-sign"></i> <?php echo sprintf(__( 'Complete the form below to create a user account for <b>%s</b>.' -), $user->getName()->getOriginal() +), Format::htmlchars($user->getName()->getOriginal()) ); ?> </p></div> <div id="user-registration" style="display:block; margin:5px;"> diff --git a/include/staff/templates/users.tmpl.php b/include/staff/templates/users.tmpl.php index 44a0644b23673a4aaf25fb546281b03fbd5c0459..11eb0952a47eaa4561fefb40e2aef178e9920347 100644 --- a/include/staff/templates/users.tmpl.php +++ b/include/staff/templates/users.tmpl.php @@ -99,7 +99,9 @@ if ($num) { ?> value="<?php echo $row['id']; ?>" <?php echo $sel?'checked="checked"':''; ?> > </td> <td> - <a class="userPreview" href="users.php?id=<?php echo $row['id']; ?>"><?php echo $name; ?></a> + <a class="userPreview" + href="users.php?id=<?php echo $row['id']; ?>"><?php + echo Format::htmlchars($name); ?></a> <?php if ($row['tickets']) @@ -107,7 +109,7 @@ if ($num) { ?> <small>(%d)</small>', $row['tickets']); ?> </td> - <td><?php echo $row['email']; ?></td> + <td><?php echo Format::htmlchars($row['email']); ?></td> <td><?php echo $status; ?></td> <td><?php echo Format::db_date($row['created']); ?></td> </tr> diff --git a/include/staff/ticket-open.inc.php b/include/staff/ticket-open.inc.php index cbfa0c840514aab7f0bbf8c6e52c168802896a7c..f9ab0d8f23482bb4ba072ddb60187cd4962844ad 100644 --- a/include/staff/ticket-open.inc.php +++ b/include/staff/ticket-open.inc.php @@ -56,7 +56,7 @@ if ($_POST) }); return false; "><i class="icon-user"></i> - <span id="user-name"><?php echo $user->getName(); ?></span> + <span id="user-name"><?php echo Format::htmlchars($user->getName()); ?></span> <<span id="user-email"><?php echo $user->getEmail(); ?></span>> </a> <a class="action-button" style="float:none;overflow:inherit" href="#" diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php index 8ca2d04c07787185dfa80e879a7e9a35a000bd33..d88f1f52dda15131cb4831ea67aa475d0d5f6cda 100644 --- a/include/staff/ticket-view.inc.php +++ b/include/staff/ticket-view.inc.php @@ -464,7 +464,9 @@ $tcount+= $ticket->getNumNotes(); <td> <?php # XXX: Add user-to-name and user-to-email HTML ID#s - $to =sprintf('%s <%s>', $ticket->getName(), $ticket->getReplyToEmail()); + $to =sprintf('%s <%s>', + Format::htmlchars($ticket->getName()), + $ticket->getReplyToEmail()); $emailReply = (!isset($info['emailreply']) || $info['emailreply']); ?> <select id="emailreply" name="emailreply"> diff --git a/include/staff/tickets.inc.php b/include/staff/tickets.inc.php index 8e32518b433abe7a4d1941c550b3585d7c4deb93..a42fb35100bdc740c2e63e077f094acf792e78c2 100644 --- a/include/staff/tickets.inc.php +++ b/include/staff/tickets.inc.php @@ -428,7 +428,8 @@ if ($results) { echo '<i class="icon-fixed-width icon-paperclip"></i> '; ?> </td> - <td nowrap> <?php echo Format::truncate($row['name'],22,strpos($row['name'],'@')); ?> </td> + <td nowrap> <?php echo Format::htmlchars( + Format::truncate($row['name'], 22, strpos($row['name'], '@'))); ?> </td> <?php if($search && !$status){ $displaystatus=ucfirst($row['status']); diff --git a/include/staff/user-view.inc.php b/include/staff/user-view.inc.php index 34c7c212ce3d93d2290c3be1454f7a78ba4e954c..7a5bd384bf413ce7e8507a5ef04c8248c847fcfe 100644 --- a/include/staff/user-view.inc.php +++ b/include/staff/user-view.inc.php @@ -10,7 +10,7 @@ $org = $user->getOrganization(); <tr> <td width="50%" class="has_bottom_border"> <h2><a href="users.php?id=<?php echo $user->getId(); ?>" - title="Reload"><i class="icon-refresh"></i> <?php echo $user->getName(); ?></a></h2> + title="Reload"><i class="icon-refresh"></i> <?php echo Format::htmlchars($user->getName()); ?></a></h2> </td> <td width="50%" class="right_align has_bottom_border"> <span class="action-button" data-dropdown="#action-dropdown-more"> @@ -76,7 +76,7 @@ $org = $user->getOrganization(); <td><b><a href="#users/<?php echo $user->getId(); ?>/edit" class="user-action"><i class="icon-edit"></i> <?php echo - $user->getName()->getOriginal(); + Format::htmlchars($user->getName()->getOriginal()); ?></a></td> </tr> <tr> diff --git a/include/staff/users.inc.php b/include/staff/users.inc.php index 673a67ef70c6e3d8b85789f74ba1bc7dd3d9c49e..15362dec22c3b90d0637e75813530d4ecebcb154 100644 --- a/include/staff/users.inc.php +++ b/include/staff/users.inc.php @@ -144,7 +144,8 @@ else ?> <tr id="<?php echo $row['id']; ?>"> <td> - <a class="userPreview" href="users.php?id=<?php echo $row['id']; ?>"><?php echo $name; ?></a> + <a class="userPreview" href="users.php?id=<?php echo $row['id']; ?>"><?php + echo Format::htmlchars($name); ?></a> <?php if ($row['tickets']) diff --git a/js/redactor-osticket.js b/js/redactor-osticket.js index da5baf97920b28bb39b1b1ad29614aeaa869f2cf..a2859c4334de2872bf7f78a81c25465e008002f3 100644 --- a/js/redactor-osticket.js +++ b/js/redactor-osticket.js @@ -241,7 +241,9 @@ $(function() { 'linebreaks': true, 'tabFocus': false, 'toolbarFixedBox': true, - 'focusCallback': function() { this.$box.addClass('no-pjax'); } + 'focusCallback': function() { this.$box.addClass('no-pjax'); }, + 'linkSize': 100000, + 'predefinedLinks': 'ajax.php/config/links' }, options||{}); if (el.data('redactor')) return; var reset = $('input[type=reset]', el.closest('form')); diff --git a/login.php b/login.php index 9e3c550ad1b92a749c90a57bf8cbc41820317b52..f79bf8563320f672fdb90c67fff9e178eafd4fd7 100644 --- a/login.php +++ b/login.php @@ -75,7 +75,7 @@ elseif ($_POST && isset($_POST['lticket'])) { // force attempts (which doesn't buy much since the link is emailed) $user->sendAccessLink(); $msg = sprintf(__("%s - access link sent to your email!"), - $user->getName()->getFirst()); + Format::htmlchars($user->getName()->getFirst())); $_POST = null; } elseif(!$errors['err']) { $errors['err'] = __('Invalid email or ticket number - try again!'); diff --git a/scp/ajax.php b/scp/ajax.php index cc99353e9b7513d3aec6c7a26632744aed578988..fe3241d51dc4d1d0e0bbcc596406efe647cb0bc3 100644 --- a/scp/ajax.php +++ b/scp/ajax.php @@ -48,7 +48,8 @@ $dispatcher = patterns('', url_post('^(?P<id>\d+)(?:/(?P<lang>\w+))?$', 'updateContent') )), url('^/config/', patterns('ajax.config.php:ConfigAjaxAPI', - url_get('^scp', 'scp') + url_get('^scp', 'scp'), + url_get('^links', 'templateLinks') )), url('^/form/', patterns('ajax.forms.php:DynamicFormsAjaxAPI', url_get('^help-topic/(?P<id>\d+)$', 'getFormsForHelpTopic'), diff --git a/scp/tickets.php b/scp/tickets.php index 35542ec45fd18d2ced4df790ea1518f17034b45f..be83ed2aa49e33ecc33b815dd4651173516ecc18 100644 --- a/scp/tickets.php +++ b/scp/tickets.php @@ -201,7 +201,8 @@ if($_POST && !$errors): // Don't validate deleted forms if (!in_array($form->getId(), $_POST['forms'])) continue; - elseif (!$form->isValid()) + $form->setSource($_POST); + if (!$form->isValid()) $errors = array_merge($errors, $form->errors()); } if(!$ticket || !$thisstaff->canEditTickets()) @@ -356,7 +357,7 @@ if($_POST && !$errors): } elseif (!$_POST['user_id'] || !($user=User::lookup($_POST['user_id']))) { $errors['err'] = 'Unknown user selected!'; } elseif ($ticket->changeOwner($user)) { - $msg = 'Ticket ownership changed to '.$user->getName(); + $msg = 'Ticket ownership changed to ' . Format::htmlchars($user->getName()); } else { $errors['err'] = 'Unable to change tiket ownership. Try again'; } diff --git a/setup/inc/file-perm.inc.php b/setup/inc/file-perm.inc.php index 025c6a2176899cf52314a3587a4c682a03cdf973..78c65c7c84cf5058eabfce23903bdf607e76e136 100644 --- a/setup/inc/file-perm.inc.php +++ b/setup/inc/file-perm.inc.php @@ -14,7 +14,8 @@ if(!defined('SETUPINC')) die('Kwaheri!'); <?php echo __('Please follow the instructions below to give read and write access to the web server user.');?> <ul> <li><b><?php echo __('CLI');?></b>:<br><i>chmod 0666 include/ost-config.php</i></li> - <li><b><?php echo __('Windows');?></b>:<br><?php echo __('Add "Full Access" permission for the "Everyone" user'); ?></li> + <li><b><?php echo __('Windows PowerShell');?></b>:<br><?php echo __('Add "Full Access" permission for the "Everyone" user'); ?><br> + <i>icacls include\ost-config.php /grant 'Everyone:F'</i></li> <li><b><?php echo __('FTP');?></b>:<br><?php echo __('Using WS_FTP this would be right hand clicking on the file, selecting chmod, and then giving all permissions to the file.');?></li> <li><b><?php echo __('Cpanel');?></b>:<br><?php echo __('Click on the file, select change permission, and then giving all permissions to the file.');?></li> </ul> diff --git a/setup/inc/install-done.inc.php b/setup/inc/install-done.inc.php index f79e89f4808f1501d6c658dba4366fe16b12cae8..29ea15c0f411f434328dcdca56af405b2d2ab18f 100644 --- a/setup/inc/install-done.inc.php +++ b/setup/inc/install-done.inc.php @@ -10,8 +10,8 @@ $url=URL; <h2><?php echo __('Config file permission');?>:</h2> <?php echo __('Change permission of ost-config.php to remove write access as shown below.');?> <ul> - <li><b><?php echo __('CLI');?></b>:<br><i>chmod 0664 include/ost-config.php</i></li> - <li><b><?php echo __('Windows PowerShell');?></b>:<br><i>icacls include/ost-config.php /grant 'Everyone:(OI)(CI)F'</i></li> + <li><b><?php echo __('CLI');?></b>:<br><i>chmod 0644 include/ost-config.php</i></li> + <li><b><?php echo __('Windows PowerShell');?></b>:<br><i>icacls include\ost-config.php /reset</i></li> <li><b><?php echo __('FTP');?></b>:<br><?php echo __('Using WS_FTP this would be right hand clicking on the file, selecting chmod, and then remove write access');?></li> <li><b><?php echo __('Cpanel');?></b>:<br><?php echo __('Click on the file, select change permission, and then remove write access.');?></li> </ul> diff --git a/setup/test/tests/stubs.php b/setup/test/tests/stubs.php index 72f0744d5a13b011304718954fd924c10dc98aa1..c13e78121be2f710b82a84d2e54d4e28e63b6ec3 100644 --- a/setup/test/tests/stubs.php +++ b/setup/test/tests/stubs.php @@ -95,6 +95,7 @@ class Phar { function setStub() {} function startBuffering() {} function stopBuffering() {} + function setSignatureAlgorithm() {} } class ZipArchive { diff --git a/tickets.php b/tickets.php index d943fd92f6fb235be9971764ab5840c4b8c8a48a..4e38384b2b05a877701f72c05d6479873c742bd2 100644 --- a/tickets.php +++ b/tickets.php @@ -47,9 +47,11 @@ if($_POST && is_object($ticket) && $ticket->getId()): $errors['err']=__('Access Denied. Client updates are currently disabled'); else { $forms=DynamicFormEntry::forTicket($ticket->getId()); - foreach ($forms as $form) + foreach ($forms as $form) { + $form->setSource($_POST); if (!$form->isValid()) $errors = array_merge($errors, $form->errors()); + } } if (!$errors) { foreach ($forms as $f) $f->save();