diff --git a/include/ajax.thread.php b/include/ajax.thread.php
index a66062e0b933607397803545f98c384d46b5b53c..0369548ed5deb1b855c6f2f9c3127d4eb9b4ff22 100644
--- a/include/ajax.thread.php
+++ b/include/ajax.thread.php
@@ -74,11 +74,11 @@ class ThreadAjaxAPI extends AjaxController {
         if (!$user_info)
             $info['error'] = __('Unable to find user in directory');
 
-        return self::_addcollaborator($thread, null, $form, $info);
+        return self::_addcollaborator($thread, null, $form, 'addcc', $info);
     }
 
     //Collaborators utils
-    function addCollaborator($tid, $uid=0) {
+    function addCollaborator($tid, $type=null, $uid=0) {
         global $thisstaff;
 
         if (!($thread=Thread::lookup($tid))
@@ -90,7 +90,7 @@ class ThreadAjaxAPI extends AjaxController {
 
         //If not a post then assume new collaborator form
         if(!$_POST)
-            return self::_addcollaborator($thread, $user);
+            return self::_addcollaborator($thread, $user, null, $type);
 
         $user = $form = null;
         if (isset($_POST['id']) && $_POST['id']) { //Existing user/
@@ -107,7 +107,7 @@ class ThreadAjaxAPI extends AjaxController {
                             array(), $errors))) {
                 $info = array('msg' => sprintf(__('%s added as a collaborator'),
                             Format::htmlchars($c->getName())));
-                $c->setCc();
+                $type == 'addbcc' ? $c->setBcc() : $c->setCc();
                 $c->save();
                 return self::_collaborators($thread, $info);
             }
@@ -119,7 +119,7 @@ class ThreadAjaxAPI extends AjaxController {
             $info +=array('error' =>__('Unable to add collaborator.').' '.__('Internal error occurred'));
         }
 
-        return self::_addcollaborator($thread, $user, $form, $info);
+        return self::_addcollaborator($thread, $user, $form, $type, $info);
     }
 
     function updateCollaborator($tid, $cid) {
@@ -194,15 +194,15 @@ class ThreadAjaxAPI extends AjaxController {
         return $resp;
     }
 
-    function _addcollaborator($thread, $user=null, $form=null, $info=array()) {
+    function _addcollaborator($thread, $user=null, $form=null, $type=null, $info=array()) {
         global $thisstaff;
 
         $info += array(
                     'title' => __('Add a collaborator'),
-                    'action' => sprintf('#thread/%d/add-collaborator',
-                        $thread->getId()),
-                    'onselect' => sprintf('ajax.php/thread/%d/add-collaborator/',
-                        $thread->getId()),
+                    'action' => sprintf('#thread/%d/add-collaborator/%s',
+                        $thread->getId(), $type),
+                    'onselect' => sprintf('ajax.php/thread/%d/add-collaborator/%s/',
+                        $thread->getId(), $type),
                     );
 
         ob_start();
diff --git a/include/class.filter.php b/include/class.filter.php
index e76b5175a3d8b5c6ac4a866bdd091fe6ec045a04..1827342284a3bab796bc1db2244dd53c527e0e0b 100644
--- a/include/class.filter.php
+++ b/include/class.filter.php
@@ -471,24 +471,28 @@ class Filter {
     }
 
     function save($id,$vars,&$errors) {
+      //get current filter actions (they're validated before saving)
+      self::save_actions($id, $vars, $errors);
+
       if ($this) {
         foreach ($this->getActions() as $A) {
+          $config = JsonDataParser::parse($A->configuration);
           if ($A->type == 'dept') {
-            $dept = Dept::lookup($A->parseConfiguration($vars)['dept_id']);
+            $dept = Dept::lookup($config['dept_id']);
             $dept_action = $A->getId();
           }
 
           if ($A->type == 'topic') {
-            $topic = Topic::lookup($A->parseConfiguration($vars)['topic_id']);
+            $topic = Topic::lookup($config['topic_id']);
             $topic_action = $A->getId();
           }
         }
       }
 
-      if($dept && !$dept->isActive() && !in_array('D' . $dept_action,$vars['actions']))
+      if($dept && !$dept->isActive() && (is_array($vars['actions']) && !in_array('D' . $dept_action,$vars['actions'])))
         $errors['err'] = sprintf(__('%s selected for %s must be active'), __('Department'), __('Filter Action'));
 
-      if($topic && !$topic->isActive() && !in_array('D' . $topic_action,$vars['actions']))
+      if($topic && !$topic->isActive() && (is_array($vars['actions']) && !in_array('D' . $topic_action,$vars['actions'])))
         $errors['err'] = sprintf(__('%s selected for %s must be active'), __('Help Topic'), __('Filter Action'));
 
         if(!$vars['execorder'])
@@ -547,7 +551,6 @@ class Filter {
         # Don't care about errors stashed in $xerrors
         $xerrors = array();
         self::save_rules($id,$vars,$xerrors);
-        self::save_actions($id, $vars, $errors);
 
         return count($errors) == 0;
     }
@@ -555,20 +558,31 @@ class Filter {
     function validate_actions($action) {
       $errors = array();
       $config = json_decode($action->ht['configuration'], true);
-      if ($action->ht['type'] == 'dept') {
-        $dept = Dept::lookup($config['dept_id']);
-        if (!$dept || !$dept->isActive()) {
-          $errors['err'] = sprintf(__('Unable to save: Please choose an active %s'), 'Department');
-          return $errors;
-        }
-      }
+      switch ($action->ht['type']) {
+        case 'dept':
+          $dept = Dept::lookup($config['dept_id']);
+          if (!$dept || !$dept->isActive()) {
+            $errors['err'] = sprintf(__('Unable to save: Please choose an active %s'), 'Department');
+            return $errors;
+          }
+          break;
 
-      if ($action->ht['type'] == 'topic') {
-        $topic = Topic::lookup($config['topic_id']);
-        if (!$topic || !$topic->isActive()) {
-          $errors['err'] = sprintf(__('Unable to save: Please choose an active %s'), 'Help Topic');
-          return $errors;
-        }
+        case 'topic':
+          $topic = Topic::lookup($config['topic_id']);
+          if (!$topic || !$topic->isActive()) {
+            $errors['err'] = sprintf(__('Unable to save: Please choose an active %s'), 'Help Topic');
+            return $errors;
+          }
+          break;
+
+        default:
+          foreach ($config as $key => $value) {
+            if (!$value) {
+              $errors['err'] = sprintf(__('Unable to save: Please insert a value for %s'), ucfirst($action->ht['type']));
+              return $errors;
+            }
+          }
+          break;
       }
 
       return false;
@@ -597,7 +611,6 @@ class Filter {
                     'sort' => (int) $sort,
                 ));
                 $I->setConfiguration($errors, $vars);
-                $config = json_decode($I->ht['configuration'], true);
 
                 $invalid = self::validate_actions($I);
                 if ($invalid) {
@@ -611,8 +624,6 @@ class Filter {
                 if ($I = FilterAction::lookup($info)) {
                     $I->setConfiguration($errors, $vars);
 
-                    $config = json_decode($I->ht['configuration'], true);
-
                     $invalid = self::validate_actions($I);
                     if ($invalid) {
                       $errors['err'] = sprintf($invalid['err']);
diff --git a/include/class.report.php b/include/class.report.php
index 5e1ac94b97f52c3c8b5f5efb50ffa06e841c3737..c39ec47cc5ea595aaddcaf46d25323929d58c1cc 100644
--- a/include/class.report.php
+++ b/include/class.report.php
@@ -211,7 +211,7 @@ class OverviewReport {
             $headers = array(__('Help Topic'));
             $header = function($row) { return Topic::getLocalNameById($row['topic_id'], $row['topic__topic']); };
             $pk = 'topic_id';
-            $topics = Topic::getHelpTopics();
+            $topics = Topic::getHelpTopics(false, Topic::DISPLAY_DISABLED);
             $stats = $stats
                 ->values('topic_id', 'topic__topic', 'topic__flags')
                 ->filter(array('dept_id__in' => $thisstaff->getDepts(), 'topic_id__gt' => 0, 'topic_id__in' => array_keys($topics)));
diff --git a/include/class.thread.php b/include/class.thread.php
index dd10d3a0d326235954f7be5066ccdb5ec182e8c3..017d7db353c3fbd5740935138f2fc26222a03dcb 100644
--- a/include/class.thread.php
+++ b/include/class.thread.php
@@ -299,12 +299,12 @@ implements Searchable {
                 return false;
 
             // Referred to staff's department
-            if ($to->getDepts() && $this->referrals->findFirst(array(
+            if ($to->getDepts() && $this->referrals->filter(array(
                             'object_id__in' => $to->getDepts(),
                             'object_type'   => ObjectModel::OBJECT_TYPE_DEPT)))
                 return true;
             // Referred to staff's  team
-            if ($to->getTeams() && $this->referrals->findFirst(array(
+            if ($to->getTeams() && $this->referrals->filter(array(
                             'object_id__in' => $to->getTeams(),
                             'object_type'   => ObjectModel::OBJECT_TYPE_TEAM)))
                 return true;
@@ -778,6 +778,18 @@ implements TemplateVariable {
         ),
     );
 
+    // Thread entry types
+    static protected $types = array(
+            'M' => 'message',
+            'R' => 'response',
+            'N' => 'note',
+            'B' => 'bccmessage',
+    );
+
+    function getTypeName() {
+      return self::$types[$this->type];
+    }
+
     function postEmail($mailinfo) {
         global $ost;
 
@@ -1720,6 +1732,10 @@ implements TemplateVariable {
     static function getPermissions() {
         return self::$perms;
     }
+
+    static function getTypes() {
+        return self::$types;
+    }
 }
 
 RolePermission::register(/* @trans */ 'Tickets', ThreadEntry::getPermissions());
diff --git a/include/class.ticket.php b/include/class.ticket.php
index a1147c2cbb29115766bfe4279cc9d98aef31c97f..167703aaf49e2d1ae32d405f33210892b29b548c 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -207,9 +207,8 @@ implements RestrictedAccess, Threadable, Searchable {
     }
 
     function isReopenable() {
-        return ($this->getStatus()->isReopenable()
-          && $this->getDept()->allowsReopen()
-        && $this->getTopic()->allowsReopen());
+        return ($this->getStatus()->isReopenable() && $this->getDept()->allowsReopen()
+        && ($this->getTopic() ? $this->getTopic()->allowsReopen() : null));
     }
 
     function isClosed() {
@@ -968,7 +967,7 @@ implements RestrictedAccess, Threadable, Searchable {
                         'name' => "{$fid}_id",
                         'label' => __('Help Topic'),
                         'default' => $this->getTopicId(),
-                        'choices' => Topic::getHelpTopics()
+                        'choices' => Topic::getHelpTopics(false, Topic::DISPLAY_DISABLED)
                         ));
             break;
         case 'source':
@@ -1649,10 +1648,18 @@ implements RestrictedAccess, Threadable, Searchable {
         $collaborators['cc'] = $collaborators;
 
         //collaborator email sent out
-        if ($collaborators['cc']) {
+        if ($collaborators['cc']  || $owner_recip) {
           //say dear collaborator if the ticket user is not a recipient
-          if (!$owner_recip)
-            $cnotice = $this->replaceVars($msg, array('recipient.name.first' => __('Collaborator'), 'recipient' => $recipient));
+          if (!$owner_recip) {
+            $nameFormats = array_keys(PersonsName::allFormats());
+            $names = array();
+            foreach ($nameFormats as $key => $value) {
+              $names['recipient.name.' . $value] = __('Collaborator');
+            }
+            $names = array_merge($names, array('recipient' => $recipient));
+            $cnotice = $this->replaceVars($msg, $names);
+          }
+
           //otherwise address email to ticket user
           else
             $cnotice = $this->replaceVars($msg, array('recipient' => $owner));
@@ -2971,7 +2978,7 @@ implements RestrictedAccess, Threadable, Searchable {
             $collabsCc = array();
             if ($vars['ccs'] && $vars['emailcollab']) {
                 $collabsCc[] = Collaborator::getCollabList($vars['ccs']);
-                $collabsCc['cc'] = $collabsCc;
+                $collabsCc['cc'] = $collabsCc[0];
             }
 
             $email->send($user, $msg['subj'], $msg['body'], $attachments,
@@ -2986,10 +2993,9 @@ implements RestrictedAccess, Threadable, Searchable {
                     if (!($recipient = User::lookup($uid)))
                         continue;
 
-                    $msg = $this->replaceVars($bccmsg->asArray(), $variables + array(
-                                'recipient' => $user,
-                                'recipient.name.first' =>
-                                $recipient->getName()->getFirst()));
+                    $extraVars = UsersName::getNameFormats($recipient, 'recipient');
+                    $extraVars = array_merge($extraVars, array('recipient' => $user));
+                    $msg = $this->replaceVars($bccmsg->asArray(), $variables + $extraVars);
 
                     $email->send($recipient, $msg['subj'], $msg['body'], $attachments, $options);
                 }
@@ -4130,15 +4136,13 @@ implements RestrictedAccess, Threadable, Searchable {
                       && ($bccmsg=$tpl->getNewTicketNoticeMsgTemplate())
                       && ($email=$dept->getEmail())
                   )
-                  $bccmsg = $ticket->replaceVars($bccmsg->asArray(),
-                      array(
-                          'message'   => $message,
-                          'signature' => $signature,
-                          'response'  => ($response) ? $response->getBody() : '',
-                          'recipient' => $ticket->getOwner(),
-                          'recipient.name.first' => $recipient->getName()->getFirst(),
-                      )
-                  );
+                  $extraVars = UsersName::getNameFormats($recipient, 'recipient');
+                  $extraVars = array_merge($extraVars, array(
+                    'message'   => $message,
+                    'signature' => $signature,
+                    'response'  => ($response) ? $response->getBody() : '',
+                    'recipient' => $ticket->getOwner()));
+                  $bccmsg = $ticket->replaceVars($bccmsg->asArray(), $extraVars);
 
                   $email->send($recipient, $bccmsg['subj'], $bccmsg['body'], $attachments,
                       $options);
diff --git a/include/class.user.php b/include/class.user.php
index dcd04b9c5d59f2bc6c02f4e54c8e928a26c647d5..083e0d5bf2b1853e82d6804a53641d353dbf8fd9 100644
--- a/include/class.user.php
+++ b/include/class.user.php
@@ -813,6 +813,16 @@ implements TemplateVariable {
         return $this;
     }
 
+    function getNameFormats($user, $type) {
+      $nameFormats = array();
+
+      foreach (PersonsName::allFormats() as $format => $func) {
+          $nameFormats[$type . '.name.' . $format] = $user->getName()->$func[1]();
+      }
+
+      return $nameFormats;
+    }
+
     function asVar() {
         return $this->__toString();
     }
diff --git a/include/client/templates/thread-entry.tmpl.php b/include/client/templates/thread-entry.tmpl.php
index ad9f3dc9fa33282b4a9bec980cc7daf2ee9fc7fc..e49b3b0389bf1c9d2f7c330ebac9039b536c0fc9 100644
--- a/include/client/templates/thread-entry.tmpl.php
+++ b/include/client/templates/thread-entry.tmpl.php
@@ -1,6 +1,6 @@
 <?php
 global $cfg;
-$entryTypes = array('M'=>'message', 'R'=>'response', 'N'=>'note', 'B' => 'bccmessage');
+$entryTypes = ThreadEntry::getTypes();
 $user = $entry->getUser() ?: $entry->getStaff();
 if ($entry->staff && $cfg->hideStaffName())
     $name = __('Staff');
@@ -11,13 +11,14 @@ if ($cfg->isAvatarsEnabled() && $user)
     $avatar = $user->getAvatar();
 ?>
 <?php
-  if ($entryTypes[$entry->type] == 'note') {
-    $entryTypes[$entry->type] = 'bccmessage';
+$type = $entryTypes[$entry->type];
+if ($type == 'note') {
+    $type =  'bccmessage';
     $entry->type = 'B';
-  }
+}
 ?>
 
-<div class="thread-entry <?php echo $entryTypes[$entry->type]; ?> <?php if ($avatar) echo 'avatar'; ?>">
+<div class="thread-entry <?php echo $type; ?> <?php if ($avatar) echo 'avatar'; ?>">
 <?php if ($avatar) { ?>
     <span class="<?php echo ($entry->type == 'M' || $entry->type == 'B') ? 'pull-left' : 'pull-right'; ?> avatar">
 <?php echo $avatar; ?>
diff --git a/include/staff/filter.inc.php b/include/staff/filter.inc.php
index 100e1273cb9def31eef2bc386705526e5fddb117..5816b4bf388cb147566688be145c9d5f8d72e6c8 100644
--- a/include/staff/filter.inc.php
+++ b/include/staff/filter.inc.php
@@ -240,17 +240,16 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
                 if ($filter) { foreach ($filter->getActions() as $A) {
                     $_warn = '';
                     $existing[] = $A->type;
+                    $config = JsonDataParser::parse($A->configuration);
                     if($A->type == 'dept') {
                       $errors['topic_id'] = '';
-                      $dept_config = $A->parseConfiguration($_POST);
-                      $dept = Dept::lookup($dept_config['dept_id']);
+                      $dept = Dept::lookup($config['dept_id']);
                       if($dept && !$dept->isActive())
                         $_warn = sprintf(__('%s must be active'), __('Department'));
                     }
                     elseif($A->type == 'topic') {
                       $errors['dept_id'] = '';
-                      $topic_config = $A->parseConfiguration($_POST);
-                      $topic = Topic::lookup($topic_config['topic_id']);
+                      $topic = Topic::lookup($config['topic_id']);
                       if($topic && !$topic->isActive())
                         $_warn = sprintf(__('%s must be active'), __('Help Topic'));
                     }
diff --git a/include/staff/templates/collaborators.tmpl.php b/include/staff/templates/collaborators.tmpl.php
index 7f80a5804053f2c9b9ecf23d9880f4d5555f7b75..1a50164f1f78421050098dfef38f89de93d9cf0b 100644
--- a/include/staff/templates/collaborators.tmpl.php
+++ b/include/staff/templates/collaborators.tmpl.php
@@ -65,7 +65,7 @@ if(($users=$thread->getCollaborators())) {?>
     ?>
     <td>
       <div><a class="collaborator" id="addcollaborator"
-          href="#thread/<?php echo $thread->getId(); ?>/add-collaborator"
+          href="#thread/<?php echo $thread->getId(); ?>/add-collaborator/addcc"
           ><i class="icon-plus-sign"></i> <?php echo __('Add Collaborator'); ?></a></div>
     </td>
     </table>
diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php
index dd351122439b1d657e8c2aa96e982b828266036d..b5ededef80a34f4bd784568e908c2edf1b8ef8fe 100644
--- a/include/staff/ticket-view.inc.php
+++ b/include/staff/ticket-view.inc.php
@@ -1197,7 +1197,7 @@ $(function() {
 
    if(el.val().includes("NEW")) {
      $("li[title='— Add New —']").remove();
-     var url = 'ajax.php/thread/' + tid + '/add-collaborator' ;
+     var url = 'ajax.php/thread/' + tid + '/add-collaborator/' + addTo ;
       $.userLookup(url, function(user) {
         e.preventDefault();
          if($('.dialog#confirm-action').length) {
diff --git a/scp/ajax.php b/scp/ajax.php
index c746da68d0650c46ce0b524f789803e70d6b1582..85d010e92b48b47d39643715bd8d9884c4c040c8 100644
--- a/scp/ajax.php
+++ b/scp/ajax.php
@@ -211,9 +211,9 @@ $dispatcher = patterns('',
         url_get('^(?P<tid>\d+)/collaborators/preview$', 'previewCollaborators'),
         url_get('^(?P<tid>\d+)/collaborators$', 'showCollaborators'),
         url_post('^(?P<tid>\d+)/collaborators$', 'updateCollaborators'),
-        url_get('^(?P<tid>\d+)/add-collaborator/(?P<uid>\d+)$', 'addCollaborator'),
+        url_get('^(?P<tid>\d+)/add-collaborator/(?P<type>\w+)/(?P<uid>\d+)$', 'addCollaborator'),
         url_get('^(?P<tid>\d+)/add-collaborator/auth:(?P<bk>\w+):(?P<id>.+)$', 'addRemoteCollaborator'),
-        url('^(?P<tid>\d+)/add-collaborator$', 'addCollaborator'),
+        url('^(?P<tid>\d+)/add-collaborator/(?P<type>\w+)$', 'addCollaborator'),
         url_get('^(?P<tid>\d+)/collaborators/(?P<cid>\d+)/view$', 'viewCollaborator'),
         url_post('^(?P<tid>\d+)/collaborators/(?P<cid>\d+)$', 'updateCollaborator')
     )),
diff --git a/scp/filters.php b/scp/filters.php
index 23bbe23e37ae0721eccbf43288dbfc6a77ab0e75..c83f9eac074175b908b3cea6cf3eaaa75778f64a 100644
--- a/scp/filters.php
+++ b/scp/filters.php
@@ -120,11 +120,12 @@ $tip_namespace = 'manage.filter';
 if($filter || ($_REQUEST['a'] && !strcasecmp($_REQUEST['a'],'add'))) {
   if($filter) {
     foreach ($filter->getActions() as $A) {
+      $config = JsonDataParser::parse($A->configuration);
       if($A->type == 'dept')
-        $dept = Dept::lookup($A->parseConfiguration($_POST)['dept_id']);
+        $dept = Dept::lookup($config['dept_id']);
 
       if($A->type == 'topic')
-        $topic = Topic::lookup($A->parseConfiguration($_POST)['topic_id']);
+        $topic = Topic::lookup($config['topic_id']);
     }
   }