diff --git a/include/class.charset.php b/include/class.charset.php
index d33c3abd105e067c169cff6a348f774b2d3bf079..160c26fadb59a8bc3dc10a4aba7277e2f269af21 100644
--- a/include/class.charset.php
+++ b/include/class.charset.php
@@ -77,4 +77,32 @@ class Charset {
         return self::transcode($text, $charset, self::UTF8);
     }
 }
+
+class transcode_filter extends php_user_filter {
+  var $from;
+  var $to;
+
+  function filter($in, $out, &$consumed, $closing) {
+      while ($bucket = stream_bucket_make_writeable($in)) {
+        $bucket->data = Charset::transcode($bucket->data, $this->from,
+                $this->to);
+        $consumed += $bucket->datalen;
+        stream_bucket_append($out, $bucket);
+      }
+      return PSFS_PASS_ON;
+  }
+
+  function onCreate() {
+      switch ($this->filtername) {
+      case 'transcode.utf8-ascii':
+          $this->from ='utf-8';
+          $this->to = 'ISO-8859-1';
+          break;
+      default:
+          return false;
+      }
+      return true;
+  }
+}
+stream_filter_register('transcode.*', 'transcode_filter');
 ?>
diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php
index c867531d983434cc99f9d7883f485405ce916587..6d654d8a300805b084bc22389a537f870654cbef 100644
--- a/include/class.dynamic_forms.php
+++ b/include/class.dynamic_forms.php
@@ -156,8 +156,12 @@ class DynamicForm extends VerySimpleModel {
         $inst = DynamicFormEntry::create(
             array('form_id'=>$this->get('id'), 'sort'=>$sort)
         );
+
         if ($data)
             $inst->setSource($data);
+
+        $inst->_fields = $this->_fields ?: null;
+
         return $inst;
     }
 
@@ -1795,7 +1799,7 @@ class SelectionField extends FormField {
     function getSearchMethods() {
         return array(
             'set' =>        __('has a value'),
-            'notset' =>     __('does not have a value'),
+            'nset' =>     __('does not have a value'),
             'includes' =>   __('includes'),
             '!includes' =>  __('does not include'),
         );
@@ -1804,7 +1808,7 @@ class SelectionField extends FormField {
     function getSearchMethodWidgets() {
         return array(
             'set' => null,
-            'notset' => null,
+            'nset' => null,
             'includes' => array('ChoiceField', array(
                 'choices' => $this->getChoices(),
                 'configuration' => array('multiselect' => true),
diff --git a/include/class.filter.php b/include/class.filter.php
index 690a97e62f7a2ea852d69583ab5d20ebe757bf25..4a66737c11bb468c6184c1c1b8431e97d93a09fd 100644
--- a/include/class.filter.php
+++ b/include/class.filter.php
@@ -471,29 +471,9 @@ 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($config['dept_id']);
-            $dept_action = $A->getId();
-          }
-
-          if ($A->type == 'topic') {
-            $topic = Topic::lookup($config['topic_id']);
-            $topic_action = $A->getId();
-          }
-        }
-      }
-
-      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() && (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'));
+        //validate filter actions before moving on
+        if (!self::validate_actions($vars, $errors))
+            return false;
 
         if(!$vars['execorder'])
             $errors['execorder'] = __('Order required');
@@ -551,42 +531,67 @@ 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;
     }
 
-    function validate_actions($action) {
-      $errors = array();
-      $config = json_decode($action->ht['configuration'], true);
-      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;
+    function validate_actions($vars, &$errors) {
+        if (!is_array(@$vars['actions']))
+            return;
 
-        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;
+      foreach ($vars['actions'] as $sort=>$v) {
+          if (is_array($v)) {
+              $info = $v['type'];
+              $sort = $v['sort'] ?: $sort;
+          } else
+              $info = substr($v, 1);
+
+          $action = new FilterAction(array(
+              'type'=>$info,
+              'sort' => (int) $sort,
+          ));
+          $errors = array();
+          $action->setConfiguration($errors, $vars);
+
+          $config = json_decode($action->ht['configuration'], true);
+          if (is_numeric($action->ht['type'])) {
+              foreach ($config as $key => $value) {
+                  if ($key == 'topic_id') {
+                      $action->ht['type'] = 'topic';
+                      $config['topic_id'] = $value;
+                  }
+                  if ($key == 'dept_id') {
+                      $action->ht['type'] = 'dept';
+                      $config['dept_id'] = $value;
+                  }
+              }
           }
-          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;
-            }
+          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');
+              }
+              break;
+            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');
+              }
+              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']));
+                }
+              }
+              break;
           }
-          break;
       }
 
-      return false;
-
+      return count($errors) == 0;
     }
 
     function save_actions($id, $vars, &$errors) {
@@ -598,7 +603,8 @@ class Filter {
                 $info = $v['type'];
                 $sort = $v['sort'] ?: $sort;
                 $action = 'N';
-            } else {
+            }
+            else {
                 $action = $v[0];
                 $info = substr($v, 1);
             }
@@ -612,24 +618,12 @@ class Filter {
                 ));
                 $I->setConfiguration($errors, $vars);
 
