cvs: smarty / NEWS /libs Smarty_Compiler.class.php

"Messju Mohr" <[email protected]>
Newsgroups gmane.comp.php.cvs.smarty
Message-ID <cvsmessju1070880261@cvsserver>
messju		Mon Dec  8 05:44:21 2003 EDT

  Modified files:              
    /smarty	NEWS 
    /smarty/libs	Smarty_Compiler.class.php 
  Log:
  add better checks for correctly nested tags when compiling
  
  
  
Index: smarty/NEWS
diff -u smarty/NEWS:1.410 smarty/NEWS:1.411
--- smarty/NEWS:1.410	Wed Dec  3 04:29:12 2003
+++ smarty/NEWS	Mon Dec  8 05:44:21 2003
@@ -1,3 +1,4 @@
+  - add better checks for correctly nested tags when compiling (messju)
   - remove {$SCRIPT_NAME}. use {$smarty.server.SCRIPT_NAME} instead (messju)
   - remove $global_assign. assign global variables explicitly instead (messju)
   - remove warning in debug_print_var on php-resources (messju)
Index: smarty/libs/Smarty_Compiler.class.php
diff -u smarty/libs/Smarty_Compiler.class.php:1.300 smarty/libs/Smarty_Compiler.class.php:1.301
--- smarty/libs/Smarty_Compiler.class.php:1.300	Wed Nov 26 09:02:05 2003
+++ smarty/libs/Smarty_Compiler.class.php	Mon Dec  8 05:44:21 2003
@@ -39,7 +39,7 @@
  * @package Smarty
  */
 
-/* $Id: Smarty_Compiler.class.php,v 1.300 2003/11/26 14:02:05 messju Exp $ */
+/* $Id: Smarty_Compiler.class.php,v 1.301 2003/12/08 10:44:21 messju Exp $ */
 
 /**
  * Template compiling class
@@ -51,8 +51,6 @@
     /**#@+
      * @access private
      */
-    var $_sectionelse_stack     =   array();    // keeps track of whether section had 'else' part
-    var $_foreachelse_stack     =   array();    // keeps track of whether foreach had 'else' part
     var $_literal_blocks        =   array();    // keeps literal template blocks
     var $_php_blocks            =   array();    // keeps php code blocks
     var $_current_file          =   null;       // the current template being compiled
@@ -316,6 +314,11 @@
             $compiled_tags[] = $this->_compile_tag($template_tags[$i]);
             $this->_current_line_no += substr_count($template_tags[$i], "\n");
         }
+        if (count($this->_tag_stack)>0) {
+            list($_open_tag, $_line_no) = end($this->_tag_stack);
+            $this->_syntax_error("unclosed tag \{$_open_tag} (opened line $_line_no).", E_USER_ERROR, __FILE__, __LINE__);
+            return;
+        }
 
         $compiled_content = '';
 
@@ -393,7 +396,6 @@
         }
 
         $compiled_content = $template_header . $compiled_content;
-
         return true;
     }
 
@@ -444,15 +446,27 @@
                 return $this->_compile_include_php_tag($tag_args);
 
             case 'if':
+                $this->_push_tag('if');
                 return $this->_compile_if_tag($tag_args);
 
             case 'else':
+                list($_open_tag) = end($this->_tag_stack);
+                if ($_open_tag != 'if' && $_open_tag != 'elseif')
+                    $this->_syntax_error('unxepected {else}', E_USER_ERROR, __FILE__, __LINE__);
+                else
+                    $this->_push_tag('else');
                 return '<?php else: ?>';
 
             case 'elseif':
+                list($_open_tag) = end($this->_tag_stack);
+                if ($_open_tag != 'if' && $_open_tag != 'elseif')
+                    $this->_syntax_error('unxepected {elseif}', E_USER_ERROR, __FILE__, __LINE__);
+                if ($_open_tag == 'if')
+                    $this->_push_tag('elseif');
                 return $this->_compile_if_tag($tag_args, true);
 
             case '/if':
+                $this->_pop_tag('if');
                 return '<?php endif; ?>';
 
             case 'capture':
