]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - wiki_stdlib.php3
fix: UpdateRecentChanges wouldn't delete old entries
[SourceForge/phpwiki.git] / wiki_stdlib.php3
1 <?
2    /*
3       Standard functions for Wiki functionality
4          WikiToolBar() 
5          WikiHeader($pagename) 
6          WikiFooter() 
7          GetCurrentDate()
8          LinkExistingWikiWord($wikiword) 
9          LinkUnknownWikiWord($wikiword) 
10          LinkURL($url)
11          RenderQuickSearch() 
12          RenderFullSearch() 
13          CookSpaces($pagearray) 
14          class Stack
15          SetHTMLOutputMode($newmode, $depth)
16          UpdateRecentChanges($dbi, $pagename) 
17          SaveCopyToArchive($pagename, $pagehash) 
18          ParseAndLink($bracketlink)
19    */
20
21    // render the Wiki toolbar at bottom of page
22    function WikiToolBar() {
23       global $ScriptUrl, $pagename, $pagehash;
24       $enc_name = rawurlencode($pagename);
25
26       $retval  = "<hr>\n" .
27                  "<a href=\"$ScriptUrl?edit=$enc_name\">EditText</a>\n" .
28                  " of this page\n";
29       if (is_array($pagehash)) {
30          $retval .= " (last edited " . $pagehash["date"] . ")\n";
31       }
32       $retval .= "<br>\n" .
33                  "<a href=\"$ScriptUrl?FindPage\">" .
34                  "FindPage</a> by browsing or searching\n";
35       return $retval;
36    }
37
38    // top of page
39    function WikiHeader($pagename) {
40       global $LogoImage, $ScriptUrl;
41       return "<html>\n<head>\n<title>" . htmlspecialchars($pagename) .
42              "</title>\n</head>\n<body>\n";
43    }
44
45    function WikiFooter() {
46       return "</body>\n</html>\n";
47    }
48
49    function GetCurrentDate() {
50       // format is like December 13, 1999
51       return date("F j, Y");
52    }
53    
54
55    function LinkExistingWikiWord($wikiword) {
56       global $ScriptUrl;
57       $enc_word = rawurlencode($wikiword);
58       $wikiword = htmlspecialchars($wikiword);
59       return "<a href=\"$ScriptUrl?$enc_word\">$wikiword</a>";
60    }
61
62    function LinkUnknownWikiWord($wikiword) {
63       global $ScriptUrl;
64       $enc_word = rawurlencode($wikiword);
65       $wikiword = htmlspecialchars($wikiword);
66       return "<u>$wikiword</u><a href=\"$ScriptUrl?edit=$enc_word\">?</a>";
67    }
68
69    function LinkURL($url) {
70       global $ScriptUrl;
71       if(ereg("[<>\"]", $url)) {
72          return "<b><u>BAD URL -- remove all of &lt;, &gt;, &quot;</u></b>";
73       }
74       $enc_url = htmlspecialchars($url);
75       return "<a href=\"$url\">$enc_url</a>";
76    }
77
78    
79    function RenderQuickSearch() {
80       global $value, $ScriptUrl;
81       $formtext = "<form action='$ScriptUrl'>\n<input type='text' size='40' name='search' value='$value'>\n</form>\n";
82       return $formtext;
83    }
84
85    function RenderFullSearch() {
86       global $value, $ScriptUrl;
87       $formtext = "<form action='$ScriptUrl'>\n<input type='text' size='40' name='full' value='$value'>\n</form>\n";
88       return $formtext;
89    }
90
91    // converts spaces to tabs
92    function CookSpaces($pagearray) {
93       return preg_replace("/ {3,8}/", "\t", $pagearray);
94    }
95
96
97    class Stack {
98       var $items;
99       var $size = 0;
100
101       function push($item) {
102          $this->items[$this->size] = $item;
103          $this->size++;
104          return true;
105       }  
106    
107       function pop() {
108          if ($this->size == 0) {
109             return false; // stack is empty
110          }  
111          $this->size--;
112          return $this->items[$this->size];
113       }  
114    
115       function cnt() {
116          return $this->size;
117       }  
118
119       function top() {
120          return $this->items[$this->size - 1];
121       }  
122
123    }  
124    // end class definition
125
126
127    // I couldn't move this to wiki_config.php3 because it 
128    // wasn't declared yet.
129    $stack = new Stack;
130
131    /* 
132       Wiki HTML output can, at any given time, be in only one mode.
133       It will be something like Unordered List, Preformatted Text,
134       plain text etc. When we change modes we have to issue close tags
135       for one mode and start tags for another.
136    */
137
138    function SetHTMLOutputMode($tag, $tagdepth, $tabcount) {
139       global $stack;
140       $retvar = "";
141    
142       if ($tagdepth == SINGLE_DEPTH) {
143    
144          if ($tabcount < $stack->cnt()) {
145    
146             // there are fewer tabs than stack, reduce stack
147             // to one less than tab count; then push new tag
148             while ($stack->cnt() > ($tabcount - 1)) {
149                $closetag = $stack->pop();
150                if ($closetag == false) {
151                   //echo "bounds error in tag stack";
152                   //exit();
153                   break;
154                }
155                #echo "</$closetag>\n";
156                $retvar .= "</$closetag>\n";
157             }
158    
159             #echo "<$tag>\n";
160             $retvar .= "<$tag>\n";
161             $stack->push($tag);
162    
163          } elseif ($tabcount > $stack->cnt()) {
164             // we add the diff to the stack
165             // stack might be zero
166             while ($stack->cnt() < $tabcount) {
167                #echo "<$tag>\n";
168                $retvar .= "<$tag>\n";
169                $stack->push($tag);
170                if ($stack->cnt() > 10) {
171                   // arbitrarily limit tag nesting
172                   echo "Stack bounds exceeded in SetHTMLOutputMode\n";
173                   exit();
174                }
175             }
176    
177          } else {
178             if ($tag == $stack->top()) {
179                return;
180             } else {
181                $closetag = $stack->pop();
182                #echo "</$closetag>\n";
183                #echo "<$tag>\n";
184                $retvar .= "</$closetag>\n";
185                $retvar .= "<$tag>\n";
186                $stack->push($tag);
187             }
188          }
189    
190       } elseif ($tagdepth == ZERO_DEPTH) {
191          // empty the stack for $depth == 0;
192          // what if the stack is empty?
193          if ($tag == $stack->top()) {
194             return;
195          }
196          while ($stack->cnt() > 0) {
197             $closetag = $stack->pop();
198             #echo "</$closetag>\n";
199             $retvar .= "</$closetag>\n";
200          }
201    
202          if ($tag) {
203             #echo "<$tag>\n";
204             $retvar .= "<$tag>\n";
205             $stack->push($tag);
206          }
207    
208       } else {
209          // error
210          echo "Passed bad tag depth value in SetHTMLOutputMode\n";
211          exit();
212       }
213
214       return $retvar;
215
216    }
217    // end SetHTMLOutputMode
218
219
220
221    // The Recent Changes file is solely handled here
222    function UpdateRecentChanges($dbi, $pagename) {
223
224       global $remoteuser; // this is set in the config
225
226       $recentchanges = RetrievePage($dbi, "RecentChanges");
227
228       // this shouldn't be necessary, since PhpWiki loads 
229       // default pages if this is a new baby Wiki
230       if ($recentchanges == -1) {
231          $recentchanges = array(); 
232       }
233
234       $currentdate = GetCurrentDate();
235
236       if ($recentchanges["date"] != $currentdate) {
237          $isNewDay = TRUE;
238          $recentchanges["date"] = $currentdate;
239       } else {
240          $isNewDay = FALSE;
241       }
242
243       $numlines = sizeof($recentchanges["text"]);
244       $newpage = array();
245       $k = 0;
246
247       // scroll through the page to the first date and break
248       for ($i = 0; $i < ($numlines + 1); $i++) {
249          if (preg_match("/^\w\w\w+ \d\d?, \d\d\d\d\r$/",
250                         $recentchanges["text"][$i])) {
251             break;
252          } else {
253             $newpage[$k++] = $recentchanges["text"][$i];
254          }
255       }
256
257       // if it's a new date, insert it, else add the updated page's
258       // name to the array
259
260       if ($isNewDay) {
261          $newpage[$k++] = "$currentdate\r";
262       } else {
263          $newpage[$k++] = $recentchanges["text"][$i++];
264       }
265       $newpage[$k++] = "\t* [$pagename] ..... $remoteuser\r";
266
267       // copy the rest of the page into the new array
268       $pagename = preg_quote($pagename);
269       for (; $i < ($numlines + 1); $i++) {
270          // skip previous entry for $pagename
271          if (preg_match("/\[$pagename\]/", $recentchanges["text"][$i])) {
272             continue;
273          } else {
274             $newpage[$k++] = $recentchanges["text"][$i];
275          }
276       }
277
278       $recentchanges["text"] = $newpage;
279
280       InsertPage($dbi, "RecentChanges", $recentchanges);
281    }
282
283
284    // for archiving pages to a seperate dbm
285    function SaveCopyToArchive($pagename, $pagehash) {
286       global $ArchiveDataBase;
287
288       $adbi = OpenDataBase($ArchiveDataBase);
289       $newpagename = $pagename;
290       InsertPage($adbi, $newpagename, $pagehash);
291    }
292
293
294    function ParseAndLink($bracketlink) {
295       global $dbi, $AllowedProtocols;
296
297       // $bracketlink will start and end with brackets; in between
298       // will be either a page name, a URL or both seperated by a pipe.
299
300       // strip brackets and leading space
301       preg_match("/(\[\s*)(.+?)(\s*\])/", $bracketlink, $match);
302       $linkdata = $match[2];
303
304       // send back links that are only numbers (they are references)
305       if (preg_match("/^\d+$/", $linkdata)) {
306          return $bracketlink;
307       }
308
309       // send back escaped ([[) bracket sets
310       if (preg_match("/^\[/", $linkdata)) {
311          return htmlspecialchars($linkdata) . "]";
312       }
313
314       // match the contents 
315       preg_match("/([^|]+)(\|)?([^|]+)?/", $linkdata, $matches);
316
317       if (isset($matches[3])) {
318          $URL = trim($matches[3]);
319          $linkname = htmlspecialchars(trim($matches[1]));
320          if (preg_match("#^($AllowedProtocols):#", $linkname)) {
321             return "<a href=\"$URL\">$linkname</a>";
322          } else {
323             return "<b><u>BAD URL -- links have to start with one of " .                                   "$AllowedProtocols followed by ':'</u></b>";
324          }
325       }
326
327       if (isset($matches[1])) {
328          $linkname = trim($matches[1]);
329          if (IsWikiPage($dbi, $linkname)) {
330             return LinkExistingWikiWord($linkname);
331          } elseif (preg_match("#^($AllowedProtocols):#", $linkname)) {
332             return LinkURL($linkname);
333          } elseif ($linkname == 'Search') {
334             return RenderQuickSearch();
335          } elseif ($linkname == 'Fullsearch') {
336             return RenderFullSearch();
337          } else {
338             return LinkUnknownWikiWord($linkname);
339          }
340       }
341
342       return $bracketlink;
343
344    }
345
346 ?>