smarty_internal_compile_private_php.php (8885B)
1 <?php 2 /** 3 * Smarty Internal Plugin Compile PHP Expression 4 * Compiles any tag which will output an expression or variable 5 * 6 * @package Smarty 7 * @subpackage Compiler 8 * @author Uwe Tews 9 */ 10 11 /** 12 * Smarty Internal Plugin Compile PHP Expression Class 13 * 14 * @package Smarty 15 * @subpackage Compiler 16 */ 17 class Smarty_Internal_Compile_Private_Php extends Smarty_Internal_CompileBase 18 { 19 20 /** 21 * Attribute definition: Overwrites base class. 22 * 23 * @var array 24 * @see Smarty_Internal_CompileBase 25 */ 26 public $required_attributes = array('code', 'type'); 27 28 /** 29 * Compiles code for generating output from any expression 30 * 31 * @param array $args array with attributes from parser 32 * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object 33 * @param array $parameter array with compilation parameter 34 * 35 * @return string 36 * @throws \SmartyException 37 */ 38 public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter) 39 { 40 // check and get attributes 41 $_attr = $this->getAttributes($compiler, $args); 42 $compiler->has_code = false; 43 if ($_attr['type'] == 'xml') { 44 $compiler->tag_nocache = true; 45 $save = $compiler->template->has_nocache_code; 46 $output = addcslashes($_attr['code'], "'\\"); 47 $compiler->parser->current_buffer->append_subtree(new Smarty_Internal_ParseTree_Tag($compiler->parser, $compiler->processNocacheCode("<?php echo '" . $output . "';?>", $compiler, true))); 48 $compiler->template->has_nocache_code = $save; 49 return ''; 50 } 51 if ($_attr['type'] != 'tag') { 52 if ($compiler->php_handling == Smarty::PHP_REMOVE) { 53 return ''; 54 } elseif ($compiler->php_handling == Smarty::PHP_QUOTE) { 55 $output = preg_replace_callback('#(<\?(?:php|=)?)|(<%)|(<script\s+language\s*=\s*["\']?\s*php\s*["\']?\s*>)|(\?>)|(%>)|(<\/script>)#i', array($this, 56 'quote'), $_attr['code']); 57 $compiler->parser->current_buffer->append_subtree(new Smarty_Internal_ParseTree_Text($compiler->parser, $output)); 58 return ''; 59 } elseif ($compiler->php_handling == Smarty::PHP_PASSTHRU || $_attr['type'] == 'unmatched') { 60 $compiler->tag_nocache = true; 61 $save = $compiler->template->has_nocache_code; 62 $output = addcslashes($_attr['code'], "'\\"); 63 $compiler->parser->current_buffer->append_subtree(new Smarty_Internal_ParseTree_Tag($compiler->parser, $compiler->processNocacheCode("<?php echo '" . $output . "';?>", $compiler, true))); 64 $compiler->template->has_nocache_code = $save; 65 return ''; 66 } elseif ($compiler->php_handling == Smarty::PHP_ALLOW) { 67 if (!($compiler->smarty instanceof SmartyBC)) { 68 $compiler->trigger_template_error('$smarty->php_handling PHP_ALLOW not allowed. Use SmartyBC to enable it', $compiler->lex->taglineno); 69 } 70 $compiler->has_code = true; 71 return $_attr['code']; 72 } else { 73 $compiler->trigger_template_error('Illegal $smarty->php_handling value', $compiler->lex->taglineno); 74 } 75 } else { 76 $compiler->has_code = true; 77 if (!($compiler->smarty instanceof SmartyBC)) { 78 $compiler->trigger_template_error('{php}[/php} tags not allowed. Use SmartyBC to enable them', $compiler->lex->taglineno); 79 } 80 $ldel = preg_quote($compiler->smarty->left_delimiter, '#'); 81 $rdel = preg_quote($compiler->smarty->right_delimiter, '#'); 82 preg_match("#^({$ldel}php\\s*)((.)*?)({$rdel})#", $_attr['code'], $match); 83 if (!empty($match[2])) { 84 if ('nocache' == trim($match[2])) { 85 $compiler->tag_nocache = true; 86 } else { 87 $compiler->trigger_template_error("illegal value of option flag \"{$match[2]}\"", $compiler->lex->taglineno); 88 } 89 } 90 return preg_replace(array("#^{$ldel}\\s*php\\s*(.)*?{$rdel}#", 91 "#{$ldel}\\s*/\\s*php\\s*{$rdel}$#"), array('<?php ', '?>'), $_attr['code']); 92 } 93 } 94 95 /** 96 * Lexer code for PHP tags 97 * 98 * This code has been moved from lexer here fo easier debugging and maintenance 99 * 100 * @param $lex 101 */ 102 public function parsePhp($lex) 103 { 104 $lex->token = Smarty_Internal_Templateparser::TP_PHP; 105 $close = 0; 106 $lex->taglineno = $lex->line; 107 $closeTag = '?>'; 108 if (strpos($lex->value, '<?xml') === 0) { 109 $lex->is_xml = true; 110 $lex->token = Smarty_Internal_Templateparser::TP_NOCACHE; 111 return; 112 } elseif (strpos($lex->value, '<?') === 0) { 113 $lex->phpType = 'php'; 114 } elseif (strpos($lex->value, '<%') === 0) { 115 $lex->phpType = 'asp'; 116 $closeTag = '%>'; 117 } elseif (strpos($lex->value, '%>') === 0) { 118 $lex->phpType = 'unmatched'; 119 } elseif (strpos($lex->value, '?>') === 0) { 120 if ($lex->is_xml) { 121 $lex->is_xml = false; 122 $lex->token = Smarty_Internal_Templateparser::TP_NOCACHE; 123 return; 124 } 125 $lex->phpType = 'unmatched'; 126 } elseif (strpos($lex->value, '<s') === 0) { 127 $lex->phpType = 'script'; 128 $closeTag = '</script>'; 129 } elseif (strpos($lex->value, $lex->smarty->left_delimiter) === 0) { 130 if ($lex->isAutoLiteral()) { 131 $lex->token = Smarty_Internal_Templateparser::TP_TEXT; 132 return; 133 } 134 $closeTag = "{$lex->smarty->left_delimiter}/php{$lex->smarty->right_delimiter}"; 135 if ($lex->value == $closeTag) { 136 $lex->compiler->trigger_template_error("unexpected closing tag '{$closeTag}'"); 137 } 138 $lex->phpType = 'tag'; 139 } 140 if ($lex->phpType == 'unmatched') { 141 return; 142 } 143 if (($lex->phpType == 'php' || $lex->phpType == 'asp') && ($lex->compiler->php_handling == Smarty::PHP_PASSTHRU || $lex->compiler->php_handling == Smarty::PHP_QUOTE)) { 144 return; 145 } 146 $start = $lex->counter + strlen($lex->value); 147 $body = true; 148 if (preg_match('~' . preg_quote($closeTag, '~') . '~i', $lex->data, $match, PREG_OFFSET_CAPTURE, $start)) { 149 $close = $match[0][1]; 150 } else { 151 $lex->compiler->trigger_template_error("missing closing tag '{$closeTag}'"); 152 } 153 while ($body) { 154 if (preg_match('~([/][*])|([/][/][^\n]*)|(\'[^\'\\\\]*(?:\\.[^\'\\\\]*)*\')|("[^"\\\\]*(?:\\.[^"\\\\]*)*")~', $lex->data, $match, PREG_OFFSET_CAPTURE, $start)) { 155 $value = $match[0][0]; 156 $from = $pos = $match[0][1]; 157 if ($pos > $close) { 158 $body = false; 159 } else { 160 $start = $pos + strlen($value); 161 $phpCommentStart = $value == '/*'; 162 if ($phpCommentStart) { 163 $phpCommentEnd = preg_match('~([*][/])~', $lex->data, $match, PREG_OFFSET_CAPTURE, $start); 164 if ($phpCommentEnd) { 165 $pos2 = $match[0][1]; 166 $start = $pos2 + strlen($match[0][0]); 167 } 168 } 169 while ($close > $pos && $close < $start) { 170 if (preg_match('~' . preg_quote($closeTag, '~') . '~i', $lex->data, $match, PREG_OFFSET_CAPTURE, $from)) { 171 $close = $match[0][1]; 172 $from = $close + strlen($match[0][0]); 173 } else { 174 $lex->compiler->trigger_template_error("missing closing tag '{$closeTag}'"); 175 } 176 } 177 if ($phpCommentStart && (!$phpCommentEnd || $pos2 > $close)) { 178 $lex->taglineno = $lex->line + substr_count(substr($lex->data, $lex->counter, $start), "\n"); 179 $lex->compiler->trigger_template_error("missing PHP comment closing tag '*/'"); 180 } 181 } 182 } else { 183 $body = false; 184 } 185 } 186 $lex->value = substr($lex->data, $lex->counter, $close + strlen($closeTag) - $lex->counter); 187 } 188 189 /* 190 * Call back function for $php_handling = PHP_QUOTE 191 * 192 */ 193 private function quote($match) 194 { 195 return htmlspecialchars($match[0], ENT_QUOTES); 196 } 197 }