1 <!-- $Id: wiki_stdlib.php3,v 1.18 2000-06-27 20:00:08 ahollosi Exp $ -->
4 Standard functions for Wiki functionality
5 GeneratePage($template, $content, $name, $hash)
6 LinkExistingWikiWord($wikiword)
7 LinkUnknownWikiWord($wikiword)
11 CookSpaces($pagearray)
13 SetHTMLOutputMode($newmode, $depth)
14 UpdateRecentChanges($dbi, $pagename, $isnewpage)
15 SaveCopyToArchive($pagename, $pagehash)
16 ParseAndLink($bracketlink)
20 function GeneratePage($template, $content, $name, $hash)
22 global $ScriptUrl, $AllowedProtocols, $templates;
23 global $datetimeformat, $dbi;
28 $page = join('', file($templates[$template]));
29 $page = str_replace('###', "#$FieldSeparator#", $page);
31 // valid for all pagetypes
32 $page = str_replace("#$FieldSeparator#SCRIPTURL#$FieldSeparator#",
34 $page = str_replace("#$FieldSeparator#PAGE#$FieldSeparator#",
35 htmlspecialchars($name), $page);
36 $page = str_replace("#$FieldSeparator#ALLOWEDPROTOCOLS#$FieldSeparator#",
37 $AllowedProtocols, $page);
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);
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);
63 $page = str_replace("#$FieldSeparator#IFCOPY#$FieldSeparator#",
66 $page = ereg_replace("#$FieldSeparator#IFCOPY#$FieldSeparator#[^\n]*",
70 $page = str_replace("#$FieldSeparator#CONTENT#$FieldSeparator#",
76 function LinkExistingWikiWord($wikiword) {
78 $enc_word = rawurlencode($wikiword);
79 $wikiword = htmlspecialchars($wikiword);
80 return "<a href=\"$ScriptUrl?$enc_word\">$wikiword</a>";
83 function LinkUnknownWikiWord($wikiword) {
85 $enc_word = rawurlencode($wikiword);
86 $wikiword = htmlspecialchars($wikiword);
87 return "<u>$wikiword</u><a href=\"$ScriptUrl?edit=$enc_word\">?</a>";
90 function LinkURL($url) {
92 if(ereg("[<>\"]", $url)) {
93 return "<b><u>BAD URL -- remove all of <, >, "</u></b>";
95 $enc_url = htmlspecialchars($url);
96 return "<a href=\"$url\">$enc_url</a>";
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";
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";
112 function RenderMostPopular() {
113 global $ScriptUrl, $dbi;
115 $query = InitMostPopular($dbi, 20);
117 while ($qhash = MostPopularNextMatch($dbi, $query)) {
118 $result .= "<DD>$qhash[hits] ... " . LinkExistingWikiWord($qhash['pagename']) . "\n";
120 $result .= "</DL>\n";
125 // converts spaces to tabs
126 function CookSpaces($pagearray) {
127 return preg_replace("/ {3,8}/", "\t", $pagearray);
135 function push($item) {
136 $this->items[$this->size] = $item;
142 if ($this->size == 0) {
143 return false; // stack is empty
146 return $this->items[$this->size];
154 return $this->items[$this->size - 1];
158 // end class definition
161 // I couldn't move this to wiki_config.php3 because it
162 // wasn't declared yet.
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.
172 function SetHTMLOutputMode($tag, $tagdepth, $tabcount) {
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";
186 $retvar .= "</$closetag>\n";
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";
197 } elseif ($tabcount > $stack->cnt()) {
198 // we add the diff to the stack
199 // stack might be zero
200 while ($stack->cnt() < $tabcount) {
202 $retvar .= "<$tag>\n";
204 if ($stack->cnt() > 10) {
205 // arbitrarily limit tag nesting
206 echo "Stack bounds exceeded in SetHTMLOutputMode\n";
212 if ($tag == $stack->top()) {
215 $closetag = $stack->pop();
216 #echo "</$closetag>\n";
218 $retvar .= "</$closetag>\n";
219 $retvar .= "<$tag>\n";
224 } elseif ($tagdepth == ZERO_DEPTH) {
225 // empty the stack for $depth == 0;
226 // what if the stack is empty?
227 if ($tag == $stack->top()) {
230 while ($stack->cnt() > 0) {
231 $closetag = $stack->pop();
232 #echo "</$closetag>\n";
233 $retvar .= "</$closetag>\n";
238 $retvar .= "<$tag>\n";
244 echo "Passed bad tag depth value in SetHTMLOutputMode\n";
251 // end SetHTMLOutputMode
255 // The Recent Changes file is solely handled here
256 function UpdateRecentChanges($dbi, $pagename, $isnewpage) {
258 global $remoteuser; // this is set in the config
261 $recentchanges = RetrievePage($dbi, "RecentChanges");
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();
270 $today = date($dateformat, $now);
272 if (date($dateformat, $recentchanges["lastmodified"]) != $today) {
274 $recentchanges["lastmodified"] = $now;
279 $numlines = sizeof($recentchanges["content"]);
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])) {
290 $newpage[$k++] = $recentchanges["content"][$i];
294 // if it's a new date, insert it, else add the updated page's
298 $newpage[$k++] = "____$today\r";
300 $newpage[$k++] = $recentchanges["content"][$i++];
303 $newpage[$k++] = "\t* [$pagename] (new) ..... $remoteuser\r";
305 $newpage[$k++] = "\t* [$pagename] ..... $remoteuser\r";
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])) {
315 $newpage[$k++] = $recentchanges["content"][$i];
319 $recentchanges["content"] = $newpage;
321 InsertPage($dbi, "RecentChanges", $recentchanges);
325 // for archiving pages to a seperate dbm
326 function SaveCopyToArchive($pagename, $pagehash) {
327 global $ArchiveDataBase;
329 $adbi = OpenDataBase($ArchiveDataBase);
330 $newpagename = $pagename;
331 InsertPage($adbi, $newpagename, $pagehash);
335 function ParseAndLink($bracketlink) {
336 global $dbi, $AllowedProtocols;
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.
341 // strip brackets and leading space
342 preg_match("/(\[\s*)(.+?)(\s*\])/", $bracketlink, $match);
343 $linkdata = $match[2];
345 // send back links that are only numbers (they are references)
346 if (preg_match("/^\d+$/", $linkdata)) {
350 // send back escaped ([[) bracket sets
351 if (preg_match("/^\[/", $linkdata)) {
352 return htmlspecialchars(substr($bracketlink, 1));
355 // match the contents
356 preg_match("/([^|]+)(\|)?([^|]+)?/", $linkdata, $matches);
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>";
365 return "<b><u>BAD URL -- links have to start with one of " . "$AllowedProtocols followed by ':'</u></b>";
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);
376 return LinkUnknownWikiWord($linkname);