You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

smarty_internal_compile_private_php.php 9.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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. * Smarty Internal Plugin Compile PHP Expression Class
  12. *
  13. * @package Smarty
  14. * @subpackage Compiler
  15. */
  16. class Smarty_Internal_Compile_Private_Php extends Smarty_Internal_CompileBase
  17. {
  18. /**
  19. * Attribute definition: Overwrites base class.
  20. *
  21. * @var array
  22. * @see Smarty_Internal_CompileBase
  23. */
  24. public $required_attributes = array('code', 'type');
  25. /**
  26. * Compiles code for generating output from any expression
  27. *
  28. * @param array $args array with attributes from parser
  29. * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
  30. * @param array $parameter array with compilation parameter
  31. *
  32. * @return string
  33. * @throws \SmartyException
  34. */
  35. public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
  36. {
  37. // check and get attributes
  38. $_attr = $this->getAttributes($compiler, $args);
  39. $compiler->has_code = false;
  40. if ($_attr['type'] == 'xml') {
  41. $compiler->tag_nocache = true;
  42. $save = $compiler->template->compiled->has_nocache_code;
  43. $output = addcslashes($_attr['code'], "'\\");
  44. $compiler->parser->current_buffer->append_subtree($compiler->parser, new Smarty_Internal_ParseTree_Tag($compiler->parser, $compiler->processNocacheCode("<?php echo '" .
  45. $output .
  46. "';?>", $compiler, true)));
  47. $compiler->template->compiled->has_nocache_code = $save;
  48. return '';
  49. }
  50. if ($_attr['type'] != 'tag') {
  51. if ($compiler->php_handling == Smarty::PHP_REMOVE) {
  52. return '';
  53. } elseif ($compiler->php_handling == Smarty::PHP_QUOTE) {
  54. $output = preg_replace_callback('#(<\?(?:php|=)?)|(<%)|(<script\s+language\s*=\s*["\']?\s*php\s*["\']?\s*>)|(\?>)|(%>)|(<\/script>)#i', array($this,
  55. 'quote'), $_attr['code']);
  56. $compiler->parser->current_buffer->append_subtree($compiler->parser, new Smarty_Internal_ParseTree_Text($output));
  57. return '';
  58. } elseif ($compiler->php_handling == Smarty::PHP_PASSTHRU || $_attr['type'] == 'unmatched') {
  59. $compiler->tag_nocache = true;
  60. $save = $compiler->template->compiled->has_nocache_code;
  61. $output = addcslashes($_attr['code'], "'\\");
  62. $compiler->parser->current_buffer->append_subtree($compiler->parser, new Smarty_Internal_ParseTree_Tag($compiler->parser, $compiler->processNocacheCode("<?php echo '" .
  63. $output .
  64. "';?>", $compiler, true)));
  65. $compiler->template->compiled->has_nocache_code = $save;
  66. return '';
  67. } elseif ($compiler->php_handling == Smarty::PHP_ALLOW) {
  68. if (!($compiler->smarty instanceof SmartyBC)) {
  69. $compiler->trigger_template_error('$smarty->php_handling PHP_ALLOW not allowed. Use SmartyBC to enable it', null, true);
  70. }
  71. $compiler->has_code = true;
  72. return $_attr['code'];
  73. } else {
  74. $compiler->trigger_template_error('Illegal $smarty->php_handling value', null, true);
  75. }
  76. } else {
  77. $compiler->has_code = true;
  78. if (!($compiler->smarty instanceof SmartyBC)) {
  79. $compiler->trigger_template_error('{php}{/php} tags not allowed. Use SmartyBC to enable them', null, true);
  80. }
  81. $ldel = preg_quote($compiler->smarty->left_delimiter, '#');
  82. $rdel = preg_quote($compiler->smarty->right_delimiter, '#');
  83. preg_match("#^({$ldel}php\\s*)((.)*?)({$rdel})#", $_attr['code'], $match);
  84. if (!empty($match[2])) {
  85. if ('nocache' == trim($match[2])) {
  86. $compiler->tag_nocache = true;
  87. } else {
  88. $compiler->trigger_template_error("illegal value of option flag \"{$match[2]}\"", null, true);
  89. }
  90. }
  91. return preg_replace(array("#^{$ldel}\\s*php\\s*(.)*?{$rdel}#",
  92. "#{$ldel}\\s*/\\s*php\\s*{$rdel}$#"), array('<?php ', '?>'), $_attr['code']);
  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') &&
  144. ($lex->compiler->php_handling == Smarty::PHP_PASSTHRU || $lex->compiler->php_handling == Smarty::PHP_QUOTE)
  145. ) {
  146. return;
  147. }
  148. $start = $lex->counter + strlen($lex->value);
  149. $body = true;
  150. if (preg_match('~' . preg_quote($closeTag, '~') . '~i', $lex->data, $match, PREG_OFFSET_CAPTURE, $start)) {
  151. $close = $match[0][1];
  152. } else {
  153. $lex->compiler->trigger_template_error("missing closing tag '{$closeTag}'");
  154. }
  155. while ($body) {
  156. if (preg_match('~([/][*])|([/][/][^\n]*)|(\'[^\'\\\\]*(?:\\.[^\'\\\\]*)*\')|("[^"\\\\]*(?:\\.[^"\\\\]*)*")~', $lex->data, $match, PREG_OFFSET_CAPTURE, $start)) {
  157. $value = $match[0][0];
  158. $from = $pos = $match[0][1];
  159. if ($pos > $close) {
  160. $body = false;
  161. } else {
  162. $start = $pos + strlen($value);
  163. $phpCommentStart = $value == '/*';
  164. if ($phpCommentStart) {
  165. $phpCommentEnd = preg_match('~([*][/])~', $lex->data, $match, PREG_OFFSET_CAPTURE, $start);
  166. if ($phpCommentEnd) {
  167. $pos2 = $match[0][1];
  168. $start = $pos2 + strlen($match[0][0]);
  169. }
  170. }
  171. while ($close > $pos && $close < $start) {
  172. if (preg_match('~' . preg_quote($closeTag, '~') .
  173. '~i', $lex->data, $match, PREG_OFFSET_CAPTURE, $from)) {
  174. $close = $match[0][1];
  175. $from = $close + strlen($match[0][0]);
  176. } else {
  177. $lex->compiler->trigger_template_error("missing closing tag '{$closeTag}'");
  178. }
  179. }
  180. if ($phpCommentStart && (!$phpCommentEnd || $pos2 > $close)) {
  181. $lex->taglineno = $lex->line + substr_count(substr($lex->data, $lex->counter, $start), "\n");
  182. $lex->compiler->trigger_template_error("missing PHP comment closing tag '*/'");
  183. }
  184. }
  185. } else {
  186. $body = false;
  187. }
  188. }
  189. $lex->value = substr($lex->data, $lex->counter, $close + strlen($closeTag) - $lex->counter);
  190. }
  191. /*
  192. * Call back function for $php_handling = PHP_QUOTE
  193. *
  194. */
  195. /**
  196. * @param $match
  197. *
  198. * @return string
  199. */
  200. private function quote($match)
  201. {
  202. return htmlspecialchars($match[0], ENT_QUOTES);
  203. }
  204. }