1 <!-- $Id: wiki_stdlib.php3,v 1.15 2000-06-21 22:57:17 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;
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);
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);
59 $page = str_replace("#$FieldSeparator#IFCOPY#$FieldSeparator#",
62 $page = ereg_replace("#$FieldSeparator#IFCOPY#$FieldSeparator#[^\n]*",
66 $page = str_replace("#$FieldSeparator#CONTENT#$FieldSeparator#",
72 function LinkExistingWikiWord($wikiword) {
74 $enc_word = rawurlencode($wikiword);
75 $wikiword = htmlspecialchars($wikiword);
76 return "<a href=\"$ScriptUrl?$enc_word\">$wikiword</a>";
79 function LinkUnknownWikiWord($wikiword) {
81 $enc_word = rawurlencode($wikiword);
82 $wikiword = htmlspecialchars($wikiword);
83 return "<u>$wikiword</u><a href=\"$ScriptUrl?edit=$enc_word\">?</a>";
86 function LinkURL($url) {
88 if(ereg("[<>\"]", $url)) {
89 return "<b><u>BAD URL -- remove all of <, >, "</u></b>";
91 $enc_url = htmlspecialchars($url);
92 return "<a href=\"$url\">$enc_url</a>";
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";
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";
108 // converts spaces to tabs
109 function CookSpaces($pagearray) {
110 return preg_replace("/ {3,8}/", "\t", $pagearray);
118 function push($item) {
119 $this->items[$this->size] = $item;
125 if ($this->size == 0) {
126 return false; // stack is empty
129 return $this->items[$this->size];
137 return $this->items[$this->size - 1];
141 // end class definition
144 // I couldn't move this to wiki_config.php3 because it
145 // wasn't declared yet.
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.
155 function SetHTMLOutputMode($tag, $tagdepth, $tabcount) {
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";
169 $retvar .= "</$closetag>\n";
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";
180 } elseif ($tabcount > $stack->cnt()) {
181 // we add the diff to the stack
182 // stack might be zero
183 while ($stack->cnt() < $tabcount) {
185 $retvar .= "<$tag>\n";
187 if ($stack->cnt() > 10) {
188 // arbitrarily limit tag nesting
189 echo "Stack bounds exceeded in SetHTMLOutputMode\n";
195 if ($tag == $stack->top()) {
198 $closetag = $stack->pop();
199 #echo "</$closetag>\n";
201 $retvar .= "</$closetag>\n";
202 $retvar .= "<$tag>\n";
207 } elseif ($tagdepth == ZERO_DEPTH) {
208 // empty the stack for $depth == 0;
209 // what if the stack is empty?
210 if ($tag == $stack->top()) {
213 while ($stack->cnt() > 0) {
214 $closetag = $stack->pop();
215 #echo "</$closetag>\n";
216 $retvar .= "</$closetag>\n";
221 $retvar .= "<$tag>\n";
227 echo "Passed bad tag depth value in SetHTMLOutputMode\n";
234 // end SetHTMLOutputMode
238 // The Recent Changes file is solely handled here
239 function UpdateRecentChanges($dbi, $pagename, $isnewpage) {
241 global $remoteuser; // this is set in the config
244 $recentchanges = RetrievePage($dbi, "RecentChanges");
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();
253 $today = date($dateformat, $now);
255 if (date($dateformat, $recentchanges["lastmodified"]) != $today) {
257 $recentchanges["lastmodified"] = $now;
262 $numlines = sizeof($recentchanges["content"]);
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])) {
272 $newpage[$k++] = $recentchanges["content"][$i];
276 // if it's a new date, insert it, else add the updated page's
280 $newpage[$k++] = "$today\r";
282 $newpage[$k++] = $recentchanges["content"][$i++];
285 $newpage[$k++] = "\t* [$pagename] (new) ..... $remoteuser\r";
287 $newpage[$k++] = "\t* [$pagename] ..... $remoteuser\r";
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])) {
297 $newpage[$k++] = $recentchanges["content"][$i];
301 $recentchanges["content"] = $newpage;
303 InsertPage($dbi, "RecentChanges", $recentchanges);
307 // for archiving pages to a seperate dbm
308 function SaveCopyToArchive($pagename, $pagehash) {
309 global $ArchiveDataBase;
311 $adbi = OpenDataBase($ArchiveDataBase);
312 $newpagename = $pagename;
313 InsertPage($adbi, $newpagename, $pagehash);
317 function ParseAndLink($bracketlink) {
318 global $dbi, $AllowedProtocols;
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.
323 // strip brackets and leading space
324 preg_match("/(\[\s*)(.+?)(\s*\])/", $bracketlink, $match);
325 $linkdata = $match[2];
327 // send back links that are only numbers (they are references)
328 if (preg_match("/^\d+$/", $linkdata)) {
332 // send back escaped ([[) bracket sets
333 if (preg_match("/^\[/", $linkdata)) {
334 return htmlspecialchars(substr($bracketlink, 1));
337 // match the contents
338 preg_match("/([^|]+)(\|)?([^|]+)?/", $linkdata, $matches);
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>";
347 return "<b><u>BAD URL -- links have to start with one of " . "$AllowedProtocols followed by ':'</u></b>";
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();
362 return LinkUnknownWikiWord($linkname);