index.php 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211
  1. <?php
  2. /*
  3. PmWiki
  4. Copyright 2001-2004 Patrick R. Michaud
  5. pmichaud@pobox.com
  6. http://www.pmichaud.com/
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. if (ini_get('register_globals')) {
  20. foreach($_REQUEST as $k=>$v) { unset(${$k}); }
  21. }
  22. $UnsafeGlobals = array_keys($GLOBALS);
  23. SDV($FarmD,dirname(__FILE__));
  24. define('PmWiki',1);
  25. @include_once("$FarmD/scripts/version.php");
  26. $WikiTitle = "PmWiki";
  27. $DefaultGroup = "Main";
  28. $DefaultTitle = "HomePage";
  29. $ScriptUrl = 'http://'.htmlspecialchars($_SERVER['HTTP_HOST']);
  30. $ScriptUrl .= htmlspecialchars($_SERVER['SCRIPT_NAME']);
  31. $PubDirUrl = preg_replace("#/[^/]*\$#","/pub",$ScriptUrl,1);
  32. $DiffKeepDays = 3650;
  33. $WikiDir = "wiki.d";
  34. $WikiLibDirs = array(&$WikiDir,"$FarmD/wikilib.d");
  35. $DeleteKeyWord = "delete";
  36. $RedirectDelay = 0;
  37. $AuthFunction = 'BasicAuth';
  38. $AsSpacedFunction = 'AsSpaced';
  39. $AllowPassword = 'nopass';
  40. $DiffFunction = 'Diff';
  41. $SysDiffCmd = '/usr/bin/diff';
  42. $PatchFunction = 'Patch';
  43. $DefaultPasswords = array('admin'=>'*','attr'=>'','edit'=>'','read'=>'');
  44. $AuthRealmFmt = '$WikiTitle';
  45. $AuthDeniedFmt = 'A valid password is required to access this feature.';
  46. $DefaultPageTextFmt = '$[Describe $Tlink here.]';
  47. $PageRedirectFmt = "<i>($[redirected from] <a href='\$PageUrl?action=edit'>\$PageName</a>)</i><p />\n";
  48. $IncludeBadAnchorFmt = "include:\$Group.\$Tlink - #\$BadAnchor \$[not found]\n";
  49. $PageEditFmt=array("
  50. <div id='wikiedit'>
  51. <a id='top' name='top'></a><h1 class='wikiaction'>$[Editing \$PageName]</h1>
  52. <form name = 'editform' action='\$PageUrl' onSubmit = 'return check_post();' method='post'>
  53. <input type='hidden' name='pagename' value='\$PageName' />
  54. <input type='hidden' name='action' value='edit' />
  55. \$EditMessageFmt
  56. <textarea name='text' rows='25' cols='60'
  57. onkeydown='if (event.keyCode == 27) event.returnValue=false;'
  58. >\$Text</textarea><br />
  59. $[Author]: <input type='text' name='author' value='\$Author' />
  60. <input type='checkbox' name='diffclass' value='minor' \$DiffClassMinor />
  61. $[This is a minor edit]<br />
  62. <input type='submit' name='post' value=' $[Save] ' />
  63. <input type='submit' name='preview' value=' $[Preview] ' />
  64. <input type='reset' value=' $[Reset] ' />
  65. </form></div>",'wiki:$[PmWiki.EditQuickReference]');
  66. $EditMessageFmt='';
  67. $PagePreviewFmt=array(
  68. "function:ProcessTextDirectives",
  69. "<h2 class='wikiaction'>Preview \$PageName</h2>
  70. <b>Page is unsaved</b><hr /><p></p>",
  71. "function:PrintText",
  72. "<hr /><b>End of preview -- remember to save</b>
  73. <br /><a href='#top'>$[Top]</a>");
  74. $PageAttrFmt="<h1 class='wikiaction'>$[\$PageName Attributes]</h1>
  75. <p>Enter new attributes for this page below. Leaving a field blank
  76. will leave the attribute unchanged. To clear an attribute, enter
  77. 'clear'.</p>";
  78. $GroupHeaderFmt = '$Group.GroupHeader';
  79. $GroupFooterFmt = '$Group.GroupFooter';
  80. $GroupAttributesFmt = '$Group.GroupAttributes';
  81. $TimeFmt = "%B %d, %Y, at %I:%M %p";
  82. $SpaceWikiWordsString = ' ';
  83. $PageNameFmt = '$Group.$Title_';
  84. $PageFileFmt = '$PageName';
  85. $PageUrlFmt = '$ScriptUrl/$Group/$Title_';
  86. $HTTPHeaders=array(
  87. "Expires: Tue, 01 Jan 2002 00:00:00 GMT",
  88. "Last-Modified: ".gmstrftime('%a, %d %b %Y %H:%M:%S GMT'),
  89. "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0",
  90. "Pragma: no-cache",
  91. "Content-Type: text/html; charset=iso-8859-1;");
  92. $HTMLDoctypeFmt =
  93. "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"
  94. \"http://www.w3.org/TR/html40/loose.dtd\">
  95. <html><head>\n";
  96. $HTMLTitleFmt = " <title>\$WikiTitle - \$HTMLTitle</title>\n";
  97. $HTMLHeaders = <<<EOT
  98. <SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript">
  99. <!--
  100. function check_post() {
  101. var namevalue = document.editform.author.value;
  102. var textvalue = document.editform.text.value;
  103. var uc = /[A-Z]/;
  104. var i, x = 0;
  105. /* 'Describe ' opens an unedited page. Nobody should be leaving that in
  106. place if they're performing a genuine page edit... */
  107. if (textvalue.substr(0, 9) == 'Describe ') {
  108. window.alert('No editing appears to have taken place');
  109. return false;
  110. }
  111. /* Randomly generated names are more likely to end in a capital letter */
  112. if (uc.test(namevalue.substring(namevalue.length - 1))) {
  113. return window.confirm('Please confirm that the name given is valid');
  114. }
  115. /* Randomly generated names often exceed genuine use of capitalization */
  116. for (i = 0; i < namevalue.length; i++) {
  117. if (uc.test(namevalue.substring(i))) {
  118. x++;
  119. if (x > 3) {
  120. return window.confirm('Please confirm that the name given is valid');
  121. }
  122. }
  123. }
  124. return true;
  125. }
  126. //-->
  127. </SCRIPT>
  128. EOT;
  129. $HTMLHeaderFmt = array(&$HTMLHeaders);
  130. $HTMLBodyFmt = "</head>\n<body>";
  131. $HTMLStartFmt = array('headers:',&$HTMLDoctypeFmt,&$HTMLHeaderFmt,
  132. &$HTMLTitleFmt,&$HTMLBodyFmt);
  133. $HTMLEndFmt = "\n</body>\n</html>";
  134. $PageStartFmt = array(&$HTMLStartFmt,"\n<div id='wikitext'>\n");
  135. $PageEndFmt = array('</div>',&$HTMLEndFmt);
  136. $HTMLVSpace = "<p></p>";
  137. $HTMLLineBreak = '';
  138. $XLLangs = array('en');
  139. $FmtWikiLink = 'FmtWikiLink';
  140. $FmtUrlLink = 'FmtUrlLink';
  141. $WikiWordPagePathFmt = array('$Group.$1','$1.$1');
  142. $WikiPageExistsFmt = "<a class='wikilink' href='\$PageUrl\$Fragment'>\$LinkText</a>";
  143. $WikiPageCreateFmt =
  144. "<span class='createlink'>\$LinkText</span><a class='createlink' href='\$PageUrl?action=edit'>?</a>";
  145. $WikiWordCountMax = 1000000;
  146. $WikiWordCount['PmWiki'] = 1;
  147. $UrlLinkFmt = "<a class='urllink' href='\$Url' rel='nofollow'>\$LinkText</a>";
  148. $UrlImgFmt = "<img src='\$Url' border='0' alt='' img>";
  149. $GroupNamePattern="[[:upper:]][[:alnum:]]+";
  150. $WikiWordPattern="[[:upper:]][[:alnum:]]*(?:[[:upper:]][[:lower:]0-9]|[[:lower:]0-9][[:upper:]])[[:alnum:]]*";
  151. $GroupFreeLinkPattern="{{(?>(?:($GroupNamePattern)([.\\/]))?([[:alpha:]][[:alnum:]]*(?:(?:[\\s_]*|-)[[:alnum:]]+)*)(?:\\|((?:(?:[\\s_]*|-)[[:alnum:]])*))?)}}((?:-?[[:alnum:]]+)*)"; # deprecated 0.6
  152. $FreeLinkPattern = $GroupFreeLinkPattern;
  153. $FragmentPattern="#([A-Za-z][-.:\\w]*)";
  154. $PageTitlePattern="[[:upper:]][[:alnum:]]*(?:-[[:alnum:]]+)*";
  155. $UrlPathPattern="[^\\s<>[\\]\"\'()`|^]*[^\\s<>[\\]\"\'()`|^,.?]";
  156. $UrlMethodPattern="http|ftp|news|file|gopher|nap|https";
  157. $ImgExtPattern="\\.(gif|jpg|jpeg|png)";
  158. $InterMapFiles=array("$FarmD/scripts/intermap.txt","$FarmD/local/farmmap.txt",
  159. 'localmap.txt', 'local/localmap.txt');
  160. $LinkPatterns=array();
  161. $PostFields = array('text');
  162. $RCDelimPattern = ' \\. ';
  163. $RecentChanges = array(
  164. 'Main.AllRecentChanges'=>'* $Group.$Tlink . . . $CurrentTime by $AuthorLink',
  165. '$Group.RecentChanges'=>'* $Group/$Tlink . . . $CurrentTime by $AuthorLink');
  166. $BrowseDirectives = array(
  167. '[[spacewikiwords]]' => '$GLOBALS["SpaceWikiWords"]=1;',
  168. '[[noheader]]' => '$GLOBALS["PageHeaderFmt"]="";',
  169. '[[notitle]]' => '$GLOBALS["PageTitleFmt"]="";',
  170. '[[nofooter]]' => '$GLOBALS["PageFooterFmt"]="";',
  171. '[[nogroupheader]]' => '', '[[nogroupfooter]]' => '');
  172. $DoubleBrackets = array('[[$Group]]'=>'$Group', '[[$Title]]'=>'$Title',
  173. '[[$Groupspaced]]'=>'$Groupspaced','[[$Titlespaced]]'=>'$Titlespaced',
  174. '[[$Tlink]]'=>'$Tlink',
  175. '[[$LastModifiedBy]]'=>'$LastModifiedBy',
  176. '[[$LastModifiedHost]]'=>'$LastModifiedHost',
  177. '[[$LastModified]]'=>'$LastModified',
  178. '[[$Author]]'=>'$Author',
  179. '[[$Version]]'=>'$Version',
  180. '[[$DefaultGroup]]'=>'$DefaultGroup',
  181. '[[$Edit' => '[[$PageUrl?action=edit ',
  182. '[[$Diff' => '[[$PageUrl?action=diff ');
  183. $InlineReplacements = array(
  184. "/'''''(.*?)'''''/" => "<em><strong>\$1</strong></em>",
  185. "/'''(.*?)'''/" => "<strong>\$1</strong>",
  186. "/''(.*?)''/" => "<em>\$1</em>",
  187. "/@@(.*?)@@/" => "<code>\$1</code>",
  188. "/\\[\\[&lt;&lt;\\]\\]/" => "<br clear='all' />",
  189. "/\\[(\\++)(.*?)\\1\\]/e" =>
  190. "'<span style=\'font-size:'.(round(pow(1.2,strlen('$1'))*100,0)).'%\'>'.str_replace('\\\"','\"','$2').'</span>'",
  191. "/\\[(-+)(.*?)\\1\\]/e" =>
  192. "'<span style=\'font-size:'.(round(pow(5/6,strlen('$1'))*100,0)).'%\'>'.str_replace('\\\"','\"','$2').'</span>'",
  193. "/^----+/" => "<hr />",
  194. "/&amp;([A-Za-z0-9]+;|#\d+;|#[xX][A-Fa-f0-9]+;)/" => "&\$1");
  195. $PageAttributes = array(
  196. 'passwdread' => '$[Set new read password:]',
  197. 'passwdedit' => '$[Set new edit password:]',
  198. 'passwdattr' => '$[Set new attribute password:]');
  199. $HandleActions = array(
  200. 'edit' => 'HandleEdit', 'post' => 'HandlePost',
  201. 'attr' => 'HandleAttr', 'postattr' => 'HandlePostAttr',
  202. 'source' => 'HandleSource');
  203. $WikiStylePattern = '%%|%[A-Za-z][-,=:#\\w\\s]*%';
  204. $WikiStyleTags = array(
  205. 'color' => array( 'style' => 'color:$value; ',
  206. 'a' => 'style=\'color:$value\' '),
  207. 'bgcolor' => array( 'style' => 'background-color:$value; '),
  208. 'font-size' => array( 'style' => 'font-size:$value; '),
  209. 'font-family' => array( 'style' => 'font-family:$value; '),
  210. 'font-style' => array( 'style' => 'font-style:$value; '),
  211. 'font-weight' => array( 'style' => 'font-weight:$value; '),
  212. 'text-decoration' => array( 'style' => 'text-decoration:$value; '),
  213. 'class' => array( 'class' => 'class=\'$value\''),
  214. 'target' => array( 'a' => 'target=\'$value\' '),
  215. 'rel' => array('a' => 'rel=\'$value\' '),
  216. 'hspace' => array( 'img' => 'hspace=\'$value\' '),
  217. 'vspace' => array( 'img' => 'vspace=\'$value\' '),
  218. 'width' => array( 'img' => 'width=\'$value\' '),
  219. 'height' => array( 'img' => 'height=\'$value\' ')
  220. );
  221. $Now = time();
  222. $MaxIncludes = 10;
  223. $TableAttr = "";
  224. $TableCellAttr = "valign='top'";
  225. $Newline = "\262";
  226. $KeepToken = "\263"; $KPCount=0;
  227. $LinkToken = "\037";
  228. $StyleToken = "\036";
  229. $EnableStdConfig = 1;
  230. umask(is_writable($WikiDir) ? (fileperms($WikiDir)^0777) : 002);
  231. if (setlocale(LC_ALL,0)=='C') setlocale(LC_ALL,'en_US');
  232. if (strpos(@$_SERVER['QUERY_STRING'],'?')!==false) {
  233. unset($_GET);
  234. parse_str(str_replace('?','&',$_SERVER['QUERY_STRING']),$_GET);
  235. }
  236. $gvars = array('pagename','action','text','restore','preview');
  237. foreach($gvars as $v) {
  238. if (isset($_GET[$v])) $$v=$_GET[$v];
  239. elseif (isset($_POST[$v])) $$v=$_POST[$v];
  240. else $$v = '';
  241. }
  242. SDV($EnablePathInfo,!preg_match("/^cgi/",php_sapi_name()));
  243. if ($pagename=='' && $EnablePathInfo)
  244. $pagename = @substr(htmlspecialchars($_SERVER['PATH_INFO']),1);
  245. if (preg_match('/[\\x80-\\xbf]/',$pagename)) $pagename=utf8_decode($pagename);
  246. if ($action=='') $action='browse';
  247. error_reporting(E_ALL ^ E_NOTICE);
  248. if (file_exists("$FarmD/local/farmconfig.php"))
  249. include_once("$FarmD/local/farmconfig.php");
  250. if (!isset($EnableLocalConfig) || $EnableLocalConfig) {
  251. if (file_exists('local/config.php'))
  252. { include_once('local/config.php'); $LocalConf=1; }
  253. elseif (file_exists('local.php')) # deprecated 0.6
  254. { include_once('local.php'); $LocalConf=1; } # deprecated 0.6
  255. elseif (file_exists('local/local.php')) # deprecated 0.6
  256. { include_once('local/local.php'); $LocalConf=1; } # deprecated 0.6
  257. }
  258. SDV($DefaultPage,"$DefaultGroup/$DefaultTitle");
  259. if ($pagename=='') $pagename=$DefaultPage;
  260. if ($EnableStdConfig)
  261. @include_once("$FarmD/scripts/stdconfig.php");
  262. mkgiddir($WikiDir);
  263. if (!file_exists("$WikiDir/.htaccess") &&
  264. $fp=@fopen("$WikiDir/.htaccess","w")) {
  265. fwrite($fp,"Order Deny,Allow\nDeny from all\n");
  266. fclose($fp);
  267. }
  268. SDV($UrlLinkTextFmt,$UrlLinkFmt);
  269. SDV($RedirectPattern,"\\[\\[redirect:(\\S+)\\]\\]");
  270. SDV($WikiPageCreateSpaceFmt,$WikiPageCreateFmt);
  271. $LinkPatterns[200]["\\bmailto:($UrlPathPattern)"] = "<a href='$0'>$1</a>";
  272. $LinkPatterns[300]["\\b($UrlMethodPattern):($UrlPathPattern)"] = $FmtUrlLink;
  273. foreach($InterMapFiles as $mapfile) {
  274. if (@!($mapfd=fopen($mapfile,"r"))) continue;
  275. while ($mapline=fgets($mapfd,1024)) {
  276. if (preg_match("/^\\s*\$/",$mapline)) continue;
  277. list($mapid,$mapurl) = preg_split("/\\s+/",$mapline);
  278. if (strpos($mapurl,'$1')===false) $mapurl .= '$1';
  279. $LinkPatterns[400]["\\b$mapid:($UrlPathPattern)"] = $FmtUrlLink;
  280. $InterMapUrls[$mapid] = $mapurl;
  281. }
  282. fclose($mapfd);
  283. }
  284. $LinkPatterns[480]["($WikiStylePattern)"] = "$StyleToken$1";
  285. $LinkPatterns[500]["\\b($GroupNamePattern([\\/.]))?($FreeLinkPattern)($FragmentPattern)?"] = $FmtWikiLink;
  286. $LinkPatterns[600]["$FreeLinkPattern($FragmentPattern)?"] = $FmtWikiLink;
  287. $LinkPatterns[700]["\\b$GroupNamePattern([\\/.])$WikiWordPattern($FragmentPattern)?"] = $FmtWikiLink;
  288. $LinkPatterns[780]["\\[\\[$FragmentPattern\\]\\]"] =
  289. "<a name='$1' id='$1'></a>";
  290. $LinkPatterns[780]["\\[\\[$FragmentPattern\\s(.+?)\\]\\]"] =
  291. "<a href='#$1'>$2</a>";
  292. $LinkPatterns[800]["\\b$WikiWordPattern($FragmentPattern)?"] = $FmtWikiLink;
  293. $CurrentTime = strftime($TimeFmt,$Now);
  294. if (preg_match("/^($GroupNamePattern)[\\/.]?\$/",$pagename,$match)) {
  295. if (PageExists($match[1].'.'.$match[1])) Redirect($match[1].'.'.$match[1]);
  296. else Redirect($match[1].".$DefaultTitle");
  297. }
  298. if (!preg_match("/^($GroupNamePattern)[\\/.]($PageTitlePattern)\$/",$pagename,
  299. $match))
  300. Abort("'$pagename' is not a valid PmWiki page name");
  301. $pagename=FmtPageName('$PageName',$pagename);
  302. $handle = @$HandleActions[$action];
  303. if (function_exists($handle)) $handle($pagename);
  304. else { HandleBrowse($pagename); }
  305. EndHTML();
  306. Lock(-1);
  307. function SDV(&$var,$val) { if (!isset($var)) $var=$val; }
  308. function SDVA(&$var,$val) {
  309. foreach($val as $k=>$v) if (!isset($var[$k])) $var[$k]=$v;
  310. }
  311. function stripmagic($s)
  312. { return get_magic_quotes_gpc() ? stripslashes($s) : $s; }
  313. function mkgiddir($dir) {
  314. global $ForceMkdir;
  315. $dir = preg_replace('!/$!','',$dir);
  316. if (is_dir($dir)) return;
  317. if (!$ForceMkdir) {
  318. $parent = dirname($dir);
  319. $rparent = realpath($parent);
  320. $perms = fileperms($parent);
  321. if (umask()!=0 && posix_getegid()!=filegroup($parent) &&
  322. ($perms & 02000)==0)
  323. Abort("PmWiki wants setgid permissions enabled on <tt>$rparent</tt><br />
  324. before it creates the <tt>$dir</tt> directory. <br />
  325. Try executing <pre> chmod 2777 $rparent</pre>
  326. on your server and reloading this page. Afterwards, you
  327. can restore the permissions<br />to their current setting by executing
  328. <pre> chmod ".decoct($perms & 03777)." $rparent</pre>If this
  329. doesn't work for you, see the link below.","Setgid");
  330. }
  331. mkdir($dir,0777) or
  332. Abort("Cannot create <tt>$dir</tt><br />
  333. Current directory is <tt>".getcwd()."</tt>","Mkdir");
  334. }
  335. function Abort($msg,$aref = NULL) {
  336. StartHTML("","Program error");
  337. echo("<h3>PmWiki can't process your request</h3>
  338. <p>$msg</p><p>We are sorry for any inconvenience.</p>");
  339. if ($aref) {
  340. $href = "http://www.pmichaud.com/ref/PmWiki/$aref";
  341. echo("<p><a href='$href' target='_blank'>$href</a></p>");
  342. }
  343. EndHTML();
  344. exit();
  345. }
  346. function SetPageVars($pagename,&$page,$title) {
  347. $GLOBALS['LastModified'] = $page['timefmt'];
  348. $GLOBALS['LastModifiedBy'] = @$page['author'];
  349. $GLOBALS['LastModifiedHost'] = @$page['host'];
  350. $GLOBALS['HTMLTitle'] = $title;
  351. $GLOBALS['GCount'] = 0;
  352. }
  353. function StartHTML($pagename,$title = "") {
  354. global $calledStartHTML; if ($calledStartHTML++) return;
  355. global $HTMLStartFmt,$GCount;
  356. $GLOBALS['HTMLTitle']=$title; $GCount=0;
  357. PrintFmt($pagename,$HTMLStartFmt);
  358. }
  359. function EndHTML($pagename=NULL,$x=NULL) {
  360. static $called; if ($called++) return;
  361. global $calledStartHTML,$HTMLEndFmt;
  362. if ($calledStartHTML) PrintFmt($pagename,$HTMLEndFmt);
  363. }
  364. function Redirect($pagename,$urlfmt='$PageUrl') {
  365. global $RedirectDelay,$ScriptUrl,$DefaultPage;
  366. clearstatcache();
  367. if (!PageExists($pagename)) $pagename=$DefaultPage;
  368. $pageurl=FmtPageName($urlfmt,$pagename);
  369. header("Location: $pageurl");
  370. header("Content-type: text/html");
  371. print("<html><head>
  372. <meta http-equiv='Refresh' Content='$RedirectDelay; URL=$pageurl'>
  373. <title>Redirect</title></head><body></body></html>");
  374. exit;
  375. }
  376. function AsSpaced($word) {
  377. global $SpaceWikiWords,$SpaceWikiWordsString;
  378. $word = str_replace('_',$SpaceWikiWordsString,$word);
  379. $word = preg_replace("/([[:lower:]\\d])([[:upper:]])/",
  380. '$1'.$SpaceWikiWordsString.'$2',$word);
  381. if ($SpaceWikiWords==2)
  382. $word = preg_replace("/([[:lower:]])(\\d+( |\$))/",
  383. '$1'.$SpaceWikiWordsString.'$2',$word);
  384. else
  385. $word = preg_replace("/(?<![-\\d])(\\d+( |\$))/",
  386. $SpaceWikiWordsString.'$1',$word);
  387. return preg_replace("/([[:upper:]])([[:upper:]][[:lower:]\\d])/",
  388. '$1'.$SpaceWikiWordsString.'$2',$word);
  389. }
  390. function FreeLink($link) {
  391. global $GroupFreeLinkPattern,$PageNameSpace;
  392. if (!preg_match("/$GroupFreeLinkPattern/",$link,$match)) return NULL;
  393. $name = preg_replace('/[_\\s]+/',' ',$match[3].$match[4]);
  394. $name = str_replace(' ',$PageNameSpace,ucwords($name));
  395. return array('name'=>$name,'text'=>$match[3].$match[5],
  396. 'group'=>$match[1],'sep'=>$match[2]);
  397. }
  398. function PrintFmt($pagename,$fmt) {
  399. global $HTTPHeaders;
  400. if (is_array($fmt))
  401. { foreach($fmt as $f) PrintFmt($pagename,$f); return; }
  402. $x = FmtPageName($fmt,$pagename);
  403. if (preg_match("/^headers:/",$x)) {
  404. foreach($HTTPHeaders as $h) (@$sent++) ? @header($h) : header($h);
  405. return;
  406. }
  407. if (preg_match("/^function:(\S+)\s*(.*)\$/s",$x,$match) &&
  408. function_exists($match[1]))
  409. { $f = $match[1]; $f($pagename,$match[2]); return; }
  410. if (preg_match("/^wiki:(.+)\$/s",$x,$match))
  411. { PrintWikiPage($pagename,$match[1]); return; }
  412. if (preg_match("/^file:(.+)/s",$x,$match)) {
  413. $filelist = preg_split('/[\\s]+/',$match[1],-1,PREG_SPLIT_NO_EMPTY);
  414. foreach($filelist as $f) {
  415. if (file_exists($f)) { include($f); return; }
  416. }
  417. return;
  418. }
  419. print $x;
  420. }
  421. function FmtUrlLink($pat,$ref,$txt) {
  422. global $InterMapUrls,$ImgExtPattern,$UrlLinkFmt,$UrlImgFmt,$UrlLinkTextFmt;
  423. $link = $UrlLinkFmt; $rtxt=$ref;
  424. if (!is_null($txt)) { $rtxt=$txt; $link=$UrlLinkTextFmt; }
  425. elseif (preg_match("/$ImgExtPattern\$/",$ref)) { $link=$UrlImgFmt; }
  426. if (preg_match('/^([^:]*):/',$ref,$match)) {
  427. if (@$InterMapUrls[$match[1]])
  428. $ref=preg_replace("/^$pat\$/",$InterMapUrls[$match[1]],$ref);
  429. }
  430. $link = str_replace('$Url',$ref,$link);
  431. return str_replace('$LinkText',$rtxt,$link);
  432. }
  433. function FmtWikiLink($pat,$ref,$btext,$out=NULL,$rname=NULL) {
  434. global $GroupNamePattern,$PageNameSpace,$SpaceWikiWords,
  435. $WikiPageExistsFmt,$WikiPageCreateSpaceFmt,$WikiPageCreateFmt,
  436. $PageTitlePattern,$FragmentPattern,$WikiWordPagePathFmt,
  437. $WikiWordPattern,$WikiWordReplaceFmt,$WWCount,$WikiWordCountMax,
  438. $AsSpacedFunction;
  439. $lref=$ref; $fragment='';
  440. if (preg_match("/^(.*)($FragmentPattern)\$/",$lref,$match))
  441. { $lref=$match[1]; $fragment=$match[2]; }
  442. if ($fl=FreeLink($lref)) { $name=$fl['name']; $txt=$fl['text']; }
  443. else {
  444. $name = preg_replace('/^.*[\\/.]/','',$lref);
  445. $txt = ($SpaceWikiWords) ? $AsSpacedFunction($name) : $name;
  446. }
  447. if (preg_match("/^($GroupNamePattern)([\\/.])/",$lref,$match))
  448. { $fl['group']=$match[1]; $fl['sep']=$match[2]; }
  449. if ($fl['group']) {
  450. $pname = $fl['group'].'.'.$name;;
  451. if ($fl['sep']=='.') $txt=$fl['group'].'.'.$txt;
  452. } else {
  453. if ($rname=='') $rname=$GLOBALS['pagename'];
  454. foreach((array)$WikiWordPagePathFmt as $pg) {
  455. $pn=FmtPageName(str_replace('$1',$name,$pg),$rname);
  456. if (PageExists($pn)) { $pname=$pn; break; }
  457. if (@$pname=='') $pname=$pn;
  458. }
  459. }
  460. if ($out=='PageName') return $pname;
  461. if (!preg_match("/\.$PageTitlePattern\$/",$pname)) return $ref;
  462. $txt .= $fragment;
  463. if (!is_null($btext)) $txt=$btext;
  464. if (PageExists($pname)) $fmt=$WikiPageExistsFmt;
  465. elseif (preg_match('/\\s/',$txt)) $fmt=$WikiPageCreateSpaceFmt;
  466. else $fmt=$WikiPageCreateFmt;
  467. if (is_null($btext) && preg_match("/^$WikiWordPattern\$/",$ref)) {
  468. if (@$WikiWordReplaceFmt[$name]) $fmt=$WikiWordReplaceFmt[$name];
  469. else {
  470. if (!isset($WWCount[$name])) $WWCount[$name]=$WikiWordCountMax;
  471. if ($WWCount[$name]-- < 1) return $ref;
  472. }
  473. }
  474. $fmt=str_replace(array('$LinkText','$Fragment'),array($txt,$fragment),$fmt);
  475. return FmtPageName($fmt,$pname);
  476. }
  477. function XL($key) {
  478. global $XL,$XLLangs;
  479. foreach($XLLangs as $l) { if (isset($XL[$l][$key])) return $XL[$l][$key]; }
  480. return $key;
  481. }
  482. function XLSDV($lang,$a) {
  483. global $XL;
  484. foreach($a as $k=>$v) { if (!isset($XL[$lang][$k])) $XL[$lang][$k]=$v; }
  485. }
  486. function XLPage($lang,$p) {
  487. global $TimeFmt,$XLLangs,$FarmD;
  488. $page = ReadPage($p);
  489. if (!$page) return;
  490. $text = preg_replace("/=>\\s*\n/",'=> ',$page['text']);
  491. foreach(explode("\n",$text) as $l)
  492. if (preg_match('/^\\s*[\'"](.+?)[\'"]\\s*=>\\s*[\'"](.+)[\'"]/',$l,$match))
  493. $xl[stripslashes($match[1])] = stripslashes($match[2]);
  494. if ($xl) {
  495. if ($xl['xlpage-i18n']) {
  496. $i18n = preg_replace('/[^-\\w]/','',$xl['xlpage-i18n']);
  497. include_once("$FarmD/scripts/xlpage-$i18n.php");
  498. }
  499. if ($xl['Locale']) setlocale(LC_ALL,$xl['Locale']);
  500. if ($xl['TimeFmt']) $TimeFmt=$xl['TimeFmt'];
  501. array_unshift($XLLangs,$lang);
  502. XLSDV($lang,$xl);
  503. }
  504. }
  505. function FmtPageName($fmt,$pagename) {
  506. if (strpos($fmt,'$')===false) return $fmt;
  507. global $UnsafeGlobals,$GroupNamePattern,$PageTitlePattern,
  508. $PageUrlFmt,$EnablePathInfo,$PageNameFmt,$WikiWordPattern,$GCount,
  509. $AsSpacedFunction;
  510. static $g;
  511. static $qk = array('$ScriptUrl','$Groupspaced','$Group',
  512. '$Titlespaced','$Title_','$Title','$Tlink');
  513. if (!is_null($pagename) && !preg_match("/^($GroupNamePattern)[\\/.]($PageTitlePattern)\$/",$pagename,$match)) return "";
  514. $fmt = preg_replace('/\\$([A-Z]\\w*Fmt)\\b/e','$GLOBALS[\'$1\']',$fmt);
  515. $fmt = preg_replace("/\\$\\[(.+?)\\]/e","XL(stripslashes('$1'))",$fmt);
  516. $qv = @array($GLOBALS['ScriptUrl'],$AsSpacedFunction($match[1]),$match[1],
  517. $AsSpacedFunction($match[2]),$match[2],str_replace('_',' ',$match[2]),
  518. preg_match("/^$WikiWordPattern\$/",$match[2]) ? $match[2] :
  519. '{{'.str_replace('_',' ',$match[2]).'}}');
  520. $fmt=str_replace('$PageUrl',$PageUrlFmt,$fmt);
  521. $fmt=str_replace('$PageName',$PageNameFmt,$fmt);
  522. if (isset($EnablePathInfo) && !$EnablePathInfo)
  523. $fmt = preg_replace('!\\$ScriptUrl/([^\'"\\s?./]+)(?:[./]([^\'"\\s?]*))?(?:\\?([^\'"\\s]*))?!e',"'\$ScriptUrl?pagename=$1'.(('$2')?'.$2':'').(('$3')?'&amp;$3':'')",$fmt);
  524. $fmt=str_replace($qk,$qv,$fmt);
  525. if (strpos($fmt,'$')===false) return $fmt;
  526. if (count($GLOBALS)!=$GCount) {
  527. foreach($GLOBALS as $n=>$v) {
  528. if ($n == 'Text') continue;
  529. if (in_array($n,$UnsafeGlobals)) continue;
  530. if (is_array($v)) { $UnsafeGlobals[]=$n; continue; }
  531. $g["\$$n"]= $GLOBALS[$n];
  532. }
  533. $GCount = count($GLOBALS);
  534. krsort($g); reset($g);
  535. }
  536. if (isset($g[$fmt])) return $g[$fmt];
  537. $fmt = str_replace(array_keys($g),array_values($g),$fmt);
  538. $fmt = str_replace('$Text',
  539. @htmlspecialchars($GLOBALS['Text'],ENT_NOQUOTES),$fmt);
  540. return $fmt;
  541. }
  542. function Diff($oldtext,$newtext) {
  543. global $WikiDir,$SysDiffCmd;
  544. if (!$SysDiffCmd) return '';
  545. $tempold = tempnam($WikiDir,"old");
  546. if ($oldfp = fopen($tempold,"w")) {
  547. fputs($oldfp,$oldtext);
  548. fclose($oldfp);
  549. }
  550. $tempnew = tempnam($WikiDir,"new");
  551. if ($newfp = fopen($tempnew,"w")) {
  552. fputs($newfp,$newtext);
  553. fclose($newfp);
  554. }
  555. $diff = '';
  556. $diff_handle = popen("$SysDiffCmd $tempold $tempnew","r");
  557. if ($diff_handle) {
  558. while (!feof($diff_handle)) { $diff .= fread($diff_handle,1024); }
  559. pclose($diff_handle);
  560. }
  561. @unlink($tempold); @unlink($tempnew);
  562. return $diff;
  563. }
  564. function Patch($page,$restore) {
  565. $text = $page['text'];
  566. krsort($page); reset($page);
  567. $t = explode("\n",$text);
  568. $nl = (substr($text,-1)=="\n");
  569. if ($nl) array_pop($t);
  570. foreach($page as $k=>$v) {
  571. if ($k<$restore) break;
  572. if (substr($k,0,5)!='diff:') continue;
  573. foreach(explode("\n",$v) as $x) {
  574. if (preg_match('/^(\\d+)(,(\\d+))?([adc])(\\d+)/',$x,$match)) {
  575. $a1 = $a2 = $match[1];
  576. if ($match[3]) $a2=$match[3];
  577. $b1 = $match[5];
  578. if ($match[4]=='d') array_splice($t,$b1,$a2-$a1+1);
  579. if ($match[4]=='c') array_splice($t,$b1-1,$a2-$a1+1);
  580. continue;
  581. }
  582. if (substr($x,0,2)=='< ') { $nlflag=true; continue; }
  583. if (preg_match('/^> (.*)$/',$x,$match)) {
  584. $nlflag=false;
  585. array_splice($t,$b1-1,0,$match[1]); $b1++;
  586. }
  587. if ($x=='\\ No newline at end of file') $nl=$nlflag;
  588. }
  589. }
  590. if ($nl) $t[]='';
  591. return implode("\n",$t);
  592. }
  593. function PageExists($pagename) {
  594. global $WikiLibDirs,$PageFileFmt;
  595. $pagefile = FmtPageName($PageFileFmt,$pagename);
  596. if (!$pagefile) return false;
  597. foreach ($WikiLibDirs as $dir) {
  598. if (file_exists("$dir/$pagefile")) return true;
  599. }
  600. return false;
  601. }
  602. function Lock($op) {
  603. global $WikiDir;
  604. static $lockfp,$curop;
  605. if (!$lockfp) {
  606. $lockfp=fopen("$WikiDir/.flock","w") or
  607. Abort("Cannot acquire lockfile","Lockfile");
  608. }
  609. if ($op<0) { flock($lockfp,LOCK_UN); fclose($lockfp); $lockfp=0; $curop=0; }
  610. elseif ($op==0) { flock($lockfp,LOCK_UN); $curop=0; }
  611. elseif ($op==1 && $curop<1) { flock($lockfp,LOCK_SH); $curop=1; }
  612. elseif ($op==2 && $curop<2) { flock($lockfp,LOCK_EX); $curop=2; }
  613. }
  614. function ReadPage($pagename,$defaulttext=NULL) {
  615. global $WikiLibDirs,$PageFileFmt,$DefaultPageTextFmt,$Now,$TimeFmt;
  616. $pagefile = FmtPageName($PageFileFmt,$pagename);
  617. if (!$pagefile) return false;
  618. if (is_null($defaulttext)) $defaulttext=$DefaultPageTextFmt;
  619. $page["text"] = FmtPageName($defaulttext,$pagename);
  620. $page["time"] = $Now;
  621. $newline = "\262";
  622. Lock(1);
  623. foreach ($WikiLibDirs as $dir) {
  624. $fp = @fopen("$dir/$pagefile","r");
  625. if ($fp) break;
  626. }
  627. if ($fp) {
  628. while (!feof($fp)) {
  629. $line = fgets($fp,4096);
  630. while (!strstr($line,"\n") && !feof($fp)) { $line .= fgets($fp,4096); }
  631. @list($k,$v) = explode("=",rtrim($line),2);
  632. if ($k=='newline') { $newline=$v; continue; }
  633. $page[$k] = str_replace($newline,"\n",$v);
  634. }
  635. fclose($fp);
  636. }
  637. $page['timefmt'] = strftime($TimeFmt,$page['time']);
  638. return $page;
  639. }
  640. function WritePage($pagename,$page) {
  641. global $Now,$WikiDir,$PageFileFmt,$Version,$Newline;
  642. Lock(2);
  643. foreach (array('timefmt','pagename','action','version','newline') as $k)
  644. unset($page[$k]);
  645. $page['name'] = $pagename;
  646. $page['time'] = $Now;
  647. $page['host'] = $_SERVER['REMOTE_ADDR'];
  648. $page['agent'] = $_SERVER['HTTP_USER_AGENT'];
  649. $page['rev'] = @$page['rev']+1;
  650. $pagefile = FmtPageName("$WikiDir/$PageFileFmt",$pagename);
  651. $pagedir = preg_replace('#/[^/]*$#','',$pagefile);
  652. if ($pagedir) mkgiddir($pagedir);
  653. $s = false;
  654. if ($pagefile && ($fp=fopen("$pagefile.new","w"))) {
  655. $s = true && fputs($fp,"version=$Version\nnewline=$Newline\n");
  656. foreach($page as $k=>$v)
  657. if ($k>"") $s = $s && fputs($fp,str_replace("\n",$Newline,"$k=$v")."\n");
  658. $s = fclose($fp) && $s;
  659. if (file_exists($pagefile)) $s = $s && unlink($pagefile);
  660. $s = $s && rename("$pagefile.new",$pagefile);
  661. }
  662. if (!$s)
  663. Abort("Cannot write text to $pagename ($pagefile)...changes not saved");
  664. }
  665. function Keep($text) {
  666. global $KeepToken,$KPV,$KPCount;
  667. $KPCount++; $KPV[$KPCount]=$text;
  668. return $KeepToken.$KPCount.$KeepToken;
  669. }
  670. function KeepWikiEscapes($text) {
  671. $e0 = array('=' => '', '@' => '<code>');
  672. $e1 = array('=' => '', '@' => '</code>');
  673. return preg_replace("/\\[([=@])(.*?)\\1\\]/se",
  674. "Keep(\$e0['$1'].htmlspecialchars(str_replace('\\\"','\"','$2'),ENT_NOQUOTES).\$e1['$1'])",$text);
  675. }
  676. function QuoteAttrs($attr) {
  677. return preg_replace('/([a-zA-Z]=)([^\'"]\\S*)/',"\$1'\$2'",$attr);
  678. }
  679. function EmitCode($code,$depth,$attr="") {
  680. global $HTMLVSpace;
  681. static $cs,$vspaces;
  682. static $li = array('dl'=>'</dd>','ul'=>'</li>','ol'=>'</li>',
  683. 'indent' => '</div>');
  684. static $le = array('dl'=>'</dl>','ul'=>'</ul>','ol'=>'</ol>');
  685. $attr = QuoteAttrs($attr);
  686. if (!$cs) { $cs = array(); }
  687. if ($code=='p') { $vspaces.="\n"; return; }
  688. if ((@$cs[0]=='table' || @$cs[0]=='pre') && $code!=@$cs[0])
  689. while (count($cs)>0) { echo "</",array_pop($cs),">"; }
  690. while (count($cs)>$depth)
  691. { $c=array_pop($cs); echo @$li[$c],@$le[$c]; }
  692. if ($depth>0 && $depth==count($cs) && $cs[$depth-1]!=$code)
  693. { $c=array_pop($cs); echo @$li[$c],@$le[$c]; }
  694. if ($vspaces)
  695. { echo (@$cs[0]=='pre') ? $vspaces : $HTMLVSpace; $vspaces=''; }
  696. if ($depth==0) return;
  697. if ($depth==count($cs)) { echo @$li[$code]; return; }
  698. while (count($cs)<$depth-1) { array_push($cs,'dl'); echo '<dl><dd>'; }
  699. while (count($cs)<$depth) {
  700. array_push($cs,$code);
  701. if ($code!='indent') echo "<$code $attr>";
  702. }
  703. }
  704. function FormatTableRow($x,$cellattr) {
  705. $x = preg_replace("/\\|\\|\$/","",$x);
  706. $td = explode('||',$x); $y='';
  707. for($i=0;$i<count($td);$i++) {
  708. if ($td[$i]=='') continue;
  709. $attr=" $cellattr";
  710. if (preg_match('/^\\s+\$/',$td[$i])) $td[$i]='&nbsp;';
  711. if (preg_match('/^!(.*?)!$/',$td[$i],$match))
  712. { $td[$i]=$match[1]; $t='caption'; $attr=''; }
  713. elseif (preg_match('/^!(.*?)$/',$td[$i],$match))
  714. { $td[$i]=$match[1]; $t='th'; }
  715. else $t='td';
  716. if (preg_match('/^\\s.*\\s$/',$td[$i])) { $attr .= " align='center'"; }
  717. elseif (preg_match('/^\\s/',$td[$i])) { $attr .= " align='right'"; }
  718. elseif (preg_match('/\\s$/',$td[$i])) { $attr .= " align='left'"; }
  719. for($colspan=1;$i+$colspan<count($td);$colspan++)
  720. if ($td[$colspan+$i] != '') break;
  721. if ($colspan>1) { $attr .= " colspan='$colspan'"; }
  722. $y .= "<$t$attr>".$td[$i]."</$t>";
  723. }
  724. if ($t=='caption') return $y;
  725. return "<tr>$y</tr>";
  726. }
  727. function EmitCell($x,$y) {
  728. static $tableattr,$intable;
  729. $y = QuoteAttrs($y);
  730. if ($x == 'cell' || $x == 'cellnr') {
  731. if (!$intable) { echo "<table $tableattr><tr><td $y>"; $intable=1; }
  732. else if ($x == 'cellnr') { echo "</td></tr><tr><td $y>"; }
  733. else { echo "</td><td $y>"; }
  734. return;
  735. }
  736. if ($intable) { echo "</td></tr></table>"; $intable=0; }
  737. $tableattr = $y;
  738. }
  739. function ApplyStyles($x) {
  740. global $WikiStylePattern,$WikiStyle,$WikiStyleTags,$StyleToken;
  741. $lineparts = preg_split("/$StyleToken($WikiStylePattern)/",$x,-1,
  742. PREG_SPLIT_DELIM_CAPTURE);
  743. $out='';
  744. $style = array();
  745. while ($lineparts) {
  746. $WikiStyle['curr']=$style; $style = array();
  747. if (preg_match("/^$WikiStylePattern\$/",$lineparts[0])) {
  748. $slist=preg_split('/[^-#=:,\\w]+/',array_shift($lineparts),-1,
  749. PREG_SPLIT_NO_EMPTY);
  750. foreach($slist as $s) {
  751. if (preg_match('/^([^=:]+)[=:](.*)$/',$s,$match)) {
  752. $style[$match[1]] = $match[2];
  753. } else { $style = array_merge($style,(array)@$WikiStyle[$s]); }
  754. }
  755. if (@$style['define']) {
  756. $d = $style['define']; unset($style['define']);
  757. $WikiStyle[$d] = $style;
  758. }
  759. }
  760. $l = array_shift($lineparts);
  761. if ($l>"") {
  762. $styleattr = '';
  763. $classattr = '';
  764. foreach($style as $k=>$v) {
  765. if (!is_array($WikiStyleTags[$k])) continue;
  766. foreach($WikiStyleTags[$k] as $tag=>$w) {
  767. $w = str_replace('$value',$v,$w);
  768. if ($tag=='style') $styleattr.=$w;
  769. elseif ($tag=='class') $classattr=$w;
  770. else $l=preg_replace("/(<$tag )/","\$1$w ",$l);
  771. }
  772. }
  773. if ($styleattr) { $styleattr="style='$styleattr'"; }
  774. if ($styleattr || $classattr)
  775. $out .= "<span $classattr $styleattr>$l</span>";
  776. else $out .= $l;
  777. }
  778. }
  779. return $out;
  780. }
  781. function PrintText($pagename,$text="") {
  782. global $KeepToken,$KPV,$LinkToken,$LinkPatterns,$ImgExtPattern,
  783. $DoubleBrackets,$TableAttr,$TableCellAttr,$HTMLLineBreak,
  784. $InlineReplacements,$WikiStylePattern,$Text,$WWCount,$WikiWordCount;
  785. static $refcount;
  786. $WWCount=$WikiWordCount;
  787. if ($text=="") $text=$Text;
  788. ksort($LinkPatterns);
  789. foreach($LinkPatterns as $n=>$a)
  790. foreach($a as $p=>$r) $linkpats[$p]=$r;
  791. $lp=$LinkToken;
  792. $text = KeepWikiEscapes($text);
  793. $text = htmlspecialchars($text,ENT_NOQUOTES);
  794. $text = str_replace("\r","",$text);
  795. $text = preg_replace("/(\\\\*)\\\\\n/e",
  796. "' '.str_repeat('<br />',strlen('$1'))",$text);
  797. foreach($DoubleBrackets as $n=>$fmt) {
  798. if ($n[0]!='/') $text=str_replace($n,FmtPageName($fmt,$pagename),$text);
  799. }
  800. $lines = explode("\n",$text);
  801. foreach($lines as $x) {
  802. foreach($DoubleBrackets as $n=>$fmt) {
  803. if ($n[0]=='/') $x=preg_replace($n,$fmt,$x);
  804. }
  805. $lpcount = 0;
  806. $lpv = array();
  807. foreach($linkpats as $pat=>$rep) {
  808. $re = "/\\[\\[($pat)(\\s.*?)?(\\]\\])/";
  809. while(preg_match($re,$x,$match)) {
  810. $x=preg_replace($re,"$lp$lpcount$lp",$x,1);
  811. array_pop($match); $txt=array_pop($match);
  812. if ($txt=="") $txt="$lp#$lp";
  813. else {
  814. $txt = ltrim($txt);
  815. if (preg_match("/$ImgExtPattern\$/",$txt)) {
  816. foreach($linkpats as $p=>$r) {
  817. if (preg_match("/^$p\$/",$txt)) {
  818. if (function_exists($r)) $txt = $r($p,$txt,NULL);
  819. else $txt = preg_replace($p,$r,$txt);
  820. break;
  821. }
  822. }
  823. }
  824. }
  825. if (function_exists($rep))
  826. $txt = $rep($pat,$match[1],$txt);
  827. else {
  828. $r = preg_replace("/^$pat\$/",$rep,$match[1]);
  829. preg_match("/(name|href)='.*?'/",$r,$match);
  830. $txt = "<a ".@$match[0].">$txt</a>";
  831. }
  832. $lpv[$lpcount++] = $txt;
  833. }
  834. }
  835. foreach($linkpats as $pat=>$rep) {
  836. $re = "/($pat)/";
  837. while(preg_match($re,$x,$match)) {
  838. $x=preg_replace($re,"$lp$lpcount$lp",$x,1);
  839. if (function_exists($rep))
  840. $txt = $rep($pat,$match[1],NULL);
  841. else $txt = preg_replace("/^$pat\$/",$rep,$match[1]);
  842. $lpv[$lpcount++] = $txt;
  843. }
  844. }
  845. if (preg_match("/^\\[\\[(table|cell|cellnr|tableend)(\\s.*?)?\\]\\]/",$x,$match)) {
  846. EmitCode("",0);
  847. @EmitCell($match[1],$match[2]);
  848. $x=preg_replace("/^\\[\\[.*?\\]\\]/","",$x);
  849. }
  850. else if (preg_match("/^\\s*\$/",$x)) { EmitCode("p",0); continue; }
  851. if (preg_match("/^(:+)[^:]*:/",$x,$match)) {
  852. $x=preg_replace("/^:+([^:]*):/","<dt>\\1</dt><dd>",$x);
  853. EmitCode("dl",strlen($match[1]));
  854. } elseif (preg_match("/^(\\*+)/",$x,$match)) {
  855. $x=preg_replace("/^\\*+/","<li>",$x);
  856. EmitCode("ul",strlen($match[1]));
  857. } elseif (preg_match("/^(#+)/",$x,$match)) {
  858. $x=preg_replace("/^#+/","<li>",$x);
  859. EmitCode("ol",strlen($match[1]));
  860. } elseif (preg_match("/^\s/",$x)) {
  861. EmitCode("pre",1);
  862. } elseif (preg_match("/^\\|\\|.*\\|\\|/",$x,$match)) {
  863. EmitCode("table",1,$TableAttr);
  864. $x=FormatTableRow($x,$TableCellAttr);
  865. } elseif (preg_match("/^\\|\\|(.*)/",$x,$match)) {
  866. EmitCode("",0);
  867. $TableAttr = $match[1];
  868. continue;
  869. } elseif (preg_match("/^(!{1,6})/",$x,$match)) {
  870. $h="h".strlen($match[1]);
  871. $x=preg_replace("/^(!{1,6})/","<$h>",$x)."</$h>";
  872. EmitCode("",0);
  873. } elseif (preg_match("/^(-+)&gt;/",$x,$match)) {
  874. $x=preg_replace("/^(-+)&gt;/","<div class='indent'>",$x);
  875. EmitCode("indent",strlen($match[1]));
  876. } else { $x.=$HTMLLineBreak; EmitCode("",0); }
  877. foreach ($InlineReplacements as $pat => $rep)
  878. $x = preg_replace($pat,$rep,$x);
  879. if (preg_match("/^\\s*($lp(\\d+)$lp)\\s*\$/",$x,$match))
  880. $x = str_replace(" img>"," /><br />",$lpv[$match[2]]);
  881. if (preg_match("/^\\s*($lp(\\d+)$lp).*\\S/",$x,$match))
  882. $x = str_replace($match[1],
  883. str_replace(" img>"," align='left' />",$lpv[$match[2]]), $x);
  884. if (preg_match("/\\S.*($lp(\\d+)$lp)\\s*\$/",$x,$match)) {
  885. $rt = str_replace(" img>"," align='right' />",$lpv[$match[2]]);
  886. if (strstr($rt,"<img")) $x=$rt.str_replace($match[1],"",$x);
  887. else $x=str_replace($match[1],$rt,$x);
  888. }
  889. $x = preg_replace("/$lp(\\d+)$lp/e",
  890. 'str_replace(" img>"," />",$lpv[$1])',$x);
  891. $x = preg_replace("/$lp#$lp/e",'"[".++$refcount."]"',$x);
  892. if ($WikiStylePattern) $x = ApplyStyles($x);
  893. while (preg_match("/$KeepToken(\\d+?)$KeepToken/",$x))
  894. $x = preg_replace("/$KeepToken(\\d+?)$KeepToken/e",'$KPV[$1]',$x);
  895. echo $x,"\n";
  896. }
  897. EmitCode("",0);
  898. EmitCell("","");
  899. }
  900. function PrintWikiPage($pagename,$wikilist=NULL) {
  901. global $PrintWikiPageNotFoundFmt;
  902. if (is_null($wikilist)) $wikilist=$pagename;
  903. $pagelist = preg_split('/\s+/',$wikilist,-1,PREG_SPLIT_NO_EMPTY);
  904. foreach($pagelist as $p) {
  905. if (PageExists($p)) {
  906. $page = RetrieveAuthPage($p,"read",false);
  907. if ($page['text'])
  908. PrintText($pagename,ProcessIncludes($pagename,$page['text']));
  909. return;
  910. }
  911. }
  912. if ($PrintWikiPageNotFoundFmt>'')
  913. print FmtPageName(@$PrintWikiPageNotFoundFmt,array_pop($pagelist));
  914. }
  915. function ProcessIncludes($pagename,$text="") {
  916. global $MaxIncludes,$IncludeBadAnchorFmt,$GroupNamePattern,$PageTitlePattern;
  917. $inclcount=0;
  918. while ($inclcount<$MaxIncludes &&
  919. preg_match("/\\[\\[include:(($GroupNamePattern([\\/.]))?$PageTitlePattern)(#(\\w[-.:\\w]*)?(#(\\w[-.:\\w]*)?)?)?\\]\\]/",$text,$match)) {
  920. list($inclrepl,$inclname,$group,$dot,$a,$aa,$b,$bb) = $match;
  921. if (!$group) $inclname=FmtPageName('$Group.',$pagename).$inclname;
  922. $inclpage = RetrieveAuthPage($inclname,"read",false);
  923. $incltext = $inclpage['text'];
  924. $badanchor = '';
  925. if ($bb && !preg_match('/^\\d+$/',$bb) &&
  926. strpos($incltext,"[[#$bb]]")===false) $badanchor=$bb;
  927. if ($aa && !preg_match('/^\\d+$/',$aa) &&
  928. strpos($incltext,"[[#$aa]]")===false) $badanchor=$aa;
  929. if ($badanchor)
  930. $incltext=FmtPageName(str_replace('$BadAnchor',$badanchor,
  931. $IncludeBadAnchorFmt),$inclname);
  932. if (preg_match('/^\\d+$/',$bb))
  933. $incltext=preg_replace("/^(([^\\n]*\\n)\{0,$bb}).*$/s",'$1',$incltext,1);
  934. elseif ($bb)
  935. $incltext=preg_replace("/[^\\n]*\\[\\[#$bb\\]\\].*$/s",'',$incltext,1);
  936. if (preg_match('/^\\d+$/',$aa)) {
  937. $aa--; $incltext=preg_replace("/^([^\\n]*\\n)\{0,$aa}/s",'',$incltext,1);
  938. if (!$b) $incltext=preg_replace("/\\n.*$/s",'',$incltext);
  939. } elseif ($aa && $b)
  940. $incltext=preg_replace("/^.*?([^\\n]*\\[\\[#$aa\\]\\])/s",'$1',$incltext,1);
  941. elseif ($aa)
  942. $incltext=preg_replace("/^.*?([^\\n]*\\[\\[#$aa\\]\\]( *\\n)?[^\\n]*).*/s",'$1',$incltext,1);
  943. $text = str_replace($inclrepl,$incltext,$text);
  944. $inclcount++;
  945. }
  946. return $text;
  947. }
  948. function ProcessTextDirectives($pagename,$text="") {
  949. global $Text,$GroupHeaderFmt,$GroupFooterFmt,$BrowseDirectives;
  950. if (!$text) $text=$Text;
  951. $text = KeepWikiEscapes($text);
  952. $text = ProcessIncludes($pagename,$text);
  953. if (!strstr($text,"[[nogroupheader]]")) {
  954. $hdname = FmtPageName($GroupHeaderFmt,$pagename);
  955. if ($hdname != $pagename) {
  956. $hdpage=ReadPage($hdname,"");
  957. if ($hdpage['text'] && substr($hdpage['text'],-1,1)!="\n" &&
  958. substr($text,0,1)!="\n") $hdpage['text'] .= "\n";
  959. $text = $hdpage['text'].$text;
  960. }
  961. }
  962. if (!strstr($text,"[[nogroupfooter]]")) {
  963. $hdname = FmtPageName($GroupFooterFmt,$pagename);
  964. if ($hdname != $pagename) {
  965. $hdpage=ReadPage($hdname,"");
  966. if ($hdpage['text'] && substr($hdpage['text'],0,1)!="\n" &&
  967. substr($text,-1,1)!="\n") $text .= "\n";
  968. $text .= $hdpage['text'];
  969. }
  970. }
  971. Lock(0);
  972. foreach($BrowseDirectives as $p=>$s) {
  973. if ($p[0]=='/') $text=preg_replace($p,$s,$text);
  974. else if (strstr($text,$p)) $text = str_replace($p,eval($s),$text);
  975. }
  976. $Text = $text;
  977. }
  978. function HandleBrowse($pagename) {
  979. global $Text,$PageRedirectFmt,$RedirectPattern,
  980. $HandleBrowseFmt,$PageStartFmt,$PageEndFmt;
  981. $page = RetrieveAuthPage($pagename,"read");
  982. if (!$page) { Abort("Invalid page name"); }
  983. $Text = $page['text'];
  984. SetPageVars($pagename,$page,$pagename);
  985. if (@!$_GET['from']) {
  986. $PageRedirectFmt = '';
  987. if (preg_match("/$RedirectPattern/",$Text,$match)) {
  988. $rpage = FmtWikiLink('',$match[1],NULL,'PageName',$pagename);
  989. if (PageExists($rpage)) Redirect($rpage,"\$PageUrl?from=$pagename");
  990. }
  991. }
  992. else $PageRedirectFmt = FmtPageName($PageRedirectFmt,$_GET['from']);
  993. ProcessTextDirectives($pagename);
  994. SDV($HandleBrowseFmt,array(&$PageStartFmt,
  995. &$PageRedirectFmt,'function:PrintText',
  996. &$PageEndFmt));
  997. PrintFmt($pagename,$HandleBrowseFmt);
  998. }
  999. function HandleEdit($pagename) {
  1000. global $restore,$preview,$HandleActions,$Text,
  1001. $HandleEditFmt,$PageStartFmt,$PageEditFmt,$PagePreviewFmt,$PageEndFmt,
  1002. $DiffClassMinor,$PatchFunction;
  1003. if (@$_POST['post'])
  1004. { $handle = $HandleActions['post']; return $handle($pagename); }
  1005. $page = RetrieveAuthPage($pagename,"edit");
  1006. if (!$page) { Abort("?cannot edit $pagename"); }
  1007. SetPageVars($pagename,$page,"Edit $pagename");
  1008. if ($restore && $PatchFunction) { $text = $PatchFunction($page,$restore); }
  1009. else if ($preview) { $text = stripmagic($_POST['text']); }
  1010. else { $text = $page['text']; }
  1011. $Text = $text;
  1012. $DiffClassMinor = '';
  1013. if (@$_POST['diffclass']=='minor') $DiffClassMinor="checked='checked'";
  1014. SDV($HandleEditFmt,array(&$PageStartFmt,
  1015. &$PageEditFmt,&$PagePreviewFmt,
  1016. &$PageEndFmt));
  1017. PrintFmt($pagename,$HandleEditFmt);
  1018. }
  1019. function HandlePost($pagename) {
  1020. global $WikiDir,$DeleteKeyWord,$RecentChanges,$RCDelimPattern,$Now,
  1021. $TimeFmt,$CurrentTime,$PageFileFmt,$DiffKeepDays,$Author,$PostFields,
  1022. $DiffFunction,$ChangeSummary;
  1023. $CurrentTime = strftime($TimeFmt,$Now);
  1024. foreach($PostFields as $k) {
  1025. if (isset($_POST[$k]))
  1026. $new[$k]=str_replace("\r","",stripmagic($_POST[$k]));
  1027. }
  1028. Lock(2);
  1029. $page = RetrieveAuthPage($pagename,"edit");
  1030. if (!$page) { Abort("?cannot post $pagename"); }
  1031. $pagename = FmtPageName('$PageName',$pagename);
  1032. if ($new['text']==$page['text'])
  1033. { Redirect($pagename); return; }
  1034. $diffclass=preg_replace('/\\W/','',@$_POST['diffclass']);
  1035. if ($page["time"]>0)
  1036. $new["diff:$Now:".$page['time'].":$diffclass"] =
  1037. $DiffFunction($new['text'],$page['text']);
  1038. $new['author'] = $Author;
  1039. $new["author:$Now"] = $Author;
  1040. $new["host:$Now"] = $_SERVER['REMOTE_ADDR'];
  1041. if ($ChangeSummary) $new["csum:$Now"] = $ChangeSummary;
  1042. foreach($new as $k=>$v) {
  1043. if ($k=='pagename' || $k=='action') continue;
  1044. $page[$k] = $v;
  1045. }
  1046. $keepgmt = $Now-$DiffKeepDays*86400;
  1047. $keys = array_keys($page);
  1048. foreach ($keys as $k)
  1049. if (preg_match("/^\\w+:(\\d+)/",$k,$match))
  1050. if ($match[1] < $keepgmt) unset($page[$k]);
  1051. $pagefile = FmtPageName($PageFileFmt,$pagename);
  1052. if ($page['text']==$DeleteKeyWord)
  1053. { @rename("$WikiDir/$pagefile","$WikiDir/$pagefile,$Now"); }
  1054. else WritePage($pagename,$page);
  1055. foreach($RecentChanges as $rcfmt => $pgfmt) {
  1056. $rcname=FmtPageName($rcfmt,$pagename); if (!$rcname) continue;
  1057. $pgtext=FmtPageName($pgfmt,$pagename); if (!$pgtext) continue;
  1058. if (@$seen[$rcname]++) continue;
  1059. $rcpage = ReadPage($rcname,"");
  1060. $rcelim = preg_quote(preg_replace("/$RCDelimPattern.*$/",' ',$pgtext),'/');
  1061. $rcpage['text'] = preg_replace("/[^\n]*$rcelim.*\n/","",$rcpage['text']);
  1062. if (!preg_match("/$RCDelimPattern/",$rcpage['text']))
  1063. $rcpage['text'] .= "$pgtext\n";
  1064. else
  1065. $rcpage['text'] = preg_replace("/([^\n]*$RCDelimPattern.*\n)/",
  1066. "$pgtext\n$1",$rcpage['text'],1);
  1067. WritePage($rcname,$rcpage);
  1068. }
  1069. Redirect($pagename);
  1070. }
  1071. function HandleSource($pagename) {
  1072. $page = RetrieveAuthPage($pagename,"read");
  1073. if (!$page) Abort("?cannot source $pagename");
  1074. Lock(0);
  1075. header("Content-Type: text/plain");
  1076. echo $page['text'];
  1077. }
  1078. function BasicAuth($pagename,$level,$authprompt=true) {
  1079. global $AuthRealmFmt,$AuthDeniedFmt,$DefaultPasswords,
  1080. $AllowPassword,$GroupAttributesFmt;
  1081. $page = ReadPage($pagename);
  1082. if (!$page) { return false; }
  1083. @$passwd = $page["passwd$level"];
  1084. if ($passwd=="") {
  1085. $grouppg = ReadPage(FmtPageName($GroupAttributesFmt,$pagename));
  1086. @$passwd = $grouppg["passwd$level"];
  1087. }
  1088. if (crypt($AllowPassword,$passwd)==$passwd) return $page;
  1089. if ($passwd=="") { $passwd=@$DefaultPasswords[$level]; }
  1090. if ($passwd=="") return $page;
  1091. foreach (array_merge((array)$DefaultPasswords['admin'],(array)$passwd) as $pw)
  1092. if (@crypt($_SERVER['PHP_AUTH_PW'],$pw)==$pw) return $page;
  1093. if (!$authprompt) return false;
  1094. $realm=FmtPageName($AuthRealmFmt,$pagename);
  1095. header("WWW-Authenticate: Basic realm=\"$realm\"");
  1096. header("Status: 401 Unauthorized");
  1097. header("HTTP-Status: 401 Unauthorized");
  1098. PrintFmt($pagename,$AuthDeniedFmt);
  1099. exit;
  1100. }
  1101. function RetrieveAuthPage($pagename,$level,$authprompt=true) {
  1102. global $AuthFunction;
  1103. if (!function_exists($AuthFunction))
  1104. Abort("?Invalid AuthFunction specified: $AuthFunction","AuthFunction");
  1105. return $AuthFunction($pagename,$level,$authprompt);
  1106. }
  1107. function PrintAttrForm($pagename) {
  1108. global $PageAttributes;
  1109. echo FmtPageName("<form action='\$PageUrl' method='post'>
  1110. <input type='hidden' name='action' value='postattr' />
  1111. <input type='hidden' name='pagename' value='$PageName' />
  1112. <table>",$pagename);
  1113. foreach($PageAttributes as $attr=>$p) {
  1114. $value = (substr($attr,0,6)=='passwd') ? '' : $page[$k];
  1115. $prompt = FmtPageName($p,$pagename);
  1116. echo "<tr><td>$prompt</td>
  1117. <td><input type='text' name='$attr' value='$value' /></td></tr>";
  1118. }
  1119. echo "</table><input type='submit' /></form>";
  1120. }
  1121. function HandleAttr($pagename) {
  1122. global $HandleAttrFmt,$PageStartFmt,$PageAttrFmt,$PageEndFmt;
  1123. $page = RetrieveAuthPage($pagename,"attr");
  1124. if (!$page) { Abort("?unable to read $pagename"); }
  1125. SetPageVars($pagename,$page,"Edit $pagename Attributes");
  1126. SDV($HandleAttrFmt,array(&$PageStartFmt,
  1127. &$PageAttrFmt,'function:PrintAttrForm',
  1128. &$PageEndFmt));
  1129. PrintFmt($pagename,$HandleAttrFmt);
  1130. }
  1131. function HandlePostAttr($pagename) {
  1132. global $PageAttributes;
  1133. $page = RetrieveAuthPage($pagename,"attr");
  1134. if (!$page) { Abort("?cannot get $pagename"); }
  1135. foreach($PageAttributes as $k=>$v) {
  1136. $newpw = $_POST[$k];
  1137. if ($newpw=="clear") unset($page[$k]);
  1138. else if ($newpw>"") $page[$k]=crypt($newpw);
  1139. }
  1140. WritePage($pagename,$page);
  1141. Redirect($pagename);
  1142. exit;
  1143. }
  1144. ?>