diff --git a/Makefile b/Makefile
index 62a4826c728fd7059d5890c974193c7f57a8af99..3289f16e67a595aa8e4db50ee4a3f2cc61094b06 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ BASE=rules_shipping
 BASE_ADV=rules_shipping_advanced
 PLUGINTYPE=vmshipment
 ZIPBASE=opentools_vm
-VERSION=5.99
+VERSION=5.99.1
 
 PLUGINFILES=$(BASE).php $(BASE)_base.php $(BASE)_framework_joomla.php $(BASE).script.php $(BASE).xml index.html
 PLUGINFILES_ADV=$(BASE_ADV).php $(BASE)_base.php $(BASE)_framework_joomla.php $(BASE_ADV).script.php $(BASE_ADV).xml index.html
diff --git a/library/rules_shipping_framework.php b/library/rules_shipping_framework.php
index d0b6e1c307bbb1d27a7b1eb7c0ce389aea732440..3c89c16218870dd25b21bbedb06c81e17fb60666 100644
--- a/library/rules_shipping_framework.php
+++ b/library/rules_shipping_framework.php
@@ -1,6 +1,8 @@
 <?php
 
-defined ('_JEXEC') or die('Restricted access');
+if ( !defined( 'ABSPATH' ) && !defined('_JEXEC') ) { 
+	die( 'Direct Access to ' . basename( __FILE__ ) . ' is not allowed.' );
+}
 
 /**
  * Shipping By Rules Framework for general, rules-based shipments, like regular postal services with complex shipping cost structures
@@ -217,6 +219,27 @@ class RulesShippingFramework {
 			'maxquantity' => 0,
 		);
 	}
+	
+	protected function getDateTimeVariables($cart, $products, $method) {
+		$utime = microtime(true);
+		$milliseconds = (int)(1000*($utime - (int)$utime));
+		$millisecondsstring = sprintf('%03d', $milliseconds);
+		return array(
+			'year'        => date("Y", $utime),
+			'year2'       => date("y", $utime),
+			'month'       => date("m", $utime),
+			'day'         => date("d", $utime),
+			'weekday'     => date("N", $utime),
+			'hour'        => date("H", $utime),
+			'hour12'      => date("h", $utime),
+			'ampm'        => date("a", $utime),
+			'minute'      => date("i", $utime),
+			'second'      => date("s", $utime),
+			'decisecond'  => $millisecondsstring[0],
+			'centisecond' => substr($millisecondsstring, 0, 2),
+			'millisecond' => $millisecondsstring,
+		);
+	}
 
 	protected function getOrderDimensions ($cart, $products, $method) {
 		return array();
@@ -237,6 +260,46 @@ class RulesShippingFramework {
 	protected function getOrderPrices ($cart, $products, $method) {
 		return array();
 	}
+	
+	/** 
+	 * Extract information about non-numerical zip codes (UK and Canada) from the postal code
+	 */
+	protected function getAddressZIP ($zip) {
+		$values = array();
+
+		// Postal code Check for UK postal codes: Use regexp to determine if ZIP structure matches and also to extract the parts.
+		// Also handle UK overseas areas/islands that use four-letter outward codes rather than "A{1,2}0{1,2}A{0,1} 0AA"
+		$zip=strtoupper($zip);
+		if (isset($zip) and preg_match('/^\s*(([A-Z]{1,2})(\d{1,2})([A-Z]?)|[A-Z]{4}|GIR)\s*(\d[A-Z]{2})\s*$/', $zip, $match)) {
+			$values['uk_outward'] = $match[1];
+			$values['uk_area'] = $match[2];
+			$values['uk_district'] = $match[3];
+			$values['uk_subdistrict'] = $match[4];
+			$values['uk_inward'] = $match[5];
+		} else {
+			$values['uk_outward'] = NULL;
+			$values['uk_area'] = NULL;
+			$values['uk_district'] = NULL;
+			$values['uk_subdistrict'] = NULL;
+			$values['uk_inward'] = NULL;
+		}
+		// Postal code Check for Canadian postal codes: Use regexp to determine if ZIP structure matches and also to extract the parts.
+		if (isset($zip) and preg_match('/^\s*(([A-Za-z])(\d)([A-Za-z]))\s*(\d[A-Za-z]\d)\s*$/', $zip, $match)) {
+			$values['canada_fsa'] = $match[1];
+			$values['canada_area'] = $match[2];
+			$values['canada_urban'] = $match[3];
+			$values['canada_subarea'] = $match[4];
+			$values['canada_ldu'] = $match[5];
+		} else {
+			$values['canada_fsa'] = NULL;
+			$values['canada_area'] = NULL;
+			$values['canada_urban'] = NULL;
+			$values['canada_subarea'] = NULL;
+			$values['canada_ldu'] = NULL;
+		}
+		// print("<pre>values: ".print_r($values,1)."</pre>");
+		return $values;
+	}
 
 	/** Allow child classes to add additional variables for the rules or modify existing one
 	 */
