Blame


1 5127fd58 2021-12-17 jrmu <?php
2 5127fd58 2021-12-17 jrmu /*
3 5127fd58 2021-12-17 jrmu PmWiki
4 fc91d0f1 2023-03-07 jrmu Copyright 2001-2023 Patrick R. Michaud
5 5127fd58 2021-12-17 jrmu pmichaud@pobox.com
6 5127fd58 2021-12-17 jrmu http://www.pmichaud.com/
7 5127fd58 2021-12-17 jrmu
8 5127fd58 2021-12-17 jrmu This program is free software; you can redistribute it and/or modify
9 5127fd58 2021-12-17 jrmu it under the terms of the GNU General Public License as published by
10 5127fd58 2021-12-17 jrmu the Free Software Foundation; either version 2 of the License, or
11 5127fd58 2021-12-17 jrmu (at your option) any later version.
12 5127fd58 2021-12-17 jrmu
13 5127fd58 2021-12-17 jrmu This program is distributed in the hope that it will be useful,
14 5127fd58 2021-12-17 jrmu but WITHOUT ANY WARRANTY; without even the implied warranty of
15 5127fd58 2021-12-17 jrmu MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 5127fd58 2021-12-17 jrmu GNU General Public License for more details.
17 5127fd58 2021-12-17 jrmu
18 5127fd58 2021-12-17 jrmu You should have received a copy of the GNU General Public License
19 5127fd58 2021-12-17 jrmu along with this program; if not, write to the Free Software
20 5127fd58 2021-12-17 jrmu Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 5127fd58 2021-12-17 jrmu
22 5127fd58 2021-12-17 jrmu ----
23 5127fd58 2021-12-17 jrmu Note from Pm: Trying to understand the PmWiki code? Wish it had
24 5127fd58 2021-12-17 jrmu more comments? If you want help with any of the code here,
25 5127fd58 2021-12-17 jrmu write me at <pmichaud@pobox.com> with your question(s) and I'll
26 5127fd58 2021-12-17 jrmu provide explanations (and add comments) that answer them.
27 5127fd58 2021-12-17 jrmu
28 5127fd58 2021-12-17 jrmu Script maintained by Petko YOTOV www.pmwiki.org/petko
29 fc91d0f1 2023-03-07 jrmu $Id: pmwiki.php 4370 2023-02-12 08:26:08Z petko $
30 5127fd58 2021-12-17 jrmu */
31 5127fd58 2021-12-17 jrmu error_reporting(E_ALL ^ E_NOTICE);
32 5127fd58 2021-12-17 jrmu StopWatch('PmWiki');
33 5127fd58 2021-12-17 jrmu @ini_set('magic_quotes_runtime', 0);
34 5127fd58 2021-12-17 jrmu @ini_set('magic_quotes_sybase', 0);
35 5127fd58 2021-12-17 jrmu if (@ini_get('pcre.backtrack_limit') < 1000000)
36 5127fd58 2021-12-17 jrmu @ini_set('pcre.backtrack_limit', 1000000);
37 5127fd58 2021-12-17 jrmu if (ini_get('register_globals'))
38 5127fd58 2021-12-17 jrmu foreach($_REQUEST as $k=>$v) {
39 5127fd58 2021-12-17 jrmu if (preg_match('/^(GLOBALS|_SERVER|_GET|_POST|_COOKIE|_FILES|_ENV|_REQUEST|_SESSION|FarmD|WikiDir)$/i', $k)) exit();
40 5127fd58 2021-12-17 jrmu ${$k}=''; unset(${$k});
41 5127fd58 2021-12-17 jrmu }
42 5127fd58 2021-12-17 jrmu $UnsafeGlobals = array_keys($GLOBALS); $GCount=0; $FmtV=array();
43 fc91d0f1 2023-03-07 jrmu $FmtV['$TokenName'] = 'pmtoken';
44 5127fd58 2021-12-17 jrmu define('PmWiki',1);
45 fc91d0f1 2023-03-07 jrmu SDV($WorkDir,'wiki.d');
46 fc91d0f1 2023-03-07 jrmu SDV($FarmD,dirname(__FILE__));
47 fc91d0f1 2023-03-07 jrmu if (strpos($FarmD, 'phar://')===0) $IsFarmArchive = 1;
48 fc91d0f1 2023-03-07 jrmu elseif (preg_match('/\\w\\w:/', $FarmD)) exit();
49 5127fd58 2021-12-17 jrmu @include_once("$FarmD/scripts/version.php");
50 5127fd58 2021-12-17 jrmu $GroupPattern = '[[:upper:]][\\w]*(?:-\\w+)*';
51 5127fd58 2021-12-17 jrmu $NamePattern = '[[:upper:]\\d][\\w]*(?:-\\w+)*';
52 5127fd58 2021-12-17 jrmu $BlockPattern = 'form|div|table|t[rdh]|p|[uo]l|d[ltd]|h[1-6r]|pre|blockquote';
53 5127fd58 2021-12-17 jrmu $WikiWordPattern = '[[:upper:]][[:alnum:]]*(?:[[:upper:]][[:lower:]0-9]|[[:lower:]0-9][[:upper:]])[[:alnum:]]*';
54 5127fd58 2021-12-17 jrmu $WikiDir = new PageStore('wiki.d/{$FullName}');
55 5127fd58 2021-12-17 jrmu $WikiLibDirs = array(&$WikiDir,new PageStore('$FarmD/wikilib.d/{$FullName}'));
56 5127fd58 2021-12-17 jrmu $PageFileEncodeFunction = 'PUE'; # only used if $WikiDir->encodefilenames is set
57 5127fd58 2021-12-17 jrmu $PageFileDecodeFunction = 'urldecode';
58 5127fd58 2021-12-17 jrmu $LocalDir = 'local';
59 5127fd58 2021-12-17 jrmu $InterMapFiles = array("$FarmD/scripts/intermap.txt",
60 5127fd58 2021-12-17 jrmu "$FarmD/local/farmmap.txt", '$SiteGroup.InterMap', 'local/localmap.txt');
61 5127fd58 2021-12-17 jrmu $Newline = "\263"; # deprecated, 2.0.0
62 5127fd58 2021-12-17 jrmu $KeepToken = "\034\034";
63 5127fd58 2021-12-17 jrmu $Now=time();
64 5127fd58 2021-12-17 jrmu define('READPAGE_CURRENT', $Now+604800);
65 5127fd58 2021-12-17 jrmu $TimeFmt = '%B %d, %Y, at %I:%M %p';
66 5127fd58 2021-12-17 jrmu $TimeISOFmt = '%Y-%m-%dT%H:%M:%S';
67 5127fd58 2021-12-17 jrmu $TimeISOZFmt = '%Y-%m-%dT%H:%M:%SZ';
68 5127fd58 2021-12-17 jrmu $MessagesFmt = array();
69 5127fd58 2021-12-17 jrmu $BlockMessageFmt = "<h3 class='wikimessage'>$[This post has been blocked by the administrator]</h3>";
70 5127fd58 2021-12-17 jrmu $EditFields = array('text');
71 fc91d0f1 2023-03-07 jrmu $EditFunctions = array('AutoCheckToken', 'EditTemplate', 'RestorePage', 'ReplaceOnSave',
72 5127fd58 2021-12-17 jrmu 'SaveAttributes', 'PostPage', 'PostRecentChanges', 'AutoCreateTargets',
73 5127fd58 2021-12-17 jrmu 'PreviewPage');
74 5127fd58 2021-12-17 jrmu $EnablePost = 1;
75 5127fd58 2021-12-17 jrmu $ChangeSummary = substr(preg_replace('/[\\x00-\\x1f]|=\\]/', '',
76 5127fd58 2021-12-17 jrmu stripmagic(@$_REQUEST['csum'])), 0, 100);
77 5127fd58 2021-12-17 jrmu $AsSpacedFunction = 'AsSpaced';
78 5127fd58 2021-12-17 jrmu $SpaceWikiWords = 0;
79 5127fd58 2021-12-17 jrmu $RCDelimPattern = ' ';
80 5127fd58 2021-12-17 jrmu $RecentChangesFmt = array(
81 5127fd58 2021-12-17 jrmu '$SiteGroup.AllRecentChanges' =>
82 fc91d0f1 2023-03-07 jrmu '* [[{$Group}.{$Name}]] . . . $CurrentLocalTime $[by] $AuthorLink: [=$ChangeSummary=]',
83 5127fd58 2021-12-17 jrmu '$Group.RecentChanges' =>
84 fc91d0f1 2023-03-07 jrmu '* [[{$Group}/{$Name}]] . . . $CurrentLocalTime $[by] $AuthorLink: [=$ChangeSummary=]');
85 5127fd58 2021-12-17 jrmu $UrlScheme = (@$_SERVER['HTTPS']=='on' || @$_SERVER['SERVER_PORT']==443)
86 5127fd58 2021-12-17 jrmu ? 'https' : 'http';
87 fc91d0f1 2023-03-07 jrmu $ScriptUrl = $UrlScheme.'://'.strval(@$_SERVER['HTTP_HOST']).strval(@$_SERVER['SCRIPT_NAME']);
88 5127fd58 2021-12-17 jrmu $PubDirUrl = preg_replace('#/[^/]*$#', '/pub', $ScriptUrl, 1);
89 fc91d0f1 2023-03-07 jrmu SDV($FarmPubDirPrefix, 'PmFarmPubDirUrl');
90 fc91d0f1 2023-03-07 jrmu if (@$IsFarmArchive) SDV($FarmPubDirUrl, "$ScriptUrl/$FarmPubDirPrefix");
91 5127fd58 2021-12-17 jrmu $HTMLVSpace = "<vspace>";
92 5127fd58 2021-12-17 jrmu $HTMLPNewline = '';
93 5127fd58 2021-12-17 jrmu $MarkupFrame = array();
94 5127fd58 2021-12-17 jrmu $MarkupFrameBase = array('cs' => array(), 'vs' => '', 'ref' => 0,
95 5127fd58 2021-12-17 jrmu 'closeall' => array(), 'is' => array(),
96 5127fd58 2021-12-17 jrmu 'escape' => 1);
97 5127fd58 2021-12-17 jrmu $WikiWordCountMax = 1000000;
98 5127fd58 2021-12-17 jrmu $WikiWordCount['PmWiki'] = 1;
99 5127fd58 2021-12-17 jrmu $TableRowIndexMax = 1;
100 5127fd58 2021-12-17 jrmu $UrlExcludeChars = '<>"{}|\\\\^`()[\\]\'';
101 5127fd58 2021-12-17 jrmu $QueryFragPattern = "[?#][^\\s$UrlExcludeChars]*";
102 5127fd58 2021-12-17 jrmu $SuffixPattern = '(?:-?[[:alnum:]]+)*';
103 5127fd58 2021-12-17 jrmu $LinkPageSelfFmt = "<a class='selflink' href='\$LinkUrl' title='\$LinkAlt'>\$LinkText</a>";
104 5127fd58 2021-12-17 jrmu $LinkPageExistsFmt = "<a class='wikilink' href='\$LinkUrl' title='\$LinkAlt'>\$LinkText</a>";
105 5127fd58 2021-12-17 jrmu $LinkPageCreateFmt =
106 5127fd58 2021-12-17 jrmu "<a class='createlinktext' rel='nofollow' title='\$LinkAlt'
107 5127fd58 2021-12-17 jrmu href='{\$PageUrl}?action=edit'>\$LinkText</a><a rel='nofollow'
108 5127fd58 2021-12-17 jrmu class='createlink' href='{\$PageUrl}?action=edit'>?</a>";
109 5127fd58 2021-12-17 jrmu $UrlLinkFmt =
110 5127fd58 2021-12-17 jrmu "<a class='urllink' href='\$LinkUrl' title='\$LinkAlt' rel='nofollow'>\$LinkText</a>";
111 5127fd58 2021-12-17 jrmu umask(002);
112 5127fd58 2021-12-17 jrmu $CookiePrefix = '';
113 5127fd58 2021-12-17 jrmu $SiteGroup = 'Site';
114 5127fd58 2021-12-17 jrmu $SiteAdminGroup = 'SiteAdmin';
115 5127fd58 2021-12-17 jrmu $DefaultGroup = 'Main';
116 5127fd58 2021-12-17 jrmu $DefaultName = 'HomePage';
117 5127fd58 2021-12-17 jrmu $GroupHeaderFmt = '(:include {$Group}.GroupHeader self=0 basepage={*$FullName}:)(:nl:)';
118 5127fd58 2021-12-17 jrmu $GroupFooterFmt = '(:nl:)(:include {$Group}.GroupFooter self=0 basepage={*$FullName}:)';
119 5127fd58 2021-12-17 jrmu $PagePathFmt = array('{$Group}.$1','$1.$1','$1.{$DefaultName}');
120 5127fd58 2021-12-17 jrmu $PageAttributes = array(
121 5127fd58 2021-12-17 jrmu 'passwdread' => '$[Set new read password:]',
122 5127fd58 2021-12-17 jrmu 'passwdedit' => '$[Set new edit password:]',
123 5127fd58 2021-12-17 jrmu 'passwdattr' => '$[Set new attribute password:]');
124 5127fd58 2021-12-17 jrmu $XLLangs = array('en');
125 5127fd58 2021-12-17 jrmu if (preg_match('/^C$|\.UTF-?8/i',setlocale(LC_ALL,0)))
126 5127fd58 2021-12-17 jrmu setlocale(LC_ALL,'en_US');
127 5127fd58 2021-12-17 jrmu $FmtP = array();
128 5127fd58 2021-12-17 jrmu $FmtPV = array(
129 5127fd58 2021-12-17 jrmu # '$ScriptUrl' => 'PUE($ScriptUrl)', ## $ScriptUrl is special
130 5127fd58 2021-12-17 jrmu '$PageUrl' =>
131 5127fd58 2021-12-17 jrmu 'PUE(($EnablePathInfo)
132 5127fd58 2021-12-17 jrmu ? "$ScriptUrl/$group/$name"
133 5127fd58 2021-12-17 jrmu : "$ScriptUrl?n=$group.$name")',
134 5127fd58 2021-12-17 jrmu '$FullName' => '"$group.$name"',
135 5127fd58 2021-12-17 jrmu '$Groupspaced' => '$AsSpacedFunction($group)',
136 5127fd58 2021-12-17 jrmu '$Namespaced' => '$AsSpacedFunction($name)',
137 5127fd58 2021-12-17 jrmu '$Group' => '$group',
138 5127fd58 2021-12-17 jrmu '$Name' => '$name',
139 5127fd58 2021-12-17 jrmu '$Titlespaced' => 'FmtPageTitle(@$page["title"], $name, 1)',
140 5127fd58 2021-12-17 jrmu '$Title' => 'FmtPageTitle(@$page["title"], $name, 0)',
141 5127fd58 2021-12-17 jrmu '$LastModifiedBy' => '@$page["author"]',
142 5127fd58 2021-12-17 jrmu '$LastModifiedHost' => '@$page["host"]',
143 fc91d0f1 2023-03-07 jrmu '$LastModified' => 'PSFT($GLOBALS["TimeFmt"], $page["time"])',
144 5127fd58 2021-12-17 jrmu '$LastModifiedSummary' => '@$page["csum"]',
145 5127fd58 2021-12-17 jrmu '$LastModifiedTime' => '$page["time"]',
146 5127fd58 2021-12-17 jrmu '$Description' => '@$page["description"]',
147 5127fd58 2021-12-17 jrmu '$SiteGroup' => '$GLOBALS["SiteGroup"]',
148 5127fd58 2021-12-17 jrmu '$SiteAdminGroup' => '$GLOBALS["SiteAdminGroup"]',
149 5127fd58 2021-12-17 jrmu '$VersionNum' => '$GLOBALS["VersionNum"]',
150 5127fd58 2021-12-17 jrmu '$Version' => '$GLOBALS["Version"]',
151 5127fd58 2021-12-17 jrmu '$WikiTitle' => '$GLOBALS["WikiTitle"]',
152 fc91d0f1 2023-03-07 jrmu '$PageLogoUrl' => 'strval(@$GLOBALS["PageLogoUrl"])',
153 5127fd58 2021-12-17 jrmu '$Author' => 'NoCache($GLOBALS["Author"])',
154 5127fd58 2021-12-17 jrmu '$AuthId' => 'NoCache($GLOBALS["AuthId"])',
155 5127fd58 2021-12-17 jrmu '$DefaultGroup' => '$GLOBALS["DefaultGroup"]',
156 5127fd58 2021-12-17 jrmu '$DefaultName' => '$GLOBALS["DefaultName"]',
157 5127fd58 2021-12-17 jrmu '$BaseName' => 'MakeBaseName($pn)',
158 5127fd58 2021-12-17 jrmu '$Action' => '$GLOBALS["action"]',
159 5127fd58 2021-12-17 jrmu '$PasswdRead' => 'PasswdVar($pn, "read")',
160 5127fd58 2021-12-17 jrmu '$PasswdEdit' => 'PasswdVar($pn, "edit")',
161 5127fd58 2021-12-17 jrmu '$PasswdAttr' => 'PasswdVar($pn, "attr")',
162 fc91d0f1 2023-03-07 jrmu '$EnabledIMap' => 'implode("|", array_keys($GLOBALS["IMap"]))', # PmSyntax
163 fc91d0f1 2023-03-07 jrmu '$GroupHomePage' => 'FmtGroupHome($pn,$group,$var)',
164 fc91d0f1 2023-03-07 jrmu '$GroupHomePageName' => 'FmtGroupHome($pn,$group,$var)',
165 fc91d0f1 2023-03-07 jrmu '$GroupHomePageTitle' => 'FmtGroupHome($pn,$group,$var)',
166 fc91d0f1 2023-03-07 jrmu '$GroupHomePageTitlespaced' => 'FmtGroupHome($pn,$group,$var)',
167 5127fd58 2021-12-17 jrmu );
168 5127fd58 2021-12-17 jrmu $SaveProperties = array('title', 'description', 'keywords');
169 5127fd58 2021-12-17 jrmu $PageTextVarPatterns = array(
170 5127fd58 2021-12-17 jrmu 'var:' => '/^(:*[ \\t]*(\\w[-\\w]*)[ \\t]*:[ \\t]?)(.*)($)/m',
171 5127fd58 2021-12-17 jrmu '(:var:...:)' => '/(\\(: *(\\w[-\\w]*) *:(?!\\))\\s?)(.*?)(:\\))/s'
172 5127fd58 2021-12-17 jrmu );
173 5127fd58 2021-12-17 jrmu
174 5127fd58 2021-12-17 jrmu $WikiTitle = 'PmWiki';
175 5127fd58 2021-12-17 jrmu $Charset = 'ISO-8859-1';
176 5127fd58 2021-12-17 jrmu $HTTPHeaders = array(
177 5127fd58 2021-12-17 jrmu "Expires: Tue, 01 Jan 2002 00:00:00 GMT",
178 5127fd58 2021-12-17 jrmu "Cache-Control: no-store, no-cache, must-revalidate",
179 5127fd58 2021-12-17 jrmu "Content-type: text/html; charset=ISO-8859-1;");
180 fc91d0f1 2023-03-07 jrmu $HTTPHeaders['XFO'] = 'X-Frame-Options: SAMEORIGIN';
181 fc91d0f1 2023-03-07 jrmu $HTTPHeaders['CSP'] = "Content-Security-Policy: frame-ancestors 'self'; base-uri 'self'; object-src 'none';";
182 fc91d0f1 2023-03-07 jrmu $HTTPHeaders['XSSP'] = 'X-XSS-Protection: 1; mode=block';
183 fc91d0f1 2023-03-07 jrmu
184 5127fd58 2021-12-17 jrmu $CacheActions = array('browse','diff','print');
185 5127fd58 2021-12-17 jrmu $EnableHTMLCache = 0;
186 5127fd58 2021-12-17 jrmu $NoHTMLCache = 0;
187 5127fd58 2021-12-17 jrmu $HTMLTagAttr = '';
188 5127fd58 2021-12-17 jrmu $HTMLDoctypeFmt =
189 5127fd58 2021-12-17 jrmu "<!DOCTYPE html
190 5127fd58 2021-12-17 jrmu PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"
191 5127fd58 2021-12-17 jrmu \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
192 5127fd58 2021-12-17 jrmu <html xmlns='http://www.w3.org/1999/xhtml' \$HTMLTagAttr><head>\n";
193 5127fd58 2021-12-17 jrmu $HTMLStylesFmt['pmwiki'] = "
194 5127fd58 2021-12-17 jrmu ul, ol, pre, dl, p { margin-top:0px; margin-bottom:0px; }
195 5127fd58 2021-12-17 jrmu code.escaped { white-space: pre; }
196 5127fd58 2021-12-17 jrmu .vspace { margin-top:1.33em; }
197 5127fd58 2021-12-17 jrmu .indent { margin-left:40px; }
198 5127fd58 2021-12-17 jrmu .outdent { margin-left:40px; text-indent:-40px; }
199 5127fd58 2021-12-17 jrmu a.createlinktext { text-decoration:none; border-bottom:1px dotted gray; }
200 5127fd58 2021-12-17 jrmu a.createlink { text-decoration:none; position:relative; top:-0.5em;
201 5127fd58 2021-12-17 jrmu font-weight:bold; font-size:smaller; border-bottom:none; }
202 5127fd58 2021-12-17 jrmu img { border:0px; }
203 5127fd58 2021-12-17 jrmu ";
204 5127fd58 2021-12-17 jrmu $HTMLHeaderFmt['styles'] = array(
205 5127fd58 2021-12-17 jrmu "<style type='text/css'><!--",&$HTMLStylesFmt,"\n--></style>");
206 5127fd58 2021-12-17 jrmu $HTMLBodyFmt = "</head>\n<body>";
207 5127fd58 2021-12-17 jrmu $HTMLStartFmt = array('headers:',&$HTMLDoctypeFmt,&$HTMLHeaderFmt,
208 5127fd58 2021-12-17 jrmu &$HTMLBodyFmt);
209 5127fd58 2021-12-17 jrmu $HTMLEndFmt = "\n</body>\n</html>";
210 5127fd58 2021-12-17 jrmu $PageStartFmt = array(&$HTMLStartFmt,"\n<div id='contents'>\n");
211 5127fd58 2021-12-17 jrmu $PageEndFmt = array('</div>',&$HTMLEndFmt);
212 5127fd58 2021-12-17 jrmu
213 5127fd58 2021-12-17 jrmu $HandleActions = array(
214 5127fd58 2021-12-17 jrmu 'browse' => 'HandleBrowse', 'print' => 'HandleBrowse',
215 5127fd58 2021-12-17 jrmu 'edit' => 'HandleEdit', 'source' => 'HandleSource',
216 5127fd58 2021-12-17 jrmu 'attr' => 'HandleAttr', 'postattr' => 'HandlePostAttr',
217 5127fd58 2021-12-17 jrmu 'logout' => 'HandleLogoutA', 'login' => 'HandleLoginA');
218 5127fd58 2021-12-17 jrmu $HandleAuth = array(
219 5127fd58 2021-12-17 jrmu 'browse' => 'read', 'source' => 'read', 'print' => 'read',
220 5127fd58 2021-12-17 jrmu 'edit' => 'edit', 'attr' => 'attr', 'postattr' => 'attr',
221 5127fd58 2021-12-17 jrmu 'logout' => 'read', 'login' => 'login');
222 5127fd58 2021-12-17 jrmu $ActionTitleFmt = array(
223 5127fd58 2021-12-17 jrmu 'edit' => '| $[Edit]',
224 5127fd58 2021-12-17 jrmu 'attr' => '| $[Attributes]',
225 5127fd58 2021-12-17 jrmu 'login' => '| $[Login]');
226 5127fd58 2021-12-17 jrmu $DefaultPasswords = array('admin'=>'@lock','read'=>'','edit'=>'','attr'=>'');
227 5127fd58 2021-12-17 jrmu $AuthCascade = array('edit'=>'read', 'attr'=>'edit');
228 5127fd58 2021-12-17 jrmu $AuthList = array('' => 1, 'nopass:' => 1, '@nopass' => 1);
229 5127fd58 2021-12-17 jrmu $SessionEncode = 'base64_encode';
230 5127fd58 2021-12-17 jrmu $SessionDecode = 'base64_decode';
231 5127fd58 2021-12-17 jrmu
232 5127fd58 2021-12-17 jrmu $CallbackFnTemplates = array(
233 5127fd58 2021-12-17 jrmu 'default' => '%s',
234 5127fd58 2021-12-17 jrmu 'return' => 'return %s;',
235 5127fd58 2021-12-17 jrmu 'markup_e' => 'extract($GLOBALS["MarkupToHTML"]); return %s;',
236 5127fd58 2021-12-17 jrmu 'qualify' => 'extract($GLOBALS["tmp_qualify"]); return %s;',
237 5127fd58 2021-12-17 jrmu );
238 5127fd58 2021-12-17 jrmu
239 5127fd58 2021-12-17 jrmu $Conditions['enabled'] = '(boolean)@$GLOBALS[$condparm]';
240 5127fd58 2021-12-17 jrmu $Conditions['false'] = 'false';
241 5127fd58 2021-12-17 jrmu $Conditions['true'] = 'true';
242 5127fd58 2021-12-17 jrmu $Conditions['group'] =
243 5127fd58 2021-12-17 jrmu "(boolean)MatchPageNames(\$pagename, FixGlob(\$condparm, '$1$2.*'))";
244 5127fd58 2021-12-17 jrmu $Conditions['name'] =
245 5127fd58 2021-12-17 jrmu "(boolean)MatchPageNames(\$pagename, FixGlob(\$condparm, '$1*.$2'))";
246 5127fd58 2021-12-17 jrmu $Conditions['match'] = 'preg_match("!$condparm!",$pagename)';
247 5127fd58 2021-12-17 jrmu $Conditions['authid'] = 'NoCache(@$GLOBALS["AuthId"] > "")';
248 5127fd58 2021-12-17 jrmu $Conditions['equal'] = 'CompareArgs($condparm) == 0';
249 5127fd58 2021-12-17 jrmu function CompareArgs($arg)
250 5127fd58 2021-12-17 jrmu { $arg = ParseArgs($arg); return strcmp(@$arg[''][0], @$arg[''][1]); }
251 5127fd58 2021-12-17 jrmu
252 5127fd58 2021-12-17 jrmu $Conditions['auth'] = 'NoCache(CondAuth($pagename, $condparm))';
253 5127fd58 2021-12-17 jrmu function CondAuth($pagename, $condparm) {
254 fc91d0f1 2023-03-07 jrmu global $AuthList, $HandleAuth;
255 5127fd58 2021-12-17 jrmu @list($level, $pn) = explode(' ', $condparm, 2);
256 fc91d0f1 2023-03-07 jrmu if (@$level && $level[0] == '@') { # user belongs to @group1,@group2
257 fc91d0f1 2023-03-07 jrmu $keys = MatchNames(array_keys((array)@$AuthList), $level, true);
258 fc91d0f1 2023-03-07 jrmu foreach($keys as $k) {
259 fc91d0f1 2023-03-07 jrmu if (@$AuthList[$k] == 1 && $AuthList["-$k"] != 1) return true;
260 fc91d0f1 2023-03-07 jrmu }
261 fc91d0f1 2023-03-07 jrmu return false;
262 fc91d0f1 2023-03-07 jrmu }
263 5127fd58 2021-12-17 jrmu $pn = ($pn > '') ? MakePageName($pagename, $pn) : $pagename;
264 5127fd58 2021-12-17 jrmu if (@$HandleAuth[$level]>'') $level = $HandleAuth[$level];
265 5127fd58 2021-12-17 jrmu return (boolean)RetrieveAuthPage($pn, $level, false, READPAGE_CURRENT);
266 5127fd58 2021-12-17 jrmu }
267 fc91d0f1 2023-03-07 jrmu $Conditions['exists'] = 'CondExists($condparm)';
268 fc91d0f1 2023-03-07 jrmu ## This is an optimized version of the earlier conditional
269 fc91d0f1 2023-03-07 jrmu ## especially for pagelists
270 fc91d0f1 2023-03-07 jrmu function CondExists($condparm, $caseinsensitive = true) {
271 fc91d0f1 2023-03-07 jrmu static $ls = false;
272 fc91d0f1 2023-03-07 jrmu if (!$ls) $ls = ListPages();
273 fc91d0f1 2023-03-07 jrmu $condparm = str_replace(array('[[',']]'), array('', ''), $condparm);
274 fc91d0f1 2023-03-07 jrmu $glob = FixGlob($condparm, '$1*.$2');
275 fc91d0f1 2023-03-07 jrmu return (boolean)MatchPageNames($ls, $glob, $caseinsensitive);
276 fc91d0f1 2023-03-07 jrmu }
277 5127fd58 2021-12-17 jrmu
278 5127fd58 2021-12-17 jrmu ## CondExpr handles complex conditions (expressions)
279 5127fd58 2021-12-17 jrmu ## Portions Copyright 2005 by D. Faure (dfaure@cpan.org)
280 5127fd58 2021-12-17 jrmu function CondExpr($pagename, $condname, $condparm) {
281 5127fd58 2021-12-17 jrmu global $CondExprOps;
282 5127fd58 2021-12-17 jrmu SDV($CondExprOps, 'and|x?or|&&|\\|\\||[!()]');
283 5127fd58 2021-12-17 jrmu if ($condname == '(' || $condname == '[')
284 5127fd58 2021-12-17 jrmu $condparm = preg_replace('/[\\]\\)]\\s*$/', '', $condparm);
285 5127fd58 2021-12-17 jrmu $condparm = str_replace('&amp;&amp;', '&&', $condparm);
286 5127fd58 2021-12-17 jrmu $terms = preg_split("/(?<!\\S)($CondExprOps)(?!\\S)/i", $condparm, -1,
287 5127fd58 2021-12-17 jrmu PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
288 5127fd58 2021-12-17 jrmu foreach($terms as $i => $t) {
289 5127fd58 2021-12-17 jrmu $t = trim($t);
290 5127fd58 2021-12-17 jrmu if (preg_match("/^($CondExprOps)$/i", $t)) continue;
291 5127fd58 2021-12-17 jrmu if ($t) $terms[$i] = CondText($pagename, "if $t", 'TRUE') ? '1' : '0';
292 5127fd58 2021-12-17 jrmu }
293 fc91d0f1 2023-03-07 jrmu
294 fc91d0f1 2023-03-07 jrmu ## PITS:01480, (:if [ {$EmptyPV} and ... ]:)
295 fc91d0f1 2023-03-07 jrmu $code = preg_replace('/(^\\s*|(and|x?or|&&|\\|\\||!)\\s+)(?=and|x?or|&&|\\|\\|)/',
296 fc91d0f1 2023-03-07 jrmu '$1 0 ', trim(implode(' ', $terms)));
297 fc91d0f1 2023-03-07 jrmu
298 fc91d0f1 2023-03-07 jrmu return @eval("return( $code );");
299 5127fd58 2021-12-17 jrmu }
300 5127fd58 2021-12-17 jrmu $Conditions['expr'] = 'CondExpr($pagename, $condname, $condparm)';
301 5127fd58 2021-12-17 jrmu $Conditions['('] = 'CondExpr($pagename, $condname, $condparm)';
302 5127fd58 2021-12-17 jrmu $Conditions['['] = 'CondExpr($pagename, $condname, $condparm)';
303 5127fd58 2021-12-17 jrmu
304 5127fd58 2021-12-17 jrmu $MarkupTable['_begin']['seq'] = 'B';
305 5127fd58 2021-12-17 jrmu $MarkupTable['_end']['seq'] = 'E';
306 5127fd58 2021-12-17 jrmu Markup('fulltext','>_begin');
307 5127fd58 2021-12-17 jrmu Markup('split','>fulltext',"\n",
308 5127fd58 2021-12-17 jrmu '$RedoMarkupLine=1; return explode("\n",$x);');
309 5127fd58 2021-12-17 jrmu Markup('directives','>split');
310 5127fd58 2021-12-17 jrmu Markup('inline','>directives');
311 5127fd58 2021-12-17 jrmu Markup('links','>inline');
312 5127fd58 2021-12-17 jrmu Markup('block','>links');
313 5127fd58 2021-12-17 jrmu Markup('style','>block');
314 5127fd58 2021-12-17 jrmu Markup('closeall', '_begin',
315 5127fd58 2021-12-17 jrmu '/^\\(:closeall:\\)$/', "MarkupMarkupClose");
316 5127fd58 2021-12-17 jrmu function MarkupMarkupClose() { return '<:block>' . MarkupClose(); }
317 5127fd58 2021-12-17 jrmu
318 fc91d0f1 2023-03-07 jrmu $ImgExtPattern="\\.(?:gif|jpg|jpeg|a?png|svgz?|GIF|JPG|JPEG|A?PNG|SVGZ?|webp|WEBP)";
319 5127fd58 2021-12-17 jrmu $ImgTagFmt="<img src='\$LinkUrl' alt='\$LinkAlt' title='\$LinkAlt' />";
320 5127fd58 2021-12-17 jrmu
321 5127fd58 2021-12-17 jrmu $BlockMarkups = array(
322 5127fd58 2021-12-17 jrmu 'block' => array('','','',0),
323 5127fd58 2021-12-17 jrmu 'ul' => array('<ul><li>','</li><li>','</li></ul>',1),
324 5127fd58 2021-12-17 jrmu 'dl' => array('<dl>','</dd>','</dd></dl>',1),
325 5127fd58 2021-12-17 jrmu 'ol' => array('<ol><li>','</li><li>','</li></ol>',1),
326 5127fd58 2021-12-17 jrmu 'p' => array('<p>','','</p>',0),
327 5127fd58 2021-12-17 jrmu 'indent' =>
328 5127fd58 2021-12-17 jrmu array("<div class='indent'>","</div><div class='indent'>",'</div>',1),
329 5127fd58 2021-12-17 jrmu 'outdent' =>
330 5127fd58 2021-12-17 jrmu array("<div class='outdent'>","</div><div class='outdent'>",'</div>',1),
331 5127fd58 2021-12-17 jrmu 'pre' => array('<pre>','','</pre>',0),
332 5127fd58 2021-12-17 jrmu 'table' => array("<table width='100%'>",'','</table>',0));
333 5127fd58 2021-12-17 jrmu
334 5127fd58 2021-12-17 jrmu foreach(array('http:','https:','mailto:','ftp:','news:','gopher:','nap:',
335 5127fd58 2021-12-17 jrmu 'file:', 'tel:', 'geo:') as $m)
336 5127fd58 2021-12-17 jrmu { $LinkFunctions[$m] = 'LinkIMap'; $IMap[$m]="$m$1"; }
337 5127fd58 2021-12-17 jrmu $LinkFunctions['<:page>'] = 'LinkPage';
338 5127fd58 2021-12-17 jrmu
339 fc91d0f1 2023-03-07 jrmu $q = preg_replace('/(\\?|%3f)([-\\w]+=)/i', '&$2', strval(@$_SERVER['QUERY_STRING']));
340 5127fd58 2021-12-17 jrmu if ($q != @$_SERVER['QUERY_STRING']) {
341 5127fd58 2021-12-17 jrmu unset($_GET);
342 5127fd58 2021-12-17 jrmu parse_str($q, $_GET);
343 5127fd58 2021-12-17 jrmu $_REQUEST = array_merge($_REQUEST, $_GET, $_POST);
344 5127fd58 2021-12-17 jrmu }
345 5127fd58 2021-12-17 jrmu
346 5127fd58 2021-12-17 jrmu if (isset($_GET['action'])) $action = $_GET['action'];
347 5127fd58 2021-12-17 jrmu elseif (isset($_POST['action'])) $action = $_POST['action'];
348 5127fd58 2021-12-17 jrmu else $action = 'browse';
349 5127fd58 2021-12-17 jrmu
350 fc91d0f1 2023-03-07 jrmu $pagename = strval(@$_REQUEST['n']);
351 fc91d0f1 2023-03-07 jrmu if (!$pagename) $pagename = strval(@$_REQUEST['pagename']);
352 5127fd58 2021-12-17 jrmu if (!$pagename &&
353 fc91d0f1 2023-03-07 jrmu preg_match('!^'.preg_quote(strval(@$_SERVER['SCRIPT_NAME']),'!').'/?([^?]*)!',
354 fc91d0f1 2023-03-07 jrmu strval(@$_SERVER['REQUEST_URI']),$match))
355 5127fd58 2021-12-17 jrmu $pagename = urldecode($match[1]);
356 5127fd58 2021-12-17 jrmu if (preg_match('/[\\x80-\\xbf]/',$pagename))
357 fc91d0f1 2023-03-07 jrmu $pagename=pm_recode($pagename, 'UTF-8', 'WINDOWS-1252');
358 5127fd58 2021-12-17 jrmu $pagename = preg_replace('![^[:alnum:]\\x80-\\xff]+$!','',$pagename);
359 5127fd58 2021-12-17 jrmu $pagename_unfiltered = $pagename;
360 5127fd58 2021-12-17 jrmu $pagename = preg_replace('![${}\'"\\\\]+!', '', $pagename);
361 5127fd58 2021-12-17 jrmu $FmtPV['$RequestedPage'] = 'PHSC($GLOBALS["pagename_unfiltered"], ENT_QUOTES)';
362 5127fd58 2021-12-17 jrmu $Cursor['*'] = &$pagename;
363 5127fd58 2021-12-17 jrmu if (function_exists("date_default_timezone_get") ) { # fix PHP5.3 warnings
364 5127fd58 2021-12-17 jrmu @date_default_timezone_set(@date_default_timezone_get());
365 5127fd58 2021-12-17 jrmu }
366 5127fd58 2021-12-17 jrmu
367 5127fd58 2021-12-17 jrmu $DenyHtaccessContent = <<<EOF
368 5127fd58 2021-12-17 jrmu <IfModule !mod_authz_host.c>
369 5127fd58 2021-12-17 jrmu Order Deny,Allow
370 5127fd58 2021-12-17 jrmu Deny from all
371 5127fd58 2021-12-17 jrmu </IfModule>
372 5127fd58 2021-12-17 jrmu
373 5127fd58 2021-12-17 jrmu <IfModule mod_authz_host.c>
374 5127fd58 2021-12-17 jrmu Require all denied
375 5127fd58 2021-12-17 jrmu </IfModule>
376 5127fd58 2021-12-17 jrmu
377 5127fd58 2021-12-17 jrmu EOF;
378 5127fd58 2021-12-17 jrmu
379 fc91d0f1 2023-03-07 jrmu SDVA($ServeFileExts, array(
380 fc91d0f1 2023-03-07 jrmu 'gif' => 'image/gif', 'png' => 'image/png', 'svg' => 'image/svg+xml',
381 fc91d0f1 2023-03-07 jrmu 'README' => 'text/plain', 'txt' => 'text/plain',
382 fc91d0f1 2023-03-07 jrmu 'css' => 'text/css', 'js' => 'application/javascript',
383 fc91d0f1 2023-03-07 jrmu ));
384 fc91d0f1 2023-03-07 jrmu function pm_servefile($basedir, $path, $cachecontrol='no-cache') {
385 fc91d0f1 2023-03-07 jrmu global $ServeFileExts;
386 fc91d0f1 2023-03-07 jrmu header("X-Sent-Via: pm_servefile");
387 fc91d0f1 2023-03-07 jrmu $ext = preg_replace('!^.*[./]!', '', $path);
388 fc91d0f1 2023-03-07 jrmu if (!isset($ServeFileExts[$ext]) || preg_match('/[?#${}]|\\.\\./', $path)) {
389 fc91d0f1 2023-03-07 jrmu http_response_code(403);
390 fc91d0f1 2023-03-07 jrmu die('Forbidden');
391 fc91d0f1 2023-03-07 jrmu }
392 fc91d0f1 2023-03-07 jrmu $filepath = "$basedir/$path";
393 fc91d0f1 2023-03-07 jrmu if(!file_exists($filepath)) {
394 fc91d0f1 2023-03-07 jrmu http_response_code(404);
395 fc91d0f1 2023-03-07 jrmu die('File not found');
396 fc91d0f1 2023-03-07 jrmu }
397 fc91d0f1 2023-03-07 jrmu
398 fc91d0f1 2023-03-07 jrmu header("Cache-Control: $cachecontrol");
399 fc91d0f1 2023-03-07 jrmu header('Expires: ');
400 fc91d0f1 2023-03-07 jrmu $filelastmod = gmdate('D, d M Y H:i:s \G\M\T', filemtime($filepath));
401 fc91d0f1 2023-03-07 jrmu if (@$_SERVER['HTTP_IF_MODIFIED_SINCE'] == $filelastmod)
402 fc91d0f1 2023-03-07 jrmu { http_response_code(304); exit(); }
403 fc91d0f1 2023-03-07 jrmu header("Last-Modified: $filelastmod");
404 fc91d0f1 2023-03-07 jrmu header("Content-Type: {$ServeFileExts[$ext]}");
405 fc91d0f1 2023-03-07 jrmu $length = filesize($filepath);
406 fc91d0f1 2023-03-07 jrmu header("Content-Length: $length");
407 fc91d0f1 2023-03-07 jrmu readfile($filepath);
408 fc91d0f1 2023-03-07 jrmu exit;
409 fc91d0f1 2023-03-07 jrmu }
410 fc91d0f1 2023-03-07 jrmu
411 fc91d0f1 2023-03-07 jrmu if (strpos($pagename, "$FarmPubDirPrefix/")===0) {
412 fc91d0f1 2023-03-07 jrmu $path = substr($pagename, strlen("$FarmPubDirPrefix/"));
413 fc91d0f1 2023-03-07 jrmu pm_servefile("$FarmD/pub", $path);
414 fc91d0f1 2023-03-07 jrmu exit;
415 fc91d0f1 2023-03-07 jrmu }
416 fc91d0f1 2023-03-07 jrmu
417 5127fd58 2021-12-17 jrmu if (file_exists("$FarmD/local/farmconfig.php"))
418 5127fd58 2021-12-17 jrmu include_once("$FarmD/local/farmconfig.php");
419 5127fd58 2021-12-17 jrmu if (IsEnabled($EnableLocalConfig,1)) {
420 5127fd58 2021-12-17 jrmu if (file_exists("$LocalDir/config.php"))
421 5127fd58 2021-12-17 jrmu include_once("$LocalDir/config.php");
422 5127fd58 2021-12-17 jrmu elseif (file_exists('config.php'))
423 5127fd58 2021-12-17 jrmu include_once('config.php');
424 5127fd58 2021-12-17 jrmu }
425 5127fd58 2021-12-17 jrmu
426 fc91d0f1 2023-03-07 jrmu SDV($CurrentTime, PSFT($TimeFmt, $Now));
427 fc91d0f1 2023-03-07 jrmu SDV($CurrentLocalTime, PSFT("@$TimeISOZFmt", $Now, null, 'GMT'));
428 fc91d0f1 2023-03-07 jrmu SDV($CurrentTimeISO, PSFT($TimeISOFmt, $Now));
429 5127fd58 2021-12-17 jrmu
430 5127fd58 2021-12-17 jrmu if (IsEnabled($EnableStdConfig,1))
431 5127fd58 2021-12-17 jrmu include_once("$FarmD/scripts/stdconfig.php");
432 5127fd58 2021-12-17 jrmu
433 5127fd58 2021-12-17 jrmu if (isset($PostConfig) && is_array($PostConfig)) {
434 5127fd58 2021-12-17 jrmu asort($PostConfig, SORT_NUMERIC);
435 5127fd58 2021-12-17 jrmu foreach ($PostConfig as $k=>$v) {
436 5127fd58 2021-12-17 jrmu if (!$k || !$v || $v<50) continue;
437 5127fd58 2021-12-17 jrmu if (function_exists($k)) $k($pagename);
438 5127fd58 2021-12-17 jrmu elseif (file_exists($k)) include_once($k);
439 5127fd58 2021-12-17 jrmu }
440 5127fd58 2021-12-17 jrmu }
441 5127fd58 2021-12-17 jrmu
442 fc91d0f1 2023-03-07 jrmu function pmsetcookie($name, $val="", $exp=0, $path="", $dom="", $secure=null, $httponly=null, $samesite=null) {
443 fc91d0f1 2023-03-07 jrmu global $EnableCookieSecure, $EnableCookieHTTPOnly, $SetCookieFunction, $CookieSameSite;
444 fc91d0f1 2023-03-07 jrmu if (IsEnabled($SetCookieFunction))
445 fc91d0f1 2023-03-07 jrmu return $SetCookieFunction($name, $val, $exp, $path, $dom, $secure, $httponly, $samesite);
446 5127fd58 2021-12-17 jrmu if (is_null($secure)) $secure = IsEnabled($EnableCookieSecure, false);
447 5127fd58 2021-12-17 jrmu if (is_null($httponly)) $httponly = IsEnabled($EnableCookieHTTPOnly, false);
448 fc91d0f1 2023-03-07 jrmu if (is_null($samesite)) $samesite = IsEnabled($CookieSameSite, 'Lax');
449 fc91d0f1 2023-03-07 jrmu
450 fc91d0f1 2023-03-07 jrmu if (PHP_VERSION_ID>=70300) {
451 fc91d0f1 2023-03-07 jrmu return setcookie($name, $val, array(
452 fc91d0f1 2023-03-07 jrmu 'expires' => $exp,
453 fc91d0f1 2023-03-07 jrmu 'path' => $path,
454 fc91d0f1 2023-03-07 jrmu 'domain' => $dom,
455 fc91d0f1 2023-03-07 jrmu 'secure' => $secure,
456 fc91d0f1 2023-03-07 jrmu 'httponly' => $httponly,
457 fc91d0f1 2023-03-07 jrmu 'samesite' => $samesite
458 fc91d0f1 2023-03-07 jrmu ));
459 fc91d0f1 2023-03-07 jrmu }
460 fc91d0f1 2023-03-07 jrmu if (!$path) $path = '/';
461 fc91d0f1 2023-03-07 jrmu setcookie($name, $val, $exp, "$path; SameSite=$samesite", $dom, $secure, $httponly);
462 5127fd58 2021-12-17 jrmu }
463 fc91d0f1 2023-03-07 jrmu function pm_session_start($a = array()) {
464 fc91d0f1 2023-03-07 jrmu global $EnableCookieSecure, $EnableCookieHTTPOnly, $CookieSameSite;
465 fc91d0f1 2023-03-07 jrmu if (function_exists('session_status')) {
466 fc91d0f1 2023-03-07 jrmu if (session_status() === PHP_SESSION_ACTIVE) return true;
467 fc91d0f1 2023-03-07 jrmu }
468 fc91d0f1 2023-03-07 jrmu
469 fc91d0f1 2023-03-07 jrmu if (!headers_sent()){
470 fc91d0f1 2023-03-07 jrmu $params = session_get_cookie_params();
471 fc91d0f1 2023-03-07 jrmu if (isset($EnableCookieSecure) && !isset($a['secure']))
472 fc91d0f1 2023-03-07 jrmu $a['secure'] = $EnableCookieSecure;
473 fc91d0f1 2023-03-07 jrmu if (isset($EnableCookieHTTPOnly) && !isset($a['httponly']))
474 fc91d0f1 2023-03-07 jrmu $a['httponly'] = $EnableCookieHTTPOnly;
475 fc91d0f1 2023-03-07 jrmu if (!isset($a['samesite'])) $a['samesite'] = IsEnabled($CookieSameSite, 'Lax');
476 fc91d0f1 2023-03-07 jrmu SDVA($a, $params);
477 fc91d0f1 2023-03-07 jrmu
478 fc91d0f1 2023-03-07 jrmu if (PHP_VERSION_ID < 70300) {
479 fc91d0f1 2023-03-07 jrmu if (!$a['path']) $a['path'] = '/';
480 fc91d0f1 2023-03-07 jrmu $a['path'] .= "; SameSite={$a['samesite']}";
481 fc91d0f1 2023-03-07 jrmu session_set_cookie_params(
482 fc91d0f1 2023-03-07 jrmu $a['lifetime'],
483 fc91d0f1 2023-03-07 jrmu $a['path'],
484 fc91d0f1 2023-03-07 jrmu $a['domain'],
485 fc91d0f1 2023-03-07 jrmu $a['secure'],
486 fc91d0f1 2023-03-07 jrmu $a['httponly']
487 fc91d0f1 2023-03-07 jrmu );
488 fc91d0f1 2023-03-07 jrmu }
489 fc91d0f1 2023-03-07 jrmu else {
490 fc91d0f1 2023-03-07 jrmu session_set_cookie_params($a);
491 fc91d0f1 2023-03-07 jrmu }
492 fc91d0f1 2023-03-07 jrmu }
493 fc91d0f1 2023-03-07 jrmu return @session_start();
494 fc91d0f1 2023-03-07 jrmu }
495 5127fd58 2021-12-17 jrmu
496 fc91d0f1 2023-03-07 jrmu
497 5127fd58 2021-12-17 jrmu foreach((array)$InterMapFiles as $f) {
498 5127fd58 2021-12-17 jrmu $f = FmtPageName($f, $pagename);
499 5127fd58 2021-12-17 jrmu if (($v = @file($f)))
500 5127fd58 2021-12-17 jrmu $v = preg_replace('/^\\s*(?>\\w[-\\w]*)(?!:)/m', '$0:', implode('', $v));
501 5127fd58 2021-12-17 jrmu else if (@PageExists($f)) {
502 5127fd58 2021-12-17 jrmu $p = ReadPage($f, READPAGE_CURRENT);
503 5127fd58 2021-12-17 jrmu $v = @$p['text'];
504 5127fd58 2021-12-17 jrmu } else continue;
505 5127fd58 2021-12-17 jrmu if (!preg_match_all("/^\\s*(\\w[-\\w]*:)[^\\S\n]+(\\S*)/m", $v,
506 5127fd58 2021-12-17 jrmu $match, PREG_SET_ORDER)) continue;
507 5127fd58 2021-12-17 jrmu foreach($match as $m) {
508 5127fd58 2021-12-17 jrmu if (strpos($m[2], '$1') === false) $m[2] .= '$1';
509 5127fd58 2021-12-17 jrmu $LinkFunctions[$m[1]] = 'LinkIMap';
510 5127fd58 2021-12-17 jrmu $IMap[$m[1]] = FmtPageName($m[2], $pagename);
511 5127fd58 2021-12-17 jrmu }
512 5127fd58 2021-12-17 jrmu }
513 5127fd58 2021-12-17 jrmu
514 5127fd58 2021-12-17 jrmu $keys = array_keys($AuthCascade);
515 5127fd58 2021-12-17 jrmu while ($keys) {
516 5127fd58 2021-12-17 jrmu $k = array_shift($keys); $t = $AuthCascade[$k];
517 5127fd58 2021-12-17 jrmu if (in_array($t, $keys))
518 5127fd58 2021-12-17 jrmu { unset($AuthCascade[$k]); $AuthCascade[$k] = $t; array_push($keys, $k); }
519 5127fd58 2021-12-17 jrmu }
520 5127fd58 2021-12-17 jrmu
521 5127fd58 2021-12-17 jrmu $LinkPattern = implode('|',array_keys($LinkFunctions)); # after InterMaps
522 5127fd58 2021-12-17 jrmu SDV($LinkPageCreateSpaceFmt,$LinkPageCreateFmt);
523 5127fd58 2021-12-17 jrmu $ActionTitle = FmtPageName(@$ActionTitleFmt[$action], $pagename);
524 5127fd58 2021-12-17 jrmu
525 5127fd58 2021-12-17 jrmu
526 5127fd58 2021-12-17 jrmu if (!@$HandleActions[$action] || !function_exists($HandleActions[$action]))
527 5127fd58 2021-12-17 jrmu $action='browse';
528 5127fd58 2021-12-17 jrmu if (IsEnabled($EnableActions, 1)) HandleDispatch($pagename, $action);
529 5127fd58 2021-12-17 jrmu Lock(0);
530 5127fd58 2021-12-17 jrmu return;
531 5127fd58 2021-12-17 jrmu
532 5127fd58 2021-12-17 jrmu ## HandleDispatch() is used to dispatch control to the appropriate
533 5127fd58 2021-12-17 jrmu ## action handler with the appropriate permissions.
534 5127fd58 2021-12-17 jrmu ## If a message is supplied, it is added to $MessagesFmt.
535 5127fd58 2021-12-17 jrmu function HandleDispatch($pagename, $action, $msg=NULL) {
536 5127fd58 2021-12-17 jrmu global $MessagesFmt, $HandleActions, $HandleAuth;
537 5127fd58 2021-12-17 jrmu if ($msg) $MessagesFmt[] = "<div class='wikimessage'>$msg</div>";
538 5127fd58 2021-12-17 jrmu $fn = $HandleActions[$action];
539 5127fd58 2021-12-17 jrmu $auth = @$HandleAuth[$action];
540 5127fd58 2021-12-17 jrmu if (!$auth) $auth = 'read';
541 5127fd58 2021-12-17 jrmu return $fn($pagename, $auth);
542 5127fd58 2021-12-17 jrmu }
543 5127fd58 2021-12-17 jrmu
544 5127fd58 2021-12-17 jrmu ## helper functions
545 5127fd58 2021-12-17 jrmu function stripmagic($x) {
546 fc91d0f1 2023-03-07 jrmu if(is_null($x)) return '';
547 5127fd58 2021-12-17 jrmu $fn = 'get_magic_quotes_gpc';
548 5127fd58 2021-12-17 jrmu if (!function_exists($fn)) return $x;
549 5127fd58 2021-12-17 jrmu if (is_array($x)) {
550 5127fd58 2021-12-17 jrmu foreach($x as $k=>$v) $x[$k] = stripmagic($v);
551 5127fd58 2021-12-17 jrmu return $x;
552 5127fd58 2021-12-17 jrmu }
553 fc91d0f1 2023-03-07 jrmu $x = strval($x);
554 5127fd58 2021-12-17 jrmu return @$fn() ? stripslashes($x) : $x;
555 5127fd58 2021-12-17 jrmu }
556 5127fd58 2021-12-17 jrmu function pre_r(&$x)
557 5127fd58 2021-12-17 jrmu { return '<pre>'.PHSC(print_r($x, true)).'</pre>'; }
558 5127fd58 2021-12-17 jrmu function PSS($x)
559 5127fd58 2021-12-17 jrmu { return str_replace('\\"','"',$x); }
560 5127fd58 2021-12-17 jrmu function PVS($x)
561 5127fd58 2021-12-17 jrmu { return preg_replace("/\n[^\\S\n]*(?=\n)/", "\n<:vspace>", $x); }
562 5127fd58 2021-12-17 jrmu function PVSE($x) { return PVS(PHSC($x, ENT_NOQUOTES)); }
563 5127fd58 2021-12-17 jrmu function PZZ($x,$y='') { return ''; }
564 5127fd58 2021-12-17 jrmu function PRR($x=NULL)
565 5127fd58 2021-12-17 jrmu { if ($x || is_null($x)) $GLOBALS['RedoMarkupLine']++; return $x; }
566 5127fd58 2021-12-17 jrmu function PUE($x)
567 fc91d0f1 2023-03-07 jrmu { return $x? preg_replace_callback('/[\\x80-\\xff \'"<>]/', "cb_pue", $x) : ''; }
568 5127fd58 2021-12-17 jrmu function cb_pue($m) { return '%'.dechex(ord($m[0])); }
569 fc91d0f1 2023-03-07 jrmu function PQA($x, $keep=true, $styletoclass=false) {
570 fc91d0f1 2023-03-07 jrmu global $EnableUnsafeInlineStyle;
571 fc91d0f1 2023-03-07 jrmu if (!@$x) return ''; # PHP 8.1
572 5127fd58 2021-12-17 jrmu $out = '';
573 fc91d0f1 2023-03-07 jrmu $s = array();
574 fc91d0f1 2023-03-07 jrmu $x = MarkupRestore($x);
575 5127fd58 2021-12-17 jrmu if (preg_match_all('/([a-zA-Z][-\\w]*)\\s*=\\s*("[^"]*"|\'[^\']*\'|\\S*)/',
576 5127fd58 2021-12-17 jrmu $x, $attr, PREG_SET_ORDER)) {
577 5127fd58 2021-12-17 jrmu foreach($attr as $a) {
578 5127fd58 2021-12-17 jrmu if (preg_match('/^on/i', $a[1])) continue;
579 5127fd58 2021-12-17 jrmu $val = preg_replace('/^([\'"]?)(.*)\\1$/', '$2', $a[2]);
580 fc91d0f1 2023-03-07 jrmu $s[$a[1]] = $val;
581 5127fd58 2021-12-17 jrmu }
582 fc91d0f1 2023-03-07 jrmu foreach($s as $key=>$val) {
583 fc91d0f1 2023-03-07 jrmu $val = PHSC($val, ENT_QUOTES, null, false);
584 fc91d0f1 2023-03-07 jrmu if ($keep) $val = Keep($val);
585 fc91d0f1 2023-03-07 jrmu $out .= "$key='$val' ";
586 fc91d0f1 2023-03-07 jrmu }
587 5127fd58 2021-12-17 jrmu }
588 5127fd58 2021-12-17 jrmu return $out;
589 5127fd58 2021-12-17 jrmu }
590 5127fd58 2021-12-17 jrmu function SDV(&$v,$x) { if (!isset($v)) $v=$x; }
591 5127fd58 2021-12-17 jrmu function SDVA(&$var,$val)
592 5127fd58 2021-12-17 jrmu { foreach($val as $k=>$v) if (!isset($var[$k])) $var[$k]=$v; }
593 5127fd58 2021-12-17 jrmu function IsEnabled(&$var,$f=0)
594 5127fd58 2021-12-17 jrmu { return (isset($var)) ? $var : $f; }
595 5127fd58 2021-12-17 jrmu function SetTmplDisplay($var, $val)
596 5127fd58 2021-12-17 jrmu { NoCache(); $GLOBALS['TmplDisplay'][$var] = $val; }
597 5127fd58 2021-12-17 jrmu function NoCache($x = '') { $GLOBALS['NoHTMLCache'] |= 1; return $x; }
598 5127fd58 2021-12-17 jrmu function ParseArgs($x, $optpat = '(?>(\\w+)[:=])') {
599 5127fd58 2021-12-17 jrmu $z = array();
600 5127fd58 2021-12-17 jrmu preg_match_all("/($optpat|[-+])?(\"[^\"]*\"|'[^']*'|\\S+)/",
601 fc91d0f1 2023-03-07 jrmu strval($x), $terms, PREG_SET_ORDER);
602 5127fd58 2021-12-17 jrmu foreach($terms as $t) {
603 5127fd58 2021-12-17 jrmu $v = preg_replace('/^([\'"])?(.*)\\1$/', '$2', $t[3]);
604 5127fd58 2021-12-17 jrmu if ($t[2]) { $z['#'][] = $t[2]; $z[$t[2]] = $v; }
605 5127fd58 2021-12-17 jrmu else { $z['#'][] = $t[1]; $z[$t[1]][] = $v; }
606 5127fd58 2021-12-17 jrmu $z['#'][] = $v;
607 5127fd58 2021-12-17 jrmu }
608 5127fd58 2021-12-17 jrmu return $z;
609 5127fd58 2021-12-17 jrmu }
610 5127fd58 2021-12-17 jrmu function PHSC($x, $flags=ENT_COMPAT, $enc=null, $dbl_enc=true) { # for PHP 5.4
611 5127fd58 2021-12-17 jrmu if (is_null($enc)) $enc = "ISO-8859-1"; # single-byte charset
612 5127fd58 2021-12-17 jrmu if (! is_array($x)) return @htmlspecialchars($x, $flags, $enc, $dbl_enc);
613 5127fd58 2021-12-17 jrmu foreach($x as $k=>$v) $x[$k] = PHSC($v, $flags, $enc, $dbl_enc);
614 5127fd58 2021-12-17 jrmu return $x;
615 fc91d0f1 2023-03-07 jrmu }
616 fc91d0f1 2023-03-07 jrmu function PSFT($fmt, $stamp=null, $locale=null, $tz=null) { # strftime() replacement
617 fc91d0f1 2023-03-07 jrmu global $Now, $FTimeFmt, $TimeFmt, $EnableFTimeNew;
618 fc91d0f1 2023-03-07 jrmu static $cached;
619 fc91d0f1 2023-03-07 jrmu if (!@$cached) {
620 fc91d0f1 2023-03-07 jrmu SDV($FTimeFmt, $TimeFmt);
621 fc91d0f1 2023-03-07 jrmu $cached['dloc'] = setlocale(LC_TIME, 0);
622 fc91d0f1 2023-03-07 jrmu $cached['dtz'] = date_default_timezone_get();
623 fc91d0f1 2023-03-07 jrmu $cached['dtzo'] = timezone_open($cached['dtz']);
624 fc91d0f1 2023-03-07 jrmu $cached['formats'] = array(
625 fc91d0f1 2023-03-07 jrmu '%d' => 'd',
626 fc91d0f1 2023-03-07 jrmu '%e' => ' j', # day " 1"-"31"
627 fc91d0f1 2023-03-07 jrmu '%u' => 'N',
628 fc91d0f1 2023-03-07 jrmu '%w' => 'w',
629 fc91d0f1 2023-03-07 jrmu '%m' => 'm',
630 fc91d0f1 2023-03-07 jrmu '%s' => 'U',
631 fc91d0f1 2023-03-07 jrmu '%n' => "\n",
632 fc91d0f1 2023-03-07 jrmu '%t' => "\t",
633 fc91d0f1 2023-03-07 jrmu '%V' => 'W', # ISO-8601 week number, starts Monday, first week with 4+ weekdays
634 fc91d0f1 2023-03-07 jrmu
635 fc91d0f1 2023-03-07 jrmu '%H' => 'H',
636 fc91d0f1 2023-03-07 jrmu '%I' => 'h', # hour 01-12
637 fc91d0f1 2023-03-07 jrmu '%k' => ' G', # hour " 1"-"23"
638 fc91d0f1 2023-03-07 jrmu '%l' => ' g', # hour " 1"-"12"
639 fc91d0f1 2023-03-07 jrmu '%M' => 'i',
640 fc91d0f1 2023-03-07 jrmu '%S' => 's',
641 fc91d0f1 2023-03-07 jrmu '%R' => 'H:i',
642 fc91d0f1 2023-03-07 jrmu '%T' => 'H:i:s',
643 fc91d0f1 2023-03-07 jrmu '%r' => 'h:i:s A',
644 fc91d0f1 2023-03-07 jrmu '%D' => 'm/d/y',
645 fc91d0f1 2023-03-07 jrmu '%F' => 'Y-m-d',
646 fc91d0f1 2023-03-07 jrmu
647 fc91d0f1 2023-03-07 jrmu '%G' => 'o', # ISO-8601 year (like %V)
648 fc91d0f1 2023-03-07 jrmu '%y' => 'y', # 21
649 fc91d0f1 2023-03-07 jrmu '%Y' => 'Y', # 2021
650 fc91d0f1 2023-03-07 jrmu
651 fc91d0f1 2023-03-07 jrmu '%Z' => 'T', # tz: EST
652 fc91d0f1 2023-03-07 jrmu '%z' => 'O', # tz offset: -0500
653 fc91d0f1 2023-03-07 jrmu );
654 fc91d0f1 2023-03-07 jrmu if (extension_loaded('intl')) {
655 fc91d0f1 2023-03-07 jrmu $full = IntlDateFormatter::FULL;
656 fc91d0f1 2023-03-07 jrmu $long = IntlDateFormatter::LONG;
657 fc91d0f1 2023-03-07 jrmu $short = IntlDateFormatter::SHORT;
658 fc91d0f1 2023-03-07 jrmu $none = IntlDateFormatter::NONE;
659 fc91d0f1 2023-03-07 jrmu $medium = IntlDateFormatter::MEDIUM;
660 fc91d0f1 2023-03-07 jrmu
661 fc91d0f1 2023-03-07 jrmu $cached['iformats'] = array(
662 fc91d0f1 2023-03-07 jrmu '%a' => array($full, $full, 'EEE'), # Mon
663 fc91d0f1 2023-03-07 jrmu '%A' => array($full, $full, 'EEEE'), # Monday
664 fc91d0f1 2023-03-07 jrmu '%h' => array($full, $full, 'MMM'), # Jan
665 fc91d0f1 2023-03-07 jrmu '%b' => array($full, $full, 'MMM'), # Jan
666 fc91d0f1 2023-03-07 jrmu '%B' => array($full, $full, 'MMMM'), # January
667 fc91d0f1 2023-03-07 jrmu '%p' => array($full, $full, 'aa'), # AM/PM
668 fc91d0f1 2023-03-07 jrmu '%P' => array($full, $full, 'aa'), # am/pm (no lowercase for intl am/pm)
669 fc91d0f1 2023-03-07 jrmu '%c' => array($long, $short), # date time
670 fc91d0f1 2023-03-07 jrmu '%x' => array($short, $none), # date
671 fc91d0f1 2023-03-07 jrmu '%X' => array($none, $medium),# time
672 fc91d0f1 2023-03-07 jrmu );
673 fc91d0f1 2023-03-07 jrmu }
674 fc91d0f1 2023-03-07 jrmu else {
675 fc91d0f1 2023-03-07 jrmu $cached['iformats'] = array();
676 fc91d0f1 2023-03-07 jrmu $cached['formats'] += array(
677 fc91d0f1 2023-03-07 jrmu '%a' => 'D', # Mon
678 fc91d0f1 2023-03-07 jrmu '%A' => 'l', # Monday
679 fc91d0f1 2023-03-07 jrmu '%h' => 'M', # Jan
680 fc91d0f1 2023-03-07 jrmu '%b' => 'M', # Jan
681 fc91d0f1 2023-03-07 jrmu '%B' => 'F', # January
682 fc91d0f1 2023-03-07 jrmu '%p' => 'a', # AM/PM
683 fc91d0f1 2023-03-07 jrmu '%P' => 'A', # am/pm
684 fc91d0f1 2023-03-07 jrmu '%c' => 'D M j H:i:s Y', # date time
685 fc91d0f1 2023-03-07 jrmu '%x' => 'm/d/y', # date
686 fc91d0f1 2023-03-07 jrmu '%X' => 'H:i:s', # time
687 fc91d0f1 2023-03-07 jrmu );
688 fc91d0f1 2023-03-07 jrmu }
689 fc91d0f1 2023-03-07 jrmu $cached['new'] = isset($EnableFTimeNew)
690 fc91d0f1 2023-03-07 jrmu ? $EnableFTimeNew
691 fc91d0f1 2023-03-07 jrmu : (PHP_VERSION_ID>=80100);
692 fc91d0f1 2023-03-07 jrmu }
693 fc91d0f1 2023-03-07 jrmu
694 fc91d0f1 2023-03-07 jrmu if (@$fmt == '') $fmt = $FTimeFmt;
695 fc91d0f1 2023-03-07 jrmu $stamp = is_numeric($stamp)? intval($stamp) : $Now;
696 fc91d0f1 2023-03-07 jrmu
697 fc91d0f1 2023-03-07 jrmu if(preg_match('/(?<!%)(%L)/', $fmt)) {
698 fc91d0f1 2023-03-07 jrmu $gmt = PSFT('@%Y-%m-%dT%H:%M:%SZ', $stamp, null, 'GMT');
699 fc91d0f1 2023-03-07 jrmu $fmt = preg_replace('/(?<!%)(%L)/', $gmt, $fmt);
700 fc91d0f1 2023-03-07 jrmu }
701 fc91d0f1 2023-03-07 jrmu
702 fc91d0f1 2023-03-07 jrmu if (! $cached['new']) {
703 fc91d0f1 2023-03-07 jrmu if (@$locale)
704 fc91d0f1 2023-03-07 jrmu setlocale(LC_TIME, preg_split('/[, ]+/', $locale, -1, PREG_SPLIT_NO_EMPTY));
705 fc91d0f1 2023-03-07 jrmu if (@$tz) @date_default_timezone_set($tz);
706 fc91d0f1 2023-03-07 jrmu $fmt = str_replace(array('%F', '%s', '%o'),
707 fc91d0f1 2023-03-07 jrmu array('%Y-%m-%d', $stamp, date('S', $stamp)),
708 fc91d0f1 2023-03-07 jrmu $fmt);
709 fc91d0f1 2023-03-07 jrmu $ret = strftime($fmt, $stamp);
710 fc91d0f1 2023-03-07 jrmu if ($tz) date_default_timezone_set($cached['dtz']);
711 fc91d0f1 2023-03-07 jrmu if (@$locale) setlocale(LC_TIME, $cached['dloc']);
712 fc91d0f1 2023-03-07 jrmu return $ret;
713 fc91d0f1 2023-03-07 jrmu }
714 fc91d0f1 2023-03-07 jrmu
715 fc91d0f1 2023-03-07 jrmu $timestamp = date_create("@$stamp");
716 fc91d0f1 2023-03-07 jrmu if ($tz) {
717 fc91d0f1 2023-03-07 jrmu $tzo = @timezone_open($tz);
718 fc91d0f1 2023-03-07 jrmu if (!@$tzo) unset($tz);
719 fc91d0f1 2023-03-07 jrmu }
720 fc91d0f1 2023-03-07 jrmu if (!@$tz) { # need to set it otherwise resets to GMT
721 fc91d0f1 2023-03-07 jrmu $tz = $cached['dtz'];
722 fc91d0f1 2023-03-07 jrmu $tzo = $cached['dtzo'];
723 fc91d0f1 2023-03-07 jrmu }
724 fc91d0f1 2023-03-07 jrmu date_timezone_set($timestamp, $tzo);
725 fc91d0f1 2023-03-07 jrmu
726 fc91d0f1 2023-03-07 jrmu $vars = array(
727 fc91d0f1 2023-03-07 jrmu 'tz' => $tz,
728 fc91d0f1 2023-03-07 jrmu 'timestamp' => $timestamp,
729 fc91d0f1 2023-03-07 jrmu 'formats' => $cached['formats'],
730 fc91d0f1 2023-03-07 jrmu 'iformats' => $cached['iformats'],
731 fc91d0f1 2023-03-07 jrmu );
732 fc91d0f1 2023-03-07 jrmu if ($locale) $vars['locale'] = substr($locale, 0, 5);
733 fc91d0f1 2023-03-07 jrmu
734 fc91d0f1 2023-03-07 jrmu $cb = new PPRC($vars);
735 fc91d0f1 2023-03-07 jrmu $fmt = preg_replace_callback('/(?<!%)(%[a-zA-Z])/', array($cb, 'ftime'), $fmt);
736 fc91d0f1 2023-03-07 jrmu return str_replace('%%', '%', $fmt);
737 5127fd58 2021-12-17 jrmu }
738 fc91d0f1 2023-03-07 jrmu function cb_PSFT($fmt, $vars) {
739 fc91d0f1 2023-03-07 jrmu extract($vars); # $timestamp, $tz, $locale, $formats, $iformats
740 fc91d0f1 2023-03-07 jrmu
741 fc91d0f1 2023-03-07 jrmu if (isset($formats[$fmt])) {
742 fc91d0f1 2023-03-07 jrmu $fmt = $timestamp->format($formats[$fmt]);
743 fc91d0f1 2023-03-07 jrmu if ($fmt[0]==' ' && strlen($fmt)>2) $fmt = substr($fmt, 1);
744 fc91d0f1 2023-03-07 jrmu return $fmt;
745 fc91d0f1 2023-03-07 jrmu }
746 fc91d0f1 2023-03-07 jrmu if ($fmt=='%o') { # ordinal, PITS:01418
747 fc91d0f1 2023-03-07 jrmu if (!@$locale) $locale = 'C';
748 fc91d0f1 2023-03-07 jrmu $f = numfmt_create($locale, NumberFormatter::ORDINAL);
749 fc91d0f1 2023-03-07 jrmu $o = $f->format($timestamp->format('j'));
750 fc91d0f1 2023-03-07 jrmu return preg_replace('/\\d+/', '', $o);
751 fc91d0f1 2023-03-07 jrmu }
752 fc91d0f1 2023-03-07 jrmu if ($fmt=='%j') return sprintf('%03d',$timestamp->format('z')+1);
753 fc91d0f1 2023-03-07 jrmu if ($fmt=='%C') return floor($timestamp->format('Y')/100);
754 fc91d0f1 2023-03-07 jrmu if ($fmt=='%g') return sprintf('%02d', $timestamp->format('o') % 100);
755 fc91d0f1 2023-03-07 jrmu if ($fmt=='%U') return cb_PSFT_UW($timestamp, $tz, 'Sunday');
756 fc91d0f1 2023-03-07 jrmu if ($fmt=='%W') return cb_PSFT_UW($timestamp, $tz, 'Monday');
757 fc91d0f1 2023-03-07 jrmu
758 fc91d0f1 2023-03-07 jrmu if (isset($iformats[$fmt])) {
759 fc91d0f1 2023-03-07 jrmu $ifmt = $iformats[$fmt];
760 fc91d0f1 2023-03-07 jrmu return datefmt_create(@$locale, $ifmt[0], $ifmt[1], $tz, null, @$ifmt[2])->format($timestamp);
761 fc91d0f1 2023-03-07 jrmu }
762 fc91d0f1 2023-03-07 jrmu return $fmt;
763 fc91d0f1 2023-03-07 jrmu }
764 fc91d0f1 2023-03-07 jrmu function cb_PSFT_UW($timestamp, $tz, $day) { # helper for %U %W
765 fc91d0f1 2023-03-07 jrmu $first = strtotime(sprintf("%d-01 $day", $timestamp->format('Y')));
766 fc91d0f1 2023-03-07 jrmu $stamp1 = date_create("@$first");
767 fc91d0f1 2023-03-07 jrmu date_timezone_set($stamp1, timezone_open($tz));
768 fc91d0f1 2023-03-07 jrmu $days = $timestamp->format('z') - $stamp1->format('z');
769 fc91d0f1 2023-03-07 jrmu return sprintf('%02d', floor($days/7)+1);
770 fc91d0f1 2023-03-07 jrmu }
771 fc91d0f1 2023-03-07 jrmu
772 fc91d0f1 2023-03-07 jrmu # Only called by old addon|skin|recipe needing update, see pmwiki.org/Troubleshooting
773 5127fd58 2021-12-17 jrmu function PCCF($code, $template = 'default', $args = '$m') {
774 5127fd58 2021-12-17 jrmu global $CallbackFnTemplates, $CallbackFunctions, $PCCFOverrideFunction;
775 5127fd58 2021-12-17 jrmu if ($PCCFOverrideFunction && is_callable($PCCFOverrideFunction))
776 5127fd58 2021-12-17 jrmu return $PCCFOverrideFunction($code, $template, $args);
777 5127fd58 2021-12-17 jrmu
778 5127fd58 2021-12-17 jrmu if (!isset($CallbackFnTemplates[$template]))
779 5127fd58 2021-12-17 jrmu Abort("No \$CallbackFnTemplates[$template]).");
780 5127fd58 2021-12-17 jrmu $code = sprintf($CallbackFnTemplates[$template], $code);
781 5127fd58 2021-12-17 jrmu if (!isset($CallbackFunctions[$code])) {
782 5127fd58 2021-12-17 jrmu $fn = create_function($args, $code); # called by old addon|skin|recipe needing update, see pmwiki.org/Troubleshooting
783 5127fd58 2021-12-17 jrmu if ($fn) $CallbackFunctions[$code] = $fn;
784 5127fd58 2021-12-17 jrmu else StopWatch("Failed to create callback function: ".PHSC($code));
785 5127fd58 2021-12-17 jrmu }
786 5127fd58 2021-12-17 jrmu return $CallbackFunctions[$code];
787 5127fd58 2021-12-17 jrmu }
788 5127fd58 2021-12-17 jrmu function PPRE($pat, $rep, $x) {
789 fc91d0f1 2023-03-07 jrmu if (! function_exists('create_function')) return $x;
790 5127fd58 2021-12-17 jrmu $lambda = PCCF("return $rep;");
791 5127fd58 2021-12-17 jrmu return preg_replace_callback($pat, $lambda, $x);
792 5127fd58 2021-12-17 jrmu }
793 5127fd58 2021-12-17 jrmu function PPRA($array, $x) {
794 fc91d0f1 2023-03-07 jrmu if ($x==='' || is_null($x)) return '';
795 5127fd58 2021-12-17 jrmu foreach((array)$array as $pat => $rep) {
796 fc91d0f1 2023-03-07 jrmu # skip broken patterns rather than crash the PHP installation
797 fc91d0f1 2023-03-07 jrmu $oldpat = preg_match('!^/.+/[^/]*e[^/]*$!', $pat);
798 fc91d0f1 2023-03-07 jrmu if ($oldpat && PHP_VERSION_ID >= 50500) continue;
799 fc91d0f1 2023-03-07 jrmu
800 5127fd58 2021-12-17 jrmu $fmt = $x; # for $FmtP
801 fc91d0f1 2023-03-07 jrmu if (is_callable($rep) && $rep != '_')
802 fc91d0f1 2023-03-07 jrmu $x = preg_replace_callback($pat,$rep,$x);
803 fc91d0f1 2023-03-07 jrmu else
804 fc91d0f1 2023-03-07 jrmu $x = preg_replace($pat,$rep,$x);# simple text OR called by old addon|skin|recipe needing update, see pmwiki.org/Troubleshooting
805 5127fd58 2021-12-17 jrmu }
806 5127fd58 2021-12-17 jrmu return $x;
807 5127fd58 2021-12-17 jrmu }
808 fc91d0f1 2023-03-07 jrmu function PRCB($pat, $repl, $subj, $vars=null, $limit=-1, &$count=null, $flags=0) {
809 fc91d0f1 2023-03-07 jrmu if (isset($vars)) {
810 fc91d0f1 2023-03-07 jrmu $cb = new PPRC($vars, $repl);
811 fc91d0f1 2023-03-07 jrmu $repl = array($cb, 'callback');
812 fc91d0f1 2023-03-07 jrmu }
813 fc91d0f1 2023-03-07 jrmu return preg_replace_callback($pat, $repl, $subj, $limit, $count, $flags);
814 fc91d0f1 2023-03-07 jrmu }
815 5127fd58 2021-12-17 jrmu ## callback functions
816 5127fd58 2021-12-17 jrmu class PPRC { # PmWiki preg replace callbacks + pass local vars
817 5127fd58 2021-12-17 jrmu var $vars;
818 fc91d0f1 2023-03-07 jrmu var $cb;
819 fc91d0f1 2023-03-07 jrmu function __construct($vars = null, $cb = null) {
820 fc91d0f1 2023-03-07 jrmu if (!is_null($vars)) $this->vars = $vars;
821 fc91d0f1 2023-03-07 jrmu if (!is_null($cb)) $this->cb = $cb;
822 fc91d0f1 2023-03-07 jrmu
823 5127fd58 2021-12-17 jrmu }
824 5127fd58 2021-12-17 jrmu function pagevar($m) { # called from FmtPageName
825 5127fd58 2021-12-17 jrmu $pagename = $this->vars;
826 5127fd58 2021-12-17 jrmu return PageVar($pagename, $m[1]);
827 5127fd58 2021-12-17 jrmu }
828 fc91d0f1 2023-03-07 jrmu function ftime($m) { # called from PSFT
829 fc91d0f1 2023-03-07 jrmu $vars = $this->vars;
830 fc91d0f1 2023-03-07 jrmu return cb_PSFT($m[0], $vars);
831 fc91d0f1 2023-03-07 jrmu }
832 fc91d0f1 2023-03-07 jrmu function callback($m) {
833 fc91d0f1 2023-03-07 jrmu $cb = $this->cb;
834 fc91d0f1 2023-03-07 jrmu return $cb($m, $this->vars);
835 fc91d0f1 2023-03-07 jrmu }
836 5127fd58 2021-12-17 jrmu }
837 5127fd58 2021-12-17 jrmu
838 5127fd58 2021-12-17 jrmu # restores kept/protected strings
839 fc91d0f1 2023-03-07 jrmu function cb_expandkpv($m) { return @$GLOBALS['KPV'][$m[1]]; }
840 5127fd58 2021-12-17 jrmu
841 5127fd58 2021-12-17 jrmu # make a string upper or lower case in various patterns
842 5127fd58 2021-12-17 jrmu function cb_toupper($m) { return strtoupper($m[1]); }
843 5127fd58 2021-12-17 jrmu function cb_tolower($m) { return strtolower($m[1]); }
844 5127fd58 2021-12-17 jrmu
845 5127fd58 2021-12-17 jrmu function pmcrypt($str, $salt=null) {
846 5127fd58 2021-12-17 jrmu if ($salt && preg_match('/^(-?@|\\*$)/', $salt)) return false;
847 5127fd58 2021-12-17 jrmu if (!is_null($salt)) return crypt($str, $salt);
848 5127fd58 2021-12-17 jrmu
849 5127fd58 2021-12-17 jrmu if (function_exists('password_hash'))
850 5127fd58 2021-12-17 jrmu return password_hash($str, PASSWORD_DEFAULT);
851 5127fd58 2021-12-17 jrmu return crypt($str);
852 5127fd58 2021-12-17 jrmu }
853 5127fd58 2021-12-17 jrmu
854 fc91d0f1 2023-03-07 jrmu # generate or check a random one-time token to prevent CSRF
855 fc91d0f1 2023-03-07 jrmu function pmtoken($token = null) {
856 fc91d0f1 2023-03-07 jrmu global $SessionMaxTokens, $PmTokenFn;
857 fc91d0f1 2023-03-07 jrmu if (IsEnabled($PmTokenFn) && function_exists($PmTokenFn))
858 fc91d0f1 2023-03-07 jrmu return $PmTokenFn($token);
859 fc91d0f1 2023-03-07 jrmu pm_session_start();
860 fc91d0f1 2023-03-07 jrmu if (!isset($_SESSION['pmtokens'])) $_SESSION['pmtokens'] = array();
861 fc91d0f1 2023-03-07 jrmu if (is_null($token)) { # create a one-time token
862 fc91d0f1 2023-03-07 jrmu $len = mt_rand(20,30);
863 fc91d0f1 2023-03-07 jrmu $token = "";
864 fc91d0f1 2023-03-07 jrmu while(strlen($token)<$len) {
865 fc91d0f1 2023-03-07 jrmu $token .= chr(mt_rand(32,126));
866 fc91d0f1 2023-03-07 jrmu }
867 fc91d0f1 2023-03-07 jrmu if (count($_SESSION['pmtokens']))
868 fc91d0f1 2023-03-07 jrmu $id = max(array_keys($_SESSION['pmtokens']))+1;
869 fc91d0f1 2023-03-07 jrmu else $id = 0;
870 fc91d0f1 2023-03-07 jrmu $_SESSION['pmtokens'][$id] = $token;
871 fc91d0f1 2023-03-07 jrmu if (IsEnabled($SessionMaxTokens, 0)) {
872 fc91d0f1 2023-03-07 jrmu $max = $SessionMaxTokens;
873 fc91d0f1 2023-03-07 jrmu $_SESSION['pmtokens'] = array_slice($_SESSION['pmtokens'], -$max, $max, true);
874 fc91d0f1 2023-03-07 jrmu }
875 fc91d0f1 2023-03-07 jrmu return "$id:" . md5($token);
876 fc91d0f1 2023-03-07 jrmu }
877 fc91d0f1 2023-03-07 jrmu # else: check a token, if correct, delete it
878 fc91d0f1 2023-03-07 jrmu @list($id, $hash) = explode(':', $token);
879 fc91d0f1 2023-03-07 jrmu $id = intval($id);
880 fc91d0f1 2023-03-07 jrmu if (isset($_SESSION['pmtokens'][$id]) && $hash == md5($_SESSION['pmtokens'][$id])) {
881 fc91d0f1 2023-03-07 jrmu unset($_SESSION['pmtokens'][$id]);
882 fc91d0f1 2023-03-07 jrmu return true;
883 fc91d0f1 2023-03-07 jrmu }
884 fc91d0f1 2023-03-07 jrmu return false;
885 fc91d0f1 2023-03-07 jrmu }
886 fc91d0f1 2023-03-07 jrmu
887 fc91d0f1 2023-03-07 jrmu function PmNonce() {
888 fc91d0f1 2023-03-07 jrmu if (function_exists('random_bytes')) {
889 fc91d0f1 2023-03-07 jrmu $nonce = bin2hex(random_bytes(5));
890 fc91d0f1 2023-03-07 jrmu }
891 fc91d0f1 2023-03-07 jrmu else $nonce = mt_rand();
892 fc91d0f1 2023-03-07 jrmu return $nonce;
893 fc91d0f1 2023-03-07 jrmu }
894 fc91d0f1 2023-03-07 jrmu
895 fc91d0f1 2023-03-07 jrmu
896 fc91d0f1 2023-03-07 jrmu
897 5127fd58 2021-12-17 jrmu function StopWatch($x) {
898 5127fd58 2021-12-17 jrmu global $StopWatch, $EnableStopWatch;
899 5127fd58 2021-12-17 jrmu if (!$EnableStopWatch) return;
900 5127fd58 2021-12-17 jrmu static $wstart = 0, $ustart = 0;
901 5127fd58 2021-12-17 jrmu list($usec,$sec) = explode(' ',microtime());
902 5127fd58 2021-12-17 jrmu $wtime = ($sec+$usec);
903 5127fd58 2021-12-17 jrmu if (!$wstart) $wstart = $wtime;
904 5127fd58 2021-12-17 jrmu if ($EnableStopWatch != 2)
905 5127fd58 2021-12-17 jrmu { $StopWatch[] = sprintf("%05.2f %s", $wtime-$wstart, $x); return; }
906 5127fd58 2021-12-17 jrmu $dat = getrusage();
907 5127fd58 2021-12-17 jrmu $utime = ($dat['ru_utime.tv_sec']+$dat['ru_utime.tv_usec']/1000000);
908 5127fd58 2021-12-17 jrmu if (!$ustart) $ustart=$utime;
909 5127fd58 2021-12-17 jrmu $StopWatch[] =
910 5127fd58 2021-12-17 jrmu sprintf("%05.2f %05.2f %s", $wtime-$wstart, $utime-$ustart, $x);
911 5127fd58 2021-12-17 jrmu }
912 5127fd58 2021-12-17 jrmu
913 5127fd58 2021-12-17 jrmu
914 5127fd58 2021-12-17 jrmu ## DRange converts a variety of string formats into date (ranges).
915 5127fd58 2021-12-17 jrmu ## It returns the start and end timestamps (+1 second) of the specified date.
916 5127fd58 2021-12-17 jrmu function DRange($when) {
917 5127fd58 2021-12-17 jrmu global $Now;
918 5127fd58 2021-12-17 jrmu ## unix/posix @timestamp dates
919 5127fd58 2021-12-17 jrmu if (preg_match('/^\\s*@(\\d+)\\s*(.*)$/', $when, $m)) {
920 5127fd58 2021-12-17 jrmu $t0 = $m[2] ? strtotime($m[2], $m[1]) : $m[1];
921 5127fd58 2021-12-17 jrmu return array($t0, $t0+1);
922 5127fd58 2021-12-17 jrmu }
923 5127fd58 2021-12-17 jrmu ## ISO-8601 dates
924 5127fd58 2021-12-17 jrmu $dpat = '/
925 5127fd58 2021-12-17 jrmu (?<!\\d) # non-digit
926 5127fd58 2021-12-17 jrmu (19\\d\\d|20[0-3]\\d) # year ($1)
927 5127fd58 2021-12-17 jrmu ([-.\\/]?) # date separator ($2)
928 5127fd58 2021-12-17 jrmu (0\\d|1[0-2]) # month ($3)
929 5127fd58 2021-12-17 jrmu (?: \\2 # repeat date separator
930 5127fd58 2021-12-17 jrmu ([0-2]\\d|3[0-1]) # day ($4)
931 5127fd58 2021-12-17 jrmu (?: T # time marker
932 5127fd58 2021-12-17 jrmu ([01]\\d|2[0-4]) # hour ($5)
933 5127fd58 2021-12-17 jrmu ([.:]?) # time separator ($6)
934 5127fd58 2021-12-17 jrmu ([0-5]\\d) # minute ($7)
935 5127fd58 2021-12-17 jrmu (?: \\6 # repeat time separator
936 5127fd58 2021-12-17 jrmu ([0-5]\\d|60) # seconds ($8)
937 5127fd58 2021-12-17 jrmu )? # optional :ss
938 5127fd58 2021-12-17 jrmu )? # optional Thh:mm:ss
939 5127fd58 2021-12-17 jrmu )? # optional -ddThh:mm:ss
940 5127fd58 2021-12-17 jrmu (?!\d) # non-digit
941 5127fd58 2021-12-17 jrmu /x';
942 5127fd58 2021-12-17 jrmu if (preg_match($dpat, $when, $m) &&
943 5127fd58 2021-12-17 jrmu !preg_match('/[+-]\\s*\\d+\\s*(sec(ond)?|min(ute)?|forth?night|day|week(day)?|month|year)s?/i', $when)) {
944 5127fd58 2021-12-17 jrmu $n = $m;
945 5127fd58 2021-12-17 jrmu ## if no time given, assume range of 1 day (except when full month)
946 5127fd58 2021-12-17 jrmu if (@$m[4]>'' && @$m[5] == '') { @$n[4]++; }
947 5127fd58 2021-12-17 jrmu ## if no day given, assume 1st of month and full month range
948 5127fd58 2021-12-17 jrmu if (@$m[4] == '') { $m[4] = 1; $n[4] = 1; $n[3]++; }
949 5127fd58 2021-12-17 jrmu ## if no seconds given, assume range of 1 minute (except when full day)
950 5127fd58 2021-12-17 jrmu if (@$m[7]>'' && @$m[8] == '') { @$n[7]++; }
951 5127fd58 2021-12-17 jrmu $t0 = @mktime($m[5], $m[7], $m[8], $m[3], $m[4], $m[1]);
952 5127fd58 2021-12-17 jrmu $t1 = @mktime($n[5], $n[7], $n[8], $n[3], $n[4], $n[1]);
953 5127fd58 2021-12-17 jrmu return array($t0, $t1);
954 5127fd58 2021-12-17 jrmu }
955 5127fd58 2021-12-17 jrmu ## now, today, tomorrow, yesterday
956 5127fd58 2021-12-17 jrmu NoCache();
957 5127fd58 2021-12-17 jrmu if ($when == 'now') return array($Now, $Now+1);
958 5127fd58 2021-12-17 jrmu $m = localtime(time());
959 5127fd58 2021-12-17 jrmu if ($when == 'tomorrow') { $m[3]++; $when = 'today'; }
960 5127fd58 2021-12-17 jrmu if ($when == 'yesterday') { $m[3]--; $when = 'today'; }
961 5127fd58 2021-12-17 jrmu if ($when == 'today')
962 5127fd58 2021-12-17 jrmu return array(mktime(0, 0, 0, $m[4]+1, $m[3] , $m[5]+1900),
963 5127fd58 2021-12-17 jrmu mktime(0, 0, 0, $m[4]+1, $m[3]+1, $m[5]+1900));
964 5127fd58 2021-12-17 jrmu if (preg_match('/^\\s*$/', $when)) return array(-1, -1);
965 5127fd58 2021-12-17 jrmu $t0 = strtotime($when);
966 5127fd58 2021-12-17 jrmu $t1 = strtotime("+1 day", $t0);
967 5127fd58 2021-12-17 jrmu return array($t0, $t1);
968 5127fd58 2021-12-17 jrmu }
969 5127fd58 2021-12-17 jrmu
970 fc91d0f1 2023-03-07 jrmu ## FmtDateTimeZ converts a GMT datetime like @2022-01-08T10:07:08Z
971 fc91d0f1 2023-03-07 jrmu ## into a <time> element formatted according to $TimeFmt
972 fc91d0f1 2023-03-07 jrmu function FmtDateTimeZ($m) {
973 fc91d0f1 2023-03-07 jrmu global $TimeFmt, $TimeISOZFmt;
974 fc91d0f1 2023-03-07 jrmu $time = strtotime(substr($m[0], 1)); # "@"
975 fc91d0f1 2023-03-07 jrmu $iso = PSFT($TimeISOZFmt, $time, null, 'GMT');
976 fc91d0f1 2023-03-07 jrmu $text = PSFT($TimeFmt, $time);
977 fc91d0f1 2023-03-07 jrmu return "<time datetime='$iso'>$text</time>";
978 fc91d0f1 2023-03-07 jrmu }
979 fc91d0f1 2023-03-07 jrmu
980 5127fd58 2021-12-17 jrmu ## DiffTimeCompact subtracts 2 timestamps and outputs a compact
981 5127fd58 2021-12-17 jrmu ## human-readable delay in hours, days, weeks, months or years
982 5127fd58 2021-12-17 jrmu function DiffTimeCompact($time, $time2=null, $precision=1) {
983 fc91d0f1 2023-03-07 jrmu if (is_null($time2)) $time2 = $GLOBALS['Now'];
984 5127fd58 2021-12-17 jrmu $suffix = explode(',', XL('h,d,w,m,y'));
985 5127fd58 2021-12-17 jrmu $x = $hours = abs($time2 - $time)/3600;
986 fc91d0f1 2023-03-07 jrmu if ($x<24) return round($x,$precision).$suffix[0];
987 fc91d0f1 2023-03-07 jrmu $x /= 24; if ($x<14) return round($x,$precision).$suffix[1];
988 fc91d0f1 2023-03-07 jrmu $x /= 7; if ($x< 9) return round($x,$precision).$suffix[2];
989 fc91d0f1 2023-03-07 jrmu $x = $hours/2/365.2425; if ($x<24) return round($x,$precision).$suffix[3];
990 5127fd58 2021-12-17 jrmu return round($hours/24/365.2425,$precision).$suffix[4];
991 5127fd58 2021-12-17 jrmu }
992 5127fd58 2021-12-17 jrmu
993 5127fd58 2021-12-17 jrmu ## FileSizeCompact outputs a human readable file size
994 5127fd58 2021-12-17 jrmu ## with an appropriate suffix.
995 5127fd58 2021-12-17 jrmu ## Note: unreliable filemtime()/stat() over 2GB @ 32bit
996 5127fd58 2021-12-17 jrmu function FileSizeCompact($n, $precision=1) {
997 fc91d0f1 2023-03-07 jrmu if (!(float)$n) return 0;
998 5127fd58 2021-12-17 jrmu $units = 'bkMGTPEZY';
999 5127fd58 2021-12-17 jrmu $b = log((float)$n, 1024);
1000 5127fd58 2021-12-17 jrmu $fb = floor($b);
1001 5127fd58 2021-12-17 jrmu return round(pow(1024,$b-$fb),$precision).@$units[$fb];
1002 5127fd58 2021-12-17 jrmu }
1003 5127fd58 2021-12-17 jrmu
1004 5127fd58 2021-12-17 jrmu ## AsSpaced converts a string with WikiWords into a spaced version
1005 5127fd58 2021-12-17 jrmu ## of that string. (It can be overridden via $AsSpacedFunction.)
1006 5127fd58 2021-12-17 jrmu function AsSpaced($text) {
1007 5127fd58 2021-12-17 jrmu $text = preg_replace("/([[:lower:]\\d])([[:upper:]])/", '$1 $2', $text);
1008 5127fd58 2021-12-17 jrmu $text = preg_replace('/([^-\\d])(\\d[-\\d]*( |$))/','$1 $2',$text);
1009 5127fd58 2021-12-17 jrmu return preg_replace("/([[:upper:]])([[:upper:]][[:lower:]\\d])/",
1010 5127fd58 2021-12-17 jrmu '$1 $2', $text);
1011 5127fd58 2021-12-17 jrmu }
1012 5127fd58 2021-12-17 jrmu
1013 5127fd58 2021-12-17 jrmu ## Lock is used to make sure only one instance of PmWiki is running when
1014 5127fd58 2021-12-17 jrmu ## files are being written. It does not "lock pages" for editing.
1015 5127fd58 2021-12-17 jrmu function Lock($op) {
1016 5127fd58 2021-12-17 jrmu global $WorkDir, $LockFile, $EnableReadOnly;
1017 5127fd58 2021-12-17 jrmu if ($op > 0 && IsEnabled($EnableReadOnly, 0))
1018 5127fd58 2021-12-17 jrmu Abort('Cannot modify site -- $EnableReadOnly is set', 'readonly');
1019 5127fd58 2021-12-17 jrmu SDV($LockFile, "$WorkDir/.flock");
1020 5127fd58 2021-12-17 jrmu mkdirp(dirname($LockFile));
1021 5127fd58 2021-12-17 jrmu static $lockfp,$curop;
1022 5127fd58 2021-12-17 jrmu if (!$lockfp) $lockfp = @fopen($LockFile, "w");
1023 5127fd58 2021-12-17 jrmu if (!$lockfp) {
1024 5127fd58 2021-12-17 jrmu if ($op <= 0) return;
1025 5127fd58 2021-12-17 jrmu @unlink($LockFile);
1026 5127fd58 2021-12-17 jrmu $lockfp = fopen($LockFile,"w") or
1027 5127fd58 2021-12-17 jrmu Abort('Cannot acquire lockfile', 'flock');
1028 5127fd58 2021-12-17 jrmu fixperms($LockFile);
1029 5127fd58 2021-12-17 jrmu }
1030 5127fd58 2021-12-17 jrmu if ($op<0) { flock($lockfp,LOCK_UN); fclose($lockfp); $lockfp=0; $curop=0; }
1031 5127fd58 2021-12-17 jrmu elseif ($op==0) { flock($lockfp,LOCK_UN); $curop=0; }
1032 5127fd58 2021-12-17 jrmu elseif ($op==1 && $curop<1)
1033 5127fd58 2021-12-17 jrmu { session_write_close(); flock($lockfp,LOCK_SH); $curop=1; }
1034 5127fd58 2021-12-17 jrmu elseif ($op==2 && $curop<2)
1035 5127fd58 2021-12-17 jrmu { session_write_close(); flock($lockfp,LOCK_EX); $curop=2; }
1036 5127fd58 2021-12-17 jrmu }
1037 5127fd58 2021-12-17 jrmu
1038 5127fd58 2021-12-17 jrmu ## mkdirp creates a directory and its parents as needed, and sets
1039 5127fd58 2021-12-17 jrmu ## permissions accordingly.
1040 5127fd58 2021-12-17 jrmu function mkdirp($dir) {
1041 5127fd58 2021-12-17 jrmu global $ScriptUrl;
1042 5127fd58 2021-12-17 jrmu if (file_exists($dir)) return;
1043 5127fd58 2021-12-17 jrmu if (!file_exists(dirname($dir))) mkdirp(dirname($dir));
1044 5127fd58 2021-12-17 jrmu if (mkdir($dir, 0777)) {
1045 5127fd58 2021-12-17 jrmu fixperms($dir);
1046 5127fd58 2021-12-17 jrmu if (@touch("$dir/xxx")) { unlink("$dir/xxx"); return; }
1047 5127fd58 2021-12-17 jrmu rmdir($dir);
1048 5127fd58 2021-12-17 jrmu }
1049 5127fd58 2021-12-17 jrmu $parent = realpath(dirname($dir));
1050 5127fd58 2021-12-17 jrmu $bdir = basename($dir);
1051 5127fd58 2021-12-17 jrmu $perms = decoct(fileperms($parent) & 03777);
1052 5127fd58 2021-12-17 jrmu $msg = "PmWiki needs to have a writable <tt>$dir/</tt> directory
1053 5127fd58 2021-12-17 jrmu before it can continue. You can create the directory manually
1054 5127fd58 2021-12-17 jrmu by executing the following commands on your server:
1055 5127fd58 2021-12-17 jrmu <pre> mkdir $parent/$bdir\n chmod 777 $parent/$bdir</pre>
1056 5127fd58 2021-12-17 jrmu Then, <a href='{$ScriptUrl}'>reload this page</a>.";
1057 5127fd58 2021-12-17 jrmu $safemode = ini_get('safe_mode');
1058 5127fd58 2021-12-17 jrmu if (!$safemode) $msg .= "<br /><br />Or, for a slightly more
1059 5127fd58 2021-12-17 jrmu secure installation, try executing <pre> chmod 2777 $parent</pre>
1060 5127fd58 2021-12-17 jrmu on your server and following <a target='_blank' href='$ScriptUrl'>
1061 5127fd58 2021-12-17 jrmu this link</a>. Afterwards you can restore the permissions to
1062 5127fd58 2021-12-17 jrmu their current setting by executing <pre> chmod $perms $parent</pre>.";
1063 5127fd58 2021-12-17 jrmu Abort($msg);
1064 5127fd58 2021-12-17 jrmu }
1065 5127fd58 2021-12-17 jrmu
1066 5127fd58 2021-12-17 jrmu ## fixperms attempts to correct permissions on a file or directory
1067 5127fd58 2021-12-17 jrmu ## so that both PmWiki and the account (current dir) owner can manipulate it
1068 5127fd58 2021-12-17 jrmu function fixperms($fname, $add = 0, $set = 0) {
1069 5127fd58 2021-12-17 jrmu clearstatcache();
1070 5127fd58 2021-12-17 jrmu if (!file_exists($fname)) Abort('?no such file');
1071 5127fd58 2021-12-17 jrmu if ($set) { # advanced admins, $UploadPermSet
1072 5127fd58 2021-12-17 jrmu if (fileperms($fname) != $set) @chmod($fname,$set);
1073 5127fd58 2021-12-17 jrmu }
1074 5127fd58 2021-12-17 jrmu else {
1075 5127fd58 2021-12-17 jrmu $bp = 0;
1076 5127fd58 2021-12-17 jrmu if (fileowner($fname)!=@fileowner('.') && @fileowner('.')!==0)
1077 5127fd58 2021-12-17 jrmu $bp = (is_dir($fname)) ? 007 : 006;
1078 5127fd58 2021-12-17 jrmu if (filegroup($fname)==@filegroup('.')) $bp <<= 3;
1079 5127fd58 2021-12-17 jrmu $bp |= $add;
1080 5127fd58 2021-12-17 jrmu if ($bp && (fileperms($fname) & $bp) != $bp)
1081 5127fd58 2021-12-17 jrmu @chmod($fname,fileperms($fname)|$bp);
1082 5127fd58 2021-12-17 jrmu }
1083 5127fd58 2021-12-17 jrmu }
1084 5127fd58 2021-12-17 jrmu
1085 5127fd58 2021-12-17 jrmu ## GlobToPCRE converts wildcard patterns into pcre patterns for
1086 5127fd58 2021-12-17 jrmu ## inclusion and exclusion. Wildcards beginning with '-' or '!'
1087 5127fd58 2021-12-17 jrmu ## are treated as things to be excluded.
1088 5127fd58 2021-12-17 jrmu function GlobToPCRE($pat) {
1089 5127fd58 2021-12-17 jrmu $pat = preg_quote($pat, '/');
1090 5127fd58 2021-12-17 jrmu $pat = str_replace(array('\\*', '\\?', '\\[', '\\]', '\\^', '\\-', '\\!'),
1091 5127fd58 2021-12-17 jrmu array('.*', '.', '[', ']', '^', '-', '!'), $pat);
1092 5127fd58 2021-12-17 jrmu $excl = array(); $incl = array();
1093 5127fd58 2021-12-17 jrmu foreach(preg_split('/,+\s?/', $pat, -1, PREG_SPLIT_NO_EMPTY) as $p) {
1094 5127fd58 2021-12-17 jrmu if ($p[0] == '-' || $p[0] == '!') $excl[] = '^'.substr($p, 1).'$';
1095 5127fd58 2021-12-17 jrmu else $incl[] = "^$p$";
1096 5127fd58 2021-12-17 jrmu }
1097 5127fd58 2021-12-17 jrmu return array(implode('|', $incl), implode('|', $excl));
1098 5127fd58 2021-12-17 jrmu }
1099 5127fd58 2021-12-17 jrmu
1100 5127fd58 2021-12-17 jrmu ## FixGlob changes wildcard patterns without '.' to things like
1101 5127fd58 2021-12-17 jrmu ## '*.foo' (name matches) or 'foo.*' (group matches).
1102 5127fd58 2021-12-17 jrmu function FixGlob($x, $rep = '$1*.$2') {
1103 5127fd58 2021-12-17 jrmu return preg_replace('/([\\s,][-!]?)([^\\/.\\s,]+)(?=[\\s,])/', $rep, ",$x,");
1104 5127fd58 2021-12-17 jrmu }
1105 5127fd58 2021-12-17 jrmu
1106 5127fd58 2021-12-17 jrmu ## MatchPageNames reduces $pagelist to those pages with names
1107 5127fd58 2021-12-17 jrmu ## matching the pattern(s) in $pat. Patterns can be either
1108 5127fd58 2021-12-17 jrmu ## regexes to include ('/'), regexes to exclude ('!'), or
1109 5127fd58 2021-12-17 jrmu ## wildcard patterns (all others).
1110 fc91d0f1 2023-03-07 jrmu function MatchPageNames($pagelist, $pat, $caseinsensitive = true) {
1111 5127fd58 2021-12-17 jrmu # Note: MatchNames() is the generic function matching patterns,
1112 5127fd58 2021-12-17 jrmu # works for attachments and other arrays. We can commit to
1113 5127fd58 2021-12-17 jrmu # keep it generic, even if we someday change MatchPageNames().
1114 fc91d0f1 2023-03-07 jrmu return MatchNames($pagelist, $pat, $caseinsensitive);
1115 5127fd58 2021-12-17 jrmu }
1116 fc91d0f1 2023-03-07 jrmu function MatchNames($list, $pat, $caseinsensitive = true) {
1117 5127fd58 2021-12-17 jrmu global $Charset, $EnableRangeMatchUTF8;
1118 5127fd58 2021-12-17 jrmu # allow range matches in utf8; doesn't work on pmwiki.org and possibly elsewhere
1119 5127fd58 2021-12-17 jrmu $pcre8 = (IsEnabled($EnableRangeMatchUTF8,0) && $Charset=='UTF-8')? 'u' : '';
1120 fc91d0f1 2023-03-07 jrmu $insensitive = $caseinsensitive ? 'i' : '';
1121 5127fd58 2021-12-17 jrmu $list = (array)$list;
1122 5127fd58 2021-12-17 jrmu foreach((array)$pat as $p) {
1123 5127fd58 2021-12-17 jrmu if (count($list) < 1) break;
1124 5127fd58 2021-12-17 jrmu if (!$p) continue;
1125 5127fd58 2021-12-17 jrmu switch ($p[0]) {
1126 5127fd58 2021-12-17 jrmu case '/':
1127 5127fd58 2021-12-17 jrmu $list = preg_grep($p, $list);
1128 5127fd58 2021-12-17 jrmu break;
1129 5127fd58 2021-12-17 jrmu case '!':
1130 5127fd58 2021-12-17 jrmu $list = array_diff($list, preg_grep($p, $list));
1131 5127fd58 2021-12-17 jrmu break;
1132 5127fd58 2021-12-17 jrmu default:
1133 5127fd58 2021-12-17 jrmu list($inclp, $exclp) = GlobToPCRE(str_replace('/', '.', $p));
1134 5127fd58 2021-12-17 jrmu if ($exclp)
1135 fc91d0f1 2023-03-07 jrmu $list = array_diff($list, preg_grep("/$exclp/$insensitive$pcre8", $list));
1136 5127fd58 2021-12-17 jrmu if ($inclp)
1137 fc91d0f1 2023-03-07 jrmu $list = preg_grep("/$inclp/$insensitive$pcre8", $list);
1138 5127fd58 2021-12-17 jrmu }
1139 5127fd58 2021-12-17 jrmu }
1140 5127fd58 2021-12-17 jrmu return $list;
1141 5127fd58 2021-12-17 jrmu }
1142 5127fd58 2021-12-17 jrmu
1143 5127fd58 2021-12-17 jrmu ## ResolvePageName "normalizes" a pagename based on the current
1144 5127fd58 2021-12-17 jrmu ## settings of $DefaultPage and $PagePathFmt. It's normally used
1145 5127fd58 2021-12-17 jrmu ## during initialization to fix up any missing or partial pagenames.
1146 5127fd58 2021-12-17 jrmu function ResolvePageName($pagename) {
1147 5127fd58 2021-12-17 jrmu global $DefaultPage, $DefaultGroup, $DefaultName,
1148 5127fd58 2021-12-17 jrmu $GroupPattern, $NamePattern, $EnableFixedUrlRedirect;
1149 5127fd58 2021-12-17 jrmu SDV($DefaultPage, "$DefaultGroup.$DefaultName");
1150 5127fd58 2021-12-17 jrmu $pagename = preg_replace('!([./][^./]+)\\.html?$!', '$1', $pagename);
1151 5127fd58 2021-12-17 jrmu if ($pagename == '') return $DefaultPage;
1152 5127fd58 2021-12-17 jrmu $p = MakePageName($DefaultPage, $pagename);
1153 5127fd58 2021-12-17 jrmu if (!preg_match("/^($GroupPattern)[.\\/]($NamePattern)$/i", $p)) {
1154 5127fd58 2021-12-17 jrmu header('HTTP/1.1 404 Not Found');
1155 5127fd58 2021-12-17 jrmu Abort("\$[?invalid page name] \"$p\"");
1156 5127fd58 2021-12-17 jrmu }
1157 5127fd58 2021-12-17 jrmu if (preg_match("/^($GroupPattern)[.\\/]($NamePattern)$/i", $pagename))
1158 5127fd58 2021-12-17 jrmu return $p;
1159 5127fd58 2021-12-17 jrmu if (IsEnabled($EnableFixedUrlRedirect, 1)
1160 5127fd58 2021-12-17 jrmu && $p && (PageExists($p) || preg_match('/[\\/.]/', $pagename)))
1161 5127fd58 2021-12-17 jrmu { Redirect($p); exit(); }
1162 5127fd58 2021-12-17 jrmu return MakePageName($DefaultPage, "$pagename.$pagename");
1163 5127fd58 2021-12-17 jrmu }
1164 5127fd58 2021-12-17 jrmu
1165 5127fd58 2021-12-17 jrmu ## MakePageName is used to convert a string $str into a fully-qualified
1166 5127fd58 2021-12-17 jrmu ## pagename. If $str doesn't contain a group qualifier, then
1167 5127fd58 2021-12-17 jrmu ## MakePageName uses $basepage and $PagePathFmt to determine the
1168 5127fd58 2021-12-17 jrmu ## group of the returned pagename.
1169 5127fd58 2021-12-17 jrmu function MakePageName($basepage, $str) {
1170 5127fd58 2021-12-17 jrmu global $MakePageNameFunction, $PageNameChars, $PagePathFmt,
1171 5127fd58 2021-12-17 jrmu $MakePageNamePatterns, $MakePageNameSplitPattern;
1172 5127fd58 2021-12-17 jrmu if (@$MakePageNameFunction) return $MakePageNameFunction($basepage, $str);
1173 fc91d0f1 2023-03-07 jrmu
1174 5127fd58 2021-12-17 jrmu SDV($PageNameChars,'-[:alnum:]');
1175 5127fd58 2021-12-17 jrmu SDV($MakePageNamePatterns, array(
1176 5127fd58 2021-12-17 jrmu "/'/" => '', # strip single-quotes
1177 5127fd58 2021-12-17 jrmu "/[^$PageNameChars]+/" => ' ', # convert everything else to space
1178 5127fd58 2021-12-17 jrmu '/((^|[^-\\w])\\w)/' => 'cb_toupper', # CamelCase
1179 5127fd58 2021-12-17 jrmu '/ /' => ''));
1180 5127fd58 2021-12-17 jrmu SDV($MakePageNameSplitPattern, '/[.\\/]/');
1181 5127fd58 2021-12-17 jrmu $str = preg_replace('/[#?].*$/', '', $str);
1182 5127fd58 2021-12-17 jrmu $m = preg_split($MakePageNameSplitPattern, $str);
1183 5127fd58 2021-12-17 jrmu if (count($m)<1 || count($m)>2 || $m[0]=='') return '';
1184 5127fd58 2021-12-17 jrmu ## handle "Group.Name" conversions
1185 5127fd58 2021-12-17 jrmu if (@$m[1] > '') {
1186 5127fd58 2021-12-17 jrmu $group = PPRA($MakePageNamePatterns, $m[0]);
1187 5127fd58 2021-12-17 jrmu $name = PPRA($MakePageNamePatterns, $m[1]);
1188 5127fd58 2021-12-17 jrmu return "$group.$name";
1189 5127fd58 2021-12-17 jrmu }
1190 5127fd58 2021-12-17 jrmu $name = PPRA($MakePageNamePatterns, $m[0]);
1191 5127fd58 2021-12-17 jrmu $isgrouphome = count($m) > 1;
1192 5127fd58 2021-12-17 jrmu foreach((array)$PagePathFmt as $pg) {
1193 5127fd58 2021-12-17 jrmu if ($isgrouphome && strncmp($pg, '$1.', 3) !== 0) continue;
1194 5127fd58 2021-12-17 jrmu $pn = FmtPageName(str_replace('$1', $name, $pg), $basepage);
1195 5127fd58 2021-12-17 jrmu if (PageExists($pn)) return $pn;
1196 5127fd58 2021-12-17 jrmu }
1197 5127fd58 2021-12-17 jrmu if ($isgrouphome) {
1198 5127fd58 2021-12-17 jrmu foreach((array)$PagePathFmt as $pg)
1199 5127fd58 2021-12-17 jrmu if (strncmp($pg, '$1.', 3) == 0)
1200 5127fd58 2021-12-17 jrmu return FmtPageName(str_replace('$1', $name, $pg), $basepage);
1201 5127fd58 2021-12-17 jrmu return "$name.$name";
1202 5127fd58 2021-12-17 jrmu }
1203 5127fd58 2021-12-17 jrmu return preg_replace('/[^\\/.]+$/', $name, $basepage);
1204 5127fd58 2021-12-17 jrmu }
1205 5127fd58 2021-12-17 jrmu
1206 5127fd58 2021-12-17 jrmu
1207 5127fd58 2021-12-17 jrmu ## MakeBaseName uses $BaseNamePatterns to return the "base" form
1208 5127fd58 2021-12-17 jrmu ## of a given pagename -- i.e., stripping any recipe-defined
1209 5127fd58 2021-12-17 jrmu ## prefixes or suffixes from the page.
1210 5127fd58 2021-12-17 jrmu function MakeBaseName($pagename, $patlist = NULL) {
1211 5127fd58 2021-12-17 jrmu global $BaseNamePatterns;
1212 5127fd58 2021-12-17 jrmu if (is_null($patlist)) $patlist = (array)@$BaseNamePatterns;
1213 5127fd58 2021-12-17 jrmu foreach($patlist as $pat => $rep)
1214 5127fd58 2021-12-17 jrmu $pagename = preg_replace($pat, $rep, $pagename); # TODO
1215 5127fd58 2021-12-17 jrmu return $pagename;
1216 5127fd58 2021-12-17 jrmu }
1217 5127fd58 2021-12-17 jrmu
1218 5127fd58 2021-12-17 jrmu
1219 5127fd58 2021-12-17 jrmu ## PCache caches basic information about a page and its attributes--
1220 5127fd58 2021-12-17 jrmu ## usually everything except page text and page history. This makes
1221 5127fd58 2021-12-17 jrmu ## for quicker access to certain values in PageVar below.
1222 5127fd58 2021-12-17 jrmu function PCache($pagename, $page) {
1223 5127fd58 2021-12-17 jrmu global $PCache;
1224 5127fd58 2021-12-17 jrmu foreach($page as $k=>$v)
1225 5127fd58 2021-12-17 jrmu if ($k!='text' && strpos($k,':')===false) $PCache[$pagename][$k]=$v;
1226 5127fd58 2021-12-17 jrmu }
1227 5127fd58 2021-12-17 jrmu
1228 5127fd58 2021-12-17 jrmu ## SetProperty saves a page property into $PCache. For convenience
1229 5127fd58 2021-12-17 jrmu ## it returns the $value of the property just set. If $sep is supplied,
1230 5127fd58 2021-12-17 jrmu ## then $value is appended to the current property (with $sep as
1231 5127fd58 2021-12-17 jrmu ## as separator) instead of replacing it. If $keep is suplied and the
1232 5127fd58 2021-12-17 jrmu ## property already exists, then $value will be ignored.
1233 5127fd58 2021-12-17 jrmu function SetProperty($pagename, $prop, $value, $sep=NULL, $keep=NULL) {
1234 5127fd58 2021-12-17 jrmu global $PCache, $KeepToken;
1235 5127fd58 2021-12-17 jrmu NoCache();
1236 5127fd58 2021-12-17 jrmu $prop = "=p_$prop";
1237 5127fd58 2021-12-17 jrmu $value = preg_replace_callback("/$KeepToken(\\d.*?)$KeepToken/",
1238 5127fd58 2021-12-17 jrmu "cb_expandkpv", $value);
1239 5127fd58 2021-12-17 jrmu if (!is_null($sep) && isset($PCache[$pagename][$prop]))
1240 5127fd58 2021-12-17 jrmu $value = $PCache[$pagename][$prop] . $sep . $value;
1241 5127fd58 2021-12-17 jrmu if (is_null($keep) || !isset($PCache[$pagename][$prop]))
1242 5127fd58 2021-12-17 jrmu $PCache[$pagename][$prop] = $value;
1243 5127fd58 2021-12-17 jrmu return $PCache[$pagename][$prop];
1244 5127fd58 2021-12-17 jrmu }
1245 5127fd58 2021-12-17 jrmu
1246 5127fd58 2021-12-17 jrmu
1247 5127fd58 2021-12-17 jrmu ## PageTextVar loads a page's text variables (defined by
1248 5127fd58 2021-12-17 jrmu ## $PageTextVarPatterns) into a page's $PCache entry, and returns
1249 5127fd58 2021-12-17 jrmu ## the property associated with $var.
1250 5127fd58 2021-12-17 jrmu function PageTextVar($pagename, $var) {
1251 fc91d0f1 2023-03-07 jrmu global $PCache, $PageTextVarPatterns, $MaxPageTextVars,
1252 fc91d0f1 2023-03-07 jrmu $DefaultUnsetPageTextVars, $DefaultEmptyPageTextVars;
1253 5127fd58 2021-12-17 jrmu SDV($MaxPageTextVars, 500);
1254 5127fd58 2021-12-17 jrmu static $status;
1255 5127fd58 2021-12-17 jrmu if (@$status["$pagename:$var"]++ > $MaxPageTextVars) return '';
1256 5127fd58 2021-12-17 jrmu if (!@$PCache[$pagename]['=pagetextvars']) {
1257 5127fd58 2021-12-17 jrmu $pc = &$PCache[$pagename];
1258 5127fd58 2021-12-17 jrmu $pc['=pagetextvars'] = 1;
1259 5127fd58 2021-12-17 jrmu $page = RetrieveAuthPage($pagename, 'read', false, READPAGE_CURRENT);
1260 5127fd58 2021-12-17 jrmu if ($page) {
1261 5127fd58 2021-12-17 jrmu foreach((array)$PageTextVarPatterns as $pat)
1262 fc91d0f1 2023-03-07 jrmu if (preg_match_all($pat, IsEnabled($pc['=preview'],strval(@$page['text'])),
1263 fc91d0f1 2023-03-07 jrmu $match, PREG_SET_ORDER)) {
1264 5127fd58 2021-12-17 jrmu foreach($match as $m) {
1265 5127fd58 2021-12-17 jrmu $t = preg_replace("/\\{\\$:{$m[2]}\\}/", '', $m[3]);
1266 fc91d0f1 2023-03-07 jrmu
1267 5127fd58 2021-12-17 jrmu $pc["=p_{$m[2]}"] = Qualify($pagename, $t);
1268 5127fd58 2021-12-17 jrmu }
1269 fc91d0f1 2023-03-07 jrmu }
1270 fc91d0f1 2023-03-07 jrmu }
1271 5127fd58 2021-12-17 jrmu }
1272 5127fd58 2021-12-17 jrmu if (! isset($PCache[$pagename]["=p_$var"]) && is_array($DefaultUnsetPageTextVars)) {
1273 5127fd58 2021-12-17 jrmu foreach($DefaultUnsetPageTextVars as $k=>$v) {
1274 5127fd58 2021-12-17 jrmu if (count(MatchNames($var, $k))) {
1275 5127fd58 2021-12-17 jrmu $PCache[$pagename]["=p_$var"] = $v;
1276 5127fd58 2021-12-17 jrmu break;
1277 5127fd58 2021-12-17 jrmu }
1278 5127fd58 2021-12-17 jrmu }
1279 5127fd58 2021-12-17 jrmu SDV($PCache[$pagename]["=p_$var"], ''); # to avoid re-loop
1280 5127fd58 2021-12-17 jrmu }
1281 fc91d0f1 2023-03-07 jrmu elseif (@$PCache[$pagename]["=p_$var"] === '' && is_array($DefaultEmptyPageTextVars)) {
1282 5127fd58 2021-12-17 jrmu foreach($DefaultEmptyPageTextVars as $k=>$v) {
1283 5127fd58 2021-12-17 jrmu if (count(MatchNames($var, $k))) {
1284 5127fd58 2021-12-17 jrmu $PCache[$pagename]["=p_$var"] = $v;
1285 5127fd58 2021-12-17 jrmu break;
1286 5127fd58 2021-12-17 jrmu }
1287 5127fd58 2021-12-17 jrmu }
1288 5127fd58 2021-12-17 jrmu SDV($PCache[$pagename]["=p_$var"], ''); # to avoid re-loop
1289 5127fd58 2021-12-17 jrmu }
1290 fc91d0f1 2023-03-07 jrmu return strval(@$PCache[$pagename]["=p_$var"]);
1291 5127fd58 2021-12-17 jrmu }
1292 5127fd58 2021-12-17 jrmu
1293 5127fd58 2021-12-17 jrmu
1294 5127fd58 2021-12-17 jrmu function PageVar($pagename, $var, $pn = '') {
1295 5127fd58 2021-12-17 jrmu global $Cursor, $PCache, $FmtPV, $AsSpacedFunction, $ScriptUrl,
1296 5127fd58 2021-12-17 jrmu $EnablePathInfo;
1297 5127fd58 2021-12-17 jrmu if ($var == '$ScriptUrl') return PUE($ScriptUrl);
1298 5127fd58 2021-12-17 jrmu if ($pn) {
1299 5127fd58 2021-12-17 jrmu $pn = isset($Cursor[$pn]) ? $Cursor[$pn] : MakePageName($pagename, $pn);
1300 5127fd58 2021-12-17 jrmu } else $pn = $pagename;
1301 5127fd58 2021-12-17 jrmu if ($pn) {
1302 5127fd58 2021-12-17 jrmu if (preg_match('/^(.+)[.\\/]([^.\\/]+)$/', $pn, $match)
1303 5127fd58 2021-12-17 jrmu && !isset($PCache[$pn]['time'])
1304 5127fd58 2021-12-17 jrmu && (!@$FmtPV[$var] || strpos($FmtPV[$var], '$page') !== false)) {
1305 5127fd58 2021-12-17 jrmu $page = ReadPage($pn, READPAGE_CURRENT);
1306 5127fd58 2021-12-17 jrmu PCache($pn, $page);
1307 5127fd58 2021-12-17 jrmu }
1308 5127fd58 2021-12-17 jrmu @list($d, $group, $name) = $match;
1309 5127fd58 2021-12-17 jrmu $page = &$PCache[$pn];
1310 fc91d0f1 2023-03-07 jrmu if (@$FmtPV[$var] && strpos(@$FmtPV[$var], '$authpage') !== false) {
1311 5127fd58 2021-12-17 jrmu if (!isset($page['=auth']['read'])) {
1312 5127fd58 2021-12-17 jrmu $x = RetrieveAuthPage($pn, 'read', false, READPAGE_CURRENT);
1313 5127fd58 2021-12-17 jrmu if ($x) PCache($pn, $x);
1314 5127fd58 2021-12-17 jrmu }
1315 5127fd58 2021-12-17 jrmu if (@$page['=auth']['read']) $authpage = &$page;
1316 5127fd58 2021-12-17 jrmu }
1317 5127fd58 2021-12-17 jrmu } else { $group = ''; $name = ''; }
1318 fc91d0f1 2023-03-07 jrmu if (isset($FmtPV[$var])) return eval("return ({$FmtPV[$var]});");
1319 5127fd58 2021-12-17 jrmu if (strncmp($var, '$:', 2)==0) return PageTextVar($pn, substr($var, 2));
1320 5127fd58 2021-12-17 jrmu return '';
1321 5127fd58 2021-12-17 jrmu }
1322 5127fd58 2021-12-17 jrmu
1323 5127fd58 2021-12-17 jrmu ## FmtPageName handles $[internationalization] and $Variable
1324 5127fd58 2021-12-17 jrmu ## substitutions in strings based on the $pagename argument.
1325 5127fd58 2021-12-17 jrmu function FmtPageName($fmt, $pagename) {
1326 5127fd58 2021-12-17 jrmu # Perform $-substitutions on $fmt relative to page given by $pagename
1327 5127fd58 2021-12-17 jrmu global $GroupPattern, $NamePattern, $EnablePathInfo, $ScriptUrl,
1328 5127fd58 2021-12-17 jrmu $GCount, $UnsafeGlobals, $FmtV, $FmtP, $FmtPV, $PCache, $AsSpacedFunction;
1329 fc91d0f1 2023-03-07 jrmu if (! @$fmt) { return ''; }
1330 5127fd58 2021-12-17 jrmu if (strpos($fmt,'$')===false) return $fmt;
1331 5127fd58 2021-12-17 jrmu $fmt = preg_replace_callback('/\\$([A-Z]\\w*Fmt)\\b/','cb_expandglobal',$fmt);
1332 5127fd58 2021-12-17 jrmu $fmt = preg_replace_callback('/\\$\\[(?>([^\\]]+))\\]/',"cb_expandxlang",$fmt);
1333 5127fd58 2021-12-17 jrmu $fmt = str_replace('{$ScriptUrl}', '$ScriptUrl', $fmt);
1334 5127fd58 2021-12-17 jrmu $pprc = new PPRC($pagename);
1335 5127fd58 2021-12-17 jrmu $fmt = preg_replace_callback('/\\{\\*?(\\$[A-Z]\\w+)\\}/',
1336 5127fd58 2021-12-17 jrmu array($pprc, 'pagevar'), $fmt);
1337 5127fd58 2021-12-17 jrmu if (strpos($fmt,'$')===false) return $fmt;
1338 5127fd58 2021-12-17 jrmu if ($FmtP) $fmt = PPRA($FmtP, $fmt); # FIXME
1339 5127fd58 2021-12-17 jrmu static $pv, $pvpat;
1340 5127fd58 2021-12-17 jrmu if ($pv != count($FmtPV)) {
1341 5127fd58 2021-12-17 jrmu $pvpat = str_replace('$', '\\$', implode('|', array_keys($FmtPV)));
1342 5127fd58 2021-12-17 jrmu $pv = count($FmtPV);
1343 5127fd58 2021-12-17 jrmu }
1344 5127fd58 2021-12-17 jrmu $fmt = preg_replace_callback("/($pvpat)\\b/", array($pprc, 'pagevar'), $fmt);
1345 5127fd58 2021-12-17 jrmu $fmt = preg_replace_callback('!\\$ScriptUrl/([^?#\'"\\s<>]+)!',
1346 5127fd58 2021-12-17 jrmu 'cb_expandscripturl', $fmt);
1347 5127fd58 2021-12-17 jrmu if (strpos($fmt,'$')===false) return $fmt;
1348 5127fd58 2021-12-17 jrmu static $g;
1349 5127fd58 2021-12-17 jrmu if ($GCount != count($GLOBALS)+count($FmtV)) {
1350 5127fd58 2021-12-17 jrmu $g = array();
1351 5127fd58 2021-12-17 jrmu foreach($GLOBALS as $n=>$v) {
1352 5127fd58 2021-12-17 jrmu if (is_array($v) || is_object($v) ||
1353 5127fd58 2021-12-17 jrmu isset($FmtV["\$$n"]) || in_array($n,$UnsafeGlobals)) continue;
1354 5127fd58 2021-12-17 jrmu $g["\$$n"] = $v;
1355 5127fd58 2021-12-17 jrmu }
1356 5127fd58 2021-12-17 jrmu $GCount = count($GLOBALS)+count($FmtV);
1357 5127fd58 2021-12-17 jrmu krsort($g); reset($g);
1358 5127fd58 2021-12-17 jrmu }
1359 5127fd58 2021-12-17 jrmu $fmt = str_replace(array_keys($g),array_values($g),$fmt);
1360 5127fd58 2021-12-17 jrmu $fmt = preg_replace_callback('/(?>(\\$[[:alpha:]]\\w+))/',
1361 5127fd58 2021-12-17 jrmu "cb_expandfmtv", $fmt);
1362 5127fd58 2021-12-17 jrmu return $fmt;
1363 5127fd58 2021-12-17 jrmu }
1364 5127fd58 2021-12-17 jrmu function cb_expandglobal($m){ return @$GLOBALS[$m[1]]; }
1365 5127fd58 2021-12-17 jrmu function cb_expandxlang ($m){ return NoCache(XL($m[1])); }
1366 5127fd58 2021-12-17 jrmu function cb_expandfmtv ($m){
1367 5127fd58 2021-12-17 jrmu return isset($GLOBALS['FmtV'][$m[1]]) ? $GLOBALS['FmtV'][$m[1]] : $m[1];
1368 5127fd58 2021-12-17 jrmu }
1369 5127fd58 2021-12-17 jrmu function cb_expandscripturl($m) {
1370 5127fd58 2021-12-17 jrmu global $EnablePathInfo, $ScriptUrl;
1371 5127fd58 2021-12-17 jrmu return (@$EnablePathInfo) ? "$ScriptUrl/" . PUE($m[1])
1372 5127fd58 2021-12-17 jrmu : "$ScriptUrl?n=".str_replace('/','.',PUE($m[1]));
1373 5127fd58 2021-12-17 jrmu }
1374 5127fd58 2021-12-17 jrmu
1375 5127fd58 2021-12-17 jrmu
1376 5127fd58 2021-12-17 jrmu ## FmtPageTitle returns the page title, or the page name.
1377 5127fd58 2021-12-17 jrmu ## It localizes standard technical pages (RecentChanges...)
1378 5127fd58 2021-12-17 jrmu function FmtPageTitle($title, $name, $spaced=0) {
1379 5127fd58 2021-12-17 jrmu if ($title>'') return str_replace("$", "&#036;", $title);
1380 5127fd58 2021-12-17 jrmu global $SpaceWikiWords, $AsSpacedFunction;
1381 5127fd58 2021-12-17 jrmu if (preg_match("/^(Site(Admin)?
1382 5127fd58 2021-12-17 jrmu |(All)?(Site|Group)(Header|Footer|Attributes)
1383 5127fd58 2021-12-17 jrmu |(Side|Left|Right)Bar
1384 5127fd58 2021-12-17 jrmu |(Wiki)?Sand[Bb]ox
1385 5127fd58 2021-12-17 jrmu |(All)?Recent(Changes|Uploads)|(Auth|Edit)Form
1386 5127fd58 2021-12-17 jrmu |InterMap|PageActions|\\w+QuickReference|\\w+Templates
1387 5127fd58 2021-12-17 jrmu |NotifyList|AuthUser|ApprovedUrls|(Block|Auth)List
1388 5127fd58 2021-12-17 jrmu )$/x", $name) && $name != XL($name))
1389 5127fd58 2021-12-17 jrmu return XL($name);
1390 5127fd58 2021-12-17 jrmu return ($spaced || $SpaceWikiWords) ? $AsSpacedFunction($name) : $name;
1391 5127fd58 2021-12-17 jrmu }
1392 5127fd58 2021-12-17 jrmu
1393 fc91d0f1 2023-03-07 jrmu ## FmtGroupHome returns the homepage of any page ($Group or $DefaultName)
1394 fc91d0f1 2023-03-07 jrmu function FmtGroupHome($pn,$group,$var) {
1395 fc91d0f1 2023-03-07 jrmu $gpn = MakePageName($pn, "$group.");
1396 fc91d0f1 2023-03-07 jrmu $pv = substr($var, 14);
1397 fc91d0f1 2023-03-07 jrmu if (!$pv) return $gpn;
1398 fc91d0f1 2023-03-07 jrmu return PageVar($gpn, "\$$pv");
1399 fc91d0f1 2023-03-07 jrmu }
1400 fc91d0f1 2023-03-07 jrmu
1401 5127fd58 2021-12-17 jrmu ## FmtTemplateVars uses $vars to replace all occurrences of
1402 5127fd58 2021-12-17 jrmu ## {$$key} in $text with $vars['key'].
1403 5127fd58 2021-12-17 jrmu function FmtTemplateVars($text, $vars, $pagename = NULL) {
1404 5127fd58 2021-12-17 jrmu global $FmtPV, $EnableUndefinedTemplateVars;
1405 5127fd58 2021-12-17 jrmu if ($pagename) {
1406 5127fd58 2021-12-17 jrmu $pat = implode('|', array_map('preg_quote', array_keys($FmtPV)));
1407 5127fd58 2021-12-17 jrmu $pprc = new PPRC($pagename);
1408 5127fd58 2021-12-17 jrmu $text = preg_replace_callback("/\\{\\$($pat)\\}/",
1409 5127fd58 2021-12-17 jrmu array($pprc, 'pagevar'), $text);
1410 5127fd58 2021-12-17 jrmu }
1411 5127fd58 2021-12-17 jrmu foreach(preg_grep('/^[\\w$]/', array_keys($vars)) as $k)
1412 5127fd58 2021-12-17 jrmu if (!is_array($vars[$k]))
1413 5127fd58 2021-12-17 jrmu $text = str_replace("{\$\$$k}", @$vars[$k], $text);
1414 5127fd58 2021-12-17 jrmu if (! IsEnabled($EnableUndefinedTemplateVars, 0))
1415 5127fd58 2021-12-17 jrmu $text = preg_replace("/\\{\\$\\$\\w+\\}/", '', $text);
1416 5127fd58 2021-12-17 jrmu return $text;
1417 5127fd58 2021-12-17 jrmu }
1418 5127fd58 2021-12-17 jrmu
1419 5127fd58 2021-12-17 jrmu ## The XL functions provide translation tables for $[i18n] strings
1420 5127fd58 2021-12-17 jrmu ## in FmtPageName().
1421 5127fd58 2021-12-17 jrmu function XL($key) {
1422 5127fd58 2021-12-17 jrmu global $XL,$XLLangs;
1423 5127fd58 2021-12-17 jrmu foreach($XLLangs as $l) if (isset($XL[$l][$key])) return $XL[$l][$key];
1424 5127fd58 2021-12-17 jrmu return $key;
1425 5127fd58 2021-12-17 jrmu }
1426 5127fd58 2021-12-17 jrmu function XLSDV($lang,$a) {
1427 5127fd58 2021-12-17 jrmu global $XL;
1428 5127fd58 2021-12-17 jrmu foreach($a as $k=>$v) {
1429 5127fd58 2021-12-17 jrmu if (!isset($XL[$lang][$k])) {
1430 5127fd58 2021-12-17 jrmu if (preg_match('/^e_(rows|cols)$/', $k)) $v = intval($v);
1431 5127fd58 2021-12-17 jrmu elseif (preg_match('/^ak_/', $k)) $v = @$v[0];
1432 5127fd58 2021-12-17 jrmu $XL[$lang][$k]=$v;
1433 5127fd58 2021-12-17 jrmu }
1434 5127fd58 2021-12-17 jrmu }
1435 5127fd58 2021-12-17 jrmu }
1436 5127fd58 2021-12-17 jrmu function XLPage($lang,$p,$nohtml=false) {
1437 5127fd58 2021-12-17 jrmu global $TimeFmt,$XLLangs,$FarmD, $EnableXLPageScriptLoad;
1438 5127fd58 2021-12-17 jrmu $page = ReadPage($p, READPAGE_CURRENT);
1439 5127fd58 2021-12-17 jrmu if (!$page) return;
1440 5127fd58 2021-12-17 jrmu $text = preg_replace("/=>\\s*\n/",'=> ',@$page['text']);
1441 5127fd58 2021-12-17 jrmu foreach(explode("\n",$text) as $l)
1442 5127fd58 2021-12-17 jrmu if (preg_match('/^\\s*[\'"](.+?)[\'"]\\s*=>\\s*[\'"](.+)[\'"]/',$l,$m))
1443 5127fd58 2021-12-17 jrmu $xl[stripslashes($m[1])] = stripslashes($nohtml? PHSC($m[2]): $m[2]);
1444 5127fd58 2021-12-17 jrmu if (isset($xl)) {
1445 5127fd58 2021-12-17 jrmu if (IsEnabled($EnableXLPageScriptLoad, 0) && @$xl['xlpage-i18n']) {
1446 5127fd58 2021-12-17 jrmu $i18n = preg_replace('/[^-\\w]/','',$xl['xlpage-i18n']);
1447 5127fd58 2021-12-17 jrmu include_once("$FarmD/scripts/xlpage-$i18n.php");
1448 5127fd58 2021-12-17 jrmu }
1449 5127fd58 2021-12-17 jrmu if (@$xl['Locale']) setlocale(LC_ALL,$xl['Locale']);
1450 5127fd58 2021-12-17 jrmu if (@$xl['TimeFmt']) $TimeFmt=$xl['TimeFmt'];
1451 5127fd58 2021-12-17 jrmu if (!in_array($lang, $XLLangs)) array_unshift($XLLangs, $lang);
1452 5127fd58 2021-12-17 jrmu XLSDV($lang,$xl);
1453 5127fd58 2021-12-17 jrmu }
1454 5127fd58 2021-12-17 jrmu }
1455 5127fd58 2021-12-17 jrmu
1456 5127fd58 2021-12-17 jrmu ## CmpPageAttr is used with uksort to order a page's elements with
1457 5127fd58 2021-12-17 jrmu ## the latest items first. This can make some operations more efficient.
1458 5127fd58 2021-12-17 jrmu function CmpPageAttr($a, $b) {
1459 5127fd58 2021-12-17 jrmu @list($x, $agmt) = explode(':', $a);
1460 5127fd58 2021-12-17 jrmu @list($x, $bgmt) = explode(':', $b);
1461 fc91d0f1 2023-03-07 jrmu $nagmt = intval($agmt);
1462 fc91d0f1 2023-03-07 jrmu $nbgmt = intval($bgmt);
1463 5127fd58 2021-12-17 jrmu if ($agmt != $bgmt)
1464 fc91d0f1 2023-03-07 jrmu return ($nagmt==0 || $nbgmt==0) ? $nagmt - $nbgmt : $nbgmt - $nagmt;
1465 5127fd58 2021-12-17 jrmu return strcmp($a, $b);
1466 5127fd58 2021-12-17 jrmu }
1467 5127fd58 2021-12-17 jrmu
1468 fc91d0f1 2023-03-07 jrmu function pm_recode($s,$from,$to) {
1469 fc91d0f1 2023-03-07 jrmu static $able;
1470 fc91d0f1 2023-03-07 jrmu if (is_null($able)) {
1471 fc91d0f1 2023-03-07 jrmu # can we rely on iconv() or on mb_convert_encoding() ?
1472 fc91d0f1 2023-03-07 jrmu if (function_exists('iconv') && @iconv("UTF-8", "WINDOWS-1252//IGNORE", "te\xd0\xafst")=='test' )
1473 fc91d0f1 2023-03-07 jrmu $able = 'iconv';
1474 fc91d0f1 2023-03-07 jrmu elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("te\xd0\xafst", "WINDOWS-1252", "UTF-8")=="te?st")
1475 fc91d0f1 2023-03-07 jrmu $able = 'mb';
1476 fc91d0f1 2023-03-07 jrmu elseif (class_exists('UConverter')) $able = 'uc';
1477 fc91d0f1 2023-03-07 jrmu else $able = false;
1478 fc91d0f1 2023-03-07 jrmu }
1479 fc91d0f1 2023-03-07 jrmu $to = strtoupper($to);
1480 fc91d0f1 2023-03-07 jrmu $from = strtoupper($from);
1481 fc91d0f1 2023-03-07 jrmu switch ($able) {
1482 fc91d0f1 2023-03-07 jrmu case "iconv":
1483 fc91d0f1 2023-03-07 jrmu return @iconv($from,"$to//IGNORE",$s);
1484 fc91d0f1 2023-03-07 jrmu case "mb":
1485 fc91d0f1 2023-03-07 jrmu return @mb_convert_encoding($s,$to,$from);
1486 fc91d0f1 2023-03-07 jrmu case "uc":
1487 fc91d0f1 2023-03-07 jrmu if ($to == 'WINDOWS-1252') $to = 'ISO-8859-1';
1488 fc91d0f1 2023-03-07 jrmu if ($from == 'WINDOWS-1252') $from = 'ISO-8859-1';
1489 fc91d0f1 2023-03-07 jrmu return @UConverter::transcode($s,$to,$from);
1490 fc91d0f1 2023-03-07 jrmu }
1491 fc91d0f1 2023-03-07 jrmu if (function_exists('utf8_decode')) {
1492 fc91d0f1 2023-03-07 jrmu if ($to=='UTF-8' && $from=='WINDOWS-1252') return @utf8_decode($s);
1493 fc91d0f1 2023-03-07 jrmu if ($from=='UTF-8' && $to=='WINDOWS-1252') return @utf8_encode($s);
1494 fc91d0f1 2023-03-07 jrmu }
1495 fc91d0f1 2023-03-07 jrmu return $s;
1496 fc91d0f1 2023-03-07 jrmu }
1497 fc91d0f1 2023-03-07 jrmu
1498 5127fd58 2021-12-17 jrmu ## class PageStore holds objects that store pages via the native
1499 5127fd58 2021-12-17 jrmu ## filesystem.
1500 5127fd58 2021-12-17 jrmu class PageStore {
1501 5127fd58 2021-12-17 jrmu var $dirfmt;
1502 5127fd58 2021-12-17 jrmu var $iswrite;
1503 5127fd58 2021-12-17 jrmu var $encodefilenames;
1504 5127fd58 2021-12-17 jrmu var $attr;
1505 5127fd58 2021-12-17 jrmu function __construct($d='$WorkDir/$FullName', $w=0, $a=NULL) {
1506 5127fd58 2021-12-17 jrmu $this->dirfmt = $d; $this->iswrite = $w; $this->attr = (array)$a;
1507 5127fd58 2021-12-17 jrmu $GLOBALS['PageExistsCache'] = array();
1508 5127fd58 2021-12-17 jrmu }
1509 5127fd58 2021-12-17 jrmu function recodefn($s,$from,$to) {
1510 fc91d0f1 2023-03-07 jrmu return pm_recode($s,$from,$to);
1511 5127fd58 2021-12-17 jrmu }
1512 5127fd58 2021-12-17 jrmu function pagefile($pagename) {
1513 5127fd58 2021-12-17 jrmu global $FarmD;
1514 5127fd58 2021-12-17 jrmu $dfmt = $this->dirfmt;
1515 5127fd58 2021-12-17 jrmu if ($pagename > '') {
1516 5127fd58 2021-12-17 jrmu $pagename = str_replace('/', '.', $pagename);
1517 5127fd58 2021-12-17 jrmu if ($dfmt == 'wiki.d/{$FullName}') # optimizations for
1518 5127fd58 2021-12-17 jrmu return $this->PFE("wiki.d/$pagename"); # standard locations
1519 5127fd58 2021-12-17 jrmu if ($dfmt == '$FarmD/wikilib.d/{$FullName}') #
1520 5127fd58 2021-12-17 jrmu return $this->PFE("$FarmD/wikilib.d/$pagename");
1521 5127fd58 2021-12-17 jrmu if ($dfmt == 'wiki.d/{$Group}/{$FullName}')
1522 5127fd58 2021-12-17 jrmu return $this->PFE(preg_replace('/([^.]+).*/', 'wiki.d/$1/$0', $pagename));
1523 5127fd58 2021-12-17 jrmu }
1524 5127fd58 2021-12-17 jrmu return $this->PFE(FmtPageName($dfmt, $pagename));
1525 5127fd58 2021-12-17 jrmu }
1526 5127fd58 2021-12-17 jrmu function PFE($f) { # pagefile_encode
1527 5127fd58 2021-12-17 jrmu if (!$this->encodefilenames) return $f;
1528 5127fd58 2021-12-17 jrmu global $PageFileEncodeFunction;
1529 5127fd58 2021-12-17 jrmu return $PageFileEncodeFunction($f);
1530 5127fd58 2021-12-17 jrmu }
1531 5127fd58 2021-12-17 jrmu function PFD($f) { # pagefile_decode
1532 5127fd58 2021-12-17 jrmu if (!$this->encodefilenames) return $f;
1533 5127fd58 2021-12-17 jrmu global $PageFileDecodeFunction;
1534 5127fd58 2021-12-17 jrmu return $PageFileDecodeFunction($f);
1535 5127fd58 2021-12-17 jrmu }
1536 5127fd58 2021-12-17 jrmu function read($pagename, $since=0) {
1537 5127fd58 2021-12-17 jrmu $newline = '';
1538 5127fd58 2021-12-17 jrmu $urlencoded = false;
1539 5127fd58 2021-12-17 jrmu $pagefile = $this->pagefile($pagename);
1540 5127fd58 2021-12-17 jrmu if ($pagefile && ($fp=@fopen($pagefile, "r"))) {
1541 5127fd58 2021-12-17 jrmu $page = $this->attr;
1542 5127fd58 2021-12-17 jrmu while (!feof($fp)) {
1543 5127fd58 2021-12-17 jrmu $line = @fgets($fp, 4096);
1544 5127fd58 2021-12-17 jrmu while (substr($line, -1, 1) != "\n" && !feof($fp))
1545 5127fd58 2021-12-17 jrmu { $line .= fgets($fp, 4096); }
1546 5127fd58 2021-12-17 jrmu $line = rtrim($line);
1547 5127fd58 2021-12-17 jrmu if ($urlencoded) $line = urldecode(str_replace('+', '%2b', $line));
1548 5127fd58 2021-12-17 jrmu @list($k,$v) = explode('=', $line, 2);
1549 5127fd58 2021-12-17 jrmu if (!$k) continue;
1550 5127fd58 2021-12-17 jrmu if ($k == 'version') {
1551 5127fd58 2021-12-17 jrmu $ordered = (strpos($v, 'ordered=1') !== false);
1552 5127fd58 2021-12-17 jrmu $urlencoded = (strpos($v, 'urlencoded=1') !== false);
1553 5127fd58 2021-12-17 jrmu if (strpos($v, 'pmwiki-0.')!==false) $newline="\262";
1554 5127fd58 2021-12-17 jrmu }
1555 5127fd58 2021-12-17 jrmu if ($k == 'newline') { $newline = $v; continue; }
1556 5127fd58 2021-12-17 jrmu if ($since > 0 && preg_match('/:(\\d+)/', $k, $m) && $m[1] < $since) {
1557 fc91d0f1 2023-03-07 jrmu if (@$ordered) break;
1558 5127fd58 2021-12-17 jrmu continue;
1559 5127fd58 2021-12-17 jrmu }
1560 5127fd58 2021-12-17 jrmu if ($newline) $v = str_replace($newline, "\n", $v);
1561 5127fd58 2021-12-17 jrmu $page[$k] = $v;
1562 5127fd58 2021-12-17 jrmu }
1563 5127fd58 2021-12-17 jrmu fclose($fp);
1564 5127fd58 2021-12-17 jrmu }
1565 5127fd58 2021-12-17 jrmu return $this->recode($pagename, @$page);
1566 5127fd58 2021-12-17 jrmu }
1567 5127fd58 2021-12-17 jrmu function write($pagename,$page) {
1568 5127fd58 2021-12-17 jrmu global $Now, $Version, $Charset, $EnableRevUserAgent, $PageExistsCache, $DenyHtaccessContent;
1569 5127fd58 2021-12-17 jrmu $page['charset'] = $Charset;
1570 5127fd58 2021-12-17 jrmu $page['name'] = $pagename;
1571 5127fd58 2021-12-17 jrmu $page['time'] = $Now;
1572 fc91d0f1 2023-03-07 jrmu $page['host'] = strval(@$_SERVER['REMOTE_ADDR']);
1573 fc91d0f1 2023-03-07 jrmu $page['agent'] = strval(@$_SERVER['HTTP_USER_AGENT']);
1574 fc91d0f1 2023-03-07 jrmu if (IsEnabled($EnableRevUserAgent, 0)) $page["agent:$Now"] = $page['agent'];
1575 fc91d0f1 2023-03-07 jrmu $page['rev'] = intval(@$page['rev'])+1;
1576 5127fd58 2021-12-17 jrmu unset($page['version']); unset($page['newline']);
1577 5127fd58 2021-12-17 jrmu uksort($page, 'CmpPageAttr');
1578 5127fd58 2021-12-17 jrmu $s = false;
1579 5127fd58 2021-12-17 jrmu $pagefile = $this->pagefile($pagename);
1580 5127fd58 2021-12-17 jrmu $dir = dirname($pagefile); mkdirp($dir);
1581 5127fd58 2021-12-17 jrmu if (!file_exists("$dir/.htaccess") && $fp = @fopen("$dir/.htaccess", "w"))
1582 5127fd58 2021-12-17 jrmu { fwrite($fp, $DenyHtaccessContent); fclose($fp); }
1583 5127fd58 2021-12-17 jrmu if ($pagefile && ($fp=fopen("$pagefile,new","w"))) {
1584 5127fd58 2021-12-17 jrmu $r0 = array('%', "\n", '<');
1585 5127fd58 2021-12-17 jrmu $r1 = array('%25', '%0a', '%3c');
1586 5127fd58 2021-12-17 jrmu $x = "version=$Version ordered=1 urlencoded=1\n";
1587 5127fd58 2021-12-17 jrmu $s = true && fputs($fp, $x); $sz = strlen($x);
1588 5127fd58 2021-12-17 jrmu foreach($page as $k=>$v)
1589 5127fd58 2021-12-17 jrmu if ($k > '' && $k[0] != '=') {
1590 5127fd58 2021-12-17 jrmu $x = str_replace($r0, $r1, "$k=$v") . "\n";
1591 5127fd58 2021-12-17 jrmu $s = $s && fputs($fp, $x); $sz += strlen($x);
1592 5127fd58 2021-12-17 jrmu }
1593 5127fd58 2021-12-17 jrmu $s = fclose($fp) && $s;
1594 5127fd58 2021-12-17 jrmu $s = $s && (filesize("$pagefile,new") > $sz * 0.95);
1595 5127fd58 2021-12-17 jrmu if (file_exists($pagefile)) $s = $s && unlink($pagefile);
1596 5127fd58 2021-12-17 jrmu $s = $s && rename("$pagefile,new", $pagefile);
1597 5127fd58 2021-12-17 jrmu }
1598 5127fd58 2021-12-17 jrmu $s && fixperms($pagefile);
1599 5127fd58 2021-12-17 jrmu if (!$s)
1600 5127fd58 2021-12-17 jrmu Abort("Cannot write page to $pagename ($pagefile)...changes not saved");
1601 5127fd58 2021-12-17 jrmu PCache($pagename, $page);
1602 5127fd58 2021-12-17 jrmu unset($PageExistsCache[$pagename]); # PITS:01401
1603 5127fd58 2021-12-17 jrmu }
1604 5127fd58 2021-12-17 jrmu function exists($pagename) {
1605 5127fd58 2021-12-17 jrmu if (!$pagename) return false;
1606 5127fd58 2021-12-17 jrmu $pagefile = $this->pagefile($pagename);
1607 5127fd58 2021-12-17 jrmu return ($pagefile && file_exists($pagefile));
1608 5127fd58 2021-12-17 jrmu }
1609 5127fd58 2021-12-17 jrmu function delete($pagename) {
1610 5127fd58 2021-12-17 jrmu global $Now, $PageExistsCache;
1611 5127fd58 2021-12-17 jrmu $pagefile = $this->pagefile($pagename);
1612 5127fd58 2021-12-17 jrmu @rename($pagefile,"$pagefile,del-$Now");
1613 5127fd58 2021-12-17 jrmu unset($PageExistsCache[$pagename]); # PITS:01401
1614 5127fd58 2021-12-17 jrmu }
1615 5127fd58 2021-12-17 jrmu function ls($pats=NULL) {
1616 5127fd58 2021-12-17 jrmu global $GroupPattern, $NamePattern;
1617 5127fd58 2021-12-17 jrmu StopWatch("PageStore::ls begin {$this->dirfmt}");
1618 5127fd58 2021-12-17 jrmu $pats=(array)$pats;
1619 5127fd58 2021-12-17 jrmu array_push($pats, "/^$GroupPattern\.$NamePattern$/");
1620 5127fd58 2021-12-17 jrmu $dir = $this->pagefile('$Group.$Name');
1621 5127fd58 2021-12-17 jrmu $maxslash = substr_count($dir, '/');
1622 5127fd58 2021-12-17 jrmu $dirlist = array(preg_replace('!/*[^/]*\\$.*$!','',$dir));
1623 5127fd58 2021-12-17 jrmu $out = array();
1624 5127fd58 2021-12-17 jrmu while (count($dirlist)>0) {
1625 5127fd58 2021-12-17 jrmu $dir = array_shift($dirlist);
1626 5127fd58 2021-12-17 jrmu $dfp = @opendir($dir); if (!$dfp) { continue; }
1627 5127fd58 2021-12-17 jrmu $dirslash = substr_count($dir, '/') + 1;
1628 5127fd58 2021-12-17 jrmu $o = array();
1629 5127fd58 2021-12-17 jrmu while ( ($pagefile = readdir($dfp)) !== false) {
1630 5127fd58 2021-12-17 jrmu if ($pagefile[0] == '.') continue;
1631 5127fd58 2021-12-17 jrmu if ($dirslash < $maxslash && is_dir("$dir/$pagefile"))
1632 5127fd58 2021-12-17 jrmu { array_push($dirlist,"$dir/$pagefile"); continue; }
1633 5127fd58 2021-12-17 jrmu if ($dirslash == $maxslash) $o[] = $this->PFD($pagefile);
1634 5127fd58 2021-12-17 jrmu }
1635 5127fd58 2021-12-17 jrmu closedir($dfp);
1636 5127fd58 2021-12-17 jrmu StopWatch("PageStore::ls merge {$this->dirfmt}");
1637 5127fd58 2021-12-17 jrmu $out = array_merge($out, MatchPageNames($o, $pats));
1638 5127fd58 2021-12-17 jrmu }
1639 5127fd58 2021-12-17 jrmu StopWatch("PageStore::ls end {$this->dirfmt}");
1640 5127fd58 2021-12-17 jrmu return $out;
1641 5127fd58 2021-12-17 jrmu }
1642 5127fd58 2021-12-17 jrmu function recode($pagename, $a) {
1643 5127fd58 2021-12-17 jrmu if (!$a) return false;
1644 5127fd58 2021-12-17 jrmu global $Charset, $PageRecodeFunction, $DefaultPageCharset, $EnableOldCharset;
1645 fc91d0f1 2023-03-07 jrmu if (@$PageRecodeFunction && function_exists($PageRecodeFunction))
1646 fc91d0f1 2023-03-07 jrmu return $PageRecodeFunction($a);
1647 5127fd58 2021-12-17 jrmu if (IsEnabled($EnableOldCharset)) $a['=oldcharset'] = @$a['charset'];
1648 5127fd58 2021-12-17 jrmu SDVA($DefaultPageCharset, array(''=>@$Charset)); # pre-2.2.31 RecentChanges
1649 5127fd58 2021-12-17 jrmu if (@$DefaultPageCharset[$a['charset']]>'') # wrong pre-2.2.30 encs. *-2, *-9, *-13
1650 5127fd58 2021-12-17 jrmu $a['charset'] = $DefaultPageCharset[@$a['charset']];
1651 5127fd58 2021-12-17 jrmu if (!$a['charset'] || $Charset==$a['charset']) return $a;
1652 5127fd58 2021-12-17 jrmu $from = ($a['charset']=='ISO-8859-1') ? 'WINDOWS-1252' : $a['charset'];
1653 5127fd58 2021-12-17 jrmu $to = ($Charset=='ISO-8859-1') ? 'WINDOWS-1252' : $Charset;
1654 fc91d0f1 2023-03-07 jrmu if ($from != $to) {
1655 5127fd58 2021-12-17 jrmu foreach($a as $k=>$v) $a[$k] = $this->recodefn($v,$from,$to);
1656 5127fd58 2021-12-17 jrmu }
1657 5127fd58 2021-12-17 jrmu $a['charset'] = $Charset;
1658 5127fd58 2021-12-17 jrmu return $a;
1659 5127fd58 2021-12-17 jrmu }
1660 5127fd58 2021-12-17 jrmu }
1661 5127fd58 2021-12-17 jrmu
1662 5127fd58 2021-12-17 jrmu function ReadPage($pagename, $since=0) {
1663 5127fd58 2021-12-17 jrmu # read a page from the appropriate directories given by $WikiReadDirsFmt.
1664 5127fd58 2021-12-17 jrmu global $WikiLibDirs,$Now;
1665 5127fd58 2021-12-17 jrmu foreach ($WikiLibDirs as $dir) {
1666 5127fd58 2021-12-17 jrmu $page = $dir->read($pagename, $since);
1667 5127fd58 2021-12-17 jrmu if ($page) break;
1668 5127fd58 2021-12-17 jrmu }
1669 fc91d0f1 2023-03-07 jrmu if (@!$page) $page = array('ctime' => $Now);
1670 5127fd58 2021-12-17 jrmu if (@!$page['time']) $page['time'] = $Now;
1671 5127fd58 2021-12-17 jrmu return $page;
1672 5127fd58 2021-12-17 jrmu }
1673 5127fd58 2021-12-17 jrmu
1674 5127fd58 2021-12-17 jrmu function WritePage($pagename,$page) {
1675 5127fd58 2021-12-17 jrmu global $WikiLibDirs,$WikiDir,$LastModFile;
1676 5127fd58 2021-12-17 jrmu $WikiDir->iswrite = 1;
1677 5127fd58 2021-12-17 jrmu for($i=0; $i<count($WikiLibDirs); $i++) {
1678 5127fd58 2021-12-17 jrmu $wd = &$WikiLibDirs[$i];
1679 5127fd58 2021-12-17 jrmu if ($wd->iswrite && $wd->exists($pagename)) break;
1680 5127fd58 2021-12-17 jrmu }
1681 5127fd58 2021-12-17 jrmu if ($i >= count($WikiLibDirs)) $wd = &$WikiDir;
1682 5127fd58 2021-12-17 jrmu $wd->write($pagename,$page);
1683 5127fd58 2021-12-17 jrmu if ($LastModFile && !@touch($LastModFile))
1684 5127fd58 2021-12-17 jrmu { unlink($LastModFile); touch($LastModFile); fixperms($LastModFile); }
1685 5127fd58 2021-12-17 jrmu }
1686 5127fd58 2021-12-17 jrmu
1687 5127fd58 2021-12-17 jrmu function PageExists($pagename) {
1688 5127fd58 2021-12-17 jrmu ## note: $PageExistsCache might change or disappear someday
1689 5127fd58 2021-12-17 jrmu global $WikiLibDirs, $PageExistsCache;
1690 5127fd58 2021-12-17 jrmu if (!isset($PageExistsCache[$pagename])) {
1691 5127fd58 2021-12-17 jrmu foreach((array)$WikiLibDirs as $dir)
1692 5127fd58 2021-12-17 jrmu if ($PageExistsCache[$pagename] = $dir->exists($pagename)) break;
1693 5127fd58 2021-12-17 jrmu }
1694 5127fd58 2021-12-17 jrmu return $PageExistsCache[$pagename];
1695 5127fd58 2021-12-17 jrmu }
1696 5127fd58 2021-12-17 jrmu
1697 5127fd58 2021-12-17 jrmu function ListPages($pat=NULL) {
1698 5127fd58 2021-12-17 jrmu global $WikiLibDirs;
1699 5127fd58 2021-12-17 jrmu foreach((array)$WikiLibDirs as $dir)
1700 5127fd58 2021-12-17 jrmu $out = array_unique(array_merge($dir->ls($pat),(array)@$out));
1701 5127fd58 2021-12-17 jrmu return $out;
1702 5127fd58 2021-12-17 jrmu }
1703 5127fd58 2021-12-17 jrmu
1704 5127fd58 2021-12-17 jrmu function RetrieveAuthPage($pagename, $level, $authprompt=true, $since=0) {
1705 5127fd58 2021-12-17 jrmu global $AuthFunction;
1706 5127fd58 2021-12-17 jrmu SDV($AuthFunction,'PmWikiAuth');
1707 5127fd58 2021-12-17 jrmu if (!function_exists($AuthFunction)) return ReadPage($pagename, $since);
1708 5127fd58 2021-12-17 jrmu return $AuthFunction($pagename, $level, $authprompt, $since);
1709 5127fd58 2021-12-17 jrmu }
1710 5127fd58 2021-12-17 jrmu
1711 5127fd58 2021-12-17 jrmu function Abort($msg, $info='') {
1712 5127fd58 2021-12-17 jrmu # exit pmwiki with an abort message
1713 5127fd58 2021-12-17 jrmu global $ScriptUrl, $Charset, $AbortFunction;
1714 5127fd58 2021-12-17 jrmu if (@$AbortFunction) return $AbortFunction($msg, $info);
1715 5127fd58 2021-12-17 jrmu if ($info)
1716 5127fd58 2021-12-17 jrmu $info = "<p class='vspace'><a target='_blank' rel='nofollow' href='http://www.pmwiki.org/pmwiki/info/$info'>$[More information]</a></p>";
1717 5127fd58 2021-12-17 jrmu $msg = "<h3>$[PmWiki can't process your request]</h3>
1718 5127fd58 2021-12-17 jrmu <p class='vspace'>$msg</p>
1719 5127fd58 2021-12-17 jrmu <p class='vspace'>$[We are sorry for any inconvenience].</p>
1720 5127fd58 2021-12-17 jrmu $info
1721 5127fd58 2021-12-17 jrmu <p class='vspace'><a href='$ScriptUrl'>$[Return to] $ScriptUrl</a></p>";
1722 5127fd58 2021-12-17 jrmu @header("Content-type: text/html; charset=$Charset");
1723 5127fd58 2021-12-17 jrmu echo preg_replace_callback('/\\$\\[([^\\]]+)\\]/', "cb_expandxlang", $msg);
1724 5127fd58 2021-12-17 jrmu exit;
1725 5127fd58 2021-12-17 jrmu }
1726 5127fd58 2021-12-17 jrmu
1727 5127fd58 2021-12-17 jrmu function Redirect($pagename, $urlfmt='$PageUrl', $redirecturl=null) {
1728 5127fd58 2021-12-17 jrmu # redirect the browser to $pagename
1729 5127fd58 2021-12-17 jrmu global $EnableRedirect, $RedirectDelay, $EnableStopWatch;
1730 5127fd58 2021-12-17 jrmu SDV($RedirectDelay, 0);
1731 5127fd58 2021-12-17 jrmu clearstatcache();
1732 5127fd58 2021-12-17 jrmu if (is_null($redirecturl)) $redirecturl = FmtPageName($urlfmt,$pagename);
1733 5127fd58 2021-12-17 jrmu if (IsEnabled($EnableRedirect,1) &&
1734 5127fd58 2021-12-17 jrmu (!isset($_REQUEST['redirect']) || $_REQUEST['redirect'])) {
1735 5127fd58 2021-12-17 jrmu header("Location: $redirecturl");
1736 5127fd58 2021-12-17 jrmu header("Content-type: text/html");
1737 5127fd58 2021-12-17 jrmu echo "<html><head>
1738 5127fd58 2021-12-17 jrmu <meta http-equiv='Refresh' Content='$RedirectDelay; URL=$redirecturl' />
1739 5127fd58 2021-12-17 jrmu <title>Redirect</title></head><body></body></html>";
1740 5127fd58 2021-12-17 jrmu exit;
1741 5127fd58 2021-12-17 jrmu }
1742 5127fd58 2021-12-17 jrmu echo "<a href='$redirecturl'>Redirect to $redirecturl</a>";
1743 5127fd58 2021-12-17 jrmu if (@$EnableStopWatch && function_exists('StopWatchHTML'))
1744 5127fd58 2021-12-17 jrmu StopWatchHTML($pagename, 1);
1745 5127fd58 2021-12-17 jrmu exit;
1746 5127fd58 2021-12-17 jrmu }
1747 5127fd58 2021-12-17 jrmu
1748 5127fd58 2021-12-17 jrmu function PrintFmt($pagename,$fmt) {
1749 5127fd58 2021-12-17 jrmu global $HTTPHeaders,$FmtV;
1750 fc91d0f1 2023-03-07 jrmu if (is_array($fmt)) {
1751 fc91d0f1 2023-03-07 jrmu foreach($fmt as $f) PrintFmt($pagename,$f);
1752 fc91d0f1 2023-03-07 jrmu return;
1753 fc91d0f1 2023-03-07 jrmu }
1754 5127fd58 2021-12-17 jrmu if ($fmt == 'headers:') {
1755 5127fd58 2021-12-17 jrmu foreach($HTTPHeaders as $h) (@$sent++) ? @header($h) : header($h);
1756 5127fd58 2021-12-17 jrmu return;
1757 5127fd58 2021-12-17 jrmu }
1758 fc91d0f1 2023-03-07 jrmu $fmt = strval($fmt);
1759 5127fd58 2021-12-17 jrmu $x = FmtPageName($fmt,$pagename);
1760 5127fd58 2021-12-17 jrmu if (strncmp($fmt, 'function:', 9) == 0 &&
1761 5127fd58 2021-12-17 jrmu preg_match('/^function:(\S+)\s*(.*)$/s', $x, $match) &&
1762 5127fd58 2021-12-17 jrmu function_exists($match[1]))
1763 5127fd58 2021-12-17 jrmu { $match[1]($pagename,$match[2]); return; }
1764 5127fd58 2021-12-17 jrmu if (strncmp($fmt, 'file:', 5) == 0 && preg_match("/^file:(.+)/s",$x,$match)) {
1765 5127fd58 2021-12-17 jrmu $filelist = preg_split('/[\\s]+/',$match[1],-1,PREG_SPLIT_NO_EMPTY);
1766 5127fd58 2021-12-17 jrmu foreach($filelist as $f) {
1767 5127fd58 2021-12-17 jrmu if (file_exists($f)) { include($f); return; }
1768 5127fd58 2021-12-17 jrmu }
1769 5127fd58 2021-12-17 jrmu return;
1770 5127fd58 2021-12-17 jrmu }
1771 5127fd58 2021-12-17 jrmu if (substr($x, 0, 7) == 'markup:')
1772 5127fd58 2021-12-17 jrmu { print MarkupToHTML($pagename, substr($x, 7)); return; }
1773 5127fd58 2021-12-17 jrmu if (substr($x, 0, 5) == 'wiki:')
1774 5127fd58 2021-12-17 jrmu { PrintWikiPage($pagename, substr($x, 5), 'read'); return; }
1775 5127fd58 2021-12-17 jrmu if (substr($x, 0, 5) == 'page:')
1776 5127fd58 2021-12-17 jrmu { PrintWikiPage($pagename, substr($x, 5), ''); return; }
1777 5127fd58 2021-12-17 jrmu echo $x;
1778 5127fd58 2021-12-17 jrmu }
1779 5127fd58 2021-12-17 jrmu
1780 fc91d0f1 2023-03-07 jrmu function PrintWikiPage($pagename, $wikilist=NULL, $auth='read', $return=false) {
1781 5127fd58 2021-12-17 jrmu if (is_null($wikilist)) $wikilist=$pagename;
1782 5127fd58 2021-12-17 jrmu $pagelist = preg_split('/\s+/',$wikilist,-1,PREG_SPLIT_NO_EMPTY);
1783 5127fd58 2021-12-17 jrmu foreach($pagelist as $p) {
1784 5127fd58 2021-12-17 jrmu if (PageExists($p)) {
1785 5127fd58 2021-12-17 jrmu $page = ($auth) ? RetrieveAuthPage($p, $auth, false, READPAGE_CURRENT)
1786 5127fd58 2021-12-17 jrmu : ReadPage($p, READPAGE_CURRENT);
1787 fc91d0f1 2023-03-07 jrmu if (@$page['text']) {
1788 fc91d0f1 2023-03-07 jrmu $html = MarkupToHTML($pagename,Qualify($p, $page['text']));
1789 fc91d0f1 2023-03-07 jrmu if ($return) return $html;
1790 fc91d0f1 2023-03-07 jrmu echo $html;
1791 fc91d0f1 2023-03-07 jrmu }
1792 fc91d0f1 2023-03-07 jrmu return '';
1793 5127fd58 2021-12-17 jrmu }
1794 5127fd58 2021-12-17 jrmu }
1795 fc91d0f1 2023-03-07 jrmu return '';
1796 5127fd58 2021-12-17 jrmu }
1797 5127fd58 2021-12-17 jrmu
1798 5127fd58 2021-12-17 jrmu function Keep($x, $pool=NULL) {
1799 fc91d0f1 2023-03-07 jrmu if (is_array($x)) $x = $x[0]; # used in many callbacks
1800 5127fd58 2021-12-17 jrmu # Keep preserves a string from being processed by wiki markups
1801 5127fd58 2021-12-17 jrmu global $BlockPattern, $KeepToken, $KPV, $KPCount;
1802 5127fd58 2021-12-17 jrmu $x = preg_replace_callback("/$KeepToken(\\d.*?)$KeepToken/", 'cb_expandkpv', $x);
1803 5127fd58 2021-12-17 jrmu if (is_null($pool) && preg_match("!</?($BlockPattern)\\b!", $x)) $pool = 'B';
1804 5127fd58 2021-12-17 jrmu $KPCount++; $KPV[$KPCount.$pool]=$x;
1805 5127fd58 2021-12-17 jrmu return $KeepToken.$KPCount.$pool.$KeepToken;
1806 5127fd58 2021-12-17 jrmu }
1807 5127fd58 2021-12-17 jrmu
1808 fc91d0f1 2023-03-07 jrmu function KeepBlock($x, $pool=NULL) {
1809 fc91d0f1 2023-03-07 jrmu return '<:block>' . Keep($x, $pool);
1810 fc91d0f1 2023-03-07 jrmu }
1811 5127fd58 2021-12-17 jrmu
1812 5127fd58 2021-12-17 jrmu ## MarkupEscape examines markup source and escapes any [@...@]
1813 5127fd58 2021-12-17 jrmu ## and [=...=] sequences using Keep(). MarkupRestore undoes the
1814 5127fd58 2021-12-17 jrmu ## effect of any MarkupEscape().
1815 5127fd58 2021-12-17 jrmu function MarkupEscape($text) {
1816 5127fd58 2021-12-17 jrmu global $EscapePattern;
1817 5127fd58 2021-12-17 jrmu SDV($EscapePattern, '\\[([=@]).*?\\1\\]');
1818 fc91d0f1 2023-03-07 jrmu return preg_replace_callback("/$EscapePattern/s", "Keep", strval($text));
1819 5127fd58 2021-12-17 jrmu }
1820 5127fd58 2021-12-17 jrmu function MarkupRestore($text) {
1821 5127fd58 2021-12-17 jrmu global $KeepToken, $KPV;
1822 fc91d0f1 2023-03-07 jrmu if (is_null($text)) return '';
1823 fc91d0f1 2023-03-07 jrmu if (!$text) return $text;
1824 5127fd58 2021-12-17 jrmu return preg_replace_callback("/$KeepToken(\\d.*?)$KeepToken/", 'cb_expandkpv', $text);
1825 5127fd58 2021-12-17 jrmu }
1826 5127fd58 2021-12-17 jrmu
1827 5127fd58 2021-12-17 jrmu
1828 5127fd58 2021-12-17 jrmu ## Qualify() applies $QualifyPatterns to convert relative links
1829 5127fd58 2021-12-17 jrmu ## and references into absolute equivalents.
1830 5127fd58 2021-12-17 jrmu function Qualify($pagename, $text) {
1831 5127fd58 2021-12-17 jrmu global $QualifyPatterns, $KeepToken, $KPV, $tmp_qualify;
1832 5127fd58 2021-12-17 jrmu if (!@$QualifyPatterns) return $text;
1833 5127fd58 2021-12-17 jrmu $text = MarkupEscape($text);
1834 5127fd58 2021-12-17 jrmu $group = $tmp_qualify['group'] = PageVar($pagename, '$Group');
1835 5127fd58 2021-12-17 jrmu $name = $tmp_qualify['name'] = PageVar($pagename, '$Name');
1836 5127fd58 2021-12-17 jrmu $tmp_qualify['pagename'] = $pagename;
1837 5127fd58 2021-12-17 jrmu $text = PPRA((array)$QualifyPatterns, $text);
1838 5127fd58 2021-12-17 jrmu return MarkupRestore($text);
1839 5127fd58 2021-12-17 jrmu }
1840 5127fd58 2021-12-17 jrmu
1841 5127fd58 2021-12-17 jrmu
1842 5127fd58 2021-12-17 jrmu function CondText($pagename,$condspec,$condtext) {
1843 5127fd58 2021-12-17 jrmu global $Conditions;
1844 5127fd58 2021-12-17 jrmu if (!preg_match("/^(\\S+)\\s*(!?)\\s*(\\S+)?\\s*(.*?)\\s*$/",
1845 5127fd58 2021-12-17 jrmu $condspec,$match)) return '';
1846 5127fd58 2021-12-17 jrmu @list($condstr,$condtype,$not,$condname,$condparm) = $match;
1847 5127fd58 2021-12-17 jrmu if (isset($Conditions[$condname])) {
1848 5127fd58 2021-12-17 jrmu $tf = @eval("return (".$Conditions[$condname].");");
1849 5127fd58 2021-12-17 jrmu if (!$tf xor $not) $condtext='';
1850 5127fd58 2021-12-17 jrmu }
1851 5127fd58 2021-12-17 jrmu return $condtext;
1852 5127fd58 2021-12-17 jrmu }
1853 5127fd58 2021-12-17 jrmu
1854 5127fd58 2021-12-17 jrmu
1855 5127fd58 2021-12-17 jrmu ## TextSection extracts a section of text delimited by page anchors.
1856 5127fd58 2021-12-17 jrmu ## The $sections parameter can have the form
1857 5127fd58 2021-12-17 jrmu ## #abc - [[#abc]] to next anchor
1858 5127fd58 2021-12-17 jrmu ## #abc#def - [[#abc]] up to [[#def]]
1859 5127fd58 2021-12-17 jrmu ## #abc#, #abc.. - [[#abc]] to end of text
1860 5127fd58 2021-12-17 jrmu ## ##abc, #..#abc - beginning of text to [[#abc]]
1861 5127fd58 2021-12-17 jrmu ## Returns the text unchanged if no sections are requested,
1862 5127fd58 2021-12-17 jrmu ## or false if a requested beginning anchor isn't in the text.
1863 5127fd58 2021-12-17 jrmu function TextSection($text, $sections, $args = NULL) {
1864 fc91d0f1 2023-03-07 jrmu if (!$text) return false; # PHP 8.1
1865 5127fd58 2021-12-17 jrmu $args = (array)$args;
1866 5127fd58 2021-12-17 jrmu $npat = '[[:alpha:]][-\\w.]*';
1867 5127fd58 2021-12-17 jrmu if (!preg_match("/#($npat)?(\\.\\.)?(#($npat)?)?/", $sections, $match))
1868 5127fd58 2021-12-17 jrmu return $text;
1869 5127fd58 2021-12-17 jrmu @list($x, $aa, $dots, $b, $bb) = $match;
1870 5127fd58 2021-12-17 jrmu if (!$dots && !$b) $bb = $npat;
1871 5127fd58 2021-12-17 jrmu if ($aa) {
1872 5127fd58 2021-12-17 jrmu $aa = preg_replace('/\\.\\.$/', '', $aa);
1873 5127fd58 2021-12-17 jrmu $pos = strpos($text, "[[#$aa]]"); if ($pos === false) return false;
1874 5127fd58 2021-12-17 jrmu if (@$args['anchors'])
1875 5127fd58 2021-12-17 jrmu while ($pos > 0 && $text[$pos-1] != "\n") $pos--;
1876 5127fd58 2021-12-17 jrmu else $pos += strlen("[[#$aa]]");
1877 5127fd58 2021-12-17 jrmu $text = substr($text, $pos);
1878 5127fd58 2021-12-17 jrmu }
1879 5127fd58 2021-12-17 jrmu if ($bb)
1880 5127fd58 2021-12-17 jrmu $text = preg_replace("/(\n)[^\n]*\\[\\[#$bb\\]\\].*$/s", '$1', $text, 1);
1881 5127fd58 2021-12-17 jrmu return $text;
1882 5127fd58 2021-12-17 jrmu }
1883 5127fd58 2021-12-17 jrmu
1884 5127fd58 2021-12-17 jrmu
1885 5127fd58 2021-12-17 jrmu ## RetrieveAuthSection extracts a section of text from a page.
1886 5127fd58 2021-12-17 jrmu ## If $pagesection starts with anything other than '#', it identifies
1887 5127fd58 2021-12-17 jrmu ## the page to extract text from. Otherwise RetrieveAuthSection looks
1888 5127fd58 2021-12-17 jrmu ## in the pages given by $list, or in $pagename if $list is not specified.
1889 5127fd58 2021-12-17 jrmu ## The selected page is placed in the global $RASPageName variable.
1890 5127fd58 2021-12-17 jrmu ## The caller is responsible for calling Qualify() as needed.
1891 5127fd58 2021-12-17 jrmu function RetrieveAuthSection($pagename, $pagesection, $list=NULL, $auth='read') {
1892 5127fd58 2021-12-17 jrmu global $RASPageName, $PCache;
1893 5127fd58 2021-12-17 jrmu if ($pagesection[0] != '#')
1894 5127fd58 2021-12-17 jrmu $list = array(MakePageName($pagename, $pagesection));
1895 fc91d0f1 2023-03-07 jrmu elseif (is_null($list)) $list = array($pagename);
1896 5127fd58 2021-12-17 jrmu foreach((array)$list as $t) {
1897 5127fd58 2021-12-17 jrmu $t = FmtPageName($t, $pagename);
1898 5127fd58 2021-12-17 jrmu if (!PageExists($t)) continue;
1899 5127fd58 2021-12-17 jrmu $tpage = RetrieveAuthPage($t, $auth, false, READPAGE_CURRENT);
1900 5127fd58 2021-12-17 jrmu if (!$tpage) continue;
1901 fc91d0f1 2023-03-07 jrmu $text = TextSection(IsEnabled($PCache[$t]['=preview'],strval(@$tpage['text'])),$pagesection);
1902 5127fd58 2021-12-17 jrmu if ($text !== false) { $RASPageName = $t; return $text; }
1903 5127fd58 2021-12-17 jrmu }
1904 5127fd58 2021-12-17 jrmu $RASPageName = '';
1905 5127fd58 2021-12-17 jrmu return false;
1906 5127fd58 2021-12-17 jrmu }
1907 5127fd58 2021-12-17 jrmu
1908 5127fd58 2021-12-17 jrmu function IncludeText($pagename, $inclspec) {
1909 fc91d0f1 2023-03-07 jrmu global $MaxIncludes, $IncludeOpt, $InclCount, $PCache, $IncludedPages;
1910 5127fd58 2021-12-17 jrmu SDV($MaxIncludes,50);
1911 5127fd58 2021-12-17 jrmu SDVA($IncludeOpt, array('self'=>1));
1912 5127fd58 2021-12-17 jrmu if (@$InclCount[$pagename]++>=$MaxIncludes) return Keep($inclspec);
1913 5127fd58 2021-12-17 jrmu $args = array_merge($IncludeOpt, ParseArgs($inclspec));
1914 5127fd58 2021-12-17 jrmu while (count($args['#'])>0) {
1915 5127fd58 2021-12-17 jrmu $k = array_shift($args['#']); $v = array_shift($args['#']);
1916 5127fd58 2021-12-17 jrmu if ($k=='') {
1917 5127fd58 2021-12-17 jrmu if ($v[0] != '#') {
1918 5127fd58 2021-12-17 jrmu if (isset($itext)) continue;
1919 5127fd58 2021-12-17 jrmu $iname = MakePageName($pagename, $v);
1920 5127fd58 2021-12-17 jrmu if (!$args['self'] && $iname == $pagename) continue;
1921 5127fd58 2021-12-17 jrmu $ipage = RetrieveAuthPage($iname, 'read', false, READPAGE_CURRENT);
1922 fc91d0f1 2023-03-07 jrmu if (isset($PCache[$iname]['=preview'])) $itext = $PCache[$iname]['=preview'];
1923 fc91d0f1 2023-03-07 jrmu elseif (isset($ipage['text'])) $itext = $ipage['text'];
1924 5127fd58 2021-12-17 jrmu }
1925 fc91d0f1 2023-03-07 jrmu if (isset($itext))
1926 fc91d0f1 2023-03-07 jrmu $itext = TextSection($itext, $v, array('anchors' => 1));
1927 5127fd58 2021-12-17 jrmu continue;
1928 5127fd58 2021-12-17 jrmu }
1929 fc91d0f1 2023-03-07 jrmu $itext = strval(@$itext);
1930 5127fd58 2021-12-17 jrmu if (preg_match('/^(?:line|para)s?$/', $k)) {
1931 5127fd58 2021-12-17 jrmu preg_match('/^(\\d*)(\\.\\.(\\d*))?$/', $v, $match);
1932 5127fd58 2021-12-17 jrmu @list($x, $a, $dots, $b) = $match;
1933 5127fd58 2021-12-17 jrmu $upat = ($k[0] == 'p') ? ".*?(\n\\s*\n|$)" : "[^\n]*(?:\n|$)";
1934 5127fd58 2021-12-17 jrmu if (!$dots) { $b=$a; $a=0; }
1935 5127fd58 2021-12-17 jrmu if ($a>0) $a--;
1936 5127fd58 2021-12-17 jrmu $itext=preg_replace("/^(($upat){0,$b}).*$/s",'$1',$itext,1);
1937 5127fd58 2021-12-17 jrmu $itext=preg_replace("/^($upat){0,$a}/s",'',$itext,1);
1938 5127fd58 2021-12-17 jrmu continue;
1939 5127fd58 2021-12-17 jrmu }
1940 5127fd58 2021-12-17 jrmu }
1941 5127fd58 2021-12-17 jrmu $basepage = isset($args['basepage'])
1942 5127fd58 2021-12-17 jrmu ? MakePageName($pagename, $args['basepage'])
1943 5127fd58 2021-12-17 jrmu : @$iname;
1944 5127fd58 2021-12-17 jrmu if ($basepage) $itext = Qualify(@$basepage, @$itext);
1945 fc91d0f1 2023-03-07 jrmu if (@$itext) @$IncludedPages[$iname]++;
1946 5127fd58 2021-12-17 jrmu return FmtTemplateVars(PVSE(@$itext), $args);
1947 5127fd58 2021-12-17 jrmu }
1948 5127fd58 2021-12-17 jrmu
1949 5127fd58 2021-12-17 jrmu
1950 5127fd58 2021-12-17 jrmu function RedirectMarkup($pagename, $opt) {
1951 5127fd58 2021-12-17 jrmu $k = Keep("(:redirect $opt:)");
1952 5127fd58 2021-12-17 jrmu global $MarkupFrame, $EnableRedirectQuiet;
1953 5127fd58 2021-12-17 jrmu if (!@$MarkupFrame[0]['redirect']) return $k;
1954 5127fd58 2021-12-17 jrmu $opt = ParseArgs($opt);
1955 5127fd58 2021-12-17 jrmu $to = @$opt['to']; if (!$to) $to = @$opt[''][0];
1956 5127fd58 2021-12-17 jrmu if (!$to) return $k;
1957 5127fd58 2021-12-17 jrmu if (preg_match('/^([^#]+)(#[A-Za-z][-\\w]*)$/', $to, $match))
1958 5127fd58 2021-12-17 jrmu { $to = $match[1]; $anchor = @$match[2]; }
1959 5127fd58 2021-12-17 jrmu $to = MakePageName($pagename, $to);
1960 5127fd58 2021-12-17 jrmu if (!PageExists($to)) return $k;
1961 5127fd58 2021-12-17 jrmu if ($to == $pagename) return '';
1962 5127fd58 2021-12-17 jrmu if (@$opt['from']
1963 5127fd58 2021-12-17 jrmu && !MatchPageNames($pagename, FixGlob($opt['from'], '$1*.$2')))
1964 5127fd58 2021-12-17 jrmu return '';
1965 5127fd58 2021-12-17 jrmu if (preg_match('/^30[1237]$/', @$opt['status']))
1966 5127fd58 2021-12-17 jrmu header("HTTP/1.1 {$opt['status']}");
1967 5127fd58 2021-12-17 jrmu Redirect($to, "{\$PageUrl}"
1968 5127fd58 2021-12-17 jrmu . (IsEnabled($EnableRedirectQuiet, 0) && IsEnabled($opt['quiet'], 0)
1969 5127fd58 2021-12-17 jrmu ? '' : "?from=$pagename")
1970 5127fd58 2021-12-17 jrmu . $anchor);
1971 5127fd58 2021-12-17 jrmu exit();
1972 5127fd58 2021-12-17 jrmu }
1973 5127fd58 2021-12-17 jrmu
1974 5127fd58 2021-12-17 jrmu
1975 5127fd58 2021-12-17 jrmu function Block($b) {
1976 5127fd58 2021-12-17 jrmu global $BlockMarkups,$HTMLVSpace,$HTMLPNewline,$MarkupFrame;
1977 5127fd58 2021-12-17 jrmu $mf = &$MarkupFrame[0]; $cs = &$mf['cs']; $vspaces = &$mf['vs'];
1978 5127fd58 2021-12-17 jrmu $out = '';
1979 5127fd58 2021-12-17 jrmu if ($b == 'vspace') {
1980 5127fd58 2021-12-17 jrmu $vspaces .= "\n";
1981 5127fd58 2021-12-17 jrmu while (count($cs)>0 && @end($cs)!='pre' && @$BlockMarkups[@end($cs)][3]==0)
1982 5127fd58 2021-12-17 jrmu { $c = array_pop($cs); $out .= $BlockMarkups[$c][2]; }
1983 5127fd58 2021-12-17 jrmu return $out;
1984 5127fd58 2021-12-17 jrmu }
1985 5127fd58 2021-12-17 jrmu @list($code, $depth, $icol) = explode(',', $b);
1986 5127fd58 2021-12-17 jrmu if (!$code) $depth = 1;
1987 fc91d0f1 2023-03-07 jrmu if (!is_numeric($depth)) $depth = @$depth? strlen($depth) : 0; # PHP8.1
1988 fc91d0f1 2023-03-07 jrmu if (!is_numeric($icol)) $icol = @$icol? strlen($icol) : 0; # PHP8.1
1989 5127fd58 2021-12-17 jrmu if ($depth > 0) $depth += @$mf['idep'];
1990 5127fd58 2021-12-17 jrmu if ($icol > 0) $mf['is'][$depth] = $icol + @$mf['icol'];
1991 5127fd58 2021-12-17 jrmu @$mf['idep'] = @$mf['icol'] = 0;
1992 5127fd58 2021-12-17 jrmu while (count($cs)>$depth)
1993 fc91d0f1 2023-03-07 jrmu { $c = array_pop($cs); $out .= @$BlockMarkups[$c][2]; }
1994 5127fd58 2021-12-17 jrmu if (!$code) {
1995 5127fd58 2021-12-17 jrmu if (@end($cs) == 'p') { $out .= $HTMLPNewline; $code = 'p'; }
1996 5127fd58 2021-12-17 jrmu else if ($depth < 2) { $code = 'p'; $mf['is'][$depth] = 0; }
1997 5127fd58 2021-12-17 jrmu else { $out .= $HTMLPNewline; $code = 'block'; }
1998 5127fd58 2021-12-17 jrmu }
1999 5127fd58 2021-12-17 jrmu if ($depth>0 && $depth==count($cs) && $cs[$depth-1]!=$code)
2000 5127fd58 2021-12-17 jrmu { $c = array_pop($cs); $out .= $BlockMarkups[$c][2]; }
2001 5127fd58 2021-12-17 jrmu while (count($cs)>0 && @end($cs)!=$code &&
2002 5127fd58 2021-12-17 jrmu @$BlockMarkups[@end($cs)][3]==0)
2003 5127fd58 2021-12-17 jrmu { $c = array_pop($cs); $out .= $BlockMarkups[$c][2]; }
2004 5127fd58 2021-12-17 jrmu if ($vspaces) {
2005 5127fd58 2021-12-17 jrmu $out .= (@end($cs) == 'pre') ? $vspaces : $HTMLVSpace;
2006 5127fd58 2021-12-17 jrmu $vspaces='';
2007 5127fd58 2021-12-17 jrmu }
2008 5127fd58 2021-12-17 jrmu if ($depth==0) { return $out; }
2009 5127fd58 2021-12-17 jrmu if ($depth==count($cs)) { return $out.$BlockMarkups[$code][1]; }
2010 5127fd58 2021-12-17 jrmu while (count($cs)<$depth-1) {
2011 5127fd58 2021-12-17 jrmu array_push($cs, 'dl'); $mf['is'][count($cs)] = 0;
2012 5127fd58 2021-12-17 jrmu $out .= $BlockMarkups['dl'][0].'<dd>';
2013 5127fd58 2021-12-17 jrmu }
2014 5127fd58 2021-12-17 jrmu if (count($cs)<$depth) {
2015 5127fd58 2021-12-17 jrmu array_push($cs,$code);
2016 5127fd58 2021-12-17 jrmu $out .= $BlockMarkups[$code][0];
2017 5127fd58 2021-12-17 jrmu }
2018 5127fd58 2021-12-17 jrmu return $out;
2019 5127fd58 2021-12-17 jrmu }
2020 5127fd58 2021-12-17 jrmu
2021 5127fd58 2021-12-17 jrmu
2022 5127fd58 2021-12-17 jrmu function MarkupClose($key = '') {
2023 5127fd58 2021-12-17 jrmu global $MarkupFrame;
2024 5127fd58 2021-12-17 jrmu $cf = & $MarkupFrame[0]['closeall'];
2025 5127fd58 2021-12-17 jrmu $out = '';
2026 5127fd58 2021-12-17 jrmu if ($key == '' || isset($cf[$key])) {
2027 5127fd58 2021-12-17 jrmu $k = array_keys((array)$cf);
2028 5127fd58 2021-12-17 jrmu while ($k) {
2029 5127fd58 2021-12-17 jrmu $x = array_pop($k); $out .= $cf[$x]; unset($cf[$x]);
2030 5127fd58 2021-12-17 jrmu if ($x == $key) break;
2031 5127fd58 2021-12-17 jrmu }
2032 5127fd58 2021-12-17 jrmu }
2033 5127fd58 2021-12-17 jrmu return $out;
2034 5127fd58 2021-12-17 jrmu }
2035 5127fd58 2021-12-17 jrmu
2036 5127fd58 2021-12-17 jrmu
2037 5127fd58 2021-12-17 jrmu function FormatTableRow($x, $sep = '\\|\\|') {
2038 5127fd58 2021-12-17 jrmu global $TableCellAttrFmt, $TableCellAlignFmt, $TableRowAttrFmt,
2039 5127fd58 2021-12-17 jrmu $TableRowIndexMax, $MarkupFrame, $FmtV, $EnableSimpleTableRowspan;
2040 5127fd58 2021-12-17 jrmu static $rowcount;
2041 5127fd58 2021-12-17 jrmu SDV($TableCellAlignFmt, " align='%s'");
2042 5127fd58 2021-12-17 jrmu
2043 5127fd58 2021-12-17 jrmu if (IsEnabled($EnableSimpleTableRowspan, 0)) {
2044 5127fd58 2021-12-17 jrmu $x = preg_replace("/\\|\\|__+(?=\\|\\|)/", '||', $x);
2045 5127fd58 2021-12-17 jrmu $x = preg_replace("/\\|\\|\\^\\^+(?=\\|\\|)/", '', $x);
2046 5127fd58 2021-12-17 jrmu }
2047 5127fd58 2021-12-17 jrmu $x = preg_replace("/$sep\\s*$/",'',$x);
2048 5127fd58 2021-12-17 jrmu $td = preg_split("/$sep/", $x); $y = '';
2049 5127fd58 2021-12-17 jrmu for($i=0;$i<count($td);$i++) {
2050 5127fd58 2021-12-17 jrmu if ($td[$i]=='') continue;
2051 5127fd58 2021-12-17 jrmu $FmtV['$TableCellCount'] = $i;
2052 5127fd58 2021-12-17 jrmu $attr = FmtPageName(@$TableCellAttrFmt, '');
2053 5127fd58 2021-12-17 jrmu if (IsEnabled($EnableSimpleTableRowspan, 0)) {
2054 5127fd58 2021-12-17 jrmu if (preg_match('/(\\+\\++)\\s*$/', $td[$i], $rspn)) {
2055 5127fd58 2021-12-17 jrmu $td[$i] = preg_replace('/\\+\\++(\\s*)$/', '$1', $td[$i]);
2056 5127fd58 2021-12-17 jrmu $attr .= " rowspan='".strlen($rspn[1])."'";
2057 5127fd58 2021-12-17 jrmu }
2058 5127fd58 2021-12-17 jrmu }
2059 5127fd58 2021-12-17 jrmu $td[$i] = preg_replace('/^(!?)\\s+$/', '$1&nbsp;', $td[$i]);
2060 5127fd58 2021-12-17 jrmu if (preg_match('/^!(.*?)!$/',$td[$i],$match))
2061 5127fd58 2021-12-17 jrmu { $td[$i]=$match[1]; $t='caption'; $attr=''; }
2062 5127fd58 2021-12-17 jrmu elseif (preg_match('/^!(.*)$/',$td[$i],$match))
2063 5127fd58 2021-12-17 jrmu { $td[$i]=$match[1]; $t='th'; }
2064 5127fd58 2021-12-17 jrmu else $t='td';
2065 5127fd58 2021-12-17 jrmu if (preg_match('/^\\s.*\\s$/',$td[$i])) {
2066 5127fd58 2021-12-17 jrmu if ($t!='caption') $attr .= sprintf($TableCellAlignFmt, 'center');
2067 5127fd58 2021-12-17 jrmu }
2068 5127fd58 2021-12-17 jrmu elseif (preg_match('/^\\s/',$td[$i])) { $attr .= sprintf($TableCellAlignFmt, 'right'); }
2069 5127fd58 2021-12-17 jrmu elseif (preg_match('/\\s$/',$td[$i])) { $attr .= sprintf($TableCellAlignFmt, 'left'); }
2070 5127fd58 2021-12-17 jrmu for ($colspan=1;$i+$colspan<count($td);$colspan++)
2071 5127fd58 2021-12-17 jrmu if ($td[$colspan+$i]!='') break;
2072 5127fd58 2021-12-17 jrmu if ($colspan>1) { $attr .= " colspan='$colspan'"; }
2073 5127fd58 2021-12-17 jrmu $y .= "<$t $attr>".trim($td[$i])."</$t>";
2074 5127fd58 2021-12-17 jrmu }
2075 5127fd58 2021-12-17 jrmu if ($t=='caption') return "<:table,1>$y";
2076 5127fd58 2021-12-17 jrmu if (@$MarkupFrame[0]['cs'][0] != 'table') $rowcount = 0; else $rowcount++;
2077 5127fd58 2021-12-17 jrmu $FmtV['$TableRowCount'] = $rowcount + 1;
2078 5127fd58 2021-12-17 jrmu $FmtV['$TableRowIndex'] = ($rowcount % $TableRowIndexMax) + 1;
2079 5127fd58 2021-12-17 jrmu $trattr = FmtPageName(@$TableRowAttrFmt, '');
2080 5127fd58 2021-12-17 jrmu return "<:table,1><tr $trattr>$y</tr>";
2081 5127fd58 2021-12-17 jrmu }
2082 5127fd58 2021-12-17 jrmu
2083 5127fd58 2021-12-17 jrmu function LinkIMap($pagename,$imap,$path,$alt,$txt,$fmt=NULL) {
2084 5127fd58 2021-12-17 jrmu global $FmtV, $IMap, $IMapLinkFmt, $UrlLinkFmt, $IMapLocalPath, $ScriptUrl, $AddLinkCSS;
2085 5127fd58 2021-12-17 jrmu SDVA($IMapLocalPath, array('Path:'=>1));
2086 5127fd58 2021-12-17 jrmu if (@$IMapLocalPath[$imap]) {
2087 5127fd58 2021-12-17 jrmu $path = preg_replace('/^(\\w+):/', "$1%3a", $path); # PITS:01260
2088 5127fd58 2021-12-17 jrmu }
2089 5127fd58 2021-12-17 jrmu $FmtV['$LinkUrl'] = PUE(str_replace('$1',$path,$IMap[$imap]));
2090 5127fd58 2021-12-17 jrmu $FmtV['$LinkText'] = $txt;
2091 fc91d0f1 2023-03-07 jrmu if (@$alt) $FmtV['$LinkAlt'] = Keep(str_replace(array('"',"'"),array('&#34;','&#39;'),$alt));
2092 fc91d0f1 2023-03-07 jrmu else $FmtV['$LinkAlt'] = '';
2093 5127fd58 2021-12-17 jrmu if (!$fmt)
2094 5127fd58 2021-12-17 jrmu $fmt = (isset($IMapLinkFmt[$imap])) ? $IMapLinkFmt[$imap] : $UrlLinkFmt;
2095 fc91d0f1 2023-03-07 jrmu if (IsEnabled($AddLinkCSS['samedomain'])) {
2096 5127fd58 2021-12-17 jrmu $parsed_url = parse_url($FmtV['$LinkUrl']);
2097 5127fd58 2021-12-17 jrmu $parsed_wiki = parse_url($ScriptUrl);
2098 fc91d0f1 2023-03-07 jrmu if (! @$parsed_url['host'] || $parsed_url['host'] == $parsed_wiki['host']) {
2099 5127fd58 2021-12-17 jrmu $fmt = preg_replace('/(<a[^>]*class=["\'])/', "$1{$AddLinkCSS['samedomain']} ", $fmt);
2100 5127fd58 2021-12-17 jrmu }
2101 5127fd58 2021-12-17 jrmu }
2102 fc91d0f1 2023-03-07 jrmu # remove unused title attributes
2103 fc91d0f1 2023-03-07 jrmu if (!$alt) $fmt = preg_replace('/\\stitle=([\'"])\\$LinkAlt\\1/', '', $fmt);
2104 5127fd58 2021-12-17 jrmu return str_replace(array_keys($FmtV),array_values($FmtV),$fmt);
2105 5127fd58 2021-12-17 jrmu }
2106 5127fd58 2021-12-17 jrmu
2107 5127fd58 2021-12-17 jrmu ## These 2 functions hide e-mail addresses from spam bot harvesters
2108 5127fd58 2021-12-17 jrmu ## recover them for most users with a javascript utility,
2109 5127fd58 2021-12-17 jrmu ## while keeping them readable for users with JS disabled.
2110 5127fd58 2021-12-17 jrmu ## Based on Cookbook:DeObMail by Petko Yotov
2111 5127fd58 2021-12-17 jrmu ## To enable, set $LinkFunctions['mailto:'] = 'ObfuscateLinkIMap';
2112 5127fd58 2021-12-17 jrmu function ObfuscateLinkIMap($pagename,$imap,$path,$title,$txt,$fmt=NULL) {
2113 5127fd58 2021-12-17 jrmu global $FmtV, $IMap, $IMapLinkFmt;
2114 5127fd58 2021-12-17 jrmu SDVA($IMapLinkFmt, array('obfuscate-mailto:' =>
2115 5127fd58 2021-12-17 jrmu "<span class='_pmXmail' title=\"\$LinkAlt\"><span class='_t'>\$LinkText</span><span class='_m'>\$LinkUrl</span></span>"));
2116 5127fd58 2021-12-17 jrmu $FmtV['$LinkUrl'] = cb_obfuscate_mail(str_replace('$1',$path,$IMap[$imap]));
2117 5127fd58 2021-12-17 jrmu $FmtV['$LinkText'] = cb_obfuscate_mail(preg_replace('/^mailto:/i', '', $txt));
2118 fc91d0f1 2023-03-07 jrmu if ($FmtV['$LinkText'] == preg_replace('/^mailto:/i', '', $FmtV['$LinkUrl'])) $FmtV['$LinkUrl'] = '';
2119 5127fd58 2021-12-17 jrmu else $FmtV['$LinkUrl'] = " -&gt; ".$FmtV['$LinkUrl'];
2120 5127fd58 2021-12-17 jrmu $FmtV['$LinkAlt'] = str_replace(array('"',"'"),array('&#34;','&#39;'),cb_obfuscate_mail($title, 0));
2121 5127fd58 2021-12-17 jrmu return str_replace(array_keys($FmtV),array_values($FmtV), $IMapLinkFmt['obfuscate-mailto:']);
2122 5127fd58 2021-12-17 jrmu }
2123 5127fd58 2021-12-17 jrmu
2124 5127fd58 2021-12-17 jrmu function cb_obfuscate_mail($x, $wrap=1) {
2125 5127fd58 2021-12-17 jrmu $classes = array('.' => '_d', '@' => '_a');
2126 5127fd58 2021-12-17 jrmu $texts = array( '.' => XL(' [period] '), '@' => XL(' [snail] '));
2127 5127fd58 2021-12-17 jrmu foreach($classes as $k=>$v)
2128 5127fd58 2021-12-17 jrmu $x = preg_replace("/(\\w)".preg_quote($k)."(\\w)/",
2129 5127fd58 2021-12-17 jrmu ($wrap?
2130 5127fd58 2021-12-17 jrmu "$1<span class='$v'>{$texts[$k]}</span>$2"
2131 5127fd58 2021-12-17 jrmu : "$1{$texts[$k]}$2")
2132 5127fd58 2021-12-17 jrmu , $x);
2133 5127fd58 2021-12-17 jrmu return $x;
2134 5127fd58 2021-12-17 jrmu }
2135 5127fd58 2021-12-17 jrmu
2136 5127fd58 2021-12-17 jrmu function LinkPage($pagename,$imap,$path,$alt,$txt,$fmt=NULL) {
2137 5127fd58 2021-12-17 jrmu global $QueryFragPattern, $LinkPageExistsFmt, $LinkPageSelfFmt,
2138 5127fd58 2021-12-17 jrmu $LinkPageCreateSpaceFmt, $LinkPageCreateFmt, $LinkTargets,
2139 fc91d0f1 2023-03-07 jrmu $EnableLinkPageRelative, $EnableLinkPlusTitlespaced, $AddLinkCSS,
2140 fc91d0f1 2023-03-07 jrmu $CategoryGroup, $LinkCategoryFmt;
2141 fc91d0f1 2023-03-07 jrmu if ($alt) $alt = str_replace(array('"',"'"),array('&#34;','&#39;'),$alt);
2142 fc91d0f1 2023-03-07 jrmu $path = preg_replace('/(#[-.:\\w]*)#.*$/', '$1', strval($path)); # PITS:01388
2143 5127fd58 2021-12-17 jrmu if (is_array($txt)) { # PITS:01392
2144 5127fd58 2021-12-17 jrmu $suffix = $txt[1];
2145 5127fd58 2021-12-17 jrmu $txt = $txt[0];
2146 5127fd58 2021-12-17 jrmu }
2147 5127fd58 2021-12-17 jrmu if (!$fmt && @$path[0] == '#') {
2148 5127fd58 2021-12-17 jrmu $path = preg_replace("/[^-.:\\w]/", '', $path);
2149 5127fd58 2021-12-17 jrmu if (trim($txt) == '+') $txt = PageVar($pagename, '$Title') . @$suffix;
2150 5127fd58 2021-12-17 jrmu if ($alt) $alt = " title='$alt'";
2151 5127fd58 2021-12-17 jrmu return ($path) ? "<a href='#$path'$alt>".str_replace("$", "&#036;", $txt)."</a>" : '';
2152 5127fd58 2021-12-17 jrmu }
2153 fc91d0f1 2023-03-07 jrmu if (preg_match('/^\\s*!/', $path)) {
2154 fc91d0f1 2023-03-07 jrmu $is_cat = true;
2155 fc91d0f1 2023-03-07 jrmu $path = preg_replace('/^\\s*!/', "$CategoryGroup/", $path);
2156 fc91d0f1 2023-03-07 jrmu $txt = preg_replace('/^\\s*!/', '', $txt);
2157 fc91d0f1 2023-03-07 jrmu }
2158 5127fd58 2021-12-17 jrmu if (!preg_match("/^\\s*([^#?]+)($QueryFragPattern)?$/",$path,$match))
2159 5127fd58 2021-12-17 jrmu return '';
2160 5127fd58 2021-12-17 jrmu $tgtname = MakePageName($pagename, $match[1]);
2161 5127fd58 2021-12-17 jrmu if (!$tgtname) return '';
2162 fc91d0f1 2023-03-07 jrmu $qf = @$match[2]? $match[2] : '';
2163 5127fd58 2021-12-17 jrmu @$LinkTargets[$tgtname]++;
2164 fc91d0f1 2023-03-07 jrmu if (@$is_cat) {
2165 fc91d0f1 2023-03-07 jrmu $fmt = $LinkCategoryFmt;
2166 fc91d0f1 2023-03-07 jrmu $c = preg_replace('/^.*\\./', '!', $tgtname);
2167 fc91d0f1 2023-03-07 jrmu @$LinkTargets[$c]++;
2168 fc91d0f1 2023-03-07 jrmu }
2169 5127fd58 2021-12-17 jrmu if (!$fmt) {
2170 5127fd58 2021-12-17 jrmu if (!PageExists($tgtname) && !preg_match('/[&?]action=/', $qf))
2171 5127fd58 2021-12-17 jrmu $fmt = preg_match('/\\s/', $txt)
2172 5127fd58 2021-12-17 jrmu ? $LinkPageCreateSpaceFmt : $LinkPageCreateFmt;
2173 5127fd58 2021-12-17 jrmu else
2174 5127fd58 2021-12-17 jrmu $fmt = ($tgtname == $pagename && $qf == '')
2175 5127fd58 2021-12-17 jrmu ? $LinkPageSelfFmt : $LinkPageExistsFmt;
2176 5127fd58 2021-12-17 jrmu }
2177 5127fd58 2021-12-17 jrmu $url = PageVar($tgtname, '$PageUrl');
2178 5127fd58 2021-12-17 jrmu if (trim($txt) == '+') $txt = PageVar($tgtname,
2179 5127fd58 2021-12-17 jrmu IsEnabled($EnableLinkPlusTitlespaced, 0) ? '$Titlespaced' : '$Title') . @$suffix;
2180 5127fd58 2021-12-17 jrmu $txt = str_replace("$", "&#036;", $txt);
2181 5127fd58 2021-12-17 jrmu if (@$EnableLinkPageRelative)
2182 5127fd58 2021-12-17 jrmu $url = preg_replace('!^[a-z]+://[^/]*!i', '', $url);
2183 fc91d0f1 2023-03-07 jrmu # remove unused title attributes
2184 fc91d0f1 2023-03-07 jrmu if (!$alt) $fmt = preg_replace('/\\stitle=([\'"])\\$LinkAlt\\1/', '', $fmt);
2185 5127fd58 2021-12-17 jrmu $fmt = str_replace(array('$LinkUrl', '$LinkText', '$LinkAlt'),
2186 fc91d0f1 2023-03-07 jrmu array($url.PUE($qf), $txt, Keep($alt)), $fmt);
2187 fc91d0f1 2023-03-07 jrmu if (IsEnabled($AddLinkCSS['othergroup'])) {
2188 5127fd58 2021-12-17 jrmu list($cgroup, ) = explode('.', $pagename);
2189 5127fd58 2021-12-17 jrmu list($tgroup, ) = explode('.', $tgtname);
2190 fc91d0f1 2023-03-07 jrmu if ($cgroup != $tgroup)
2191 5127fd58 2021-12-17 jrmu $fmt = preg_replace('/(<a[^>]*class=["\'])/', "$1{$AddLinkCSS['othergroup']} ", $fmt);
2192 5127fd58 2021-12-17 jrmu }
2193 5127fd58 2021-12-17 jrmu return FmtPageName($fmt,$tgtname);
2194 5127fd58 2021-12-17 jrmu }
2195 5127fd58 2021-12-17 jrmu
2196 5127fd58 2021-12-17 jrmu function MakeLink($pagename,$tgt,$txt=NULL,$suffix=NULL,$fmt=NULL) {
2197 5127fd58 2021-12-17 jrmu global $LinkPattern,$LinkFunctions,$UrlExcludeChars,$ImgExtPattern,$ImgTagFmt,
2198 5127fd58 2021-12-17 jrmu $LinkTitleFunction;
2199 fc91d0f1 2023-03-07 jrmu if (preg_match("/^(.*)(?:\"(.*)\")\\s*$/",$tgt,$x)) list(,$tgt,$title) = $x;
2200 5127fd58 2021-12-17 jrmu $t = preg_replace('/[()]/','',trim($tgt));
2201 5127fd58 2021-12-17 jrmu $t = preg_replace('/<[^>]*>/','',$t);
2202 5127fd58 2021-12-17 jrmu $t = trim(MarkupRestore($t));
2203 fc91d0f1 2023-03-07 jrmu $txtr = trim(MarkupRestore(strval($txt)));
2204 5127fd58 2021-12-17 jrmu
2205 5127fd58 2021-12-17 jrmu preg_match("/^($LinkPattern)?(.+)$/",$t,$m);
2206 5127fd58 2021-12-17 jrmu if (!@$m[1]) $m[1]='<:page>';
2207 5127fd58 2021-12-17 jrmu if (preg_match("/(($LinkPattern)([^$UrlExcludeChars]+$ImgExtPattern))(\"(.*)\")?$/",$txtr,$tm))
2208 5127fd58 2021-12-17 jrmu $txt = $LinkFunctions[$tm[2]]($pagename,$tm[2],$tm[3],@$tm[5],
2209 5127fd58 2021-12-17 jrmu $tm[1],$ImgTagFmt);
2210 5127fd58 2021-12-17 jrmu else {
2211 5127fd58 2021-12-17 jrmu if (is_null($txt)) {
2212 5127fd58 2021-12-17 jrmu $txt = preg_replace('/\\([^)]*\\)/','',$tgt);
2213 5127fd58 2021-12-17 jrmu if ($m[1]=='<:page>') {
2214 5127fd58 2021-12-17 jrmu $txt = preg_replace('!/\\s*$!', '', $txt);
2215 5127fd58 2021-12-17 jrmu $txt = preg_replace('!^.*[^<]/!', '', $txt);
2216 5127fd58 2021-12-17 jrmu }
2217 5127fd58 2021-12-17 jrmu }
2218 5127fd58 2021-12-17 jrmu if ($m[1]=='<:page>' && trim($txt) == '+' && $suffix>'') { # PITS:01392
2219 5127fd58 2021-12-17 jrmu $txt = array(trim($txt), $suffix);
2220 5127fd58 2021-12-17 jrmu }
2221 5127fd58 2021-12-17 jrmu else $txt .= $suffix;
2222 5127fd58 2021-12-17 jrmu }
2223 5127fd58 2021-12-17 jrmu if (@$LinkTitleFunction) $title = $LinkTitleFunction($pagename,$m,$txt);
2224 5127fd58 2021-12-17 jrmu else $title = PHSC(MarkupRestore(@$title), ENT_QUOTES);
2225 5127fd58 2021-12-17 jrmu $out = $LinkFunctions[$m[1]]($pagename,$m[1],@$m[2],@$title,$txt,$fmt);
2226 5127fd58 2021-12-17 jrmu return preg_replace('/(<[^>]+)\\stitle=(""|\'\')/', '$1', $out);
2227 5127fd58 2021-12-17 jrmu }
2228 5127fd58 2021-12-17 jrmu
2229 fc91d0f1 2023-03-07 jrmu function Markup($id, $when, $pat=NULL, $rep=NULL) {
2230 fc91d0f1 2023-03-07 jrmu global $MarkupTable, $EnableMarkupDiag, $ObsoleteMarkups;
2231 5127fd58 2021-12-17 jrmu unset($GLOBALS['MarkupRules']);
2232 5127fd58 2021-12-17 jrmu if (preg_match('/^([<>])?(.+)$/', $when, $m)) {
2233 5127fd58 2021-12-17 jrmu $MarkupTable[$id]['cmd'] = $when;
2234 5127fd58 2021-12-17 jrmu $MarkupTable[$m[2]]['dep'][$id] = $m[1];
2235 5127fd58 2021-12-17 jrmu if (!$m[1]) $m[1] = '=';
2236 5127fd58 2021-12-17 jrmu if (@$MarkupTable[$m[2]]['seq']) {
2237 5127fd58 2021-12-17 jrmu $MarkupTable[$id]['seq'] = $MarkupTable[$m[2]]['seq'].$m[1];
2238 5127fd58 2021-12-17 jrmu foreach((array)@$MarkupTable[$id]['dep'] as $i=>$m)
2239 5127fd58 2021-12-17 jrmu Markup($i,"$m$id");
2240 5127fd58 2021-12-17 jrmu unset($GLOBALS['MarkupTable'][$id]['dep']);
2241 5127fd58 2021-12-17 jrmu }
2242 5127fd58 2021-12-17 jrmu }
2243 5127fd58 2021-12-17 jrmu if ($pat && !isset($MarkupTable[$id]['pat'])) {
2244 fc91d0f1 2023-03-07 jrmu $oldpat = preg_match('!(^/.+/[^/]*)e([^/]*)$!', $pat, $mm);
2245 fc91d0f1 2023-03-07 jrmu if ($oldpat && PHP_VERSION_ID >= 50500) {
2246 fc91d0f1 2023-03-07 jrmu # disable old markup for recent PHP versions
2247 fc91d0f1 2023-03-07 jrmu $trace = TraceMarkup($id, true);
2248 fc91d0f1 2023-03-07 jrmu $rep = 'ObsoleteMarkup';
2249 fc91d0f1 2023-03-07 jrmu $pat = $mm[1].$mm[2];
2250 fc91d0f1 2023-03-07 jrmu }
2251 5127fd58 2021-12-17 jrmu $MarkupTable[$id]['pat'] = $pat;
2252 5127fd58 2021-12-17 jrmu $MarkupTable[$id]['rep'] = $rep;
2253 fc91d0f1 2023-03-07 jrmu
2254 fc91d0f1 2023-03-07 jrmu if (IsEnabled($EnableMarkupDiag, 0) || isset($ObsoleteMarkups[$id])) {
2255 fc91d0f1 2023-03-07 jrmu $MarkupTable[$id]['dbg'] = isset($ObsoleteMarkups[$id])
2256 fc91d0f1 2023-03-07 jrmu ? $ObsoleteMarkups[$id]
2257 fc91d0f1 2023-03-07 jrmu : TraceMarkup($id, false);
2258 fc91d0f1 2023-03-07 jrmu }
2259 fc91d0f1 2023-03-07 jrmu }
2260 fc91d0f1 2023-03-07 jrmu }
2261 5127fd58 2021-12-17 jrmu
2262 fc91d0f1 2023-03-07 jrmu function Markup_e($id, $when, $pat, $rep, $template = 'markup_e') {
2263 fc91d0f1 2023-03-07 jrmu if (!is_callable($rep)) {
2264 fc91d0f1 2023-03-07 jrmu if (PHP_VERSION_ID < 70200 || isset($GLOBALS['PCCFOverrideFunction']))
2265 fc91d0f1 2023-03-07 jrmu $rep = PCCF($rep, $template);
2266 fc91d0f1 2023-03-07 jrmu else {
2267 fc91d0f1 2023-03-07 jrmu TraceMarkup($id, true);
2268 fc91d0f1 2023-03-07 jrmu $rep = 'ObsoleteMarkup';
2269 5127fd58 2021-12-17 jrmu }
2270 5127fd58 2021-12-17 jrmu }
2271 fc91d0f1 2023-03-07 jrmu Markup($id, $when, $pat, $rep, 1);
2272 5127fd58 2021-12-17 jrmu }
2273 5127fd58 2021-12-17 jrmu
2274 fc91d0f1 2023-03-07 jrmu function TraceMarkup($id, $obsolete = false) {
2275 fc91d0f1 2023-03-07 jrmu global $ObsoleteMarkups;
2276 fc91d0f1 2023-03-07 jrmu $trace = debug_backtrace();
2277 fc91d0f1 2023-03-07 jrmu foreach($trace as $t) {
2278 fc91d0f1 2023-03-07 jrmu if (! preg_match('/^Markup(_e)?$/i', $t['function'])) continue;
2279 fc91d0f1 2023-03-07 jrmu if ($t['args'][0] !== $id) continue;
2280 fc91d0f1 2023-03-07 jrmu $excl = $obsolete? "!" : " ";
2281 fc91d0f1 2023-03-07 jrmu $msg = "$excl File: {$t['file']}, line: {$t['line']}"
2282 fc91d0f1 2023-03-07 jrmu . ", pat: {$t['args'][2]}, rep: {$t['args'][3]}.";
2283 fc91d0f1 2023-03-07 jrmu if ($obsolete) $ObsoleteMarkups[$id] = $msg;
2284 fc91d0f1 2023-03-07 jrmu return $msg;
2285 fc91d0f1 2023-03-07 jrmu }
2286 5127fd58 2021-12-17 jrmu }
2287 5127fd58 2021-12-17 jrmu
2288 fc91d0f1 2023-03-07 jrmu function ObsoleteMarkup($m) {
2289 fc91d0f1 2023-03-07 jrmu extract($GLOBALS['MarkupToHTML']);
2290 fc91d0f1 2023-03-07 jrmu global $ObsoleteMarkups;
2291 fc91d0f1 2023-03-07 jrmu $id = PHSC($markupid, ENT_QUOTES, null, false);
2292 fc91d0f1 2023-03-07 jrmu $txt = PHSC($m[0], ENT_QUOTES, null, false);
2293 fc91d0f1 2023-03-07 jrmu if (isset($ObsoleteMarkups[$markupid])) {
2294 fc91d0f1 2023-03-07 jrmu $dbg = PHSC($ObsoleteMarkups[$markupid], ENT_QUOTES, null, false);
2295 fc91d0f1 2023-03-07 jrmu }
2296 fc91d0f1 2023-03-07 jrmu else $dbg = '';
2297 fc91d0f1 2023-03-07 jrmu return Keep("<code title='Markup rule &quot;$id&quot; is obsolete and has been disabled. $dbg See pmwiki.org/Troubleshooting'
2298 fc91d0f1 2023-03-07 jrmu class='obsolete-markup frame'>&#9888; $txt</code>");
2299 fc91d0f1 2023-03-07 jrmu }
2300 fc91d0f1 2023-03-07 jrmu
2301 5127fd58 2021-12-17 jrmu function DisableMarkup() {
2302 5127fd58 2021-12-17 jrmu global $MarkupTable;
2303 5127fd58 2021-12-17 jrmu $idlist = func_get_args();
2304 5127fd58 2021-12-17 jrmu unset($GLOBALS['MarkupRules']);
2305 5127fd58 2021-12-17 jrmu while (count($idlist)>0) {
2306 5127fd58 2021-12-17 jrmu $id = array_shift($idlist);
2307 5127fd58 2021-12-17 jrmu if (is_array($id)) { $idlist = array_merge($idlist, $id); continue; }
2308 5127fd58 2021-12-17 jrmu $MarkupTable[$id] = array('cmd' => 'none', 'pat'=>'');
2309 5127fd58 2021-12-17 jrmu }
2310 5127fd58 2021-12-17 jrmu }
2311 5127fd58 2021-12-17 jrmu
2312 5127fd58 2021-12-17 jrmu function mpcmp($a,$b) { return @strcmp($a['seq'].'=',$b['seq'].'='); }
2313 5127fd58 2021-12-17 jrmu function BuildMarkupRules() {
2314 5127fd58 2021-12-17 jrmu global $MarkupTable,$MarkupRules,$LinkPattern;
2315 5127fd58 2021-12-17 jrmu if (!$MarkupRules) {
2316 5127fd58 2021-12-17 jrmu uasort($MarkupTable,'mpcmp');
2317 5127fd58 2021-12-17 jrmu foreach($MarkupTable as $id=>$m)
2318 5127fd58 2021-12-17 jrmu if (@$m['pat'] && @$m['seq']) {
2319 fc91d0f1 2023-03-07 jrmu $MarkupRules[str_replace('\\L',strval(@$LinkPattern),$m['pat'])]
2320 5127fd58 2021-12-17 jrmu = array($m['rep'], $id);
2321 5127fd58 2021-12-17 jrmu }
2322 5127fd58 2021-12-17 jrmu }
2323 5127fd58 2021-12-17 jrmu return $MarkupRules;
2324 5127fd58 2021-12-17 jrmu }
2325 5127fd58 2021-12-17 jrmu
2326 5127fd58 2021-12-17 jrmu
2327 5127fd58 2021-12-17 jrmu function MarkupToHTML($pagename, $text, $opt = NULL) {
2328 5127fd58 2021-12-17 jrmu # convert wiki markup text to HTML output
2329 5127fd58 2021-12-17 jrmu global $MarkupRules, $MarkupFrame, $MarkupFrameBase, $WikiWordCount,
2330 5127fd58 2021-12-17 jrmu $K0, $K1, $RedoMarkupLine, $MarkupToHTML;
2331 5127fd58 2021-12-17 jrmu $MarkupToHTML['pagename'] = $pagename;
2332 5127fd58 2021-12-17 jrmu
2333 5127fd58 2021-12-17 jrmu StopWatch('MarkupToHTML begin');
2334 5127fd58 2021-12-17 jrmu array_unshift($MarkupFrame, array_merge($MarkupFrameBase, (array)$opt));
2335 5127fd58 2021-12-17 jrmu $MarkupFrame[0]['wwcount'] = $WikiWordCount;
2336 5127fd58 2021-12-17 jrmu foreach((array)$text as $l)
2337 5127fd58 2021-12-17 jrmu $lines[] = $MarkupFrame[0]['escape'] ? PVSE($l) : $l;
2338 5127fd58 2021-12-17 jrmu $lines[] = '(:closeall:)';
2339 5127fd58 2021-12-17 jrmu $out = '';
2340 5127fd58 2021-12-17 jrmu while (count($lines)>0) {
2341 5127fd58 2021-12-17 jrmu $x = array_shift($lines);
2342 5127fd58 2021-12-17 jrmu $RedoMarkupLine=0;
2343 5127fd58 2021-12-17 jrmu $markrules = BuildMarkupRules();
2344 5127fd58 2021-12-17 jrmu foreach($markrules as $p=>$r) {
2345 5127fd58 2021-12-17 jrmu list($r, $id) = (array)$r;
2346 5127fd58 2021-12-17 jrmu $MarkupToHTML['markupid'] = $id;
2347 5127fd58 2021-12-17 jrmu if ($p[0] == '/') {
2348 5127fd58 2021-12-17 jrmu if (is_callable($r)) $x = preg_replace_callback($p,$r,$x);
2349 5127fd58 2021-12-17 jrmu else $x=preg_replace($p,$r,$x); # simple text OR called by old addon|skin|recipe needing update, see pmwiki.org/Troubleshooting
2350 5127fd58 2021-12-17 jrmu }
2351 5127fd58 2021-12-17 jrmu elseif (strstr($x,$p)!==false) $x=eval($r);
2352 fc91d0f1 2023-03-07 jrmu if (isset($php_errormsg)) ### TODO: $php_errormsg removed since PHP 8
2353 5127fd58 2021-12-17 jrmu { echo "ERROR: pat=$p $php_errormsg"; unset($php_errormsg); }
2354 5127fd58 2021-12-17 jrmu if ($RedoMarkupLine) { $lines=array_merge((array)$x,$lines); continue 2; }
2355 5127fd58 2021-12-17 jrmu }
2356 5127fd58 2021-12-17 jrmu if ($x>'') $out .= "$x\n";
2357 5127fd58 2021-12-17 jrmu }
2358 5127fd58 2021-12-17 jrmu foreach((array)(@$MarkupFrame[0]['posteval']) as $v) eval($v);
2359 5127fd58 2021-12-17 jrmu array_shift($MarkupFrame);
2360 5127fd58 2021-12-17 jrmu StopWatch('MarkupToHTML end');
2361 5127fd58 2021-12-17 jrmu return $out;
2362 5127fd58 2021-12-17 jrmu }
2363 5127fd58 2021-12-17 jrmu
2364 5127fd58 2021-12-17 jrmu function HandleBrowse($pagename, $auth = 'read') {
2365 5127fd58 2021-12-17 jrmu # handle display of a page
2366 5127fd58 2021-12-17 jrmu global $DefaultPageTextFmt, $PageNotFoundHeaderFmt, $HTTPHeaders,
2367 5127fd58 2021-12-17 jrmu $EnableHTMLCache, $NoHTMLCache, $PageCacheFile, $LastModTime, $IsHTMLCached,
2368 5127fd58 2021-12-17 jrmu $FmtV, $HandleBrowseFmt, $PageStartFmt, $PageEndFmt, $PageRedirectFmt;
2369 5127fd58 2021-12-17 jrmu $page = RetrieveAuthPage($pagename, $auth, true, READPAGE_CURRENT);
2370 5127fd58 2021-12-17 jrmu if (!$page) Abort("?cannot read $pagename");
2371 5127fd58 2021-12-17 jrmu PCache($pagename,$page);
2372 fc91d0f1 2023-03-07 jrmu if (PageExists($pagename)) $text = $FmtV['$PageSourceText'] = @$page['text'];
2373 5127fd58 2021-12-17 jrmu else {
2374 5127fd58 2021-12-17 jrmu SDV($DefaultPageTextFmt,'(:include $[{$SiteGroup}.PageNotFound]:)');
2375 5127fd58 2021-12-17 jrmu $text = FmtPageName($DefaultPageTextFmt, $pagename);
2376 5127fd58 2021-12-17 jrmu SDV($PageNotFoundHeaderFmt, 'HTTP/1.1 404 Not Found');
2377 5127fd58 2021-12-17 jrmu SDV($HTTPHeaders['status'], $PageNotFoundHeaderFmt);
2378 5127fd58 2021-12-17 jrmu }
2379 5127fd58 2021-12-17 jrmu $opt = array();
2380 5127fd58 2021-12-17 jrmu SDV($PageRedirectFmt,"<p><i>($[redirected from] <a rel='nofollow'
2381 5127fd58 2021-12-17 jrmu href='{\$PageUrl}?action=edit'>{\$FullName}</a>)</i></p>\n");
2382 5127fd58 2021-12-17 jrmu if (@!$_GET['from']) { $opt['redirect'] = 1; $PageRedirectFmt = ''; }
2383 5127fd58 2021-12-17 jrmu else {
2384 5127fd58 2021-12-17 jrmu $frompage = MakePageName($pagename, $_GET['from']);
2385 5127fd58 2021-12-17 jrmu $PageRedirectFmt = (!$frompage) ? ''
2386 5127fd58 2021-12-17 jrmu : FmtPageName($PageRedirectFmt, $frompage);
2387 5127fd58 2021-12-17 jrmu }
2388 5127fd58 2021-12-17 jrmu if (@$EnableHTMLCache && !$NoHTMLCache && $PageCacheFile &&
2389 5127fd58 2021-12-17 jrmu @filemtime($PageCacheFile) > $LastModTime) {
2390 5127fd58 2021-12-17 jrmu list($ctext) = unserialize(file_get_contents($PageCacheFile));
2391 5127fd58 2021-12-17 jrmu $FmtV['$PageText'] = "<!--cached-->$ctext";
2392 5127fd58 2021-12-17 jrmu $IsHTMLCached = 1;
2393 5127fd58 2021-12-17 jrmu StopWatch("HandleBrowse: using cached copy");
2394 5127fd58 2021-12-17 jrmu } else {
2395 5127fd58 2021-12-17 jrmu $IsHTMLCached = 0;
2396 5127fd58 2021-12-17 jrmu $text = '(:groupheader:)'.@$text.'(:groupfooter:)';
2397 5127fd58 2021-12-17 jrmu $t1 = time();
2398 5127fd58 2021-12-17 jrmu $FmtV['$PageText'] = MarkupToHTML($pagename, $text, $opt);
2399 5127fd58 2021-12-17 jrmu if (@$EnableHTMLCache > 0 && !$NoHTMLCache && $PageCacheFile
2400 5127fd58 2021-12-17 jrmu && (time() - $t1 + 1) >= $EnableHTMLCache) {
2401 5127fd58 2021-12-17 jrmu $fp = @fopen("$PageCacheFile,new", "x");
2402 5127fd58 2021-12-17 jrmu if ($fp) {
2403 5127fd58 2021-12-17 jrmu StopWatch("HandleBrowse: caching page");
2404 5127fd58 2021-12-17 jrmu fwrite($fp, serialize(array($FmtV['$PageText']))); fclose($fp);
2405 5127fd58 2021-12-17 jrmu rename("$PageCacheFile,new", $PageCacheFile);
2406 5127fd58 2021-12-17 jrmu }
2407 5127fd58 2021-12-17 jrmu }
2408 5127fd58 2021-12-17 jrmu }
2409 5127fd58 2021-12-17 jrmu SDV($HandleBrowseFmt,array(&$PageStartFmt, &$PageRedirectFmt, '$PageText',
2410 5127fd58 2021-12-17 jrmu &$PageEndFmt));
2411 5127fd58 2021-12-17 jrmu PrintFmt($pagename,$HandleBrowseFmt);
2412 5127fd58 2021-12-17 jrmu }
2413 5127fd58 2021-12-17 jrmu
2414 5127fd58 2021-12-17 jrmu
2415 5127fd58 2021-12-17 jrmu ## UpdatePage goes through all of the steps needed to update a page,
2416 5127fd58 2021-12-17 jrmu ## preserving page history, computing link targets, page titles,
2417 5127fd58 2021-12-17 jrmu ## and other page attributes. It does this by calling each entry
2418 5127fd58 2021-12-17 jrmu ## in $EditFunctions. $pagename is the name of the page to be updated,
2419 5127fd58 2021-12-17 jrmu ## $page is the old version of the page (used for page history),
2420 5127fd58 2021-12-17 jrmu ## $new is the new version of the page to be saved, and $fnlist is
2421 5127fd58 2021-12-17 jrmu ## an optional list of functions to use instead of $EditFunctions.
2422 5127fd58 2021-12-17 jrmu function UpdatePage(&$pagename, &$page, &$new, $fnlist = NULL) {
2423 5127fd58 2021-12-17 jrmu global $EditFunctions, $IsPagePosted;
2424 5127fd58 2021-12-17 jrmu StopWatch("UpdatePage: begin $pagename");
2425 5127fd58 2021-12-17 jrmu if (is_null($fnlist)) $fnlist = $EditFunctions;
2426 5127fd58 2021-12-17 jrmu $IsPagePosted = false;
2427 5127fd58 2021-12-17 jrmu foreach((array)$fnlist as $fn) {
2428 5127fd58 2021-12-17 jrmu StopWatch("UpdatePage: $fn ($pagename)");
2429 5127fd58 2021-12-17 jrmu $fn($pagename, $page, $new);
2430 5127fd58 2021-12-17 jrmu }
2431 5127fd58 2021-12-17 jrmu StopWatch("UpdatePage: end $pagename");
2432 5127fd58 2021-12-17 jrmu return $IsPagePosted;
2433 5127fd58 2021-12-17 jrmu }
2434 5127fd58 2021-12-17 jrmu
2435 fc91d0f1 2023-03-07 jrmu # AutoCheckToken verifies if the posted content was sent
2436 fc91d0f1 2023-03-07 jrmu # from the website forms, to prevent CSRF
2437 fc91d0f1 2023-03-07 jrmu function AutoCheckToken() {
2438 fc91d0f1 2023-03-07 jrmu # TODO: Work in progress (Jan 2021), releasing for
2439 fc91d0f1 2023-03-07 jrmu return true;
2440 fc91d0f1 2023-03-07 jrmu
2441 fc91d0f1 2023-03-07 jrmu global $EnablePost, $AutoCheckTokenActions, $EnablePmToken,
2442 fc91d0f1 2023-03-07 jrmu $FmtV, $action, $BlockMessageFmt, $MessagesFmt;
2443 fc91d0f1 2023-03-07 jrmu
2444 fc91d0f1 2023-03-07 jrmu # a quick way to disable tokens
2445 fc91d0f1 2023-03-07 jrmu if (! IsEnabled($EnablePmToken, 1)) return true;
2446 fc91d0f1 2023-03-07 jrmu
2447 fc91d0f1 2023-03-07 jrmu SDVA($AutoCheckTokenActions, array( # 1=POST, 2=GET, 0=disabled
2448 fc91d0f1 2023-03-07 jrmu 'edit' => 1,
2449 fc91d0f1 2023-03-07 jrmu 'postattr' => 1,
2450 fc91d0f1 2023-03-07 jrmu 'postupload' => 1,
2451 fc91d0f1 2023-03-07 jrmu 'approvesites' => 2,
2452 fc91d0f1 2023-03-07 jrmu 'approveurls' => 2,
2453 fc91d0f1 2023-03-07 jrmu ));
2454 fc91d0f1 2023-03-07 jrmu $tname = $FmtV['$TokenName'];
2455 fc91d0f1 2023-03-07 jrmu $x = @$AutoCheckTokenActions[$action];
2456 fc91d0f1 2023-03-07 jrmu if (!$x) return true;
2457 fc91d0f1 2023-03-07 jrmu elseif ($x==1) {
2458 fc91d0f1 2023-03-07 jrmu if ( count($_POST) < 1 || pmtoken(''.@$_POST[$tname]) ) return true;
2459 fc91d0f1 2023-03-07 jrmu }
2460 fc91d0f1 2023-03-07 jrmu elseif ($x==2 && pmtoken(''.@$_GET[$tname])) return true;
2461 fc91d0f1 2023-03-07 jrmu
2462 fc91d0f1 2023-03-07 jrmu $EnablePost = 0;
2463 fc91d0f1 2023-03-07 jrmu $MessagesFmt[] = $BlockMessageFmt;
2464 fc91d0f1 2023-03-07 jrmu $MessagesFmt[] = XL('Token invalid or missing.');
2465 fc91d0f1 2023-03-07 jrmu return false;
2466 fc91d0f1 2023-03-07 jrmu }
2467 5127fd58 2021-12-17 jrmu
2468 5127fd58 2021-12-17 jrmu # EditTemplate allows a site administrator to pre-populate new pages
2469 5127fd58 2021-12-17 jrmu # with the contents of another page.
2470 5127fd58 2021-12-17 jrmu function EditTemplate($pagename, &$page, &$new) {
2471 5127fd58 2021-12-17 jrmu global $EditTemplatesFmt;
2472 5127fd58 2021-12-17 jrmu if (@$new['text'] > '') return;
2473 5127fd58 2021-12-17 jrmu if (@$_REQUEST['template'] && PageExists($_REQUEST['template'])) {
2474 5127fd58 2021-12-17 jrmu $p = RetrieveAuthPage($_REQUEST['template'], 'read', false,
2475 5127fd58 2021-12-17 jrmu READPAGE_CURRENT);
2476 5127fd58 2021-12-17 jrmu if ($p['text'] > '') $new['text'] = $p['text'];
2477 5127fd58 2021-12-17 jrmu return;
2478 5127fd58 2021-12-17 jrmu }
2479 5127fd58 2021-12-17 jrmu foreach((array)$EditTemplatesFmt as $t) {
2480 5127fd58 2021-12-17 jrmu $p = RetrieveAuthPage(FmtPageName($t,$pagename), 'read', false,
2481 5127fd58 2021-12-17 jrmu READPAGE_CURRENT);
2482 5127fd58 2021-12-17 jrmu if (@$p['text'] > '') { $new['text'] = $p['text']; return; }
2483 5127fd58 2021-12-17 jrmu }
2484 5127fd58 2021-12-17 jrmu }
2485 5127fd58 2021-12-17 jrmu
2486 5127fd58 2021-12-17 jrmu # RestorePage handles returning to the version of text as of
2487 5127fd58 2021-12-17 jrmu # the version given by $restore or $_REQUEST['restore'].
2488 5127fd58 2021-12-17 jrmu function RestorePage($pagename,&$page,&$new,$restore=NULL) {
2489 5127fd58 2021-12-17 jrmu if (is_null($restore)) $restore=@$_REQUEST['restore'];
2490 5127fd58 2021-12-17 jrmu if (!$restore) return;
2491 5127fd58 2021-12-17 jrmu $t = $page['text'];
2492 5127fd58 2021-12-17 jrmu $nl = (substr($t,-1)=="\n");
2493 5127fd58 2021-12-17 jrmu $t = explode("\n",$t);
2494 5127fd58 2021-12-17 jrmu if ($nl) array_pop($t);
2495 5127fd58 2021-12-17 jrmu krsort($page); reset($page);
2496 5127fd58 2021-12-17 jrmu foreach($page as $k=>$v) {
2497 5127fd58 2021-12-17 jrmu if ($k<$restore) break;
2498 5127fd58 2021-12-17 jrmu if (strncmp($k, 'diff:', 5) != 0) continue;
2499 5127fd58 2021-12-17 jrmu foreach(explode("\n",$v) as $x) {
2500 5127fd58 2021-12-17 jrmu if (preg_match('/^(\\d+)(,(\\d+))?([adc])(\\d+)/',$x,$match)) {
2501 5127fd58 2021-12-17 jrmu $a1 = $a2 = $match[1];
2502 5127fd58 2021-12-17 jrmu if ($match[3]) $a2=$match[3];
2503 5127fd58 2021-12-17 jrmu $b1 = $match[5];
2504 5127fd58 2021-12-17 jrmu if ($match[4]=='d') array_splice($t,$b1,$a2-$a1+1);
2505 5127fd58 2021-12-17 jrmu if ($match[4]=='c') array_splice($t,$b1-1,$a2-$a1+1);
2506 5127fd58 2021-12-17 jrmu continue;
2507 5127fd58 2021-12-17 jrmu }
2508 5127fd58 2021-12-17 jrmu if (strncmp($x,'< ',2) == 0) { $nlflag=true; continue; }
2509 5127fd58 2021-12-17 jrmu if (preg_match('/^> (.*)$/',$x,$match)) {
2510 5127fd58 2021-12-17 jrmu $nlflag=false;
2511 5127fd58 2021-12-17 jrmu array_splice($t,$b1-1,0,$match[1]); $b1++;
2512 5127fd58 2021-12-17 jrmu }
2513 5127fd58 2021-12-17 jrmu if ($x=='\\ No newline at end of file') $nl=$nlflag;
2514 5127fd58 2021-12-17 jrmu }
2515 5127fd58 2021-12-17 jrmu }
2516 5127fd58 2021-12-17 jrmu if ($nl) $t[]='';
2517 5127fd58 2021-12-17 jrmu $new['text']=implode("\n",$t);
2518 5127fd58 2021-12-17 jrmu $new['=preview'] = $new['text'];
2519 5127fd58 2021-12-17 jrmu PCache($pagename, $new);
2520 5127fd58 2021-12-17 jrmu return $new['text'];
2521 5127fd58 2021-12-17 jrmu }
2522 5127fd58 2021-12-17 jrmu
2523 5127fd58 2021-12-17 jrmu ## ReplaceOnSave performs text replacements on the text being posted.
2524 5127fd58 2021-12-17 jrmu ## Patterns held in $ROEPatterns are replaced on every edit request,
2525 5127fd58 2021-12-17 jrmu ## patterns held in $ROSPatterns are replaced only when the page
2526 5127fd58 2021-12-17 jrmu ## is being posted (as signaled by $EnablePost).
2527 5127fd58 2021-12-17 jrmu function ReplaceOnSave($pagename,&$page,&$new) {
2528 5127fd58 2021-12-17 jrmu global $EnablePost, $ROSPatterns, $ROEPatterns;
2529 5127fd58 2021-12-17 jrmu $new['text'] = ProcessROESPatterns(@$new['text'], $ROEPatterns);
2530 5127fd58 2021-12-17 jrmu if ($EnablePost) {
2531 5127fd58 2021-12-17 jrmu $new['text'] = ProcessROESPatterns($new['text'], $ROSPatterns);
2532 5127fd58 2021-12-17 jrmu }
2533 5127fd58 2021-12-17 jrmu $new['=preview'] = $new['text'];
2534 5127fd58 2021-12-17 jrmu PCache($pagename, $new);
2535 5127fd58 2021-12-17 jrmu }
2536 5127fd58 2021-12-17 jrmu function ProcessROESPatterns($text, $patterns) {
2537 5127fd58 2021-12-17 jrmu global $EnableROSEscape;
2538 5127fd58 2021-12-17 jrmu if (IsEnabled($EnableROSEscape, 0)) $text = MarkupEscape($text);
2539 5127fd58 2021-12-17 jrmu $text = PPRA((array)@$patterns, $text);
2540 5127fd58 2021-12-17 jrmu if (IsEnabled($EnableROSEscape, 0)) $text = MarkupRestore($text);
2541 5127fd58 2021-12-17 jrmu return $text;
2542 5127fd58 2021-12-17 jrmu }
2543 5127fd58 2021-12-17 jrmu
2544 5127fd58 2021-12-17 jrmu function SaveAttributes($pagename,&$page,&$new) {
2545 5127fd58 2021-12-17 jrmu global $EnablePost, $LinkTargets, $SaveAttrPatterns, $PCache,
2546 5127fd58 2021-12-17 jrmu $SaveProperties;
2547 5127fd58 2021-12-17 jrmu if (!$EnablePost) return;
2548 5127fd58 2021-12-17 jrmu $text = PPRA($SaveAttrPatterns, $new['text']);
2549 5127fd58 2021-12-17 jrmu $LinkTargets = array();
2550 5127fd58 2021-12-17 jrmu $new['=html'] = MarkupToHTML($pagename,$text);
2551 5127fd58 2021-12-17 jrmu $new['targets'] = implode(',',array_keys((array)$LinkTargets));
2552 5127fd58 2021-12-17 jrmu $p = & $PCache[$pagename];
2553 5127fd58 2021-12-17 jrmu foreach((array)$SaveProperties as $k) {
2554 5127fd58 2021-12-17 jrmu if (@$p["=p_$k"]) $new[$k] = $p["=p_$k"];
2555 5127fd58 2021-12-17 jrmu else unset($new[$k]);
2556 5127fd58 2021-12-17 jrmu }
2557 5127fd58 2021-12-17 jrmu unset($new['excerpt']);
2558 5127fd58 2021-12-17 jrmu }
2559 5127fd58 2021-12-17 jrmu
2560 5127fd58 2021-12-17 jrmu function PostPage($pagename, &$page, &$new) {
2561 5127fd58 2021-12-17 jrmu global $DiffKeepDays, $DiffFunction, $DeleteKeyPattern, $EnablePost,
2562 5127fd58 2021-12-17 jrmu $Now, $Charset, $Author, $WikiDir, $IsPagePosted, $DiffKeepNum;
2563 5127fd58 2021-12-17 jrmu SDV($DiffKeepDays,3650);
2564 5127fd58 2021-12-17 jrmu SDV($DiffKeepNum,20);
2565 5127fd58 2021-12-17 jrmu SDV($DeleteKeyPattern,"^\\s*delete\\s*$");
2566 5127fd58 2021-12-17 jrmu $IsPagePosted = false;
2567 fc91d0f1 2023-03-07 jrmu if (!$EnablePost) return;
2568 fc91d0f1 2023-03-07 jrmu if (preg_match("/$DeleteKeyPattern/",$new['text'])) {
2569 fc91d0f1 2023-03-07 jrmu if (@$new['passwdattr']>'' && !CondAuth($pagename, 'attr'))
2570 fc91d0f1 2023-03-07 jrmu Abort('$[The page has an "attr" attribute and cannot be deleted.]');
2571 fc91d0f1 2023-03-07 jrmu else $WikiDir->delete($pagename);
2572 5127fd58 2021-12-17 jrmu $IsPagePosted = true;
2573 fc91d0f1 2023-03-07 jrmu return;
2574 5127fd58 2021-12-17 jrmu }
2575 fc91d0f1 2023-03-07 jrmu $new['charset'] = $Charset; # kept for now, may be needed if custom PageStore
2576 fc91d0f1 2023-03-07 jrmu $new['author'] = @$Author;
2577 fc91d0f1 2023-03-07 jrmu $new["author:$Now"] = @$Author;
2578 fc91d0f1 2023-03-07 jrmu $new["host:$Now"] = strval(@$_SERVER['REMOTE_ADDR']);
2579 fc91d0f1 2023-03-07 jrmu $diffclass = preg_replace('/\\W/','',strval(@$_POST['diffclass']));
2580 fc91d0f1 2023-03-07 jrmu if ($page['time']>0 && function_exists(@$DiffFunction))
2581 fc91d0f1 2023-03-07 jrmu $new["diff:$Now:{$page['time']}:$diffclass"] =
2582 fc91d0f1 2023-03-07 jrmu $DiffFunction($new['text'],@$page['text']);
2583 fc91d0f1 2023-03-07 jrmu $keepgmt = $Now-$DiffKeepDays * 86400;
2584 fc91d0f1 2023-03-07 jrmu $keepnum = array();
2585 fc91d0f1 2023-03-07 jrmu $keys = array_keys($new);
2586 fc91d0f1 2023-03-07 jrmu foreach($keys as $k)
2587 fc91d0f1 2023-03-07 jrmu if (preg_match("/^\\w+:(\\d+)/",$k,$match)) {
2588 fc91d0f1 2023-03-07 jrmu $keepnum[$match[1]] = 1;
2589 fc91d0f1 2023-03-07 jrmu if (count($keepnum)>$DiffKeepNum && $match[1]<$keepgmt)
2590 fc91d0f1 2023-03-07 jrmu unset($new[$k]);
2591 fc91d0f1 2023-03-07 jrmu }
2592 fc91d0f1 2023-03-07 jrmu WritePage($pagename,$new);
2593 fc91d0f1 2023-03-07 jrmu $IsPagePosted = true;
2594 5127fd58 2021-12-17 jrmu }
2595 5127fd58 2021-12-17 jrmu
2596 5127fd58 2021-12-17 jrmu function PostRecentChanges($pagename,$page,$new,$Fmt=null) {
2597 5127fd58 2021-12-17 jrmu global $IsPagePosted, $RecentChangesFmt, $RCDelimPattern, $RCLinesMax,
2598 fc91d0f1 2023-03-07 jrmu $EnableRCDiffBytes, $Now, $EnableLocalTimes;
2599 5127fd58 2021-12-17 jrmu if (!$IsPagePosted && $Fmt==null) return;
2600 fc91d0f1 2023-03-07 jrmu if (is_null($Fmt)) $Fmt = $RecentChangesFmt;
2601 5127fd58 2021-12-17 jrmu foreach($Fmt as $rcfmt=>$pgfmt) {
2602 5127fd58 2021-12-17 jrmu $rcname = FmtPageName($rcfmt,$pagename); if (!$rcname) continue;
2603 5127fd58 2021-12-17 jrmu $pgtext = FmtPageName($pgfmt,$pagename); if (!$pgtext) continue;
2604 5127fd58 2021-12-17 jrmu if (@$seen[$rcname]++) continue;
2605 5127fd58 2021-12-17 jrmu
2606 5127fd58 2021-12-17 jrmu if (IsEnabled($EnableRCDiffBytes, 0)) {
2607 5127fd58 2021-12-17 jrmu $pgtext = PPRA(array(
2608 5127fd58 2021-12-17 jrmu '/\\(([+-])(\\d+)\\)(\\s*=\\]\\s*)$/'=>'$3%diffmarkup%{$1($1$2)$1}%%',
2609 5127fd58 2021-12-17 jrmu '/\\(\\+(0\\)\\+\\}%%)$/'=>'(&#177;$1'), $pgtext);
2610 5127fd58 2021-12-17 jrmu }
2611 5127fd58 2021-12-17 jrmu $rcpage = ReadPage($rcname);
2612 5127fd58 2021-12-17 jrmu $rcelim = preg_quote(preg_replace("/$RCDelimPattern.*$/",' ',$pgtext),'/');
2613 5127fd58 2021-12-17 jrmu $rcpage['text'] = preg_replace("/^.*$rcelim.*\n/m", '', @$rcpage['text']);
2614 5127fd58 2021-12-17 jrmu if (!preg_match("/$RCDelimPattern/",$rcpage['text']))
2615 5127fd58 2021-12-17 jrmu $rcpage['text'] .= "$pgtext\n";
2616 5127fd58 2021-12-17 jrmu else
2617 5127fd58 2021-12-17 jrmu $rcpage['text'] = preg_replace("/([^\n]*$RCDelimPattern.*\n)/",
2618 5127fd58 2021-12-17 jrmu str_replace("$", "\\$", $pgtext) . "\n$1", $rcpage['text'], 1);
2619 5127fd58 2021-12-17 jrmu if (@$RCLinesMax > 0)
2620 5127fd58 2021-12-17 jrmu $rcpage['text'] = implode("\n", array_slice(
2621 5127fd58 2021-12-17 jrmu explode("\n", $rcpage['text'], $RCLinesMax + 1), 0, $RCLinesMax));
2622 5127fd58 2021-12-17 jrmu WritePage($rcname, $rcpage);
2623 5127fd58 2021-12-17 jrmu }
2624 5127fd58 2021-12-17 jrmu }
2625 5127fd58 2021-12-17 jrmu
2626 5127fd58 2021-12-17 jrmu function AutoCreateTargets($pagename, &$page, &$new) {
2627 5127fd58 2021-12-17 jrmu global $IsPagePosted, $AutoCreate, $LinkTargets;
2628 5127fd58 2021-12-17 jrmu if (!$IsPagePosted) return;
2629 5127fd58 2021-12-17 jrmu foreach((array)@$AutoCreate as $pat => $init) {
2630 5127fd58 2021-12-17 jrmu if (is_null($init)) continue;
2631 5127fd58 2021-12-17 jrmu foreach(preg_grep($pat, array_keys((array)@$LinkTargets)) as $aname) {
2632 5127fd58 2021-12-17 jrmu if (PageExists($aname)) continue;
2633 5127fd58 2021-12-17 jrmu $x = RetrieveAuthPage($aname, 'edit', false, READPAGE_CURRENT);
2634 5127fd58 2021-12-17 jrmu if (!$x) continue;
2635 5127fd58 2021-12-17 jrmu WritePage($aname, $init);
2636 5127fd58 2021-12-17 jrmu }
2637 5127fd58 2021-12-17 jrmu }
2638 5127fd58 2021-12-17 jrmu }
2639 5127fd58 2021-12-17 jrmu
2640 5127fd58 2021-12-17 jrmu function PreviewPage($pagename,&$page,&$new) {
2641 fc91d0f1 2023-03-07 jrmu global $IsPageSaved, $FmtV, $ROSPatterns, $PCache,
2642 fc91d0f1 2023-03-07 jrmu $HTMLStylesFmt, $IncludedPages, $EnableListIncludedPages;
2643 fc91d0f1 2023-03-07 jrmu $text = ProcessROESPatterns($new['text'], $ROSPatterns);
2644 fc91d0f1 2023-03-07 jrmu $text = '(:groupheader:)'.$text.'(:groupfooter:)';
2645 fc91d0f1 2023-03-07 jrmu $IncludedPages = array();
2646 fc91d0f1 2023-03-07 jrmu $preview = MarkupToHTML($pagename,$text);
2647 fc91d0f1 2023-03-07 jrmu $incp = array_diff(array_keys($IncludedPages), array($pagename));
2648 fc91d0f1 2023-03-07 jrmu $cnt = count($incp);
2649 fc91d0f1 2023-03-07 jrmu if (IsEnabled($EnableListIncludedPages,0) && $cnt) {
2650 fc91d0f1 2023-03-07 jrmu $label = XL('Text or data included from other pages');
2651 fc91d0f1 2023-03-07 jrmu $edit = XL('Edit');
2652 fc91d0f1 2023-03-07 jrmu SDV($HTMLStylesFmt['inclpages'], 'details.inclpages {display: inline-block;}');
2653 fc91d0f1 2023-03-07 jrmu $out = "<br/><details class='inclpages'>"
2654 fc91d0f1 2023-03-07 jrmu . "<summary>($cnt) $label</summary><ul>\n";
2655 fc91d0f1 2023-03-07 jrmu sort($incp);
2656 fc91d0f1 2023-03-07 jrmu foreach($incp as $pn) {
2657 fc91d0f1 2023-03-07 jrmu $url = PageVar($pn, '$PageUrl');
2658 fc91d0f1 2023-03-07 jrmu $out .= "<li> <a class='wikilink' href='$url'>$pn</a>
2659 fc91d0f1 2023-03-07 jrmu (<a class='wikilink' href='$url?action=edit'>$edit</a>)</li>\n";
2660 fc91d0f1 2023-03-07 jrmu }
2661 fc91d0f1 2023-03-07 jrmu $out .= "</ul></details>";
2662 fc91d0f1 2023-03-07 jrmu $FmtV['$IncludedPages'] = $out;
2663 fc91d0f1 2023-03-07 jrmu }
2664 fc91d0f1 2023-03-07 jrmu else $FmtV['$IncludedPages'] = '';
2665 5127fd58 2021-12-17 jrmu if (@$_REQUEST['preview']) {
2666 fc91d0f1 2023-03-07 jrmu $FmtV['$PreviewText'] = $preview;
2667 5127fd58 2021-12-17 jrmu }
2668 5127fd58 2021-12-17 jrmu }
2669 5127fd58 2021-12-17 jrmu
2670 5127fd58 2021-12-17 jrmu function HandleEdit($pagename, $auth = 'edit') {
2671 fc91d0f1 2023-03-07 jrmu global $IsPagePosted, $EditFields, $ChangeSummary, $EditFunctions,
2672 5127fd58 2021-12-17 jrmu $EnablePost, $FmtV, $Now, $EditRedirectFmt, $EnableRCDiffBytes,
2673 5127fd58 2021-12-17 jrmu $PageEditForm, $HandleEditFmt, $PageStartFmt, $PageEditFmt, $PageEndFmt;
2674 5127fd58 2021-12-17 jrmu SDV($EditRedirectFmt, '$FullName');
2675 5127fd58 2021-12-17 jrmu if (@$_POST['cancel'])
2676 5127fd58 2021-12-17 jrmu { Redirect(FmtPageName($EditRedirectFmt, $pagename)); return; }
2677 5127fd58 2021-12-17 jrmu Lock(2);
2678 5127fd58 2021-12-17 jrmu $page = RetrieveAuthPage($pagename, $auth, true);
2679 5127fd58 2021-12-17 jrmu if (!$page) Abort("?cannot edit $pagename");
2680 5127fd58 2021-12-17 jrmu $new = $page;
2681 5127fd58 2021-12-17 jrmu foreach((array)$EditFields as $k)
2682 5127fd58 2021-12-17 jrmu if (isset($_POST[$k])) $new[$k]=str_replace("\r",'',stripmagic($_POST[$k]));
2683 5127fd58 2021-12-17 jrmu
2684 5127fd58 2021-12-17 jrmu if (IsEnabled($EnableRCDiffBytes, 0) && isset($new['text'])) {
2685 fc91d0f1 2023-03-07 jrmu $bytes = strlen($new['text']) - strlen(strval(@$page['text']));
2686 5127fd58 2021-12-17 jrmu if ($bytes>=0) $bytes = "+$bytes";
2687 5127fd58 2021-12-17 jrmu $ChangeSummary = rtrim($ChangeSummary) . " ($bytes)";
2688 5127fd58 2021-12-17 jrmu }
2689 5127fd58 2021-12-17 jrmu $new['csum'] = $ChangeSummary;
2690 5127fd58 2021-12-17 jrmu if ($ChangeSummary) $new["csum:$Now"] = $ChangeSummary;
2691 fc91d0f1 2023-03-07 jrmu $EnablePost &= (bool)preg_grep('/^post/', array_keys(@$_POST));
2692 5127fd58 2021-12-17 jrmu $new['=preview'] = @$new['text'];
2693 5127fd58 2021-12-17 jrmu PCache($pagename, $new);
2694 5127fd58 2021-12-17 jrmu UpdatePage($pagename, $page, $new);
2695 5127fd58 2021-12-17 jrmu Lock(0);
2696 5127fd58 2021-12-17 jrmu if ($IsPagePosted && !@$_POST['postedit'])
2697 5127fd58 2021-12-17 jrmu { Redirect(FmtPageName($EditRedirectFmt, $pagename)); return; }
2698 5127fd58 2021-12-17 jrmu $FmtV['$DiffClassMinor'] =
2699 5127fd58 2021-12-17 jrmu (@$_POST['diffclass']=='minor') ? "checked='checked'" : '';
2700 5127fd58 2021-12-17 jrmu $FmtV['$EditText'] =
2701 5127fd58 2021-12-17 jrmu str_replace('$','&#036;',PHSC(@$new['text'],ENT_NOQUOTES));
2702 5127fd58 2021-12-17 jrmu $FmtV['$EditBaseTime'] = $Now;
2703 fc91d0f1 2023-03-07 jrmu $FmtV['$TokenValue'] = pmtoken();
2704 5127fd58 2021-12-17 jrmu if (@$PageEditForm) {
2705 5127fd58 2021-12-17 jrmu $efpage = FmtPageName($PageEditForm, $pagename);
2706 5127fd58 2021-12-17 jrmu $form = RetrieveAuthPage($efpage, 'read', false, READPAGE_CURRENT);
2707 5127fd58 2021-12-17 jrmu if (!$form || !@$form['text'])
2708 5127fd58 2021-12-17 jrmu Abort("?unable to retrieve edit form $efpage", 'editform');
2709 5127fd58 2021-12-17 jrmu $FmtV['$EditForm'] = MarkupToHTML($pagename, $form['text']);
2710 5127fd58 2021-12-17 jrmu }
2711 5127fd58 2021-12-17 jrmu SDV($PageEditFmt, "<div id='wikiedit'>
2712 5127fd58 2021-12-17 jrmu <h2 class='wikiaction'>$[Editing {\$FullName}]</h2>
2713 5127fd58 2021-12-17 jrmu <form method='post' rel='nofollow' action='\$PageUrl?action=edit'>
2714 5127fd58 2021-12-17 jrmu <input type='hidden' name='action' value='edit' />
2715 5127fd58 2021-12-17 jrmu <input type='hidden' name='n' value='\$FullName' />
2716 5127fd58 2021-12-17 jrmu <input type='hidden' name='basetime' value='\$EditBaseTime' />
2717 fc91d0f1 2023-03-07 jrmu <input type='hidden' name='\$TokenName' value='\$TokenValue' />
2718 5127fd58 2021-12-17 jrmu \$EditMessageFmt
2719 5127fd58 2021-12-17 jrmu <textarea id='text' name='text' rows='25' cols='60'
2720 5127fd58 2021-12-17 jrmu >\$EditText</textarea><br />
2721 5127fd58 2021-12-17 jrmu <input type='submit' name='post' value=' $[Save] ' />");
2722 5127fd58 2021-12-17 jrmu SDV($HandleEditFmt, array(&$PageStartFmt, &$PageEditFmt, &$PageEndFmt));
2723 5127fd58 2021-12-17 jrmu PrintFmt($pagename, $HandleEditFmt);
2724 5127fd58 2021-12-17 jrmu }
2725 5127fd58 2021-12-17 jrmu
2726 5127fd58 2021-12-17 jrmu function HandleSource($pagename, $auth = 'read') {
2727 5127fd58 2021-12-17 jrmu global $HTTPHeaders;
2728 5127fd58 2021-12-17 jrmu $page = RetrieveAuthPage($pagename, $auth, true, READPAGE_CURRENT);
2729 5127fd58 2021-12-17 jrmu if (!$page) Abort("?cannot source $pagename");
2730 5127fd58 2021-12-17 jrmu foreach ($HTTPHeaders as $h) {
2731 5127fd58 2021-12-17 jrmu $h = preg_replace('!^Content-type:\\s+text/html!i',
2732 5127fd58 2021-12-17 jrmu 'Content-type: text/plain', $h);
2733 5127fd58 2021-12-17 jrmu header($h);
2734 5127fd58 2021-12-17 jrmu }
2735 5127fd58 2021-12-17 jrmu echo @$page['text'];
2736 5127fd58 2021-12-17 jrmu }
2737 5127fd58 2021-12-17 jrmu
2738 5127fd58 2021-12-17 jrmu ## PmWikiAuth provides password-protection of pages using PHP sessions.
2739 5127fd58 2021-12-17 jrmu ## It is normally called from RetrieveAuthPage. Since RetrieveAuthPage
2740 5127fd58 2021-12-17 jrmu ## can be called a lot within a single page execution (i.e., for every
2741 5127fd58 2021-12-17 jrmu ## page accessed), we cache the results of site passwords and
2742 5127fd58 2021-12-17 jrmu ## GroupAttribute pages to be able to speed up subsequent calls.
2743 5127fd58 2021-12-17 jrmu function PmWikiAuth($pagename, $level, $authprompt=true, $since=0) {
2744 5127fd58 2021-12-17 jrmu global $DefaultPasswords, $GroupAttributesFmt, $AllowPassword,
2745 fc91d0f1 2023-03-07 jrmu $AuthCascade, $AuthId, $AuthList, $NoHTMLCache;
2746 5127fd58 2021-12-17 jrmu static $acache;
2747 5127fd58 2021-12-17 jrmu SDV($GroupAttributesFmt,'$Group/GroupAttributes');
2748 5127fd58 2021-12-17 jrmu SDV($AllowPassword,'nopass');
2749 5127fd58 2021-12-17 jrmu $page = ReadPage($pagename, $since);
2750 5127fd58 2021-12-17 jrmu if (!$page) { return false; }
2751 5127fd58 2021-12-17 jrmu if (!isset($acache))
2752 5127fd58 2021-12-17 jrmu SessionAuth($pagename, (@$_POST['authpw'])
2753 5127fd58 2021-12-17 jrmu ? array('authpw' => array($_POST['authpw'] => 1))
2754 5127fd58 2021-12-17 jrmu : '');
2755 5127fd58 2021-12-17 jrmu if (@$AuthId) {
2756 5127fd58 2021-12-17 jrmu $AuthList["id:$AuthId"] = 1;
2757 5127fd58 2021-12-17 jrmu $AuthList["id:-$AuthId"] = -1;
2758 5127fd58 2021-12-17 jrmu $AuthList["id:*"] = 1;
2759 5127fd58 2021-12-17 jrmu }
2760 5127fd58 2021-12-17 jrmu ## To allow @_site_edit in GroupAttributes, we cache it first
2761 5127fd58 2021-12-17 jrmu if (!isset($acache['@site'])) {
2762 5127fd58 2021-12-17 jrmu foreach($DefaultPasswords as $k => $v) {
2763 5127fd58 2021-12-17 jrmu $x = array(2, array(), '');
2764 5127fd58 2021-12-17 jrmu $acache['@site'][$k] = IsAuthorized($v, 'site', $x);
2765 5127fd58 2021-12-17 jrmu $AuthList["@_site_$k"] = $acache['@site'][$k][0] ? 1 : 0;
2766 5127fd58 2021-12-17 jrmu }
2767 5127fd58 2021-12-17 jrmu }
2768 5127fd58 2021-12-17 jrmu $gn = FmtPageName($GroupAttributesFmt, $pagename);
2769 5127fd58 2021-12-17 jrmu if (!isset($acache[$gn])) {
2770 5127fd58 2021-12-17 jrmu $gp = ReadPage($gn, READPAGE_CURRENT);
2771 5127fd58 2021-12-17 jrmu foreach($DefaultPasswords as $k => $v) {
2772 5127fd58 2021-12-17 jrmu $acache[$gn][$k] = IsAuthorized(@$gp["passwd$k"], 'group',
2773 5127fd58 2021-12-17 jrmu $acache['@site'][$k]);
2774 5127fd58 2021-12-17 jrmu }
2775 5127fd58 2021-12-17 jrmu }
2776 5127fd58 2021-12-17 jrmu foreach($DefaultPasswords as $k => $v)
2777 5127fd58 2021-12-17 jrmu list($page['=auth'][$k], $page['=passwd'][$k], $page['=pwsource'][$k]) =
2778 5127fd58 2021-12-17 jrmu IsAuthorized(@$page["passwd$k"], 'page', $acache[$gn][$k]);
2779 5127fd58 2021-12-17 jrmu foreach($AuthCascade as $k => $t) {
2780 5127fd58 2021-12-17 jrmu if ($page['=auth'][$k]+0 == 2) {
2781 5127fd58 2021-12-17 jrmu $page['=auth'][$k] = $page['=auth'][$t];
2782 5127fd58 2021-12-17 jrmu if ($page['=passwd'][$k] = $page['=passwd'][$t]) # assign
2783 5127fd58 2021-12-17 jrmu $page['=pwsource'][$k] = "cascade:$t";
2784 5127fd58 2021-12-17 jrmu }
2785 5127fd58 2021-12-17 jrmu }
2786 5127fd58 2021-12-17 jrmu if (@$page['=auth']['admin'])
2787 5127fd58 2021-12-17 jrmu foreach($page['=auth'] as $lv=>$a) @$page['=auth'][$lv] = 3;
2788 5127fd58 2021-12-17 jrmu if (@$page['=passwd']['read']) $NoHTMLCache |= 2;
2789 5127fd58 2021-12-17 jrmu if ($level=='ALWAYS' || @$page['=auth'][$level]) return $page;
2790 5127fd58 2021-12-17 jrmu if (!$authprompt) return false;
2791 5127fd58 2021-12-17 jrmu $GLOBALS['AuthNeeded'] = (@$_POST['authpw'])
2792 5127fd58 2021-12-17 jrmu ? $page['=pwsource'][$level] . ' ' . $level : '';
2793 5127fd58 2021-12-17 jrmu PCache($pagename, $page);
2794 fc91d0f1 2023-03-07 jrmu PrintAuthForm($pagename);
2795 fc91d0f1 2023-03-07 jrmu exit;
2796 fc91d0f1 2023-03-07 jrmu }
2797 fc91d0f1 2023-03-07 jrmu
2798 fc91d0f1 2023-03-07 jrmu ## Split from PmWikiAuth to allow for recipes to call it
2799 fc91d0f1 2023-03-07 jrmu function PrintAuthForm($pagename) {
2800 fc91d0f1 2023-03-07 jrmu global $FmtV, $AuthPromptFmt, $PageStartFmt, $PageEndFmt;
2801 5127fd58 2021-12-17 jrmu $postvars = '';
2802 5127fd58 2021-12-17 jrmu foreach($_POST as $k=>$v) {
2803 5127fd58 2021-12-17 jrmu if ($k == 'authpw' || $k == 'authid') continue;
2804 5127fd58 2021-12-17 jrmu $k = PHSC(stripmagic($k), ENT_QUOTES);
2805 5127fd58 2021-12-17 jrmu if (is_array($v)) {
2806 5127fd58 2021-12-17 jrmu foreach($v as $vk=>$vv) {
2807 5127fd58 2021-12-17 jrmu $vk = PHSC(stripmagic($vk), ENT_QUOTES);
2808 5127fd58 2021-12-17 jrmu $vv = str_replace('$', '&#036;',
2809 5127fd58 2021-12-17 jrmu PHSC(stripmagic($vv), ENT_COMPAT));
2810 5127fd58 2021-12-17 jrmu $postvars .= "<input type='hidden' name='{$k}[{$vk}]' value=\"$vv\" />\n";
2811 5127fd58 2021-12-17 jrmu }
2812 5127fd58 2021-12-17 jrmu }
2813 5127fd58 2021-12-17 jrmu else {
2814 5127fd58 2021-12-17 jrmu $v = str_replace('$', '&#036;',
2815 5127fd58 2021-12-17 jrmu PHSC(stripmagic($v), ENT_COMPAT));
2816 5127fd58 2021-12-17 jrmu $postvars .= "<input type='hidden' name='$k' value=\"$v\" />\n";
2817 5127fd58 2021-12-17 jrmu }
2818 5127fd58 2021-12-17 jrmu }
2819 5127fd58 2021-12-17 jrmu $FmtV['$PostVars'] = $postvars;
2820 fc91d0f1 2023-03-07 jrmu $r = str_replace("'", '%37', stripmagic(strval(@$_SERVER['REQUEST_URI'])));
2821 5127fd58 2021-12-17 jrmu SDV($AuthPromptFmt,array(&$PageStartFmt,
2822 5127fd58 2021-12-17 jrmu "<p><b>$[Password required]</b></p>
2823 5127fd58 2021-12-17 jrmu <form name='authform' action='$r' method='post'>
2824 5127fd58 2021-12-17 jrmu $[Password]: <input tabindex='1' type='password' name='authpw'
2825 fc91d0f1 2023-03-07 jrmu value='' autofocus='autofocus' />
2826 fc91d0f1 2023-03-07 jrmu <input type='submit' value='$[OK]' />\$PostVars</form>", &$PageEndFmt));
2827 5127fd58 2021-12-17 jrmu PrintFmt($pagename,$AuthPromptFmt);
2828 5127fd58 2021-12-17 jrmu exit;
2829 5127fd58 2021-12-17 jrmu }
2830 5127fd58 2021-12-17 jrmu
2831 fc91d0f1 2023-03-07 jrmu
2832 5127fd58 2021-12-17 jrmu function IsAuthorized($chal, $source, &$from) {
2833 5127fd58 2021-12-17 jrmu global $AuthList, $AuthPw, $AllowPassword;
2834 5127fd58 2021-12-17 jrmu if (!$chal) return $from;
2835 5127fd58 2021-12-17 jrmu $auth = 0;
2836 5127fd58 2021-12-17 jrmu $passwd = array();
2837 5127fd58 2021-12-17 jrmu foreach((array)$chal as $c) {
2838 5127fd58 2021-12-17 jrmu $x = '';
2839 5127fd58 2021-12-17 jrmu $pwchal = preg_split('/([, ]|\\w+:)/', $c, -1, PREG_SPLIT_DELIM_CAPTURE);
2840 5127fd58 2021-12-17 jrmu foreach($pwchal as $pw) {
2841 5127fd58 2021-12-17 jrmu if ($pw == ',' || $pw == '') continue;
2842 5127fd58 2021-12-17 jrmu else if ($pw == ' ') { $x = ''; continue; }
2843 5127fd58 2021-12-17 jrmu else if (substr($pw, -1, 1) == ':') { $x = $pw; continue; }
2844 5127fd58 2021-12-17 jrmu else if ($pw[0] != '@' && $x > '') $pw = $x . $pw;
2845 5127fd58 2021-12-17 jrmu if (!$pw) continue;
2846 5127fd58 2021-12-17 jrmu $passwd[] = $pw;
2847 5127fd58 2021-12-17 jrmu if ($auth < 0) continue;
2848 5127fd58 2021-12-17 jrmu if ($x || $pw[0] == '@') {
2849 5127fd58 2021-12-17 jrmu if (@$AuthList[$pw]) $auth = $AuthList[$pw];
2850 5127fd58 2021-12-17 jrmu continue;
2851 5127fd58 2021-12-17 jrmu }
2852 5127fd58 2021-12-17 jrmu if ($AllowPassword && pmcrypt($AllowPassword, $pw) == $pw) # nopass
2853 5127fd58 2021-12-17 jrmu { $auth=1; continue; }
2854 5127fd58 2021-12-17 jrmu foreach((array)$AuthPw as $pwresp) # password
2855 5127fd58 2021-12-17 jrmu if (pmcrypt($pwresp, $pw) == $pw) { $auth=1; continue; }
2856 5127fd58 2021-12-17 jrmu }
2857 5127fd58 2021-12-17 jrmu }
2858 5127fd58 2021-12-17 jrmu if (!$passwd) return $from;
2859 5127fd58 2021-12-17 jrmu if ($auth < 0) $auth = 0;
2860 5127fd58 2021-12-17 jrmu return array($auth, $passwd, $source);
2861 5127fd58 2021-12-17 jrmu }
2862 5127fd58 2021-12-17 jrmu
2863 5127fd58 2021-12-17 jrmu
2864 5127fd58 2021-12-17 jrmu ## SessionAuth works with PmWikiAuth to manage authorizations
2865 5127fd58 2021-12-17 jrmu ## as stored in sessions. First, it can be used to set session
2866 5127fd58 2021-12-17 jrmu ## variables by calling it with an $auth argument. It then
2867 5127fd58 2021-12-17 jrmu ## uses the authid, authpw, and authlist session variables
2868 5127fd58 2021-12-17 jrmu ## to set the corresponding values of $AuthId, $AuthPw, and $AuthList
2869 5127fd58 2021-12-17 jrmu ## as needed.
2870 5127fd58 2021-12-17 jrmu function SessionAuth($pagename, $auth = NULL) {
2871 5127fd58 2021-12-17 jrmu global $AuthId, $AuthList, $AuthPw, $SessionEncode, $SessionDecode,
2872 fc91d0f1 2023-03-07 jrmu $EnableSessionPasswords, $EnableAuthPostRegenerateSID;
2873 5127fd58 2021-12-17 jrmu static $called;
2874 5127fd58 2021-12-17 jrmu
2875 5127fd58 2021-12-17 jrmu @$called++;
2876 5127fd58 2021-12-17 jrmu $sn = session_name(); # in PHP5.3, $_REQUEST doesn't contain $_COOKIE
2877 5127fd58 2021-12-17 jrmu if (!$auth && ($called > 1 || (!@$_REQUEST[$sn] && !@$_COOKIE[$sn]))) return;
2878 5127fd58 2021-12-17 jrmu
2879 5127fd58 2021-12-17 jrmu $sid = session_id();
2880 fc91d0f1 2023-03-07 jrmu pm_session_start();
2881 fc91d0f1 2023-03-07 jrmu if ($called == 1 && isset($_POST['authpw']) && $_POST['authpw']
2882 fc91d0f1 2023-03-07 jrmu && IsEnabled($EnableAuthPostRegenerateSID, true) && $sid) {
2883 fc91d0f1 2023-03-07 jrmu @session_regenerate_id();
2884 fc91d0f1 2023-03-07 jrmu }
2885 fc91d0f1 2023-03-07 jrmu
2886 5127fd58 2021-12-17 jrmu foreach((array)$auth as $k => $v) {
2887 5127fd58 2021-12-17 jrmu if ($k == 'authpw') {
2888 5127fd58 2021-12-17 jrmu foreach((array)$v as $pw => $pv) {
2889 5127fd58 2021-12-17 jrmu if ($SessionEncode) $pw = $SessionEncode($pw);
2890 5127fd58 2021-12-17 jrmu $_SESSION[$k][$pw] = $pv;
2891 5127fd58 2021-12-17 jrmu }
2892 5127fd58 2021-12-17 jrmu }
2893 5127fd58 2021-12-17 jrmu else if ($k) $_SESSION[$k] = (array)$v + (array)@$_SESSION[$k];
2894 5127fd58 2021-12-17 jrmu }
2895 5127fd58 2021-12-17 jrmu
2896 fc91d0f1 2023-03-07 jrmu if (!isset($AuthId)) $AuthId = @$_SESSION['authid'] ? @end($_SESSION['authid']) : '';
2897 5127fd58 2021-12-17 jrmu $AuthPw = array_map($SessionDecode, array_keys((array)@$_SESSION['authpw']));
2898 5127fd58 2021-12-17 jrmu if (!IsEnabled($EnableSessionPasswords, 1)) $_SESSION['authpw'] = array();
2899 5127fd58 2021-12-17 jrmu $AuthList = array_merge($AuthList, (array)@$_SESSION['authlist']);
2900 5127fd58 2021-12-17 jrmu
2901 5127fd58 2021-12-17 jrmu if (!$sid) @session_write_close();
2902 5127fd58 2021-12-17 jrmu }
2903 5127fd58 2021-12-17 jrmu
2904 5127fd58 2021-12-17 jrmu
2905 5127fd58 2021-12-17 jrmu function PasswdVar($pagename, $level) {
2906 5127fd58 2021-12-17 jrmu global $PCache, $PasswdVarAuth, $FmtV;
2907 5127fd58 2021-12-17 jrmu $page = $PCache[$pagename];
2908 5127fd58 2021-12-17 jrmu if (!isset($page['=passwd'][$level])) {
2909 5127fd58 2021-12-17 jrmu $page = RetrieveAuthPage($pagename, 'ALWAYS', false, READPAGE_CURRENT);
2910 5127fd58 2021-12-17 jrmu if ($page) PCache($pagename, $page);
2911 5127fd58 2021-12-17 jrmu }
2912 5127fd58 2021-12-17 jrmu SDV($PasswdVarAuth, 'attr');
2913 5127fd58 2021-12-17 jrmu if ($PasswdVarAuth && !@$page['=auth'][$PasswdVarAuth]) return XL('(protected)');
2914 5127fd58 2021-12-17 jrmu $pwsource = $page['=pwsource'][$level];
2915 5127fd58 2021-12-17 jrmu if (strncmp($pwsource, 'cascade:', 8) == 0) {
2916 5127fd58 2021-12-17 jrmu $FmtV['$PWCascade'] = substr($pwsource, 8);
2917 5127fd58 2021-12-17 jrmu return FmtPageName('$[(using $PWCascade password)]', $pagename);
2918 5127fd58 2021-12-17 jrmu }
2919 5127fd58 2021-12-17 jrmu $setting = PHSC(implode(' ', preg_replace('/^(?!@|\\w+:).+$/', '****',
2920 5127fd58 2021-12-17 jrmu (array)$page['=passwd'][$level])));
2921 5127fd58 2021-12-17 jrmu if ($pwsource == 'group' || $pwsource == 'site') {
2922 5127fd58 2021-12-17 jrmu $FmtV['$PWSource'] = $pwsource;
2923 5127fd58 2021-12-17 jrmu $setting = FmtPageName('$[(set by $PWSource)] ', $pagename)
2924 5127fd58 2021-12-17 jrmu . PHSC($setting);
2925 5127fd58 2021-12-17 jrmu }
2926 5127fd58 2021-12-17 jrmu return $setting;
2927 5127fd58 2021-12-17 jrmu }
2928 5127fd58 2021-12-17 jrmu
2929 5127fd58 2021-12-17 jrmu
2930 5127fd58 2021-12-17 jrmu function PrintAttrForm($pagename) {
2931 5127fd58 2021-12-17 jrmu global $PageAttributes, $PCache, $FmtV;
2932 fc91d0f1 2023-03-07 jrmu $FmtV['$TokenValue'] = pmtoken();
2933 5127fd58 2021-12-17 jrmu echo FmtPageName("<form action='\$PageUrl' method='post'>
2934 5127fd58 2021-12-17 jrmu <input type='hidden' name='action' value='postattr' />
2935 fc91d0f1 2023-03-07 jrmu <input type='hidden' name='\$TokenName' value='\$TokenValue' />
2936 5127fd58 2021-12-17 jrmu <input type='hidden' name='n' value='\$FullName' />
2937 5127fd58 2021-12-17 jrmu <table>",$pagename);
2938 5127fd58 2021-12-17 jrmu $page = $PCache[$pagename];
2939 5127fd58 2021-12-17 jrmu foreach($PageAttributes as $attr=>$p) {
2940 5127fd58 2021-12-17 jrmu if (!$p) continue;
2941 5127fd58 2021-12-17 jrmu if (strncmp($attr, 'passwd', 6) == 0) {
2942 5127fd58 2021-12-17 jrmu $setting = PageVar($pagename, '$Passwd'.ucfirst(substr($attr, 6)));
2943 5127fd58 2021-12-17 jrmu $value = '';
2944 5127fd58 2021-12-17 jrmu } else { $setting = $value = PHSC(@$page[$attr]); }
2945 5127fd58 2021-12-17 jrmu $prompt = FmtPageName($p,$pagename);
2946 5127fd58 2021-12-17 jrmu echo "<tr><td>$prompt</td>
2947 5127fd58 2021-12-17 jrmu <td><input type='text' name='$attr' value='$value' /></td>
2948 5127fd58 2021-12-17 jrmu <td>$setting</td></tr>";
2949 5127fd58 2021-12-17 jrmu }
2950 5127fd58 2021-12-17 jrmu echo FmtPageName("</table><input type='submit' value='$[Save]' /></form>",
2951 5127fd58 2021-12-17 jrmu $pagename);
2952 5127fd58 2021-12-17 jrmu }
2953 5127fd58 2021-12-17 jrmu
2954 5127fd58 2021-12-17 jrmu function HandleAttr($pagename, $auth = 'attr') {
2955 5127fd58 2021-12-17 jrmu global $HandleAttrFmt,$PageAttrFmt,$PageStartFmt,$PageEndFmt;
2956 5127fd58 2021-12-17 jrmu $page = RetrieveAuthPage($pagename, $auth, true, READPAGE_CURRENT);
2957 5127fd58 2021-12-17 jrmu if (!$page) { Abort("?unable to read $pagename"); }
2958 5127fd58 2021-12-17 jrmu PCache($pagename,$page);
2959 5127fd58 2021-12-17 jrmu XLSDV('en', array('EnterAttributes' =>
2960 5127fd58 2021-12-17 jrmu "Enter new attributes for this page below. Leaving a field blank
2961 5127fd58 2021-12-17 jrmu will leave the attribute unchanged. To clear an attribute, enter
2962 5127fd58 2021-12-17 jrmu 'clear'."));
2963 5127fd58 2021-12-17 jrmu SDV($PageAttrFmt,"<div class='wikiattr'>
2964 5127fd58 2021-12-17 jrmu <h2 class='wikiaction'>$[{\$FullName} Attributes]</h2>
2965 5127fd58 2021-12-17 jrmu <p>$[EnterAttributes]</p></div>");
2966 5127fd58 2021-12-17 jrmu SDV($HandleAttrFmt,array(&$PageStartFmt,&$PageAttrFmt,
2967 5127fd58 2021-12-17 jrmu 'function:PrintAttrForm',&$PageEndFmt));
2968 5127fd58 2021-12-17 jrmu PrintFmt($pagename,$HandleAttrFmt);
2969 5127fd58 2021-12-17 jrmu }
2970 5127fd58 2021-12-17 jrmu
2971 5127fd58 2021-12-17 jrmu function HandlePostAttr($pagename, $auth = 'attr') {
2972 5127fd58 2021-12-17 jrmu global $PageAttributes, $EnablePostAttrClearSession;
2973 fc91d0f1 2023-03-07 jrmu if (! AutoCheckToken()) {
2974 fc91d0f1 2023-03-07 jrmu Abort('? $[Token invalid or missing.]');
2975 fc91d0f1 2023-03-07 jrmu }
2976 5127fd58 2021-12-17 jrmu Lock(2);
2977 5127fd58 2021-12-17 jrmu $page = RetrieveAuthPage($pagename, $auth, true);
2978 5127fd58 2021-12-17 jrmu if (!$page) { Abort("?unable to read $pagename"); }
2979 5127fd58 2021-12-17 jrmu foreach($PageAttributes as $attr=>$p) {
2980 5127fd58 2021-12-17 jrmu $v = stripmagic(@$_POST[$attr]);
2981 5127fd58 2021-12-17 jrmu if ($v == '') continue;
2982 5127fd58 2021-12-17 jrmu if ($v=='clear') unset($page[$attr]);
2983 5127fd58 2021-12-17 jrmu else if (strncmp($attr, 'passwd', 6) != 0) $page[$attr] = $v;
2984 5127fd58 2021-12-17 jrmu else {
2985 5127fd58 2021-12-17 jrmu $a = array();
2986 5127fd58 2021-12-17 jrmu preg_match_all('/"[^"]*"|\'[^\']*\'|\\S+/', $v, $match);
2987 5127fd58 2021-12-17 jrmu foreach($match[0] as $pw)
2988 5127fd58 2021-12-17 jrmu $a[] = preg_match('/^(@|\\w+:)/', $pw) ? $pw
2989 5127fd58 2021-12-17 jrmu : pmcrypt(preg_replace('/^([\'"])(.*)\\1$/', '$2', $pw));
2990 5127fd58 2021-12-17 jrmu if ($a) $page[$attr] = implode(' ',$a);
2991 5127fd58 2021-12-17 jrmu }
2992 5127fd58 2021-12-17 jrmu }
2993 5127fd58 2021-12-17 jrmu WritePage($pagename,$page);
2994 5127fd58 2021-12-17 jrmu Lock(0);
2995 5127fd58 2021-12-17 jrmu if (IsEnabled($EnablePostAttrClearSession, 1)) {
2996 fc91d0f1 2023-03-07 jrmu pm_session_start();
2997 5127fd58 2021-12-17 jrmu unset($_SESSION['authid']);
2998 5127fd58 2021-12-17 jrmu unset($_SESSION['authlist']);
2999 5127fd58 2021-12-17 jrmu $_SESSION['authpw'] = array();
3000 5127fd58 2021-12-17 jrmu }
3001 5127fd58 2021-12-17 jrmu Redirect($pagename);
3002 5127fd58 2021-12-17 jrmu exit;
3003 5127fd58 2021-12-17 jrmu }
3004 5127fd58 2021-12-17 jrmu
3005 5127fd58 2021-12-17 jrmu
3006 5127fd58 2021-12-17 jrmu function HandleLogoutA($pagename, $auth = 'read') {
3007 5127fd58 2021-12-17 jrmu global $LogoutRedirectFmt, $LogoutCookies;
3008 5127fd58 2021-12-17 jrmu SDV($LogoutRedirectFmt, '$FullName');
3009 5127fd58 2021-12-17 jrmu SDV($LogoutCookies, array());
3010 fc91d0f1 2023-03-07 jrmu pm_session_start();
3011 5127fd58 2021-12-17 jrmu $_SESSION = array();
3012 5127fd58 2021-12-17 jrmu if ( session_id() != '' || isset($_COOKIE[session_name()]) )
3013 5127fd58 2021-12-17 jrmu pmsetcookie(session_name(), '', time()-43200, '/');
3014 5127fd58 2021-12-17 jrmu foreach ($LogoutCookies as $c)
3015 5127fd58 2021-12-17 jrmu if (isset($_COOKIE[$c])) pmsetcookie($c, '', time()-43200, '/');
3016 5127fd58 2021-12-17 jrmu session_destroy();
3017 5127fd58 2021-12-17 jrmu Redirect(FmtPageName($LogoutRedirectFmt, $pagename));
3018 5127fd58 2021-12-17 jrmu }
3019 5127fd58 2021-12-17 jrmu
3020 5127fd58 2021-12-17 jrmu
3021 5127fd58 2021-12-17 jrmu function HandleLoginA($pagename, $auth = 'login') {
3022 5127fd58 2021-12-17 jrmu global $AuthId, $DefaultPasswords;
3023 5127fd58 2021-12-17 jrmu unset($DefaultPasswords['admin']);
3024 5127fd58 2021-12-17 jrmu $prompt = @(!$_POST['authpw'] || ($AuthId != $_POST['authid']));
3025 5127fd58 2021-12-17 jrmu $page = RetrieveAuthPage($pagename, $auth, $prompt, READPAGE_CURRENT);
3026 5127fd58 2021-12-17 jrmu Redirect($pagename);
3027 5127fd58 2021-12-17 jrmu }
3028 5127fd58 2021-12-17 jrmu