4 This plugin provides a SearchAndReplace dialog page, which allows
5 to grep for pages and to replace content/text using regular expression
6 matching and replacing (as well as ordinary string replacing). It is
7 very powerful, even if the interface and description make it appear
10 Only moderators and superusers can use it ($ewiki_ring level must not
13 WARNING: security leak! moderates may be able to use the /e modifier
14 to execute arbitrary code -- There is now a check for this, which logs
20 $ewiki_plugins["page"]["SearchAndReplace"] = "ewiki_page_searchandreplace";
24 function ewiki_page_searchandreplace($id, $data, $action) {
26 global $ewiki_ring, $ewiki_plugins;
28 $o = ewiki_make_title($id, $id, 2);
30 #-- admin requ. ---------------------------------------------------------
31 if (!ewiki_auth($id,$data,$action, $ring=1, "_FORCE_LOGIN=1") || !isset($ewiki_ring) || ($ewiki_ring > 1)) {
32 if (is_array($data)) {
33 $data = "You'll need moderator/administrator privileges to use this.";
38 #-- form ----------------------------------------------------------------
39 if (empty($_REQUEST["snr_go"]) && empty($_REQUEST["snr_test"])) {
40 $url = ewiki_script("", $id);
42 Use this form to replace all occourences of a phrase in all WikiPages.
44 <form action="$url" method="POST" enctype="multipart/form-data">
45 search for string<br />
46 <input type="text" name="snr_search_string" value="" size="30"><br />
47 <small>this text snippet always matches case-insensitive, used as
48 <b>first-stage</b> search string; leave it empty to use only the regular
49 expression matching (slower)</small><br />
50 look this string up only in <select name="snr_search_string_where"><option selected="selected" value="content">page content / body</option> <option value="id">page name / title</option></select><br />
52 <i>and/or</i> with <tt>/Perl/i</tt> regular expression<br />
53 <input type="text" name="snr_search_regex" value="" size="30"><br />
54 <small>this is <b>optional</b>, and is anyhow only used as second-stage search
55 pattern; if used allows to use regex backreferences in the replacement
56 string field</small><br />
58 then replace with string<br />
59 <input type="text" name="snr_replace" value="" size="30"><br />
60 <small>can contain backreferences \1 and \$1 if the regex search field was
63 <input type="submit" name="snr_test" value="dry run / test regex">
64 <input type="submit" name="snr_go" value="Replace All">
68 The regular expression matching is optional, you'll often only need the
69 simple string search field and another simple string in the replacement
73 Please note, that this form allows to initially search for a simple string,
74 but you can leave this empty and only use a regex search. And as it is a
75 two stage searching, both patterns can be completely different.
78 Text replacement always happens in the WikiPages body, even if the simple
79 search string can be used to search for page names - if you do so, you
80 certainly need a second regular expression pattern for content replacement.
86 $do = $_REQUEST["snr_go"];
89 $search_where = $_REQUEST["snr_search_string_where"];
90 $search_string = $_REQUEST["snr_search_string"];
91 $search_regex = $_REQUEST["snr_search_regex"];
92 $replacement = $_REQUEST["snr_replace"];
93 if ($search_string == "*") {
96 $search_string2 = preg_quote($search_string, "/");
97 $replacement2 = addcslashes($replacement, "\$");
99 #-- security check in search_regex
100 if (preg_match('/([\w\s]+)$/', $search_regex, $uu) && strstr($uu[0],"e")) {
101 ewiki_log("use of regex '$search_regex' could be security circumvention attempt", 1);
102 return($o . "wrong regex delimiter");
106 if (empty($search_string) && empty($search_regex) || empty($replacement)) {
107 return($o . "too few parameters, needs at least one search and a replacement string");
110 #-- initial database string search
111 if (empty($search_string)) {
112 $result = ewiki_db::GETALL(array("id", "version", "flags"));
115 $result = ewiki_db::SEARCH($search_where,$search_string);
118 #-- walk through pages
119 while ($row=$result->get()) {
121 #-- skip binary entries
122 if (EWIKI_DB_F_TEXT != ($row["flags"] & EWIKI_DB_F_TYPE)) {
127 $row = ewiki_db::GET($id);
130 if (!ewiki_auth($id, $row, "edit", ...
135 if (preg_match($search_regex, $row[$search_where], $uu)) {
137 $row["content"] = preg_replace($search_regex, $replacement, $row["content"]);
140 elseif ($search_string) {
141 if (stristr($row[$search_where], $search_string)) {
143 $row["content"] = preg_replace("/$search_string2/i", $replacement, $row["content"]);
148 $o .= "ยท <a href=\"" . ewiki_script("", $id) . "\">" . htmlentities($id)
149 . "</a> matched given search pattern<br />\n";
151 $row["lastmodified"] = time();
152 $row["author"] = ewiki_author("SearchAndReplace");
154 if (ewiki_db::WRITE($row)) {
155 $o .= " changed.<br />\n";
158 $o .= " database store error<br />\n";
159 $o .= " " . mysql_error() . "<br />\n";
167 ewiki_log("SearchAndReplace for '$search_strinmg' and '$search_regex' to replace with '$replacement'");