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