pmwiki.php 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212
  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'>\$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. if( preg_match_all( '|http://|', $page['text'], $arMatches) > 20) { die( 'too many links'); }
  643. Lock(2);
  644. foreach (array('timefmt','pagename','action','version','newline') as $k)
  645. unset($page[$k]);
  646. $page['name'] = $pagename;
  647. $page['time'] = $Now;
  648. $page['host'] = $_SERVER['REMOTE_ADDR'];
  649. $page['agent'] = $_SERVER['HTTP_USER_AGENT'];
  650. $page['rev'] = @$page['rev']+1;
  651. $pagefile = FmtPageName("$WikiDir/$PageFileFmt",$pagename);
  652. $pagedir = preg_replace('#/[^/]*$#','',$pagefile);
  653. if ($pagedir) mkgiddir($pagedir);
  654. $s = false;
  655. if ($pagefile && ($fp=fopen("$pagefile.new","w"))) {
  656. $s = true && fputs($fp,"version=$Version\nnewline=$Newline\n");
  657. foreach($page as $k=>$v)
  658. if ($k>"") $s = $s && fputs($fp,str_replace("\n",$Newline,"$k=$v")."\n");
  659. $s = fclose($fp) && $s;
  660. if (file_exists($pagefile)) $s = $s && unlink($pagefile);
  661. $s = $s && rename("$pagefile.new",$pagefile);
  662. }
  663. if (!$s)
  664. Abort("Cannot write text to $pagename ($pagefile)...changes not saved");
  665. }
  666. function Keep($text) {
  667. global $KeepToken,$KPV,$KPCount;
  668. $KPCount++; $KPV[$KPCount]=$text;
  669. return $KeepToken.$KPCount.$KeepToken;
  670. }
  671. function KeepWikiEscapes($text) {
  672. $e0 = array('=' => '', '@' => '<code>');
  673. $e1 = array('=' => '', '@' => '</code>');
  674. return preg_replace("/\\[([=@])(.*?)\\1\\]/se",
  675. "Keep(\$e0['$1'].htmlspecialchars(str_replace('\\\"','\"','$2'),ENT_NOQUOTES).\$e1['$1'])",$text);
  676. }
  677. function QuoteAttrs($attr) {
  678. return preg_replace('/([a-zA-Z]=)([^\'"]\\S*)/',"\$1'\$2'",$attr);
  679. }
  680. function EmitCode($code,$depth,$attr="") {
  681. global $HTMLVSpace;
  682. static $cs,$vspaces;
  683. static $li = array('dl'=>'</dd>','ul'=>'</li>','ol'=>'</li>',
  684. 'indent' => '</div>');
  685. static $le = array('dl'=>'</dl>','ul'=>'</ul>','ol'=>'</ol>');
  686. $attr = QuoteAttrs($attr);
  687. if (!$cs) { $cs = array(); }
  688. if ($code=='p') { $vspaces.="\n"; return; }
  689. if ((@$cs[0]=='table' || @$cs[0]=='pre') && $code!=@$cs[0])
  690. while (count($cs)>0) { echo "</",array_pop($cs),">"; }
  691. while (count($cs)>$depth)
  692. { $c=array_pop($cs); echo @$li[$c],@$le[$c]; }
  693. if ($depth>0 && $depth==count($cs) && $cs[$depth-1]!=$code)
  694. { $c=array_pop($cs); echo @$li[$c],@$le[$c]; }
  695. if ($vspaces)
  696. { echo (@$cs[0]=='pre') ? $vspaces : $HTMLVSpace; $vspaces=''; }
  697. if ($depth==0) return;
  698. if ($depth==count($cs)) { echo @$li[$code]; return; }
  699. while (count($cs)<$depth-1) { array_push($cs,'dl'); echo '<dl><dd>'; }
  700. while (count($cs)<$depth) {
  701. array_push($cs,$code);
  702. if ($code!='indent') echo "<$code $attr>";
  703. }
  704. }
  705. function FormatTableRow($x,$cellattr) {
  706. $x = preg_replace("/\\|\\|\$/","",$x);
  707. $td = explode('||',$x); $y='';
  708. for($i=0;$i<count($td);$i++) {
  709. if ($td[$i]=='') continue;
  710. $attr=" $cellattr";
  711. if (preg_match('/^\\s+\$/',$td[$i])) $td[$i]='&nbsp;';
  712. if (preg_match('/^!(.*?)!$/',$td[$i],$match))
  713. { $td[$i]=$match[1]; $t='caption'; $attr=''; }
  714. elseif (preg_match('/^!(.*?)$/',$td[$i],$match))
  715. { $td[$i]=$match[1]; $t='th'; }
  716. else $t='td';
  717. if (preg_match('/^\\s.*\\s$/',$td[$i])) { $attr .= " align='center'"; }
  718. elseif (preg_match('/^\\s/',$td[$i])) { $attr .= " align='right'"; }
  719. elseif (preg_match('/\\s$/',$td[$i])) { $attr .= " align='left'"; }
  720. for($colspan=1;$i+$colspan<count($td);$colspan++)
  721. if ($td[$colspan+$i] != '') break;
  722. if ($colspan>1) { $attr .= " colspan='$colspan'"; }
  723. $y .= "<$t$attr>".$td[$i]."</$t>";
  724. }
  725. if ($t=='caption') return $y;
  726. return "<tr>$y</tr>";
  727. }
  728. function EmitCell($x,$y) {
  729. static $tableattr,$intable;
  730. $y = QuoteAttrs($y);
  731. if ($x == 'cell' || $x == 'cellnr') {
  732. if (!$intable) { echo "<table $tableattr><tr><td $y>"; $intable=1; }
  733. else if ($x == 'cellnr') { echo "</td></tr><tr><td $y>"; }
  734. else { echo "</td><td $y>"; }
  735. return;
  736. }
  737. if ($intable) { echo "</td></tr></table>"; $intable=0; }
  738. $tableattr = $y;
  739. }
  740. function ApplyStyles($x) {
  741. global $WikiStylePattern,$WikiStyle,$WikiStyleTags,$StyleToken;
  742. $lineparts = preg_split("/$StyleToken($WikiStylePattern)/",$x,-1,
  743. PREG_SPLIT_DELIM_CAPTURE);
  744. $out='';
  745. $style = array();
  746. while ($lineparts) {
  747. $WikiStyle['curr']=$style; $style = array();
  748. if (preg_match("/^$WikiStylePattern\$/",$lineparts[0])) {
  749. $slist=preg_split('/[^-#=:,\\w]+/',array_shift($lineparts),-1,
  750. PREG_SPLIT_NO_EMPTY);
  751. foreach($slist as $s) {
  752. if (preg_match('/^([^=:]+)[=:](.*)$/',$s,$match)) {
  753. $style[$match[1]] = $match[2];
  754. } else { $style = array_merge($style,(array)@$WikiStyle[$s]); }
  755. }
  756. if (@$style['define']) {
  757. $d = $style['define']; unset($style['define']);
  758. $WikiStyle[$d] = $style;
  759. }
  760. }
  761. $l = array_shift($lineparts);
  762. if ($l>"") {
  763. $styleattr = '';
  764. $classattr = '';
  765. foreach($style as $k=>$v) {
  766. if (!is_array($WikiStyleTags[$k])) continue;
  767. foreach($WikiStyleTags[$k] as $tag=>$w) {
  768. $w = str_replace('$value',$v,$w);
  769. if ($tag=='style') $styleattr.=$w;
  770. elseif ($tag=='class') $classattr=$w;
  771. else $l=preg_replace("/(<$tag )/","\$1$w ",$l);
  772. }
  773. }
  774. if ($styleattr) { $styleattr="style='$styleattr'"; }
  775. if ($styleattr || $classattr)
  776. $out .= "<span $classattr $styleattr>$l</span>";
  777. else $out .= $l;
  778. }
  779. }
  780. return $out;
  781. }
  782. function PrintText($pagename,$text="") {
  783. global $KeepToken,$KPV,$LinkToken,$LinkPatterns,$ImgExtPattern,
  784. $DoubleBrackets,$TableAttr,$TableCellAttr,$HTMLLineBreak,
  785. $InlineReplacements,$WikiStylePattern,$Text,$WWCount,$WikiWordCount;
  786. static $refcount;
  787. $WWCount=$WikiWordCount;
  788. if ($text=="") $text=$Text;
  789. ksort($LinkPatterns);
  790. foreach($LinkPatterns as $n=>$a)
  791. foreach($a as $p=>$r) $linkpats[$p]=$r;
  792. $lp=$LinkToken;
  793. $text = KeepWikiEscapes($text);
  794. $text = htmlspecialchars($text,ENT_NOQUOTES);
  795. $text = str_replace("\r","",$text);
  796. $text = preg_replace("/(\\\\*)\\\\\n/e",
  797. "' '.str_repeat('<br />',strlen('$1'))",$text);
  798. foreach($DoubleBrackets as $n=>$fmt) {
  799. if ($n[0]!='/') $text=str_replace($n,FmtPageName($fmt,$pagename),$text);
  800. }
  801. $lines = explode("\n",$text);
  802. foreach($lines as $x) {
  803. foreach($DoubleBrackets as $n=>$fmt) {
  804. if ($n[0]=='/') $x=preg_replace($n,$fmt,$x);
  805. }
  806. $lpcount = 0;
  807. $lpv = array();
  808. foreach($linkpats as $pat=>$rep) {
  809. $re = "/\\[\\[($pat)(\\s.*?)?(\\]\\])/";
  810. while(preg_match($re,$x,$match)) {
  811. $x=preg_replace($re,"$lp$lpcount$lp",$x,1);
  812. array_pop($match); $txt=array_pop($match);
  813. if ($txt=="") $txt="$lp#$lp";
  814. else {
  815. $txt = ltrim($txt);
  816. if (preg_match("/$ImgExtPattern\$/",$txt)) {
  817. foreach($linkpats as $p=>$r) {
  818. if (preg_match("/^$p\$/",$txt)) {
  819. if (function_exists($r)) $txt = $r($p,$txt,NULL);
  820. else $txt = preg_replace($p,$r,$txt);
  821. break;
  822. }
  823. }
  824. }
  825. }
  826. if (function_exists($rep))
  827. $txt = $rep($pat,$match[1],$txt);
  828. else {
  829. $r = preg_replace("/^$pat\$/",$rep,$match[1]);
  830. preg_match("/(name|href)='.*?'/",$r,$match);
  831. $txt = "<a ".@$match[0].">$txt</a>";
  832. }
  833. $lpv[$lpcount++] = $txt;
  834. }
  835. }
  836. foreach($linkpats as $pat=>$rep) {
  837. $re = "/($pat)/";
  838. while(preg_match($re,$x,$match)) {
  839. $x=preg_replace($re,"$lp$lpcount$lp",$x,1);
  840. if (function_exists($rep))
  841. $txt = $rep($pat,$match[1],NULL);
  842. else $txt = preg_replace("/^$pat\$/",$rep,$match[1]);
  843. $lpv[$lpcount++] = $txt;
  844. }
  845. }
  846. if (preg_match("/^\\[\\[(table|cell|cellnr|tableend)(\\s.*?)?\\]\\]/",$x,$match)) {
  847. EmitCode("",0);
  848. @EmitCell($match[1],$match[2]);
  849. $x=preg_replace("/^\\[\\[.*?\\]\\]/","",$x);
  850. }
  851. else if (preg_match("/^\\s*\$/",$x)) { EmitCode("p",0); continue; }
  852. if (preg_match("/^(:+)[^:]*:/",$x,$match)) {
  853. $x=preg_replace("/^:+([^:]*):/","<dt>\\1</dt><dd>",$x);
  854. EmitCode("dl",strlen($match[1]));
  855. } elseif (preg_match("/^(\\*+)/",$x,$match)) {
  856. $x=preg_replace("/^\\*+/","<li>",$x);
  857. EmitCode("ul",strlen($match[1]));
  858. } elseif (preg_match("/^(#+)/",$x,$match)) {
  859. $x=preg_replace("/^#+/","<li>",$x);
  860. EmitCode("ol",strlen($match[1]));
  861. } elseif (preg_match("/^\s/",$x)) {
  862. EmitCode("pre",1);
  863. } elseif (preg_match("/^\\|\\|.*\\|\\|/",$x,$match)) {
  864. EmitCode("table",1,$TableAttr);
  865. $x=FormatTableRow($x,$TableCellAttr);
  866. } elseif (preg_match("/^\\|\\|(.*)/",$x,$match)) {
  867. EmitCode("",0);
  868. $TableAttr = $match[1];
  869. continue;
  870. } elseif (preg_match("/^(!{1,6})/",$x,$match)) {
  871. $h="h".strlen($match[1]);
  872. $x=preg_replace("/^(!{1,6})/","<$h>",$x)."</$h>";
  873. EmitCode("",0);
  874. } elseif (preg_match("/^(-+)&gt;/",$x,$match)) {
  875. $x=preg_replace("/^(-+)&gt;/","<div class='indent'>",$x);
  876. EmitCode("indent",strlen($match[1]));
  877. } else { $x.=$HTMLLineBreak; EmitCode("",0); }
  878. foreach ($InlineReplacements as $pat => $rep)
  879. $x = preg_replace($pat,$rep,$x);
  880. if (preg_match("/^\\s*($lp(\\d+)$lp)\\s*\$/",$x,$match))
  881. $x = str_replace(" img>"," /><br />",$lpv[$match[2]]);
  882. if (preg_match("/^\\s*($lp(\\d+)$lp).*\\S/",$x,$match))
  883. $x = str_replace($match[1],
  884. str_replace(" img>"," align='left' />",$lpv[$match[2]]), $x);
  885. if (preg_match("/\\S.*($lp(\\d+)$lp)\\s*\$/",$x,$match)) {
  886. $rt = str_replace(" img>"," align='right' />",$lpv[$match[2]]);
  887. if (strstr($rt,"<img")) $x=$rt.str_replace($match[1],"",$x);
  888. else $x=str_replace($match[1],$rt,$x);
  889. }
  890. $x = preg_replace("/$lp(\\d+)$lp/e",
  891. 'str_replace(" img>"," />",$lpv[$1])',$x);
  892. $x = preg_replace("/$lp#$lp/e",'"[".++$refcount."]"',$x);
  893. if ($WikiStylePattern) $x = ApplyStyles($x);
  894. while (preg_match("/$KeepToken(\\d+?)$KeepToken/",$x))
  895. $x = preg_replace("/$KeepToken(\\d+?)$KeepToken/e",'$KPV[$1]',$x);
  896. echo $x,"\n";
  897. }
  898. EmitCode("",0);
  899. EmitCell("","");
  900. }
  901. function PrintWikiPage($pagename,$wikilist=NULL) {
  902. global $PrintWikiPageNotFoundFmt;
  903. if (is_null($wikilist)) $wikilist=$pagename;
  904. $pagelist = preg_split('/\s+/',$wikilist,-1,PREG_SPLIT_NO_EMPTY);
  905. foreach($pagelist as $p) {
  906. if (PageExists($p)) {
  907. $page = RetrieveAuthPage($p,"read",false);
  908. if ($page['text'])
  909. PrintText($pagename,ProcessIncludes($pagename,$page['text']));
  910. return;
  911. }
  912. }
  913. if ($PrintWikiPageNotFoundFmt>'')
  914. print FmtPageName(@$PrintWikiPageNotFoundFmt,array_pop($pagelist));
  915. }
  916. function ProcessIncludes($pagename,$text="") {
  917. global $MaxIncludes,$IncludeBadAnchorFmt,$GroupNamePattern,$PageTitlePattern;
  918. $inclcount=0;
  919. while ($inclcount<$MaxIncludes &&
  920. preg_match("/\\[\\[include:(($GroupNamePattern([\\/.]))?$PageTitlePattern)(#(\\w[-.:\\w]*)?(#(\\w[-.:\\w]*)?)?)?\\]\\]/",$text,$match)) {
  921. list($inclrepl,$inclname,$group,$dot,$a,$aa,$b,$bb) = $match;
  922. if (!$group) $inclname=FmtPageName('$Group.',$pagename).$inclname;
  923. $inclpage = RetrieveAuthPage($inclname,"read",false);
  924. $incltext = $inclpage['text'];
  925. $badanchor = '';
  926. if ($bb && !preg_match('/^\\d+$/',$bb) &&
  927. strpos($incltext,"[[#$bb]]")===false) $badanchor=$bb;
  928. if ($aa && !preg_match('/^\\d+$/',$aa) &&
  929. strpos($incltext,"[[#$aa]]")===false) $badanchor=$aa;
  930. if ($badanchor)
  931. $incltext=FmtPageName(str_replace('$BadAnchor',$badanchor,
  932. $IncludeBadAnchorFmt),$inclname);
  933. if (preg_match('/^\\d+$/',$bb))
  934. $incltext=preg_replace("/^(([^\\n]*\\n)\{0,$bb}).*$/s",'$1',$incltext,1);
  935. elseif ($bb)
  936. $incltext=preg_replace("/[^\\n]*\\[\\[#$bb\\]\\].*$/s",'',$incltext,1);
  937. if (preg_match('/^\\d+$/',$aa)) {
  938. $aa--; $incltext=preg_replace("/^([^\\n]*\\n)\{0,$aa}/s",'',$incltext,1);
  939. if (!$b) $incltext=preg_replace("/\\n.*$/s",'',$incltext);
  940. } elseif ($aa && $b)
  941. $incltext=preg_replace("/^.*?([^\\n]*\\[\\[#$aa\\]\\])/s",'$1',$incltext,1);
  942. elseif ($aa)
  943. $incltext=preg_replace("/^.*?([^\\n]*\\[\\[#$aa\\]\\]( *\\n)?[^\\n]*).*/s",'$1',$incltext,1);
  944. $text = str_replace($inclrepl,$incltext,$text);
  945. $inclcount++;
  946. }
  947. return $text;
  948. }
  949. function ProcessTextDirectives($pagename,$text="") {
  950. global $Text,$GroupHeaderFmt,$GroupFooterFmt,$BrowseDirectives;
  951. if (!$text) $text=$Text;
  952. $text = KeepWikiEscapes($text);
  953. $text = ProcessIncludes($pagename,$text);
  954. if (!strstr($text,"[[nogroupheader]]")) {
  955. $hdname = FmtPageName($GroupHeaderFmt,$pagename);
  956. if ($hdname != $pagename) {
  957. $hdpage=ReadPage($hdname,"");
  958. if ($hdpage['text'] && substr($hdpage['text'],-1,1)!="\n" &&
  959. substr($text,0,1)!="\n") $hdpage['text'] .= "\n";
  960. $text = $hdpage['text'].$text;
  961. }
  962. }
  963. if (!strstr($text,"[[nogroupfooter]]")) {
  964. $hdname = FmtPageName($GroupFooterFmt,$pagename);
  965. if ($hdname != $pagename) {
  966. $hdpage=ReadPage($hdname,"");
  967. if ($hdpage['text'] && substr($hdpage['text'],0,1)!="\n" &&
  968. substr($text,-1,1)!="\n") $text .= "\n";
  969. $text .= $hdpage['text'];
  970. }
  971. }
  972. Lock(0);
  973. foreach($BrowseDirectives as $p=>$s) {
  974. if ($p[0]=='/') $text=preg_replace($p,$s,$text);
  975. else if (strstr($text,$p)) $text = str_replace($p,eval($s),$text);
  976. }
  977. $Text = $text;
  978. }
  979. function HandleBrowse($pagename) {
  980. global $Text,$PageRedirectFmt,$RedirectPattern,
  981. $HandleBrowseFmt,$PageStartFmt,$PageEndFmt;
  982. $page = RetrieveAuthPage($pagename,"read");
  983. if (!$page) { Abort("Invalid page name"); }
  984. $Text = $page['text'];
  985. SetPageVars($pagename,$page,$pagename);
  986. if (@!$_GET['from']) {
  987. $PageRedirectFmt = '';
  988. if (preg_match("/$RedirectPattern/",$Text,$match)) {
  989. $rpage = FmtWikiLink('',$match[1],NULL,'PageName',$pagename);
  990. if (PageExists($rpage)) Redirect($rpage,"\$PageUrl?from=$pagename");
  991. }
  992. }
  993. else $PageRedirectFmt = FmtPageName($PageRedirectFmt,$_GET['from']);
  994. ProcessTextDirectives($pagename);
  995. SDV($HandleBrowseFmt,array(&$PageStartFmt,
  996. &$PageRedirectFmt,'function:PrintText',
  997. &$PageEndFmt));
  998. PrintFmt($pagename,$HandleBrowseFmt);
  999. }
  1000. function HandleEdit($pagename) {
  1001. global $restore,$preview,$HandleActions,$Text,
  1002. $HandleEditFmt,$PageStartFmt,$PageEditFmt,$PagePreviewFmt,$PageEndFmt,
  1003. $DiffClassMinor,$PatchFunction;
  1004. if (@$_POST['post'])
  1005. { $handle = $HandleActions['post']; return $handle($pagename); }
  1006. $page = RetrieveAuthPage($pagename,"edit");
  1007. if (!$page) { Abort("?cannot edit $pagename"); }
  1008. SetPageVars($pagename,$page,"Edit $pagename");
  1009. if ($restore && $PatchFunction) { $text = $PatchFunction($page,$restore); }
  1010. else if ($preview) { $text = stripmagic($_POST['text']); }
  1011. else { $text = $page['text']; }
  1012. $Text = $text;
  1013. $DiffClassMinor = '';
  1014. if (@$_POST['diffclass']=='minor') $DiffClassMinor="checked='checked'";
  1015. SDV($HandleEditFmt,array(&$PageStartFmt,
  1016. &$PageEditFmt,&$PagePreviewFmt,
  1017. &$PageEndFmt));
  1018. PrintFmt($pagename,$HandleEditFmt);
  1019. }
  1020. function HandlePost($pagename) {
  1021. global $WikiDir,$DeleteKeyWord,$RecentChanges,$RCDelimPattern,$Now,
  1022. $TimeFmt,$CurrentTime,$PageFileFmt,$DiffKeepDays,$Author,$PostFields,
  1023. $DiffFunction,$ChangeSummary;
  1024. $CurrentTime = strftime($TimeFmt,$Now);
  1025. foreach($PostFields as $k) {
  1026. if (isset($_POST[$k]))
  1027. $new[$k]=str_replace("\r","",stripmagic($_POST[$k]));
  1028. }
  1029. Lock(2);
  1030. $page = RetrieveAuthPage($pagename,"edit");
  1031. if (!$page) { Abort("?cannot post $pagename"); }
  1032. $pagename = FmtPageName('$PageName',$pagename);
  1033. if ($new['text']==$page['text'])
  1034. { Redirect($pagename); return; }
  1035. $diffclass=preg_replace('/\\W/','',@$_POST['diffclass']);
  1036. if ($page["time"]>0)
  1037. $new["diff:$Now:".$page['time'].":$diffclass"] =
  1038. $DiffFunction($new['text'],$page['text']);
  1039. $new['author'] = $Author;
  1040. $new["author:$Now"] = $Author;
  1041. $new["host:$Now"] = $_SERVER['REMOTE_ADDR'];
  1042. if ($ChangeSummary) $new["csum:$Now"] = $ChangeSummary;
  1043. foreach($new as $k=>$v) {
  1044. if ($k=='pagename' || $k=='action') continue;
  1045. $page[$k] = $v;
  1046. }
  1047. $keepgmt = $Now-$DiffKeepDays*86400;
  1048. $keys = array_keys($page);
  1049. foreach ($keys as $k)
  1050. if (preg_match("/^\\w+:(\\d+)/",$k,$match))
  1051. if ($match[1] < $keepgmt) unset($page[$k]);
  1052. $pagefile = FmtPageName($PageFileFmt,$pagename);
  1053. if ($page['text']==$DeleteKeyWord)
  1054. { @rename("$WikiDir/$pagefile","$WikiDir/$pagefile,$Now"); }
  1055. else WritePage($pagename,$page);
  1056. foreach($RecentChanges as $rcfmt => $pgfmt) {
  1057. $rcname=FmtPageName($rcfmt,$pagename); if (!$rcname) continue;
  1058. $pgtext=FmtPageName($pgfmt,$pagename); if (!$pgtext) continue;
  1059. if (@$seen[$rcname]++) continue;
  1060. $rcpage = ReadPage($rcname,"");
  1061. $rcelim = preg_quote(preg_replace("/$RCDelimPattern.*$/",' ',$pgtext),'/');
  1062. $rcpage['text'] = preg_replace("/[^\n]*$rcelim.*\n/","",$rcpage['text']);
  1063. if (!preg_match("/$RCDelimPattern/",$rcpage['text']))
  1064. $rcpage['text'] .= "$pgtext\n";
  1065. else
  1066. $rcpage['text'] = preg_replace("/([^\n]*$RCDelimPattern.*\n)/",
  1067. "$pgtext\n$1",$rcpage['text'],1);
  1068. WritePage($rcname,$rcpage);
  1069. }
  1070. Redirect($pagename);
  1071. }
  1072. function HandleSource($pagename) {
  1073. $page = RetrieveAuthPage($pagename,"read");
  1074. if (!$page) Abort("?cannot source $pagename");
  1075. Lock(0);
  1076. header("Content-Type: text/plain");
  1077. echo $page['text'];
  1078. }
  1079. function BasicAuth($pagename,$level,$authprompt=true) {
  1080. global $AuthRealmFmt,$AuthDeniedFmt,$DefaultPasswords,
  1081. $AllowPassword,$GroupAttributesFmt;
  1082. $page = ReadPage($pagename);
  1083. if (!$page) { return false; }
  1084. @$passwd = $page["passwd$level"];
  1085. if ($passwd=="") {
  1086. $grouppg = ReadPage(FmtPageName($GroupAttributesFmt,$pagename));
  1087. @$passwd = $grouppg["passwd$level"];
  1088. }
  1089. if (crypt($AllowPassword,$passwd)==$passwd) return $page;
  1090. if ($passwd=="") { $passwd=@$DefaultPasswords[$level]; }
  1091. if ($passwd=="") return $page;
  1092. foreach (array_merge((array)$DefaultPasswords['admin'],(array)$passwd) as $pw)
  1093. if (@crypt($_SERVER['PHP_AUTH_PW'],$pw)==$pw) return $page;
  1094. if (!$authprompt) return false;
  1095. $realm=FmtPageName($AuthRealmFmt,$pagename);
  1096. header("WWW-Authenticate: Basic realm=\"$realm\"");
  1097. header("Status: 401 Unauthorized");
  1098. header("HTTP-Status: 401 Unauthorized");
  1099. PrintFmt($pagename,$AuthDeniedFmt);
  1100. exit;
  1101. }
  1102. function RetrieveAuthPage($pagename,$level,$authprompt=true) {
  1103. global $AuthFunction;
  1104. if (!function_exists($AuthFunction))
  1105. Abort("?Invalid AuthFunction specified: $AuthFunction","AuthFunction");
  1106. return $AuthFunction($pagename,$level,$authprompt);
  1107. }
  1108. function PrintAttrForm($pagename) {
  1109. global $PageAttributes;
  1110. echo FmtPageName("<form action='\$PageUrl' method='post'>
  1111. <input type='hidden' name='action' value='postattr' />
  1112. <input type='hidden' name='pagename' value='$PageName' />
  1113. <table>",$pagename);
  1114. foreach($PageAttributes as $attr=>$p) {
  1115. $value = (substr($attr,0,6)=='passwd') ? '' : $page[$k];
  1116. $prompt = FmtPageName($p,$pagename);
  1117. echo "<tr><td>$prompt</td>
  1118. <td><input type='text' name='$attr' value='$value' /></td></tr>";
  1119. }
  1120. echo "</table><input type='submit' /></form>";
  1121. }
  1122. function HandleAttr($pagename) {
  1123. global $HandleAttrFmt,$PageStartFmt,$PageAttrFmt,$PageEndFmt;
  1124. $page = RetrieveAuthPage($pagename,"attr");
  1125. if (!$page) { Abort("?unable to read $pagename"); }
  1126. SetPageVars($pagename,$page,"Edit $pagename Attributes");
  1127. SDV($HandleAttrFmt,array(&$PageStartFmt,
  1128. &$PageAttrFmt,'function:PrintAttrForm',
  1129. &$PageEndFmt));
  1130. PrintFmt($pagename,$HandleAttrFmt);
  1131. }
  1132. function HandlePostAttr($pagename) {
  1133. global $PageAttributes;
  1134. $page = RetrieveAuthPage($pagename,"attr");
  1135. if (!$page) { Abort("?cannot get $pagename"); }
  1136. foreach($PageAttributes as $k=>$v) {
  1137. $newpw = $_POST[$k];
  1138. if ($newpw=="clear") unset($page[$k]);
  1139. else if ($newpw>"") $page[$k]=crypt($newpw);
  1140. }
  1141. WritePage($pagename,$page);
  1142. Redirect($pagename);
  1143. exit;
  1144. }
  1145. ?>