Revisão | f88c0de38e1421eccfe624bcd7e8844efa4b517f (tree) |
---|---|
Hora | 2022-01-24 02:04:15 |
Autor | hai-fun <haifun129@gmai...> |
Commiter | hai-fun |
v1.4, author: sonots
@@ -0,0 +1,480 @@ | ||
1 | +<?php | |
2 | +/** | |
3 | + * Replace Page Contents with Regular Expression | |
4 | + * | |
5 | + * @author sonots | |
6 | + * @license http://www.gnu.org/licenses/gpl.html GPL v2 | |
7 | + * @link http://lsx.sourceforge.jp/?Plugin%2Fregexp.inc.php | |
8 | + * @version $Id: regexp.inc.php,v 1.4 2008-07-20 07:23:17Z sonots $ | |
9 | + * @package plugin | |
10 | + */ | |
11 | + | |
12 | +class PluginRegexp | |
13 | +{ | |
14 | + function PluginRegexp() | |
15 | + { | |
16 | + // modify here for default values | |
17 | + static $conf = array( | |
18 | + 'ignore_freeze' => TRUE, | |
19 | + 'adminonly' => TRUE, | |
20 | + ); | |
21 | + static $default_options = array( | |
22 | + 'pcmd' => '', | |
23 | + 'pass' => '', | |
24 | + 'filter' => '', | |
25 | + 'except' => '', | |
26 | + 'page' => '', | |
27 | + 'search' => '', | |
28 | + 'replace' => '', | |
29 | + 'regexp' => TRUE, | |
30 | + 'msearch' => '', | |
31 | + 'mreplace' => '', | |
32 | + 'notimestamp' => TRUE, | |
33 | + ); | |
34 | + $this->conf = & $conf; | |
35 | + $this->default_options = & $default_options; | |
36 | + | |
37 | + // init | |
38 | + $this->options = $this->default_options; | |
39 | + $this->view = new PluginRegexpView($this); | |
40 | + } | |
41 | + | |
42 | + // static | |
43 | + var $conf; | |
44 | + var $default_values; | |
45 | + // var | |
46 | + var $error = ''; | |
47 | + var $plugin = 'regexp'; | |
48 | + var $options = array(); | |
49 | + var $view; | |
50 | + var $preg_replace; | |
51 | + var $str_replace; | |
52 | + | |
53 | + function action() | |
54 | + { | |
55 | + set_time_limit(0); | |
56 | + global $vars; | |
57 | + foreach ($this->options as $key => $val) { | |
58 | + $this->options[$key] = isset($vars[$key]) ? $vars[$key] : ''; | |
59 | + } | |
60 | + foreach ($this->options as $key => $val) { | |
61 | + ${$key} = $val; | |
62 | + } | |
63 | + if ($pcmd == '') { | |
64 | + $body = $this->view->showform(); | |
65 | + } elseif ($search == '' && $msearch == '') { | |
66 | + $body = $this->view->showform('No search.'); | |
67 | + } elseif (! $this->view->login()) { // auth::check_role('role_adm_contents') | |
68 | + $body = $this->view->showform('The password is wrong.'); | |
69 | + } elseif ($pcmd == 'preview') { | |
70 | + $body = $this->do_preview(); | |
71 | + } elseif ($pcmd == 'replace') { | |
72 | + $pages = $this->do_replace_all(); | |
73 | + $body = $this->view->result($pages); | |
74 | + } | |
75 | + return array('msg'=>$this->plugin, 'body'=>$body); | |
76 | + } | |
77 | + | |
78 | + function do_preview() | |
79 | + { | |
80 | + foreach ($this->options as $key => $val) { | |
81 | + ${$key} = $val; | |
82 | + } | |
83 | + $diff = ''; | |
84 | + $pages = $this->get_pages($filter, $except, $page); | |
85 | + foreach ($pages as $apage) { | |
86 | + $replaced = $this->replace($apage, $search, $replace, $msearch, $mreplace, $regexp); | |
87 | + if (is_null($replaced)) continue; | |
88 | + $source = implode("", get_source($apage)); | |
89 | + $diff = do_diff($source, $replaced); | |
90 | + break; | |
91 | + } | |
92 | + $body = $this->view->preview($apage, $diff, $pages); | |
93 | + return $body; | |
94 | + } | |
95 | + | |
96 | + | |
97 | + function do_replace_all() | |
98 | + { | |
99 | + foreach ($this->options as $key => $val) { | |
100 | + ${$key} = $val; | |
101 | + } | |
102 | + $pages = $this->get_pages($filter, $except, $page); | |
103 | + $replaced_pages = array(); | |
104 | + foreach ($pages as $apage) { | |
105 | + $replaced = $this->replace($apage, $search, $replace, $msearch, $mreplace, $regexp); | |
106 | + if (is_null($replaced)) continue; | |
107 | + $GLOBALS['cycle'] = 0; | |
108 | + page_write($apage, $replaced, $notimestamp); | |
109 | + $replaced_pages[] = $apage; | |
110 | + } | |
111 | + return $replaced_pages; | |
112 | + } | |
113 | + | |
114 | + /** | |
115 | + * Replace contents of a page | |
116 | + * | |
117 | + * @param string $page | |
118 | + * @param string $search | |
119 | + * @param string $replace | |
120 | + * @param string $msearch multiline search | |
121 | + * @param string $mreplace | |
122 | + * @param boolean $regexp | |
123 | + * @param string|null replaced contents. null if no replace occurred | |
124 | + */ | |
125 | + function replace($page, $search, $replace, $msearch, $mreplace, $regexp = TRUE) | |
126 | + { | |
127 | + if (! $this->is_editable($page)) return null; | |
128 | + if ($regexp) { | |
129 | + // mb_preg_replace usually does not exist. | |
130 | + $replace_func = function_exists('mb_preg_replace') ? 'mb_preg_replace' : 'preg_replace'; | |
131 | + if ($msearch != '') $msearch = '/' . str_replace('/', '\/', $msearch) . '/D'; | |
132 | + // Memo: refer http://us.php.net/manual/ja/reference.pcre.pattern.modifiers.php for D. | |
133 | + if ($search != '') $search = '/' . str_replace('/', '\/', $search) . '/'; | |
134 | + } else { | |
135 | + // mb_str_replace usually does not exist. | |
136 | + $replace_func = function_exists('mb_str_replace') ? 'mb_str_replace' : 'str_replace'; | |
137 | + } | |
138 | + $lines = get_source($page); | |
139 | + $source = implode("", $lines); | |
140 | + if ($msearch != '') { | |
141 | + $msearch = str_replace("\r", "\n", str_replace("\r\n", "\n", $msearch)); | |
142 | + $replace = call_user_func($replace_func, $msearch, $mreplace, $source); | |
143 | + } elseif ($search != '') { | |
144 | + $replace_lines = array(); | |
145 | + foreach ($lines as $line) { | |
146 | + $line = rtrim($line, "\n"); | |
147 | + $replace_lines[] = call_user_func($replace_func, $search, $replace, $line) . "\n"; | |
148 | + } | |
149 | + $replace = implode("", $replace_lines); | |
150 | + } | |
151 | + if ($source == $replace) return null; | |
152 | + return $replace; | |
153 | + } | |
154 | + | |
155 | + /** | |
156 | + * Get filtered pages (not all existpages) | |
157 | + * | |
158 | + * @param string $filter regexp filter | |
159 | + * @param string $except regexp except filter | |
160 | + * @param string $onepage one exact page name | |
161 | + */ | |
162 | + function get_pages($filter = '', $except = '', $onepage = '') | |
163 | + { | |
164 | + if (! empty($onepage)) { | |
165 | + return (array)$onepage; | |
166 | + } | |
167 | + if (method_exists('auth', 'get_existpages')) { // plus! | |
168 | + $pages = auth::get_existpages(); | |
169 | + } else { | |
170 | + $pages = get_existpages(); | |
171 | + } | |
172 | + if (! empty($filter)) { | |
173 | + $pregfilter = '/' . str_replace('/', '\/', $filter) . '/'; | |
174 | + foreach($pages as $file => $page) { | |
175 | + if (! preg_match($pregfilter, $page)) { | |
176 | + unset($pages[$file]); | |
177 | + } | |
178 | + } | |
179 | + } | |
180 | + if (! empty($except)) { | |
181 | + $pregexcept = '/' . str_replace('/', '\/', $except) . '/'; | |
182 | + foreach($pages as $file => $page) { | |
183 | + if (preg_match($pregexcept, $page)) { | |
184 | + unset($pages[$file]); | |
185 | + } | |
186 | + } | |
187 | + } | |
188 | + return $pages; | |
189 | + } | |
190 | + | |
191 | + /** | |
192 | + * Check if the page is editable or not | |
193 | + * | |
194 | + * PukiWIki API Extension | |
195 | + * | |
196 | + * @param string $page | |
197 | + * @return boolean | |
198 | + */ | |
199 | + function is_editable($page) | |
200 | + { | |
201 | + global $cantedit; | |
202 | + if ($this->conf['ignore_freeze']) { | |
203 | + $editable = ! in_array($page, $cantedit); | |
204 | + } else { | |
205 | + $editable = (! is_freeze($page) and ! in_array($page, $cantedit) ); | |
206 | + } | |
207 | + return $editable; | |
208 | + } | |
209 | +} | |
210 | + | |
211 | +////////////////////////////////// | |
212 | +class PluginRegexpView | |
213 | +{ | |
214 | + // static | |
215 | + var $msg; | |
216 | + // var | |
217 | + var $plugin = 'regexp'; | |
218 | + var $options; | |
219 | + var $conf; | |
220 | + var $model; | |
221 | + | |
222 | + function PluginRegexpView(&$model) | |
223 | + { | |
224 | + static $msg = array(); | |
225 | + if (empty($msg)) { | |
226 | + $msg = array( | |
227 | + 'label' => array( | |
228 | + 'pass' => _('Admin Password'), | |
229 | + 'filter' => _('Filter Pages'), | |
230 | + 'except' => _('Except Pages'), | |
231 | + 'page' => _('A Page'), | |
232 | + 'search' => _('Search'), | |
233 | + 'replace' => _('Replace'), | |
234 | + 'msearch' => _('Multiline Search'), | |
235 | + 'mreplace' => _('Multiline Replace'), | |
236 | + 'regexp' => _('Regexp'), | |
237 | + 'notimestamp' => _('notimestamp'), | |
238 | + 'preview' => _('Preview'), | |
239 | + ), | |
240 | + 'text' => array( | |
241 | + 'pass' => '', | |
242 | + 'filter' => 'Filter pages to be processed by regular expression. <br />Ex) "^PukiWiki" => all pages starting with "PukiWiki."', | |
243 | + 'except' => 'Except pages by regular expression.', | |
244 | + 'page' => 'Specify a page to be processed. If this field is specified, "Filter Pages" is ignored.', | |
245 | + 'search' => 'The string to be replaced. Apply replacing strings to each line separately. ', | |
246 | + 'replace' => 'Ex) Search ^#ls\((.*)\)$ => Replace #lsx(\1). <br />Ex) Search &mimetex\(((?:[^;]|[^)];)*)\); => Replace $ \1 $. (with regexp check)', | |
247 | + 'msearch' => 'The multi-line strings to be replaced. Apply replacing strings to whole contents at one time. Use this when you want to include returns or line feeds. If this field is specified, "Search" is ignored. ', | |
248 | + 'mreplace' => '', | |
249 | + 'regexp' => 'Use regular expression for searching.', | |
250 | + 'notimestamp' => 'Do not change timestamps.', | |
251 | + 'preview' => '', | |
252 | + ), | |
253 | + ); | |
254 | + } | |
255 | + | |
256 | + $this->msg = &$msg; | |
257 | + $this->model = &$model; | |
258 | + $this->options = &$model->options; | |
259 | + $this->conf = &$model->conf; | |
260 | + } | |
261 | + | |
262 | + function login() | |
263 | + { | |
264 | + if ($this->conf['adminonly'] === FALSE) return TRUE; | |
265 | + global $vars; | |
266 | + $pass = isset($vars['pass']) ? $vars['pass'] : $this->getcookie('pass'); | |
267 | + if (pkwk_login($pass)) { | |
268 | + $this->setcookie('pass', $pass); | |
269 | + return TRUE; | |
270 | + } else { | |
271 | + return FALSE; | |
272 | + } | |
273 | + } | |
274 | + | |
275 | + /** | |
276 | + * Get cookie | |
277 | + * | |
278 | + * @param string $key | |
279 | + * @return mixed | |
280 | + */ | |
281 | + function getcookie($key) | |
282 | + { | |
283 | + $key = 'plugin_regexp_' . $key; | |
284 | + return isset($_COOKIE[$key]) ? unserialize($_COOKIE[$key]) : null; | |
285 | + } | |
286 | + | |
287 | + /** | |
288 | + * Set cookie | |
289 | + * | |
290 | + * @param string $key | |
291 | + * @param mixed $val | |
292 | + * @return void | |
293 | + */ | |
294 | + function setcookie($key, $val) | |
295 | + { | |
296 | + global $script; | |
297 | + $parsed = parse_url($script); | |
298 | + $path = $this->get_dirname($parsed['path']); | |
299 | + $key = 'plugin_regexp_' . $key; | |
300 | + setcookie($key, serialize($val), 0, $path); | |
301 | + $_COOKIE[$key] = serialize($val); | |
302 | + } | |
303 | + | |
304 | + function result($pages) | |
305 | + { | |
306 | + $links = array(); | |
307 | + foreach ($pages as $page) { | |
308 | + $links[] = make_pagelink($page); | |
309 | + } | |
310 | + $msg = implode("<br />\n", $links); | |
311 | + $body = '<p>The following pages were replaced.</p><div>' . $msg . '</div>'; | |
312 | + return $body; | |
313 | + } | |
314 | + | |
315 | + function preview($page, $diff, $pages) | |
316 | + { | |
317 | + global $script; | |
318 | + if ($page == '' || $diff == '') { | |
319 | + return '<div>No page found or nothing changed.</div>'; | |
320 | + } | |
321 | + unset($this->options['pass']); | |
322 | + unset($this->options['pcmd']); | |
323 | + foreach ($this->options as $key => $val) { | |
324 | + $this->setcookie($key, $val); | |
325 | + } | |
326 | + | |
327 | + $msg = '<div>A preview, <b>' . htmlspecialchars($page) . '</b></div>'; | |
328 | + //$diff = '<pre>' . htmlspecialchars($diff) . '</pre>'; | |
329 | + $msg .= '<pre>' . diff_style_to_css(htmlspecialchars($diff)) . '</pre>'; // Pukiwiki API | |
330 | + | |
331 | + $msg .= '<div>List of target pages (Result of Filter Pages) </div>'; | |
332 | + $msg .= '<ul>'; | |
333 | + foreach ($pages as $apage) { | |
334 | + $msg .= '<li>' . make_pagelink($apage) . '</li>'; | |
335 | + } | |
336 | + $msg .= '</ul>'; | |
337 | + | |
338 | + $form = array(); | |
339 | + $form[] = '<form action="' . $script . '?cmd=' . $this->plugin . '" method="post">'; | |
340 | + $form[] = '<div>'; | |
341 | + $form[] = ' Do you want to replace all pages? '; | |
342 | + $form[] = ' <input type="hidden" name="cmd" value="regexp" />'; | |
343 | + $form[] = ' <input type="hidden" name="pcmd" value="replace" />'; | |
344 | + foreach ($this->options as $key => $val) { | |
345 | + $form[] = ' <input type="hidden" name="' . $key . '" value="' . $val . '" />'; | |
346 | + } | |
347 | + $form[] = ' <input type="submit" name="ok" value="Yes" /><br />'; | |
348 | + $form[] = '</div>'; | |
349 | + $form[] = '</form>'; | |
350 | + $form = implode("\n", $form); | |
351 | + return $msg . $form; | |
352 | + } | |
353 | + | |
354 | + /** | |
355 | + * Show form | |
356 | + * | |
357 | + * @param string $msg | |
358 | + * @return string html | |
359 | + */ | |
360 | + function showform($msg = "") | |
361 | + { | |
362 | + global $script; | |
363 | + foreach ($this->options as $key => $val) { | |
364 | + ${$key} = $this->getcookie($key); | |
365 | + if (is_null(${$key})) ${$key} = $val; | |
366 | + } | |
367 | + $regexp = ($regexp == 'on') ? ' checked="checked"' : ''; | |
368 | + $notimestamp = ($notimestamp == 'on') ? ' checked="checked"' : ''; | |
369 | + | |
370 | + $form = array(); | |
371 | + $form[] = '<form action="' . $script . '?cmd=' . $this->plugin . '" method="post">'; | |
372 | + $form[] = '<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody>'; | |
373 | + if ($this->conf['adminonly']) { | |
374 | + $form[] = '<tr><td class="style_td">' . $this->msg['label']['pass'] . | |
375 | + '</td><td class="style_td"><input type="password" name="pass" size="24" value="' . $pass . '" />' . | |
376 | + '</td><td class="style_td">' . $this->msg['text']['pass'] . '</td></tr>'; | |
377 | + } | |
378 | + $form[] = '<tr><td class="style_td">' . $this->msg['label']['filter'] . | |
379 | + '</td><td class="style_td"><input type="text" name="filter" size="42" value="' . $filter . '" />' . | |
380 | + '</td><td class="style_td">' . $this->msg['text']['filter'] . '</td></tr>'; | |
381 | + $form[] = '<tr><td class="style_td">' . $this->msg['label']['except'] . | |
382 | + '</td><td class="style_td"><input type="text" name="except" size="42" value="' . $except . '" />' . | |
383 | + '</td><td class="style_td">' . $this->msg['text']['except'] . '</td></tr>'; | |
384 | + $form[] = '<tr><td class="style_td">' . $this->msg['label']['page'] . | |
385 | + '</td><td class="style_td"><input type="text" name="page" size="42" value="' . $page . '" />' . | |
386 | + '</td><td class="style_td">' . $this->msg['text']['page'] . '</td></tr>'; | |
387 | + $form[] = '<tr><td class="style_td"><label for="regexp">' . $this->msg['label']['regexp'] . '</label>' . | |
388 | + '</td><td class="style_td"><input type="checkbox" name="regexp" id="regexp" value="on"' . $regexp . '/>' . | |
389 | + '</td><td class="style_td">' . $this->msg['text']['regexp'] . '</td></tr>'; | |
390 | + $form[] = '<tr><td class="style_td">' . $this->msg['label']['search'] . | |
391 | + '</td><td class="style_td"><input type="text" name="search" size="42" value="' . $search . '" />' . | |
392 | + '</td><td class="style_td">' . $this->msg['text']['search'] . '</td></tr>'; | |
393 | + $form[] = '<tr><td class="style_td">' . $this->msg['label']['replace'] . | |
394 | + '</td><td class="style_td"><input type="text" name="replace" size="42" value="' . $replace . '" />' . | |
395 | + '</td><td class="style_td">' . $this->msg['text']['replace'] . '</td></tr>'; | |
396 | + $form[] = '<tr><td class="style_td">' . $this->msg['label']['msearch'] . | |
397 | + '</td><td class="style_td"><textarea name="msearch" rows="3" cols="40">' . $msearch . '</textarea>' . | |
398 | + '</td><td class="style_td">' . $this->msg['text']['msearch'] . '</td></tr>'; | |
399 | + $form[] = '<tr><td class="style_td">' . $this->msg['label']['mreplace'] . | |
400 | + '</td><td class="style_td"><textarea name="mreplace" rows="3" cols="40">' . $mreplace . '</textarea>' . | |
401 | + '</td><td class="style_td">' . $this->msg['text']['mreplace'] . '</td></tr>'; | |
402 | + $form[] = '<tr><td class="style_td"><label for="notimestamp">' . $this->msg['label']['notimestamp'] . '</label>' . | |
403 | + '</td><td class="style_td"><input type="checkbox" name="notimestamp" id="notimestamp" value="on"' . $notimestamp . '/>' . | |
404 | + '</td><td class="style_td">' . $this->msg['text']['notimestamp'] . '</td></tr>'; | |
405 | + $form[] = '</tbody></table></div>'; | |
406 | + $form[] = '<div>'; | |
407 | + $form[] = ' <input type="hidden" name="cmd" value="regexp" />'; | |
408 | + $form[] = ' <input type="hidden" name="pcmd" value="preview" />'; | |
409 | + $form[] = ' <input type="submit" name="submit" id="preview" value="' . $this->msg['label']['preview'] . '" />'; | |
410 | + $form[] = '</div>'; | |
411 | + $form[] = '</form>'; | |
412 | + $form = implode("\n", $form); | |
413 | + | |
414 | + if ($msg != '') { | |
415 | + $msg = '<p><b>' . $msg . '</b></p>'; | |
416 | + } | |
417 | + return $msg . $form; | |
418 | + } | |
419 | + /** | |
420 | + * Get the dirname of a path | |
421 | + * | |
422 | + * PHP API Extension | |
423 | + * | |
424 | + * PHP's dirname works as | |
425 | + * <code> | |
426 | + * 'Page/' => '.', 'Page/a' => 'Page', 'Page' => '.' | |
427 | + * </code> | |
428 | + * This function works as | |
429 | + * <code> | |
430 | + * 'Page/' => 'Page', 'Page/a' => 'Page', 'Page' => '' | |
431 | + * </code> | |
432 | + * | |
433 | + * @access public | |
434 | + * @static | |
435 | + * @param string $path | |
436 | + * @return string dirname | |
437 | + * @version $Id: v 1.0 2008-06-05 11:14:46 sonots $ | |
438 | + */ | |
439 | + function get_dirname($path) | |
440 | + { | |
441 | + if (($pos = strrpos($path, '/')) !== false) { | |
442 | + return substr($path, 0, $pos); | |
443 | + } else { | |
444 | + return ''; | |
445 | + } | |
446 | + } | |
447 | +} | |
448 | + | |
449 | +// php extension | |
450 | +if (! function_exists('_')) { | |
451 | + function &_($str) | |
452 | + { | |
453 | + return $str; | |
454 | + } | |
455 | +} | |
456 | + | |
457 | +////////////////////////////////// | |
458 | +function plugin_regexp_init() | |
459 | +{ | |
460 | + global $plugin_regexp_name; | |
461 | + if (class_exists('PluginRegexpUnitTest')) { | |
462 | + $plugin_regexp_name = 'PluginRegexpUnitTest'; | |
463 | + } elseif (class_exists('PluginRegexpUser')) { | |
464 | + $plugin_regexp_name = 'PluginRegexpUser'; | |
465 | + } else { | |
466 | + $plugin_regexp_name = 'PluginRegexp'; | |
467 | + } | |
468 | +} | |
469 | +function plugin_regexp_action() | |
470 | +{ | |
471 | + global $plugin_regexp, $plugin_regexp_name; | |
472 | + $plugin_regexp = new $plugin_regexp_name(); | |
473 | + return call_user_func(array(&$plugin_regexp, 'action')); | |
474 | +} | |
475 | + | |
476 | +if (! defined('INIT_DIR')) // if not Plus! | |
477 | + if (file_exists(DATA_HOME . 'init/regexp.ini.php')) | |
478 | + include_once(DATA_HOME . 'init/regexp.ini.php'); | |
479 | + | |
480 | +?> |