From e1ceb050e19c7574bca146a8da7047ee4ff456b5 Mon Sep 17 00:00:00 2001
From: Marius Burkard <m.burkard@pixcept.de>
Date: Sun, 10 Jul 2016 05:02:35 -0400
Subject: [PATCH] Merge branch 'stable-3.1'

---
 interface/lib/classes/tpl.inc.php |  167 +++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 107 insertions(+), 60 deletions(-)

diff --git a/interface/lib/classes/tpl.inc.php b/interface/lib/classes/tpl.inc.php
index 4b411e2..2104cf6 100644
--- a/interface/lib/classes/tpl.inc.php
+++ b/interface/lib/classes/tpl.inc.php
@@ -234,12 +234,12 @@
 			if (is_array($k)) {
 				foreach($k as $key => $value){
 					$key = ($this->OPTIONS['CASELESS']) ? strtolower(trim($key)) : trim($key);
-					if (preg_match('/^[A-Za-z]+[A-Za-z0-9_]*$/', $key) && $value !== null ) {
+					if (preg_match('/^[A-Za-z_]+[A-Za-z0-9_]*$/', $key) && $value !== null ) {
 						$this->_vars[$key] = $value;
 					}
 				}
 			} else {
-				if (preg_match('/^[A-Za-z]+[A-Za-z0-9_]*$/', $k) && $v !== null) {
+				if (preg_match('/^[A-Za-z_]+[A-Za-z0-9_]*$/', $k) && $v !== null) {
 					if ($this->OPTIONS['CASELESS']) $k = strtolower($k);
 					$this->_vars[trim($k)] = $v;
 				} else {
@@ -287,7 +287,7 @@
 			for ($i = 0; $i < $num_args; $i++) {
 				$var = func_get_arg($i);
 				if ($this->OPTIONS['CASELESS']) $var = strtolower($var);
-				if (!preg_match('/^[A-Za-z]+[A-Za-z0-9_]*$/', $var)) continue;
+				if (!preg_match('/^[A-Za-z_]+[A-Za-z0-9_]*$/', $var)) continue;
 				unset($this->_vars[$var]);
 			}
 			return true;
@@ -344,7 +344,7 @@
 		 */
 		public function setLoop($k, $v)
 		{
-			if (is_array($v) && preg_match('/^[A-Za-z]+[A-Za-z0-9_]*$/', $k)) {
+			if (is_array($v) && preg_match('/^[A-Za-z_]+[A-Za-z0-9_]*$/', $k)) {
 				$k = ($this->OPTIONS['CASELESS']) ? strtolower(trim($k)) : trim($k);
 				$this->_arrvars[$k] = array();
 				if ($this->OPTIONS['SET_LOOP_VAR'] && !empty($v)) $this->setvar($k, 1);
@@ -839,32 +839,36 @@
 		 * @access private
 		 * @return mixed data/string or boolean
 		 */
-		private function _getData ($tmplfile, $do_eval=false)
+		private function _getData ($tmplfile, $do_eval=false, $tmpl_from_string = false)
 		{
 			//* check the current file depth
 			if ($this->_includedepth > $this->OPTIONS['MAX_INCLUDES'] || $tmplfile == false) {
 				return;
 			} else {
 				if ($this->_debug){
-					array_push($this->_debugIncludedfiles, $tmplfile);
+					if($tmpl_from_string) array_push($this->_debugIncludedfiles, 'String: ' . substr($tmplfile, 0, 25) . '...');
+					else array_push($this->_debugIncludedfiles, $tmplfile);
 				}
 				if ($do_eval) {
-					array_push($this->_currentincludedir, dirname($tmplfile));
+					if($tmpl_from_string == true) array_push($this->_currentincludedir, end($this->_currentincludedir));
+					else array_push($this->_currentincludedir, dirname($tmplfile));
 					$this->_includedepth++;
 				}
 			}
 
 
-			if($this->_cache && $this->_checkCache($tmplfile)) { //* cache exists so lets use it
-				$data = fread($fp = fopen($this->_cachefile, 'r'), filesize($this->_cachefile));
-				fclose($fp);
+			if($this->_cache && $this->_checkCache($tmplfile, $tmpl_from_string)) { //* cache exists so lets use it
+				$data = file_get_contents($this->_cachefile);
 			} else { //* no cache lets parse the file
-				$data = fread($fp = fopen($tmplfile, 'r'), filesize($tmplfile));
-				fclose($fp);
+				if($tmpl_from_string == true) {
+					$data = $tmplfile;
+				} else {
+					$data = file_get_contents($tmplfile);
+				}
 
 				$regex = '/(<|<\/|{|{\/|<!--|<!--\/){1}\s*';
 				$regex.= 'tmpl_([\w]+)\s*';
-				$regex.= '(?:';
+				$regex.= '((?:(?:';
 				$regex.=    '(?:';
 				$regex.=        '(name|format|escape|op|value|file)';
 				$regex.=        '\s*=\s*';
@@ -873,30 +877,10 @@
 				$regex.=    '((?<=[\"\'])';
 				$regex.=    '[^\"\']*|[a-z0-9_\.]*)';
 				$regex.=    '[\"\']?';
-				$regex.= ')?\s*';
-				$regex.= '(?:';
-				$regex.=    '(?:';
-				$regex.=        '(name|format|escape|op|value)';
-				$regex.=        '\s*=\s*';
-				$regex.=    ')';
-				$regex.=    '(?:[\"\'])?';
-				$regex.=    '((?<=[\"\'])';
-				$regex.=    '[^\"\']*|[a-z0-9_\.]*)';
-				$regex.=    '[\"\']?';
-				$regex.= ')?\s*';
-				$regex.= '(?:';
-				$regex.=    '(?:';
-				$regex.=        '(name|format|escape|op|value)';
-				$regex.=        '\s*=\s*';
-				$regex.=    ')';
-				$regex.=    '(?:[\"\'])?';
-				$regex.=    '((?<=[\"\'])';
-				$regex.=    '[^\"\']*|[a-z0-9_\.]*)';
-				$regex.=    '[\"\']?';
-				$regex.= ')?\s*';
+				$regex.= ')?\s*)*?)';
 				$regex.= '(?:>|\/>|}|-->){1}';
-				$regex.= '([\r\n|\n|\r])?/i';
-				$data = preg_replace_callback($regex, array($this, _parseTag), $data);
+				$regex.= '/i';
+				$data = preg_replace_callback($regex, array($this, '_parseTag'), $data);
 
 				if ($this->_cache) { // add cache if need be
 					$this->_createCache($data);
@@ -904,7 +888,7 @@
 			}
 
 			//* now we must parse the $data and check for any <tmpl_include>'s
-			if ($this->_debug) $this->doDebugWarnings(file($tmplfile), $tmplfile);
+			if ($this->_debug && $tmpl_from_string == false) $this->doDebugWarnings(file($tmplfile), $tmplfile);
 
 			if ($do_eval) {
 				$success = @eval('?>'.$data.'<?php return 1;');
@@ -1026,7 +1010,7 @@
 		 * @access private
 		 * @return string used for eval'ing
 		 */
-		private function _parseIf($varname, $value = null, $op = null, $namespace = null)
+		private function _parseIf($varname, $value = null, $op = null, $namespace = null, $format = null)
 		{
 			if (isset($namespace)) $namespace = substr($namespace, 0, -1);
 			$comp_str = ''; // used for extended if statements
@@ -1065,12 +1049,62 @@
 				}
 			}
 			if ($this->OPTIONS['GLOBAL_VARS'] && empty($namespace)) {
-				return '(('.$retstr.'[\''.$varname.'\'] !== null) ? '.$retstr.'[\''.$varname.'\'] : $this->_vars[\''.$varname.'\'])'.$comp_str;
-			} else {
-				return $retstr."['".$varname."']".$comp_str;
+				$retstr = '(('.$retstr.'[\''.$varname.'\'] !== null) ? '.$retstr.'[\''.$varname.'\'] : $this->_vars[\''.$varname.'\'])';
+				if(isset($format) && isset($value) && $format == 'version') {
+					return 'version_compare(' . $retstr . ', \'' . $value . '\', \'' . (!empty($op) ? $op : '==') . '\')';
+				} else {
+					return $retstr.$comp_str;
+				}
+			}
+			else {
+				if(isset($format) && isset($value) && $format == 'version') {
+					return 'version_compare(' . $retstr."['".$varname."']" . ', \'' . $value . '\', \'' . (!empty($op) ? $op : '==') . '\')';
+				} else {
+					return $retstr."['".$varname."']".$comp_str;
+				}
 			}
 		}
 
+		/**
+		 * returns a string containing hook data
+		 * @param string $type
+		 * @param string $name
+		 * @return string hook data
+		 */
+		private function _parseHook ($name)
+		{
+			global $app;
+			
+			if(!$name) return false;
+			
+			$module = isset($_SESSION['s']['module']['name']) ? $_SESSION['s']['module']['name'] : '';
+			$form = isset($app->tform->formDef['name']) ? $app->tform->formDef['name'] : '';
+			
+			$events = array();
+			if($module) {
+				$events[] = $module . ':' . ($form ? $form : '') . ':' . $name;
+				$events[] = $module . ':' . ($form ? $form : '') . ':on_template_content';
+			} else {
+				$events[] = $name;
+				$events[] = 'on_template_content';
+			}
+			
+			$events = array_unique($events);
+			
+			for($e = 0; $e < count($events); $e++) {
+				$tmpresult = $app->plugin->raiseEvent($events[$e], array(
+					'name' => $name,
+					'module' => $module,
+					'form' => $form
+				), true);
+				if(!$tmpresult) $tmpresult = '';
+				else $tmpresult = $this->_getData($tmpresult, false, true);
+				
+				$result .= $tmpresult;
+			}
+			
+			return $result;
+		}
 
 		/**
 		 * returns a string used for parsing in tmpl_loop statements.
@@ -1186,26 +1220,36 @@
 			$wholetag = $args[0];
 			$openclose = $args[1];
 			$tag = strtolower($args[2]);
-			$newline = $args[9];
-
-			if ($tag == 'else') return '<?php } else { ?>'.$newline;
+			
+			if ($tag == 'else') return '<?php } else { ?>';
 			if ($tag == 'tmpl_include') return $wholetag; // ignore tmpl_include tags
 
 			if (preg_match("/^<\/|{\/|<!--\/$/s", $openclose) || preg_match("/^end[if|loop|unless|comment]$/", $tag)) {
 				if ($tag == 'loop' || $tag == 'endloop') array_pop($this->_namespace);
 				if ($tag == 'comment' || $tag == 'endcomment') {
-					return '<?php */ ?>'.$newline;
+					return '<?php */ ?>';
 				} else {
-					return '<?php } ?>'.$newline;
+					return '<?php } ?>';
 				}
 			}
 
-			//* arrange attributes
-			for ($i=3; $i < 8; $i=($i+2)) {
-				if (empty($args[$i]) && empty($args[($i+1)])) break;
-				$key = (empty($args[$i])) ? 'name' : strtolower($args[$i]);
-				if ($key == 'name' && preg_match('/^(php)?include$/', $tag)) $key = 'file';
-				$$key = $args[($i+1)];
+			// arrange attributes
+			$tmp_atts = $args[3];
+			$atts = preg_split('/\s+/', $tmp_atts);
+			foreach($atts as $att) {
+				$regex =    '/(?:';
+				$regex.=        '(name|format|escape|op|value|file)';
+				$regex.=        '\s*=\s*';
+				$regex.=    ')?';
+				$regex.=    '(?:[\"\'])?';
+				$regex.=    '((?<=[\"\'])';
+				$regex.=    '[^\"\']*|[a-z0-9_\.]*)';
+				$regex.=    '[\"\']?/';
+				if(preg_match($regex, $att, $match)) {
+					$key = (empty($match[1])) ? 'name' : strtolower($match[1]);
+					if ($key == 'name' && preg_match('/^(php)?include$/', $tag)) $key = 'file';
+					$$key = $match[2];
+				}
 			}
 
 			$var = ($this->OPTIONS['CASELESS']) ? strtolower($name) : $name;
@@ -1229,32 +1273,35 @@
 				if (empty($escape) && (!empty($this->OPTIONS['DEFAULT_ESCAPE']) && strtolower($this->OPTIONS['DEFAULT_ESCAPE']) != 'none')) {
 					$escape = strtolower($this->OPTIONS['DEFAULT_ESCAPE']);
 				}
-				return '<?php '.$this->_parseVar ($wholetag, $tag, $var, @$escape, @$format, @$namespace)." ?>$newline";
+				return '<?php '.$this->_parseVar ($wholetag, $tag, $var, @$escape, @$format, @$namespace)." ?>\n";
 
 			case 'if':
-				return '<?php if ('. $this->_parseIf($var, @$value, @$op, @$namespace) .') { ?>'.$newline;
+				return '<?php if ('. $this->_parseIf($var, @$value, @$op, @$namespace, @$format) .') { ?>';
 
 			case 'unless':
-				return '<?php if (!'. $this->_parseIf($var, @$value, @$op, @$namespace) .') { ?>'.$newline;
+				return '<?php if (!'. $this->_parseIf($var, @$value, @$op, @$namespace, @$format) .') { ?>';
 
 			case 'elseif':
-				return '<?php } elseif ('. $this->_parseIf($var, @$value, @$op, @$namespace) .') { ?>'.$newline;
+				return '<?php } elseif ('. $this->_parseIf($var, @$value, @$op, @$namespace, @$format) .') { ?>';
 
 			case 'loop':
-				return '<?php '. $this->_parseLoop($var) .'?>'.$newline;
+				return '<?php '. $this->_parseLoop($var) .'?>';
 
 			case 'comment':
 				if (empty($var)) { // full open/close style comment
-					return '<?php /* ?>'.$newline;
+					return '<?php /* ?>';
 				} else { // just ignore tag if it was a one line comment
 					return;
 				}
 
 			case 'phpinclude':
 				if ($this->OPTIONS['ENABLE_PHPINCLUDE']) {
-					return '<?php include(\''.$file.'\'); ?>'.$newline;
+					return '<?php include(\''.$file.'\'); ?>';
 				}
-
+			
+			case 'hook':
+				return $this->_parseHook(@$var);
+			
 			case 'include':
 				return '<?php $this->_getData($this->_fileSearch(\''.$file.'\'), 1); ?>';
 

--
Gitblit v1.9.1