1 <!-- $Id: wiki_stdlib.php3,v 1.14 2000-06-18 15:12:13 ahollosi Exp $ -->
4 Standard functions for Wiki functionality
5 GeneratePage($template, $content, $name, $hash)
7 LinkExistingWikiWord($wikiword)
8 LinkUnknownWikiWord($wikiword)
12 CookSpaces($pagearray)
14 SetHTMLOutputMode($newmode, $depth)
15 UpdateRecentChanges($dbi, $pagename, $isnewpage)
16 SaveCopyToArchive($pagename, $pagehash)
17 ParseAndLink($bracketlink)
21 function GeneratePage($template, $content, $name, $hash)
23 global $ScriptUrl, $AllowedProtocols, $templates;
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 $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);
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#",
59 $page = str_replace("#$FieldSeparator#IFCOPY#$FieldSeparator#",
62 $page = ereg_replace("#$FieldSeparator#IFCOPY#$FieldSeparator#[^\n]*",
66 $page = str_replace("#$FieldSeparator#CONTENT#$FieldSeparator#",
72 function GetCurrentDate() {
73 // format is like December 13, 1999
74 return date("F j, Y");
78 function LinkExistingWikiWord($wikiword) {
80 $enc_word = rawurlencode($wikiword);
81 $wikiword = htmlspecialchars($wikiword);
82 return "<a href=\"$ScriptUrl?$enc_word\">$wikiword</a>";
85 function LinkUnknownWikiWord($wikiword) {
87 $enc_word = rawurlencode($wikiword);
88 $wikiword = htmlspecialchars($wikiword);
89 return "<u>$wikiword</u><a href=\"$ScriptUrl?edit=$enc_word\">?</a>";
92 function LinkURL($url) {
94 if(ereg("[<>\"]", $url)) {
95 return "<b><u>BAD URL -- remove all of <, >, "</u></b>";
97 $enc_url = htmlspecialchars($url);
98 return "<a href=\"$url\">$enc_url</a>";
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";
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";
114 // converts spaces to tabs
115 function CookSpaces($pagearray) {
116 return preg_replace("/ {3,8}/", "\t", $pagearray);
124 function push($item) {
125 $this->items[$this->size] = $item;
131 if ($this->size == 0) {
132 return false; // stack is empty
135 return $this->items[$this->size];
143 return $this->items[$this->size - 1];
147 // end class definition
150 // I couldn't move this to wiki_config.php3 because it
151 // wasn't declared yet.
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.
161 function SetHTMLOutputMode($tag, $tagdepth, $tabcount) {
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";
175 $retvar .= "</$closetag>\n";
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";
186 } elseif ($tabcount > $stack->cnt()) {
187 // we add the diff to the stack
188 // stack might be zero
189 while ($stack->cnt() < $tabcount) {
191 $retvar .= "<$tag>\n";
193 if ($stack->cnt() > 10) {
194 // arbitrarily limit tag nesting
195 echo "Stack bounds exceeded in SetHTMLOutputMode\n";
201 if ($tag == $stack->top()) {
204 $closetag = $stack->pop();
205 #echo "</$closetag>\n";
207 $retvar .= "</$closetag>\n";
208 $retvar .= "<$tag>\n";
213 } elseif ($tagdepth == ZERO_DEPTH) {
214 // empty the stack for $depth == 0;
215 // what if the stack is empty?
216 if ($tag == $stack->top()) {
219 while ($stack->cnt() > 0) {
220 $closetag = $stack->pop();
221 #echo "</$closetag>\n";
222 $retvar .= "</$closetag>\n";
227 $retvar .= "<$tag>\n";
233 echo "Passed bad tag depth value in SetHTMLOutputMode\n";
240 // end SetHTMLOutputMode
244 // The Recent Changes file is solely handled here
245 function UpdateRecentChanges($dbi, $pagename, $isnewpage) {
247 global $remoteuser; // this is set in the config
249 $recentchanges = RetrievePage($dbi, "RecentChanges");
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();
257 $currentdate = GetCurrentDate();
259 if ($recentchanges["date"] != $currentdate) {
261 $recentchanges["date"] = $currentdate;
266 $numlines = sizeof($recentchanges["content"]);
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])) {
276 $newpage[$k++] = $recentchanges["content"][$i];
280 // if it's a new date, insert it, else add the updated page's
284 $newpage[$k++] = "$currentdate\r";
286 $newpage[$k++] = $recentchanges["content"][$i++];
289 $newpage[$k++] = "\t* [$pagename] (new) ..... $remoteuser\r";
291 $newpage[$k++] = "\t* [$pagename] ..... $remoteuser\r";
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])) {
301 $newpage[$k++] = $recentchanges["content"][$i];
305 $recentchanges["content"] = $newpage;
307 InsertPage($dbi, "RecentChanges", $recentchanges);
311 // for archiving pages to a seperate dbm
312 function SaveCopyToArchive($pagename, $pagehash) {
313 global $ArchiveDataBase;
315 $adbi = OpenDataBase($ArchiveDataBase);
316 $newpagename = $pagename;
317 InsertPage($adbi, $newpagename, $pagehash);
321 function ParseAndLink($bracketlink) {
322 global $dbi, $AllowedProtocols;
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.
327 // strip brackets and leading space
328 preg_match("/(\[\s*)(.+?)(\s*\])/", $bracketlink, $match);
329 $linkdata = $match[2];
331 // send back links that are only numbers (they are references)
332 if (preg_match("/^\d+$/", $linkdata)) {
336 // send back escaped ([[) bracket sets
337 if (preg_match("/^\[/", $linkdata)) {
338 return htmlspecialchars(substr($bracketlink, 1));
341 // match the contents
342 preg_match("/([^|]+)(\|)?([^|]+)?/", $linkdata, $matches);
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>";
351 return "<b><u>BAD URL -- links have to start with one of " . "$AllowedProtocols followed by ':'</u></b>";
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();
366 return LinkUnknownWikiWord($linkname);