]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - wiki_stdlib.php3
Updated for 1.1.7.
[SourceForge/phpwiki.git] / wiki_stdlib.php3
1 <!-- $Id: wiki_stdlib.php3,v 1.23 2000-07-15 18:06:40 ahollosi Exp $ -->
2 <?
3    /*
4       Standard functions for Wiki functionality
5          GeneratePage($template, $content, $name, $hash)
6          LinkExistingWikiWord($wikiword) 
7          LinkUnknownWikiWord($wikiword) 
8          LinkURL($url)
9          RenderQuickSearch() 
10          RenderFullSearch() 
11          RenderMostPopular()
12          CookSpaces($pagearray) 
13          class Stack
14          SetHTMLOutputMode($newmode, $depth)
15          UpdateRecentChanges($dbi, $pagename, $isnewpage) 
16          SaveCopyToArchive($pagename, $pagehash) 
17          ParseAndLink($bracketlink)
18    */
19
20
21    function GeneratePage($template, $content, $name, $hash)
22    {
23       global $ScriptUrl, $AllowedProtocols, $templates;
24       global $datetimeformat, $dbi, $logo;
25
26       if (!is_array($hash))
27          unset($hash);
28
29       $page = join('', file($templates[$template]));
30       $page = str_replace('###', "#$FieldSeparator#", $page);
31
32       // valid for all pagetypes
33       $page = str_replace("#$FieldSeparator#SCRIPTURL#$FieldSeparator#",
34                         $ScriptUrl, $page);
35       $page = str_replace("#$FieldSeparator#PAGE#$FieldSeparator#",
36                         htmlspecialchars($name), $page);
37       $page = str_replace("#$FieldSeparator#ALLOWEDPROTOCOLS#$FieldSeparator#",
38                         $AllowedProtocols, $page);
39       $page = str_replace("#$FieldSeparator#LOGO#$FieldSeparator#",
40                         $logo, $page);
41
42       // invalid for messages (search results, error messages)
43       if ($template != 'MESSAGE') {
44          $page = str_replace("#$FieldSeparator#PAGEURL#$FieldSeparator#",
45                         rawurlencode($name), $page);
46          $page = str_replace("#$FieldSeparator#LASTMODIFIED#$FieldSeparator#",
47                         date($datetimeformat, $hash['lastmodified']), $page);
48          $page = str_replace("#$FieldSeparator#LASTAUTHOR#$FieldSeparator#",
49                         $hash['author'], $page);
50          $page = str_replace("#$FieldSeparator#VERSION#$FieldSeparator#",
51                         $hash['version'], $page);
52          if (strstr($page, "#$FieldSeparator#HITS#$FieldSeparator#")) {
53             $page = str_replace("#$FieldSeparator#HITS#$FieldSeparator#",
54                         GetHitCount($dbi, $name), $page);
55          }
56       }
57
58       // valid only for EditLinks
59       if ($template == 'EDITLINKS') {
60          for ($i = 1; $i <= NUM_LINKS; $i++)
61             $page = str_replace("#$FieldSeparator#R$i#$FieldSeparator#",
62                         $hash['refs'][$i], $page);
63       }
64
65       if ($hash['copy']) {
66          $page = str_replace("#$FieldSeparator#IFCOPY#$FieldSeparator#",
67                         '', $page);
68       } else {
69          $page = ereg_replace("#$FieldSeparator#IFCOPY#$FieldSeparator#[^\n]*",
70                         '', $page);
71       }
72
73       $page = str_replace("#$FieldSeparator#CONTENT#$FieldSeparator#",
74                         $content, $page);
75       print $page;
76    }
77
78
79    function LinkExistingWikiWord($wikiword) {
80       global $ScriptUrl;
81       $enc_word = rawurlencode($wikiword);
82       $wikiword = htmlspecialchars($wikiword);
83       return "<a href=\"$ScriptUrl?$enc_word\">$wikiword</a>";
84    }
85
86    function LinkUnknownWikiWord($wikiword) {
87       global $ScriptUrl;
88       $enc_word = rawurlencode($wikiword);
89       $wikiword = htmlspecialchars($wikiword);
90       return "<u>$wikiword</u><a href=\"$ScriptUrl?edit=$enc_word\">?</a>";
91    }
92
93    function LinkURL($url) {
94       global $ScriptUrl;
95       if(ereg("[<>\"]", $url)) {
96          return "<b><u>BAD URL -- remove all of &lt;, &gt;, &quot;</u></b>";
97       }
98       $enc_url = htmlspecialchars($url);
99       return "<a href=\"$url\">$enc_url</a>";
100    }
101
102    
103    function RenderQuickSearch() {
104       global $value, $ScriptUrl;
105       $formtext = "<form action='$ScriptUrl'>\n<input type='text' size='40' name='search' value='$value'>\n</form>\n";
106       return $formtext;
107    }
108
109    function RenderFullSearch() {
110       global $value, $ScriptUrl;
111       $formtext = "<form action='$ScriptUrl'>\n<input type='text' size='40' name='full' value='$value'>\n</form>\n";
112       return $formtext;
113    }
114
115    function RenderMostPopular() {
116       global $ScriptUrl, $dbi;
117       
118       $query = InitMostPopular($dbi, 20);
119       $result = "<DL>\n";
120       while ($qhash = MostPopularNextMatch($dbi, $query)) {
121          $result .= "<DD>$qhash[hits] ... " . LinkExistingWikiWord($qhash['pagename']) . "\n";
122       }
123       $result .= "</DL>\n";
124       
125       return $result;
126    }
127
128    // converts spaces to tabs
129    function CookSpaces($pagearray) {
130       return preg_replace("/ {3,8}/", "\t", $pagearray);
131    }
132
133
134    class Stack {
135       var $items;
136       var $size = 0;
137
138       function push($item) {
139          $this->items[$this->size] = $item;
140          $this->size++;
141          return true;
142       }  
143    
144       function pop() {
145          if ($this->size == 0) {
146             return false; // stack is empty
147          }  
148          $this->size--;
149          return $this->items[$this->size];
150       }  
151    
152       function cnt() {
153          return $this->size;
154       }  
155
156       function top() {
157          return $this->items[$this->size - 1];
158       }  
159
160    }  
161    // end class definition
162
163
164    // I couldn't move this to wiki_config.php3 because it 
165    // wasn't declared yet.
166    $stack = new Stack;
167
168    /* 
169       Wiki HTML output can, at any given time, be in only one mode.
170       It will be something like Unordered List, Preformatted Text,
171       plain text etc. When we change modes we have to issue close tags
172       for one mode and start tags for another.
173    */
174
175    function SetHTMLOutputMode($tag, $tagdepth, $tabcount) {
176       global $stack;
177       $retvar = "";
178    
179       if ($tagdepth == SINGLE_DEPTH) {
180          if ($tabcount < $stack->cnt()) {
181             // there are fewer tabs than stack,
182             // reduce stack to that tab count
183             while ($stack->cnt() > $tabcount) {
184                $closetag = $stack->pop();
185                if ($closetag == false) {
186                   //echo "bounds error in tag stack";
187                   break;
188                }
189                $retvar .= "</$closetag>\n";
190             }
191
192             // if list type isn't the same,
193             // back up one more and push new tag
194             if ($tag != $stack->top()) {
195                $closetag = $stack->pop();
196                $retvar .= "</$closetag><$tag>\n";
197                $stack->push($tag);
198             }
199    
200          } elseif ($tabcount > $stack->cnt()) {
201             // we add the diff to the stack
202             // stack might be zero
203             while ($stack->cnt() < $tabcount) {
204                #echo "<$tag>\n";
205                $retvar .= "<$tag>\n";
206                $stack->push($tag);
207                if ($stack->cnt() > 10) {
208                   // arbitrarily limit tag nesting
209                   echo "Stack bounds exceeded in SetHTMLOutputMode\n";
210                   exit();
211                }
212             }
213    
214          } else {
215             if ($tag == $stack->top()) {
216                return;
217             } else {
218                $closetag = $stack->pop();
219                #echo "</$closetag>\n";
220                #echo "<$tag>\n";
221                $retvar .= "</$closetag>\n";
222                $retvar .= "<$tag>\n";
223                $stack->push($tag);
224             }
225          }
226    
227       } elseif ($tagdepth == ZERO_DEPTH) {
228          // empty the stack for $depth == 0;
229          // what if the stack is empty?
230          if ($tag == $stack->top()) {
231             return;
232          }
233          while ($stack->cnt() > 0) {
234             $closetag = $stack->pop();
235             #echo "</$closetag>\n";
236             $retvar .= "</$closetag>\n";
237          }
238    
239          if ($tag) {
240             #echo "<$tag>\n";
241             $retvar .= "<$tag>\n";
242             $stack->push($tag);
243          }
244    
245       } else {
246          // error
247          echo "Passed bad tag depth value in SetHTMLOutputMode\n";
248          exit();
249       }
250
251       return $retvar;
252
253    }
254    // end SetHTMLOutputMode
255
256
257
258    // The Recent Changes file is solely handled here
259    function UpdateRecentChanges($dbi, $pagename, $isnewpage) {
260
261       global $remoteuser; // this is set in the config
262       global $dateformat;
263       global $ScriptUrl;
264
265       $recentchanges = RetrievePage($dbi, "RecentChanges");
266
267       // this shouldn't be necessary, since PhpWiki loads 
268       // default pages if this is a new baby Wiki
269       if ($recentchanges == -1) {
270          $recentchanges = array(); 
271       }
272
273       $now = time();
274       $today = date($dateformat, $now);
275
276       if (date($dateformat, $recentchanges["lastmodified"]) != $today) {
277          $isNewDay = TRUE;
278          $recentchanges["lastmodified"] = $now;
279       } else {
280          $isNewDay = FALSE;
281       }
282
283       $numlines = sizeof($recentchanges["content"]);
284       $newpage = array();
285       $k = 0;
286
287       // scroll through the page to the first date and break
288       // dates are marked with "____" at the beginning of the line
289       for ($i = 0; $i < ($numlines + 1); $i++) {
290          if (preg_match("/^____/",
291                         $recentchanges["content"][$i])) {
292             break;
293          } else {
294             $newpage[$k++] = $recentchanges["content"][$i];
295          }
296       }
297
298       // if it's a new date, insert it, else add the updated page's
299       // name to the array
300
301       if ($isNewDay) {
302          $newpage[$k++] = "____$today\r";
303          $newpage[$k++] = "\r";
304       } else {
305          $newpage[$k++] = $recentchanges["content"][$i++];
306       }
307       if($isnewpage) {
308          $newpage[$k++] = "\t* [$pagename] (new) ..... $remoteuser\r";
309       } else {
310          $diffurl = "$ScriptUrl?diff=" . rawurlencode($pagename);
311          $newpage[$k++] = "\t* [$pagename] ([diff|$diffurl]) ..... $remoteuser\r";
312       }
313
314       // copy the rest of the page into the new array
315       $pagename = preg_quote($pagename);
316       for (; $i < ($numlines + 1); $i++) {
317          // skip previous entry for $pagename
318          if (preg_match("|\[$pagename\]|", $recentchanges["content"][$i])) {
319             continue;
320          } else {
321             $newpage[$k++] = $recentchanges["content"][$i];
322          }
323       }
324
325       $recentchanges["content"] = $newpage;
326
327       InsertPage($dbi, "RecentChanges", $recentchanges);
328    }
329
330
331    // for archiving pages to a seperate dbm
332    function SaveCopyToArchive($pagename, $pagehash) {
333       global $ArchiveDataBase;
334
335       $adbi = OpenDataBase($ArchiveDataBase);
336       $newpagename = $pagename;
337       InsertPage($adbi, $newpagename, $pagehash);
338    }
339
340
341    function ParseAndLink($bracketlink) {
342       global $dbi, $AllowedProtocols;
343
344       // $bracketlink will start and end with brackets; in between
345       // will be either a page name, a URL or both seperated by a pipe.
346
347       // strip brackets and leading space
348       preg_match("/(\[\s*)(.+?)(\s*\])/", $bracketlink, $match);
349       $linkdata = $match[2];
350
351       // send back links that are only numbers (they are references)
352       if (preg_match("/^\d+$/", $linkdata)) {
353          return $bracketlink;
354       }
355
356       // send back escaped ([[) bracket sets
357       if (preg_match("/^\[/", $linkdata)) {
358          return htmlspecialchars(substr($bracketlink, 1));
359       }
360
361       // match the contents 
362       preg_match("/([^|]+)(\|)?([^|]+)?/", $linkdata, $matches);
363
364       if (isset($matches[3])) {
365          $URL = trim($matches[3]);
366          $linkname = htmlspecialchars(trim($matches[1]));
367          // assert proper URL's
368          if (preg_match("#^($AllowedProtocols):#", $URL)) {
369             return "<a href=\"$URL\">$linkname</a>";
370          } else {
371             return "<b><u>BAD URL -- links have to start with one of " .                                                "$AllowedProtocols followed by ':'</u></b>";
372          }
373       }
374
375       if (isset($matches[1])) {
376          $linkname = trim($matches[1]);
377          if (IsWikiPage($dbi, $linkname)) {
378             return LinkExistingWikiWord($linkname);
379          } elseif (preg_match("#^($AllowedProtocols):#", $linkname)) {
380             return LinkURL($linkname);
381          } else {
382             return LinkUnknownWikiWord($linkname);
383          }
384       }
385
386       return $bracketlink;
387
388    }
389
390 ?>