OSDN Git Service

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