1: | <?php
|
2: | |
3: | |
4: | |
5: | |
6: | |
7: | |
8: | |
9: |
|
10: |
|
11: | |
12: | |
13: | |
14: | |
15: | |
16: |
|
17: | class Smarty_Internal_Compile_Private_Php extends Smarty_Internal_CompileBase
|
18: | {
|
19: | |
20: | |
21: | |
22: | |
23: | |
24: |
|
25: | public $required_attributes = array('code', 'type');
|
26: |
|
27: | |
28: | |
29: | |
30: | |
31: | |
32: | |
33: | |
34: | |
35: | |
36: |
|
37: | public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
|
38: | {
|
39: |
|
40: | $_attr = $this->getAttributes($compiler, $args);
|
41: | $compiler->has_code = false;
|
42: | if ($_attr[ 'type' ] === 'xml') {
|
43: | $compiler->tag_nocache = true;
|
44: | $output = addcslashes($_attr[ 'code' ], "'\\");
|
45: | $compiler->parser->current_buffer->append_subtree(
|
46: | $compiler->parser,
|
47: | new Smarty_Internal_ParseTree_Tag(
|
48: | $compiler->parser,
|
49: | $compiler->processNocacheCode(
|
50: | "<?php echo '{$output}';?>\n",
|
51: | true
|
52: | )
|
53: | )
|
54: | );
|
55: | return '';
|
56: | }
|
57: | if ($_attr[ 'type' ] !== 'tag') {
|
58: | if ($compiler->php_handling === Smarty::PHP_REMOVE) {
|
59: | return '';
|
60: | } elseif ($compiler->php_handling === Smarty::PHP_QUOTE) {
|
61: | $output =
|
62: | preg_replace_callback(
|
63: | '#(<\?(?:php|=)?)|(<%)|(<script\s+language\s*=\s*["\']?\s*php\s*["\']?\s*>)|(\?>)|(%>)|(<\/script>)#i',
|
64: | array($this, 'quote'),
|
65: | $_attr[ 'code' ]
|
66: | );
|
67: | $compiler->parser->current_buffer->append_subtree(
|
68: | $compiler->parser,
|
69: | new Smarty_Internal_ParseTree_Text($output)
|
70: | );
|
71: | return '';
|
72: | } elseif ($compiler->php_handling === Smarty::PHP_PASSTHRU || $_attr[ 'type' ] === 'unmatched') {
|
73: | $compiler->tag_nocache = true;
|
74: | $output = addcslashes($_attr[ 'code' ], "'\\");
|
75: | $compiler->parser->current_buffer->append_subtree(
|
76: | $compiler->parser,
|
77: | new Smarty_Internal_ParseTree_Tag(
|
78: | $compiler->parser,
|
79: | $compiler->processNocacheCode(
|
80: | "<?php echo '{$output}';?>\n",
|
81: | true
|
82: | )
|
83: | )
|
84: | );
|
85: | return '';
|
86: | } elseif ($compiler->php_handling === Smarty::PHP_ALLOW) {
|
87: | if (!($compiler->smarty instanceof SmartyBC)) {
|
88: | $compiler->trigger_template_error(
|
89: | '$smarty->php_handling PHP_ALLOW not allowed. Use SmartyBC to enable it',
|
90: | null,
|
91: | true
|
92: | );
|
93: | }
|
94: | $compiler->has_code = true;
|
95: | return $_attr[ 'code' ];
|
96: | } else {
|
97: | $compiler->trigger_template_error('Illegal $smarty->php_handling value', null, true);
|
98: | }
|
99: | } else {
|
100: | $compiler->has_code = true;
|
101: | if (!($compiler->smarty instanceof SmartyBC)) {
|
102: | $compiler->trigger_template_error(
|
103: | '{php}{/php} tags not allowed. Use SmartyBC to enable them',
|
104: | null,
|
105: | true
|
106: | );
|
107: | }
|
108: | $ldel = preg_quote($compiler->smarty->left_delimiter, '#');
|
109: | $rdel = preg_quote($compiler->smarty->right_delimiter, '#');
|
110: | preg_match("#^({$ldel}php\\s*)((.)*?)({$rdel})#", $_attr[ 'code' ], $match);
|
111: | if (!empty($match[ 2 ])) {
|
112: | if ('nocache' === trim($match[ 2 ])) {
|
113: | $compiler->tag_nocache = true;
|
114: | } else {
|
115: | $compiler->trigger_template_error("illegal value of option flag '{$match[2]}'", null, true);
|
116: | }
|
117: | }
|
118: | return preg_replace(
|
119: | array("#^{$ldel}\\s*php\\s*(.)*?{$rdel}#", "#{$ldel}\\s*/\\s*php\\s*{$rdel}$#"),
|
120: | array('<?php ', '?>'),
|
121: | $_attr[ 'code' ]
|
122: | );
|
123: | }
|
124: | }
|
125: |
|
126: | |
127: | |
128: | |
129: | |
130: | |
131: | |
132: | |
133: | |
134: |
|
135: | public function parsePhp(Smarty_Internal_Templatelexer $lex)
|
136: | {
|
137: | $lex->token = Smarty_Internal_Templateparser::TP_PHP;
|
138: | $close = 0;
|
139: | $lex->taglineno = $lex->line;
|
140: | $closeTag = '?>';
|
141: | if (strpos($lex->value, '<?xml') === 0) {
|
142: | $lex->is_xml = true;
|
143: | $lex->phpType = 'xml';
|
144: | return;
|
145: | } elseif (strpos($lex->value, '<?') === 0) {
|
146: | $lex->phpType = 'php';
|
147: | } elseif (strpos($lex->value, '<%') === 0) {
|
148: | $lex->phpType = 'asp';
|
149: | $closeTag = '%>';
|
150: | } elseif (strpos($lex->value, '%>') === 0) {
|
151: | $lex->phpType = 'unmatched';
|
152: | } elseif (strpos($lex->value, '?>') === 0) {
|
153: | if ($lex->is_xml) {
|
154: | $lex->is_xml = false;
|
155: | $lex->phpType = 'xml';
|
156: | return;
|
157: | }
|
158: | $lex->phpType = 'unmatched';
|
159: | } elseif (strpos($lex->value, '<s') === 0) {
|
160: | $lex->phpType = 'script';
|
161: | $closeTag = '</script>';
|
162: | } elseif (strpos($lex->value, $lex->smarty->left_delimiter) === 0) {
|
163: | if ($lex->isAutoLiteral()) {
|
164: | $lex->token = Smarty_Internal_Templateparser::TP_TEXT;
|
165: | return;
|
166: | }
|
167: | $closeTag = "{$lex->smarty->left_delimiter}/php{$lex->smarty->right_delimiter}";
|
168: | if ($lex->value === $closeTag) {
|
169: | $lex->compiler->trigger_template_error("unexpected closing tag '{$closeTag}'");
|
170: | }
|
171: | $lex->phpType = 'tag';
|
172: | }
|
173: | if ($lex->phpType === 'unmatched') {
|
174: | return;
|
175: | }
|
176: | if (($lex->phpType === 'php' || $lex->phpType === 'asp')
|
177: | &&
|
178: | ($lex->compiler->php_handling === Smarty::PHP_PASSTHRU ||
|
179: | $lex->compiler->php_handling === Smarty::PHP_QUOTE)
|
180: | ) {
|
181: | return;
|
182: | }
|
183: | $start = $lex->counter + strlen($lex->value);
|
184: | $body = true;
|
185: | if (preg_match('~' . preg_quote($closeTag, '~') . '~i', $lex->data, $match, PREG_OFFSET_CAPTURE, $start)) {
|
186: | $close = $match[ 0 ][ 1 ];
|
187: | } else {
|
188: | $lex->compiler->trigger_template_error("missing closing tag '{$closeTag}'");
|
189: | }
|
190: | while ($body) {
|
191: | if (preg_match(
|
192: | '~([/][*])|([/][/][^\n]*)|(\'[^\'\\\\]*(?:\\.[^\'\\\\]*)*\')|("[^"\\\\]*(?:\\.[^"\\\\]*)*")~',
|
193: | $lex->data,
|
194: | $match,
|
195: | PREG_OFFSET_CAPTURE,
|
196: | $start
|
197: | )
|
198: | ) {
|
199: | $value = $match[ 0 ][ 0 ];
|
200: | $from = $pos = $match[ 0 ][ 1 ];
|
201: | if ($pos > $close) {
|
202: | $body = false;
|
203: | } else {
|
204: | $start = $pos + strlen($value);
|
205: | $phpCommentStart = $value === '/*';
|
206: | if ($phpCommentStart) {
|
207: | $phpCommentEnd = preg_match('~([*][/])~', $lex->data, $match, PREG_OFFSET_CAPTURE, $start);
|
208: | if ($phpCommentEnd) {
|
209: | $pos2 = $match[ 0 ][ 1 ];
|
210: | $start = $pos2 + strlen($match[ 0 ][ 0 ]);
|
211: | }
|
212: | }
|
213: | while ($close > $pos && $close < $start) {
|
214: | if (preg_match(
|
215: | '~' . preg_quote($closeTag, '~') . '~i',
|
216: | $lex->data,
|
217: | $match,
|
218: | PREG_OFFSET_CAPTURE,
|
219: | $from
|
220: | )
|
221: | ) {
|
222: | $close = $match[ 0 ][ 1 ];
|
223: | $from = $close + strlen($match[ 0 ][ 0 ]);
|
224: | } else {
|
225: | $lex->compiler->trigger_template_error("missing closing tag '{$closeTag}'");
|
226: | }
|
227: | }
|
228: | if ($phpCommentStart && (!$phpCommentEnd || $pos2 > $close)) {
|
229: | $lex->taglineno = $lex->line + substr_count(substr($lex->data, $lex->counter, $start), "\n");
|
230: | $lex->compiler->trigger_template_error("missing PHP comment closing tag '*/'");
|
231: | }
|
232: | }
|
233: | } else {
|
234: | $body = false;
|
235: | }
|
236: | }
|
237: | $lex->value = substr($lex->data, $lex->counter, $close + strlen($closeTag) - $lex->counter);
|
238: | }
|
239: |
|
240: | |
241: | |
242: | |
243: |
|
244: | |
245: | |
246: | |
247: | |
248: |
|
249: | private function quote($match)
|
250: | {
|
251: | return htmlspecialchars($match[ 0 ], ENT_QUOTES);
|
252: | }
|
253: | }
|
254: | |