1 <!-- $Id: stdlib.php,v 1.7 2000-10-31 19:23:03 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;
95 $page = join('', file($templates[$template]));
96 $page = str_replace('###', "#$FieldSeparator#", $page);
98 // valid for all pagetypes
99 $page = str_replace("#$FieldSeparator#SCRIPTURL#$FieldSeparator#",
101 $page = str_replace("#$FieldSeparator#PAGE#$FieldSeparator#",
102 htmlspecialchars($name), $page);
103 $page = str_replace("#$FieldSeparator#ALLOWEDPROTOCOLS#$FieldSeparator#",
104 $AllowedProtocols, $page);
105 $page = str_replace("#$FieldSeparator#LOGO#$FieldSeparator#",
108 // invalid for messages (search results, error messages)
109 if ($template != 'MESSAGE') {
110 $page = str_replace("#$FieldSeparator#PAGEURL#$FieldSeparator#",
111 rawurlencode($name), $page);
112 $page = str_replace("#$FieldSeparator#LASTMODIFIED#$FieldSeparator#",
113 date($datetimeformat, $hash['lastmodified']), $page);
114 $page = str_replace("#$FieldSeparator#LASTAUTHOR#$FieldSeparator#",
115 $hash['author'], $page);
116 $page = str_replace("#$FieldSeparator#VERSION#$FieldSeparator#",
117 $hash['version'], $page);
118 if (strstr($page, "#$FieldSeparator#HITS#$FieldSeparator#")) {
119 $page = str_replace("#$FieldSeparator#HITS#$FieldSeparator#",
120 GetHitCount($dbi, $name), $page);
122 if (strstr($page, "#$FieldSeparator#RELATEDPAGES#$FieldSeparator#")) {
123 $page = str_replace("#$FieldSeparator#RELATEDPAGES#$FieldSeparator#",
124 LinkRelatedPages($dbi, $name), $page);
128 // valid only for EditLinks
129 if ($template == 'EDITLINKS') {
130 for ($i = 1; $i <= NUM_LINKS; $i++)
131 $page = str_replace("#$FieldSeparator#R$i#$FieldSeparator#",
132 $hash['refs'][$i], $page);
136 $page = str_replace("#$FieldSeparator#IFCOPY#$FieldSeparator#",
139 $page = ereg_replace("#$FieldSeparator#IFCOPY#$FieldSeparator#[^\n]*",
143 $page = str_replace("#$FieldSeparator#CONTENT#$FieldSeparator#",
149 function LinkExistingWikiWord($wikiword) {
151 $enc_word = rawurlencode($wikiword);
152 $wikiword = htmlspecialchars($wikiword);
153 return "<a href=\"$ScriptUrl?$enc_word\">$wikiword</a>";
156 function LinkUnknownWikiWord($wikiword) {
158 $enc_word = rawurlencode($wikiword);
159 $wikiword = htmlspecialchars($wikiword);
160 return "<u>$wikiword</u><a href=\"$ScriptUrl?edit=$enc_word\">?</a>";
163 function LinkURL($url) {
165 if(ereg("[<>\"]", $url)) {
166 return "<b><u>BAD URL -- remove all of <, >, "</u></b>";
168 $enc_url = htmlspecialchars($url);
169 return "<a href=\"$url\">$enc_url</a>";
173 function LinkImage($url, $alt="[External Image]") {
175 if(ereg("[<>\"]", $url)) {
176 return "<b><u>BAD URL -- remove all of <, >, "</u></b>";
178 return "<img src=\"$url\" ALT=\"$alt\">";
182 function RenderQuickSearch($value = "") {
184 return "<form action=\"$ScriptUrl\">\n" .
185 "<input type=text size=30 name=search value=\"$value\">\n" .
186 "<input type=submit value=\"". gettext("Search") .
190 function RenderFullSearch($value = "") {
192 return "<form action=\"$ScriptUrl\">\n" .
193 "<input type=text size=30 name=full value=\"$value\">\n" .
194 "<input type=submit value=\"". gettext("Search") .
198 function RenderMostPopular() {
199 global $ScriptUrl, $dbi;
201 $query = InitMostPopular($dbi, MOST_POPULAR_LIST_LENGTH);
203 while ($qhash = MostPopularNextMatch($dbi, $query)) {
204 $result .= "<DD>$qhash[hits] ... " . LinkExistingWikiWord($qhash['pagename']) . "\n";
206 $result .= "</DL>\n";
211 // converts spaces to tabs
212 function CookSpaces($pagearray) {
213 return preg_replace("/ {3,8}/", "\t", $pagearray);
221 function push($item) {
222 $this->items[$this->size] = $item;
228 if ($this->size == 0) {
229 return false; // stack is empty
232 return $this->items[$this->size];
240 return $this->items[$this->size - 1];
244 // end class definition
247 // I couldn't move this to lib/config.php because it
248 // wasn't declared yet.
252 Wiki HTML output can, at any given time, be in only one mode.
253 It will be something like Unordered List, Preformatted Text,
254 plain text etc. When we change modes we have to issue close tags
255 for one mode and start tags for another.
258 function SetHTMLOutputMode($tag, $tagdepth, $tabcount) {
262 if ($tagdepth == SINGLE_DEPTH) {
263 if ($tabcount < $stack->cnt()) {
264 // there are fewer tabs than stack,
265 // reduce stack to that tab count
266 while ($stack->cnt() > $tabcount) {
267 $closetag = $stack->pop();
268 if ($closetag == false) {
269 //echo "bounds error in tag stack";
272 $retvar .= "</$closetag>\n";
275 // if list type isn't the same,
276 // back up one more and push new tag
277 if ($tag != $stack->top()) {
278 $closetag = $stack->pop();
279 $retvar .= "</$closetag><$tag>\n";
283 } elseif ($tabcount > $stack->cnt()) {
284 // we add the diff to the stack
285 // stack might be zero
286 while ($stack->cnt() < $tabcount) {
288 $retvar .= "<$tag>\n";
290 if ($stack->cnt() > 10) {
291 // arbitrarily limit tag nesting
292 ExitWiki(gettext ("Stack bounds exceeded in SetHTMLOutputMode"));
297 if ($tag == $stack->top()) {
300 $closetag = $stack->pop();
301 #echo "</$closetag>\n";
303 $retvar .= "</$closetag>\n";
304 $retvar .= "<$tag>\n";
309 } elseif ($tagdepth == ZERO_DEPTH) {
310 // empty the stack for $depth == 0;
311 // what if the stack is empty?
312 if ($tag == $stack->top()) {
315 while ($stack->cnt() > 0) {
316 $closetag = $stack->pop();
317 #echo "</$closetag>\n";
318 $retvar .= "</$closetag>\n";
323 $retvar .= "<$tag>\n";
329 ExitWiki ("Passed bad tag depth value in SetHTMLOutputMode");
335 // end SetHTMLOutputMode
339 // The Recent Changes file is solely handled here
340 function UpdateRecentChanges($dbi, $pagename, $isnewpage) {
342 global $remoteuser; // this is set in the config
344 global $WikiPageStore;
346 $recentchanges = RetrievePage($dbi, gettext ("RecentChanges"),
349 // this shouldn't be necessary, since PhpWiki loads
350 // default pages if this is a new baby Wiki
351 if ($recentchanges == -1) {
352 $recentchanges = array();
356 $today = date($dateformat, $now);
358 if (date($dateformat, $recentchanges["lastmodified"]) != $today) {
360 $recentchanges["lastmodified"] = $now;
365 $numlines = sizeof($recentchanges["content"]);
369 // scroll through the page to the first date and break
370 // dates are marked with "____" at the beginning of the line
371 for ($i = 0; $i < ($numlines + 1); $i++) {
372 if (preg_match("/^____/",
373 $recentchanges["content"][$i])) {
376 $newpage[$k++] = $recentchanges["content"][$i];
380 // if it's a new date, insert it, else add the updated page's
384 $newpage[$k++] = "____$today\r";
385 $newpage[$k++] = "\r";
387 $newpage[$k++] = $recentchanges["content"][$i++];
390 $newpage[$k++] = "* [$pagename] (new) ..... $remoteuser\r";
392 $diffurl = "phpwiki:?diff=" . rawurlencode($pagename);
393 $newpage[$k++] = "* [$pagename] ([diff|$diffurl]) ..... $remoteuser\r";
396 // copy the rest of the page into the new array
397 $pagename = preg_quote($pagename);
398 for (; $i < ($numlines + 1); $i++) {
399 // skip previous entry for $pagename
400 if (preg_match("|\[$pagename\]|", $recentchanges["content"][$i])) {
403 $newpage[$k++] = $recentchanges["content"][$i];
407 $recentchanges["content"] = $newpage;
409 InsertPage($dbi, gettext ("RecentChanges"), $recentchanges);
414 function ParseAndLink($bracketlink) {
415 global $dbi, $ScriptUrl, $AllowedProtocols, $InlineImages;
417 // $bracketlink will start and end with brackets; in between
418 // will be either a page name, a URL or both separated by a pipe.
420 // strip brackets and leading space
421 preg_match("/(\[\s*)(.+?)(\s*\])/", $bracketlink, $match);
422 // match the contents
423 preg_match("/([^|]+)(\|)?([^|]+)?/", $match[2], $matches);
425 // if $matches[3] is set, this is a link in the form of:
426 // [some link name | http://blippy.com/]
428 if (isset($matches[3])) {
429 $URL = trim($matches[3]);
430 $linkname = htmlspecialchars(trim($matches[1]));
431 // assert proper URL's
432 if (preg_match("#^($AllowedProtocols):#", $URL)) {
433 if (preg_match("/($InlineImages)$/i", $URL)) {
434 $link['type'] = 'image-named';
435 $link['link'] = LinkImage($URL, $linkname);
437 $link['type'] = 'url-named';
438 $link['link'] = "<a href=\"$URL\">$linkname</a>";
440 } elseif (preg_match("#^phpwiki:(.*)#", $URL, $match)) {
441 $link['type'] = 'url-wiki-named';
442 $link['link'] = "<a href=\"$ScriptUrl$match[1]\">$linkname</a>";
444 $link['type'] = 'url-bad';
445 $link['link'] = "<b><u>BAD URL -- links have to start with one" .
446 "of $AllowedProtocols followed by ':'</u></b>";
452 // otherwise this is just a Wiki page like this: [page name]
453 // or a URL in brackets: [http://foo.com/]
455 if (isset($matches[1])) {
456 $linkname = trim($matches[1]);
457 if (IsWikiPage($dbi, $linkname)) {
458 $link['type'] = 'wiki';
459 $link['link'] = LinkExistingWikiWord($linkname);
460 } elseif (preg_match("#^($AllowedProtocols):#", $linkname)) {
461 // if it's an image, embed it; otherwise, it's a regular link
462 if (preg_match("/($InlineImages)$/i", $linkname)) {
463 $link['type'] = 'image-simple';
464 $link['link'] = LinkImage($linkname);
466 $link['type'] = 'url-simple';
467 $link['link'] = LinkURL($linkname);
470 $link['type'] = 'wiki-unknown';
471 $link['link'] = LinkUnknownWikiWord($linkname);
476 $link['type'] = 'unknown';
477 $link['link'] = $bracketlink;
482 function ExtractWikiPageLinks($content)
484 global $WikiNameRegexp;
486 $wikilinks = array();
487 $numlines = count($content);
488 for($l = 0; $l < $numlines; $l++)
490 $line = $content[$l];
491 $numBracketLinks = preg_match_all("/\[\s*(.+?)\s*\]/", $line, $brktlinks);
492 for ($i = 0; $i < $numBracketLinks; $i++) {
493 $link = ParseAndLink($brktlinks[0][$i]);
494 if($link['type'] == 'wiki' || $link['type'] == 'wiki-unknown')
495 $wikilinks[$brktlinks[1][$i]]++;
497 $brktlink = preg_quote($brktlinks[0][$i]);
498 $line = preg_replace("|$brktlink|", '', $line);
501 if (preg_match_all("/!?$WikiNameRegexp/", $line, $link)) {
502 for ($i = 0; $link[0][$i]; $i++) {
503 if($link[0][$i][0] <> '!')
504 $wikilinks[$link[0][$i]]++;