@@ -468,42 +482,48 @@
                 return $this->right_delimiter;
 
             case 'section':
-                array_push($this->_sectionelse_stack, false);
+                $this->_push_tag('section');
                 return $this->_compile_section_start($tag_args);
 
             case 'sectionelse':
-                $this->_sectionelse_stack[count($this->_sectionelse_stack)-1] = true;
+                $this->_push_tag('sectionelse');
                 return "<?php endfor; else: ?>";
+                break;
 
             case '/section':
-                if (array_pop($this->_sectionelse_stack))
+                $_open_tag = $this->_pop_tag('section');
+                if ($_open_tag == 'sectionelse')
                     return "<?php endif; ?>";
                 else
                     return "<?php endfor; endif; ?>";
 
             case 'foreach':
-                array_push($this->_foreachelse_stack, false);
+                $this->_push_tag('foreach');
                 return $this->_compile_foreach_start($tag_args);
                 break;
 
             case 'foreachelse':
-                $this->_foreachelse_stack[count($this->_foreachelse_stack)-1] = true;
+                $this->_push_tag('foreachelse');
                 return "<?php endforeach; unset(\$_from); else: ?>";
 
             case '/foreach':
-                if (array_pop($this->_foreachelse_stack))
+                $_open_tag = $this->_pop_tag('foreach');
+                if ($_open_tag == 'foreachelse')
                     return "<?php endif; ?>";
                 else
                     return "<?php endforeach; unset(\$_from); endif; ?>";
+                break;
 
             case 'strip':
             case '/strip':
                 if ($tag_command{0}=='/') {
+                    $this->_pop_tag('strip');
                     if (--$this->_strip_depth==0) { /* outermost closing {/strip} */
                         $this->_additional_newline = "\n";
                         return $this->left_delimiter.$tag_command.$this->right_delimiter;
                     }
                 } else {
+                    $this->_push_tag('strip');
                     if ($this->_strip_depth++==0) { /* outermost opening {strip} */
                         $this->_additional_newline = "";
                         return $this->left_delimiter.$tag_command.$this->right_delimiter;
@@ -674,6 +694,11 @@
          */
         $this->_add_plugin('block', $tag_command);
 
+        if ($start_tag)
+            $this->_push_tag($tag_command);
+        else
+            $this->_pop_tag($tag_command);
+
         if ($start_tag) {
             $output = '<?php ' . $this->_push_cacheable_state('block', $tag_command);
             $attrs = $this->_parse_attrs($tag_args);
@@ -2098,6 +2123,47 @@
             . '}\';}';
     }
 
+
+    /**
+     * push opening tag-name, file-name and line-number on the tag-stack
+     * @param: string the opening tag's name
+     */
+    function _push_tag($open_tag)
+    {
+        array_push($this->_tag_stack, array($open_tag, $this->_current_line_no));
+    }
+
+    /**
+     * pop closing tag-name
+     * raise an error if this stack-top doesn't match with the closing tag
+     * @param: string the closing tag's name
+     * @return: string the opening tag's name
+     */
+    function _pop_tag($close_tag)
+    {
+        $message = '';
+        if (count($this->_tag_stack)>0) {
+            list($_open_tag, $_line_no) = array_pop($this->_tag_stack);
+            if ($close_tag == $_open_tag) {
+                return $_open_tag;
+            }
+            if ($close_tag == 'if' && ($_open_tag == 'else' || $_open_tag == 'elseif' )) {
+                return $this->_pop_tag($close_tag);
+            }
+            if ($close_tag == 'section' && $_open_tag == 'sectionelse') {
+                $this->_pop_tag($close_tag);
+                return $_open_tag;
+            }
+            if ($close_tag == 'foreach' && $_open_tag == 'foreachelse') {
+                $this->_pop_tag($close_tag);
+                return $_open_tag;
+            }
+            $message = " expected {/$_open_tag} (opened line $_line_no).";
+        }
+        $this->_syntax_error("mismatched tag {/$close_tag}.$message",
+                             E_USER_ERROR, __FILE__, __LINE__);
+    }
+
 }
 
 /**

-- 
Smarty CVS Mailing List (http://cvs.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.