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