]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - wiki_stdlib.php3
New CREDITS file so everybody gets credit for what they did, in classic
[SourceForge/phpwiki.git] / wiki_stdlib.php3
1 <!-- $Id: wiki_stdlib.php3,v 1.20 2000-06-30 01:40:40 wainstead 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
264       $recentchanges = RetrievePage($dbi, "RecentChanges");
265
266       // this shouldn't be necessary, since PhpWiki loads 
267       // default pages if this is a new baby Wiki
268       if ($recentchanges == -1) {
269          $recentchanges = array(); 
270       }
271
272       $now = time();
273       $today = date($dateformat, $now);
274
275       if (date($dateformat, $recentchanges["lastmodified"]) != $today) {
276          $isNewDay = TRUE;
277          $recentchanges["lastmodified"] = $now;
278       } else {
279          $isNewDay = FALSE;
280       }
281
282       $numlines = sizeof($recentchanges["content"]);
283       $newpage = array();
284       $k = 0;
285
286       // scroll through the page to the first date and break
287       // dates are marked with "____" at the beginning of the line
288       for ($i = 0; $i < ($numlines + 1); $i++) {
289          if (preg_match("/^____/",
290                         $recentchanges["content"][$i])) {
291             break;
292          } else {
293             $newpage[$k++] = $recentchanges["content"][$i];
294          }
295       }
296
297       // if it's a new date, insert it, else add the updated page's
298       // name to the array
299
300       if ($isNewDay) {
301          $newpage[$k++] = "____$today\r";
302       } else {
303          $newpage[$k++] = $recentchanges["content"][$i++];
304       }
305       if($isnewpage) {
306          $newpage[$k++] = "\t* [$pagename] (new) ..... $remoteuser\r";
307       } else {
308          $newpage[$k++] = "\t* [$pagename] ..... $remoteuser\r";
309       }
310
311       // copy the rest of the page into the new array
312       $pagename = preg_quote($pagename);
313       for (; $i < ($numlines + 1); $i++) {
314          // skip previous entry for $pagename
315          if (preg_match("/\[$pagename\]/", $recentchanges["content"][$i])) {
316             continue;
317          } else {
318             $newpage[$k++] = $recentchanges["content"][$i];
319          }
320       }
321
322       $recentchanges["content"] = $newpage;
323
324       InsertPage($dbi, "RecentChanges", $recentchanges);
325    }
326
327
328    // for archiving pages to a seperate dbm
329    function SaveCopyToArchive($pagename, $pagehash) {
330       global $ArchiveDataBase;
331
332       $adbi = OpenDataBase($ArchiveDataBase);
333       $newpagename = $pagename;
334       InsertPage($adbi, $newpagename, $pagehash);
335    }
336
337
338    function ParseAndLink($bracketlink) {
339       global $dbi, $AllowedProtocols;
340
341       // $bracketlink will start and end with brackets; in between
342       // will be either a page name, a URL or both seperated by a pipe.
343
344       // strip brackets and leading space
345       preg_match("/(\[\s*)(.+?)(\s*\])/", $bracketlink, $match);
346       $linkdata = $match[2];
347
348       // send back links that are only numbers (they are references)
349       if (preg_match("/^\d+$/", $linkdata)) {
350          return $bracketlink;
351       }
352
353       // send back escaped ([[) bracket sets
354       if (preg_match("/^\[/", $linkdata)) {
355          return htmlspecialchars(substr($bracketlink, 1));
356       }
357
358       // match the contents 
359       preg_match("/([^|]+)(\|)?([^|]+)?/", $linkdata, $matches);
360
361       if (isset($matches[3])) {
362          $URL = trim($matches[3]);
363          $linkname = htmlspecialchars(trim($matches[1]));
364          // assert proper URL's
365          if (preg_match("#^($AllowedProtocols):#", $URL)) {
366             return "<a href=\"$URL\">$linkname</a>";
367          } else {
368             return "<b><u>BAD URL -- links have to start with one of " .                                                "$AllowedProtocols followed by ':'</u></b>";
369          }
370       }
371
372       if (isset($matches[1])) {
373          $linkname = trim($matches[1]);
374          if (IsWikiPage($dbi, $linkname)) {
375             return LinkExistingWikiWord($linkname);
376          } elseif (preg_match("#^($AllowedProtocols):#", $linkname)) {
377             return LinkURL($linkname);
378          } else {
379             return LinkUnknownWikiWord($linkname);
380          }
381       }
382
383       return $bracketlink;
384
385    }
386
387 ?>