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