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']); }