@@ -250,6 +313,7 @@ class RulesShippingFramework {
 	
 	public function getCartValues ($cart, $products, $method) {
 		$cartvals = array_merge (
+			$this->getDateTimeVariables($cart, $products, $method),
 			$this->getOrderCounts($cart, $products, $method),
 			// Add the prices, optionally calculated from the products subset of the cart
 			$this->getOrderPrices ($cart, $products, $method),
@@ -296,31 +360,33 @@ class RulesShippingFramework {
 			$cartvals_callback = function ($products) use ($this_class, $cart, $method) {
 				return $this_class->getCartValues ($cart, $products, $method, NULL);
 			};
-			foreach ($this->rules[$id] as $r) {
-				if ($r->matches($cartvals, $cart->products, $cartvals_callback)) {
-					$rtype = $r->getType();
-					switch ($rtype) {
-						case 'shipping': 
-						case 'shippingwithtax':
-						case 'noshipping': 
-								$result["rule"] = $r;
-								$result["rule_name"] = $r->getRuleName();
-								break;
-						case 'modifiers_add':
-						case 'modifiers_multiply':
-								$result[$rtype][] = $r;
-								break;
-						case 'definition': // A definition updates the $cartvals, but has no other effects
-								$cartvals[strtolower($r->getRuleName())] = $r->getValue();
-								break;
-						default:
-								$this->warning('OTSHIPMENT_RULES_UNKNOWN_TYPE', $r->getType(), $r->rulestring);
-								break;
+			if (isset($this->rules[$id])) {
+				foreach ($this->rules[$id] as $r) {
+					if ($r->matches($cartvals, $this->getCartProducts($cart, $method), $cartvals_callback)) {
+						$rtype = $r->getType();
+						switch ($rtype) {
+							case 'shipping': 
+							case 'shippingwithtax':
+							case 'noshipping': 
+									$result["rule"] = $r;
+									$result["rule_name"] = $r->getRuleName();
+									break;
+							case 'modifiers_add':
+							case 'modifiers_multiply':
+									$result[$rtype][] = $r;
+									break;
+							case 'definition': // A definition updates the $cartvals, but has no other effects
+									$cartvals[strtolower($r->getRuleName())] = $r->getValue();
+									break;
+							default:
+									$this->warning('OTSHIPMENT_RULES_UNKNOWN_TYPE', $r->getType(), $r->rulestring);
+									break;
+						}
+					}
+					if (!is_null($result["rule"])) {
+						$this->match[$id] = $result;
+						return $result; // <- This also breaks out of the foreach loop!
 					}
-				}
-				if (!is_null($result["rule"])) {
-					$this->match[$id] = $result;
-					return $result; // <- This also breaks out of the foreach loop!
 				}
 			}
 		}
@@ -329,6 +395,18 @@ class RulesShippingFramework {
 		return NULL;
 	}
 
+	protected function handleNoShipping($match, $method) {
+		if ($match['rule']->isNoShipping()) {
+			if (!empty($match["rule_name"]))
+				$this->warning('OTSHIPMENT_RULES_NOSHIPPING_MESSAGE', $match["rule_name"]);
+			$name = $this->getMethodName($method);
+			$this->debug('checkConditions '.$name.' indicates NoShipping for this method, specified by rule "'.$match["rule_name"].'" ('.$match['rule']->rulestring.').');
+			return true;
+		} else {
+			return false;
+		}
+	}
+	
 	/**
 	 * @param $cart
 	 * @param int             $method
@@ -339,19 +417,16 @@ class RulesShippingFramework {
 		$name = $this->getMethodName($method);
 		if (!isset($this->rules[$id])) 
 			$this->parseMethodRules($method);
+		// TODO: This needs to be redone sooner or later!
 		$match = $this->evaluateMethodRules ($cart, $method);
 		if ($match && !is_null ($match['rule'])) {
 			$this->setMethodCosts($method, $match, null);
 			// If NoShipping is set, this method should NOT offer any shipping at all, so return FALSE, otherwise TRUE
 			// If the rule has a name, print it as warning (otherwise don't print anything)
-			if ($match['rule']->isNoShipping()) {
-				if (!empty($match["rule_name"]))
-					$this->warning('OTSHIPMENT_RULES_NOSHIPPING_MESSAGE', $match["rule_name"]);
-				$this->debug('checkConditions '.$name.' indicates NoShipping for this method, specified by rule "'.$match["rule_name"].'" ('.$match['rule']->rulestring.').');
+			if ($this->handleNoShipping($match, $method)) {
 				return FALSE;
-			} else {
-				return TRUE;
 			}
+			return TRUE;
 		}
 		$this->debug('checkConditions '.$name.' does not fulfill all conditions, no rule matches');
 		return FALSE;
@@ -370,11 +445,16 @@ class RulesShippingFramework {
 	 * @return int
 	 */
 	function getCosts ($cart, $method) {
+		$results = array();
 		$id = $this->getMethodId($method);
 		if (!isset($this->rules[$id])) 
 			$this->parseMethodRules($method);
 		$match = $this->evaluateMethodRules ($cart, $method);
 		if ($match) {
+			if ($this->handleNoShipping($match, $method)) {
+				return $results;
+			}
+		
 			$r = $match["rule"];
 			$this->debug('Rule ' . $match["rule_name"] . ' ('.$r->rulestring.') matched.');
 
@@ -390,11 +470,20 @@ class RulesShippingFramework {
 			}
 			$this->setMethodCosts($method, $match, $cost);
 
-			return $cost;
+			$res = array(
+				'method' =>   $id,
+				'name' =>     $this->getMethodName($method),
+// 				'rulesetname'=>$match['ruleset_name'],
+				'rulename' => $match["rule_name"],
+				'cost' =>     $cost,
+			);
+			$results[] = $res;
 		}
 		
-		$this->debug('getCosts '.$this->getMethodName($method).' does not return shipping costs');
-		return 0;
+		if (empty($results)) {
+			$this->debug('getCosts '.$this->getMethodName($method).' does not return shipping costs');
+		}
+		return $results;
 	}
 	
 	public function getRuleName($methodid) {
@@ -676,6 +765,7 @@ class ShippingRule {
 		if (count($conditionvals)<1)
 			return $this->evaluateTerm($expr, $vals, $products, $cartvals_callback);
 
+		// TODO: Make this more general!
 		$filterkeys = array( 
 			"evaluate_for_categories" =>    'categories',
 			"evaluate_for_products" =>      'skus',
diff --git a/releases/plg_opentools_vm_rules_shipping_advanced_v5.99.1.zip b/releases/plg_opentools_vm_rules_shipping_advanced_v5.99.1.zip
new file mode 100644
index 0000000000000000000000000000000000000000..ea0fe3954b9dd2285ca7663571e513ab94b608f4
Binary files /dev/null and b/releases/plg_opentools_vm_rules_shipping_advanced_v5.99.1.zip differ
diff --git a/releases/plg_opentools_vm_rules_shipping_v5.99.1.zip b/releases/plg_opentools_vm_rules_shipping_v5.99.1.zip
new file mode 100644
index 0000000000000000000000000000000000000000..443982bf7dbae2aba81d44bb2029e246ab4ffb32
Binary files /dev/null and b/releases/plg_opentools_vm_rules_shipping_v5.99.1.zip differ
diff --git a/rules_shipping.xml b/rules_shipping.xml
index afc6f0ba033de854e56992d59a4f0b7b7b75f2f2..7711e204a53699cf060c3dc463707281816dc055 100644
--- a/rules_shipping.xml
+++ b/rules_shipping.xml
@@ -6,7 +6,7 @@
     <authorUrl>http://www.open-tools.net</authorUrl>
     <copyright>Copyright (C) 2013-2014, Reinhold Kainhofer</copyright>
     <license>GPL v3+</license>
-    <version>5.99</version>
+    <version>5.99.1</version>
     <description>OTSHIPMENT_RULES_DESC</description>
     <files>
         <filename plugin="rules_shipping">rules_shipping.php</filename>
diff --git a/rules_shipping_advanced.xml b/rules_shipping_advanced.xml
index da37c2e33f0f0d76415427f91e8d03d52ad7272b..188815a03863d9af945f5f7c2a9755d0260ef3d6 100644
--- a/rules_shipping_advanced.xml
+++ b/rules_shipping_advanced.xml
@@ -6,7 +6,7 @@
     <authorUrl>http://www.open-tools.net</authorUrl>
     <copyright>Copyright (C) 2013-2014, Reinhold Kainhofer</copyright>
     <license>GPL v3+</license>
-    <version>5.99</version>
+    <version>5.99.1</version>
     <description>OTSHIPMENT_RULES_ADV_DESC</description>
     <files>
         <filename plugin="rules_shipping_advanced">rules_shipping_advanced.php</filename>
diff --git a/rules_shipping_base.php b/rules_shipping_base.php
index 1c92cf0ec24ee2d28e7cc522e02d30c2816d42c2..9a3d279bdaae9a88f46812a827c32d7aaa866908 100644
--- a/rules_shipping_base.php
+++ b/rules_shipping_base.php
@@ -120,7 +120,10 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
 		// We need to call getCosts, because in J3 $method->rule_name and $method->cost as set in getCosts is no longer preserved.
 		// Instead, we simply call getCosts again, which as a side-effect sets all those members of $method.
 		$costs = $this->helper->getCosts($cart,$method);
-		$rulename = $this->helper->getRuleName($method->virtuemart_shipmentmethod_id);
+		if (empty($costs)) 
+			return FALSE;
+		$rulename = $costs[0]['rulename'];
+// 		$rulename = $this->helper->getRuleName($method->virtuemart_shipmentmethod_id);
 		$variables = $this->helper->getRuleVariables($method->virtuemart_shipmentmethod_id);
 		$values['virtuemart_order_id'] = $order['details']['BT']->virtuemart_order_id;
 		$values['order_number'] = $order['details']['BT']->order_number;
@@ -138,7 +141,12 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
 		return TRUE;
 	}
 	function getCosts (VirtueMartCart $cart, $method, $cart_prices) {
-		return $this->helper->getCosts($cart, $method, $cart_prices);
+		$costs = $this->helper->getCosts($cart, $method, $cart_prices);
+		if (empty($costs)) {
+			return false;
+		} else {
+			return $costs[0]['cost'];
+		}
 	}
 	protected function checkConditions ($cart, $method, $cart_prices) {
 		return $this->helper->checkConditions($cart, $method, $cart_prices);
diff --git a/rules_shipping_framework_joomla.php b/rules_shipping_framework_joomla.php
index 0c54b3eb0beac362cff6c966461f8b1a54445ca1..3792c516e0124bf1bcdd7f48141d21fecad955f8 100644
--- a/rules_shipping_framework_joomla.php
+++ b/rules_shipping_framework_joomla.php
@@ -102,10 +102,11 @@ class RulesShippingFrameworkJoomla extends RulesShippingFramework {
 		$counts = array(
 			'articles' => 0,
 			'products' => count($products),
+			'quantity' => 0,
 			'minquantity' => 9999999999,
 			'maxquantity' => 0,
 		);
-		
+
 		foreach ($products as $product) {
 			$counts['articles']   += $product->quantity;
 			$counts['maxquantity'] = max ($counts['maxquantity'], $product->quantity);