OSDN Git Service

sync the original code
[nucleus-jp/nucleus-jp-ancient.git] / utf8 / nucleus / libs / PARSER.php
1 <?php\r
2 /*\r
3  * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)\r
4  * Copyright (C) 2002-2005 The Nucleus Group\r
5  *\r
6  * This program is free software; you can redistribute it and/or\r
7  * modify it under the terms of the GNU General Public License\r
8  * as published by the Free Software Foundation; either version 2\r
9  * of the License, or (at your option) any later version.\r
10  * (see nucleus/documentation/index.html#license for more info)\r
11  */\r
12 /**\r
13  * @license http://nucleuscms.org/license.txt GNU General Public License\r
14  * @copyright Copyright (C) 2002-2005 The Nucleus Group\r
15  * @version $Id: PARSER.php,v 1.4 2005-08-13 07:33:02 kimitake Exp $\r
16  * $NucleusJP: PARSER.php,v 1.3 2005/03/12 06:19:05 kimitake Exp $\r
17  */\r
18  \r
19 /**\r
20  * This is the parser class of Nucleus. It is used for various things (skin parsing,\r
21  * form generation, ...)\r
22  */\r
23 class PARSER {\r
24 \r
25         // array with the names of all allowed actions\r
26         var $actions;\r
27         \r
28         // reference to actions handler\r
29         var $handler;\r
30         \r
31         // delimiters that can be used for skin/templatevars\r
32         var $delim;\r
33         \r
34         // parameter delimiter (to separate skinvar params)\r
35         var $pdelim;\r
36         \r
37         // usually set to 0. When set to 1, all skinvars are allowed regardless of $actions\r
38         var $norestrictions;\r
39         \r
40         /**\r
41          * Creates a new parser object with the given allowed actions \r
42          * and the given handler\r
43          *\r
44          * @param $allowedActions array\r
45          * @param $handler class object with functions for each action (reference)\r
46          * @param $delim optional delimiter\r
47          * @param $paramdelim optional parameterdelimiter        \r
48          */\r
49         function PARSER($allowedActions, &$handler, $delim = '(<%|%>)', $pdelim = ',') {\r
50                 $this->actions = $allowedActions;\r
51                 $this->handler =& $handler;\r
52                 $this->delim = $delim;\r
53                 $this->pdelim = $pdelim;\r
54                 $this->norestrictions = 0;      // set this to 1 to disable checking for allowedActions\r
55         }\r
56         \r
57         /**\r
58          * Parses the given contents and outputs it\r
59          */\r
60         function parse(&$contents) {\r
61         \r
62                 $pieces = preg_split('/'.$this->delim.'/',$contents);\r
63                 \r
64                 $maxidx = sizeof($pieces);\r
65                 for ($idx = 0;$idx<$maxidx;$idx++) {\r
66                         echo $pieces[$idx];             \r
67                         $idx++;\r
68                         $this->doAction($pieces[$idx]);\r
69                 }\r
70         }\r
71         \r
72 \r
73         /**\r
74           * handle an action \r
75           */\r
76         function doAction($action) {\r
77                 global $manager;\r
78 \r
79                 if (!$action) return;\r
80                 \r
81                 // split into action name + arguments\r
82                 if (strstr($action,'(')) {\r
83                         $paramStartPos = strpos($action, '(');\r
84                         $params = substr($action, $paramStartPos + 1, strlen($action) - $paramStartPos - 2);\r
85                         $action = substr($action, 0, $paramStartPos);\r
86                         $params = explode ($this->pdelim, $params);\r
87                         \r
88                         // trim parameters \r
89                         // for PHP versions lower than 4.0.6:\r
90                         //   - add // before '$params = ...' \r
91                         //   - remove // before 'foreach'\r
92                         $params = array_map('trim',$params);\r
93                         // foreach ($params as $key => $value) { $params[$key] = trim($value); }                        \r
94                 } else {\r
95                         // no parameters\r
96                         $params = array();\r
97                 }\r
98         \r
99                 $actionlc = strtolower($action);\r
100                 \r
101                 // skip execution of skinvars while inside an if condition which hides this part of the page\r
102                 if (!$this->handler->if_currentlevel && ($actionlc != 'else') && ($actionlc != 'endif') && (substr($actionlc,0,2) != 'if'))\r
103                         return;\r
104         \r
105                 if (in_array($actionlc, $this->actions) || $this->norestrictions ) {\r
106                         // when using PHP versions lower than 4.0.5, uncomment the line before\r
107                         // and comment the call_user_func_array call\r
108                         //$this->call_using_array($action, $this->handler, $params);\r
109                         call_user_func_array(array(&$this->handler,'parse_' . $actionlc), $params);\r
110                 } else {\r
111                         // redirect to plugin action if possible\r
112                         if (in_array('plugin', $this->actions) && $manager->pluginInstalled('NP_'.$action))\r
113                                 $this->doAction('plugin('.$action.$this->pdelim.implode($this->pdelim,$params).')');\r
114                         else\r
115                                 echo '<b>DISALLOWED (' , $action , ')</b>';\r
116                 }\r
117                 \r
118         }\r
119         \r
120         /**\r
121           * Calls a method using an array of parameters (for use with PHP versions lower than 4.0.5)\r
122           * ( = call_user_func_array() function )\r
123           */\r
124         function call_using_array($methodname, &$handler, $paramarray) {\r
125 \r
126                 $methodname = 'parse_' . $methodname;\r
127                 \r
128                 if (!method_exists($handler, $methodname)) {\r
129                         return;\r
130                 }\r
131 \r
132                 $command = 'call_user_func(array(&$handler,$methodname)';\r
133                 for ($i = 0; $i<count($paramarray); $i++)\r
134                         $command .= ',$paramarray[' . $i . ']';\r
135                 $command .= ');';\r
136                 eval($command); // execute the correct method\r
137         }\r
138         \r
139         function setProperty($property, $value) {\r
140                 global $manager;\r
141                 $manager->setParserProperty($property, $value);\r
142         }\r
143         \r
144         function getProperty($name) {\r
145                 global $manager;\r
146                 return $manager->getParserProperty($name);\r
147         }\r
148         \r
149         \r
150 }\r
151 \r
152 /**\r
153  * This class contains parse actions that are available in all ACTION classes\r
154  * e.g. include, phpinclude, parsedinclude, skinfile, ...\r
155  *\r
156  * It should never be used on it's own\r
157  */\r
158 class BaseActions {\r
159         \r
160         // depth level for includes (max. level is 3)\r
161         var $level;\r
162         \r
163         // array of evaluated conditions (true/false). The element at the end is the one for the most nested\r
164         // if block.\r
165         var $if_conditions;\r
166         \r
167         // at all times, can be evaluated to either true if the current block needs to be displayed. This \r
168         // variable is used to decide to skip skinvars in parts that will never be outputted.\r
169         var $if_currentlevel;\r
170         \r
171         // contains a search string with keywords that need to be highlighted. These get parsed into $aHighlight\r
172         var $strHighlight;\r
173         \r
174         // array of keywords that need to be highlighted in search results (see the highlight() \r
175         // and parseHighlight() methods)\r
176         var $aHighlight;\r
177         \r
178 \r
179         // reference to the parser object that is using this object as actions-handler\r
180 \r
181         var $parser;\r
182         \r
183 \r
184         function BaseActions() {\r
185                 $this->level = 0; \r
186                 \r
187                 // if nesting level\r
188                 $this->if_conditions = array(); // array on which condition values are pushed/popped\r
189                 $this->if_currentlevel = 1;             // 1 = current level is displayed; 0 = current level not displayed\r
190 \r
191                 // highlights           \r
192                 $this->strHighlight = '';                       // full highlight\r
193                 $this->aHighlight = array();            // parsed highlight\r
194                 \r
195         }\r
196 \r
197         // include file (no parsing of php)\r
198         function parse_include($filename) {\r
199                 @readfile($this->getIncludeFileName($filename));\r
200         }\r
201         \r
202         // php-include file \r
203         function parse_phpinclude($filename) {\r
204                 includephp($this->getIncludeFileName($filename));\r
205         }       \r
206         // parsed include\r
207         function parse_parsedinclude($filename) {\r
208                 // check current level\r
209                 if ($this->level > 3) return;   // max. depth reached (avoid endless loop)\r
210                 $filename = $this->getIncludeFileName($filename);\r
211                 if (!file_exists($filename)) return '';\r
212                 \r
213                 $fsize = filesize($filename);\r
214                 \r
215                 // nothing to include\r
216                 if ($fsize <= 0)\r
217                         return;\r
218                 \r
219                 $this->level = $this->level + 1;\r
220                 \r
221                 // read file \r
222                 $fd = fopen ($filename, 'r');\r
223                 $contents = fread ($fd, $fsize);\r
224                 fclose ($fd);           \r
225                 \r
226                 // parse file contents\r
227                 $this->parser->parse($contents);\r
228                 \r
229                 $this->level = $this->level - 1;                \r
230         }\r
231         \r
232         /**\r
233          * Returns the correct location of the file to be included, according to\r
234          * parser properties\r
235          *\r
236          * IF IncludeMode = 'skindir' => use skindir\r
237          */\r
238         function getIncludeFileName($filename) {\r
239                 // leave absolute filenames and http urls as they are\r
240                 if (\r
241                                 (substr($filename,0,1) == '/')\r
242                         ||      (substr($filename,0,7) == 'http://')\r
243                         ||      (substr($filename,0,6) == 'ftp://')                     \r
244                         )\r
245                         return $filename;\r
246         \r
247                 $filename = PARSER::getProperty('IncludePrefix') . $filename;\r
248                 if (PARSER::getProperty('IncludeMode') == 'skindir') {\r
249                         global $DIR_SKINS;\r
250                         return $DIR_SKINS . $filename;\r
251                 } else {\r
252                         return $filename;\r
253                 }\r
254         }\r
255         \r
256         /**\r
257          * Inserts an url relative to the skindir (useful when doing import/export)\r
258          *\r
259          * e.g. <skinfile(default/myfile.sth)>\r
260          */\r
261         function parse_skinfile($filename) {\r
262                 global $CONF;\r
263                 \r
264                 echo $CONF['SkinsURL'] . PARSER::getProperty('IncludePrefix') . $filename;\r
265         }\r
266         \r
267         /**\r
268          * Sets a property for the parser\r
269          */\r
270         function parse_set($property, $value) {\r
271                 PARSER::setProperty($property, $value);\r
272         }\r
273         \r
274         /**\r
275          * Helper function: add if condition\r
276          */\r
277         function _addIfCondition($condition) {\r
278         \r
279                 array_push($this->if_conditions,$condition);\r
280         \r
281                 $this->_updateTopIfCondition();\r
282                         \r
283                 ob_start();             \r
284         }\r
285         \r
286         function _updateTopIfCondition() {\r
287                 if (sizeof($this->if_conditions) == 0) \r
288                         $this->if_currentlevel = 1;\r
289                 else\r
290                         $this->if_currentlevel = $this->if_conditions[sizeof($this->if_conditions) - 1];\r
291         }\r
292         \r
293         /**\r
294          * returns the currently top if condition\r
295          */\r
296         function _getTopIfCondition() {\r
297                 return $this->if_currentlevel;\r
298         }\r
299         \r
300         /**\r
301          * else\r
302          */\r
303         function parse_else() {\r
304                 if (sizeof($this->if_conditions) == 0) return;\r
305                 $old = $this->if_currentlevel;\r
306                 if (array_pop($this->if_conditions)) {\r
307                         ob_end_flush();\r
308                         $this->_addIfCondition(0);\r
309                 } else {\r
310                         ob_end_clean();\r
311                         $this->_addIfCondition(1);\r
312                 }\r
313         }\r
314         \r
315         /**\r
316          * Ends a conditional if-block \r
317          * see e.g. ifcat (BLOG), ifblogsetting (PAGEFACTORY)\r
318          */\r
319         function parse_endif() {\r
320                 // we can only close what has been opened\r
321                 if (sizeof($this->if_conditions) == 0) return;\r
322                 \r
323                 if (array_pop($this->if_conditions)) {\r
324                         ob_end_flush();\r
325                 } else {\r
326                         ob_end_clean();\r
327                 }\r
328                 \r
329                 $this->_updateTopIfCondition();\r
330         }\r
331         \r
332         \r
333         /** \r
334          * Sets the search terms to be highlighted\r
335          *\r
336          * @param $highlight\r
337          *              A series of search terms\r
338          */\r
339         function setHighlight($highlight) {     \r
340                 $this->strHighlight = $highlight;\r
341                 if ($highlight) {\r
342                         $this->aHighlight = parseHighlight($highlight); \r
343                 }\r
344         }\r
345         \r
346         /**\r
347          * Applies the highlight to the given piece of text\r
348          *\r
349          * @param &$data\r
350          *              Data that needs to be highlighted\r
351          * @see setHighlight\r
352          */\r
353         function highlight(&$data) {\r
354                 if ($this->aHighlight)\r
355                         return highlight($data,$this->aHighlight,$this->template['SEARCH_HIGHLIGHT']);\r
356                 else\r
357                         return $data;\r
358         }\r
359         \r
360         \r
361 \r
362 }\r
363  \r
364 ?>\r