11 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied |
11 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied |
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. |
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. |
13 */ |
13 */ |
14 |
14 |
15 class RenderMan { |
15 class RenderMan { |
16 |
16 |
17 public static function strToPageID($string) |
17 public static function strToPageID($string) |
18 { |
18 { |
19 global $db, $session, $paths, $template, $plugins; // Common objects |
19 global $db, $session, $paths, $template, $plugins; // Common objects |
20 $k = array_keys($paths->nslist); |
20 $k = array_keys($paths->nslist); |
21 $proj_alt = 'Project:'; |
21 $proj_alt = 'Project:'; |
22 if ( substr($string, 0, (strlen($proj_alt))) == $proj_alt ) |
22 if ( substr($string, 0, (strlen($proj_alt))) == $proj_alt ) |
23 { |
23 { |
24 $ns = 'Project'; |
24 $ns = 'Project'; |
25 $pg = substr($string, strlen($proj_alt), strlen($string)); |
25 $pg = substr($string, strlen($proj_alt), strlen($string)); |
26 return Array($pg, $ns); |
26 return Array($pg, $ns); |
27 } |
27 } |
28 for($i=0;$i<sizeof($paths->nslist);$i++) |
28 for($i=0;$i<sizeof($paths->nslist);$i++) |
29 { |
29 { |
30 $ln = strlen($paths->nslist[$k[$i]]); |
30 $ln = strlen($paths->nslist[$k[$i]]); |
31 if(substr($string, 0, $ln) == $paths->nslist[$k[$i]]) |
31 if(substr($string, 0, $ln) == $paths->nslist[$k[$i]]) |
32 { |
32 { |
33 $ns = $k[$i]; |
33 $ns = $k[$i]; |
34 $pg = substr($string, strlen($paths->nslist[$ns]), strlen($string)); |
34 $pg = substr($string, strlen($paths->nslist[$ns]), strlen($string)); |
35 } |
35 } |
36 } |
36 } |
37 return Array($pg, $ns); |
37 return Array($pg, $ns); |
38 } |
38 } |
39 |
39 |
40 public static function getPage($page_id, $namespace, $wiki = 1, $smilies = true, $filter_links = true, $redir = true, $render = true) |
40 public static function getPage($page_id, $namespace, $wiki = 1, $smilies = true, $filter_links = true, $redir = true, $render = true) |
41 { |
41 { |
42 global $db, $session, $paths, $template, $plugins; // Common objects |
42 global $db, $session, $paths, $template, $plugins; // Common objects |
43 |
43 |
44 $page = new PageProcessor($page_id, $namespace); |
44 $page = new PageProcessor($page_id, $namespace); |
45 $text = $page->fetch_text(); |
45 $text = $page->fetch_text(); |
46 |
46 |
47 if ( !$render ) |
47 if ( !$render ) |
48 return $text; |
48 return $text; |
49 |
49 |
50 $text = self::render($text, $wiki, $smilies, $filter_links); |
50 $text = self::render($text, $wiki, $smilies, $filter_links); |
51 return $text; |
51 return $text; |
52 } |
52 } |
53 |
53 |
54 public static function getTemplate($id, $parms) |
54 public static function getTemplate($id, $parms) |
55 { |
55 { |
56 global $db, $session, $paths, $template, $plugins; // Common objects |
56 global $db, $session, $paths, $template, $plugins; // Common objects |
57 if ( !isPage($paths->get_pathskey($id, 'Template')) ) |
57 if ( !isPage($paths->get_pathskey($id, 'Template')) ) |
58 { |
58 { |
59 return '[['.$paths->nslist['Template'].$id.']]'; |
59 return '[['.$paths->nslist['Template'].$id.']]'; |
60 } |
60 } |
61 if(isset($paths->template_cache[$id])) |
61 if(isset($paths->template_cache[$id])) |
62 { |
62 { |
63 $text = $paths->template_cache[$id]; |
63 $text = $paths->template_cache[$id]; |
64 } |
64 } |
65 else |
65 else |
66 { |
66 { |
67 $page = new PageProcessor($id, 'Template'); |
67 $page = new PageProcessor($id, 'Template'); |
68 $text = $page->fetch_text(); |
68 $text = $page->fetch_text(); |
69 $paths->template_cache[$id] = $text; |
69 $paths->template_cache[$id] = $text; |
70 } |
70 } |
71 |
71 |
72 $text = preg_replace('/<noinclude>(.*?)<\/noinclude>/is', '', $text); |
72 $text = preg_replace('/<noinclude>(.*?)<\/noinclude>/is', '', $text); |
73 $text = preg_replace('/<nodisplay>(.*?)<\/nodisplay>/is', '\\1', $text); |
73 $text = preg_replace('/<nodisplay>(.*?)<\/nodisplay>/is', '\\1', $text); |
74 |
74 |
75 preg_match_all('#\(_([0-9]+)_\)#', $text, $matchlist); |
75 preg_match_all('#\(_([0-9]+)_\)#', $text, $matchlist); |
76 |
76 |
77 foreach($matchlist[1] as $m) |
77 foreach($matchlist[1] as $m) |
78 { |
78 { |
79 if(isset($parms[((int)$m)+1])) |
79 if(isset($parms[((int)$m)+1])) |
80 { |
80 { |
81 $p = $parms[((int)$m)+1]; |
81 $p = $parms[((int)$m)+1]; |
82 } |
82 } |
83 else |
83 else |
84 { |
84 { |
85 $p = '<b>Notice:</b> RenderMan::getTemplate(): Parameter '.$m.' is not set'; |
85 $p = '<b>Notice:</b> RenderMan::getTemplate(): Parameter '.$m.' is not set'; |
86 } |
86 } |
87 $text = str_replace('(_'.$m.'_)', $p, $text); |
87 $text = str_replace('(_'.$m.'_)', $p, $text); |
88 $text = str_replace('{{' . ( $m + 1 ) . '}}', $p, $text); |
88 $text = str_replace('{{' . ( $m + 1 ) . '}}', $p, $text); |
89 } |
89 } |
90 $text = RenderMan::include_templates($text); |
90 $text = RenderMan::include_templates($text); |
91 return $text; |
91 return $text; |
92 } |
92 } |
93 |
93 |
94 public static function fetch_template_text($id) |
94 public static function fetch_template_text($id) |
95 { |
95 { |
96 global $db, $session, $paths, $template, $plugins; // Common objects |
96 global $db, $session, $paths, $template, $plugins; // Common objects |
97 $fetch_ns = 'Template'; |
97 $fetch_ns = 'Template'; |
98 if ( !isPage($paths->get_pathskey($id, 'Template')) ) |
98 if ( !isPage($paths->get_pathskey($id, 'Template')) ) |
99 { |
99 { |
100 // Transclusion of another page |
100 // Transclusion of another page |
101 // 1.1.5: Now You, Too, Can Be A Template, Even If You're Just A Plain Old Article! (TM) |
101 // 1.1.5: Now You, Too, Can Be A Template, Even If You're Just A Plain Old Article! (TM) |
102 $nssep = substr($paths->nslist['Special'], -1); |
102 $nssep = substr($paths->nslist['Special'], -1); |
103 $nslist = $paths->nslist; |
103 $nslist = $paths->nslist; |
104 foreach ( $nslist as &$ns ) |
104 foreach ( $nslist as &$ns ) |
105 { |
105 { |
106 if ( $ns == '' ) |
106 if ( $ns == '' ) |
107 $ns = $nssep; |
107 $ns = $nssep; |
108 } |
108 } |
109 $prefixlist = array_flip($nslist); |
109 $prefixlist = array_flip($nslist); |
110 foreach ( $nslist as &$ns ) |
110 foreach ( $nslist as &$ns ) |
111 { |
111 { |
112 $ns = preg_quote($ns); |
112 $ns = preg_quote($ns); |
113 } |
113 } |
114 $nslist = implode('|', $nslist); |
114 $nslist = implode('|', $nslist); |
115 if ( preg_match("/^($nslist)(.*?)$/", $id, $match) ) |
115 if ( preg_match("/^($nslist)(.*?)$/", $id, $match) ) |
116 { |
116 { |
117 // in practice this should always be true but just to be safe... |
117 // in practice this should always be true but just to be safe... |
118 if ( isset($prefixlist[$match[1]]) ) |
118 if ( isset($prefixlist[$match[1]]) ) |
119 { |
119 { |
120 $new_id = $paths->nslist[ $prefixlist[$match[1]] ] . sanitize_page_id($match[2]); |
120 $new_id = $paths->nslist[ $prefixlist[$match[1]] ] . sanitize_page_id($match[2]); |
121 if ( !isPage($new_id) ) |
121 if ( !isPage($new_id) ) |
122 { |
122 { |
123 return "[[$new_id]]"; |
123 return "[[$new_id]]"; |
124 } |
124 } |
125 $fetch_ns = $prefixlist[$match[1]]; |
125 $fetch_ns = $prefixlist[$match[1]]; |
126 $id = sanitize_page_id($match[2]); |
126 $id = sanitize_page_id($match[2]); |
127 } |
127 } |
128 } |
128 } |
129 else |
129 else |
130 { |
130 { |
131 return '[['.$paths->nslist['Template'].$id.']]'; |
131 return '[['.$paths->nslist['Template'].$id.']]'; |
132 } |
132 } |
133 } |
133 } |
134 if(isset($paths->template_cache[$id])) |
134 if(isset($paths->template_cache[$id])) |
135 { |
135 { |
136 $text = $paths->template_cache[$id]; |
136 $text = $paths->template_cache[$id]; |
137 } |
137 } |
138 else |
138 else |
139 { |
139 { |
140 $text = RenderMan::getPage($id, $fetch_ns, 0, false, false, false, false); |
140 $text = RenderMan::getPage($id, $fetch_ns, 0, false, false, false, false); |
141 $paths->template_cache[$id] = $text; |
141 $paths->template_cache[$id] = $text; |
142 } |
142 } |
143 |
143 |
144 if ( is_string($text) ) |
144 if ( is_string($text) ) |
145 { |
145 { |
146 $text = preg_replace('/<noinclude>(.*?)<\/noinclude>/is', '', $text); |
146 $text = preg_replace('/<noinclude>(.*?)<\/noinclude>/is', '', $text); |
147 $text = preg_replace('/<nodisplay>(.*?)<\/nodisplay>/is', '\\1', $text); |
147 $text = preg_replace('/<nodisplay>(.*?)<\/nodisplay>/is', '\\1', $text); |
148 } |
148 } |
149 |
149 |
150 return $text; |
150 return $text; |
151 } |
151 } |
152 |
152 |
153 /** |
153 /** |
154 * Renders a glob of text. Note that this is PHP-safe, so if returned text (or rather, "?>" . $returned) has PHP it can be eval'ed. |
154 * Renders a glob of text. Note that this is PHP-safe, so if returned text (or rather, "?>" . $returned) has PHP it can be eval'ed. |
155 * @param string Text to render |
155 * @param string Text to render |
156 * @param int Render parameters - see constants.php |
156 * @param int Render parameters - see constants.php |
157 * @return string Rendered text |
157 * @return string Rendered text |
158 */ |
158 */ |
159 |
159 |
160 public static function render($text, $flags = RENDER_WIKI_DEFAULT, $smilies = true) |
160 public static function render($text, $flags = RENDER_WIKI_DEFAULT, $smilies = true) |
161 { |
161 { |
162 global $db, $session, $paths, $template, $plugins; // Common objects |
162 global $db, $session, $paths, $template, $plugins; // Common objects |
163 |
163 |
164 if ( !$smilies ) |
164 if ( !$smilies ) |
165 $flags |= RENDER_NOSMILIES; |
165 $flags |= RENDER_NOSMILIES; |
166 |
166 |
167 if ( !($flags & RENDER_NOSMILIES) ) |
167 if ( !($flags & RENDER_NOSMILIES) ) |
168 { |
168 { |
169 $text = RenderMan::smilieyize($text); |
169 $text = RenderMan::smilieyize($text); |
170 } |
170 } |
171 if ( $flags & RENDER_WIKI_DEFAULT ) |
171 if ( $flags & RENDER_WIKI_DEFAULT ) |
172 { |
172 { |
173 $text = RenderMan::next_gen_wiki_format($text, $flags); |
173 $text = RenderMan::next_gen_wiki_format($text, $flags); |
174 } |
174 } |
175 else if ( $flags & RENDER_WIKI_TEMPLATE ) |
175 else if ( $flags & RENDER_WIKI_TEMPLATE ) |
176 { |
176 { |
177 $text = $template->tplWikiFormat($text); |
177 $text = $template->tplWikiFormat($text); |
178 } |
178 } |
179 return $text; |
179 return $text; |
180 } |
180 } |
181 |
181 |
182 private static function next_gen_wiki_format($text, $flags = 0) |
182 private static function next_gen_wiki_format($text, $flags = 0) |
183 { |
183 { |
184 global $db, $session, $paths, $template, $plugins; // Common objects |
184 global $db, $session, $paths, $template, $plugins; // Common objects |
185 global $lang; |
185 global $lang; |
186 |
186 |
187 profiler_log("RenderMan: starting wikitext render"); |
187 profiler_log("RenderMan: starting wikitext render"); |
188 require_once( ENANO_ROOT . '/includes/wikiformat.php' ); |
188 require_once( ENANO_ROOT . '/includes/wikiformat.php' ); |
189 require_once( ENANO_ROOT . '/includes/wikiengine/TagSanitizer.php' ); |
189 require_once( ENANO_ROOT . '/includes/wikiengine/TagSanitizer.php' ); |
190 require_once( ENANO_ROOT . '/includes/wikiengine/Tables.php' ); |
190 require_once( ENANO_ROOT . '/includes/wikiengine/Tables.php' ); |
191 |
191 |
192 // this is still needed by parser plugins |
192 // this is still needed by parser plugins |
193 $random_id = md5( time() . mt_rand() ); |
193 $random_id = md5( time() . mt_rand() ); |
194 |
194 |
195 // Strip out <nowiki> sections |
195 // Strip out <nowiki> sections |
196 self::nowiki_strip($text, $nowiki_stripped); |
196 self::nowiki_strip($text, $nowiki_stripped); |
197 |
197 |
198 // Run early parsing plugins |
198 // Run early parsing plugins |
199 $code = $plugins->setHook('render_wikiformat_veryearly'); |
199 $code = $plugins->setHook('render_wikiformat_veryearly'); |
200 foreach ( $code as $cmd ) |
200 foreach ( $code as $cmd ) |
201 { |
201 { |
202 eval($cmd); |
202 eval($cmd); |
203 } |
203 } |
204 |
204 |
205 // Strip out embedded PHP |
205 // Strip out embedded PHP |
206 self::php_strip($text, $php_stripped); |
206 self::php_strip($text, $php_stripped); |
207 |
207 |
208 // Convert newlines for the parser |
208 // Convert newlines for the parser |
209 $text = str_replace("\r\n", "\n", $text); |
209 $text = str_replace("\r\n", "\n", $text); |
210 |
210 |
211 // Perform render through the engine |
211 // Perform render through the engine |
212 $carpenter = new Carpenter(); |
212 $carpenter = new Carpenter(); |
213 $carpenter->flags = $flags; |
213 $carpenter->flags = $flags; |
214 $carpenter->hook(array(__CLASS__, 'hook_pre'), PO_AFTER, 'lang'); |
214 $carpenter->hook(array(__CLASS__, 'hook_pre'), PO_AFTER, 'lang'); |
215 $carpenter->hook(array(__CLASS__, 'hook_posttemplates'), PO_AFTER, 'templates'); |
215 $carpenter->hook(array(__CLASS__, 'hook_posttemplates'), PO_AFTER, 'templates'); |
216 if ( $flags & RENDER_WIKI_TEMPLATE ) |
216 if ( $flags & RENDER_WIKI_TEMPLATE ) |
217 { |
217 { |
218 // FIXME: Where is noinclude/nodisplay being processed in the pipeline? (Seems to be processed, but not here) |
218 // FIXME: Where is noinclude/nodisplay being processed in the pipeline? (Seems to be processed, but not here) |
219 } |
219 } |
220 |
220 |
221 // |
221 // |
222 // Set rules for the rendering process |
222 // Set rules for the rendering process |
223 // |
223 // |
224 |
224 |
225 if ( $flags & RENDER_BLOCK && !($flags & RENDER_INLINE) ) |
225 if ( $flags & RENDER_BLOCK && !($flags & RENDER_INLINE) ) |
226 { |
226 { |
227 // block only |
227 // block only |
228 $carpenter->disable_all_rules(); |
228 $carpenter->disable_all_rules(); |
229 foreach ( array('blockquote', 'tables', 'heading', 'hr', 'multilist', 'bold', 'italic', 'underline', 'paragraph', 'blockquotepost') as $rule ) |
229 foreach ( array('blockquote', 'tables', 'heading', 'hr', 'multilist', 'bold', 'italic', 'underline', 'paragraph', 'blockquotepost') as $rule ) |
230 { |
230 { |
231 $carpenter->enable_rule($rule); |
231 $carpenter->enable_rule($rule); |
232 } |
232 } |
233 |
233 |
234 $code = $plugins->setHook('render_block_only'); |
234 $code = $plugins->setHook('render_block_only'); |
235 foreach ( $code as $cmd ) |
235 foreach ( $code as $cmd ) |
236 { |
236 { |
237 eval($cmd); |
237 eval($cmd); |
238 } |
238 } |
239 } |
239 } |
240 else if ( $flags & RENDER_INLINE && !($flags & RENDER_BLOCK) ) |
240 else if ( $flags & RENDER_INLINE && !($flags & RENDER_BLOCK) ) |
241 { |
241 { |
242 // inline only |
242 // inline only |
243 $carpenter->disable_all_rules(); |
243 $carpenter->disable_all_rules(); |
244 foreach ( array('bold', 'italic', 'underline', 'externalwithtext', 'externalnotext', 'image', 'internallink') as $rule ) |
244 foreach ( array('bold', 'italic', 'underline', 'externalwithtext', 'externalnotext', 'image', 'internallink') as $rule ) |
245 { |
245 { |
246 $carpenter->enable_rule($rule); |
246 $carpenter->enable_rule($rule); |
247 } |
247 } |
248 |
248 |
249 $code = $plugins->setHook('render_inline_only'); |
249 $code = $plugins->setHook('render_inline_only'); |
250 foreach ( $code as $cmd ) |
250 foreach ( $code as $cmd ) |
251 { |
251 { |
252 eval($cmd); |
252 eval($cmd); |
253 } |
253 } |
254 } |
254 } |
255 else |
255 else |
256 { |
256 { |
257 // full render |
257 // full render |
258 $code = $plugins->setHook('render_full'); |
258 $code = $plugins->setHook('render_full'); |
259 foreach ( $code as $cmd ) |
259 foreach ( $code as $cmd ) |
260 { |
260 { |
261 eval($cmd); |
261 eval($cmd); |
262 } |
262 } |
263 } |
263 } |
264 $text = $carpenter->render($text); |
264 $text = $carpenter->render($text); |
265 |
265 |
266 // For plugin compat |
266 // For plugin compat |
267 $result =& $text; |
267 $result =& $text; |
268 |
268 |
269 // Post processing hook |
269 // Post processing hook |
270 $code = $plugins->setHook('render_wikiformat_post'); |
270 $code = $plugins->setHook('render_wikiformat_post'); |
271 foreach ( $code as $cmd ) |
271 foreach ( $code as $cmd ) |
272 { |
272 { |
273 eval($cmd); |
273 eval($cmd); |
274 } |
274 } |
275 |
275 |
276 // Add PHP and nowiki back in |
276 // Add PHP and nowiki back in |
277 self::nowiki_unstrip($text, $nowiki_stripped); |
277 self::nowiki_unstrip($text, $nowiki_stripped); |
278 self::php_unstrip($text, $php_stripped); |
278 self::php_unstrip($text, $php_stripped); |
279 |
279 |
280 profiler_log("RenderMan: finished wikitext render"); |
280 profiler_log("RenderMan: finished wikitext render"); |
281 |
281 |
282 return $text; |
282 return $text; |
283 } |
283 } |
284 |
284 |
285 public static function hook_pre($text) |
285 public static function hook_pre($text) |
286 { |
286 { |
287 global $db, $session, $paths, $template, $plugins; // Common objects |
287 global $db, $session, $paths, $template, $plugins; // Common objects |
288 |
288 |
289 $code = $plugins->setHook('render_wikiformat_pre'); |
289 $code = $plugins->setHook('render_wikiformat_pre'); |
290 foreach ( $code as $cmd ) |
290 foreach ( $code as $cmd ) |
291 { |
291 { |
292 eval($cmd); |
292 eval($cmd); |
293 } |
293 } |
294 |
294 |
295 return $text; |
295 return $text; |
296 } |
296 } |
297 |
297 |
298 public static function hook_posttemplates($text) |
298 public static function hook_posttemplates($text) |
299 { |
299 { |
300 global $db, $session, $paths, $template, $plugins; // Common objects |
300 global $db, $session, $paths, $template, $plugins; // Common objects |
301 |
301 |
302 $code = $plugins->setHook('render_wikiformat_posttemplates'); |
302 $code = $plugins->setHook('render_wikiformat_posttemplates'); |
303 foreach ( $code as $cmd ) |
303 foreach ( $code as $cmd ) |
304 { |
304 { |
305 eval($cmd); |
305 eval($cmd); |
306 } |
306 } |
307 |
307 |
308 return $text; |
308 return $text; |
309 } |
309 } |
310 |
310 |
311 /** |
311 /** |
312 * Strip out <nowiki> tags (to bypass parsing on them) |
312 * Strip out <nowiki> tags (to bypass parsing on them) |
313 * @access private |
313 * @access private |
314 */ |
314 */ |
315 |
315 |
316 private static function nowiki_strip(&$text, &$stripdata) |
316 private static function nowiki_strip(&$text, &$stripdata) |
317 { |
317 { |
318 self::tag_strip('nowiki', $text, $stripdata); |
318 self::tag_strip('nowiki', $text, $stripdata); |
319 } |
319 } |
320 |
320 |
321 /** |
321 /** |
322 * Restore stripped <nowiki> tags. |
322 * Restore stripped <nowiki> tags. |
323 * @access private |
323 * @access private |
324 */ |
324 */ |
325 |
325 |
326 public static function nowiki_unstrip(&$text, &$stripdata) |
326 public static function nowiki_unstrip(&$text, &$stripdata) |
327 { |
327 { |
328 self::tag_unstrip('nowiki', $text, $stripdata); |
328 self::tag_unstrip('nowiki', $text, $stripdata); |
329 } |
329 } |
330 |
330 |
331 /** |
331 /** |
332 * Strip out an arbitrary HTML tag. |
332 * Strip out an arbitrary HTML tag. |
333 * @access private |
333 * @access private |
334 */ |
334 */ |
335 |
335 |
336 public static function tag_strip($tag, &$text, &$stripdata) |
336 public static function tag_strip($tag, &$text, &$stripdata) |
337 { |
337 { |
338 $random_id = md5( time() . mt_rand() ); |
338 $random_id = md5( time() . mt_rand() ); |
339 |
339 |
340 preg_match_all("#<$tag>(.*?)</$tag>#is", $text, $blocks); |
340 preg_match_all("#<$tag>(.*?)</$tag>#is", $text, $blocks); |
341 |
341 |
342 foreach ( $blocks[0] as $i => $match ) |
342 foreach ( $blocks[0] as $i => $match ) |
343 { |
343 { |
344 $text = str_replace($match, "{{$tag}:{$random_id}:{$i}}", $text); |
344 $text = str_replace($match, "{{$tag}:{$random_id}:{$i}}", $text); |
345 } |
345 } |
346 |
346 |
347 $stripdata = array( |
347 $stripdata = array( |
348 'random_id' => $random_id, |
348 'random_id' => $random_id, |
349 'blocks' => $blocks[1] |
349 'blocks' => $blocks[1] |
350 ); |
350 ); |
351 } |
351 } |
352 |
352 |
353 /** |
353 /** |
354 * Strip out an arbitrary HTML tag, pushing on to the existing list of stripped data. |
354 * Strip out an arbitrary HTML tag, pushing on to the existing list of stripped data. |
355 * @access private |
355 * @access private |
356 */ |
356 */ |
357 |
357 |
358 public static function tag_strip_push($tag, &$text, &$stripdata) |
358 public static function tag_strip_push($tag, &$text, &$stripdata) |
359 { |
359 { |
360 if ( !is_array($stripdata) ) |
360 if ( !is_array($stripdata) ) |
361 { |
361 { |
362 $stripdata = array( |
362 $stripdata = array( |
363 'random_id' => md5( time() . mt_rand() ), |
363 'random_id' => md5( time() . mt_rand() ), |
364 'blocks' => array() |
364 'blocks' => array() |
365 ); |
365 ); |
366 } |
366 } |
367 $random_id =& $stripdata['random_id']; |
367 $random_id =& $stripdata['random_id']; |
368 |
368 |
369 preg_match_all("#<$tag>(.*?)</$tag>#is", $text, $blocks); |
369 preg_match_all("#<$tag>(.*?)</$tag>#is", $text, $blocks); |
370 |
370 |
371 foreach ( $blocks[0] as $i => $match ) |
371 foreach ( $blocks[0] as $i => $match ) |
372 { |
372 { |
373 $j = count($stripdata['blocks']); |
373 $j = count($stripdata['blocks']); |
374 $stripdata['blocks'][] = $blocks[1][$i]; |
374 $stripdata['blocks'][] = $blocks[1][$i]; |
375 $text = str_replace($match, "{{$tag}:{$random_id}:{$j}}", $text); |
375 $text = str_replace($match, "{{$tag}:{$random_id}:{$j}}", $text); |
376 } |
376 } |
377 } |
377 } |
378 |
378 |
379 /** |
379 /** |
380 * Restore stripped <nowiki> tags. |
380 * Restore stripped <nowiki> tags. |
381 * @access private |
381 * @access private |
382 */ |
382 */ |
383 |
383 |
384 public static function tag_unstrip($tag, &$text, &$stripdata, $keep = false) |
384 public static function tag_unstrip($tag, &$text, &$stripdata, $keep = false) |
385 { |
385 { |
386 $random_id = $stripdata['random_id']; |
386 $random_id = $stripdata['random_id']; |
387 |
387 |
388 foreach ( $stripdata['blocks'] as $i => $block ) |
388 foreach ( $stripdata['blocks'] as $i => $block ) |
389 { |
389 { |
390 $block = $keep ? "<$tag>$block</$tag>" : $block; |
390 $block = $keep ? "<$tag>$block</$tag>" : $block; |
391 $text = str_replace("{{$tag}:{$random_id}:{$i}}", $block, $text); |
391 $text = str_replace("{{$tag}:{$random_id}:{$i}}", $block, $text); |
392 } |
392 } |
393 |
393 |
394 $stripdata = array(); |
394 $stripdata = array(); |
395 } |
395 } |
396 |
396 |
397 /** |
397 /** |
398 * Strip out PHP code (to prevent it from being sent through the parser). Private because it does not do what you think it does. (The method you are looking for is strip_php.) |
398 * Strip out PHP code (to prevent it from being sent through the parser). Private because it does not do what you think it does. (The method you are looking for is strip_php.) |
399 * @access private |
399 * @access private |
400 */ |
400 */ |
401 |
401 |
402 private static function php_strip(&$text, &$stripdata) |
402 private static function php_strip(&$text, &$stripdata) |
403 { |
403 { |
404 $random_id = md5( time() . mt_rand() ); |
404 $random_id = md5( time() . mt_rand() ); |
405 |
405 |
406 preg_match_all('#<\?(?:php)?[\s=].+?\?>#is', $text, $blocks); |
406 preg_match_all('#<\?(?:php)?[\s=].+?\?>#is', $text, $blocks); |
407 |
407 |
408 foreach ( $blocks[0] as $i => $match ) |
408 foreach ( $blocks[0] as $i => $match ) |
409 { |
409 { |
410 $text = str_replace($match, "{PHP:$random_id:$i}", $text); |
410 $text = str_replace($match, "{PHP:$random_id:$i}", $text); |
411 } |
411 } |
412 |
412 |
413 $stripdata = array( |
413 $stripdata = array( |
414 'random_id' => $random_id, |
414 'random_id' => $random_id, |
415 'blocks' => $blocks[0] |
415 'blocks' => $blocks[0] |
416 ); |
416 ); |
417 } |
417 } |
418 |
418 |
419 /** |
419 /** |
420 * Restore stripped PHP code |
420 * Restore stripped PHP code |
421 * @access private |
421 * @access private |
422 */ |
422 */ |
423 |
423 |
424 private static function php_unstrip(&$text, &$stripdata) |
424 private static function php_unstrip(&$text, &$stripdata) |
425 { |
425 { |
426 $random_id = $stripdata['random_id']; |
426 $random_id = $stripdata['random_id']; |
427 |
427 |
428 foreach ( $stripdata['blocks'] as $i => $block ) |
428 foreach ( $stripdata['blocks'] as $i => $block ) |
429 { |
429 { |
430 $text = str_replace("{PHP:$random_id:$i}", $block, $text); |
430 $text = str_replace("{PHP:$random_id:$i}", $block, $text); |
431 } |
431 } |
432 |
432 |
433 $stripdata = array(); |
433 $stripdata = array(); |
434 } |
434 } |
435 |
435 |
436 /** |
436 /** |
437 * Deprecated. |
437 * Deprecated. |
438 */ |
438 */ |
439 |
439 |
440 public static function wikiFormat($message, $filter_links = true, $do_params = false, $plaintext = false) |
440 public static function wikiFormat($message, $filter_links = true, $do_params = false, $plaintext = false) |
441 { |
441 { |
442 global $db, $session, $paths, $template, $plugins; // Common objects |
442 global $db, $session, $paths, $template, $plugins; // Common objects |
443 |
443 |
444 return RenderMan::next_gen_wiki_format($message, $plaintext, $filter_links, $do_params); |
444 return RenderMan::next_gen_wiki_format($message, $plaintext, $filter_links, $do_params); |
445 } |
445 } |
446 |
446 |
447 public static function destroy_javascript($message, $_php = false) |
447 public static function destroy_javascript($message, $_php = false) |
448 { |
448 { |
449 $message = preg_replace('#<(script|object|applet|embed|iframe|frame|form|input|select)(.*?)>#is', '<\\1\\2>', $message); |
449 $message = preg_replace('#<(script|object|applet|embed|iframe|frame|form|input|select)(.*?)>#is', '<\\1\\2>', $message); |
450 $message = preg_replace('#</(script|object|applet|embed|iframe|frame|form|input|select)(.*?)>#is', '</\\1\\2>', $message); |
450 $message = preg_replace('#</(script|object|applet|embed|iframe|frame|form|input|select)(.*?)>#is', '</\\1\\2>', $message); |
451 $message = preg_replace('#(javascript|script|activex|chrome|about|applet):#is', '\\1:', $message); |
451 $message = preg_replace('#(javascript|script|activex|chrome|about|applet):#is', '\\1:', $message); |
452 if ( $_php ) |
452 if ( $_php ) |
453 { |
453 { |
454 // Left in only for compatibility |
454 // Left in only for compatibility |
455 $message = preg_replace('#<(.*?)>#is', '<\\1>', $message); |
455 $message = preg_replace('#<(.*?)>#is', '<\\1>', $message); |
456 $message = preg_replace('#<(.*?)>#is', '<\\1>', $message); |
456 $message = preg_replace('#<(.*?)>#is', '<\\1>', $message); |
457 $message = preg_replace('#<(\?|\?php|%)(.*?)(\?|%)>#is', '<\\1\\2\\3>', $message); |
457 $message = preg_replace('#<(\?|\?php|%)(.*?)(\?|%)>#is', '<\\1\\2\\3>', $message); |
458 // strip <a href="foo" onclick="bar();">-type attacks |
458 // strip <a href="foo" onclick="bar();">-type attacks |
459 $message = preg_replace('#<([a-zA-Z:\-]+) (.*?)on([A-Za-z]*)=(.*?)>#is', '<\\1\\2on\\3=\\4>', $message); |
459 $message = preg_replace('#<([a-zA-Z:\-]+) (.*?)on([A-Za-z]*)=(.*?)>#is', '<\\1\\2on\\3=\\4>', $message); |
460 } |
460 } |
461 return $message; |
461 return $message; |
462 } |
462 } |
463 |
463 |
464 public static function strip_php($message) |
464 public static function strip_php($message) |
465 { |
465 { |
466 return RenderMan::destroy_javascript($message, true); |
466 return RenderMan::destroy_javascript($message, true); |
467 } |
467 } |
468 |
468 |
469 public static function sanitize_html($text) |
469 public static function sanitize_html($text) |
470 { |
470 { |
471 $text = htmlspecialchars($text); |
471 $text = htmlspecialchars($text); |
472 $allowed_tags = Array('b', 'i', 'u', 'pre', 'code', 'tt', 'br', 'p', 'nowiki', '!--([\w\W]+)--'); |
472 $allowed_tags = Array('b', 'i', 'u', 'pre', 'code', 'tt', 'br', 'p', 'nowiki', '!--([\w\W]+)--'); |
473 foreach($allowed_tags as $t) |
473 foreach($allowed_tags as $t) |
474 { |
474 { |
475 $text = preg_replace('#<'.$t.'>(.*?)</'.$t.'>#is', '<'.$t.'>\\1</'.$t.'>', $text); |
475 $text = preg_replace('#<'.$t.'>(.*?)</'.$t.'>#is', '<'.$t.'>\\1</'.$t.'>', $text); |
476 $text = preg_replace('#<'.$t.' />#is', '<'.$t.' />', $text); |
476 $text = preg_replace('#<'.$t.' />#is', '<'.$t.' />', $text); |
477 $text = preg_replace('#<'.$t.'>#is', '<'.$t.'>', $text); |
477 $text = preg_replace('#<'.$t.'>#is', '<'.$t.'>', $text); |
478 } |
478 } |
479 return $text; |
479 return $text; |
480 } |
480 } |
481 |
481 |
482 /** |
482 /** |
483 * Reverse-renders a blob of text (converts it from XHTML back to wikitext) by using parser hints and educated guesses. |
483 * Reverse-renders a blob of text (converts it from XHTML back to wikitext) by using parser hints and educated guesses. |
484 * @param string XHTML |
484 * @param string XHTML |
485 * @return string Wikitext |
485 * @return string Wikitext |
486 */ |
486 */ |
487 |
487 |
488 public static function reverse_render($text) |
488 public static function reverse_render($text) |
489 { |
489 { |
490 // convert \r\n to \n |
490 // convert \r\n to \n |
491 $text = str_replace("\r\n", "\n", $text); |
491 $text = str_replace("\r\n", "\n", $text); |
492 |
492 |
493 // Separate certain block level elements onto their own lines. This tidies up the tag |
493 // Separate certain block level elements onto their own lines. This tidies up the tag |
494 // soup that TinyMCE sometimes produces. |
494 // soup that TinyMCE sometimes produces. |
495 $block_elements = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'div', 'table', 'ul', 'pre'); |
495 $block_elements = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'div', 'table', 'ul', 'pre'); |
496 $block_elements = implode('|', $block_elements); |
496 $block_elements = implode('|', $block_elements); |
497 $regex = "#(</(?:$block_elements)>)\n?<($block_elements)(>| .+?>)#i"; |
497 $regex = "#(</(?:$block_elements)>)\n?<($block_elements)(>| .+?>)#i"; |
498 $text = preg_replace($regex, "$1\n\n<$2$3", $text); |
498 $text = preg_replace($regex, "$1\n\n<$2$3", $text); |
499 |
499 |
500 $text = self::reverse_process_parser_hints($text); |
500 $text = self::reverse_process_parser_hints($text); |
501 $text = self::reverse_process_headings($text); |
501 $text = self::reverse_process_headings($text); |
502 $text = self::reverse_process_lists($text); |
502 $text = self::reverse_process_lists($text); |
503 $text = self::reverse_process_tables($text); |
503 $text = self::reverse_process_tables($text); |
504 |
504 |
505 // Lastly, strip out paragraph tags. |
505 // Lastly, strip out paragraph tags. |
506 $text = preg_replace('|^ *<p>(.+?)</p> *$|m', "\\1", $text); |
506 $text = preg_replace('|^ *<p>(.+?)</p> *$|m', "\\1", $text); |
507 |
507 |
508 return $text; |
508 return $text; |
509 } |
509 } |
510 |
510 |
511 public static function reverse_process_parser_hints($text) |
511 public static function reverse_process_parser_hints($text) |
512 { |
512 { |
513 global $db, $session, $paths, $template, $plugins; // Common objects |
513 global $db, $session, $paths, $template, $plugins; // Common objects |
514 |
514 |
515 if ( !preg_match_all('|<!--#([a-z0-9_]+)(?: (.+?))?-->([\w\W]*?)<!--#/\\1-->|s', $text, $matches) ) |
515 if ( !preg_match_all('|<!--#([a-z0-9_]+)(?: (.+?))?-->([\w\W]*?)<!--#/\\1-->|s', $text, $matches) ) |
516 return $text; |
516 return $text; |
517 |
517 |
518 foreach ( $matches[0] as $i => $match ) |
518 foreach ( $matches[0] as $i => $match ) |
519 { |
519 { |
520 $tag =& $matches[1][$i]; |
520 $tag =& $matches[1][$i]; |
521 $attribs =& $matches[2][$i]; |
521 $attribs =& $matches[2][$i]; |
522 $inner =& $matches[3][$i]; |
522 $inner =& $matches[3][$i]; |
523 |
523 |
524 $attribs = self::reverse_process_hint_attribs($attribs); |
524 $attribs = self::reverse_process_hint_attribs($attribs); |
525 switch($tag) |
525 switch($tag) |
526 { |
526 { |
527 case 'smiley': |
527 case 'smiley': |
528 case 'internallink': |
528 case 'internallink': |
529 case 'imagelink': |
529 case 'imagelink': |
530 if ( isset($attribs['code']) ) |
530 if ( isset($attribs['code']) ) |
531 { |
531 { |
532 $text = str_replace($match, $attribs['code'], $text); |
532 $text = str_replace($match, $attribs['code'], $text); |
533 } |
533 } |
534 else if ( isset($attribs['src']) ) |
534 else if ( isset($attribs['src']) ) |
535 { |
535 { |
536 $text = str_replace($match, $attribs['src'], $text); |
536 $text = str_replace($match, $attribs['src'], $text); |
537 } |
537 } |
538 break; |
538 break; |
539 } |
539 } |
540 } |
540 } |
541 |
541 |
542 return $text; |
542 return $text; |
543 } |
543 } |
544 |
544 |
545 public static function reverse_process_hint_attribs($attribs) |
545 public static function reverse_process_hint_attribs($attribs) |
546 { |
546 { |
547 $return = array(); |
547 $return = array(); |
548 if ( !preg_match_all('/([a-z0-9_-]+)="([^"]+?)"/', $attribs, $matches) ) |
548 if ( !preg_match_all('/([a-z0-9_-]+)="([^"]+?)"/', $attribs, $matches) ) |
549 return array(); |
549 return array(); |
550 |
550 |
551 foreach ( $matches[0] as $i => $match ) |
551 foreach ( $matches[0] as $i => $match ) |
552 { |
552 { |
553 $name =& $matches[1][$i]; |
553 $name =& $matches[1][$i]; |
554 $value =& $matches[2][$i]; |
554 $value =& $matches[2][$i]; |
555 |
555 |
556 $value = base64_decode($value); |
556 $value = base64_decode($value); |
557 |
557 |
558 $return[$name] = $value; |
558 $return[$name] = $value; |
559 } |
559 } |
560 |
560 |
561 return $return; |
561 return $return; |
562 } |
562 } |
563 |
563 |
564 /** |
564 /** |
565 * Escapes a string so that it's safe to use as an attribute in a parser hint. |
565 * Escapes a string so that it's safe to use as an attribute in a parser hint. |
566 * @param string |
566 * @param string |
567 * @return string |
567 * @return string |
568 */ |
568 */ |
569 |
569 |
570 public static function escape_parser_hint_attrib($text) |
570 public static function escape_parser_hint_attrib($text) |
571 { |
571 { |
572 return base64_encode($text); |
572 return base64_encode($text); |
573 } |
573 } |
574 |
574 |
575 public static function reverse_process_headings($text) |
575 public static function reverse_process_headings($text) |
576 { |
576 { |
577 if ( !preg_match_all('|^<h([1-6])(?: id="toc[0-9]+")?>(.*?)</h\\1>$|m', $text, $matches) ) |
577 if ( !preg_match_all('|^<h([1-6])(?: id="toc[0-9]+")?>(.*?)</h\\1>$|m', $text, $matches) ) |
578 return $text; |
578 return $text; |
579 |
579 |
580 foreach ( $matches[0] as $i => $match ) |
580 foreach ( $matches[0] as $i => $match ) |
581 { |
581 { |
582 // generate heading tag |
582 // generate heading tag |
583 $heading_size = intval($matches[1][$i]); |
583 $heading_size = intval($matches[1][$i]); |
584 $eq = ''; |
584 $eq = ''; |
585 for ( $j = 0; $j < $heading_size; $j++ ) |
585 for ( $j = 0; $j < $heading_size; $j++ ) |
586 $eq .= '='; |
586 $eq .= '='; |
587 |
587 |
588 $heading =& $matches[2][$i]; |
588 $heading =& $matches[2][$i]; |
589 |
589 |
590 $tag = "$eq $heading $eq"; |
590 $tag = "$eq $heading $eq"; |
591 $text = str_replace($match, $tag, $text); |
591 $text = str_replace($match, $tag, $text); |
592 } |
592 } |
593 |
593 |
594 return $text; |
594 return $text; |
595 } |
595 } |
596 |
596 |
597 public static function reverse_process_lists($text) |
597 public static function reverse_process_lists($text) |
598 { |
598 { |
599 if ( !preg_match('!(</?(?:ul|ol|li)>)!', $text) ) |
599 if ( !preg_match('!(</?(?:ul|ol|li)>)!', $text) ) |
600 return $text; |
600 return $text; |
601 |
601 |
602 $split = preg_split('!(</?(?:ul|ol|li)>)!', $text, -1, PREG_SPLIT_DELIM_CAPTURE); |
602 $split = preg_split('!(</?(?:ul|ol|li)>)!', $text, -1, PREG_SPLIT_DELIM_CAPTURE); |
603 |
603 |
604 $stack_height = 0; |
604 $stack_height = 0; |
605 $current_list = ''; |
605 $current_list = ''; |
606 $old_current_list = ''; |
606 $old_current_list = ''; |
607 $spaces = ''; |
607 $spaces = ''; |
608 $marker = '*'; |
608 $marker = '*'; |
609 $list_id = 0; |
609 $list_id = 0; |
610 $just_terminated = false; |
610 $just_terminated = false; |
611 foreach ( $split as $tag ) |
611 foreach ( $split as $tag ) |
612 { |
612 { |
613 switch($tag) |
613 switch($tag) |
614 { |
614 { |
615 case '<ul>': |
615 case '<ul>': |
616 case '<ol>': |
616 case '<ol>': |
617 $stack_height++; |
617 $stack_height++; |
618 $just_terminated = false; |
618 $just_terminated = false; |
619 if ( $stack_height > 1 ) |
619 if ( $stack_height > 1 ) |
620 $spaces .= $marker; |
620 $spaces .= $marker; |
621 |
621 |
622 $marker = ( $tag == 'ol' ) ? '#' : '*'; |
622 $marker = ( $tag == 'ol' ) ? '#' : '*'; |
623 if ( $stack_height > 1 ) |
623 if ( $stack_height > 1 ) |
624 $current_list .= "\n"; |
624 $current_list .= "\n"; |
625 |
625 |
626 break; |
626 break; |
627 case '</ul>': |
627 case '</ul>': |
628 case '</ol>': |
628 case '</ol>': |
629 $stack_height--; |
629 $stack_height--; |
630 $spaces = substr($spaces, 1); |
630 $spaces = substr($spaces, 1); |
631 |
631 |
632 if ( $stack_height == 0 ) |
632 if ( $stack_height == 0 ) |
633 { |
633 { |
634 // rotate |
634 // rotate |
635 $text = str_replace_once("{$old_current_list}{$tag}", trim($current_list), $text); |
635 $text = str_replace_once("{$old_current_list}{$tag}", trim($current_list), $text); |
636 $current_list = ''; |
636 $current_list = ''; |
637 $old_current_list = ''; |
637 $old_current_list = ''; |
638 } |
638 } |
639 $just_terminated = true; |
639 $just_terminated = true; |
640 break; |
640 break; |
641 case '<li>': |
641 case '<li>': |
642 if ( $stack_height < 1 ) |
642 if ( $stack_height < 1 ) |
643 break; |
643 break; |
644 |
644 |
645 $current_list .= "{$spaces}{$marker} "; |
645 $current_list .= "{$spaces}{$marker} "; |
646 break; |
646 break; |
647 case '</li>': |
647 case '</li>': |
648 if ( $stack_height < 1 ) |
648 if ( $stack_height < 1 ) |
649 break; |
649 break; |
650 |
650 |
651 if ( !$just_terminated ) |
651 if ( !$just_terminated ) |
652 $current_list .= "\n"; |
652 $current_list .= "\n"; |
653 |
653 |
654 $just_terminated = false; |
654 $just_terminated = false; |
655 break; |
655 break; |
656 default: |
656 default: |
657 if ( $stack_height > 0 ) |
657 if ( $stack_height > 0 ) |
658 { |
658 { |
659 $current_list .= trim($tag); |
659 $current_list .= trim($tag); |
660 } |
660 } |
661 break; |
661 break; |
662 } |
662 } |
663 if ( $stack_height > 0 ) |
663 if ( $stack_height > 0 ) |
664 { |
664 { |
665 $old_current_list .= $tag; |
665 $old_current_list .= $tag; |
666 } |
666 } |
667 } |
667 } |
668 |
668 |
669 return $text; |
669 return $text; |
670 } |
670 } |
671 |
671 |
672 public static function reverse_process_tables($text) |
672 public static function reverse_process_tables($text) |
673 { |
673 { |
674 return $text; |
674 return $text; |
675 } |
675 } |
676 |
676 |
677 /** |
677 /** |
678 * Parses internal links (wikilinks) in a block of text. |
678 * Parses internal links (wikilinks) in a block of text. |
679 * @param string Text to process |
679 * @param string Text to process |
680 * @param string Optional. If included will be used as a template instead of using the default syntax. |
680 * @param string Optional. If included will be used as a template instead of using the default syntax. |
681 * @param bool If false, does not add wikilink-nonexistent or check for exsistence of pages. Can reduce DB queries; defualts to true. |
681 * @param bool If false, does not add wikilink-nonexistent or check for exsistence of pages. Can reduce DB queries; defualts to true. |
682 * @param string Page ID. If specified, class="currentpage" will be added to links if they match the given page ID and namespace |
682 * @param string Page ID. If specified, class="currentpage" will be added to links if they match the given page ID and namespace |
683 * @param string Namespace. If specified, class="currentpage" will be added to links if they match the given page ID and namespace |
683 * @param string Namespace. If specified, class="currentpage" will be added to links if they match the given page ID and namespace |
684 * @return string |
684 * @return string |
685 */ |
685 */ |
686 |
686 |
687 public static function parse_internal_links($text, $tplcode = false, $do_exist_check = true, $match_page_id = false, $match_namespace = false) |
687 public static function parse_internal_links($text, $tplcode = false, $do_exist_check = true, $match_page_id = false, $match_namespace = false) |
688 { |
688 { |
689 global $db, $session, $paths, $template, $plugins; // Common objects |
689 global $db, $session, $paths, $template, $plugins; // Common objects |
690 |
690 |
691 $parser = is_string($tplcode) ? $template->makeParserText($tplcode) : false; |
691 $parser = is_string($tplcode) ? $template->makeParserText($tplcode) : false; |
692 |
692 |
693 // allow blank urlname? |
693 // allow blank urlname? |
694 $repeater = have_blank_urlname_page() ? '*' : '+'; |
694 $repeater = have_blank_urlname_page() ? '*' : '+'; |
695 |
695 |
696 // stage 1 - links with alternate text |
696 // stage 1 - links with alternate text |
697 preg_match_all('/\[\[([^\[\]<>\{\}\|]' . $repeater . ')\|(.+?)\]\]/', $text, $matches); |
697 preg_match_all('/\[\[([^\[\]<>\{\}\|]' . $repeater . ')\|(.+?)\]\]/', $text, $matches); |
698 foreach ( $matches[0] as $i => $match ) |
698 foreach ( $matches[0] as $i => $match ) |
699 { |
699 { |
700 list($page_id, $namespace) = RenderMan::strToPageID($matches[1][$i]); |
700 list($page_id, $namespace) = RenderMan::strToPageID($matches[1][$i]); |
701 $link = self::generate_internal_link($namespace, $page_id, $matches[2][$i], $match, $parser, $do_exist_check, $match_page_id, $match_namespace); |
701 $link = self::generate_internal_link($namespace, $page_id, $matches[2][$i], $match, $parser, $do_exist_check, $match_page_id, $match_namespace); |
702 $text = str_replace($match, $link, $text); |
702 $text = str_replace($match, $link, $text); |
703 } |
703 } |
704 |
704 |
705 // stage 2 - links with no alternate text |
705 // stage 2 - links with no alternate text |
706 preg_match_all('/\[\[([^\[\]<>\{\}\|]' . $repeater . ')\]\]/', $text, $matches); |
706 preg_match_all('/\[\[([^\[\]<>\{\}\|]' . $repeater . ')\]\]/', $text, $matches); |
707 foreach ( $matches[0] as $i => $match ) |
707 foreach ( $matches[0] as $i => $match ) |
708 { |
708 { |
709 list($page_id, $namespace) = RenderMan::strToPageID($matches[1][$i]); |
709 list($page_id, $namespace) = RenderMan::strToPageID($matches[1][$i]); |
710 $pid_clean = $paths->nslist[$namespace] . sanitize_page_id($page_id); |
710 $pid_clean = $paths->nslist[$namespace] . sanitize_page_id($page_id); |
711 $inner_text = ( isPage($pid_clean) ) ? htmlspecialchars(get_page_title($pid_clean)) : htmlspecialchars($matches[1][$i]); |
711 $inner_text = ( isPage($pid_clean) ) ? htmlspecialchars(get_page_title($pid_clean)) : htmlspecialchars($matches[1][$i]); |
712 |
712 |
713 $link = self::generate_internal_link($namespace, $page_id, $inner_text, $match, $parser, $do_exist_check, $match_page_id, $match_namespace); |
713 $link = self::generate_internal_link($namespace, $page_id, $inner_text, $match, $parser, $do_exist_check, $match_page_id, $match_namespace); |
714 |
714 |
715 $text = str_replace($match, $link, $text); |
715 $text = str_replace($match, $link, $text); |
716 } |
716 } |
717 |
717 |
718 return $text; |
718 return $text; |
719 } |
719 } |
720 |
720 |
721 /** |
721 /** |
722 * Internal link generation function |
722 * Internal link generation function |
723 * @access private |
723 * @access private |
724 * @return string HTML |
724 * @return string HTML |
725 */ |
725 */ |
726 |
726 |
727 private static function generate_internal_link($namespace, $page_id, $inner_text, $match, $parser = false, $do_exist_check = true, $match_page_id = false, $match_namespace = false) |
727 private static function generate_internal_link($namespace, $page_id, $inner_text, $match, $parser = false, $do_exist_check = true, $match_page_id = false, $match_namespace = false) |
728 { |
728 { |
729 global $db, $session, $paths, $template, $plugins; // Common objects |
729 global $db, $session, $paths, $template, $plugins; // Common objects |
730 |
730 |
731 if ( ($pos = strrpos($page_id, '#')) !== false ) |
731 if ( ($pos = strrpos($page_id, '#')) !== false ) |
732 { |
732 { |
733 $hash = substr($page_id, $pos); |
733 $hash = substr($page_id, $pos); |
734 $page_id = substr($page_id, 0, $pos); |
734 $page_id = substr($page_id, 0, $pos); |
735 } |
735 } |
736 else |
736 else |
737 { |
737 { |
738 $hash = ''; |
738 $hash = ''; |
739 } |
739 } |
740 |
740 |
741 if ( $namespace == 'Admin' ) |
741 if ( $namespace == 'Admin' ) |
742 { |
742 { |
743 // No linking directly to Admin pages! |
743 // No linking directly to Admin pages! |
744 $get = 'module=' . $paths->nslist[$namespace] . sanitize_page_id($page_id); |
744 $get = 'module=' . $paths->nslist[$namespace] . sanitize_page_id($page_id); |
745 $pid_clean = $paths->nslist['Special'] . 'Administration'; |
745 $pid_clean = $paths->nslist['Special'] . 'Administration'; |
746 $onclick = ' onclick="ajaxLoginNavTo(\'Special\', \'Administration\', USER_LEVEL_ADMIN, \'' . addslashes($get) . '\'); return false;"'; |
746 $onclick = ' onclick="ajaxLoginNavTo(\'Special\', \'Administration\', USER_LEVEL_ADMIN, \'' . addslashes($get) . '\'); return false;"'; |
747 } |
747 } |
748 else |
748 else |
749 { |
749 { |
750 $get = false; |
750 $get = false; |
751 $onclick = ''; |
751 $onclick = ''; |
752 $pid_clean = $paths->nslist[$namespace] . sanitize_page_id($page_id); |
752 $pid_clean = $paths->nslist[$namespace] . sanitize_page_id($page_id); |
753 } |
753 } |
754 |
754 |
755 $url = makeUrl($pid_clean, $get, true) . $hash; |
755 $url = makeUrl($pid_clean, $get, true) . $hash; |
756 $quot = '"'; |
756 $quot = '"'; |
757 $exists = ( ($do_exist_check && isPage($pid_clean)) || !$do_exist_check ) ? '' : ' class="wikilink-nonexistent"'; |
757 $exists = ( ($do_exist_check && isPage($pid_clean)) || !$do_exist_check ) ? '' : ' class="wikilink-nonexistent"'; |
758 |
758 |
759 if ( $match_page_id && $match_namespace && $pid_clean === $paths->get_pathskey($match_page_id, $match_namespace) ) |
759 if ( $match_page_id && $match_namespace && $pid_clean === $paths->get_pathskey($match_page_id, $match_namespace) ) |
760 $exists .= ' class="currentpage"'; |
760 $exists .= ' class="currentpage"'; |
761 |
761 |
762 if ( $parser ) |
762 if ( $parser ) |
763 { |
763 { |
764 $parser->assign_vars(array( |
764 $parser->assign_vars(array( |
765 'HREF' => $url, |
765 'HREF' => $url, |
766 'FLAGS' => $exists, |
766 'FLAGS' => $exists, |
767 'TEXT' => $inner_text |
767 'TEXT' => $inner_text |
768 )); |
768 )); |
769 $link = $parser->run(); |
769 $link = $parser->run(); |
770 } |
770 } |
771 else |
771 else |
772 { |
772 { |
773 $omatch = self::escape_parser_hint_attrib($match); |
773 $omatch = self::escape_parser_hint_attrib($match); |
774 $link = "<!--#internallink src=\"$omatch\" --><a{$onclick} href={$quot}{$url}{$quot}{$exists}>{$inner_text}</a><!--#/internallink-->"; |
774 $link = "<!--#internallink src=\"$omatch\" --><a{$onclick} href={$quot}{$url}{$quot}{$exists}>{$inner_text}</a><!--#/internallink-->"; |
775 } |
775 } |
776 |
776 |
777 return $link; |
777 return $link; |
778 } |
778 } |
779 |
779 |
780 /** |
780 /** |
781 * Parses a partial template tag in wikitext, and return an array with the parameters. |
781 * Parses a partial template tag in wikitext, and return an array with the parameters. |
782 * @param string The portion of the template tag that contains the parameters. |
782 * @param string The portion of the template tag that contains the parameters. |
783 * @example |
783 * @example |
784 * <code> |
784 * <code> |
785 foo = lorem ipsum |
785 foo = lorem ipsum |
786 bar = dolor sit amet |
786 bar = dolor sit amet |
787 * </code> |
787 * </code> |
788 * @return array Example: |
788 * @return array Example: |
789 * [foo] => lorem ipsum |
789 * [foo] => lorem ipsum |
790 * [bar] => dolor sit amet |
790 * [bar] => dolor sit amet |
791 */ |
791 */ |
792 |
792 |
793 public static function parse_template_vars($input, $newlinemode = true) |
793 public static function parse_template_vars($input, $newlinemode = true) |
794 { |
794 { |
795 $parms = array(); |
795 $parms = array(); |
796 $input = trim($input); |
796 $input = trim($input); |
797 if ( $newlinemode ) |
797 if ( $newlinemode ) |
798 { |
798 { |
799 // we're going by newlines. |
799 // we're going by newlines. |
800 // split by parameter, then parse each one individually |
800 // split by parameter, then parse each one individually |
801 $input = explode("\n", str_replace("\r", '', $input)); |
801 $input = explode("\n", str_replace("\r", '', $input)); |
802 $lastparam = ''; |
802 $lastparam = ''; |
803 $i = 0; |
803 $i = 0; |
804 foreach ( $input as $line ) |
804 foreach ( $input as $line ) |
805 { |
805 { |
806 if ( preg_match('/^ *\|? *([A-z0-9_]+) *= *(.+)$/', $line, $match) ) |
806 if ( preg_match('/^ *\|? *([A-z0-9_]+) *= *(.+)$/', $line, $match) ) |
807 { |
807 { |
808 // new parameter, named |
808 // new parameter, named |
809 $parms[ $match[1] ] = $match[2]; |
809 $parms[ $match[1] ] = $match[2]; |
810 $lastparam = $match[1]; |
810 $lastparam = $match[1]; |
811 } |
811 } |
812 else if ( preg_match('/^ *\| *(.+)$/', $line, $match) || $lastparam === '' ) |
812 else if ( preg_match('/^ *\| *(.+)$/', $line, $match) || $lastparam === '' ) |
813 { |
813 { |
814 $parms[ $i ] = $match[1]; |
814 $parms[ $i ] = $match[1]; |
815 $lastparam = $i; |
815 $lastparam = $i; |
816 $i++; |
816 $i++; |
817 } |
817 } |
818 else |
818 else |
819 { |
819 { |
820 $parms[ $lastparam ] .= "\n$line"; |
820 $parms[ $lastparam ] .= "\n$line"; |
821 } |
821 } |
822 } |
822 } |
823 } |
823 } |
824 else |
824 else |
825 { |
825 { |
826 $result = preg_match_all('/ |
826 $result = preg_match_all('/ |
827 (?:^|[ ]*)\| # start of parameter - string start or series of spaces |
827 (?:^|[ ]*)\| # start of parameter - string start or series of spaces |
828 [ ]* |
828 [ ]* |
829 (?: |
829 (?: |
830 ([A-z0-9_]+) # variable name |
830 ([A-z0-9_]+) # variable name |
831 [ ]* = [ ]* # assignment |
831 [ ]* = [ ]* # assignment |
832 )? # name section is optional - if the parameter name is not given, a numerical index is assigned |
832 )? # name section is optional - if the parameter name is not given, a numerical index is assigned |
833 ([^\|]+|.+?\n[ ]*\|) # value |
833 ([^\|]+|.+?\n[ ]*\|) # value |
834 /x', trim($input), $matches); |
834 /x', trim($input), $matches); |
835 if ( $result ) |
835 if ( $result ) |
836 { |
836 { |
837 $pi = 0; |
837 $pi = 0; |
838 for ( $i = 0; $i < count($matches[0]); $i++ ) |
838 for ( $i = 0; $i < count($matches[0]); $i++ ) |
839 { |
839 { |
840 $matches[1][$i] = trim($matches[1][$i]); |
840 $matches[1][$i] = trim($matches[1][$i]); |
841 $parmname = !empty($matches[1][$i]) ? $matches[1][$i] : strval(++$pi); |
841 $parmname = !empty($matches[1][$i]) ? $matches[1][$i] : strval(++$pi); |
842 $parms[ $parmname ] = $matches[2][$i]; |
842 $parms[ $parmname ] = $matches[2][$i]; |
843 } |
843 } |
844 } |
844 } |
845 } |
845 } |
846 // die('<pre>' . print_r($parms, true) . '</pre>'); |
846 // die('<pre>' . print_r($parms, true) . '</pre>'); |
847 return $parms; |
847 return $parms; |
848 } |
848 } |
849 |
849 |
850 /** |
850 /** |
851 * Processes all template tags within a block of wikitext. |
851 * Processes all template tags within a block of wikitext. |
852 * Updated in 1.0.2 to also parse template tags in the format of {{Foo |a = b |b = c |c = therefore, a}} |
852 * Updated in 1.0.2 to also parse template tags in the format of {{Foo |a = b |b = c |c = therefore, a}} |
853 * @param string The text to process |
853 * @param string The text to process |
854 * @return string Formatted text |
854 * @return string Formatted text |
855 * @example |
855 * @example |
856 * <code> |
856 * <code> |
857 $text = '{{Template |
857 $text = '{{Template |
858 | parm1 = Foo |
858 | parm1 = Foo |
859 | parm2 = Bar |
859 | parm2 = Bar |
860 }}'; |
860 }}'; |
861 $text = RenderMan::include_templates($text); |
861 $text = RenderMan::include_templates($text); |
862 * </code> |
862 * </code> |
863 */ |
863 */ |
864 |
864 |
865 public static function include_templates($text) |
865 public static function include_templates($text) |
866 { |
866 { |
867 global $db, $session, $paths, $template, $plugins; // Common objects |
867 global $db, $session, $paths, $template, $plugins; // Common objects |
868 // $template_regex = "/\{\{([^\]]+?)((\n([ ]*?)[A-z0-9]+([ ]*?)=([ ]*?)(.+?))*)\}\}/is"; |
868 // $template_regex = "/\{\{([^\]]+?)((\n([ ]*?)[A-z0-9]+([ ]*?)=([ ]*?)(.+?))*)\}\}/is"; |
869 // matches: |
869 // matches: |
870 // 1 - template name |
870 // 1 - template name |
871 // 2 - parameter section |
871 // 2 - parameter section |
872 $template_regex = "/ |
872 $template_regex = "/ |
873 \{\{ # opening |
873 \{\{ # opening |
874 ([^\n\t\a\r]+) # template name |
874 ([^\n\t\a\r]+) # template name |
875 ((?:(?:[\s]+\|?)[ ]*(?:[A-z0-9_]+)[ ]*=[ ]*?(?:.+))*) # parameters |
875 ((?:(?:[\s]+\|?)[ ]*(?:[A-z0-9_]+)[ ]*=[ ]*?(?:.+))*) # parameters |
876 \}\} # closing |
876 \}\} # closing |
877 /isxU"; |
877 /isxU"; |
878 if ( $count = preg_match_all($template_regex, $text, $matches) ) |
878 if ( $count = preg_match_all($template_regex, $text, $matches) ) |
879 { |
879 { |
880 // die('<pre>' . print_r($matches, true) . '</pre>'); |
880 // die('<pre>' . print_r($matches, true) . '</pre>'); |
881 for ( $i = 0; $i < $count; $i++ ) |
881 for ( $i = 0; $i < $count; $i++ ) |
882 { |
882 { |
883 $matches[1][$i] = sanitize_page_id($matches[1][$i]); |
883 $matches[1][$i] = sanitize_page_id($matches[1][$i]); |
884 $newlinemode = ( substr($matches[2][$i], 0, 1) == "\n" ); |
884 $newlinemode = ( substr($matches[2][$i], 0, 1) == "\n" ); |
885 $parmsection = trim($matches[2][$i]); |
885 $parmsection = trim($matches[2][$i]); |
886 if ( !empty($parmsection) ) |
886 if ( !empty($parmsection) ) |
887 { |
887 { |
888 $parms = RenderMan::parse_template_vars($parmsection, $newlinemode); |
888 $parms = RenderMan::parse_template_vars($parmsection, $newlinemode); |
889 if ( !is_array($parms) ) |
889 if ( !is_array($parms) ) |
890 // Syntax error |
890 // Syntax error |
891 $parms = array(); |
891 $parms = array(); |
892 } |
892 } |
893 else |
893 else |
894 { |
894 { |
895 $parms = Array(); |
895 $parms = Array(); |
896 } |
896 } |
897 if ( $tpl_code = RenderMan::fetch_template_text($matches[1][$i]) ) |
897 if ( $tpl_code = RenderMan::fetch_template_text($matches[1][$i]) ) |
898 { |
898 { |
899 // Intelligent paragraphs. |
899 // Intelligent paragraphs. |
900 // If: |
900 // If: |
901 // * A line is fully wrapped in a <p> tag |
901 // * A line is fully wrapped in a <p> tag |
902 // * The line contains a variable |
902 // * The line contains a variable |
903 // * The variable contains newlines |
903 // * The variable contains newlines |
904 // Then: |
904 // Then: |
905 // * Drop the <p> tag, replace it fully paragraph-ized by newlines |
905 // * Drop the <p> tag, replace it fully paragraph-ized by newlines |
906 |
906 |
907 if ( preg_match_all('/^( *)<p(\s.+)?>(.*?\{([A-z0-9]+)\}.*?)<\/p> *$/m', $tpl_code, $paramatch) ) |
907 if ( preg_match_all('/^( *)<p(\s.+)?>(.*?\{([A-z0-9]+)\}.*?)<\/p> *$/m', $tpl_code, $paramatch) ) |
908 { |
908 { |
909 $parser = new Carpenter(); |
909 $parser = new Carpenter(); |
910 $parser->exclusive_rule('paragraph'); |
910 $parser->exclusive_rule('paragraph'); |
911 |
911 |
912 foreach ( $paramatch[0] as $j => $match ) |
912 foreach ( $paramatch[0] as $j => $match ) |
913 { |
913 { |
914 // $line is trimmed (the <p> is gone) |
914 // $line is trimmed (the <p> is gone) |
915 $spacing =& $paramatch[1][$i]; |
915 $spacing =& $paramatch[1][$i]; |
916 $para_attrs =& $paramatch[2][$j]; |
916 $para_attrs =& $paramatch[2][$j]; |
917 $para_attrs = str_replace(array('$', '\\'), array('\$', '\\\\'), $para_attrs); |
917 $para_attrs = str_replace(array('$', '\\'), array('\$', '\\\\'), $para_attrs); |
918 $line =& $paramatch[3][$j]; |
918 $line =& $paramatch[3][$j]; |
919 $varname =& $paramatch[4][$j]; |
919 $varname =& $paramatch[4][$j]; |
920 if ( isset($parms[$varname]) && strstr($parms[$varname], "\n") ) |
920 if ( isset($parms[$varname]) && strstr($parms[$varname], "\n") ) |
921 { |
921 { |
922 $newline = str_replace('{' . $varname . '}', $parms[$varname], $line); |
922 $newline = str_replace('{' . $varname . '}', $parms[$varname], $line); |
923 $paraized = $parser->render($newline); |
923 $paraized = $parser->render($newline); |
924 $paraized = preg_replace('/^<p>/m', "$spacing<p{$para_attrs}>", $paraized); |
924 $paraized = preg_replace('/^<p>/m', "$spacing<p{$para_attrs}>", $paraized); |
925 $paraized = $spacing . trim($paraized); |
925 $paraized = $spacing . trim($paraized); |
926 $tpl_code = str_replace_once($match, $paraized, $tpl_code); |
926 $tpl_code = str_replace_once($match, $paraized, $tpl_code); |
927 } |
927 } |
928 } |
928 } |
929 } |
929 } |
930 |
930 |
931 $parser = $template->makeParserText($tpl_code); |
931 $parser = $template->makeParserText($tpl_code); |
932 $parser->assign_vars($parms); |
932 $parser->assign_vars($parms); |
933 $text = str_replace($matches[0][$i], $parser->run(), $text); |
933 $text = str_replace($matches[0][$i], $parser->run(), $text); |
934 } |
934 } |
935 } |
935 } |
936 } |
936 } |
937 return $text; |
937 return $text; |
938 } |
938 } |
939 |
939 |
940 /** |
940 /** |
941 * Preprocesses an HTML text string prior to being sent to MySQL. |
941 * Preprocesses an HTML text string prior to being sent to MySQL. |
942 * @param string $text |
942 * @param string $text |
943 * @param bool $strip_all_php - if true, strips all PHP regardless of user permissions. Else, strips PHP only if user level < USER_LEVEL_ADMIN. Defaults to true. |
943 * @param bool $strip_all_php - if true, strips all PHP regardless of user permissions. Else, strips PHP only if user level < USER_LEVEL_ADMIN. Defaults to true. |
944 * @param bool $sqlescape - if true, sends text through $db->escape(). Otherwise returns unescaped text. Defaults to true. |
944 * @param bool $sqlescape - if true, sends text through $db->escape(). Otherwise returns unescaped text. Defaults to true. |
945 * @param bool $reduceheadings - if true, finds HTML headings and replaces them with wikitext. Else, does not touch headings. Defaults to true. |
945 * @param bool $reduceheadings - if true, finds HTML headings and replaces them with wikitext. Else, does not touch headings. Defaults to true. |
946 * @param Session_ACLPageInfo Optional permissions instance to check against, $session is used if not provided |
946 * @param Session_ACLPageInfo Optional permissions instance to check against, $session is used if not provided |
947 */ |
947 */ |
948 public static function preprocess_text($text, $strip_all_php = true, $sqlescape = true, $reduceheadings = true, $perms = false) |
948 public static function preprocess_text($text, $strip_all_php = true, $sqlescape = true, $reduceheadings = true, $perms = false) |
949 { |
949 { |
950 global $db, $session, $paths, $template, $plugins; // Common objects |
950 global $db, $session, $paths, $template, $plugins; // Common objects |
951 $random_id = md5( time() . mt_rand() ); |
951 $random_id = md5( time() . mt_rand() ); |
952 |
952 |
953 $code = $plugins->setHook('render_sanitize_pre'); |
953 $code = $plugins->setHook('render_sanitize_pre'); |
954 foreach ( $code as $cmd ) |
954 foreach ( $code as $cmd ) |
955 { |
955 { |
956 eval($cmd); |
956 eval($cmd); |
957 } |
957 } |
958 |
958 |
959 if ( !is_object($perms) ) |
959 if ( !is_object($perms) ) |
960 { |
960 { |
961 $namespace = $paths->namespace; |
961 $namespace = $paths->namespace; |
962 $perms =& $session; |
962 $perms =& $session; |
963 } |
963 } |
964 else |
964 else |
965 { |
965 { |
966 $namespace = $perms->namespace; |
966 $namespace = $perms->namespace; |
967 } |
967 } |
968 |
968 |
969 $can_do_php = ( !$strip_all_php && $perms->get_permissions('php_in_pages') ); |
969 $can_do_php = ( !$strip_all_php && $perms->get_permissions('php_in_pages') ); |
970 $can_do_html = $session->check_acl_scope('html_in_pages', $namespace) && $perms->get_permissions('html_in_pages'); |
970 $can_do_html = $session->check_acl_scope('html_in_pages', $namespace) && $perms->get_permissions('html_in_pages'); |
971 |
971 |
972 if ( $can_do_html && !$can_do_php ) |
972 if ( $can_do_html && !$can_do_php ) |
973 { |
973 { |
974 $text = preg_replace('#<(\?|\?php|%)(.*?)(\?|%)>#is', '<\\1\\2\\3>', $text); |
974 $text = preg_replace('#<(\?|\?php|%)(.*?)(\?|%)>#is', '<\\1\\2\\3>', $text); |
975 } |
975 } |
976 else if ( !$can_do_html && !$can_do_php ) |
976 else if ( !$can_do_html && !$can_do_php ) |
977 { |
977 { |
978 $text = sanitize_html($text, true); |
978 $text = sanitize_html($text, true); |
979 // If we can't do PHP, we can't do Javascript either. |
979 // If we can't do PHP, we can't do Javascript either. |
980 $text = RenderMan::destroy_javascript($text); |
980 $text = RenderMan::destroy_javascript($text); |
981 } |
981 } |
982 |
982 |
983 // Strip out <nowiki> sections and PHP code |
983 // Strip out <nowiki> sections and PHP code |
984 |
984 |
985 $php = preg_match_all('#(<|<)\?php(.*?)\?(>|>)#is', $text, $phpsec); |
985 $php = preg_match_all('#(<|<)\?php(.*?)\?(>|>)#is', $text, $phpsec); |
986 |
986 |
987 //die('<pre>'.htmlspecialchars(print_r($phpsec, true))."\n".htmlspecialchars(print_r($text, true)).'</pre>'); |
987 //die('<pre>'.htmlspecialchars(print_r($phpsec, true))."\n".htmlspecialchars(print_r($text, true)).'</pre>'); |
988 |
988 |
989 for($i=0;$i<sizeof($phpsec[1]);$i++) |
989 for($i=0;$i<sizeof($phpsec[1]);$i++) |
990 { |
990 { |
991 $text = str_replace($phpsec[0][$i], '{PHP:'.$random_id.':'.$i.'}', $text); |
991 $text = str_replace($phpsec[0][$i], '{PHP:'.$random_id.':'.$i.'}', $text); |
992 } |
992 } |
993 |
993 |
994 $nw = preg_match_all('#<nowiki>(.*?)<\/nowiki>#is', $text, $nowiki); |
994 $nw = preg_match_all('#<nowiki>(.*?)<\/nowiki>#is', $text, $nowiki); |
995 |
995 |
996 for($i=0;$i<sizeof($nowiki[1]);$i++) |
996 for($i=0;$i<sizeof($nowiki[1]);$i++) |
997 { |
997 { |
998 $text = str_replace('<nowiki>'.$nowiki[1][$i].'</nowiki>', '{NOWIKI:'.$random_id.':'.$i.'}', $text); |
998 $text = str_replace('<nowiki>'.$nowiki[1][$i].'</nowiki>', '{NOWIKI:'.$random_id.':'.$i.'}', $text); |
999 } |
999 } |
1000 |
1000 |
1001 $text = str_replace('~~~~~', enano_date('G:i, j F Y (T)'), $text); |
1001 $text = str_replace('~~~~~', enano_date('G:i, j F Y (T)'), $text); |
1002 $text = str_replace('~~~~', "[[User:$session->username|$session->username]] ".enano_date('G:i, j F Y (T)'), $text); |
1002 $text = str_replace('~~~~', "[[User:$session->username|$session->username]] ".enano_date('G:i, j F Y (T)'), $text); |
1003 $text = str_replace('~~~', "[[User:$session->username|$session->username]] ", $text); |
1003 $text = str_replace('~~~', "[[User:$session->username|$session->username]] ", $text); |
1004 |
1004 |
1005 $code = $plugins->setHook('render_sanitize_post'); |
1005 $code = $plugins->setHook('render_sanitize_post'); |
1006 foreach ( $code as $cmd ) |
1006 foreach ( $code as $cmd ) |
1007 { |
1007 { |
1008 eval($cmd); |
1008 eval($cmd); |
1009 } |
1009 } |
1010 |
1010 |
1011 // gently apply some reverse-processing to allow the parser to do magic with TOCs and stuff |
1011 // gently apply some reverse-processing to allow the parser to do magic with TOCs and stuff |
1012 if ( $reduceheadings ) |
1012 if ( $reduceheadings ) |
1013 $text = self::reverse_process_headings($text); |
1013 $text = self::reverse_process_headings($text); |
1014 |
1014 |
1015 // Reinsert <nowiki> sections |
1015 // Reinsert <nowiki> sections |
1016 for($i=0;$i<$nw;$i++) |
1016 for($i=0;$i<$nw;$i++) |
1017 { |
1017 { |
1018 $text = str_replace('{NOWIKI:'.$random_id.':'.$i.'}', '<nowiki>'.$nowiki[1][$i].'</nowiki>', $text); |
1018 $text = str_replace('{NOWIKI:'.$random_id.':'.$i.'}', '<nowiki>'.$nowiki[1][$i].'</nowiki>', $text); |
1019 } |
1019 } |
1020 // Reinsert PHP |
1020 // Reinsert PHP |
1021 for($i=0;$i<$php;$i++) |
1021 for($i=0;$i<$php;$i++) |
1022 { |
1022 { |
1023 $phsec = ''.$phpsec[1][$i].'?php'.$phpsec[2][$i].'?'.$phpsec[3][$i].''; |
1023 $phsec = ''.$phpsec[1][$i].'?php'.$phpsec[2][$i].'?'.$phpsec[3][$i].''; |
1024 if ( $strip_all_php ) |
1024 if ( $strip_all_php ) |
1025 $phsec = htmlspecialchars($phsec); |
1025 $phsec = htmlspecialchars($phsec); |
1026 $text = str_replace('{PHP:'.$random_id.':'.$i.'}', $phsec, $text); |
1026 $text = str_replace('{PHP:'.$random_id.':'.$i.'}', $phsec, $text); |
1027 } |
1027 } |
1028 |
1028 |
1029 $text = ( $sqlescape ) ? $db->escape($text) : $text; |
1029 $text = ( $sqlescape ) ? $db->escape($text) : $text; |
1030 |
1030 |
1031 return $text; |
1031 return $text; |
1032 } |
1032 } |
1033 |
1033 |
1034 public static function smilieyize($text, $complete_urls = false) |
1034 public static function smilieyize($text, $complete_urls = false) |
1035 { |
1035 { |
1036 |
1036 |
1037 $random_id = md5( time() . mt_rand() ); |
1037 $random_id = md5( time() . mt_rand() ); |
1038 |
1038 |
1039 // Smileys array - eventually this will be fetched from the database by |
1039 // Smileys array - eventually this will be fetched from the database by |
1040 // RenderMan::initSmileys during initialization, but it will all be hardcoded for beta 2 |
1040 // RenderMan::initSmileys during initialization, but it will all be hardcoded for beta 2 |
1041 |
1041 |
1042 $smileys = Array( |
1042 $smileys = Array( |
1043 'O:-)' => 'face-angel.png', |
1043 'O:-)' => 'face-angel.png', |
1044 'O:)' => 'face-angel.png', |
1044 'O:)' => 'face-angel.png', |
1045 'O=)' => 'face-angel.png', |
1045 'O=)' => 'face-angel.png', |
1046 ':-)' => 'face-smile.png', |
1046 ':-)' => 'face-smile.png', |
1047 ':)' => 'face-smile.png', |
1047 ':)' => 'face-smile.png', |
1048 '=)' => 'face-smile-big.png', |
1048 '=)' => 'face-smile-big.png', |
1049 ':-(' => 'face-sad.png', |
1049 ':-(' => 'face-sad.png', |
1050 ':(' => 'face-sad.png', |
1050 ':(' => 'face-sad.png', |
1051 ';(' => 'face-sad.png', |
1051 ';(' => 'face-sad.png', |
1052 ':-O' => 'face-surprise.png', |
1052 ':-O' => 'face-surprise.png', |
1053 ';-)' => 'face-wink.png', |
1053 ';-)' => 'face-wink.png', |
1054 ';)' => 'face-wink.png', |
1054 ';)' => 'face-wink.png', |
1055 '8-)' => 'face-glasses.png', |
1055 '8-)' => 'face-glasses.png', |
1056 '8)' => 'face-glasses.png', |
1056 '8)' => 'face-glasses.png', |
1057 ':-D' => 'face-grin.png', |
1057 ':-D' => 'face-grin.png', |
1058 ':D' => 'face-grin.png', |
1058 ':D' => 'face-grin.png', |
1059 '=D' => 'face-grin.png', |
1059 '=D' => 'face-grin.png', |
1060 ':-*' => 'face-kiss.png', |
1060 ':-*' => 'face-kiss.png', |
1061 ':*' => 'face-kiss.png', |
1061 ':*' => 'face-kiss.png', |
1062 '=*' => 'face-kiss.png', |
1062 '=*' => 'face-kiss.png', |
1063 ':\'(' => 'face-crying.png', |
1063 ':\'(' => 'face-crying.png', |
1064 ':-|' => 'face-plain.png', |
1064 ':-|' => 'face-plain.png', |
1065 ':-\\' => 'face-plain.png', |
1065 ':-\\' => 'face-plain.png', |
1066 ':-/' => 'face-plain.png', |
1066 ':-/' => 'face-plain.png', |
1067 ':joke:' => 'face-plain.png', |
1067 ':joke:' => 'face-plain.png', |
1068 ']:->' => 'face-devil-grin.png', |
1068 ']:->' => 'face-devil-grin.png', |
1069 ']:->' => 'face-devil-grin.png', |
1069 ']:->' => 'face-devil-grin.png', |
1070 ':kiss:' => 'face-kiss.png', |
1070 ':kiss:' => 'face-kiss.png', |
1071 ':-P' => 'face-tongue-out.png', |
1071 ':-P' => 'face-tongue-out.png', |
1072 ':P' => 'face-tongue-out.png', |
1072 ':P' => 'face-tongue-out.png', |
1073 ':-p' => 'face-tongue-out.png', |
1073 ':-p' => 'face-tongue-out.png', |
1074 ':p' => 'face-tongue-out.png', |
1074 ':p' => 'face-tongue-out.png', |
1075 ':-X' => 'face-sick.png', |
1075 ':-X' => 'face-sick.png', |
1076 ':X' => 'face-sick.png', |
1076 ':X' => 'face-sick.png', |
1077 ':sick:' => 'face-sick.png', |
1077 ':sick:' => 'face-sick.png', |
1078 ':-]' => 'face-oops.png', |
1078 ':-]' => 'face-oops.png', |
1079 ':]' => 'face-oops.png', |
1079 ':]' => 'face-oops.png', |
1080 ':oops:' => 'face-oops.png', |
1080 ':oops:' => 'face-oops.png', |
1081 ':-[' => 'face-embarassed.png', |
1081 ':-[' => 'face-embarassed.png', |
1082 ':[' => 'face-embarassed.png' |
1082 ':[' => 'face-embarassed.png' |
1083 ); |
1083 ); |
1084 |
1084 |
1085 // Strip out <nowiki> sections |
1085 // Strip out <nowiki> sections |
1086 //return '<pre>'.htmlspecialchars($text).'</pre>'; |
1086 //return '<pre>'.htmlspecialchars($text).'</pre>'; |
1087 $nw = preg_match_all('#<nowiki>(.*?)<\/nowiki>#is', $text, $nowiki); |
1087 $nw = preg_match_all('#<nowiki>(.*?)<\/nowiki>#is', $text, $nowiki); |
1088 |
1088 |
1089 for ( $i = 0; $i < count($nowiki[1]); $i++ ) |
1089 for ( $i = 0; $i < count($nowiki[1]); $i++ ) |
1090 { |
1090 { |
1091 $text = str_replace('<nowiki>' . $nowiki[1][$i] . '</nowiki>', '{NOWIKI:'.$random_id.':'.$i.'}', $text); |
1091 $text = str_replace('<nowiki>' . $nowiki[1][$i] . '</nowiki>', '{NOWIKI:'.$random_id.':'.$i.'}', $text); |
1092 } |
1092 } |
1093 |
1093 |
1094 foreach ( $smileys as $smiley => $smiley_path ) |
1094 foreach ( $smileys as $smiley => $smiley_path ) |
1095 { |
1095 { |
1096 $hex_smiley = hexencode($smiley, '&#x', ';'); |
1096 $hex_smiley = hexencode($smiley, '&#x', ';'); |
1097 $pfx = ( $complete_urls ) ? get_server_url() : ''; |
1097 $pfx = ( $complete_urls ) ? get_server_url() : ''; |
1098 $text = str_replace(' ' . $smiley, |
1098 $text = str_replace(' ' . $smiley, |
1099 ' <!--#smiley code="' . self::escape_parser_hint_attrib($smiley) . '"--><nowiki> |
1099 ' <!--#smiley code="' . self::escape_parser_hint_attrib($smiley) . '"--><nowiki> |
1100 <!-- The above is a reverse-parser hint --> |
1100 <!-- The above is a reverse-parser hint --> |
1101 <img title="' . $hex_smiley . '" alt="' . $hex_smiley . '" src="' . $pfx . scriptPath . '/images/smilies/' . $smiley_path . '" |
1101 <img title="' . $hex_smiley . '" alt="' . $hex_smiley . '" src="' . $pfx . scriptPath . '/images/smilies/' . $smiley_path . '" |
1102 style="border: 0;" /> |
1102 style="border: 0;" /> |
1103 </nowiki><!--#/smiley-->', $text); |
1103 </nowiki><!--#/smiley-->', $text); |
1104 } |
1104 } |
1105 //*/ |
1105 //*/ |
1106 |
1106 |
1107 // Reinsert <nowiki> sections |
1107 // Reinsert <nowiki> sections |
1108 for ( $i = 0; $i < $nw; $i++ ) |
1108 for ( $i = 0; $i < $nw; $i++ ) |
1109 { |
1109 { |
1110 $text = str_replace('{NOWIKI:'.$random_id.':'.$i.'}', '<nowiki>'.$nowiki[1][$i].'</nowiki>', $text); |
1110 $text = str_replace('{NOWIKI:'.$random_id.':'.$i.'}', '<nowiki>'.$nowiki[1][$i].'</nowiki>', $text); |
1111 } |
1111 } |
1112 |
1112 |
1113 return $text; |
1113 return $text; |
1114 } |
1114 } |
1115 |
1115 |
1116 /** |
1116 /** |
1117 * Generates a summary of the differences between two texts, and formats it as XHTML. |
1117 * Generates a summary of the differences between two texts, and formats it as XHTML. |
1118 * @param $str1 string the first block of text |
1118 * @param $str1 string the first block of text |
1119 * @param $str2 string the second block of text |
1119 * @param $str2 string the second block of text |
1120 * @return string |
1120 * @return string |
1121 */ |
1121 */ |
1122 public static function diff($str1, $str2) |
1122 public static function diff($str1, $str2) |
1123 { |
1123 { |
1124 global $db, $session, $paths, $template, $plugins; // Common objects |
1124 global $db, $session, $paths, $template, $plugins; // Common objects |
1125 require_once(ENANO_ROOT.'/includes/diff.php'); |
1125 require_once(ENANO_ROOT.'/includes/diff.php'); |
1126 $str1 = explode("\n", $str1); |
1126 $str1 = explode("\n", $str1); |
1127 $str2 = explode("\n", $str2); |
1127 $str2 = explode("\n", $str2); |
1128 $diff = new Diff($str1, $str2); |
1128 $diff = new Diff($str1, $str2); |
1129 $renderer = new TableDiffFormatter(); |
1129 $renderer = new TableDiffFormatter(); |
1130 return '<table class="diff">'.$renderer->format($diff).'</table>'; |
1130 return '<table class="diff">'.$renderer->format($diff).'</table>'; |
1131 } |
1131 } |
1132 |
1132 |
1133 /** |
1133 /** |
1134 * Changes wikitext image tags to HTML. |
1134 * Changes wikitext image tags to HTML. |
1135 * @param string The wikitext to process |
1135 * @param string The wikitext to process |
1136 * @param array Will be overwritten with the list of HTML tags (the system uses tokens for TextWiki compatibility) |
1136 * @param array Will be overwritten with the list of HTML tags (the system uses tokens for TextWiki compatibility) |
1137 * @return string |
1137 * @return string |
1138 */ |
1138 */ |
1139 |
1139 |
1140 public static function process_image_tags($text, &$taglist) |
1140 public static function process_image_tags($text, &$taglist) |
1141 { |
1141 { |
1142 global $db, $session, $paths, $template, $plugins; // Common objects |
1142 global $db, $session, $paths, $template, $plugins; // Common objects |
1143 |
1143 |
1144 $s_delim = "\xFF"; |
1144 $s_delim = "\xFF"; |
1145 $f_delim = "\xFF"; |
1145 $f_delim = "\xFF"; |
1146 $taglist = array(); |
1146 $taglist = array(); |
1147 |
1147 |
1148 // Wicked huh? |
1148 // Wicked huh? |
1149 $ns_file = str_replace('/', '\\/', preg_quote($paths->nslist['File'])); |
1149 $ns_file = str_replace('/', '\\/', preg_quote($paths->nslist['File'])); |
1150 $regex = '/ |
1150 $regex = '/ |
1151 \[\[ # starting delimiter |
1151 \[\[ # starting delimiter |
1152 :' . $ns_file . '([\w\s0-9_\(\)!@%\^\+\|\.-]+?\.(?:png|gif|jpg|jpeg)) # image filename |
1152 :' . $ns_file . '([\w\s0-9_\(\)!@%\^\+\|\.-]+?\.(?:png|gif|jpg|jpeg)) # image filename |
1153 (?:(?:\|(?:.+?))*) # parameters |
1153 (?:(?:\|(?:.+?))*) # parameters |
1154 \]\] # ending delimiter |
1154 \]\] # ending delimiter |
1155 /ix'; |
1155 /ix'; |
1156 |
1156 |
1157 preg_match_all($regex, $text, $matches); |
1157 preg_match_all($regex, $text, $matches); |
1158 |
1158 |
1159 foreach ( $matches[0] as $i => $match ) |
1159 foreach ( $matches[0] as $i => $match ) |
1160 { |
1160 { |
1161 |
1161 |
1162 $full_tag =& $matches[0][$i]; |
1162 $full_tag =& $matches[0][$i]; |
1163 $filename =& $matches[1][$i]; |
1163 $filename =& $matches[1][$i]; |
1164 |
1164 |
1165 // apply recursion (hack? @todo could this be done with (?R) in PCRE?) |
1165 // apply recursion (hack? @todo could this be done with (?R) in PCRE?) |
1166 $tag_pos = strpos($text, $full_tag); |
1166 $tag_pos = strpos($text, $full_tag); |
1167 $tag_end_pos = $tag_pos + strlen($full_tag); |
1167 $tag_end_pos = $tag_pos + strlen($full_tag); |
1168 while ( get_char_count($full_tag, ']') < get_char_count($full_tag, '[') && $tag_end_pos < strlen($text) ) |
1168 while ( get_char_count($full_tag, ']') < get_char_count($full_tag, '[') && $tag_end_pos < strlen($text) ) |
1169 { |
1169 { |
1170 $full_tag .= substr($text, $tag_end_pos, 1); |
1170 $full_tag .= substr($text, $tag_end_pos, 1); |
1171 $tag_end_pos++; |
1171 $tag_end_pos++; |
1172 } |
1172 } |
1173 if ( $tag_end_pos > strlen($text) ) |
1173 if ( $tag_end_pos > strlen($text) ) |
1174 { |
1174 { |
1175 // discard tag, not closed fully |
1175 // discard tag, not closed fully |
1176 continue; |
1176 continue; |
1177 } |
1177 } |
1178 |
1178 |
1179 // init the various image parameters |
1179 // init the various image parameters |
1180 $width = null; |
1180 $width = null; |
1181 $height = null; |
1181 $height = null; |
1182 $scale_type = null; |
1182 $scale_type = null; |
1183 $raw_display = false; |
1183 $raw_display = false; |
1184 $clear = null; |
1184 $clear = null; |
1185 $caption = null; |
1185 $caption = null; |
1186 |
1186 |
1187 // trim tag and parse particles |
1187 // trim tag and parse particles |
1188 $tag_trim = rtrim(ltrim($full_tag, '['), ']'); |
1188 $tag_trim = rtrim(ltrim($full_tag, '['), ']'); |
1189 // trim off the filename from the start of the tag |
1189 // trim off the filename from the start of the tag |
1190 $filepart_len = 1 + strlen($paths->nslist['File']) + strlen($filename) + 1; |
1190 $filepart_len = 1 + strlen($paths->nslist['File']) + strlen($filename) + 1; |
1191 $tag_trim = substr($tag_trim, $filepart_len); |
1191 $tag_trim = substr($tag_trim, $filepart_len); |
1192 // explode and we should have parameters |
1192 // explode and we should have parameters |
1193 $tag_parts = explode('|', $tag_trim); |
1193 $tag_parts = explode('|', $tag_trim); |
1194 |
1194 |
1195 // for each of the parameters, see if it matches a known option. If so, apply it; |
1195 // for each of the parameters, see if it matches a known option. If so, apply it; |
1196 // otherwise, see if a plugin reserved that parameter and if not treat it as the caption |
1196 // otherwise, see if a plugin reserved that parameter and if not treat it as the caption |
1197 foreach ( $tag_parts as $param ) |
1197 foreach ( $tag_parts as $param ) |
1198 { |
1198 { |
1199 switch($param) |
1199 switch($param) |
1200 { |
1200 { |
1201 case 'left': |
1201 case 'left': |
1202 case 'right': |
1202 case 'right': |
1203 $clear = $param; |
1203 $clear = $param; |
1204 break; |
1204 break; |
1205 case 'thumb': |
1205 case 'thumb': |
1206 $scale_type = 'thumb'; |
1206 $scale_type = 'thumb'; |
1207 break; |
1207 break; |
1208 case 'raw': |
1208 case 'raw': |
1209 $raw_display = true; |
1209 $raw_display = true; |
1210 break; |
1210 break; |
1211 default: |
1211 default: |
1212 // height specification |
1212 // height specification |
1213 if ( preg_match('/^([0-9]+)x([0-9]+)$/', $param, $dims) ) |
1213 if ( preg_match('/^([0-9]+)x([0-9]+)$/', $param, $dims) ) |
1214 { |
1214 { |
1215 $width = intval($dims[1]); |
1215 $width = intval($dims[1]); |
1216 $height = intval($dims[2]); |
1216 $height = intval($dims[2]); |
1217 break; |
1217 break; |
1218 } |
1218 } |
1219 // not the height, so see if a plugin took this over |
1219 // not the height, so see if a plugin took this over |
1220 // this hook requires plugins to return true if they modified anything |
1220 // this hook requires plugins to return true if they modified anything |
1221 $code = $plugins->setHook('img_tag_parse_params'); |
1221 $code = $plugins->setHook('img_tag_parse_params'); |
1222 foreach ( $code as $cmd ) |
1222 foreach ( $code as $cmd ) |
1223 { |
1223 { |
1224 if ( eval($cmd) ) |
1224 if ( eval($cmd) ) |
1225 break 2; |
1225 break 2; |
1226 } |
1226 } |
1227 // we would have broken out by now if a plugin properly handled this, |
1227 // we would have broken out by now if a plugin properly handled this, |
1228 // so just set the caption now. |
1228 // so just set the caption now. |
1229 $caption = $param; |
1229 $caption = $param; |
1230 break; |
1230 break; |
1231 } |
1231 } |
1232 } |
1232 } |
1233 |
1233 |
1234 if ( !isPage( $paths->nslist['File'] . $filename ) ) |
1234 if ( !isPage( $paths->nslist['File'] . $filename ) ) |
1235 { |
1235 { |
1236 $text = str_replace($full_tag, '[[' . $paths->nslist['File'] . $filename . ']]', $text); |
1236 $text = str_replace($full_tag, '[[' . $paths->nslist['File'] . $filename . ']]', $text); |
1237 continue; |
1237 continue; |
1238 } |
1238 } |
1239 |
1239 |
1240 if ( $scale_type == 'thumb' ) |
1240 if ( $scale_type == 'thumb' ) |
1241 { |
1241 { |
1242 $r_width = 225; |
1242 $r_width = 225; |
1243 $r_height = 225; |
1243 $r_height = 225; |
1244 |
1244 |
1245 $url = makeUrlNS('Special', 'DownloadFile/' . $filename, 'preview&width=' . $r_width . '&height=' . $r_height, true); |
1245 $url = makeUrlNS('Special', 'DownloadFile/' . $filename, 'preview&width=' . $r_width . '&height=' . $r_height, true); |
1246 } |
1246 } |
1247 else if ( !empty($width) && !empty($height) ) |
1247 else if ( !empty($width) && !empty($height) ) |
1248 { |
1248 { |
1249 $r_width = $width; |
1249 $r_width = $width; |
1250 $r_height = $height; |
1250 $r_height = $height; |
1251 |
1251 |
1252 $url = makeUrlNS('Special', 'DownloadFile/' . $filename, 'preview&width=' . $r_width . '&height=' . $r_height, true); |
1252 $url = makeUrlNS('Special', 'DownloadFile/' . $filename, 'preview&width=' . $r_width . '&height=' . $r_height, true); |
1253 } |
1253 } |
1254 else |
1254 else |
1255 { |
1255 { |
1256 $url = makeUrlNS('Special', 'DownloadFile/' . $filename); |
1256 $url = makeUrlNS('Special', 'DownloadFile/' . $filename); |
1257 } |
1257 } |
1258 |
1258 |
1259 $img_tag = '<img src="' . $url . '" '; |
1259 $img_tag = '<img src="' . $url . '" '; |
1260 |
1260 |
1261 // if ( isset($r_width) && isset($r_height) && $scale_type != '|thumb' ) |
1261 // if ( isset($r_width) && isset($r_height) && $scale_type != '|thumb' ) |
1262 // { |
1262 // { |
1263 // $img_tag .= 'width="' . $r_width . '" height="' . $r_height . '" '; |
1263 // $img_tag .= 'width="' . $r_width . '" height="' . $r_height . '" '; |
1264 // } |
1264 // } |
1265 |
1265 |
1266 $img_tag .= 'style="border-width: 0px; /* background-color: white; */" '; |
1266 $img_tag .= 'style="border-width: 0px; /* background-color: white; */" '; |
1267 |
1267 |
1268 $code = $plugins->setHook('img_tag_parse_img'); |
1268 $code = $plugins->setHook('img_tag_parse_img'); |
1269 foreach ( $code as $cmd ) |
1269 foreach ( $code as $cmd ) |
1270 { |
1270 { |
1271 eval($cmd); |
1271 eval($cmd); |
1272 } |
1272 } |
1273 |
1273 |
1274 $img_tag .= '/>'; |
1274 $img_tag .= '/>'; |
1275 |
1275 |
1276 $s_full_tag = self::escape_parser_hint_attrib($full_tag); |
1276 $s_full_tag = self::escape_parser_hint_attrib($full_tag); |
1277 $complete_tag = '<!--#imagelink src="' . $s_full_tag . '" -->'; |
1277 $complete_tag = '<!--#imagelink src="' . $s_full_tag . '" -->'; |
1278 |
1278 |
1279 if ( !empty($scale_type) && !$raw_display ) |
1279 if ( !empty($scale_type) && !$raw_display ) |
1280 { |
1280 { |
1281 $complete_tag .= '<div class="thumbnail" '; |
1281 $complete_tag .= '<div class="thumbnail" '; |
1282 $clear_text = ''; |
1282 $clear_text = ''; |
1283 if ( !empty($clear) ) |
1283 if ( !empty($clear) ) |
1284 { |
1284 { |
1285 $side = ( $clear == 'left' ) ? 'left' : 'right'; |
1285 $side = ( $clear == 'left' ) ? 'left' : 'right'; |
1286 $opposite = ( $clear == 'left' ) ? 'right' : 'left'; |
1286 $opposite = ( $clear == 'left' ) ? 'right' : 'left'; |
1287 $clear_text .= "float: $side; margin-$opposite: 20px; width: {$r_width}px;"; |
1287 $clear_text .= "float: $side; margin-$opposite: 20px; width: {$r_width}px;"; |
1288 $complete_tag .= 'style="' . $clear_text . '" '; |
1288 $complete_tag .= 'style="' . $clear_text . '" '; |
1289 } |
1289 } |
1290 $complete_tag .= '>'; |
1290 $complete_tag .= '>'; |
1291 |
1291 |
1292 $complete_tag .= '<a href="' . makeUrlNS('File', $filename) . '" style="display: block;">'; |
1292 $complete_tag .= '<a href="' . makeUrlNS('File', $filename) . '" style="display: block;">'; |
1293 $complete_tag .= $img_tag; |
1293 $complete_tag .= $img_tag; |
1294 $complete_tag .= '</a>'; |
1294 $complete_tag .= '</a>'; |
1295 |
1295 |
1296 $mag_button = '<a href="' . makeUrlNS('File', $filename) . '" style="display: block; float: right; clear: right; margin: 0 0 10px 10px;"><img alt="[ + ]" src="' . scriptPath . '/images/thumbnail.png" style="border-width: 0px;" /></a>'; |
1296 $mag_button = '<a href="' . makeUrlNS('File', $filename) . '" style="display: block; float: right; clear: right; margin: 0 0 10px 10px;"><img alt="[ + ]" src="' . scriptPath . '/images/thumbnail.png" style="border-width: 0px;" /></a>'; |
1297 |
1297 |
1298 if ( !empty($caption) ) |
1298 if ( !empty($caption) ) |
1299 { |
1299 { |
1300 $complete_tag .= $mag_button . $caption; |
1300 $complete_tag .= $mag_button . $caption; |
1301 } |
1301 } |
1302 |
1302 |
1303 $complete_tag .= '</div>'; |
1303 $complete_tag .= '</div>'; |
1304 } |
1304 } |
1305 else if ( $raw_display ) |
1305 else if ( $raw_display ) |
1306 { |
1306 { |
1307 $complete_tag .= "$img_tag"; |
1307 $complete_tag .= "$img_tag"; |
1308 $taglist[$i] = $complete_tag; |
1308 $taglist[$i] = $complete_tag; |
1309 |
1309 |
1310 $repl = "{$s_delim}e_img_{$i}{$f_delim}"; |
1310 $repl = "{$s_delim}e_img_{$i}{$f_delim}"; |
1311 $text = str_replace($full_tag, $repl, $text); |
1311 $text = str_replace($full_tag, $repl, $text); |
1312 continue; |
1312 continue; |
1313 } |
1313 } |
1314 else |
1314 else |
1315 { |
1315 { |
1316 $complete_tag .= '<a href="' . makeUrlNS('File', $filename) . '" style="display: block;"'; |
1316 $complete_tag .= '<a href="' . makeUrlNS('File', $filename) . '" style="display: block;"'; |
1317 $code = $plugins->setHook('img_tag_parse_link'); |
1317 $code = $plugins->setHook('img_tag_parse_link'); |
1318 foreach ( $code as $cmd ) |
1318 foreach ( $code as $cmd ) |
1319 { |
1319 { |
1320 eval($cmd); |
1320 eval($cmd); |
1321 } |
1321 } |
1322 $complete_tag .= '>'; |
1322 $complete_tag .= '>'; |
1323 $complete_tag .= $img_tag; |
1323 $complete_tag .= $img_tag; |
1324 $complete_tag .= '</a>'; |
1324 $complete_tag .= '</a>'; |
1325 } |
1325 } |
1326 |
1326 |
1327 $complete_tag .= "<!--#/imagelink-->"; |
1327 $complete_tag .= "<!--#/imagelink-->"; |
1328 $taglist[$i] = $complete_tag; |
1328 $taglist[$i] = $complete_tag; |
1329 |
1329 |
1330 /* |
1330 /* |
1331 $pos = strpos($text, $full_tag); |
1331 $pos = strpos($text, $full_tag); |
1332 |
1332 |
1333 while(true) |
1333 while(true) |
1334 { |
1334 { |
1335 $check1 = substr($text, $pos, 3); |
1335 $check1 = substr($text, $pos, 3); |
1336 $check2 = substr($text, $pos, 1); |
1336 $check2 = substr($text, $pos, 1); |
1337 if ( $check1 == '<p>' || $pos == 0 || $check2 == "\n" ) |
1337 if ( $check1 == '<p>' || $pos == 0 || $check2 == "\n" ) |
1338 { |
1338 { |
1339 // die('found at pos '.$pos); |
1339 // die('found at pos '.$pos); |
1340 break; |
1340 break; |
1341 } |
1341 } |
1342 $pos--; |
1342 $pos--; |
1343 } |
1343 } |
1344 */ |
1344 */ |
1345 |
1345 |
1346 /* |
1346 /* |
1347 $repl = "{$s_delim}e_img_{$i}{$f_delim}"; |
1347 $repl = "{$s_delim}e_img_{$i}{$f_delim}"; |
1348 $text = substr($text, 0, $pos) . $repl . substr($text, $pos); |
1348 $text = substr($text, 0, $pos) . $repl . substr($text, $pos); |
1349 |
1349 |
1350 $text = str_replace($full_tag, '', $text); |
1350 $text = str_replace($full_tag, '', $text); |
1351 */ |
1351 */ |
1352 $text = str_replace_once($full_tag, $complete_tag, $text); |
1352 $text = str_replace_once($full_tag, $complete_tag, $text); |
1353 |
1353 |
1354 unset($full_tag, $filename, $scale_type, $width, $height, $clear, $caption, $r_width, $r_height); |
1354 unset($full_tag, $filename, $scale_type, $width, $height, $clear, $caption, $r_width, $r_height); |
1355 |
1355 |
1356 } |
1356 } |
1357 |
1357 |
1358 // if ( count($matches[0]) > 0 ) |
1358 // if ( count($matches[0]) > 0 ) |
1359 // die('<pre>' . htmlspecialchars($text) . '</pre>'); |
1359 // die('<pre>' . htmlspecialchars($text) . '</pre>'); |
1360 |
1360 |
1361 return $text; |
1361 return $text; |
1362 } |
1362 } |
1363 |
1363 |
1364 /** |
1364 /** |
1365 * Finalizes processing of image tags. |
1365 * Finalizes processing of image tags. |
1366 * @param string The preprocessed text |
1366 * @param string The preprocessed text |
1367 * @param array The list of image tags created by RenderMan::process_image_tags() |
1367 * @param array The list of image tags created by RenderMan::process_image_tags() |
1368 */ |
1368 */ |
1369 |
1369 |
1370 public static function process_imgtags_stage2($text, $taglist) |
1370 public static function process_imgtags_stage2($text, $taglist) |
1371 { |
1371 { |
1372 $s_delim = "\xFF"; |
1372 $s_delim = "\xFF"; |
1373 $f_delim = "\xFF"; |
1373 $f_delim = "\xFF"; |
1374 foreach ( $taglist as $i => $tag ) |
1374 foreach ( $taglist as $i => $tag ) |
1375 { |
1375 { |
1376 $repl = "{$s_delim}e_img_{$i}{$f_delim}"; |
1376 $repl = "{$s_delim}e_img_{$i}{$f_delim}"; |
1377 $text = str_replace($repl, $tag, $text); |
1377 $text = str_replace($repl, $tag, $text); |
1378 } |
1378 } |
1379 return $text; |
1379 return $text; |
1380 } |
1380 } |
1381 |
1381 |
1382 } |
1382 } |
1383 |
1383 |
1384 ?> |
1384 ?> |