From cbdde7a3370f61be6e82a53770fbb4c4d44ceee4 Mon Sep 17 00:00:00 2001
From: Reinhold Kainhofer <reinhold@kainhofer.com>
Date: Sun, 17 Nov 2013 13:32:58 +0100
Subject: [PATCH] Make function names and operators case-insensitive

Internally, operators are converted to UPPER case, while function names are converted to lower case.
---
 rules_shipping_advanced.php | 31 ++++++++++++++++---------------
 rules_shipping_base.php     |  6 +++---
 2 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/rules_shipping_advanced.php b/rules_shipping_advanced.php
index 5a1610a..13d69a8 100644
--- a/rules_shipping_advanced.php
+++ b/rules_shipping_advanced.php
@@ -113,7 +113,7 @@ class ShippingRule_Advanced extends ShippingRule {
 		// (OR, AND, in; but make sure we don't capture parts of words, so we need to 
 		// use lookbehind/lookahead patterns to exclude OR following another letter 
 		// or followed by another letter) and then all arithmetic operators
-		$re = '/\s*("[^"]*"|\'[^\']*\'|(?<![A-Za-z0-9])(?:OR|AND|IN|or|and|in)(?![A-Za-z0-9])|&&|<=|=>|>=|=>|<>|!=|==|<|=|>|~|\+|-|\*|\/|%|\(|\)|\^|,)\s*/';
+		$re = '/\s*("[^"]*"|\'[^\']*\'|(?<![A-Za-z0-9])(?:OR|AND|IN)(?![A-Za-z0-9])|&&|<=|=>|>=|=>|<>|!=|==|<|=|>|~|\+|-|\*|\/|%|\(|\)|\^|,)\s*/i';
 		$atoms = preg_split($re, $expression, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
 		// JFactory::getApplication()->enqueueMessage("TOKENIZING '$expression' returns: <pre>".print_r($atoms,1)."</pre>", 'error');
 		return $atoms;
@@ -162,21 +162,21 @@ class ShippingRule_Advanced extends ShippingRule {
 		
 		$operators = array(
 			".-" => 100, ".+" => 100,
-			"in" => 80, 
+			"IN" => 80, 
 			"^"  => 70, 
 			"*"  => 60, "/"  => 60, "%"  => 60, 
 			"+"  => 50, "-"  => 50, 
 			"<"  => 40, "<=" => 40, ">"  => 40, ">=" => 40, "=>" => 40, "=<" => 40,
 			"==" => 40, "!=" => 40, "<>" => 40, "~" => 40,
-			"&&"  => 21, "AND" => 21, 
-			"OR"  => 20, 
+			"&&"  => 21, "AND" => 21,
+			"OR"  => 20,
 			"="  => 10,
 			"("  =>  0, ")"  =>0 
 		);
 		$unary_ops = array("-" => ".-", "+" => ".+");
 
 		// Any of these indicate a comparison and thus a condition:
-		$condition_ops = array('<', '<=', '=<', '<>', '!=', '==', '>', '>=', '=>', '~', 'OR', 'AND', 'AND', '&&', 'in');
+		$condition_ops = array('<', '<=', '=<', '<>', '!=', '==', '>', '>=', '=>', '~', 'OR', 'AND', '&&', 'IN');
 		$comparison_ops = array('<', '<=', '=<', '<>', '!=', '==', '>', '>=', '=>', '~');
 		$is_condition = false;
 		$is_assignment = false;
@@ -186,6 +186,7 @@ class ShippingRule_Advanced extends ShippingRule {
 		$function_args = array();
 		$out_stack = array();
 		foreach ($atoms as $a) { // 2)
+			$aupper = strtoupper($a); # All operators are converted to uppercase!
 		
 			if ($a == ",") { // A function argument separator
 				// pop-and-apply all operators back to the left function paren
@@ -209,7 +210,7 @@ class ShippingRule_Advanced extends ShippingRule {
 			} elseif ($a == "(" and !$prev_token_operator) { // 5) parenthesis after operand -> FUNCTION CALL
 				array_push ($stack, "FUNCTION(");
 				// retrieve function name from RPN list (remove last entry from operand stack!)
-				$function = array_pop ($out_stack);
+				$function = strtolower(array_pop ($out_stack));
 				$new_stack = array();
 				// Set up function call data structure on function_args stack:
 				$function_args[] = array(/* old operand stack: */$out_stack, $function);
@@ -253,10 +254,10 @@ class ShippingRule_Advanced extends ShippingRule {
 				} while (true);
 				$prev_token_operator = false;
 				
-			} elseif (isset($unary_ops[$a]) && $prev_token_operator) { // 4) UNARY operators
+			} elseif (isset($unary_ops[$aupper]) && $prev_token_operator) { // 4) UNARY operators
 				// Unary and binary operators need to be handled differently: 
 				// Unary operators must only pop other unary operators, never any binary operator
-				$unary_op = $unary_ops[$a];
+				$unary_op = $unary_ops[$aupper];
 				// For unary operators, pop other unary operators from the stack until you reach an opening parenthesis, 
 				// an operator of lower precedence, or a right associative symbol of equal precedence. 
 				while (count($stack)>0) { // 4a)
@@ -273,10 +274,10 @@ class ShippingRule_Advanced extends ShippingRule {
 				array_push ($stack, $unary_op); // 4b)
 				$prev_token_operator = true;
 				
-			} elseif (isset($operators[$a])) { // 4) BINARY operators
-				$prec = $operators[$a];
-				$is_condition |= in_array($a, $condition_ops);
-				$is_assignment |= ($a == "=");
+			} elseif (isset($operators[$aupper])) { // 4) BINARY operators
+				$prec = $operators[$aupper];
+				$is_condition |= in_array($aupper, $condition_ops);
+				$is_assignment |= ($aupper == "=");
 				
 				// For operators, pop operators from the stack until you reach an opening parenthesis, 
 				// an operator of lower precedence, or a right associative symbol of equal precedence. 
@@ -295,7 +296,7 @@ class ShippingRule_Advanced extends ShippingRule {
 						array_push ($out_stack, $op);
 					}
 				} while (0);
-				array_push ($stack, $a); // 4b)
+				array_push ($stack, $aupper); // 4b)
 				$prev_token_operator = true;
 				
 			} else { // 3) Everything else is an Operand
@@ -368,12 +369,12 @@ class ShippingRule_Advanced extends ShippingRule {
 				// if e is a comparison, and operator(o1) is also a comparison, 
 				// insert the arguments to the existing comparison instead of creating a new one
 				if (in_array ($e, $comparison_ops)) {
-					if ($o1[0]=='comparison') {
+					if ($o1[0]=='COMPARISON') {
 						$op = $o1;
 						// Append the new comparison to the existing one
 						array_push($op, $e, $o2);
 					} else {
-						$op = array ('comparison', $o1, $e, $o2);
+						$op = array ('COMPARISON', $o1, $e, $o2);
 					}
 				} else {
 					$op = array ($e, $o1, $o2); // 4b)
diff --git a/rules_shipping_base.php b/rules_shipping_base.php
index 776b8b3..422b795 100644
--- a/rules_shipping_base.php
+++ b/rules_shipping_base.php
@@ -872,7 +872,7 @@ class ShippingRule {
 			}
 			foreach ($expr as $e) {
 				$term = $evaluate ? ($this->evaluateTerm($e, $vals)) : $e;
-				if ($op == 'comparison') {
+				if ($op == 'COMPARISON') {
 					// For comparisons, we only evaluate every other term (the operators are NOT evaluated!)
 					$evaluate = !$evaluate;
 				}
@@ -888,7 +888,7 @@ class ShippingRule {
 				case 'OR':  foreach ($args as $a) { $res = ($res || $a); }; break;
 				case '&&':
 				case 'AND':  $res = true; foreach ($args as $a) { $res = ($res && $a); }; break;
-				case 'in': $res = in_array($args[0], $args[1]);  break;
+				case 'IN': $res = in_array($args[0], $args[1]);  break;
 				
 				// Comparisons:
 				case '<':
@@ -902,7 +902,7 @@ class ShippingRule {
 				case '>':
 				case '~':
 					$res = $this->evaluateComparison(array($args[0], $op, $args[1]), $vals); break;
-				case 'comparison':
+				case 'COMPARISON':
 					$res = $this->evaluateComparison($args, $vals); break;
 				
 				// Unary operators:
-- 
GitLab