diff options
Diffstat (limited to 'pmwiki.php')
-rw-r--r-- | pmwiki.php | 114 |
1 files changed, 86 insertions, 28 deletions
@@ -308,7 +308,7 @@ function CondExpr($pagename, $condname, $condparm) { $code = trim(preg_replace('/(^\\s*|(and|x?or|&&|\\|\\||!)\\s+)(?=and|x?or|&&|\\|\\|)/', '$1 0 ', trim(implode(' ', $terms)))); - if(!$code) return false; + if (!$code) return false; return @eval("return( $code );"); } $Conditions['expr'] = 'CondExpr($pagename, $condname, $condparm)'; @@ -404,7 +404,7 @@ function pm_servefile($basedir, $path, $cachecontrol='no-cache') { die('Forbidden'); } $filepath = "$basedir/$path"; - if(!file_exists($filepath)) { + if (!file_exists($filepath)) { http_response_code(404); die('File not found'); } @@ -562,7 +562,7 @@ function HandleDispatch($pagename, $action, $msg=NULL) { ## helper functions function stripmagic($x) { - if(is_null($x)) return ''; + if (is_null($x)) return ''; $fn = 'get_magic_quotes_gpc'; if (!function_exists($fn)) return $x; if (is_array($x)) { @@ -724,7 +724,7 @@ function PSFT($fmt, $stamp=null, $locale=null, $tz=null) { # strftime() replacem if (@$fmt == '') $fmt = $FTimeFmt; $stamp = is_numeric($stamp)? intval($stamp) : $Now; - if(preg_match('/(?<!%)(%L)/', $fmt)) { + if (preg_match('/(?<!%)(%L)/', $fmt)) { $gmt = PSFT('@%Y-%m-%dT%H:%M:%SZ', $stamp, null, 'GMT'); $fmt = preg_replace('/(?<!%)(%L)/', $gmt, $fmt); } @@ -846,6 +846,47 @@ function PRCB($pat, $repl, $subj, $vars=null, $limit=-1, &$count=null, $flags=0) return preg_replace_callback($pat, $repl, $subj, $limit, $count, $flags); return preg_replace_callback($pat, $repl, $subj, $limit, $count); } + +## This is a replacement for json_encode+PHSC, but only for arrays that +## are used by the PmWiki core. It may or may not work in other cases. +## This may fail with international characters if UTF-8 is not enabled. +function pm_json_encode($x, $encodespecial=false) { + if (!isset($x) || is_null($x)) return 'null'; + if (is_bool($x)) return $x? "true" : "false"; + if (is_int($x) || is_float($x)) return strval($x); + + if (function_exists('json_encode')) + $out = json_encode($x); + + elseif (is_string($x)) ## escape controls and specials per RFC:8259 + $out = '"'.preg_replace_callback("/[\x00-\x1f\\/\\\\\"]/",'cb_rfc8259',$x).'"'; + + elseif (is_array($x)) { + $a = array(); + if (array_values($x) === $x) { # numeric sequential array + foreach($x as $v) + $a[] = pm_json_encode($v); + + $out = "[".implode(',', $a)."]"; + } + else { # associative array -> json object + foreach($x as $k=>$v) { + $jk = is_int($k)? "\"$k\"" : pm_json_encode($k); + $jv = pm_json_encode($v); + $a[] = "$jk:$jv"; + } + $out = "{".implode(',', $a)."}"; + } + } + else return 'null'; # other types not yet supported + + return $encodespecial? PHSC($out, ENT_QUOTES) : $out; +} +function cb_rfc8259($m) { + return sprintf('\\u00%02x', ord($m[0])); +} + + ## callback functions class PPRC { # PmWiki preg replace callbacks + pass local vars var $vars; @@ -881,8 +922,8 @@ function pmcrypt($str, $salt=null) { SDV($PmCryptAlgo, PASSWORD_DEFAULT); if ($salt && preg_match('/^(-?@|\\*$)/', $salt)) return false; if (!is_null($salt)) { - if(function_exists('password_verify')) { - if(password_verify($str, $salt)) return $salt; + if (function_exists('password_verify')) { + if (password_verify($str, $salt)) return $salt; # else retry with crypt() } return crypt($str, $salt); @@ -1500,7 +1541,7 @@ function XLSDV($lang,$a) { function XLPage($lang,$p,$nohtml=false) { global $TimeFmt,$XLLangs,$FarmD, $EnableXLPageScriptLoad; $page = ReadPage($p, READPAGE_CURRENT); - if (!$page) return; + if (!$page || !@$page['text']) return; $text = preg_replace("/=>\\s*\n/",'=> ',@$page['text']); foreach(explode("\n",$text) as $l) if (preg_match('/^\\s*[\'"](.+?)[\'"]\\s*=>\\s*[\'"](.+)[\'"]/',$l,$m)) @@ -1673,6 +1714,7 @@ class PageStore { function delete($pagename) { global $Now, $PageExistsCache; $pagefile = $this->pagefile($pagename); + clearstatcache(); @rename($pagefile,"$pagefile,del-$Now"); unset($PageExistsCache[$pagename]); # PITS:01401 } @@ -1765,7 +1807,7 @@ function ListPages($pat=NULL) { return $out; } -function RAPC($pagename, $level, $authprompt=false, $since=READPAGE_CURRENT) { +function RAPC($pagename, $level='read', $authprompt=false, $since=READPAGE_CURRENT) { # helper function, widely used return RetrieveAuthPage($pagename, $level, $authprompt, $since); } @@ -1813,6 +1855,13 @@ function Redirect($pagename, $urlfmt='$PageUrl', $redirecturl=null) { exit; } +function PrintJSON($pagename, $out) { + $json = pm_json_encode($out); + header('Content-Type: application/json'); + print $json; + exit; +} + function PrintFmt($pagename,$fmt) { global $EnablePrePrintFmt; if (IsEnabled($EnablePrePrintFmt, 1)) PrePrintFmt($pagename,$fmt); @@ -2547,25 +2596,28 @@ function UpdatePage(&$pagename, &$page, &$new, $fnlist = NULL) { # EditTemplate allows a site administrator to pre-populate new pages # with the contents of another page. function EditTemplate($pagename, &$page, &$new) { - global $EditTemplatesFmt; + global $EditTemplatesFmt, $ROEPatterns, $TROEPatterns; if (@$new['text'] > '') return; - if (@$_REQUEST['template'] && PageExists($_REQUEST['template'])) { - $p = RetrieveAuthPage($_REQUEST['template'], 'read', false, - READPAGE_CURRENT); - if ($p['text'] > '') $new['text'] = $p['text']; - return; + $rqt = @$_REQUEST['template']; + if ($rqt && PageExists($rqt)) { + $p = RAPC($rqt); + if (@$p['text'] > '') $new['text'] = $p['text']; } - foreach((array)$EditTemplatesFmt as $t) { - if (strpos($t, ' ')!==false) { - $args = ParseArgs($t); - if (@$args['name']) { - if (! MatchPageNames($pagename, FixGlob($args['name']))) continue; + else { + foreach((array)$EditTemplatesFmt as $t) { + if (strpos($t, ' ')!==false) { + $args = ParseArgs($t); + if (@$args['name']) { + if (! MatchPageNames($pagename, FixGlob($args['name']))) continue; + } + $t = $args[''][0]; } - $t = $args[''][0]; + $p = RAPC(FmtPageName($t,$pagename)); + if (@$p['text'] > '') { $new['text'] = $p['text']; break; } } - $p = RetrieveAuthPage(FmtPageName($t,$pagename), 'read', false, - READPAGE_CURRENT); - if (@$p['text'] > '') { $new['text'] = $p['text']; return; } + } + if (@$new['text']>'' && is_array($TROEPatterns)) { + $new['text'] = ProcessROESPatterns(@$new['text'], $TROEPatterns); } } @@ -2710,11 +2762,13 @@ function PostPage($pagename, &$page, &$new) { if (!$EnablePost) return; if (preg_match("/$DeleteKeyPattern/",$new['text'])) { if (@$new['passwdattr']>'' && !CondAuth($pagename, 'attr')) - Abort('$[The page has an "attr" attribute and cannot be deleted.]'); - else $WikiDir->delete($pagename); - $IsPagePosted = true; - return; + return Abort('$[The page has an "attr" attribute and cannot be deleted.]'); + $csum = @$new['csum']; + $new = array_merge($new, $page); + $new['csum'] = $csum; + $deleted = 1; } + else $deleted = 0; $new['charset'] = $Charset; # kept for now, may be needed if custom PageStore $new['author'] = @$Author; $new["author:$Now"] = @$Author; @@ -2733,6 +2787,10 @@ function PostPage($pagename, &$page, &$new) { unset($new[$k]); } WritePage($pagename,$new); + + if ($deleted) { + $WikiDir->delete($pagename); + } $IsPagePosted = true; } @@ -2951,7 +3009,7 @@ function PmWikiAuth($pagename, $level, $authprompt=true, $since=0) { ## Split from PmWikiAuth to allow for recipes to call it function PrintAuthForm($pagename) { global $FmtV, $AuthPromptFmt, $PageStartFmt, $PageEndFmt, $AuthFormRespCode; - if(IsEnabled($AuthFormRespCode, 0)) http_response_code($AuthFormRespCode); + if (IsEnabled($AuthFormRespCode, 0)) http_response_code($AuthFormRespCode); $postvars = ''; foreach($_POST as $k=>$v) { if ($k == 'authpw' || $k == 'authid') continue; |