aboutsummaryrefslogtreecommitdiff
path: root/pmwiki.php
diff options
context:
space:
mode:
Diffstat (limited to 'pmwiki.php')
-rw-r--r--pmwiki.php114
1 files changed, 86 insertions, 28 deletions
diff --git a/pmwiki.php b/pmwiki.php
index 1bcba98b..c2557b5c 100644
--- a/pmwiki.php
+++ b/pmwiki.php
@@ -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;