2 rcs_id('$Id: stdlib.php,v 1.16 2000-12-30 21:42:50 ahollosi Exp $');
4 Standard functions for Wiki functionality
5 LinkRelatedPages($dbi, $pagename)
6 GeneratePage($template, $content, $name, $hash)
7 LinkExistingWikiWord($wikiword)
8 LinkUnknownWikiWord($wikiword)
14 CookSpaces($pagearray)
16 SetHTMLOutputMode($newmode, $depth)
17 UpdateRecentChanges($dbi, $pagename, $isnewpage)
18 ParseAndLink($bracketlink)
19 ExtractWikiPageLinks($content)
24 function ExitWiki($errormsg)
29 if($exitwiki) // just in case CloseDataBase calls us
36 print "<P><hr noshade><h2>" . gettext("WikiFatalError") . "</h2>\n";
38 print "\n</BODY></HTML>";
44 function LinkRelatedPages($dbi, $pagename)
46 // currently not supported everywhere
47 if(!function_exists('GetWikiPageLinks'))
50 $links = GetWikiPageLinks($dbi, $pagename);
53 $txt .= sprintf (gettext ("%d best incoming links:"), NUM_RELATED_PAGES);
55 for($i = 0; $i < NUM_RELATED_PAGES; $i++) {
56 if(isset($links['in'][$i])) {
57 list($name, $score) = $links['in'][$i];
58 $txt .= LinkExistingWikiWord($name) . " ($score), ";
63 $txt .= sprintf (gettext ("%d best outgoing links:"), NUM_RELATED_PAGES);
65 for($i = 0; $i < NUM_RELATED_PAGES; $i++) {
66 if(isset($links['out'][$i])) {
67 list($name, $score) = $links['out'][$i];
68 if(IsWikiPage($dbi, $name))
69 $txt .= LinkExistingWikiWord($name) . " ($score), ";
74 $txt .= sprintf (gettext ("%d most popular nearby:"), NUM_RELATED_PAGES);
76 for($i = 0; $i < NUM_RELATED_PAGES; $i++) {
77 if(isset($links['popular'][$i])) {
78 list($name, $score) = $links['popular'][$i];
79 $txt .= LinkExistingWikiWord($name) . " ($score), ";
87 function GeneratePage($template, $content, $name, $hash)
89 global $ScriptUrl, $AllowedProtocols, $templates;
90 global $datetimeformat, $dbi, $logo, $FieldSeparator;
95 function _dotoken ($id, $val, &$page) {
96 global $FieldSeparator;
97 $page = str_replace("$FieldSeparator#$id$FieldSeparator#",
101 function _iftoken ($id, $condition, &$page) {
102 global $FieldSeparator;
104 // line based IF directive
105 $lineyes = "$FieldSeparator#IF $id$FieldSeparator#";
106 $lineno = "$FieldSeparator#IF !$id$FieldSeparator#";
107 // block based IF directive
108 $blockyes = "$FieldSeparator#IF:$id$FieldSeparator#";
109 $blockyesend = "$FieldSeparator#ENDIF:$id$FieldSeparator#";
110 $blockno = "$FieldSeparator#IF:!$id$FieldSeparator#";
111 $blocknoend = "$FieldSeparator#ENDIF:!$id$FieldSeparator#";
114 $page = str_replace($lineyes, '', $page);
115 $page = str_replace($blockyes, '', $page);
116 $page = str_replace($blockyesend, '', $page);
117 $page = preg_replace("/$blockno(.*?)$blocknoend/s", '', $page);
118 $page = ereg_replace("${lineno}[^\n]*\n", '', $page);
120 $page = str_replace($lineno, '', $page);
121 $page = str_replace($blockno, '', $page);
122 $page = str_replace($blocknoend, '', $page);
123 $page = preg_replace("/$blockyes(.*?)$blockyesend/s", '', $page);
124 $page = ereg_replace("${lineyes}[^\n]*\n", '', $page);
128 $page = join('', file($templates[$template]));
129 $page = str_replace('###', "$FieldSeparator#", $page);
131 // valid for all pagetypes
132 _iftoken('COPY', isset($hash['copy']), $page);
133 _iftoken('LOCK', (isset($hash['flags']) &&
134 ($hash['flags'] & FLAG_PAGE_LOCKED)), $page);
135 _iftoken('ADMIN', defined('WIKI_ADMIN'), $page);
137 _dotoken('SCRIPTURL', $ScriptUrl, $page);
138 _dotoken('PAGE', htmlspecialchars($name), $page);
139 _dotoken('ALLOWEDPROTOCOLS', $AllowedProtocols, $page);
140 _dotoken('LOGO', $logo, $page);
142 // invalid for messages (search results, error messages)
143 if ($template != 'MESSAGE') {
144 _dotoken('PAGEURL', rawurlencode($name), $page);
145 _dotoken('LASTMODIFIED',
146 date($datetimeformat, $hash['lastmodified']), $page);
147 _dotoken('LASTAUTHOR', $hash['author'], $page);
148 _dotoken('VERSION', $hash['version'], $page);
149 if (strstr($page, "$FieldSeparator#HITS$FieldSeparator#")) {
150 _dotoken('HITS', GetHitCount($dbi, $name), $page);
152 if (strstr($page, "$FieldSeparator#RELATEDPAGES$FieldSeparator#")) {
153 _dotoken('RELATEDPAGES', LinkRelatedPages($dbi, $name), $page);
157 // valid only for EditLinks
158 if ($template == 'EDITLINKS') {
159 for ($i = 1; $i <= NUM_LINKS; $i++)
160 _dotoken("R$i", $hash['refs'][$i], $page);
163 _dotoken('CONTENT', $content, $page);
168 function LinkExistingWikiWord($wikiword, $linktext='') {
170 $enc_word = rawurlencode($wikiword);
172 $linktext = htmlspecialchars($wikiword);
173 return "<a href=\"$ScriptUrl?$enc_word\">$linktext</a>";
176 function LinkUnknownWikiWord($wikiword, $linktext='') {
178 $enc_word = rawurlencode($wikiword);
180 $linktext = htmlspecialchars($wikiword);
181 return "<u>$linktext</u><a href=\"$ScriptUrl?edit=$enc_word\">?</a>";
184 function LinkURL($url, $linktext='') {
186 if(ereg("[<>\"]", $url)) {
187 return "<b><u>BAD URL -- remove all of <, >, "</u></b>";
191 $linktext = htmlspecialchars($url);
192 return "<a href=\"$url\">$linktext</a>";
196 function LinkImage($url, $alt="[External Image]") {
198 if(ereg("[<>\"]", $url)) {
199 return "<b><u>BAD URL -- remove all of <, >, "</u></b>";
201 return "<img src=\"$url\" ALT=\"$alt\">";
205 function RenderQuickSearch($value = "") {
207 return "<form action=\"$ScriptUrl\">\n" .
208 "<input type=text size=30 name=search value=\"$value\">\n" .
209 "<input type=submit value=\"". gettext("Search") .
213 function RenderFullSearch($value = "") {
215 return "<form action=\"$ScriptUrl\">\n" .
216 "<input type=text size=30 name=full value=\"$value\">\n" .
217 "<input type=submit value=\"". gettext("Search") .
221 function RenderMostPopular() {
222 global $ScriptUrl, $dbi;
224 $query = InitMostPopular($dbi, MOST_POPULAR_LIST_LENGTH);
226 while ($qhash = MostPopularNextMatch($dbi, $query)) {
227 $result .= "<DD>$qhash[hits] ... " . LinkExistingWikiWord($qhash['pagename']) . "\n";
229 $result .= "</DL>\n";
234 function ParseAdminTokens($line) {
237 while (preg_match("/%%ADMIN-INPUT-(.*?)-(\w+)%%/", $line, $matches)) {
238 $head = str_replace("_", " ", $matches[2]);
239 $form = "<FORM ACTION=\"$ScriptUrl\" METHOD=POST>"
240 ."$head: <INPUT NAME=$matches[1] SIZE=20> "
241 ."<INPUT TYPE=SUBMIT VALUE=\"" . gettext("Go") . "\">"
243 $line = str_replace($matches[0], $form, $line);
248 // converts spaces to tabs
249 function CookSpaces($pagearray) {
250 return preg_replace("/ {3,8}/", "\t", $pagearray);
255 var $items = array();
258 function push($item) {
259 $this->items[$this->size] = $item;
265 if ($this->size == 0) {
266 return false; // stack is empty
269 return $this->items[$this->size];
278 return $this->items[$this->size - 1];
284 // end class definition
287 // I couldn't move this to lib/config.php because it
288 // wasn't declared yet.
292 Wiki HTML output can, at any given time, be in only one mode.
293 It will be something like Unordered List, Preformatted Text,
294 plain text etc. When we change modes we have to issue close tags
295 for one mode and start tags for another.
298 function SetHTMLOutputMode($tag, $tagdepth, $tabcount) {
302 if ($tagdepth == SINGLE_DEPTH) {
303 if ($tabcount < $stack->cnt()) {
304 // there are fewer tabs than stack,
305 // reduce stack to that tab count
306 while ($stack->cnt() > $tabcount) {
307 $closetag = $stack->pop();
308 if ($closetag == false) {
309 //echo "bounds error in tag stack";
312 $retvar .= "</$closetag>\n";
315 // if list type isn't the same,
316 // back up one more and push new tag
317 if ($tag != $stack->top()) {
318 $closetag = $stack->pop();
319 $retvar .= "</$closetag><$tag>\n";
323 } elseif ($tabcount > $stack->cnt()) {
324 // we add the diff to the stack
325 // stack might be zero
326 while ($stack->cnt() < $tabcount) {
328 $retvar .= "<$tag>\n";
330 if ($stack->cnt() > 10) {
331 // arbitrarily limit tag nesting
332 ExitWiki(gettext ("Stack bounds exceeded in SetHTMLOutputMode"));
337 if ($tag == $stack->top()) {
340 $closetag = $stack->pop();
341 #echo "</$closetag>\n";
343 $retvar .= "</$closetag>\n";
344 $retvar .= "<$tag>\n";
349 } elseif ($tagdepth == ZERO_DEPTH) {
350 // empty the stack for $depth == 0;
351 // what if the stack is empty?
352 if ($tag == $stack->top()) {
355 while ($stack->cnt() > 0) {
356 $closetag = $stack->pop();
357 #echo "</$closetag>\n";
358 $retvar .= "</$closetag>\n";
363 $retvar .= "<$tag>\n";
369 ExitWiki ("Passed bad tag depth value in SetHTMLOutputMode");
375 // end SetHTMLOutputMode
379 // The Recent Changes file is solely handled here
380 function UpdateRecentChanges($dbi, $pagename, $isnewpage) {
382 global $remoteuser; // this is set in the config
384 global $WikiPageStore;
386 $recentchanges = RetrievePage($dbi, gettext ("RecentChanges"),
389 // this shouldn't be necessary, since PhpWiki loads
390 // default pages if this is a new baby Wiki
391 if ($recentchanges == -1) {
392 $recentchanges = array();
396 $today = date($dateformat, $now);
398 if (date($dateformat, $recentchanges["lastmodified"]) != $today) {
400 $recentchanges["lastmodified"] = $now;
405 $numlines = sizeof($recentchanges["content"]);
409 // scroll through the page to the first date and break
410 // dates are marked with "____" at the beginning of the line
411 for ($i = 0; $i < $numlines; $i++) {
412 if (preg_match("/^____/",
413 $recentchanges["content"][$i])) {
416 $newpage[$k++] = $recentchanges["content"][$i];
420 // if it's a new date, insert it, else add the updated page's
423 $newpage[$k++] = $isNewDay ? "____$today\r"
424 : $recentchanges["content"][$i++];
426 $newpage[$k++] = "* [$pagename] (new) ..... $remoteuser\r";
428 $diffurl = "phpwiki:?diff=" . rawurlencode($pagename);
429 $newpage[$k++] = "* [$pagename] ([diff|$diffurl]) ..... $remoteuser\r";
432 $newpage[$k++] = "\r";
434 // copy the rest of the page into the new array
435 $pagename = preg_quote($pagename);
436 for (; $i < $numlines; $i++) {
437 // skip previous entry for $pagename
438 if (preg_match("|\[$pagename\]|", $recentchanges["content"][$i])) {
441 $newpage[$k++] = $recentchanges["content"][$i];
445 $recentchanges["content"] = $newpage;
447 InsertPage($dbi, gettext ("RecentChanges"), $recentchanges);
452 function ParseAndLink($bracketlink) {
453 global $dbi, $ScriptUrl, $AllowedProtocols, $InlineImages;
455 // $bracketlink will start and end with brackets; in between
456 // will be either a page name, a URL or both separated by a pipe.
458 // strip brackets and leading space
459 preg_match("/(\[\s*)(.+?)(\s*\])/", $bracketlink, $match);
460 // match the contents
461 preg_match("/([^|]+)(\|)?([^|]+)?/", $match[2], $matches);
463 if (isset($matches[3])) {
464 // named link of the form "[some link name | http://blippy.com/]"
465 $URL = trim($matches[3]);
466 $linkname = htmlspecialchars(trim($matches[1]));
469 // unnamed link of the form "[http://blippy.com/] or [wiki page]"
470 $URL = trim($matches[1]);
472 $linktype = 'simple';
475 if (IsWikiPage($dbi, $URL)) {
476 $link['type'] = "wiki-$linktype";
477 $link['link'] = LinkExistingWikiWord($URL, $linkname);
478 } elseif (preg_match("#^($AllowedProtocols):#", $URL)) {
479 // if it's an image, embed it; otherwise, it's a regular link
480 if (preg_match("/($InlineImages)$/i", $URL)) {
481 $link['type'] = "image-$linktype";
482 $link['link'] = LinkImage($URL, $linkname);
484 $link['type'] = "url-$linktype";
485 $link['link'] = LinkURL($URL, $linkname);
487 } elseif (preg_match("#^phpwiki:(.*)#", $URL, $match)) {
488 $link['type'] = "url-wiki-$linktype";
489 $link['link'] = "<a href=\"$ScriptUrl$match[1]\">$linkname</a>";
491 $link['type'] = "wiki-unknown-$linktype";
492 $link['link'] = LinkUnknownWikiWord($URL, $linkname);
499 function ExtractWikiPageLinks($content)
501 global $WikiNameRegexp;
503 $wikilinks = array();
504 $numlines = count($content);
505 for($l = 0; $l < $numlines; $l++)
507 $line = str_replace('[[', ' ', $content[$l]); // remove escaped '['
508 $numBracketLinks = preg_match_all("/\[\s*([^\]|]+\|)?\s*(.+?)\s*\]/", $line, $brktlinks);
509 for ($i = 0; $i < $numBracketLinks; $i++) {
510 $link = ParseAndLink($brktlinks[0][$i]);
511 if (preg_match("#^wiki#", $link['type']))
512 $wikilinks[$brktlinks[2][$i]] = 1;
514 $brktlink = preg_quote($brktlinks[0][$i]);
515 $line = preg_replace("|$brktlink|", '', $line);
518 if (preg_match_all("/!?$WikiNameRegexp/", $line, $link)) {
519 for ($i = 0; isset($link[0][$i]); $i++) {
520 if($link[0][$i][0] <> '!')
521 $wikilinks[$link[0][$i]] = 1;