From 584465c9a6080a5bddca5face3b5df11018ffcf7 Mon Sep 17 00:00:00 2001 From: Jared Hancock <jared@osticket.com> Date: Mon, 27 Jan 2014 13:45:43 -0600 Subject: [PATCH] filters: Implement regular expression matching --- include/class.filter.php | 50 +++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/include/class.filter.php b/include/class.filter.php index a17962cf2..d295c240c 100644 --- a/include/class.filter.php +++ b/include/class.filter.php @@ -242,12 +242,14 @@ class Filter { $how = array( # how => array(function, null or === this, null or !== this) - 'equal' => array('strcmp', 0), - 'not_equal' => array('strcmp', null, 0), - 'contains' => array('strpos', null, false), - 'dn_contain'=> array('strpos', false), - 'starts' => array('strpos', 0), - 'ends' => array('endsWith', true) + 'equal' => array('strcasecmp', 0), + 'not_equal' => array('strcasecmp', null, 0), + 'contains' => array('stripos', null, false), + 'dn_contain'=> array('stripos', false), + 'starts' => array('stripos', 0), + 'ends' => array('iendsWith', true), + 'match' => array('pregMatchB', 1), + 'not_match' => array('pregMatchB', null, 0), ); $match = false; @@ -260,12 +262,8 @@ class Filter { foreach ($this->getRules() as $rule) { if (!isset($how[$rule['h']])) continue; list($func, $pos, $neg) = $how[$rule['h']]; - # TODO: convert $what and $rule['v'] to mb_strtoupper and do - # case-sensitive, binary-safe comparisons. Would be really - # nice to do $rule['v'] on the database side for - # performance -- but ::getFlatRules() is a blocker - $result = call_user_func($func, strtoupper($what[$rule['w']]), - strtoupper($rule['v'])); + + $result = call_user_func($func, $what[$rule['w']], $rule['v']); if (($pos === null && $result !== $neg) or ($result === $pos)) { # Match. $match = true; @@ -341,7 +339,9 @@ class Filter { 'contains'=> 'Contains', 'dn_contain'=> 'Does Not Contain', 'starts'=> 'Starts With', - 'ends'=> 'Ends With' + 'ends'=> 'Ends With', + 'match'=> 'Matches Regex', + 'not_match'=> 'Does Not Match Regex', ); } @@ -404,6 +404,14 @@ class Filter { $rules=array(); for($i=1; $i<=25; $i++) { //Expecting no more than 25 rules... if($vars["rule_w$i"] || $vars["rule_h$i"]) { + // Check for REGEX compile errors + if (in_array($vars["rule_h$i"], array('match','not_match'))) { + $wrapped = "/".$vars["rule_v$i"]."/iu"; + if (false === @preg_match($vars["rule_v$i"], ' ') + && (false !== @preg_match($wrapped, ' '))) + $vars["rule_v$i"] = $wrapped; + } + if(!$vars["rule_w$i"] || !in_array($vars["rule_w$i"],$matches)) $errors["rule_$i"]='Invalid match selection'; elseif(!$vars["rule_h$i"] || !in_array($vars["rule_h$i"],$types)) @@ -414,6 +422,12 @@ class Filter { && $vars["rule_h$i"]=='equal' && !Validator::is_email($vars["rule_v$i"])) $errors["rule_$i"]='Valid email required for the match type'; + elseif (in_array($vars["rule_h$i"], array('match','not_match')) + && (false === @preg_match($vars["rule_v$i"], ' '))) + $errors["rule_$i"] = sprintf('Regex compile error: (#%s)', + preg_last_error()); + + else //for everything-else...we assume it's valid. $rules[]=array('what'=>$vars["rule_w$i"], 'how'=>$vars["rule_h$i"],'val'=>$vars["rule_v$i"]); @@ -902,13 +916,17 @@ class TicketFilter { * Returns TRUE if the haystack ends with needle and FALSE otherwise. * Thanks, http://stackoverflow.com/a/834355 */ -function endsWith($haystack, $needle) +function iendsWith($haystack, $needle) { - $length = strlen($needle); + $length = mb_strlen($needle); if ($length == 0) { return true; } - return (substr($haystack, -$length) === $needle); + return (strcasecmp(mb_substr($haystack, -$length), $needle) === 0); +} + +function pregMatchB($subject, $pattern) { + return preg_match($pattern, $subject); } ?> -- GitLab