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 &mdash; Organization'), $user->getName());
+            $info['title'] = sprintf(__('%s &mdash; 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>&nbsp;<?php echo Format::db_date($row['created']); ?></td>
                 <td>&nbsp;<?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>&lt;%s&gt;</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>&nbsp;<?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>&nbsp;
-                    <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>
                     &nbsp;
                     <?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>
                 &lt;<span id="user-email"><?php echo $user->getEmail(); ?></span>&gt;
                 </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 &lt;%s&gt;', $ticket->getName(), $ticket->getReplyToEmail());
+                    $to =sprintf('%s &lt;%s&gt;',
+                            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>&nbsp;';
                     ?>
                 </td>
-                <td nowrap>&nbsp;<?php echo Format::truncate($row['name'],22,strpos($row['name'],'@')); ?>&nbsp;</td>
+                <td nowrap>&nbsp;<?php echo Format::htmlchars(
+                        Format::truncate($row['name'], 22, strpos($row['name'], '@'))); ?>&nbsp;</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>&nbsp;<?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>&nbsp;
-                    <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>
                     &nbsp;
                     <?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();