Blame


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