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