Marius Burkard
2016-04-20 67d99a763eb9f44d3ef4fd334d1293ae8ccd847e
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); ?>';