-                $invalid = self::validate_actions($I);
-                if ($invalid) {
-                  $errors['err'] = sprintf($invalid['err']);
-                  return;
-                }
-
                 $I->save();
                 break;
             case 'I': # existing filter action
                 if ($I = FilterAction::lookup($info)) {
                     $I->setConfiguration($errors, $vars);
 
-                    $invalid = self::validate_actions($I);
-                    if ($invalid) {
-                      $errors['err'] = sprintf($invalid['err']);
-                      return;
-                    }
-
                     $I->sort = (int) $sort;
                     $I->save();
                 }
diff --git a/include/class.filter_action.php b/include/class.filter_action.php
index 59bafbf57ebfe40205adbfe2dbecd60b33525083..181935af263d4ea863b6b36b8a1da25adc1a3406 100644
--- a/include/class.filter_action.php
+++ b/include/class.filter_action.php
@@ -69,7 +69,9 @@ class FilterAction extends VerySimpleModel {
 
     function getImpl() {
         if (!isset($this->_impl)) {
-            if (!($I = self::lookupByType($this->type, $this)))
+            //TODO: Figure out why $this->type gives an id
+            $existing = is_numeric($this->type) ? (self::lookup($this->type)) : $this;
+            if (!($I = self::lookupByType($existing->type, $existing)))
                 throw new Exception(sprintf(
                     '%s: No such filter action registered', $this->type));
             $this->_impl = $I;
diff --git a/include/class.format.php b/include/class.format.php
index 05d8699881bfb67ea117b916bb22aa8f45fb8f96..a2d72340dcf02e3cba45990e4e455ab8146604e3 100644
--- a/include/class.format.php
+++ b/include/class.format.php
@@ -308,8 +308,9 @@ class Format {
                   ':<html[^>]+:i',              # drop html attributes
                   ':<(a|span) (name|style)="(mso-bookmark\:)?_MailEndCompose">(.+)?<\/(a|span)>:', # Drop _MailEndCompose
                   ':<div dir=(3D)?"ltr">(.*?)<\/div>(.*):is', # drop Gmail "ltr" attributes
+                  ':data-cid="[^"]*":',         # drop image cid attributes
             ),
-            array('', '', '', '', '<html', '$4', '$2 $3'),
+            array('', '', '', '', '<html', '$4', '$2 $3', ''),
             $html);
 
         // HtmLawed specific config only
diff --git a/include/class.forms.php b/include/class.forms.php
index 5022a8ce2808fa88c56f52205b66ad5186f08c2b..7d7c585e9e8629ab2d09f74c0f50158dbbab0006 100644
--- a/include/class.forms.php
+++ b/include/class.forms.php
@@ -4605,7 +4605,7 @@ class FreeTextWidget extends Widget {
             <section class="freetext-files">
             <div class="title"><?php echo __('Related Resources'); ?></div>
             <?php foreach ($attachments->all() as $attach) {
-                $filename = $attach->getFilename();
+                $filename = Format::htmlchars($attach->getFilename());
                 ?>
                 <div class="file">
                 <a href="<?php echo $attach->file->getDownloadUrl(); ?>"
diff --git a/include/class.pdf.php b/include/class.pdf.php
index 10398fd65d171a23231795f32dbb2288014d08da..672bade176aef2d56d0235ebfbf384e62d5c1dd9 100644
--- a/include/class.pdf.php
+++ b/include/class.pdf.php
@@ -90,7 +90,7 @@ class Ticket2PDF extends mPDFWithLocalImages
             return;
         $html = ob_get_clean();
 
-        $this->SetAutoFont();
+        $this->SetAutoFont(AUTOFONT_RTL);
         $this->WriteHtml($html, 0, true, true);
     }
 }
@@ -120,7 +120,7 @@ class Task2PDF extends mPDFWithLocalImages {
         ob_start();
         include STAFFINC_DIR.'templates/task-print.tmpl.php';
         $html = ob_get_clean();
-        $this->SetAutoFont();
+        $this->SetAutoFont(AUTOFONT_RTL);
         $this->WriteHtml($html, 0, true, true);
 
     }
diff --git a/include/class.staff.php b/include/class.staff.php
index a9024227332507d9dce728d05ed8bf0512886f08..3833c63533505f740f8ca1da3ed13d494e9fec96 100644
--- a/include/class.staff.php
+++ b/include/class.staff.php
@@ -76,7 +76,9 @@ implements AuthenticatedUser, EmailContact, TemplateVariable, Searchable {
         if (isset($this->_config[$field]))
             return $this->_config[$field];
 
-        return parent::get($field, $default);
+        try {
+            return parent::get($field, $default);
+        } catch (Exception $e) {}
     }
 
     function getConfig() {
diff --git a/include/staff/users.inc.php b/include/staff/users.inc.php
index 04c292a0bbf5fbc66b47f99564eb94f1fae8abdc..6e61c002b5ceb721bd50d8ed6d27d6111c1557d7 100644
--- a/include/staff/users.inc.php
+++ b/include/staff/users.inc.php
@@ -10,13 +10,15 @@ $users = User::objects()
 
 if ($_REQUEST['query']) {
     $search = $_REQUEST['query'];
-    $users->filter(Q::any(array(
+    $filter = Q::any(array(
         'emails__address__contains' => $search,
         'name__contains' => $search,
         'org__name__contains' => $search,
-        'cdata__phone__contains' => $search,
-        // TODO: Add search for cdata
-    )));
+    ));
+    if (UserForm::getInstance()->getField('phone'))
+        $filter->add(array('cdata__phone__contains' => $search));
+
+    $users->filter($filter);
     $qs += array('query' => $_REQUEST['query']);
 }