mirror of
https://github.com/UnickSoft/graphonline.git
synced 2026-02-16 02:30:51 +00:00
first commit
This commit is contained in:
12
wiki/scripts/.htaccess
Executable file
12
wiki/scripts/.htaccess
Executable file
@@ -0,0 +1,12 @@
|
||||
# This file is script/.htaccess -- the default distribution contains this
|
||||
# file to prevent script/ files from being accessed directly by browsers
|
||||
# (this is a potential, albeit very unlikely, security hole).
|
||||
#
|
||||
# If you alter or replace this file, it will likely be overwritten when
|
||||
# you upgrade from one version of PmWiki to another. Be sure to save
|
||||
# a copy of your alterations in another location so you can restore them,
|
||||
# and you might try changing this file to be read-only to prevent a PmWiki
|
||||
# upgrade from overwriting your altered version.
|
||||
|
||||
Order Deny,Allow
|
||||
Deny from all
|
||||
54
wiki/scripts/author.php
Executable file
54
wiki/scripts/author.php
Executable file
@@ -0,0 +1,54 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2013 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script handles author tracking.
|
||||
*/
|
||||
|
||||
SDV($AuthorNameChars, "- '\\w\\x80-\\xff");
|
||||
SDV($AuthorCookie, $CookiePrefix.'author');
|
||||
SDV($AuthorCookieExpires,$Now+60*60*24*30);
|
||||
SDV($AuthorCookieDir,'/');
|
||||
SDV($AuthorGroup,'Profiles');
|
||||
SDV($AuthorRequiredFmt,
|
||||
"<h3 class='wikimessage'>$[An author name is required.]</h3>");
|
||||
Markup('[[~','<links','/\\[\\[~(.*?)\\]\\]/',"[[$AuthorGroup/$1]]");
|
||||
|
||||
$LogoutCookies[] = $AuthorCookie;
|
||||
|
||||
if (!isset($Author)) {
|
||||
if (isset($_POST['author'])) {
|
||||
$x = stripmagic($_POST['author']);
|
||||
setcookie($AuthorCookie, $x, $AuthorCookieExpires, $AuthorCookieDir);
|
||||
} elseif (@$_COOKIE[$AuthorCookie]) {
|
||||
$x = stripmagic(@$_COOKIE[$AuthorCookie]);
|
||||
} else $x = @$AuthId;
|
||||
$Author = PHSC(preg_replace("/[^$AuthorNameChars]/", '', $x),
|
||||
ENT_COMPAT);
|
||||
}
|
||||
if (!isset($AuthorPage)) $AuthorPage =
|
||||
FmtPageName('$AuthorGroup/$Name', MakePageName("$AuthorGroup.$AuthorGroup", $Author));
|
||||
SDV($AuthorLink,($Author) ? "[[~$Author]]" : '?');
|
||||
|
||||
if (IsEnabled($EnableAuthorSignature,1)) {
|
||||
SDVA($ROSPatterns, array(
|
||||
'/(?<!~)~~~~(?!~)/' => "[[~$Author]] $CurrentTime",
|
||||
'/(?<!~)~~~(?!~)/' => "[[~$Author]]",
|
||||
));
|
||||
Markup('~~~~','<[[~','/(?<!~)~~~~(?!~)/',"[[~$Author]] $CurrentTime");
|
||||
Markup('~~~','>~~~~','/(?<!~)~~~(?!~)/',"[[~$Author]]");
|
||||
}
|
||||
if (IsEnabled($EnablePostAuthorRequired,0))
|
||||
array_unshift($EditFunctions,'RequireAuthor');
|
||||
|
||||
## RequireAuthor forces an author to enter a name before posting.
|
||||
function RequireAuthor($pagename, &$page, &$new) {
|
||||
global $Author, $MessagesFmt, $AuthorRequiredFmt, $EnablePost;
|
||||
if (!$Author) {
|
||||
$MessagesFmt[] = $AuthorRequiredFmt;
|
||||
$EnablePost = 0;
|
||||
}
|
||||
}
|
||||
213
wiki/scripts/authuser.php
Executable file
213
wiki/scripts/authuser.php
Executable file
@@ -0,0 +1,213 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2005-2015 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
The APR compatible MD5 encryption algorithm in _crypt() below is
|
||||
based on code Copyright 2005 by D. Faure and the File::Passwd
|
||||
PEAR library module by Mike Wallner <mike@php.net>.
|
||||
|
||||
This script enables simple authentication based on username and
|
||||
password combinations. At present this script can authenticate
|
||||
from passwords held in arrays or in .htpasswd-formatted files,
|
||||
but eventually it will support authentication via sources such
|
||||
as LDAP and Active Directory.
|
||||
|
||||
To configure a .htpasswd-formatted file for authentication, do
|
||||
$AuthUser['htpasswd'] = '/path/to/.htpasswd';
|
||||
prior to including this script.
|
||||
|
||||
Individual username/password combinations can also be placed
|
||||
directly in the $AuthUser array, such as:
|
||||
$AuthUser['pmichaud'] = pmcrypt('secret');
|
||||
|
||||
To authenticate against an LDAP server, put the url for
|
||||
the server in $AuthUser['ldap'], as in:
|
||||
$AuthUser['ldap'] = 'ldap://ldap.example.com/ou=People,o=example?uid';
|
||||
*/
|
||||
|
||||
# let Site.AuthForm know that we're doing user-based authorization
|
||||
$EnableAuthUser = 1;
|
||||
|
||||
if (@$_POST['authid'])
|
||||
AuthUserId($pagename, stripmagic(@$_POST['authid']),
|
||||
stripmagic(@$_POST['authpw']));
|
||||
else SessionAuth($pagename);
|
||||
|
||||
function AuthUserId($pagename, $id, $pw=NULL) {
|
||||
global $AuthUser, $AuthUserPageFmt, $AuthUserFunctions,
|
||||
$AuthId, $MessagesFmt, $AuthUserPat;
|
||||
|
||||
$auth = array();
|
||||
foreach((array)$AuthUser as $k=>$v) $auth[$k] = (array)$v;
|
||||
$authid = '';
|
||||
|
||||
# load information from SiteAdmin.AuthUser (or page in $AuthUserPageFmt)
|
||||
SDV($AuthUserPageFmt, '$SiteAdminGroup.AuthUser');
|
||||
SDVA($AuthUserFunctions, array(
|
||||
'htpasswd' => 'AuthUserHtPasswd',
|
||||
'ldap' => 'AuthUserLDAP',
|
||||
# 'mysql' => 'AuthUserMySQL',
|
||||
$id => 'AuthUserConfig'));
|
||||
|
||||
SDV($AuthUserPat, "/^\\s*([@\\w][^\\s:]*):(.*)/m");
|
||||
$pn = FmtPageName($AuthUserPageFmt, $pagename);
|
||||
$apage = ReadPage($pn, READPAGE_CURRENT);
|
||||
if ($apage && preg_match_all($AuthUserPat,
|
||||
$apage['text'], $matches, PREG_SET_ORDER)) {
|
||||
foreach($matches as $m) {
|
||||
if (!preg_match_all('/\\bldaps?:\\S+|[^\\s,]+/', $m[2], $v))
|
||||
continue;
|
||||
if ($m[1]{0} == '@')
|
||||
foreach($v[0] as $g) $auth[$g][] = $m[1];
|
||||
else $auth[$m[1]] = array_merge((array)@$auth[$m[1]], $v[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (func_num_args()==2) $authid = $id;
|
||||
else
|
||||
foreach($AuthUserFunctions as $k => $fn)
|
||||
if (@$auth[$k] && $fn($pagename, $id, $pw, $auth[$k], $authlist))
|
||||
{ $authid = $id; break; }
|
||||
|
||||
if (!$authid) { $GLOBALS['InvalidLogin'] = 1; return; }
|
||||
if (!isset($AuthId)) $AuthId = $authid;
|
||||
$authlist["id:$authid"] = 1;
|
||||
$authlist["id:-$authid"] = -1;
|
||||
foreach(preg_grep('/^@/', (array)@$auth[$authid]) as $g)
|
||||
$authlist[$g] = 1;
|
||||
foreach(preg_grep('/^@/', (array)@$auth['*']) as $g)
|
||||
$authlist[$g] = 1;
|
||||
foreach(preg_grep('/^@/', array_keys($auth)) as $g) # useless? PITS:01201
|
||||
if (in_array($authid, $auth[$g])) $authlist[$g] = 1;
|
||||
if ($auth['htgroup']) {
|
||||
foreach(AuthUserHtGroup($pagename, $id, $pw, $auth['htgroup']) as $g)
|
||||
$authlist["@$g"] = 1;
|
||||
}
|
||||
foreach(preg_grep('/^@/', (array)@$auth["-$authid"]) as $g)
|
||||
unset($authlist[$g]);
|
||||
SessionAuth($pagename, array('authid' => $authid, 'authlist' => $authlist));
|
||||
}
|
||||
|
||||
|
||||
function AuthUserConfig($pagename, $id, $pw, $pwlist) {
|
||||
foreach ((array)$pwlist as $chal)
|
||||
if (_crypt($pw, $chal) == $chal) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function AuthUserHtPasswd($pagename, $id, $pw, $pwlist) {
|
||||
foreach ((array)$pwlist as $f) {
|
||||
$fp = fopen($f, "r"); if (!$fp) continue;
|
||||
while ($x = fgets($fp, 1024)) {
|
||||
$x = rtrim($x);
|
||||
@list($i, $c, $r) = explode(':', $x, 3);
|
||||
if ($i == $id && _crypt($pw, $c) == $c) { fclose($fp); return true; }
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function AuthUserHtGroup($pagename, $id, $pw, $pwlist) {
|
||||
$groups = array();
|
||||
foreach ((array)$pwlist as $f) {
|
||||
$fp = fopen($f, 'r'); if (!$fp) continue;
|
||||
while ($x = fgets($fp, 4096)) {
|
||||
if (preg_match('/^(\\w[^\\s:]+)\\s*:(.*)$/', trim($x), $match)) {
|
||||
$glist = preg_split('/[\\s,]+/', $match[2], -1, PREG_SPLIT_NO_EMPTY);
|
||||
if (in_array($id, $glist)) $groups[$match[1]] = 1;
|
||||
}
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
return array_keys($groups);
|
||||
}
|
||||
|
||||
|
||||
function AuthUserLDAP($pagename, $id, $pw, $pwlist) {
|
||||
global $AuthLDAPBindDN, $AuthLDAPBindPassword;
|
||||
if (!$pw) return false;
|
||||
if (!function_exists('ldap_connect'))
|
||||
Abort('authuser: LDAP authentication requires PHP ldap functions','ldapfn');
|
||||
foreach ((array)$pwlist as $ldap) {
|
||||
if (!preg_match('!(ldaps?://[^/]+)/(.*)$!', $ldap, $match))
|
||||
continue;
|
||||
## connect to the LDAP server
|
||||
list($z, $url, $path) = $match;
|
||||
$ds = ldap_connect($url);
|
||||
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
## For Active Directory, don't specify a path and we simply
|
||||
## attempt to bind with the username and password directly
|
||||
if (!$path && @ldap_bind($ds, $id, $pw)) { ldap_close($ds); return true; }
|
||||
## Otherwise, we use Apache-style urls for LDAP authentication
|
||||
## Split the path into its search components
|
||||
list($basedn, $attr, $sub, $filter) = explode('?', $path);
|
||||
if (!$attr) $attr = 'uid';
|
||||
if (!$sub) $sub = 'one';
|
||||
if (!$filter) $filter = '(objectClass=*)';
|
||||
$binddn = @$AuthLDAPBindDN;
|
||||
$bindpw = @$AuthLDAPBindPassword;
|
||||
if (ldap_bind($ds, $binddn, $bindpw)) {
|
||||
## Search for the appropriate uid
|
||||
$fn = ($sub == 'sub') ? 'ldap_search' : 'ldap_list';
|
||||
$sr = $fn($ds, $basedn, "(&$filter($attr=$id))", array($attr));
|
||||
$x = ldap_get_entries($ds, $sr);
|
||||
## If we find a unique id, bind to it for success
|
||||
if ($x['count'] == 1) {
|
||||
$dn = $x[0]['dn'];
|
||||
if (@ldap_bind($ds, $dn, $pw)) { ldap_close($ds); return true; }
|
||||
}
|
||||
}
|
||||
ldap_close($ds);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
# The _crypt function provides support for SHA1 encrypted passwords
|
||||
# (keyed by '{SHA}') and Apache MD5 encrypted passwords (keyed by
|
||||
# '$apr1$'); otherwise it just calls PHP's crypt() for the rest.
|
||||
# The APR MD5 encryption code was contributed by D. Faure.
|
||||
|
||||
function _crypt($plain, $salt=null) {
|
||||
if (strncmp($salt, '{SHA}', 5) == 0)
|
||||
return '{SHA}'.base64_encode(pack('H*', sha1($plain)));
|
||||
if (strncmp($salt, '$apr1$', 6) == 0) {
|
||||
preg_match('/^\\$apr1\\$([^$]+)/', $salt, $match);
|
||||
$salt = $match[1];
|
||||
$length = strlen($plain);
|
||||
$context = $plain . '$apr1$' . $salt;
|
||||
$binary = pack('H32', md5($plain . $salt . $plain));
|
||||
for($i = $length; $i > 0; $i -= 16)
|
||||
$context .= substr($binary, 0, min(16, $i));
|
||||
for($i = $length; $i > 0; $i >>= 1)
|
||||
$context .= ($i & 1) ? chr(0) : $plain{0};
|
||||
$binary = pack('H32', md5($context));
|
||||
for($i = 0; $i < 1000; $i++) {
|
||||
$new = ($i & 1) ? $plain : $binary;
|
||||
if ($i % 3) $new .= $salt;
|
||||
if ($i % 7) $new .= $plain;
|
||||
$new .= ($i & 1) ? $binary : $plain;
|
||||
$binary = pack('H32', md5($new));
|
||||
}
|
||||
$q = '';
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$k = $i + 6;
|
||||
$j = $i + 12;
|
||||
if ($j == 16) $j = 5;
|
||||
$q = $binary{$i}.$binary{$k}.$binary{$j} . $q;
|
||||
}
|
||||
$q = chr(0).chr(0).$binary{11} . $q;
|
||||
$q = strtr(strrev(substr(base64_encode($q), 2)),
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
|
||||
'./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
|
||||
return "\$apr1\$$salt\$$q";
|
||||
}
|
||||
if (md5($plain) == $salt) return $salt;
|
||||
return pmcrypt($plain, $salt);
|
||||
}
|
||||
240
wiki/scripts/blocklist.php
Executable file
240
wiki/scripts/blocklist.php
Executable file
@@ -0,0 +1,240 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2006-2013 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script adds blocklisting capabilities to PmWiki, and can
|
||||
be enabled by simply setting the following in local/config.php:
|
||||
|
||||
$EnableBlocklist = 1;
|
||||
|
||||
With $EnableBlocklist set to 1, this module will search through
|
||||
the SiteAdmin.Blocklist page, as well as any other pages given by
|
||||
the $Blocklist pages variable, looking for lines of the
|
||||
form "block:some phrase" or "block:/regex/", with "some phrase"
|
||||
and "/regex/" indicating things to be excluded from any
|
||||
posting to the site.
|
||||
|
||||
In addition, if a page contains IP addresses of the form
|
||||
"a.b.c.d" or "a.b.c.*", then any posts coming from hosts
|
||||
matching the address will be blocked.
|
||||
|
||||
There is also an "unblock:..." form, which removes an entry
|
||||
from the blocklist. This is useful for removing specific
|
||||
block items in wikifarms and with automatically downloaded
|
||||
blocklists (below).
|
||||
|
||||
The script also has the capability of automatically downloading
|
||||
blocklists from other sources, such as chongqed.org and
|
||||
and the MoinMaster blocklist. These are configured using
|
||||
the $BlocklistDownload array. An $EnableBlocklist value
|
||||
of at least 10 configures PmWiki to automatically download
|
||||
these external blocklists and refresh them daily.
|
||||
|
||||
More information about blocklists is available in the
|
||||
PmWiki.Blocklist page.
|
||||
*/
|
||||
|
||||
|
||||
## Some recipes do page updates outside of the built-in posting
|
||||
## cycle, so $EnableBlocklistImmediate is used to determine if
|
||||
## we need to catch these. Currently this defaults to enabled,
|
||||
## but at some point we may change the default to disabled.
|
||||
if (IsEnabled($EnableBlocklistImmediate, 1)) {
|
||||
SDVA($BlocklistActions, array('comment' => 1));
|
||||
$ptext = implode(' ', @$_POST);
|
||||
if ($ptext && @$BlocklistActions[$action]) {
|
||||
Blocklist($pagename, $ptext);
|
||||
if (!$EnablePost) {
|
||||
unset($_POST['post']);
|
||||
unset($_POST['postattr']);
|
||||
unset($_POST['postedit']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
## If $EnableBlocklist is set to 10 or higher, then arrange to
|
||||
## periodically download the "chongqed" and "moinmaster" blacklists.
|
||||
if ($EnableBlocklist >= 10) {
|
||||
# SDVA($BlocklistDownload['SiteAdmin.Blocklist-Chongqed'], array(
|
||||
# 'url' => 'http://blacklist.chongqed.org/',
|
||||
# 'format' => 'regex'));
|
||||
SDVA($BlocklistDownload['SiteAdmin.Blocklist-MoinMaster'], array(
|
||||
'url' => 'http://moinmo.in/BadContent?action=raw',
|
||||
'format' => 'regex'));
|
||||
}
|
||||
|
||||
|
||||
## CheckBlocklist is inserted into $EditFunctions, to automatically
|
||||
## check for blocks on anything being posted through the normal
|
||||
## "update a page cycle"
|
||||
array_unshift($EditFunctions, 'CheckBlocklist');
|
||||
function CheckBlocklist($pagename, &$page, &$new) {
|
||||
StopWatch("CheckBlocklist: begin $pagename");
|
||||
$ptext = implode(' ', @$_POST);
|
||||
if (@$ptext) Blocklist($pagename, $ptext);
|
||||
StopWatch("CheckBlocklist: end $pagename");
|
||||
}
|
||||
|
||||
|
||||
## Blocklist is the function that does all of the work of
|
||||
## checking for reasons to block a posting. It reads
|
||||
## the available blocklist pages ($BlocklistPages) and
|
||||
## builds an array of strings and regular expressiongs to
|
||||
## be checked against the page; if any are found, then
|
||||
## posting is blocked (via $EnablePost=0). The function
|
||||
## also checks the REMOTE_ADDR against any blocked IP addresses.
|
||||
function Blocklist($pagename, $text) {
|
||||
global $BlocklistPages, $BlockedMessagesFmt, $BlocklistDownload,
|
||||
$BlocklistDownloadRefresh, $Now, $EnablePost, $WhyBlockedFmt,
|
||||
$MessagesFmt, $BlocklistMessageFmt, $EnableWhyBlocked, $IsBlocked;
|
||||
|
||||
StopWatch("Blocklist: begin $pagename");
|
||||
|
||||
$BlocklistDownload = (array)@$BlocklistDownload;
|
||||
SDV($BlocklistPages,
|
||||
array_merge(array('$SiteAdminGroup.Blocklist',
|
||||
'$SiteAdminGroup.Blocklist-Farm'),
|
||||
array_keys($BlocklistDownload)));
|
||||
SDV($BlocklistMessageFmt, "<h3 class='wikimessage'>$[This post has been blocked by the administrator]</h3>");
|
||||
SDVA($BlockedMessagesFmt, array(
|
||||
'ip' => '$[Address blocked from posting]: ',
|
||||
'text' => '$[Text blocked from posting]: '));
|
||||
SDV($BlocklistDownloadRefresh, 86400);
|
||||
|
||||
## Loop over all blocklist pages
|
||||
foreach((array)$BlocklistPages as $b) {
|
||||
|
||||
## load the current blocklist page
|
||||
$pn = FmtPageName($b, $pagename);
|
||||
$page = ReadPage($pn, READPAGE_CURRENT);
|
||||
if (!$page) continue;
|
||||
|
||||
## if the page being checked is a blocklist page, stop blocking
|
||||
if ($pagename == $pn) return;
|
||||
|
||||
## If the blocklist page is managed by automatic download,
|
||||
## schedule any new downloads here
|
||||
if (@$BlocklistDownload[$pn]) {
|
||||
$bd = &$BlocklistDownload[$pn];
|
||||
SDVA($bd, array(
|
||||
'refresh' => $BlocklistDownloadRefresh,
|
||||
'url' => "http://www.pmwiki.org/blocklists/$pn" ));
|
||||
if (!@$page['text'] || $page['time'] < $Now - $bd['refresh'])
|
||||
register_shutdown_function('BlocklistDownload', $pn, getcwd());
|
||||
}
|
||||
|
||||
## If the blocklist is simply a list of regexes to be matched, load
|
||||
## them into $terms['block'] and continue to the next blocklist page.
|
||||
## Some regexes from remote sites aren't well-formed, so we have
|
||||
## to escape any slashes that aren't already escaped.
|
||||
if (strpos(@$page['text'], 'blocklist-format: regex') !==false) {
|
||||
if (preg_match_all('/^([^\\s#].+)/m', $page['text'], $match))
|
||||
foreach($match[0] as $m) {
|
||||
$m = preg_replace('#(?<!\\\\)/#', '\\/', trim($m));
|
||||
$terms['block'][] = "/$m/";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
## Treat the page as a pmwiki-format blocklist page, with
|
||||
## IP addresses and "block:"-style declarations. First, see
|
||||
## if we need to block the author based on a.b.c.d or a.b.c.*
|
||||
## IP addresses.
|
||||
$ip = preg_quote($_SERVER['REMOTE_ADDR']);
|
||||
$ip = preg_replace('/\\d+$/', '($0\\b|\\*)', $ip);
|
||||
if (preg_match("/\\b$ip/", @$page['text'], $match)) {
|
||||
$EnablePost = 0;
|
||||
$IsBlocked = 1;
|
||||
$WhyBlockedFmt[] = $BlockedMessagesFmt['ip'] . $match[0];
|
||||
}
|
||||
|
||||
## Now we'll load any "block:" or "unblock:" specifications
|
||||
## from the page text.
|
||||
if (preg_match_all('/(un)?(?:block|regex):(.*)/', @$page['text'],
|
||||
$match, PREG_SET_ORDER))
|
||||
foreach($match as $m) $terms[$m[1].'block'][] = trim($m[2]);
|
||||
}
|
||||
|
||||
## okay, we've loaded all of the terms, now subtract any 'unblock'
|
||||
## terms from the block set.
|
||||
StopWatch("Blocklist: diff unblock");
|
||||
$blockterms = array_diff((array)@$terms['block'], (array)@$terms['unblock']);
|
||||
|
||||
## go through each of the remaining blockterms and see if it matches the
|
||||
## text -- if so, disable posting and add a message to $WhyBlockedFmt.
|
||||
StopWatch('Blocklist: blockterms (count='.count($blockterms).')');
|
||||
$itext = strtolower($text);
|
||||
foreach($blockterms as $b) {
|
||||
if ($b{0} == '/') {
|
||||
if (!preg_match($b, $text)) continue;
|
||||
} else if (strpos($itext, strtolower($b)) === false) continue;
|
||||
$EnablePost = 0;
|
||||
$IsBlocked = 1;
|
||||
$WhyBlockedFmt[] = $BlockedMessagesFmt['text'] . $b;
|
||||
}
|
||||
StopWatch('Blocklist: blockterms done');
|
||||
|
||||
## If we came across any reasons to block, let's provide a message
|
||||
## to the author that it was blocked. If $EnableWhyBlocked is set,
|
||||
## we'll even tell the author why. :-)
|
||||
if (@$WhyBlockedFmt) {
|
||||
$MessagesFmt[] = $BlocklistMessageFmt;
|
||||
if (IsEnabled($EnableWhyBlocked, 0))
|
||||
foreach((array)$WhyBlockedFmt as $why)
|
||||
$MessagesFmt[] = "<pre class='blocklistmessage'>$why</pre>\n";
|
||||
}
|
||||
StopWatch("Blocklist: end $pagename");
|
||||
}
|
||||
|
||||
|
||||
## BlocklistDownload() handles retrieving blocklists from
|
||||
## external sources into PmWiki pages. If it's able to
|
||||
## download an updated list, it uses that; otherwise it leaves
|
||||
## any existing list alone.
|
||||
function BlocklistDownload($pagename, $dir = '') {
|
||||
global $BlocklistDownloadFmt, $BlocklistDownload, $FmtV;
|
||||
|
||||
if ($dir) { flush(); chdir($dir); }
|
||||
SDV($BlocklistDownloadFmt, "
|
||||
[@
|
||||
## blocklist-note: NOTE: This page is automatically generated by blocklist.php
|
||||
## blocklist-note: NOTE: Any edits to this page may be lost!
|
||||
## blocklist-url: \$BlocklistDownloadUrl
|
||||
## blocklist-when: \$CurrentTimeISO
|
||||
# blocklist-format: \$BlocklistFormat
|
||||
\$BlocklistData
|
||||
@]
|
||||
");
|
||||
|
||||
## get the existing blocklist page
|
||||
$bd = &$BlocklistDownload[$pagename];
|
||||
$page = ReadPage($pagename, READPAGE_CURRENT);
|
||||
|
||||
## try to retrieve the remote data
|
||||
$blocklistdata = @file($bd['url']);
|
||||
|
||||
## if we didn't get it, and we don't already have text, save a
|
||||
## note in the page so we know what happened
|
||||
if (!$blocklistdata && !@$page['text']) {
|
||||
$auf = ini_get('allow_url_fopen');
|
||||
$blocklistdata = "#### Unable to download blocklist (allow_url_fopen=$auf)";
|
||||
}
|
||||
|
||||
## if we have some new text to save, let's format it and save it
|
||||
if ($blocklistdata) {
|
||||
$blocklistdata = implode('', (array)$blocklistdata);
|
||||
$blocklistdata = preg_replace('/^##blocklist.*/m', '', $blocklistdata);
|
||||
$FmtV['$BlocklistData'] = $blocklistdata;
|
||||
$FmtV['$BlocklistDownloadUrl'] = $bd['url'];
|
||||
$FmtV['$BlocklistFormat'] = $bd['format'];
|
||||
$page['text'] = FmtPageName($BlocklistDownloadFmt, $pagename);
|
||||
SDV($page['passwdread'], '@lock');
|
||||
}
|
||||
|
||||
## save our updated(?) blocklist page
|
||||
WritePage($pagename, $page);
|
||||
}
|
||||
63
wiki/scripts/caches.php
Executable file
63
wiki/scripts/caches.php
Executable file
@@ -0,0 +1,63 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2006-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
*/
|
||||
|
||||
## Browser cache-control. If this is a cacheable action (e.g., browse,
|
||||
## diff), then set the Last-Modified header to the time the site was
|
||||
## last modified. If the browser has provided us with a matching
|
||||
## If-Modified-Since request header, we can return 304 Not Modified.
|
||||
SDV($LastModFile,"$WorkDir/.lastmod");
|
||||
if (!$LastModFile) return;
|
||||
|
||||
$LastModTime = @filemtime($LastModFile);
|
||||
foreach(get_included_files() as $f)
|
||||
{ $v = @filemtime($f); if ($v > $LastModTime) $LastModTime = $v; }
|
||||
|
||||
if (@$EnableIMSCaching) {
|
||||
SDV($IMSCookie, $CookiePrefix.'imstime');
|
||||
SDV($IMSCookieExpires, $Now + 60*60*24*30);
|
||||
SDV($IMSInvalidators, array('authpw', 'author'));
|
||||
$LogoutCookies[] = $IMSCookie;
|
||||
|
||||
if ($IMSCookie) {
|
||||
$IMSTime = @$_COOKIE[$IMSCookie];
|
||||
if ($IMSTime < $LastModTime
|
||||
|| array_intersect($IMSInvalidators, array_keys($_POST))) {
|
||||
$IMSTime = $Now;
|
||||
setcookie($IMSCookie, $IMSTime, $IMSCookieExpires, '/');
|
||||
}
|
||||
} else $IMSTime = $LastModTime;
|
||||
|
||||
if (in_array($action, (array)$CacheActions)) {
|
||||
$HTTPLastMod = gmdate('D, d M Y H:i:s \G\M\T',$IMSTime);
|
||||
$HTTPHeaders[] = "Cache-Control: no-cache";
|
||||
$HTTPHeaders[] = "Last-Modified: $HTTPLastMod";
|
||||
if (@$_SERVER['HTTP_IF_MODIFIED_SINCE']==$HTTPLastMod) {
|
||||
header("HTTP/1.0 304 Not Modified");
|
||||
header("Cache-Control: no-cache");
|
||||
header("Expires: ");
|
||||
header("Last-Modified: $HTTPLastMod");
|
||||
exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($NoHTMLCache
|
||||
|| !@$PageCacheDir
|
||||
|| count($_POST) > 0
|
||||
|| count($_GET) > 1
|
||||
|| (count($_GET) == 1 && !@$_GET['n'])) { $NoHTMLCache |= 1; return; }
|
||||
|
||||
mkdirp($PageCacheDir);
|
||||
if (!file_exists("$PageCacheDir/.htaccess")
|
||||
&& $fp = @fopen("$PageCacheDir/.htaccess", "w"))
|
||||
{ fwrite($fp, "Order Deny,Allow\nDeny from all\n"); fclose($fp); }
|
||||
$PageCacheFile = "$PageCacheDir/$pagename,cache";
|
||||
if (file_exists($PageCacheFile) && @filemtime($PageCacheFile) < $LastModTime)
|
||||
@unlink($PageCacheFile);
|
||||
|
||||
66
wiki/scripts/creole.php
Executable file
66
wiki/scripts/creole.php
Executable file
@@ -0,0 +1,66 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2007-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script adds Creole v0.4 markup (http://www.wikicreole.org/)
|
||||
to PmWiki. To activate this script, simply add the following into
|
||||
a local customization file:
|
||||
|
||||
include_once('scripts/creole.php');
|
||||
|
||||
*/
|
||||
|
||||
## **strong**
|
||||
Markup('**', 'inline',
|
||||
'/^\\*\\*(?>(.+?)\\*\\*)(?!\\S)|(?<!^)\\*\\*(.+?)\\*\\*/',
|
||||
'<strong>$1$2</strong>');
|
||||
|
||||
## //emphasized//
|
||||
Markup('//', 'inline',
|
||||
'/(?<!http:|https:|ftp:)\\/\\/(.*?)\\/\\//',
|
||||
'<em>$1</em>');
|
||||
|
||||
## == Headings ==
|
||||
Markup_e('^=', 'block',
|
||||
'/^(={1,6})\\s?(.*?)(\\s*=*\\s*)$/',
|
||||
"'<:block,1><h'.strlen(\$m[1]).'>'.\$m[2].'</h'.strlen(\$m[1]).'>'");
|
||||
|
||||
## Line breaks
|
||||
Markup('\\\\', 'inline', '/\\\\\\\\/', '<br />');
|
||||
|
||||
## Preformatted
|
||||
Markup_e('^{{{', '[=',
|
||||
"/^\\{\\{\\{\n(.*?\n)\\}\\}\\}[^\\S\n]*\n/sm",
|
||||
"Keep('<pre class=\"escaped\">'.\$m[1].'</pre>')");
|
||||
Markup_e('{{{', '>{{{',
|
||||
'/\\{\\{\\{(.*?)\\}\\}\\}/s',
|
||||
"Keep('<code class=\"escaped\">'.\$m[1].'</code>')");
|
||||
|
||||
## Tables
|
||||
Markup_e('|-table', '>^||',
|
||||
'/^\\|(.*)$/',
|
||||
"FormatTableRow(\$m[0], '\\|')");
|
||||
|
||||
## Images
|
||||
Markup_e('{{', 'inline',
|
||||
'/\\{\\{(?>(\\L))([^|\\]]*)(?:\\|\\s*(.*?)\\s*)?\\}\\}/',
|
||||
"Keep(\$GLOBALS['LinkFunctions'][\$m[1]](\$pagename, \$m[1], \$m[2], \$m[3],
|
||||
\$m[1].\$m[2], \$GLOBALS['ImgTagFmt']),'L')");
|
||||
|
||||
|
||||
## GUIButtons
|
||||
SDVA($GUIButtons, array(
|
||||
'em' => array(100, "//", "//", '$[Emphasized]',
|
||||
'$GUIButtonDirUrlFmt/em.gif"$[Emphasized (italic)]"',
|
||||
'$[ak_em]'),
|
||||
'strong' => array(110, "**", "**", '$[Strong]',
|
||||
'$GUIButtonDirUrlFmt/strong.gif"$[Strong (bold)]"',
|
||||
'$[ak_strong]'),
|
||||
'h2' => array(400, '\\n== ', ' ==\\n', '$[Heading]',
|
||||
'$GUIButtonDirUrlFmt/h.gif"$[Heading]"'),
|
||||
|
||||
));
|
||||
|
||||
41
wiki/scripts/crypt.php
Executable file
41
wiki/scripts/crypt.php
Executable file
@@ -0,0 +1,41 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2002-2015 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script defines ?action=crypt, providing help for WikiAdministrators
|
||||
to set up site-wide passwords in the installation.
|
||||
*/
|
||||
|
||||
SDV($HandleActions['crypt'],'HandleCrypt');
|
||||
SDV($ActionTitleFmt['crypt'],'| $[Password encryption]');
|
||||
|
||||
function HandleCrypt($pagename, $auth='read') {
|
||||
global $ScriptUrl,$HTMLStartFmt,$HTMLEndFmt;
|
||||
PrintFmt($pagename,$HTMLStartFmt);
|
||||
$passwd = stripmagic(@$_POST["passwd"]);
|
||||
echo FmtPageName(
|
||||
"<form action='{\$ScriptUrl}' method='POST'><p>
|
||||
Enter password to encrypt:
|
||||
<input type='text' name='passwd' value='"
|
||||
. PHSC($passwd, ENT_QUOTES) ."' />
|
||||
<input type='submit' />
|
||||
<input type='hidden' name='n' value='{\$FullName}' />
|
||||
<input type='hidden' name='action' value='crypt' /></p></form>",
|
||||
$pagename);
|
||||
if ($passwd) {
|
||||
$crypt = pmcrypt($passwd);
|
||||
echo "<p class='vspace'>Encrypted password = $crypt</p>";
|
||||
echo "<p class='vspace'>To set a site-wide password, insert the line below
|
||||
in your <i>config.php</i> file, <br />replacing <tt>'type'</tt> with
|
||||
one of <tt>'admin'</tt>, <tt>'read'</tt>, <tt>'edit'</tt>,
|
||||
or <tt>'attr'</tt>. <br />See <a
|
||||
href='$ScriptUrl?n=PmWiki.PasswordsAdmin'>PasswordsAdmin</a> for more
|
||||
details.</p>
|
||||
<pre class='vspace'> \$DefaultPasswords['type']='$crypt';</pre>";
|
||||
}
|
||||
PrintFmt($pagename,$HTMLEndFmt);
|
||||
}
|
||||
|
||||
60
wiki/scripts/diag.php
Executable file
60
wiki/scripts/diag.php
Executable file
@@ -0,0 +1,60 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2003-2005, 2007 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file adds "?action=diag" and "?action=phpinfo" actions to PmWiki.
|
||||
This produces lots of diagnostic output that may be helpful to the
|
||||
software authors when debugging PmWiki or other scripts.
|
||||
*/
|
||||
|
||||
@ini_set('display_errors', '1');
|
||||
@ini_set('track_errors','1');
|
||||
|
||||
if ($action=='diag') {
|
||||
@session_start();
|
||||
header('Content-type: text/plain');
|
||||
print_r($GLOBALS);
|
||||
exit();
|
||||
}
|
||||
|
||||
if ($action=='phpinfo') { phpinfo(); exit(); }
|
||||
|
||||
function Ruleset() {
|
||||
global $MarkupTable;
|
||||
$out = '';
|
||||
$dbg = 0;
|
||||
BuildMarkupRules();
|
||||
foreach($MarkupTable as $id=>$m) {
|
||||
$out .= sprintf("%-16s %-16s %-16s %s\n",$id,@$m['cmd'],@$m['seq'], @$m['dbg']);
|
||||
if(@$m['dbg']) $dbg++;
|
||||
}
|
||||
if($dbg) $out .= "
|
||||
[!] Markup rules possibly incompatible with PHP 5.5 or newer.
|
||||
Please contact the recipe maintainer for update
|
||||
or see www.pmwiki.org/wiki/PmWiki/CustomMarkup";
|
||||
return $out;
|
||||
}
|
||||
|
||||
$HandleActions['ruleset'] = 'HandleRuleset';
|
||||
|
||||
function HandleRuleset($pagename) {
|
||||
header("Content-type: text/plain");
|
||||
print Ruleset();
|
||||
}
|
||||
|
||||
function StopWatchHTML($pagename, $print = 0) {
|
||||
global $StopWatch;
|
||||
StopWatch('now');
|
||||
$l = strlen(count($StopWatch));
|
||||
$out = '<pre>';
|
||||
foreach((array)$StopWatch as $i => $x)
|
||||
$out .= sprintf("%{$l}d: %s\n", $i, $x);
|
||||
$out .= '</pre>';
|
||||
if (is_array($StopWatch)) array_pop($StopWatch);
|
||||
if ($print) print $out;
|
||||
return $out;
|
||||
}
|
||||
|
||||
73
wiki/scripts/draft.php
Executable file
73
wiki/scripts/draft.php
Executable file
@@ -0,0 +1,73 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2006-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
*/
|
||||
|
||||
SDV($DraftSuffix, '-Draft');
|
||||
if ($DraftSuffix)
|
||||
SDV($SearchPatterns['normal']['draft'], "!$DraftSuffix\$!");
|
||||
|
||||
## set up a 'publish' authorization level, defaulting to 'edit' authorization
|
||||
SDV($DefaultPasswords['publish'], '');
|
||||
SDV($AuthCascade['publish'], 'edit');
|
||||
SDV($FmtPV['$PasswdPublish'], 'PasswdVar($pn, "publish")');
|
||||
if ($AuthCascade['attr'] == 'edit') $AuthCascade['attr'] = 'publish';
|
||||
|
||||
## Add a 'publish' page attribute if desired
|
||||
if (IsEnabled($EnablePublishAttr, 0))
|
||||
SDV($PageAttributes['passwdpublish'], '$[Set new publish password:]');
|
||||
|
||||
|
||||
$basename = preg_replace("/$DraftSuffix\$/", '', $pagename);
|
||||
## if no -Draft page, switch to $basename
|
||||
if (!PageExists($pagename) && PageExists($basename)) $pagename = $basename;
|
||||
|
||||
## The section below handles specialized EditForm pages and handler.
|
||||
## We don't bother to load it if we're not editing.
|
||||
SDV($DraftActionsPattern, 'edit');
|
||||
if (! preg_match("/($DraftActionsPattern)/", $action)) return;
|
||||
|
||||
## set edit form button labels to reflect draft prompts
|
||||
SDVA($InputTags['e_savebutton'], array('value' => ' '.XL('Publish').' '));
|
||||
SDVA($InputTags['e_saveeditbutton'], array('value' => ' '.XL('Save draft and edit').' '));
|
||||
SDVA($InputTags['e_savedraftbutton'], array(
|
||||
':html' => "<input type='submit' \$InputFormArgs />",
|
||||
'name' => 'postdraft', 'value' => ' '.XL('Save draft').' ',
|
||||
'accesskey' => XL('ak_savedraft')));
|
||||
|
||||
## with drafts enabled, the 'post' operation requires 'publish' permissions
|
||||
if ($_POST['post'] && $HandleAuth['edit'] == 'edit')
|
||||
$HandleAuth['edit'] = 'publish';
|
||||
|
||||
## disable the 'publish' button if not authorized to publish
|
||||
if (!CondAuth($basename, 'publish'))
|
||||
SDVA($InputTags['e_savebutton'], array('disabled' => 'disabled'));
|
||||
|
||||
## add the draft handler into $EditFunctions
|
||||
array_unshift($EditFunctions, 'EditDraft');
|
||||
function EditDraft(&$pagename, &$page, &$new) {
|
||||
global $WikiDir, $DraftSuffix, $DeleteKeyPattern, $EnableDraftAtomicDiff,
|
||||
$DraftRecentChangesFmt, $RecentChangesFmt, $Now;
|
||||
SDV($DeleteKeyPattern, "^\\s*delete\\s*$");
|
||||
$basename = preg_replace("/$DraftSuffix\$/", '', $pagename);
|
||||
$draftname = $basename . $DraftSuffix;
|
||||
if ($_POST['postdraft'] || $_POST['postedit']) $pagename = $draftname;
|
||||
else if ($_POST['post'] && !preg_match("/$DeleteKeyPattern/", $new['text'])) {
|
||||
$pagename = $basename;
|
||||
if(IsEnabled($EnableDraftAtomicDiff, 0)) {
|
||||
$page = ReadPage($basename);
|
||||
foreach($new as $k=>$v) # delete draft history
|
||||
if(preg_match('/:\\d+(:\\d+:)?$/', $k) && ! preg_match("/:$Now(:\\d+:)?$/", $k)) unset($new[$k]);
|
||||
unset($new['rev']);
|
||||
SDVA($new, $page);
|
||||
}
|
||||
$WikiDir->delete($draftname);
|
||||
}
|
||||
else if (PageExists($draftname) && $pagename != $draftname)
|
||||
{ Redirect($draftname, '$PageUrl?action=edit'); exit(); }
|
||||
if ($pagename == $draftname && isset($DraftRecentChangesFmt))
|
||||
$RecentChangesFmt = $DraftRecentChangesFmt;
|
||||
}
|
||||
544
wiki/scripts/feeds.php
Executable file
544
wiki/scripts/feeds.php
Executable file
@@ -0,0 +1,544 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2005-2010 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script provides a number of syndication feed and xml-based
|
||||
metadata options to PmWiki, including Atom, RSS 2.0, RSS 1.0 (RDF),
|
||||
and the Dublin Core Metadata extensions. This module is typically
|
||||
activated from a local configuration file via a line such as
|
||||
|
||||
if ($action == 'atom') include_once("$FarmD/scripts/feeds.php");
|
||||
if ($action == 'dc') include_once("$FarmD/scripts/feeds.php");
|
||||
|
||||
When enabled, ?action=atom, ?action=rss, and ?action=rdf produce
|
||||
syndication feeds based on any wikitrail contained in the page,
|
||||
or, for Category pages, on the pages in the category. The feeds
|
||||
are generated using pagelist, thus one can include parameters such
|
||||
as count=, list=, order=, etc. in the url to adjust the feed output.
|
||||
|
||||
?action=dc will normally generate Dublin Core Metadata for the
|
||||
current page only, but placing a group=, trail=, or link= argument
|
||||
in the url causes it to generate metadata for all pages in the
|
||||
associated group, trail, or backlink.
|
||||
|
||||
There are a large number of customizations available, most of which
|
||||
are controlled by the $FeedFmt array. Elements $FeedFmt look like
|
||||
|
||||
$FeedFmt['atom']['feed']['rights'] = 'All Rights Reserved';
|
||||
|
||||
where the first index corresponds to the action (?action=atom),
|
||||
the second index indicates a per-feed or per-item element, and
|
||||
the third index is the name of the element being generated.
|
||||
The above setting would therefore generate a
|
||||
"<rights>All Rights Reserved</rights>" in the feed for
|
||||
?action=atom. If the value of an entry begins with a '<',
|
||||
then feeds.php doesn't automatically add the tag around it.
|
||||
Elements can also be callable functions which are called to
|
||||
generate the appropriate output.
|
||||
|
||||
For example, to set the RSS 2.0 <author> element to the
|
||||
value of the last author to modify a page, one can set
|
||||
(in local/config.php):
|
||||
|
||||
$FeedFmt['rss']['item']['author'] = '$LastModifiedBy';
|
||||
|
||||
To use the RSS 2.0 <description> element to contain the
|
||||
change summary of the most recent edit, set
|
||||
|
||||
$FeedFmt['rss']['item']['description'] = '$LastModifiedSummary';
|
||||
|
||||
Feeds.php can also be combined with attachments to support
|
||||
podcasting via ?action=rss. Any page such as "PageName"
|
||||
that has an mp3 attachment with the same name as the page
|
||||
("PageName.mp3") will have an appropriate <enclosure> element
|
||||
in the feed output. The set of allowed attachments can be
|
||||
extended using the $RSSEnclosureFmt array:
|
||||
|
||||
$RSSEnclosureFmt = array('{$Name}.mp3', '{$Name}.mp4');
|
||||
|
||||
References:
|
||||
http://www.atomenabled.org/developers/syndication/
|
||||
http://dublincore.org/documents/dcmes-xml/
|
||||
http://en.wikipedia.org/wiki/Podcasting
|
||||
*/
|
||||
|
||||
## Settings for ?action=atom
|
||||
SDVA($FeedFmt['atom']['feed'], array(
|
||||
'_header' => 'Content-type: text/xml; charset="$Charset"',
|
||||
'_start' => '<?xml version="1.0" encoding="$Charset"?'.'>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">'."\n",
|
||||
'_end' => "</feed>\n",
|
||||
'title' => '$WikiTitle',
|
||||
'link' => '<link rel="self" href="{$PageUrl}?action=atom" />',
|
||||
'id' => '{$PageUrl}?action=atom',
|
||||
'updated' => '$FeedISOTime',
|
||||
'author' => "<author><name>$WikiTitle</name></author>\n",
|
||||
'generator' => '$Version',
|
||||
'logo' => '$PageLogoUrl'));
|
||||
SDVA($FeedFmt['atom']['item'], array(
|
||||
'_start' => "<entry>\n",
|
||||
'id' => '{$PageUrl}',
|
||||
'title' => '{$Title}',
|
||||
'updated' => '$ItemISOTime',
|
||||
'link' => "<link rel=\"alternate\" href=\"{\$PageUrl}\" />\n",
|
||||
'author' => "<author><name>{\$LastModifiedBy}</name></author>\n",
|
||||
'summary' => '{$Description}',
|
||||
'category' => "<category term=\"\$Category\" />\n",
|
||||
'_end' => "</entry>\n"));
|
||||
|
||||
## Settings for ?action=dc
|
||||
SDVA($FeedFmt['dc']['feed'], array(
|
||||
'_header' => 'Content-type: text/xml; charset="$Charset"',
|
||||
'_start' => '<?xml version="1.0" encoding="$Charset"?'.'>
|
||||
<!DOCTYPE rdf:RDF PUBLIC "-//DUBLIN CORE//DCMES DTD 2002/07/31//EN"
|
||||
"http://dublincore.org/documents/2002/07/31/dcmes-xml/dcmes-xml-dtd.dtd">
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">'."\n",
|
||||
'_end' => "</rdf:RDF>\n"));
|
||||
SDVA($FeedFmt['dc']['item'], array(
|
||||
'_start' => "<rdf:Description rdf:about=\"{\$PageUrl}\">\n",
|
||||
'dc:title' => '{$Title}',
|
||||
'dc:identifier' => '{$PageUrl}',
|
||||
'dc:date' => '$ItemISOTime',
|
||||
'dc:type' => 'Text',
|
||||
'dc:format' => 'text/html',
|
||||
'dc:description' => '{$Description}',
|
||||
'dc:subject' => "<dc:subject>\$Category</dc:subject>\n",
|
||||
'dc:publisher' => '$WikiTitle',
|
||||
'dc:author' => '{$LastModifiedBy}',
|
||||
'_end' => "</rdf:Description>\n"));
|
||||
|
||||
## RSS 2.0 settings for ?action=rss
|
||||
SDVA($FeedFmt['rss']['feed'], array(
|
||||
'_header' => 'Content-type: text/xml; charset="$Charset"',
|
||||
'_start' => '<?xml version="1.0" encoding="$Charset"?'.'>
|
||||
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<channel>'."\n",
|
||||
'_end' => "</channel>\n</rss>\n",
|
||||
'title' => '$WikiTitle | {$Group} / {$Title}',
|
||||
'link' => '{$PageUrl}?action=rss',
|
||||
'description' => '{$Group}.{$Title}',
|
||||
'lastBuildDate' => '$FeedRSSTime'));
|
||||
SDVA($FeedFmt['rss']['item'], array(
|
||||
'_start' => "<item>\n",
|
||||
'_end' => "</item>\n",
|
||||
'title' => '{$Group} / {$Title}',
|
||||
'link' => '{$PageUrl}',
|
||||
'description' => '{$Description}',
|
||||
'dc:contributor' => '{$LastModifiedBy}',
|
||||
'dc:date' => '$ItemISOTime',
|
||||
'pubDate' => '$ItemRSSTime',
|
||||
'enclosure' => 'RSSEnclosure'));
|
||||
|
||||
## RDF 1.0, for ?action=rdf
|
||||
SDVA($FeedFmt['rdf']['feed'], array(
|
||||
'_header' => 'Content-type: text/xml; charset="$Charset"',
|
||||
'_start' => '<?xml version="1.0" encoding="$Charset"?'.'>
|
||||
<rdf:RDF xmlns="http://purl.org/rss/1.0/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<channel rdf:about="{$PageUrl}?action=rdf">'."\n",
|
||||
'title' => '$WikiTitle | {$Group} / {$Title}',
|
||||
'link' => '{$PageUrl}?action=rdf',
|
||||
'description' => '{$Group}.{$Title}',
|
||||
'dc:date' => '$FeedISOTime',
|
||||
'items' => "<items>\n<rdf:Seq>\n\$FeedRDFSeq</rdf:Seq>\n</items>\n",
|
||||
'_items' => "</channel>\n",
|
||||
'_end' => "</rdf:RDF>\n"));
|
||||
SDVA($FeedFmt['rdf']['item'], array(
|
||||
'_start' => "<item rdf:about=\"{\$PageUrl}\">\n",
|
||||
'_end' => "</item>\n",
|
||||
'title' => '$WikiTitle | {$Group} / {$Title}',
|
||||
'link' => '{$PageUrl}',
|
||||
'description' => '{$Description}',
|
||||
'dc:date' => '$ItemISOTime'));
|
||||
|
||||
foreach(array_keys($FeedFmt) as $k) {
|
||||
SDV($HandleActions[$k], 'HandleFeed');
|
||||
SDV($HandleAuth[$k], 'read');
|
||||
}
|
||||
|
||||
function HandleFeed($pagename, $auth = 'read') {
|
||||
global $FeedFmt, $action, $PCache, $FmtV, $TimeISOZFmt, $RSSTimeFmt,
|
||||
$FeedPageListOpt, $FeedCategoryOpt, $FeedTrailOpt,
|
||||
$FeedDescPatterns, $CategoryGroup, $EntitiesTable;
|
||||
SDV($RSSTimeFmt, 'D, d M Y H:i:s \G\M\T');
|
||||
SDV($FeedDescPatterns,
|
||||
array('/<[^>]*$/' => ' ', '/\\w+$/' => '', '/<[^>]+>/' => ''));
|
||||
$FeedPageListOpt = (array)@$FeedPageListOpt;
|
||||
SDVA($FeedCategoryOpt, array('link' => $pagename));
|
||||
SDVA($FeedTrailOpt, array('trail' => $pagename, 'count' => 10));
|
||||
|
||||
$f = $FeedFmt[$action];
|
||||
$page = RetrieveAuthPage($pagename, $auth, true, READPAGE_CURRENT);
|
||||
if (!$page) Abort("?cannot generate feed");
|
||||
$feedtime = $page['time'];
|
||||
|
||||
# determine list of pages to display
|
||||
if (@($_REQUEST['trail'] || $_REQUEST['group'] || $_REQUEST['link']
|
||||
|| $_REQUEST['name']))
|
||||
$opt = $FeedPageListOpt;
|
||||
else if (preg_match("/^$CategoryGroup\\./", $pagename))
|
||||
$opt = $FeedCategoryOpt;
|
||||
else if ($action != 'dc') $opt = $FeedTrailOpt;
|
||||
else {
|
||||
PCache($pagename, $page);
|
||||
$pagelist = array($pagename);
|
||||
}
|
||||
if (!@$pagelist) {
|
||||
$opt = array_merge($opt, @$_REQUEST);
|
||||
$pagelist = MakePageList($pagename, $opt, 0);
|
||||
}
|
||||
|
||||
# process list of pages in feed
|
||||
$rdfseq = '';
|
||||
$pl = array();
|
||||
foreach($pagelist as $pn) {
|
||||
if (!PageExists($pn)) continue;
|
||||
if (!isset($PCache[$pn]['time']))
|
||||
{ $page = ReadPage($pn, READPAGE_CURRENT); PCache($pn, $page); }
|
||||
$pc = & $PCache[$pn];
|
||||
$pl[] = $pn;
|
||||
$rdfseq .= FmtPageName("<rdf:li resource=\"{\$PageUrl}\" />\n", $pn);
|
||||
if ($pc['time'] > $feedtime) $feedtime = $pc['time'];
|
||||
if (@$opt['count'] && count($pl) >= $opt['count']) break;
|
||||
}
|
||||
$pagelist = $pl;
|
||||
|
||||
$FmtV['$FeedRDFSeq'] = $rdfseq;
|
||||
$FmtV['$FeedISOTime'] = gmstrftime($TimeISOZFmt, $feedtime);
|
||||
$FmtV['$FeedRSSTime'] = gmdate($RSSTimeFmt, $feedtime);
|
||||
# format start of feed
|
||||
$out = FmtPageName($f['feed']['_start'], $pagename);
|
||||
|
||||
# format feed elements
|
||||
foreach($f['feed'] as $k => $v) {
|
||||
if ($k{0} == '_' || !$v) continue;
|
||||
$x = FmtPageName($v, $pagename);
|
||||
if (!$x) continue;
|
||||
$out .= ($v{0} == '<') ? $x : "<$k>$x</$k>\n";
|
||||
}
|
||||
|
||||
# format items in feed
|
||||
if (@$f['feed']['_items'])
|
||||
$out .= FmtPageName($f['feed']['_items'], $pagename);
|
||||
foreach($pagelist as $pn) {
|
||||
$page = &$PCache[$pn];
|
||||
$FmtV['$ItemDesc'] = @$page['description'];
|
||||
$FmtV['$ItemISOTime'] = gmstrftime($TimeISOZFmt, $page['time']);
|
||||
$FmtV['$ItemRSSTime'] = gmdate($RSSTimeFmt, $page['time']);
|
||||
|
||||
$out .= FmtPageName($f['item']['_start'], $pn);
|
||||
foreach((array)@$f['item'] as $k => $v) {
|
||||
if ($k{0} == '_' || !$v) continue;
|
||||
if (is_callable($v)) { $out .= $v($pn, $page, $k); continue; }
|
||||
if (strpos($v, '$LastModifiedBy') !== false && !@$page['author'])
|
||||
continue;
|
||||
if (strpos($v, '$Category') !== false) {
|
||||
if (preg_match_all("/(?<=^|,)$CategoryGroup\\.([^,]+)/",
|
||||
@$page['targets'], $match)) {
|
||||
foreach($match[1] as $c) {
|
||||
$FmtV['$Category'] = $c;
|
||||
$out .= FmtPageName($v, $pn);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
$x = FmtPageName($v, $pn);
|
||||
if (!$x) continue;
|
||||
$out .= ($v{0} == '<') ? $x : "<$k>$x</$k>\n";
|
||||
}
|
||||
$out .= FmtPageName($f['item']['_end'], $pn);
|
||||
}
|
||||
$out .= FmtPageName($f['feed']['_end'], $pagename);
|
||||
foreach((array)@$f['feed']['_header'] as $fmt)
|
||||
header(FmtPageName($fmt, $pagename));
|
||||
print str_replace(array_keys($EntitiesTable),
|
||||
array_values($EntitiesTable), $out);
|
||||
}
|
||||
|
||||
## RSSEnclosure is called in ?action=rss to generate <enclosure>
|
||||
## tags for any pages that have an attached "PageName.mp3" file.
|
||||
## The set of attachments to enclose is given by $RSSEnclosureFmt.
|
||||
function RSSEnclosure($pagename, &$page, $k) {
|
||||
global $RSSEnclosureFmt, $UploadFileFmt, $UploadExts;
|
||||
if (!function_exists('MakeUploadName')) return '';
|
||||
SDV($RSSEnclosureFmt, array('{$Name}.mp3'));
|
||||
$encl = '';
|
||||
foreach((array)$RSSEnclosureFmt as $fmt) {
|
||||
$path = FmtPageName($fmt, $pagename);
|
||||
$upname = MakeUploadName($pagename, $path);
|
||||
$filepath = FmtPageName("$UploadFileFmt/$upname", $pagename);
|
||||
if (file_exists($filepath)) {
|
||||
$length = filesize($filepath);
|
||||
$type = @$UploadExts[preg_replace('/.*\\./', '', $filepath)];
|
||||
$url = LinkUpload($pagename, 'Attach:', $path, '', '', '$LinkUrl');
|
||||
$encl .= "<$k url='$url' length='$length' type='$type' />";
|
||||
}
|
||||
}
|
||||
return $encl;
|
||||
}
|
||||
|
||||
## Since most feeds don't understand html character entities, we
|
||||
## convert the common ones to their numeric form here.
|
||||
SDVA($EntitiesTable, array(
|
||||
# entities defined in "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent"
|
||||
' ' => ' ',
|
||||
'¡' => '¡',
|
||||
'¢' => '¢',
|
||||
'£' => '£',
|
||||
'¤' => '¤',
|
||||
'¥' => '¥',
|
||||
'¦' => '¦',
|
||||
'§' => '§',
|
||||
'¨' => '¨',
|
||||
'©' => '©',
|
||||
'ª' => 'ª',
|
||||
'«' => '«',
|
||||
'¬' => '¬',
|
||||
'­' => '­',
|
||||
'®' => '®',
|
||||
'¯' => '¯',
|
||||
'°' => '°',
|
||||
'±' => '±',
|
||||
'²' => '²',
|
||||
'³' => '³',
|
||||
'´' => '´',
|
||||
'µ' => 'µ',
|
||||
'¶' => '¶',
|
||||
'·' => '·',
|
||||
'¸' => '¸',
|
||||
'¹' => '¹',
|
||||
'º' => 'º',
|
||||
'»' => '»',
|
||||
'¼' => '¼',
|
||||
'½' => '½',
|
||||
'¾' => '¾',
|
||||
'¿' => '¿',
|
||||
'À' => 'À',
|
||||
'Á' => 'Á',
|
||||
'Â' => 'Â',
|
||||
'Ã' => 'Ã',
|
||||
'Ä' => 'Ä',
|
||||
'Å' => 'Å',
|
||||
'Æ' => 'Æ',
|
||||
'Ç' => 'Ç',
|
||||
'È' => 'È',
|
||||
'É' => 'É',
|
||||
'Ê' => 'Ê',
|
||||
'Ë' => 'Ë',
|
||||
'Ì' => 'Ì',
|
||||
'Í' => 'Í',
|
||||
'Î' => 'Î',
|
||||
'Ï' => 'Ï',
|
||||
'Ð' => 'Ð',
|
||||
'Ñ' => 'Ñ',
|
||||
'Ò' => 'Ò',
|
||||
'Ó' => 'Ó',
|
||||
'Ô' => 'Ô',
|
||||
'Õ' => 'Õ',
|
||||
'Ö' => 'Ö',
|
||||
'×' => '×',
|
||||
'Ø' => 'Ø',
|
||||
'Ù' => 'Ù',
|
||||
'Ú' => 'Ú',
|
||||
'Û' => 'Û',
|
||||
'Ü' => 'Ü',
|
||||
'Ý' => 'Ý',
|
||||
'Þ' => 'Þ',
|
||||
'ß' => 'ß',
|
||||
'à' => 'à',
|
||||
'á' => 'á',
|
||||
'â' => 'â',
|
||||
'ã' => 'ã',
|
||||
'ä' => 'ä',
|
||||
'å' => 'å',
|
||||
'æ' => 'æ',
|
||||
'ç' => 'ç',
|
||||
'è' => 'è',
|
||||
'é' => 'é',
|
||||
'ê' => 'ê',
|
||||
'ë' => 'ë',
|
||||
'ì' => 'ì',
|
||||
'í' => 'í',
|
||||
'î' => 'î',
|
||||
'ï' => 'ï',
|
||||
'ð' => 'ð',
|
||||
'ñ' => 'ñ',
|
||||
'ò' => 'ò',
|
||||
'ó' => 'ó',
|
||||
'ô' => 'ô',
|
||||
'õ' => 'õ',
|
||||
'ö' => 'ö',
|
||||
'÷' => '÷',
|
||||
'ø' => 'ø',
|
||||
'ù' => 'ù',
|
||||
'ú' => 'ú',
|
||||
'û' => 'û',
|
||||
'ü' => 'ü',
|
||||
'ý' => 'ý',
|
||||
'þ' => 'þ',
|
||||
'ÿ' => 'ÿ',
|
||||
# entities defined in "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent"
|
||||
'"' => '"',
|
||||
#'&' => '&#38;',
|
||||
#'<' => '&#60;',
|
||||
#'>' => '>',
|
||||
''' => ''',
|
||||
'Œ' => 'Œ',
|
||||
'œ' => 'œ',
|
||||
'Š' => 'Š',
|
||||
'š' => 'š',
|
||||
'Ÿ' => 'Ÿ',
|
||||
'ˆ' => 'ˆ',
|
||||
'˜' => '˜',
|
||||
' ' => ' ',
|
||||
' ' => ' ',
|
||||
' ' => ' ',
|
||||
'‌' => '‌',
|
||||
'‍' => '‍',
|
||||
'‎' => '‎',
|
||||
'‏' => '‏',
|
||||
'–' => '–',
|
||||
'—' => '—',
|
||||
'‘' => '‘',
|
||||
'’' => '’',
|
||||
'‚' => '‚',
|
||||
'“' => '“',
|
||||
'”' => '”',
|
||||
'„' => '„',
|
||||
'†' => '†',
|
||||
'‡' => '‡',
|
||||
'‰' => '‰',
|
||||
'‹' => '‹',
|
||||
'›' => '›',
|
||||
'€' => '€',
|
||||
# entities defined in "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent"
|
||||
'ƒ' => 'ƒ',
|
||||
'Α' => 'Α',
|
||||
'Β' => 'Β',
|
||||
'Γ' => 'Γ',
|
||||
'Δ' => 'Δ',
|
||||
'Ε' => 'Ε',
|
||||
'Ζ' => 'Ζ',
|
||||
'Η' => 'Η',
|
||||
'Θ' => 'Θ',
|
||||
'Ι' => 'Ι',
|
||||
'Κ' => 'Κ',
|
||||
'Λ' => 'Λ',
|
||||
'Μ' => 'Μ',
|
||||
'Ν' => 'Ν',
|
||||
'Ξ' => 'Ξ',
|
||||
'Ο' => 'Ο',
|
||||
'Π' => 'Π',
|
||||
'Ρ' => 'Ρ',
|
||||
'Σ' => 'Σ',
|
||||
'Τ' => 'Τ',
|
||||
'Υ' => 'Υ',
|
||||
'Φ' => 'Φ',
|
||||
'Χ' => 'Χ',
|
||||
'Ψ' => 'Ψ',
|
||||
'Ω' => 'Ω',
|
||||
'α' => 'α',
|
||||
'β' => 'β',
|
||||
'γ' => 'γ',
|
||||
'δ' => 'δ',
|
||||
'ε' => 'ε',
|
||||
'ζ' => 'ζ',
|
||||
'η' => 'η',
|
||||
'θ' => 'θ',
|
||||
'ι' => 'ι',
|
||||
'κ' => 'κ',
|
||||
'λ' => 'λ',
|
||||
'μ' => 'μ',
|
||||
'ν' => 'ν',
|
||||
'ξ' => 'ξ',
|
||||
'ο' => 'ο',
|
||||
'π' => 'π',
|
||||
'ρ' => 'ρ',
|
||||
'ς' => 'ς',
|
||||
'σ' => 'σ',
|
||||
'τ' => 'τ',
|
||||
'υ' => 'υ',
|
||||
'φ' => 'φ',
|
||||
'χ' => 'χ',
|
||||
'ψ' => 'ψ',
|
||||
'ω' => 'ω',
|
||||
'ϑ' => 'ϑ',
|
||||
'ϒ' => 'ϒ',
|
||||
'ϖ' => 'ϖ',
|
||||
'•' => '•',
|
||||
'…' => '…',
|
||||
'′' => '′',
|
||||
'″' => '″',
|
||||
'‾' => '‾',
|
||||
'⁄' => '⁄',
|
||||
'℘' => '℘',
|
||||
'ℑ' => 'ℑ',
|
||||
'ℜ' => 'ℜ',
|
||||
'™' => '™',
|
||||
'ℵ' => 'ℵ',
|
||||
'←' => '←',
|
||||
'↑' => '↑',
|
||||
'→' => '→',
|
||||
'↓' => '↓',
|
||||
'↔' => '↔',
|
||||
'↵' => '↵',
|
||||
'⇐' => '⇐',
|
||||
'⇑' => '⇑',
|
||||
'⇒' => '⇒',
|
||||
'⇓' => '⇓',
|
||||
'⇔' => '⇔',
|
||||
'∀' => '∀',
|
||||
'∂' => '∂',
|
||||
'∃' => '∃',
|
||||
'∅' => '∅',
|
||||
'∇' => '∇',
|
||||
'∈' => '∈',
|
||||
'∉' => '∉',
|
||||
'∋' => '∋',
|
||||
'∏' => '∏',
|
||||
'∑' => '∑',
|
||||
'−' => '−',
|
||||
'∗' => '∗',
|
||||
'√' => '√',
|
||||
'∝' => '∝',
|
||||
'∞' => '∞',
|
||||
'∠' => '∠',
|
||||
'∧' => '∧',
|
||||
'∨' => '∨',
|
||||
'∩' => '∩',
|
||||
'∪' => '∪',
|
||||
'∫' => '∫',
|
||||
'∴' => '∴',
|
||||
'∼' => '∼',
|
||||
'≅' => '≅',
|
||||
'≈' => '≈',
|
||||
'≠' => '≠',
|
||||
'≡' => '≡',
|
||||
'≤' => '≤',
|
||||
'≥' => '≥',
|
||||
'⊂' => '⊂',
|
||||
'⊃' => '⊃',
|
||||
'⊄' => '⊄',
|
||||
'⊆' => '⊆',
|
||||
'⊇' => '⊇',
|
||||
'⊕' => '⊕',
|
||||
'⊗' => '⊗',
|
||||
'⊥' => '⊥',
|
||||
'⋅' => '⋅',
|
||||
'⌈' => '⌈',
|
||||
'⌉' => '⌉',
|
||||
'⌊' => '⌊',
|
||||
'⌋' => '⌋',
|
||||
'⟨' => '〈',
|
||||
'⟩' => '〉',
|
||||
'◊' => '◊',
|
||||
'♠' => '♠',
|
||||
'♣' => '♣',
|
||||
'♥' => '♥',
|
||||
'♦' => '♦'));
|
||||
|
||||
339
wiki/scripts/forms.php
Executable file
339
wiki/scripts/forms.php
Executable file
@@ -0,0 +1,339 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2005-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
*/
|
||||
|
||||
# $InputAttrs are the attributes we allow in output tags
|
||||
SDV($InputAttrs, array('name', 'value', 'id', 'class', 'rows', 'cols',
|
||||
'size', 'maxlength', 'action', 'method', 'accesskey', 'tabindex', 'multiple',
|
||||
'checked', 'disabled', 'readonly', 'enctype', 'src', 'alt',
|
||||
'required', 'placeholder', 'autocomplete'
|
||||
));
|
||||
|
||||
# Set up formatting for text, submit, hidden, radio, etc. types
|
||||
foreach(array('text', 'submit', 'hidden', 'password', 'radio', 'checkbox',
|
||||
'reset', 'file', 'image') as $t)
|
||||
SDV($InputTags[$t][':html'], "<input type='$t' \$InputFormArgs />");
|
||||
SDV($InputTags['text']['class'], 'inputbox');
|
||||
SDV($InputTags['password']['class'], 'inputbox');
|
||||
SDV($InputTags['submit']['class'], 'inputbutton');
|
||||
SDV($InputTags['reset']['class'], 'inputbutton');
|
||||
SDV($InputTags['radio'][':checked'], 'checked');
|
||||
SDV($InputTags['checkbox'][':checked'], 'checked');
|
||||
|
||||
# (:input form:)
|
||||
SDVA($InputTags['form'], array(
|
||||
':args' => array('action', 'method'),
|
||||
':html' => "<form \$InputFormArgs>",
|
||||
'method' => 'post'));
|
||||
|
||||
# (:input end:)
|
||||
SDV($InputTags['end'][':html'], '</form>');
|
||||
|
||||
# (:input textarea:)
|
||||
SDVA($InputTags['textarea'], array(
|
||||
':content' => array('value'),
|
||||
':attr' => array_diff($InputAttrs, array('value')),
|
||||
':html' => "<textarea \$InputFormArgs>\$InputFormContent</textarea>"));
|
||||
|
||||
# (:input image:)
|
||||
SDV($InputTags['image'][':args'], array('name', 'src', 'alt'));
|
||||
|
||||
# (:input select:)
|
||||
SDVA($InputTags['select-option'], array(
|
||||
':args' => array('name', 'value', 'label'),
|
||||
':content' => array('label', 'value', 'name'),
|
||||
':attr' => array('value', 'selected'),
|
||||
':checked' => 'selected',
|
||||
':html' => "<option \$InputFormArgs>\$InputFormContent</option>"));
|
||||
SDVA($InputTags['select'], array(
|
||||
'class' => 'inputbox',
|
||||
':html' => "<select \$InputSelectArgs>\$InputSelectOptions</select>"));
|
||||
|
||||
# (:input defaults?:)
|
||||
SDVA($InputTags['default'], array(':fn' => 'InputDefault'));
|
||||
SDVA($InputTags['defaults'], array(':fn' => 'InputDefault'));
|
||||
|
||||
## (:input ...:) directives
|
||||
Markup_e('input', 'directives',
|
||||
'/\\(:input\\s+(\\w+)(.*?):\\)/i',
|
||||
"InputMarkup(\$pagename, \$m[1], \$m[2])");
|
||||
|
||||
## (:input select:) has its own markup processing
|
||||
Markup_e('input-select', '<input',
|
||||
'/\\(:input\\s+select\\s.*?:\\)(?:\\s*\\(:input\\s+select\\s.*?:\\))*/i',
|
||||
"InputSelect(\$pagename, 'select', \$m[0])");
|
||||
|
||||
## The 'input+sp' rule combines multiple (:input select ... :)
|
||||
## into a single markup line (to avoid split line effects)
|
||||
Markup('input+sp', '<split',
|
||||
'/(\\(:input\\s+select\\s(?>.*?:\\)))\\s+(?=\\(:input\\s)/', '$1');
|
||||
|
||||
SDV($InputFocusFmt,
|
||||
"<script language='javascript' type='text/javascript'><!--
|
||||
document.getElementById('\$InputFocusId').focus();//--></script>");
|
||||
|
||||
## InputToHTML performs standard processing on (:input ...:) arguments,
|
||||
## and returns the formatted HTML string.
|
||||
function InputToHTML($pagename, $type, $args, &$opt) {
|
||||
global $InputTags, $InputAttrs, $InputValues, $FmtV, $KeepToken,
|
||||
$InputFocusLevel, $InputFocusId, $InputFocusFmt, $HTMLFooterFmt;
|
||||
if (!@$InputTags[$type]) return "(:input $type $args:)";
|
||||
## get input arguments
|
||||
if (!is_array($args)) $args = ParseArgs($args, '(?>([\\w-]+)[:=])');
|
||||
## convert any positional arguments to named arguments
|
||||
$posnames = @$InputTags[$type][':args'];
|
||||
if (!$posnames) $posnames = array('name', 'value');
|
||||
while (count($posnames) > 0 && count(@$args['']) > 0) {
|
||||
$n = array_shift($posnames);
|
||||
if (!isset($args[$n])) $args[$n] = array_shift($args['']);
|
||||
}
|
||||
## merge defaults for input type with arguments
|
||||
$opt = array_merge($InputTags[$type], $args);
|
||||
## www.w3.org/TR/html4/types
|
||||
if(isset($opt['id'])) $opt['id'] = preg_replace('/[^-A-Za-z0-9:_.]+/', '_', $opt['id']);
|
||||
## convert any remaining positional args to flags
|
||||
foreach ((array)@$opt[''] as $a)
|
||||
{ $a = strtolower($a); if (!isset($opt[$a])) $opt[$a] = $a; }
|
||||
if (isset($opt['name'])) {
|
||||
$opt['name'] = preg_replace('/^\\$:/', 'ptv_', @$opt['name']);
|
||||
$opt['name'] = preg_replace('/[^-A-Za-z0-9:_.\\[\\]]+/', '_', $opt['name']);
|
||||
$name = $opt['name'];
|
||||
## set control values from $InputValues array
|
||||
## radio, checkbox, select, etc. require a flag of some sort,
|
||||
## others just set 'value'
|
||||
if (isset($InputValues[$name])) {
|
||||
$checked = @$opt[':checked'];
|
||||
if ($checked) {
|
||||
$opt[$checked] = in_array(@$opt['value'], (array)$InputValues[$name])
|
||||
? $checked : false;
|
||||
} else if (!isset($opt['value'])) $opt['value'] = $InputValues[$name];
|
||||
}
|
||||
}
|
||||
## build $InputFormContent
|
||||
$FmtV['$InputFormContent'] = '';
|
||||
foreach((array)@$opt[':content'] as $a)
|
||||
if (isset($opt[$a])) { $FmtV['$InputFormContent'] = $opt[$a]; break; }
|
||||
## hash and store any "secure" values
|
||||
if (@$opt['secure'] == '#') $opt['secure'] = rand();
|
||||
if (@$opt['secure'] > '') {
|
||||
$md5 = md5($opt['secure'] . $opt['value']);
|
||||
@session_start();
|
||||
$_SESSION['forms'][$md5] = $opt['value'];
|
||||
$opt['value'] = $md5;
|
||||
}
|
||||
## handle focus=# option
|
||||
$focus = @$opt['focus'];
|
||||
if (isset($focus)
|
||||
&& (!isset($InputFocusLevel) || $focus < $InputFocusLevel)) {
|
||||
if (!isset($opt['id'])) $opt['id'] = "wikifocus$focus";
|
||||
$InputFocusLevel = $focus;
|
||||
$InputFocusId = $opt['id'];
|
||||
$HTMLFooterFmt['inputfocus'] = $InputFocusFmt;
|
||||
}
|
||||
## build $InputFormArgs from $opt
|
||||
$attrlist = (isset($opt[':attr'])) ? $opt[':attr'] : $InputAttrs;
|
||||
$attr = array();
|
||||
foreach ($attrlist as $a) {
|
||||
if (!isset($opt[$a]) || $opt[$a]===false) continue;
|
||||
if(strpos($opt[$a], $KeepToken)!== false) # multiline textarea/hidden fields
|
||||
$opt[$a] = Keep(str_replace("'", ''', MarkupRestore($opt[$a]) ));
|
||||
$attr[] = "$a='".str_replace("'", ''', $opt[$a])."'";
|
||||
}
|
||||
$FmtV['$InputFormArgs'] = implode(' ', $attr);
|
||||
return FmtPageName($opt[':html'], $pagename);
|
||||
}
|
||||
|
||||
|
||||
## InputMarkup handles the (:input ...:) directive. It either
|
||||
## calls any function given by the :fn element of the corresponding
|
||||
## tag, or else just returns the result of InputToHTML().
|
||||
function InputMarkup($pagename, $type, $args) {
|
||||
global $InputTags;
|
||||
$fn = @$InputTags[$type][':fn'];
|
||||
if ($fn) return $fn($pagename, $type, $args);
|
||||
return Keep(InputToHTML($pagename, $type, $args, $opt));
|
||||
}
|
||||
|
||||
|
||||
## (:input default:) directive.
|
||||
function InputDefault($pagename, $type, $args) {
|
||||
global $InputValues, $PageTextVarPatterns, $PCache;
|
||||
$args = ParseArgs($args);
|
||||
$args[''] = (array)@$args[''];
|
||||
$name = (isset($args['name'])) ? $args['name'] : array_shift($args['']);
|
||||
$name = preg_replace('/^\\$:/', 'ptv_', $name);
|
||||
$value = (isset($args['value'])) ? $args['value'] : array_shift($args['']);
|
||||
if (!isset($InputValues[$name])) $InputValues[$name] = $value;
|
||||
if (@$args['request']) {
|
||||
$req = array_merge($_GET, $_POST);
|
||||
foreach($req as $k => $v)
|
||||
if (!isset($InputValues[$k]))
|
||||
$InputValues[$k] = PHSC(stripmagic($v), ENT_NOQUOTES);
|
||||
}
|
||||
$sources = @$args['source'];
|
||||
if ($sources) {
|
||||
foreach(explode(',', $sources) as $source) {
|
||||
$source = MakePageName($pagename, $source);
|
||||
if (!PageExists($source)) continue;
|
||||
$page = RetrieveAuthPage($source, 'read', false, READPAGE_CURRENT);
|
||||
if (! $page || ! isset($page['text'])) continue;
|
||||
foreach((array)$PageTextVarPatterns as $pat)
|
||||
if (preg_match_all($pat, IsEnabled($PCache[$source]['=preview'], $page['text']),
|
||||
$match, PREG_SET_ORDER))
|
||||
foreach($match as $m)
|
||||
# if (!isset($InputValues['ptv_'.$m[2]])) PITS:01337
|
||||
$InputValues['ptv_'.$m[2]] =
|
||||
PHSC(Qualify($source, $m[3]), ENT_NOQUOTES);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
## (:input select ...:) is special, because we need to process a bunch of
|
||||
## them as a single unit.
|
||||
function InputSelect($pagename, $type, $markup) {
|
||||
global $InputTags, $InputAttrs, $FmtV;
|
||||
preg_match_all('/\\(:input\\s+\\S+\\s+(.*?):\\)/', $markup, $match);
|
||||
$selectopt = (array)$InputTags[$type];
|
||||
$opt = $selectopt;
|
||||
$optionshtml = '';
|
||||
$optiontype = isset($InputTags["$type-option"])
|
||||
? "$type-option" : "select-option";
|
||||
foreach($match[1] as $args) {
|
||||
$optionshtml .= InputToHTML($pagename, $optiontype, $args, $oo);
|
||||
$opt = array_merge($opt, $oo);
|
||||
}
|
||||
$attrlist = array_diff($InputAttrs, array('value'));
|
||||
$attr = array();
|
||||
foreach($attrlist as $a) {
|
||||
if (!isset($opt[$a]) || $opt[$a]===false) continue;
|
||||
$attr[] = "$a='".str_replace("'", ''', $opt[$a])."'";
|
||||
}
|
||||
$FmtV['$InputSelectArgs'] = implode(' ', $attr);
|
||||
$FmtV['$InputSelectOptions'] = $optionshtml;
|
||||
return Keep(FmtPageName($selectopt[':html'], $pagename));
|
||||
}
|
||||
|
||||
|
||||
function InputActionForm($pagename, $type, $args) {
|
||||
global $InputAttrs;
|
||||
$args = ParseArgs($args);
|
||||
if (@$args['pagename']) $pagename = $args['pagename'];
|
||||
$opt = NULL;
|
||||
$html = InputToHTML($pagename, $type, $args, $opt);
|
||||
foreach(preg_grep('/^[\\w$]/', array_keys($args)) as $k) {
|
||||
if (is_array($args[$k]) || in_array($k, $InputAttrs)) continue;
|
||||
if ($k == 'n' || $k == 'pagename') continue;
|
||||
$html .= "<input type='hidden' name='$k' value='{$args[$k]}' />";
|
||||
}
|
||||
return Keep($html);
|
||||
}
|
||||
|
||||
|
||||
## RequestArgs is used to extract values from controls (typically
|
||||
## in $_GET and $_POST).
|
||||
function RequestArgs($req = NULL) {
|
||||
if (is_null($req)) $req = array_merge($_GET, $_POST);
|
||||
foreach ($req as $k => $v) $req[$k] = stripmagic($req[$k]);
|
||||
return $req;
|
||||
}
|
||||
|
||||
|
||||
## Form-based authorization prompts (for use with PmWikiAuth)
|
||||
SDVA($InputTags['auth_form'], array(
|
||||
':html' => "<form \$InputFormArgs>\$PostVars",
|
||||
'action' => str_replace("'", '%37', stripmagic($_SERVER['REQUEST_URI'])),
|
||||
'method' => 'post',
|
||||
'name' => 'authform'));
|
||||
SDV($AuthPromptFmt, array(&$PageStartFmt, 'page:$SiteGroup.AuthForm',
|
||||
"<script language='javascript' type='text/javascript'><!--
|
||||
try { document.authform.authid.focus(); }
|
||||
catch(e) { document.authform.authpw.focus(); } //--></script>",
|
||||
&$PageEndFmt));
|
||||
|
||||
## PITS:01188, these should exist in "browse" mode
|
||||
## NOTE: also defined in prefs.php
|
||||
XLSDV('en', array(
|
||||
'ak_save' => 's',
|
||||
'ak_saveedit' => 'u',
|
||||
'ak_preview' => 'p',
|
||||
'ak_textedit' => ',',
|
||||
'e_rows' => '23',
|
||||
'e_cols' => '60'));
|
||||
|
||||
## The section below handles specialized EditForm pages.
|
||||
## We don't bother to load it if we're not editing.
|
||||
|
||||
if ($action != 'edit') return;
|
||||
|
||||
SDV($PageEditForm, '$SiteGroup.EditForm');
|
||||
SDV($PageEditFmt, '$EditForm');
|
||||
if (@$_REQUEST['editform']) {
|
||||
$PageEditForm=$_REQUEST['editform'];
|
||||
$PageEditFmt='$EditForm';
|
||||
}
|
||||
$Conditions['e_preview'] = '(boolean)$_REQUEST["preview"]';
|
||||
|
||||
# (:e_preview:) displays the preview of formatted text.
|
||||
Markup_e('e_preview', 'directives',
|
||||
'/^\\(:e_preview:\\)/',
|
||||
"isset(\$GLOBALS['FmtV']['\$PreviewText']) ? Keep(\$GLOBALS['FmtV']['\$PreviewText']): ''");
|
||||
|
||||
# If we didn't load guiedit.php, then set (:e_guibuttons:) to
|
||||
# simply be empty.
|
||||
Markup('e_guibuttons', 'directives', '/\\(:e_guibuttons:\\)/', '');
|
||||
|
||||
# Prevent (:e_preview:) and (:e_guibuttons:) from
|
||||
# participating in text rendering step.
|
||||
SDV($SaveAttrPatterns['/\\(:e_(preview|guibuttons):\\)/'], ' ');
|
||||
|
||||
SDVA($InputTags['e_form'], array(
|
||||
':html' => "<form action='{\$PageUrl}?action=edit' method='post'
|
||||
\$InputFormArgs><input type='hidden' name='action' value='edit'
|
||||
/><input type='hidden' name='n' value='{\$FullName}'
|
||||
/><input type='hidden' name='basetime' value='\$EditBaseTime'
|
||||
/>"));
|
||||
SDVA($InputTags['e_textarea'], array(
|
||||
':html' => "<textarea \$InputFormArgs
|
||||
onkeydown='if (event.keyCode==27) event.returnValue=false;'
|
||||
>\$EditText</textarea>",
|
||||
'name' => 'text', 'id' => 'text', 'accesskey' => XL('ak_textedit'),
|
||||
'rows' => XL('e_rows'), 'cols' => XL('e_cols')));
|
||||
SDVA($InputTags['e_author'], array(
|
||||
':html' => "<input type='text' \$InputFormArgs />",
|
||||
'name' => 'author', 'value' => $Author));
|
||||
SDVA($InputTags['e_changesummary'], array(
|
||||
':html' => "<input type='text' \$InputFormArgs />",
|
||||
'name' => 'csum', 'size' => '60', 'maxlength' => '100',
|
||||
'value' => PHSC(stripmagic(@$_POST['csum']), ENT_QUOTES)));
|
||||
SDVA($InputTags['e_minorcheckbox'], array(
|
||||
':html' => "<input type='checkbox' \$InputFormArgs />",
|
||||
'name' => 'diffclass', 'value' => 'minor'));
|
||||
if (@$_POST['diffclass']=='minor')
|
||||
SDV($InputTags['e_minorcheckbox']['checked'], 'checked');
|
||||
SDVA($InputTags['e_savebutton'], array(
|
||||
':html' => "<input type='submit' \$InputFormArgs />",
|
||||
'name' => 'post', 'value' => ' '.XL('Save').' ',
|
||||
'accesskey' => XL('ak_save')));
|
||||
SDVA($InputTags['e_saveeditbutton'], array(
|
||||
':html' => "<input type='submit' \$InputFormArgs />",
|
||||
'name' => 'postedit', 'value' => ' '.XL('Save and edit').' ',
|
||||
'accesskey' => XL('ak_saveedit')));
|
||||
SDVA($InputTags['e_savedraftbutton'], array(':html' => ''));
|
||||
SDVA($InputTags['e_previewbutton'], array(
|
||||
':html' => "<input type='submit' \$InputFormArgs />",
|
||||
'name' => 'preview', 'value' => ' '.XL('Preview').' ',
|
||||
'accesskey' => XL('ak_preview')));
|
||||
SDVA($InputTags['e_cancelbutton'], array(
|
||||
':html' => "<input type='submit' \$InputFormArgs />",
|
||||
'name' => 'cancel', 'value' => ' '.XL('Cancel').' ' ));
|
||||
SDVA($InputTags['e_resetbutton'], array(
|
||||
':html' => "<input type='reset' \$InputFormArgs />",
|
||||
'value' => ' '.XL('Reset').' '));
|
||||
|
||||
82
wiki/scripts/guiedit.php
Executable file
82
wiki/scripts/guiedit.php
Executable file
@@ -0,0 +1,82 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2013 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script adds a graphical button bar to the edit page form.
|
||||
The buttons are placed in the $GUIButtons array; each button
|
||||
is specified by an array of five values:
|
||||
- the position of the button relative to others (a number)
|
||||
- the opening markup sequence
|
||||
- the closing markup sequence
|
||||
- the default text if none was highlighted
|
||||
- the text of the button, either (a) HTML markup or (b) the
|
||||
url of a gif/jpg/png image to be used for the button
|
||||
(along with optional "title" text in quotes).
|
||||
|
||||
The buttons specified in this file are the default buttons
|
||||
for the standard markups. Some buttons (e.g., the attach/upload
|
||||
button) are specified in their respective cookbook module.
|
||||
*/
|
||||
|
||||
SDVA($HTMLHeaderFmt, array('guiedit' => "<script type='text/javascript'
|
||||
src='\$FarmPubDirUrl/guiedit/guiedit.js'></script>\n"));
|
||||
|
||||
SDV($GUIButtonDirUrlFmt,'$FarmPubDirUrl/guiedit');
|
||||
|
||||
SDVA($GUIButtons, array(
|
||||
'em' => array(100, "''", "''", '$[Emphasized]',
|
||||
'$GUIButtonDirUrlFmt/em.gif"$[Emphasized (italic)]"',
|
||||
'$[ak_em]'),
|
||||
'strong' => array(110, "'''", "'''", '$[Strong]',
|
||||
'$GUIButtonDirUrlFmt/strong.gif"$[Strong (bold)]"',
|
||||
'$[ak_strong]'),
|
||||
'pagelink' => array(200, '[[', ']]', '$[Page link]',
|
||||
'$GUIButtonDirUrlFmt/pagelink.gif"$[Link to internal page]"'),
|
||||
'extlink' => array(210, '[[', ']]', 'http:// | $[link text]',
|
||||
'$GUIButtonDirUrlFmt/extlink.gif"$[Link to external page]"'),
|
||||
'big' => array(300, "'+", "+'", '$[Big text]',
|
||||
'$GUIButtonDirUrlFmt/big.gif"$[Big text]"'),
|
||||
'small' => array(310, "'-", "-'", '$[Small text]',
|
||||
'$GUIButtonDirUrlFmt/small.gif"$[Small text]"'),
|
||||
'sup' => array(320, "'^", "^'", '$[Superscript]',
|
||||
'$GUIButtonDirUrlFmt/sup.gif"$[Superscript]"'),
|
||||
'sub' => array(330, "'_", "_'", '$[Subscript]',
|
||||
'$GUIButtonDirUrlFmt/sub.gif"$[Subscript]"'),
|
||||
'h2' => array(400, '\\n!! ', '\\n', '$[Heading]',
|
||||
'$GUIButtonDirUrlFmt/h.gif"$[Heading]"'),
|
||||
'center' => array(410, '%center%', '', '',
|
||||
'$GUIButtonDirUrlFmt/center.gif"$[Center]"')));
|
||||
|
||||
Markup_e('e_guibuttons', 'directives',
|
||||
'/\\(:e_guibuttons:\\)/',
|
||||
"Keep(FmtPageName(GUIButtonCode(\$pagename), \$pagename))");
|
||||
|
||||
function GUIButtonCode($pagename) {
|
||||
global $GUIButtons;
|
||||
$cmpfn = create_function('$a,$b', 'return $a[0]-$b[0];');
|
||||
usort($GUIButtons, $cmpfn);
|
||||
$out = "<script type='text/javascript'><!--\n";
|
||||
foreach ($GUIButtons as $k => $g) {
|
||||
if (!$g) continue;
|
||||
@list($when, $mopen, $mclose, $mtext, $tag, $mkey) = $g;
|
||||
if ($tag{0} == '<') {
|
||||
$out .= "document.write(\"$tag\");\n";
|
||||
continue;
|
||||
}
|
||||
if (preg_match('/^(.*\\.(gif|jpg|png))("([^"]+)")?$/', $tag, $m)) {
|
||||
$title = (@$m[4] > '') ? "title='{$m[4]}'" : '';
|
||||
$tag = "<img src='{$m[1]}' $title style='border:0px;' />";
|
||||
}
|
||||
$mopen = str_replace(array('\\', "'"), array('\\\\', "\\\\'"), $mopen);
|
||||
$mclose = str_replace(array('\\', "'"), array('\\\\', "\\\\'"), $mclose);
|
||||
$mtext = str_replace(array('\\', "'"), array('\\\\', "\\\\'"), $mtext);
|
||||
$out .=
|
||||
"insButton(\"$mopen\", \"$mclose\", '$mtext', \"$tag\", \"$mkey\");\n";
|
||||
}
|
||||
$out .= '//--></script>';
|
||||
return $out;
|
||||
}
|
||||
|
||||
46
wiki/scripts/httpauth.php
Executable file
46
wiki/scripts/httpauth.php
Executable file
@@ -0,0 +1,46 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2005 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file defines an alternate authentication scheme based on the
|
||||
HTTP Basic authentication protocol (i.e., the scheme used by default
|
||||
in PmWiki 1).
|
||||
*/
|
||||
|
||||
## If the webserver has already authenticated someone, then use
|
||||
## that identifier for our authorization id. We also disable
|
||||
## the use of the browser's Basic Auth form later, since it tends
|
||||
## to confuse webservers.
|
||||
if (IsEnabled($EnableRemoteUserAuth, 1) && @$_SERVER['REMOTE_USER']) {
|
||||
SDV($EnableHTTPBasicAuth, 0);
|
||||
SDV($AuthId, $_SERVER['REMOTE_USER']);
|
||||
}
|
||||
|
||||
## If the browser supplied a password, add that password to the
|
||||
## list of passwords used for authentication
|
||||
if (@$_SERVER['PHP_AUTH_PW'])
|
||||
SessionAuth($pagename, array('authpw'=>array($_SERVER['PHP_AUTH_PW'] => 1)));
|
||||
|
||||
|
||||
## $EnableHTTPBasicAuth tells PmWikiAuth to use the browser's
|
||||
## HTTP Basic protocol prompt instead of a form-based prompt.
|
||||
if (IsEnabled($EnableHTTPBasicAuth, 1))
|
||||
SDV($AuthPromptFmt, 'function:HTTPBasicAuthPrompt');
|
||||
|
||||
## HTTPBasicAuthPrompt replaces PmWikiAuth's form-based password
|
||||
## prompt with the browser-based HTTP Basic prompt.
|
||||
function HTTPBasicAuthPrompt($pagename) {
|
||||
global $AuthRealmFmt, $AuthDeniedFmt;
|
||||
SDV($AuthRealmFmt,$GLOBALS['WikiTitle']);
|
||||
SDV($AuthDeniedFmt,'A valid password is required to access this feature.');
|
||||
$realm=FmtPageName($AuthRealmFmt,$pagename);
|
||||
header("WWW-Authenticate: Basic realm=\"$realm\"");
|
||||
header("Status: 401 Unauthorized");
|
||||
header("HTTP-Status: 401 Unauthorized");
|
||||
PrintFmt($pagename,$AuthDeniedFmt);
|
||||
exit;
|
||||
}
|
||||
|
||||
10
wiki/scripts/intermap.txt
Executable file
10
wiki/scripts/intermap.txt
Executable file
@@ -0,0 +1,10 @@
|
||||
PmWiki: http://www.pmwiki.org/wiki/PmWiki/
|
||||
Cookbook: http://www.pmwiki.org/wiki/Cookbook/
|
||||
Skins: http://www.pmwiki.org/wiki/Skins/
|
||||
Wiki: http://www.c2.com/cgi/wiki?
|
||||
UseMod: http://www.usemod.com/cgi-bin/wiki.pl?
|
||||
Meatball: http://www.usemod.com/cgi-bin/mb.pl?
|
||||
Wikipedia: http://en.wikipedia.org/wiki/
|
||||
PITS: http://www.pmwiki.org/wiki/PITS/
|
||||
PmL10n: http://www.pmwiki.org/wiki/Localization/
|
||||
Path:
|
||||
124
wiki/scripts/markupexpr.php
Executable file
124
wiki/scripts/markupexpr.php
Executable file
@@ -0,0 +1,124 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2007-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script implements "markup expressions" -- a method to
|
||||
do simple computations and manipulations from markup. The
|
||||
generic form of a markup expression is "{(func arg1 arg2)}",
|
||||
where the named function (held in the $MarkupExpr array)
|
||||
is called with arg1 and arg2 as arguments.
|
||||
|
||||
Markup expressions can be nested. For example, to strip
|
||||
off the first five characters and convert the remainder to
|
||||
lowercase, an author can write:
|
||||
|
||||
{(tolower (substr "HELLOWORLD" 5))} # produces "world"
|
||||
|
||||
Some "built-in" expressions defined by this recipe include:
|
||||
substr - extract a portion of a string
|
||||
ftime - date/time formatting
|
||||
strlen - length of a string
|
||||
rand - generate a random number
|
||||
pagename - build a pagename from a string
|
||||
toupper - convert string to uppercase
|
||||
tolower - convert string to lowercase
|
||||
ucfirst - convert first character to uppercase
|
||||
ucwords - convert first character of each word to uppercase
|
||||
asspaced - spaceformatting of wikiwords
|
||||
|
||||
Custom expressions may be added by other recipes by adding
|
||||
entries into the $MarkupExpr array. Each entry's key is
|
||||
the name of the function, the value is the code to be evaluated
|
||||
for that function (similar to the way $FmtPV works). By default,
|
||||
any arguments for the expression are placed into the $args array:
|
||||
|
||||
## expressions like {(myfunc foo bar)}
|
||||
$MarkupExpr['myfunc'] = 'myfunc($args[0], $args[1])';
|
||||
|
||||
The expression arguments are parsed using ParseArgs(), and the
|
||||
result of this parsing is available through the $argp array:
|
||||
|
||||
## expressions like {(myfunc fmt=foo output=bar)}
|
||||
$MarkupExpr['myfunc'] = 'myfunc($argp["fmt"], $argp["output"])';
|
||||
|
||||
Finally, if the code in $MarkupExpr contains '$params', then
|
||||
it is executed directly without any preprocessing into arguments,
|
||||
and $params contains the entire argument string. Note that $params
|
||||
may contain escaped values representing quoted arguments and
|
||||
results of other expressions; these values may be un-escaped
|
||||
by using "preg_replace($rpat, $rrep, $params)".
|
||||
*/
|
||||
Markup_e('{(', '>{$var}',
|
||||
'/\\{(\\(\\w+\\b.*?\\))\\}/',
|
||||
"MarkupExpression(\$pagename, \$m[1])");
|
||||
|
||||
SDVA($MarkupExpr, array(
|
||||
'substr' => 'call_user_func_array("substr", $args)',
|
||||
'strlen' => 'strlen($args[0])',
|
||||
'ftime' => 'ME_ftime(@$args[0], @$args[1], $argp)',
|
||||
'rand' => '($args) ? rand($args[0], $args[1]) : rand()',
|
||||
'ucfirst' => 'ucfirst($args[0])',
|
||||
'ucwords' => 'ucwords($args[0])',
|
||||
'tolower' => 'strtolower($args[0])',
|
||||
'toupper' => 'strtoupper($args[0])',
|
||||
'mod' => '0 + ($args[0] % $args[1])',
|
||||
'asspaced' => '$GLOBALS["AsSpacedFunction"]($args[0])',
|
||||
'pagename' => 'MakePageName($pagename, PPRE($rpat, $rrep, $params))',
|
||||
));
|
||||
|
||||
function MarkupExpression($pagename, $expr) {
|
||||
global $KeepToken, $KPV, $MarkupExpr;
|
||||
$rpat = "/$KeepToken(\\d+P)$KeepToken/";
|
||||
$rrep = '$GLOBALS["KPV"][$m[1]]';
|
||||
$expr = PPRE('/([\'"])(.*?)\\1/', "Keep(\$m[2],'P')", $expr);
|
||||
$expr = PPRE('/\\(\\W/', "Keep(\$m[0],'P')", $expr);
|
||||
while (preg_match('/\\((\\w+)(\\s[^()]*)?\\)/', $expr, $match)) {
|
||||
list($repl, $func, $params) = $match;
|
||||
$code = @$MarkupExpr[$func];
|
||||
## if not a valid function, save this string as-is and exit
|
||||
if (!$code) break;
|
||||
## if the code uses '$params', we just evaluate directly
|
||||
if (strpos($code, '$params') !== false) {
|
||||
$out = eval("return ({$code});");
|
||||
if ($expr == $repl) { $expr = $out; break; }
|
||||
$expr = str_replace($repl, $out, $expr);
|
||||
continue;
|
||||
}
|
||||
## otherwise, we parse arguments into $args before evaluating
|
||||
$argp = ParseArgs($params);
|
||||
$x = $argp['#']; $args = array();
|
||||
while ($x) {
|
||||
list($k, $v) = array_splice($x, 0, 2);
|
||||
if ($k == '' || $k == '+' || $k == '-')
|
||||
$args[] = $k.PPRE($rpat, $rrep, $v);
|
||||
}
|
||||
## fix any quoted arguments
|
||||
foreach ($argp as $k => $v)
|
||||
if (!is_array($v)) $argp[$k] = PPRE($rpat, $rrep, $v);
|
||||
$out = eval("return ({$code});");
|
||||
if ($expr == $repl) { $expr = $out; break; }
|
||||
$expr = str_replace($repl, Keep($out, 'P'), $expr);
|
||||
}
|
||||
return PPRE($rpat, $rrep, $expr);
|
||||
}
|
||||
|
||||
## ME_ftime handles {(ftime ...)} expressions.
|
||||
##
|
||||
function ME_ftime($arg0 = '', $arg1 = '', $argp = NULL) {
|
||||
global $TimeFmt, $Now, $FTimeFmt;
|
||||
if (@$argp['fmt']) $fmt = $argp['fmt'];
|
||||
else if (strpos($arg0, '%') !== false) { $fmt = $arg0; $arg0 = $arg1; }
|
||||
else if (strpos($arg1, '%') !== false) $fmt = $arg1;
|
||||
## determine the timestamp
|
||||
if (isset($argp['when'])) list($time, $x) = DRange($argp['when']);
|
||||
else if ($arg0 > '') list($time, $x) = DRange($arg0);
|
||||
else $time = $Now;
|
||||
if (@$fmt == '') { SDV($FTimeFmt, $TimeFmt); $fmt = $FTimeFmt; }
|
||||
## make sure we have %F available for ISO dates
|
||||
$fmt = str_replace(array('%F', '%s'), array('%Y-%m-%d', $time), $fmt);
|
||||
return strftime($fmt, $time);
|
||||
}
|
||||
|
||||
197
wiki/scripts/notify.php
Executable file
197
wiki/scripts/notify.php
Executable file
@@ -0,0 +1,197 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2006-2011 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script enables email notifications to be sent when posts
|
||||
are made. It is included by default from the stdconfig.php
|
||||
script if $EnableNotify is set to non-zero.
|
||||
|
||||
Once enabled, the addresses to receive messages are configured
|
||||
via the Site.NotifyList page. A simple line in that page
|
||||
such as
|
||||
|
||||
notify=somebody@example.com
|
||||
|
||||
will cause messages to be periodically sent to "somebody@example.com"
|
||||
listing the pages that have changed on the site since the previous
|
||||
message was sent. Multiple notify lines can be placed in the page,
|
||||
and there are options to restrict the types of notifications
|
||||
desired. For more details, see the PmWiki.Notify page in
|
||||
the documentation.
|
||||
|
||||
Several variables set defaults for this script:
|
||||
|
||||
$NotifyFrom - return email address to use in message.
|
||||
$NotifyDelay - number of seconds to wait before sending mail
|
||||
after the first post.
|
||||
$NotifySquelch - minimum number of seconds between sending email
|
||||
messages to each address. Individual "notify=" lines in
|
||||
Site.NotifyList can override this value via a custom "squelch="
|
||||
parameter.
|
||||
$NotifyFile - scratchpad file used to keep track of pending emails.
|
||||
$NotifyListPageFmt - name of the NotifyList configuration page.
|
||||
$NotifySubjectFmt - subject line for sent messages.
|
||||
$NotifyBodyFmt - body of message to be sent. The string '$NotifyItems'
|
||||
is replaced with the list of posts in the email.
|
||||
$NotifyItemFmt - the format for each post to be included in a notification.
|
||||
$NotifyTimeFmt - the format for dates and times ($PostTime)
|
||||
in notification messages.
|
||||
$NotifyHeaders - any additional message headers to be sent.
|
||||
$NotifyParameters - any additional parameters to be passed to PHP's
|
||||
mail() function.
|
||||
*/
|
||||
|
||||
SDV($NotifyDelay, 0);
|
||||
SDV($NotifySquelch, 10800);
|
||||
SDV($NotifyFile, "$WorkDir/.notifylist");
|
||||
SDV($NotifyListPageFmt, '$SiteAdminGroup.NotifyList');
|
||||
SDV($NotifySubjectFmt, '[$WikiTitle] recent notify posts');
|
||||
SDV($NotifyBodyFmt,
|
||||
"Recent \$WikiTitle posts:\n"
|
||||
. " \$ScriptUrl/$[{\$SiteGroup}/AllRecentChanges]\n\n\$NotifyItems\n");
|
||||
SDV($NotifyTimeFmt, $TimeFmt);
|
||||
SDV($NotifyItemFmt,
|
||||
' * {$FullName} . . . $PostTime by {$Author}');
|
||||
SDV($NotifyHeaders, '');
|
||||
SDV($NotifyParameters, '');
|
||||
|
||||
if (@$NotifyFrom)
|
||||
$NotifyHeaders = "From: $NotifyFrom\r\n$NotifyHeaders";
|
||||
|
||||
$EditFunctions[] = 'PostNotify';
|
||||
|
||||
## check if we need to do notifications
|
||||
if ($action != 'edit' && $action != 'postupload') NotifyCheck($pagename);
|
||||
|
||||
|
||||
function NotifyCheck($pagename) {
|
||||
global $NotifyFile, $Now, $LastModTime;
|
||||
$nfp = @fopen($NotifyFile, 'r');
|
||||
if (!$nfp) return;
|
||||
$nextevent = fgets($nfp);
|
||||
fclose($nfp);
|
||||
if ($Now < $nextevent && $LastModTime < filemtime($NotifyFile)) return;
|
||||
register_shutdown_function('NotifyUpdate', $pagename, getcwd());
|
||||
}
|
||||
|
||||
|
||||
function PostNotify($pagename, &$page, &$new) {
|
||||
global $IsPagePosted;
|
||||
if ($IsPagePosted)
|
||||
register_shutdown_function('NotifyUpdate', $pagename, getcwd());
|
||||
}
|
||||
|
||||
|
||||
function NotifyUpdate($pagename, $dir='') {
|
||||
global $NotifyList, $NotifyListPageFmt, $NotifyFile, $IsPagePosted, $IsUploadPosted,
|
||||
$FmtV, $NotifyTimeFmt, $NotifyItemFmt, $SearchPatterns,
|
||||
$NotifySquelch, $NotifyDelay, $Now, $Charset, $EnableNotifySubjectEncode,
|
||||
$NotifySubjectFmt, $NotifyBodyFmt, $NotifyHeaders, $NotifyParameters;
|
||||
|
||||
$abort = ignore_user_abort(true);
|
||||
if ($dir) { flush(); chdir($dir); }
|
||||
|
||||
$GLOBALS['EnableRedirect'] = 0;
|
||||
|
||||
## Read in the current notify configuration
|
||||
$pn = FmtPageName($NotifyListPageFmt, $pagename);
|
||||
$npage = ReadPage($pn, READPAGE_CURRENT);
|
||||
preg_match_all('/^[\s*:#->]*(notify[:=].*)/m', $npage['text'], $nlist);
|
||||
$nlist = array_merge((array)@$NotifyList, (array)@$nlist[1]);
|
||||
if (!$nlist) return;
|
||||
|
||||
## make sure other processes are locked out
|
||||
Lock(2);
|
||||
|
||||
## let's load the current .notifylist table
|
||||
$nfile = FmtPageName($NotifyFile, $pagename);
|
||||
$nfp = @fopen($nfile, 'r');
|
||||
if ($nfp) {
|
||||
## get our current squelch and delay timestamps
|
||||
clearstatcache();
|
||||
$sz = filesize($nfile);
|
||||
list($nextevent, $firstpost) = explode(' ', rtrim(fgets($nfp, $sz)));
|
||||
## restore our notify array
|
||||
$notify = unserialize(fgets($nfp, $sz));
|
||||
fclose($nfp);
|
||||
}
|
||||
if (!is_array($notify)) $notify = array();
|
||||
|
||||
## if this is for a newly posted page, get its information
|
||||
if ($IsPagePosted || $IsUploadPosted) {
|
||||
$page = ReadPage($pagename, READPAGE_CURRENT);
|
||||
$FmtV['$PostTime'] = strftime($NotifyTimeFmt, $Now);
|
||||
$item = urlencode(FmtPageName($NotifyItemFmt, $pagename));
|
||||
if ($firstpost < 1) $firstpost = $Now;
|
||||
}
|
||||
|
||||
foreach($nlist as $n) {
|
||||
$opt = ParseArgs($n);
|
||||
$mailto = preg_split('/[\s,]+/', $opt['notify']);
|
||||
if (!$mailto) continue;
|
||||
if ($opt['squelch'])
|
||||
foreach($mailto as $m) $squelch[$m] = $opt['squelch'];
|
||||
if (!$IsPagePosted) continue;
|
||||
if ($opt['link']) {
|
||||
$link = MakePageName($pagename, $opt['link']);
|
||||
if (!preg_match("/(^|,)$link(,|$)/i", $page['targets'])) continue;
|
||||
}
|
||||
$pats = @(array)$SearchPatterns[$opt['list']];
|
||||
if ($opt['group']) $pats[] = FixGlob($opt['group'], '$1$2.*');
|
||||
if ($opt['name']) $pats[] = FixGlob($opt['name'], '$1*.$2');
|
||||
if ($pats && !MatchPageNames($pagename, $pats)) continue;
|
||||
if ($opt['trail']) {
|
||||
$trail = ReadTrail($pagename, $opt['trail']);
|
||||
for ($i=0; $i<count($trail); $i++)
|
||||
if ($trail[$i]['pagename'] == $pagename) break;
|
||||
if ($i >= count($trail)) continue;
|
||||
}
|
||||
foreach($mailto as $m) { $notify[$m][] = $item; }
|
||||
}
|
||||
|
||||
$nnow = time();
|
||||
if ($nnow < $firstpost + $NotifyDelay)
|
||||
$nextevent = $firstpost + $NotifyDelay;
|
||||
else {
|
||||
$firstpost = 0;
|
||||
$nextevent = $nnow + 86400;
|
||||
$mailto = array_keys($notify);
|
||||
$subject = FmtPageName($NotifySubjectFmt, $pagename);
|
||||
if(IsEnabled($EnableNotifySubjectEncode, 0)
|
||||
&& preg_match("/[^\x20-\x7E]/", $subject))
|
||||
$subject = strtoupper("=?$Charset?B?"). base64_encode($subject)."?=";
|
||||
$body = FmtPageName($NotifyBodyFmt, $pagename);
|
||||
foreach ($mailto as $m) {
|
||||
$msquelch = @$notify[$m]['lastmail'] +
|
||||
((@$squelch[$m]) ? $squelch[$m] : $NotifySquelch);
|
||||
if ($nnow < $msquelch) {
|
||||
if ($msquelch < $nextevent && count($notify[$m])>1)
|
||||
$nextevent = $msquelch;
|
||||
continue;
|
||||
}
|
||||
unset($notify[$m]['lastmail']);
|
||||
if (!$notify[$m]) { unset($notify[$m]); continue; }
|
||||
$mbody = str_replace('$NotifyItems',
|
||||
urldecode(implode("\n", $notify[$m])), $body);
|
||||
if ($NotifyParameters && !@ini_get('safe_mode'))
|
||||
mail($m, $subject, $mbody, $NotifyHeaders, $NotifyParameters);
|
||||
else
|
||||
mail($m, $subject, $mbody, $NotifyHeaders);
|
||||
$notify[$m] = array('lastmail' => $nnow);
|
||||
}
|
||||
}
|
||||
|
||||
## save the updated notify status
|
||||
$nfp = @fopen($nfile, "w");
|
||||
if ($nfp) {
|
||||
fputs($nfp, "$nextevent $firstpost\n");
|
||||
fputs($nfp, serialize($notify) . "\n");
|
||||
fclose($nfp);
|
||||
}
|
||||
Lock(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
856
wiki/scripts/pagelist.php
Executable file
856
wiki/scripts/pagelist.php
Executable file
@@ -0,0 +1,856 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script implements (:pagelist:) and friends -- it's one
|
||||
of the nastiest scripts you'll ever encounter. Part of the reason
|
||||
for this is that page listings are so powerful and flexible, so
|
||||
that adds complexity. They're also expensive, so we have to
|
||||
optimize them wherever we can.
|
||||
|
||||
The core function is FmtPageList(), which will generate a
|
||||
listing according to a wide variety of options. FmtPageList takes
|
||||
care of initial option processing, and then calls a "FPL"
|
||||
(format page list) function to obtain the formatted output.
|
||||
The FPL function is chosen by the 'fmt=' option to (:pagelist:).
|
||||
|
||||
Each FPL function calls MakePageList() to obtain the list
|
||||
of pages, formats the list somehow, and returns the results
|
||||
to FmtPageList. FmtPageList then returns the output to
|
||||
the caller, and calls Keep() (preserves HTML) or PRR() (re-evaluate
|
||||
as markup) as appropriate for the output being returned.
|
||||
*/
|
||||
|
||||
## $PageIndexFile is the index file for term searches and link= option
|
||||
if (IsEnabled($EnablePageIndex, 1)) {
|
||||
SDV($PageIndexFile, "$WorkDir/.pageindex");
|
||||
$EditFunctions[] = 'PostPageIndex';
|
||||
}
|
||||
|
||||
SDV($StrFoldFunction, 'strtolower');
|
||||
|
||||
## $SearchPatterns holds patterns for list= option
|
||||
SDV($SearchPatterns['all'], array());
|
||||
SDVA($SearchPatterns['normal'], array(
|
||||
'recent' => '!\.(All)?Recent(Changes|Uploads)$!',
|
||||
'group' => '!\.Group(Print)?(Header|Footer|Attributes)$!',
|
||||
'self' => str_replace('.', '\\.', "!^$pagename$!")));
|
||||
|
||||
## $FPLFormatOpt is a list of options associated with fmt=
|
||||
## values. 'default' is used for any undefined values of fmt=.
|
||||
SDVA($FPLFormatOpt, array(
|
||||
'default' => array('fn' => 'FPLTemplate', 'fmt' => '#default'),
|
||||
'bygroup' => array('fn' => 'FPLTemplate', 'template' => '#bygroup',
|
||||
'class' => 'fplbygroup'),
|
||||
'simple' => array('fn' => 'FPLTemplate', 'template' => '#simple',
|
||||
'class' => 'fplsimple'),
|
||||
'group' => array('fn' => 'FPLTemplate', 'template' => '#group',
|
||||
'class' => 'fplgroup'),
|
||||
'title' => array('fn' => 'FPLTemplate', 'template' => '#title',
|
||||
'class' => 'fpltitle', 'order' => 'title'),
|
||||
'count' => array('fn' => 'FPLCountA'),
|
||||
));
|
||||
|
||||
SDV($SearchResultsFmt, "<div class='wikisearch'>\$[SearchFor]
|
||||
<div class='vspace'></div>\$MatchList
|
||||
<div class='vspace'></div>\$[SearchFound]</div>");
|
||||
SDV($SearchQuery, str_replace('$', '$',
|
||||
PHSC(stripmagic(@$_REQUEST['q']), ENT_NOQUOTES)));
|
||||
XLSDV('en', array(
|
||||
'SearchFor' => 'Results of search for <em>$Needle</em>:',
|
||||
'SearchFound' =>
|
||||
'$MatchCount pages found out of $MatchSearched pages searched.'));
|
||||
|
||||
SDV($PageListArgPattern, '((?:\\$:?)?\\w+)[:=]');
|
||||
|
||||
Markup_e('pagelist', 'directives',
|
||||
'/\\(:pagelist(\\s+.*?)?:\\)/i',
|
||||
"FmtPageList('\$MatchList', \$pagename, array('o' => \$m[1].' '))");
|
||||
Markup_e('searchbox', 'directives',
|
||||
'/\\(:searchbox(\\s.*?)?:\\)/',
|
||||
"SearchBox(\$pagename, ParseArgs(\$m[1], '$PageListArgPattern'))");
|
||||
Markup_e('searchresults', 'directives',
|
||||
'/\\(:searchresults(\\s+.*?)?:\\)/i',
|
||||
"FmtPageList(\$GLOBALS['SearchResultsFmt'], \$pagename,
|
||||
array('req' => 1, 'request'=>1, 'o' => \$m[1]))");
|
||||
|
||||
SDV($SaveAttrPatterns['/\\(:(searchresults|pagelist)(\\s+.*?)?:\\)/i'], ' ');
|
||||
|
||||
SDV($HandleActions['search'], 'HandleSearchA');
|
||||
SDV($HandleAuth['search'], 'read');
|
||||
SDV($ActionTitleFmt['search'], '| $[Search Results]');
|
||||
|
||||
SDVA($PageListFilters, array(
|
||||
'PageListCache' => 80,
|
||||
'PageListProtect' => 90,
|
||||
'PageListSources' => 100,
|
||||
'PageListPasswords' => 120,
|
||||
'PageListIf' => 140,
|
||||
'PageListTermsTargets' => 160,
|
||||
'PageListVariables' => 180,
|
||||
'PageListSort' => 900,
|
||||
));
|
||||
|
||||
foreach(array('random', 'size', 'time', 'ctime') as $o)
|
||||
SDV($PageListSortCmp[$o], "@(\$PCache[\$x]['$o']-\$PCache[\$y]['$o'])");
|
||||
SDV($PageListSortCmp['title'],
|
||||
'@strcasecmp($PCache[$x][\'=title\'], $PCache[$y][\'=title\'])');
|
||||
|
||||
define('PAGELIST_PRE' , 1);
|
||||
define('PAGELIST_ITEM', 2);
|
||||
define('PAGELIST_POST', 4);
|
||||
|
||||
## SearchBox generates the output of the (:searchbox:) markup.
|
||||
## If $SearchBoxFmt is defined, that is used, otherwise a searchbox
|
||||
## is generated. Options include group=, size=, label=.
|
||||
function SearchBox($pagename, $opt) {
|
||||
global $SearchBoxFmt, $SearchBoxOpt, $SearchQuery, $EnablePathInfo;
|
||||
if (isset($SearchBoxFmt)) return Keep(FmtPageName($SearchBoxFmt, $pagename));
|
||||
SDVA($SearchBoxOpt, array('size' => '40',
|
||||
'label' => FmtPageName('$[Search]', $pagename),
|
||||
'value' => str_replace("'", "'", $SearchQuery)));
|
||||
$opt = array_merge((array)$SearchBoxOpt, @$_GET, (array)$opt);
|
||||
$opt['action'] = 'search';
|
||||
$target = (@$opt['target'])
|
||||
? MakePageName($pagename, $opt['target']) : $pagename;
|
||||
$opt['n'] = IsEnabled($EnablePathInfo, 0) ? '' : $target;
|
||||
$out = FmtPageName(" class='wikisearch' action='\$PageUrl' method='get'>",
|
||||
$target);
|
||||
foreach($opt as $k => $v) {
|
||||
if ($v == '' || is_array($v)) continue;
|
||||
$v = str_replace("'", "'", $v);
|
||||
$opt[$k] = $v;
|
||||
if ($k == 'q' || $k == 'label' || $k == 'value' || $k == 'size') continue;
|
||||
$k = str_replace("'", "'", $k);
|
||||
$out .= "<input type='hidden' name='$k' value='$v' />";
|
||||
}
|
||||
$out .= "<input type='text' name='q' value='{$opt['value']}'
|
||||
class='inputbox searchbox' size='{$opt['size']}' /><input type='submit'
|
||||
class='inputbutton searchbutton' value='{$opt['label']}' />";
|
||||
return '<form '.Keep($out).'</form>';
|
||||
}
|
||||
|
||||
|
||||
## FmtPageList combines options from markup, request form, and url,
|
||||
## calls the appropriate formatting function, and returns the string.
|
||||
function FmtPageList($outfmt, $pagename, $opt) {
|
||||
global $GroupPattern, $FmtV, $PageListArgPattern,
|
||||
$FPLFormatOpt, $FPLFunctions;
|
||||
# get any form or url-submitted request
|
||||
$rq = PHSC(stripmagic(@$_REQUEST['q']), ENT_NOQUOTES);
|
||||
# build the search string
|
||||
$FmtV['$Needle'] = $opt['o'] . ' ' . $rq;
|
||||
# Handle "group/" at the beginning of the form-submitted request
|
||||
if (preg_match("!^($GroupPattern(\\|$GroupPattern)*)?/!i", $rq, $match)) {
|
||||
$opt['group'] = @$match[1];
|
||||
$rq = substr($rq, strlen(@$match[1])+1);
|
||||
}
|
||||
$opt = array_merge($opt, ParseArgs($opt['o'], $PageListArgPattern));
|
||||
# merge markup options with form and url
|
||||
if (@$opt['request'] && @$_REQUEST) {
|
||||
$rkeys = preg_grep('/^=/', array_keys($_REQUEST), PREG_GREP_INVERT);
|
||||
if ($opt['request'] != '1') {
|
||||
list($incl, $excl) = GlobToPCRE($opt['request']);
|
||||
if ($excl) $rkeys = array_diff($rkeys, preg_grep("/$excl/", $rkeys));
|
||||
if ($incl) $rkeys = preg_grep("/$incl/", $rkeys);
|
||||
}
|
||||
$cleanrequest = array();
|
||||
foreach($rkeys as $k) {
|
||||
$cleanrequest[$k] = stripmagic($_REQUEST[$k]);
|
||||
}
|
||||
$opt = array_merge($opt, ParseArgs($rq, $PageListArgPattern), $cleanrequest);
|
||||
}
|
||||
|
||||
# non-posted blank search requests return nothing
|
||||
if (@($opt['req'] && !$opt['-'] && !$opt[''] && !$opt['+'] && !$opt['q']))
|
||||
return '';
|
||||
# terms and group to be included and excluded
|
||||
$GLOBALS['SearchIncl'] = array_merge((array)@$opt[''], (array)@$opt['+']);
|
||||
$GLOBALS['SearchExcl'] = (array)@$opt['-'];
|
||||
$GLOBALS['SearchGroup'] = @$opt['group'];
|
||||
$fmt = @$opt['fmt']; if (!$fmt) $fmt = 'default';
|
||||
$fmtopt = @$FPLFormatOpt[$fmt];
|
||||
if (!is_array($fmtopt)) {
|
||||
if ($fmtopt) $fmtopt = array('fn' => $fmtopt);
|
||||
elseif (@$FPLFunctions[$fmt])
|
||||
$fmtopt = array('fn' => $FPLFunctions[$fmt]);
|
||||
else $fmtopt = $FPLFormatOpt['default'];
|
||||
}
|
||||
$fmtfn = @$fmtopt['fn'];
|
||||
if (!is_callable($fmtfn)) $fmtfn = $FPLFormatOpt['default']['fn'];
|
||||
$matches = array();
|
||||
$opt = array_merge($fmtopt, $opt);
|
||||
$out = $fmtfn($pagename, $matches, $opt);
|
||||
$FmtV['$MatchCount'] = count($matches);
|
||||
if ($outfmt != '$MatchList')
|
||||
{ $FmtV['$MatchList'] = $out; $out = FmtPageName($outfmt, $pagename); }
|
||||
if ($out[0] == '<') $out = Keep($out);
|
||||
return PRR($out);
|
||||
}
|
||||
|
||||
|
||||
## MakePageList generates a list of pages using the specifications given
|
||||
## by $opt.
|
||||
function MakePageList($pagename, $opt, $retpages = 1) {
|
||||
global $MakePageListOpt, $PageListFilters, $PCache;
|
||||
|
||||
StopWatch('MakePageList pre');
|
||||
SDVA($MakePageListOpt, array('list' => 'default'));
|
||||
$opt = array_merge((array)$MakePageListOpt, (array)$opt);
|
||||
if (!@$opt['order'] && !@$opt['trail']) $opt['order'] = 'name';
|
||||
$opt['order'] = preg_replace('/[^-\\w:$]+/', ',', $opt['order']);
|
||||
|
||||
ksort($opt); $opt['=key'] = md5(serialize($opt));
|
||||
|
||||
$itemfilters = array(); $postfilters = array();
|
||||
asort($PageListFilters);
|
||||
$opt['=phase'] = PAGELIST_PRE; $list=array(); $pn=NULL; $page=NULL;
|
||||
foreach($PageListFilters as $fn => $v) {
|
||||
if ($v<0) continue;
|
||||
$ret = $fn($list, $opt, $pagename, $page);
|
||||
if ($ret & PAGELIST_ITEM) $itemfilters[] = $fn;
|
||||
if ($ret & PAGELIST_POST) $postfilters[] = $fn;
|
||||
}
|
||||
|
||||
StopWatch("MakePageList items count=".count($list).", filters=".implode(',',$itemfilters));
|
||||
$opt['=phase'] = PAGELIST_ITEM;
|
||||
$matches = array(); $opt['=readc'] = 0;
|
||||
foreach((array)$list as $pn) {
|
||||
$page = array();
|
||||
foreach((array)$itemfilters as $fn)
|
||||
if (!$fn($list, $opt, $pn, $page)) continue 2;
|
||||
$page['pagename'] = $page['name'] = $pn;
|
||||
PCache($pn, $page);
|
||||
$matches[] = $pn;
|
||||
}
|
||||
$list = $matches;
|
||||
StopWatch("MakePageList post count=".count($list).", readc={$opt['=readc']}");
|
||||
|
||||
$opt['=phase'] = PAGELIST_POST; $pn=NULL; $page=NULL;
|
||||
foreach((array)$postfilters as $fn)
|
||||
$fn($list, $opt, $pagename, $page);
|
||||
|
||||
if ($retpages)
|
||||
for($i=0; $i<count($list); $i++)
|
||||
$list[$i] = &$PCache[$list[$i]];
|
||||
StopWatch('MakePageList end');
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
||||
function PageListProtect(&$list, &$opt, $pn, &$page) {
|
||||
global $EnablePageListProtect;
|
||||
|
||||
switch ($opt['=phase']) {
|
||||
case PAGELIST_PRE:
|
||||
if (!IsEnabled($EnablePageListProtect, 1) && @$opt['readf'] < 1000)
|
||||
return 0;
|
||||
StopWatch("PageListProtect enabled");
|
||||
$opt['=protectexclude'] = array();
|
||||
$opt['=protectsafe'] = (array)@$opt['=protectsafe'];
|
||||
return PAGELIST_ITEM|PAGELIST_POST;
|
||||
|
||||
case PAGELIST_ITEM:
|
||||
if (@$opt['=protectsafe'][$pn]) return 1;
|
||||
$page = RetrieveAuthPage($pn, 'ALWAYS', false, READPAGE_CURRENT);
|
||||
$opt['=readc']++;
|
||||
if (!$page['=auth']['read']) $opt['=protectexclude'][$pn] = 1;
|
||||
if (!$page['=passwd']['read']) $opt['=protectsafe'][$pn] = 1;
|
||||
else NoCache();
|
||||
return 1;
|
||||
|
||||
case PAGELIST_POST:
|
||||
$excl = array_keys($opt['=protectexclude']);
|
||||
$safe = array_keys($opt['=protectsafe']);
|
||||
StopWatch("PageListProtect excluded=" .count($excl)
|
||||
. ", safe=" . count($safe));
|
||||
$list = array_diff($list, $excl);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function PageListSources(&$list, &$opt, $pn, &$page) {
|
||||
global $SearchPatterns;
|
||||
|
||||
StopWatch('PageListSources begin');
|
||||
## add the list= option to our list of pagename filter patterns
|
||||
$opt['=pnfilter'] = array_merge((array)@$opt['=pnfilter'],
|
||||
(array)@$SearchPatterns[$opt['list']]);
|
||||
|
||||
if (@$opt['group']) $opt['=pnfilter'][] = FixGlob($opt['group'], '$1$2.*');
|
||||
if (@$opt['name']) $opt['=pnfilter'][] = FixGlob($opt['name'], '$1*.$2');
|
||||
|
||||
if (@$opt['trail']) {
|
||||
$trail = ReadTrail($pn, $opt['trail']);
|
||||
$tlist = array();
|
||||
foreach($trail as $tstop) {
|
||||
$n = $tstop['pagename'];
|
||||
$tlist[] = $n;
|
||||
$tstop['parentnames'] = array();
|
||||
PCache($n, $tstop);
|
||||
}
|
||||
foreach($trail as $tstop)
|
||||
$PCache[$tstop['pagename']]['parentnames'][] =
|
||||
@$trail[$tstop['parent']]['pagename'];
|
||||
if (!@$opt['=cached']) $list = MatchPageNames($tlist, $opt['=pnfilter']);
|
||||
} else if (!@$opt['=cached']) $list = ListPages($opt['=pnfilter']);
|
||||
StopWatch("PageListSources end count=".count($list));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function PageListPasswords(&$list, &$opt, $pn, &$page) {
|
||||
if ($opt['=phase'] == PAGELIST_PRE)
|
||||
return (@$opt['passwd'] > '' && !@$opt['=cached']) ? PAGELIST_ITEM : 0;
|
||||
|
||||
if (!$page) { $page = ReadPage($pn, READPAGE_CURRENT); $opt['=readc']++; }
|
||||
if (!$page) return 0;
|
||||
return (boolean)preg_grep('/^passwd/', array_keys($page));
|
||||
}
|
||||
|
||||
|
||||
function PageListIf(&$list, &$opt, $pn, &$page) {
|
||||
global $Conditions, $Cursor;
|
||||
|
||||
## See if we have any "if" processing to perform
|
||||
if ($opt['=phase'] == PAGELIST_PRE)
|
||||
return (@$opt['if'] > '') ? PAGELIST_ITEM : 0;
|
||||
|
||||
$condspec = $opt['if'];
|
||||
$Cursor['='] = $pn;
|
||||
$varpat = '\\{([=*]|!?[-\\w.\\/\\x80-\\xff]*)(\\$:?\\w+)\\}';
|
||||
while (preg_match("/$varpat/", $condspec, $match)) {
|
||||
$condspec = PPRE("/$varpat/",
|
||||
"PVSE(PageVar('$pn', \$m[2], \$m[1]))", $condspec);
|
||||
}
|
||||
if (!preg_match("/^\\s*(!?)\\s*(\\S*)\\s*(.*?)\\s*$/", $condspec, $match))
|
||||
return 0;
|
||||
list($x, $not, $condname, $condparm) = $match;
|
||||
if (!isset($Conditions[$condname])) return 1;
|
||||
$tf = (int)@eval("return ({$Conditions[$condname]});");
|
||||
return (boolean)($tf xor $not);
|
||||
}
|
||||
|
||||
|
||||
function PageListTermsTargets(&$list, &$opt, $pn, &$page) {
|
||||
global $FmtV;
|
||||
static $reindex = array();
|
||||
$fold = $GLOBALS['StrFoldFunction'];
|
||||
|
||||
switch ($opt['=phase']) {
|
||||
case PAGELIST_PRE:
|
||||
$FmtV['$MatchSearched'] = count($list);
|
||||
$incl = array(); $excl = array();
|
||||
foreach((array)@$opt[''] as $i) { $incl[] = $fold($i); }
|
||||
foreach((array)@$opt['+'] as $i) { $incl[] = $fold($i); }
|
||||
foreach((array)@$opt['-'] as $i) { $excl[] = $fold($i); }
|
||||
|
||||
$indexterms = PageIndexTerms($incl);
|
||||
foreach($incl as $i) {
|
||||
$delim = (!preg_match('/[^\\w\\x80-\\xff]/', $i)) ? '$' : '/';
|
||||
$opt['=inclp'][] = $delim . preg_quote($i,$delim) . $delim . 'i';
|
||||
}
|
||||
if ($excl)
|
||||
$opt['=exclp'][] = '$'.implode('|', array_map('preg_quote',$excl)).'$i';
|
||||
|
||||
if (@$opt['link']) {
|
||||
$link = MakePageName($pn, $opt['link']);
|
||||
$opt['=linkp'] = "/(^|,)$link(,|$)/i";
|
||||
$indexterms[] = " $link ";
|
||||
}
|
||||
|
||||
if (@$opt['=cached']) return 0;
|
||||
if ($indexterms) {
|
||||
StopWatch("PageListTermsTargets begin count=".count($list));
|
||||
$xlist = PageIndexGrep($indexterms, true);
|
||||
$list = array_diff($list, $xlist);
|
||||
StopWatch("PageListTermsTargets end count=".count($list));
|
||||
}
|
||||
|
||||
if (@$opt['=inclp'] || @$opt['=exclp'] || @$opt['=linkp'])
|
||||
return PAGELIST_ITEM|PAGELIST_POST;
|
||||
return 0;
|
||||
|
||||
case PAGELIST_ITEM:
|
||||
if (!$page) { $page = ReadPage($pn, READPAGE_CURRENT); $opt['=readc']++; }
|
||||
if (!$page) return 0;
|
||||
if (@$opt['=linkp'] && !preg_match($opt['=linkp'], @$page['targets']))
|
||||
{ $reindex[] = $pn; return 0; }
|
||||
if (@$opt['=inclp'] || @$opt['=exclp']) {
|
||||
$text = $fold($pn."\n".@$page['targets']."\n".@$page['text']);
|
||||
foreach((array)@$opt['=exclp'] as $i)
|
||||
if (preg_match($i, $text)) return 0;
|
||||
foreach((array)@$opt['=inclp'] as $i)
|
||||
if (!preg_match($i, $text)) {
|
||||
if ($i{0} == '$') $reindex[] = $pn;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
case PAGELIST_POST:
|
||||
if ($reindex) PageIndexQueueUpdate($reindex);
|
||||
$reindex = array();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function PageListVariables(&$list, &$opt, $pn, &$page) {
|
||||
switch ($opt['=phase']) {
|
||||
case PAGELIST_PRE:
|
||||
$varlist = preg_grep('/^\\$/', array_keys($opt));
|
||||
if (!$varlist) return 0;
|
||||
foreach($varlist as $v) {
|
||||
list($inclp, $exclp) = GlobToPCRE($opt[$v]);
|
||||
if ($inclp) $opt['=varinclp'][$v] = "/$inclp/i";
|
||||
if ($exclp) $opt['=varexclp'][$v] = "/$exclp/i";
|
||||
}
|
||||
return PAGELIST_ITEM;
|
||||
|
||||
case PAGELIST_ITEM:
|
||||
if (@$opt['=varinclp'])
|
||||
foreach($opt['=varinclp'] as $v => $pat)
|
||||
if (!preg_match($pat, PageVar($pn, $v))) return 0;
|
||||
if (@$opt['=varexclp'])
|
||||
foreach($opt['=varexclp'] as $v => $pat)
|
||||
if (preg_match($pat, PageVar($pn, $v))) return 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function PageListSort(&$list, &$opt, $pn, &$page) {
|
||||
global $PageListSortCmp, $PCache, $PageListSortRead;
|
||||
SDVA($PageListSortRead, array('name' => 0, 'group' => 0, 'random' => 0,
|
||||
'title' => 0));
|
||||
|
||||
switch ($opt['=phase']) {
|
||||
case PAGELIST_PRE:
|
||||
$ret = 0;
|
||||
foreach(preg_split('/[^-\\w:$]+/', @$opt['order'], -1, PREG_SPLIT_NO_EMPTY)
|
||||
as $o) {
|
||||
$ret |= PAGELIST_POST;
|
||||
$r = '+';
|
||||
if ($o{0} == '-') { $r = '-'; $o = substr($o, 1); }
|
||||
$opt['=order'][$o] = $r;
|
||||
if ($o{0} != '$' &&
|
||||
(!isset($PageListSortRead[$o]) || $PageListSortRead[$o]))
|
||||
$ret |= PAGELIST_ITEM;
|
||||
}
|
||||
StopWatch(@"PageListSort pre ret=$ret order={$opt['order']}");
|
||||
return $ret;
|
||||
|
||||
case PAGELIST_ITEM:
|
||||
if (!$page) { $page = ReadPage($pn, READPAGE_CURRENT); $opt['=readc']++; }
|
||||
return 1;
|
||||
}
|
||||
|
||||
## case PAGELIST_POST
|
||||
StopWatch('PageListSort begin');
|
||||
$order = $opt['=order'];
|
||||
if (@$order['title'])
|
||||
foreach($list as $pn) $PCache[$pn]['=title'] = PageVar($pn, '$Title');
|
||||
if (@$order['group'])
|
||||
foreach($list as $pn) $PCache[$pn]['group'] = PageVar($pn, '$Group');
|
||||
if (@$order['random'])
|
||||
{ NoCache(); foreach($list as $pn) $PCache[$pn]['random'] = rand(); }
|
||||
foreach(preg_grep('/^\\$/', array_keys($order)) as $o)
|
||||
foreach($list as $pn)
|
||||
$PCache[$pn][$o] = PageVar($pn, $o);
|
||||
$code = '';
|
||||
foreach($opt['=order'] as $o => $r) {
|
||||
if (@$PageListSortCmp[$o])
|
||||
$code .= "\$c = {$PageListSortCmp[$o]}; ";
|
||||
else
|
||||
$code .= "\$c = @strcasecmp(\$PCache[\$x]['$o'],\$PCache[\$y]['$o']); ";
|
||||
$code .= "if (\$c) return $r\$c;\n";
|
||||
}
|
||||
StopWatch('PageListSort sort');
|
||||
if ($code)
|
||||
uasort($list,
|
||||
create_function('$x,$y', "global \$PCache; $code return 0;"));
|
||||
StopWatch('PageListSort end');
|
||||
}
|
||||
|
||||
|
||||
function PageListCache(&$list, &$opt, $pn, &$page) {
|
||||
global $PageListCacheDir, $LastModTime, $PageIndexFile;
|
||||
|
||||
if (@!$PageListCacheDir) return 0;
|
||||
if (isset($opt['cache']) && !$opt['cache']) return 0;
|
||||
|
||||
$key = $opt['=key'];
|
||||
$cache = "$PageListCacheDir/$key,cache";
|
||||
switch ($opt['=phase']) {
|
||||
case PAGELIST_PRE:
|
||||
if (!file_exists($cache) || filemtime($cache) <= $LastModTime)
|
||||
return PAGELIST_POST;
|
||||
StopWatch("PageListCache begin load key=$key");
|
||||
list($list, $opt['=protectsafe']) =
|
||||
unserialize(file_get_contents($cache));
|
||||
$opt['=cached'] = 1;
|
||||
StopWatch("PageListCache end load");
|
||||
return 0;
|
||||
|
||||
case PAGELIST_POST:
|
||||
StopWatch("PageListCache begin save key=$key");
|
||||
$fp = @fopen($cache, "w");
|
||||
if ($fp) {
|
||||
fputs($fp, serialize(array($list, $opt['=protectsafe'])));
|
||||
fclose($fp);
|
||||
}
|
||||
StopWatch("PageListCache end save");
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
## HandleSearchA performs ?action=search. It's basically the same
|
||||
## as ?action=browse, except it takes its contents from Site.Search.
|
||||
function HandleSearchA($pagename, $level = 'read') {
|
||||
global $PageSearchForm, $FmtV, $HandleSearchFmt,
|
||||
$PageStartFmt, $PageEndFmt;
|
||||
SDV($HandleSearchFmt,array(&$PageStartFmt, '$PageText', &$PageEndFmt));
|
||||
SDV($PageSearchForm, '$[{$SiteGroup}/Search]');
|
||||
$form = RetrieveAuthPage($pagename, $level, true, READPAGE_CURRENT);
|
||||
if (!$form) Abort("?unable to read $pagename");
|
||||
PCache($pagename, $form);
|
||||
$text = preg_replace('/\\[([=@])(.*?)\\1\\]/s', ' ', @$form['text']);
|
||||
if (!preg_match('/\\(:searchresults(\\s.*?)?:\\)/', $text))
|
||||
foreach((array)$PageSearchForm as $formfmt) {
|
||||
$form = ReadPage(FmtPageName($formfmt, $pagename), READPAGE_CURRENT);
|
||||
if ($form['text']) break;
|
||||
}
|
||||
$text = @$form['text'];
|
||||
if (!$text) $text = '(:searchresults:)';
|
||||
$FmtV['$PageText'] = MarkupToHTML($pagename,$text);
|
||||
PrintFmt($pagename, $HandleSearchFmt);
|
||||
}
|
||||
|
||||
|
||||
########################################################################
|
||||
## The functions below provide different formatting options for
|
||||
## the output list, controlled by the fmt= parameter and the
|
||||
## $FPLFormatOpt hash.
|
||||
########################################################################
|
||||
|
||||
## This helper function handles the count= parameter for extracting
|
||||
## a range of pagelist in the list.
|
||||
function CalcRange($range, $n) {
|
||||
if ($n < 1) return array(0, 0);
|
||||
if (strpos($range, '..') === false) {
|
||||
if ($range > 0) return array(1, min($range, $n));
|
||||
if ($range < 0) return array(max($n + $range + 1, 1), $n);
|
||||
return array(1, $n);
|
||||
}
|
||||
list($r0, $r1) = explode('..', $range);
|
||||
if ($r0 < 0) $r0 += $n + 1;
|
||||
if ($r1 < 0) $r1 += $n + 1;
|
||||
else if ($r1 == 0) $r1 = $n;
|
||||
if ($r0 < 1 && $r1 < 1) return array($n+1, $n+1);
|
||||
return array(max($r0, 1), max($r1, 1));
|
||||
}
|
||||
|
||||
|
||||
## FPLCountA handles fmt=count
|
||||
function FPLCountA($pagename, &$matches, $opt) {
|
||||
$matches = array_values(MakePageList($pagename, $opt, 0));
|
||||
return count($matches);
|
||||
}
|
||||
|
||||
SDVA($FPLTemplateFunctions, array(
|
||||
'FPLTemplateLoad' => 100,
|
||||
'FPLTemplateDefaults' => 200,
|
||||
'FPLTemplatePageList' => 300,
|
||||
'FPLTemplateSliceList' => 400,
|
||||
'FPLTemplateFormat' => 500
|
||||
));
|
||||
|
||||
function FPLTemplate($pagename, &$matches, $opt) {
|
||||
global $FPLTemplateFunctions;
|
||||
StopWatch("FPLTemplate: Chain begin");
|
||||
asort($FPLTemplateFunctions, SORT_NUMERIC);
|
||||
$fnlist = $FPLTemplateFunctions;
|
||||
$output = '';
|
||||
foreach($FPLTemplateFunctions as $fn=>$i) {
|
||||
if ($i<0) continue;
|
||||
StopWatch("FPLTemplate: $fn");
|
||||
$fn($pagename, $matches, $opt, $tparts, $output);
|
||||
}
|
||||
StopWatch("FPLTemplate: Chain end");
|
||||
return $output;
|
||||
}
|
||||
|
||||
## Loads a template section
|
||||
function FPLTemplateLoad($pagename, $matches, $opt, &$tparts){
|
||||
global $Cursor, $FPLTemplatePageFmt, $RASPageName, $PageListArgPattern;
|
||||
SDV($FPLTemplatePageFmt, array('{$FullName}',
|
||||
'{$SiteGroup}.LocalTemplates', '{$SiteGroup}.PageListTemplates'));
|
||||
|
||||
$template = @$opt['template'];
|
||||
if (!$template) $template = @$opt['fmt'];
|
||||
$ttext = RetrieveAuthSection($pagename, $template, $FPLTemplatePageFmt);
|
||||
$ttext = PVSE(Qualify($RASPageName, $ttext));
|
||||
|
||||
## save any escapes
|
||||
$ttext = MarkupEscape($ttext);
|
||||
## remove any anchor markups to avoid duplications
|
||||
$ttext = preg_replace('/\\[\\[#[A-Za-z][-.:\\w]*\\]\\]/', '', $ttext);
|
||||
|
||||
## extract portions of template
|
||||
$tparts = preg_split('/\\(:(template)\\s+([-!]?)\\s*(\\w+)\\s*(.*?):\\)/i',
|
||||
$ttext, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
}
|
||||
|
||||
## Merge parameters from (:template default :) with those in the (:pagelist:)
|
||||
function FPLTemplateDefaults($pagename, $matches, &$opt, &$tparts){
|
||||
global $PageListArgPattern;
|
||||
$i = 0;
|
||||
while ($i < count($tparts)) {
|
||||
if ($tparts[$i] != 'template') { $i++; continue; }
|
||||
if ($tparts[$i+2] != 'defaults' && $tparts[$i+2] != 'default') { $i+=5; continue; }
|
||||
$pvars = $GLOBALS['MarkupTable']['{$var}']; # expand {$PVars}
|
||||
$ttext = preg_replace_callback($pvars['pat'], $pvars['rep'], $tparts[$i+3]);
|
||||
$opt = array_merge(ParseArgs($ttext, $PageListArgPattern), $opt);
|
||||
array_splice($tparts, $i, 4);
|
||||
}
|
||||
SDVA($opt, array('class' => 'fpltemplate', 'wrap' => 'div'));
|
||||
}
|
||||
|
||||
## get the list of pages
|
||||
function FPLTemplatePageList($pagename, &$matches, &$opt){
|
||||
$matches = array_unique(array_merge((array)$matches, MakePageList($pagename, $opt, 0)));
|
||||
## count matches before any slicing and save value as template var {$$PageListCount}
|
||||
$opt['PageListCount'] = count($matches);
|
||||
}
|
||||
|
||||
## extract page subset according to 'count=' parameter
|
||||
function FPLTemplateSliceList($pagename, &$matches, $opt){
|
||||
if (@$opt['count']) {
|
||||
list($r0, $r1) = CalcRange($opt['count'], count($matches));
|
||||
if ($r1 < $r0)
|
||||
$matches = array_reverse(array_slice($matches, $r1-1, $r0-$r1+1));
|
||||
else
|
||||
$matches = array_slice($matches, $r0-1, $r1-$r0+1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function FPLTemplateFormat($pagename, $matches, $opt, $tparts, &$output){
|
||||
global $Cursor, $FPLTemplateMarkupFunction, $PCache;
|
||||
SDV($FPLTemplateMarkupFunction, 'MarkupToHTML');
|
||||
$savecursor = $Cursor;
|
||||
$pagecount = $groupcount = $grouppagecount = $traildepth = 0;
|
||||
$pseudovars = array('{$$PageCount}' => &$pagecount,
|
||||
'{$$GroupCount}' => &$groupcount,
|
||||
'{$$GroupPageCount}' => &$grouppagecount,
|
||||
'{$$PageTrailDepth}' => &$traildepth);
|
||||
|
||||
foreach(preg_grep('/^[\\w$]/', array_keys($opt)) as $k)
|
||||
if (!is_array($opt[$k]))
|
||||
$pseudovars["{\$\$$k}"] = PHSC($opt[$k], ENT_NOQUOTES);
|
||||
|
||||
$vk = array_keys($pseudovars);
|
||||
$vv = array_values($pseudovars);
|
||||
|
||||
$lgroup = ''; $out = '';
|
||||
if(count($matches)==0 ) {
|
||||
$t = 0;
|
||||
while($t < count($tparts)) {
|
||||
if($tparts[$t]=='template' && $tparts[$t+2]=='none') {
|
||||
$out .= MarkupRestore(FPLExpandItemVars($tparts[$t+4], $matches, 0, $pseudovars));
|
||||
$t+=4;
|
||||
}
|
||||
$t++;
|
||||
}
|
||||
} # else:
|
||||
foreach($matches as $i => $pn) {
|
||||
$traildepth = intval(@$PCache[$pn]['depth']);
|
||||
$group = PageVar($pn, '$Group');
|
||||
if ($group != $lgroup) { $groupcount++; $grouppagecount = 0; $lgroup = $group; }
|
||||
$grouppagecount++; $pagecount++;
|
||||
|
||||
$t = 0;
|
||||
while ($t < count($tparts)) {
|
||||
if ($tparts[$t] != 'template') { $item = $tparts[$t]; $t++; }
|
||||
else {
|
||||
list($neg, $when, $control, $item) = array_slice($tparts, $t+1, 4); $t+=5;
|
||||
if($when=='none') continue;
|
||||
if (!$control) {
|
||||
if ($when == 'first' && ($neg xor ($i != 0))) continue;
|
||||
if ($when == 'last' && ($neg xor ($i != count($matches) - 1))) continue;
|
||||
} else {
|
||||
if ($when == 'first' || !isset($last[$t])) {
|
||||
$curr = FPLExpandItemVars($control, $matches, $i, $pseudovars);
|
||||
if ($when == 'first' && ($neg xor (($i != 0) && ($last[$t] == $curr))))
|
||||
{ $last[$t] = $curr; continue; }
|
||||
$last[$t] = $curr;
|
||||
}
|
||||
if ($when == 'last') {
|
||||
$next = FPLExpandItemVars($control, $matches, $i+1, $pseudovars);
|
||||
if ($neg xor ($next == $last[$t] && $i != count($matches) - 1)) continue;
|
||||
$last[$t] = $next;
|
||||
}
|
||||
}
|
||||
}
|
||||
$item = FPLExpandItemVars($item, $matches, $i, $pseudovars);
|
||||
$out .= MarkupRestore($item);
|
||||
}
|
||||
}
|
||||
|
||||
$class = preg_replace('/[^-a-zA-Z0-9\\x80-\\xff]/', ' ', @$opt['class']);
|
||||
if ($class) $class = " class='$class'";
|
||||
$wrap = @$opt['wrap'];
|
||||
if ($wrap != 'inline') {
|
||||
$out = $FPLTemplateMarkupFunction($pagename, $out, array('escape' => 0, 'redirect'=>1));
|
||||
if ($wrap != 'none') $out = "<div$class>$out</div>";
|
||||
}
|
||||
$Cursor = $savecursor;
|
||||
$output .= $out;
|
||||
}
|
||||
## This function moves repeated code blocks out of FPLTemplateFormat()
|
||||
function FPLExpandItemVars($item, $matches, $idx, $psvars) {
|
||||
global $Cursor, $EnableUndefinedTemplateVars;
|
||||
$Cursor['<'] = $Cursor['<'] = (string)@$matches[$idx-1];
|
||||
$Cursor['='] = $pn = (string)@$matches[$idx];
|
||||
$Cursor['>'] = $Cursor['>'] = (string)@$matches[$idx+1];
|
||||
$item = str_replace(array_keys($psvars), array_values($psvars), $item);
|
||||
$item = PPRE('/\\{(=|&[lg]t;)(\\$:?\\w[-\\w]*)\\}/',
|
||||
"PVSE(PageVar('$pn', \$m[2], \$m[1]))", $item);
|
||||
if(! IsEnabled($EnableUndefinedTemplateVars, 0))
|
||||
$item = preg_replace("/\\{\\$\\$\\w+\\}/", '', $item);
|
||||
return $item;
|
||||
}
|
||||
|
||||
########################################################################
|
||||
## The functions below optimize searches by maintaining a file of
|
||||
## words and link cross references (the "page index").
|
||||
########################################################################
|
||||
|
||||
## PageIndexTerms($terms) takes an array of strings and returns a
|
||||
## normalized list of associated search terms. This reduces the
|
||||
## size of the index and speeds up searches.
|
||||
function PageIndexTerms($terms) {
|
||||
global $StrFoldFunction;
|
||||
$w = array();
|
||||
foreach((array)$terms as $t) {
|
||||
$w = array_merge($w, preg_split('/[^\\w\\x80-\\xff]+/',
|
||||
$StrFoldFunction($t), -1, PREG_SPLIT_NO_EMPTY));
|
||||
}
|
||||
return $w;
|
||||
}
|
||||
|
||||
## The PageIndexUpdate($pagelist) function updates the page index
|
||||
## file with terms and target links for the pages in $pagelist.
|
||||
## The optional $dir parameter allows this function to be called
|
||||
## via register_shutdown_function (which sometimes changes directories
|
||||
## on us).
|
||||
function PageIndexUpdate($pagelist = NULL, $dir = '') {
|
||||
global $EnableReadOnly, $PageIndexUpdateList, $PageIndexFile,
|
||||
$PageIndexTime, $Now;
|
||||
if (IsEnabled($EnableReadOnly, 0)) return;
|
||||
$abort = ignore_user_abort(true);
|
||||
if ($dir) { flush(); chdir($dir); }
|
||||
if (is_null($pagelist))
|
||||
{ $pagelist = (array)$PageIndexUpdateList; $PageIndexUpdateList = array(); }
|
||||
if (!$pagelist || !$PageIndexFile) return;
|
||||
SDV($PageIndexTime, 10);
|
||||
$c = count($pagelist); $updatecount = 0;
|
||||
StopWatch("PageIndexUpdate begin ($c pages to update)");
|
||||
$pagelist = (array)$pagelist;
|
||||
$timeout = time() + $PageIndexTime;
|
||||
$cmpfn = create_function('$a,$b', 'return strlen($b)-strlen($a);');
|
||||
Lock(2);
|
||||
$ofp = fopen("$PageIndexFile,new", 'w');
|
||||
foreach($pagelist as $pn) {
|
||||
if (@$updated[$pn]) continue;
|
||||
@$updated[$pn]++;
|
||||
if (time() > $timeout) continue;
|
||||
$page = ReadPage($pn, READPAGE_CURRENT);
|
||||
if ($page) {
|
||||
$targets = str_replace(',', ' ', @$page['targets']);
|
||||
$terms = PageIndexTerms(array(@$page['text'], $targets, $pn));
|
||||
usort($terms, $cmpfn);
|
||||
$x = '';
|
||||
foreach($terms as $t) { if (strpos($x, $t) === false) $x .= " $t"; }
|
||||
fputs($ofp, "$pn:$Now: $targets :$x\n");
|
||||
}
|
||||
$updatecount++;
|
||||
}
|
||||
$ifp = @fopen($PageIndexFile, 'r');
|
||||
if ($ifp) {
|
||||
while (!feof($ifp)) {
|
||||
$line = fgets($ifp, 4096);
|
||||
while (substr($line, -1, 1) != "\n" && !feof($ifp))
|
||||
$line .= fgets($ifp, 4096);
|
||||
$i = strpos($line, ':');
|
||||
if ($i === false) continue;
|
||||
$n = substr($line, 0, $i);
|
||||
if (@$updated[$n]) continue;
|
||||
fputs($ofp, $line);
|
||||
}
|
||||
fclose($ifp);
|
||||
}
|
||||
fclose($ofp);
|
||||
if (file_exists($PageIndexFile)) unlink($PageIndexFile);
|
||||
rename("$PageIndexFile,new", $PageIndexFile);
|
||||
fixperms($PageIndexFile);
|
||||
StopWatch("PageIndexUpdate end ($updatecount updated)");
|
||||
ignore_user_abort($abort);
|
||||
}
|
||||
|
||||
## PageIndexQueueUpdate specifies pages to be updated in
|
||||
## the index upon shutdown (via register_shutdown function).
|
||||
function PageIndexQueueUpdate($pagelist) {
|
||||
global $PageIndexUpdateList;
|
||||
if (!@$PageIndexUpdateList)
|
||||
register_shutdown_function('PageIndexUpdate', NULL, getcwd());
|
||||
$PageIndexUpdateList = array_merge((array)@$PageIndexUpdateList,
|
||||
(array)$pagelist);
|
||||
$c1 = count($pagelist); $c2 = count($PageIndexUpdateList);
|
||||
StopWatch("PageIndexQueueUpdate: queued $c1 pages ($c2 total)");
|
||||
}
|
||||
|
||||
## PageIndexGrep returns a list of pages that match the strings
|
||||
## provided. Note that some search terms may need to be normalized
|
||||
## in order to get the desired results (see PageIndexTerms above).
|
||||
## Also note that this just works for the index; if the index is
|
||||
## incomplete, then so are the results returned by this list.
|
||||
## (MakePageList above already knows how to deal with this.)
|
||||
function PageIndexGrep($terms, $invert = false) {
|
||||
global $PageIndexFile;
|
||||
if (!$PageIndexFile) return array();
|
||||
StopWatch('PageIndexGrep begin');
|
||||
$pagelist = array();
|
||||
$fp = @fopen($PageIndexFile, 'r');
|
||||
if ($fp) {
|
||||
$terms = (array)$terms;
|
||||
while (!feof($fp)) {
|
||||
$line = fgets($fp, 4096);
|
||||
while (substr($line, -1, 1) != "\n" && !feof($fp))
|
||||
$line .= fgets($fp, 4096);
|
||||
$i = strpos($line, ':');
|
||||
if (!$i) continue;
|
||||
$add = true;
|
||||
foreach($terms as $t)
|
||||
if (strpos($line, $t) === false) { $add = false; break; }
|
||||
if ($add xor $invert) $pagelist[] = substr($line, 0, $i);
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
StopWatch('PageIndexGrep end');
|
||||
return $pagelist;
|
||||
}
|
||||
|
||||
## PostPageIndex is inserted into $EditFunctions to update
|
||||
## the linkindex whenever a page is saved.
|
||||
function PostPageIndex($pagename, &$page, &$new) {
|
||||
global $IsPagePosted;
|
||||
if ($IsPagePosted) PageIndexQueueUpdate($pagename);
|
||||
}
|
||||
218
wiki/scripts/pagerev.php
Executable file
218
wiki/scripts/pagerev.php
Executable file
@@ -0,0 +1,218 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script defines routines for displaying page revisions. It
|
||||
is included by default from the stdconfig.php script.
|
||||
*/
|
||||
|
||||
function LinkSuppress($pagename,$imap,$path,$title,$txt,$fmt=NULL)
|
||||
{ return $txt; }
|
||||
|
||||
SDV($DiffShow['minor'],(@$_REQUEST['minor']!='n')?'y':'n');
|
||||
SDV($DiffShow['source'],(@$_REQUEST['source']!='n')?'y':'n');
|
||||
SDV($DiffMinorFmt, ($DiffShow['minor']=='y') ?
|
||||
"<a href='{\$PageUrl}?action=diff&source=".$DiffShow['source']."&minor=n'>$[Hide minor edits]</a>" :
|
||||
"<a href='{\$PageUrl}?action=diff&source=".$DiffShow['source']."&minor=y'>$[Show minor edits]</a>" );
|
||||
SDV($DiffSourceFmt, ($DiffShow['source']=='y') ?
|
||||
"<a href='{\$PageUrl}?action=diff&source=n&minor=".$DiffShow['minor']."'>$[Show changes to output]</a>" :
|
||||
"<a href='{\$PageUrl}?action=diff&source=y&minor=".$DiffShow['minor']."'>$[Show changes to markup]</a>");
|
||||
SDV($PageDiffFmt,"<h2 class='wikiaction'>$[{\$FullName} History]</h2>
|
||||
<p>$DiffMinorFmt - $DiffSourceFmt</p>
|
||||
");
|
||||
SDV($DiffStartFmt,"
|
||||
<div class='diffbox'><div class='difftime'><a name='diff\$DiffGMT' href='#diff\$DiffGMT'>\$DiffTime</a>
|
||||
\$[by] <span class='diffauthor' title='\$DiffHost'>\$DiffAuthor</span> - \$DiffChangeSum</div>");
|
||||
SDV($DiffDelFmt['a'],"
|
||||
<div class='difftype'>\$[Deleted line \$DiffLines:]</div>
|
||||
<div class='diffdel'>");
|
||||
SDV($DiffDelFmt['c'],"
|
||||
<div class='difftype'>\$[Changed line \$DiffLines from:]</div>
|
||||
<div class='diffdel'>");
|
||||
SDV($DiffAddFmt['d'],"
|
||||
<div class='difftype'>\$[Added line \$DiffLines:]</div>
|
||||
<div class='diffadd'>");
|
||||
SDV($DiffAddFmt['c'],"</div>
|
||||
<div class='difftype'>$[to:]</div>
|
||||
<div class='diffadd'>");
|
||||
SDV($DiffEndDelAddFmt,"</div>");
|
||||
SDV($DiffEndFmt,"</div>");
|
||||
SDV($DiffRestoreFmt,"
|
||||
<div class='diffrestore'><a href='{\$PageUrl}?action=edit&restore=\$DiffId&preview=y'>$[Restore]</a></div>");
|
||||
|
||||
SDV($HandleActions['diff'], 'HandleDiff');
|
||||
SDV($HandleAuth['diff'], 'read');
|
||||
SDV($ActionTitleFmt['diff'], '| $[History]');
|
||||
SDV($HTMLStylesFmt['diff'], "
|
||||
.diffbox { width:570px; border-left:1px #999999 solid; margin-top:1.33em; }
|
||||
.diffauthor { font-weight:bold; }
|
||||
.diffchangesum { font-weight:bold; }
|
||||
.difftime { font-family:verdana,sans-serif; font-size:66%;
|
||||
background-color:#dddddd; }
|
||||
.difftype { clear:both; font-family:verdana,sans-serif;
|
||||
font-size:66%; font-weight:bold; }
|
||||
.diffadd { border-left:5px #99ff99 solid; padding-left:5px; }
|
||||
.diffdel { border-left:5px #ffff99 solid; padding-left:5px; }
|
||||
.diffrestore { clear:both; font-family:verdana,sans-serif;
|
||||
font-size:66%; margin:1.5em 0px; }
|
||||
.diffmarkup { font-family:monospace; }
|
||||
.diffmarkup del { background:#ffff99; text-decoration: none; }
|
||||
.diffmarkup ins { background:#99ff99; text-decoration: none; }");
|
||||
|
||||
function PrintDiff($pagename) {
|
||||
global $DiffHTMLFunction,$DiffShow,$DiffStartFmt,$TimeFmt,
|
||||
$DiffEndFmt,$DiffRestoreFmt,$FmtV, $LinkFunctions;
|
||||
$page = ReadPage($pagename);
|
||||
if (!$page) return;
|
||||
krsort($page); reset($page);
|
||||
$lf = $LinkFunctions;
|
||||
$LinkFunctions['http:'] = 'LinkSuppress';
|
||||
$LinkFunctions['https:'] = 'LinkSuppress';
|
||||
SDV($DiffHTMLFunction, 'DiffHTML');
|
||||
foreach($page as $k=>$v) {
|
||||
if (!preg_match("/^diff:(\d+):(\d+):?([^:]*)/",$k,$match)) continue;
|
||||
$diffclass = $match[3];
|
||||
if ($diffclass=='minor' && $DiffShow['minor']!='y') continue;
|
||||
$diffgmt = $FmtV['$DiffGMT'] = $match[1];
|
||||
$FmtV['$DiffTime'] = strftime($TimeFmt,$diffgmt);
|
||||
$diffauthor = @$page["author:$diffgmt"];
|
||||
if (!$diffauthor) @$diffauthor=$page["host:$diffgmt"];
|
||||
if (!$diffauthor) $diffauthor="unknown";
|
||||
$FmtV['$DiffChangeSum'] = PHSC(@$page["csum:$diffgmt"]);
|
||||
$FmtV['$DiffHost'] = @$page["host:$diffgmt"];
|
||||
$FmtV['$DiffAuthor'] = $diffauthor;
|
||||
$FmtV['$DiffId'] = $k;
|
||||
$html = $DiffHTMLFunction($pagename, $v);
|
||||
if ($html===false) continue;
|
||||
echo FmtPageName($DiffStartFmt,$pagename);
|
||||
echo $html;
|
||||
echo FmtPageName($DiffEndFmt,$pagename);
|
||||
echo FmtPageName($DiffRestoreFmt,$pagename);
|
||||
}
|
||||
$LinkFunctions = $lf;
|
||||
}
|
||||
|
||||
# This function converts a single diff entry from the wikipage file
|
||||
# into HTML, ready for display.
|
||||
function DiffHTML($pagename, $diff) {
|
||||
if (@$_REQUEST['nodiff']>'') return '';
|
||||
global $FmtV, $DiffShow, $DiffAddFmt, $DiffDelFmt, $DiffEndDelAddFmt,
|
||||
$DiffRenderSourceFunction;
|
||||
SDV($DiffRenderSourceFunction, 'DiffRenderSource');
|
||||
$difflines = explode("\n",$diff."\n");
|
||||
$in=array(); $out=array(); $dtype=''; $html = '';
|
||||
foreach($difflines as $d) {
|
||||
if ($d>'') {
|
||||
if ($d[0]=='-' || $d[0]=='\\') continue;
|
||||
if ($d[0]=='<') { $out[]=substr($d,2); continue; }
|
||||
if ($d[0]=='>') { $in[]=substr($d,2); continue; }
|
||||
}
|
||||
if (preg_match("/^(\\d+)(,(\\d+))?([adc])(\\d+)(,(\\d+))?/",
|
||||
$dtype,$match)) {
|
||||
if (@$match[7]>'') {
|
||||
$lines='lines';
|
||||
$count=$match[1].'-'.($match[1]+$match[7]-$match[5]);
|
||||
} elseif ($match[3]>'') {
|
||||
$lines='lines'; $count=$match[1].'-'.$match[3];
|
||||
} else { $lines='line'; $count=$match[1]; }
|
||||
if ($match[4]=='a' || $match[4]=='c') {
|
||||
$txt = str_replace('line',$lines,$DiffDelFmt[$match[4]]);
|
||||
$FmtV['$DiffLines'] = $count;
|
||||
$html .= FmtPageName($txt,$pagename);
|
||||
if ($DiffShow['source']=='y')
|
||||
$html .= "<div class='diffmarkup'>"
|
||||
.$DiffRenderSourceFunction($in, $out, 0)
|
||||
."</div>";
|
||||
else $html .= MarkupToHTML($pagename,
|
||||
PPRE('/\\(:.*?:\\)/',"Keep(PHSC(\$m[0]))", join("\n",$in)));
|
||||
}
|
||||
if ($match[4]=='d' || $match[4]=='c') {
|
||||
$txt = str_replace('line',$lines,$DiffAddFmt[$match[4]]);
|
||||
$FmtV['$DiffLines'] = $count;
|
||||
$html .= FmtPageName($txt,$pagename);
|
||||
if ($DiffShow['source']=='y')
|
||||
$html .= "<div class='diffmarkup'>"
|
||||
.$DiffRenderSourceFunction($in, $out, 1)
|
||||
."</div>";
|
||||
else $html .= MarkupToHTML($pagename,
|
||||
PPRE('/\\(:.*?:\\)/',"Keep(PHSC(\$m[0]))",join("\n",$out)));
|
||||
}
|
||||
$html .= FmtPageName($DiffEndDelAddFmt,$pagename);
|
||||
}
|
||||
$in=array(); $out=array(); $dtype=$d;
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
function HandleDiff($pagename, $auth='read') {
|
||||
global $HandleDiffFmt, $PageStartFmt, $PageDiffFmt, $PageEndFmt;
|
||||
$page = RetrieveAuthPage($pagename, $auth, true, READPAGE_CURRENT);
|
||||
if (!$page) { Abort("?cannot diff $pagename"); }
|
||||
PCache($pagename, $page);
|
||||
SDV($HandleDiffFmt,array(&$PageStartFmt,
|
||||
&$PageDiffFmt,"<div id='wikidiff'>", 'function:PrintDiff', '</div>',
|
||||
&$PageEndFmt));
|
||||
PrintFmt($pagename,$HandleDiffFmt);
|
||||
}
|
||||
## Functions for simple word-diff (written by Petko Yotov)
|
||||
function DiffRenderSource($in, $out, $which) {
|
||||
global $WordDiffFunction, $EnableDiffInline;
|
||||
if (!IsEnabled($EnableDiffInline, 1)) {
|
||||
$a = $which? $out : $in;
|
||||
return str_replace("\n","<br />",PHSC(join("\n",$a)));
|
||||
}
|
||||
$countdifflines = abs(count($in)-count($out));
|
||||
$lines = $cnt = $x2 = $y2 = array();
|
||||
foreach($in as $line) {
|
||||
$tmp = $countdifflines>20 ? array($line) : DiffPrepareInline($line);
|
||||
if(!$which) $cnt[] = array(count($x2), count($tmp));
|
||||
$x2 = array_merge($x2, $tmp);
|
||||
}
|
||||
foreach($out as $line) {
|
||||
$tmp = $countdifflines>20 ? array($line) : DiffPrepareInline($line);
|
||||
if($which) $cnt[] = array(count($y2), count($tmp));
|
||||
$y2 = array_merge($y2, $tmp);
|
||||
}
|
||||
$z = $WordDiffFunction(implode("\n", $x2), implode("\n", $y2));
|
||||
|
||||
$z2 = array_map('PHSC', ($which? $y2 : $x2));
|
||||
array_unshift($z2, '');
|
||||
foreach (explode("\n", $z) as $zz) {
|
||||
if (preg_match('/^(\\d+)(,(\\d+))?([adc])(\\d+)(,(\\d+))?/',$zz,$m)) {
|
||||
$a1 = $a2 = $m[1];
|
||||
if ($m[3]) $a2=$m[3];
|
||||
$b1 = $b2 = $m[5];
|
||||
if ($m[7]) $b2=$m[7];
|
||||
|
||||
if (!$which && ($m[4]=='c'||$m[4]=='d')) {
|
||||
$z2[$a1] = '<del>'. $z2[$a1];
|
||||
$z2[$a2] .= '</del>';
|
||||
}
|
||||
if ($which && ($m[4]=='c'||$m[4]=='a')) {
|
||||
$z2[$b1] = '<ins>'.$z2[$b1];
|
||||
$z2[$b2] .= '</ins>';
|
||||
}
|
||||
}
|
||||
}
|
||||
$line = array_shift($z2);
|
||||
$z2[0] = $line.$z2[0];
|
||||
foreach ($cnt as $a) $lines[] = implode('', array_slice($z2, $a[0], $a[1]));
|
||||
$ret = implode("\n", $lines);
|
||||
$ret = str_replace(array('</del> <del>', '</ins> <ins>'), ' ', $ret);
|
||||
$ret = preg_replace('/(<(ins|del)>|^) /', '$1 ', $ret);
|
||||
return str_replace(array(" ", "\n ", "\n"),array(" ", "<br /> ", "<br />"),$ret);
|
||||
}
|
||||
## Split a line into pieces before passing it through `diff`
|
||||
function DiffPrepareInline($x) {
|
||||
global $DiffSplitInlineDelims;
|
||||
SDV($DiffSplitInlineDelims, "-@!?#$%^&*()=+[]{}.'\"\\:|,<>_/;~");
|
||||
return preg_split("/([".preg_quote($DiffSplitInlineDelims, '/')."\\s])/",
|
||||
$x, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
}
|
||||
|
||||
SDV($WordDiffFunction, 'PHPDiff'); # faster than sysdiff for many calls
|
||||
if (IsEnabled($EnableDiffInline, 1) && $DiffShow['source'] == 'y'
|
||||
&& $WordDiffFunction == 'PHPDiff' && !function_exists('PHPDiff'))
|
||||
include_once("$FarmD/scripts/phpdiff.php");
|
||||
39
wiki/scripts/pgcust.php
Executable file
39
wiki/scripts/pgcust.php
Executable file
@@ -0,0 +1,39 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2002-2005 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script enables per-page and per-group customizations in the
|
||||
local/ subdirectory (or whatever directory is given by $LocalDir).
|
||||
For example, to create customizations for the 'Demo' group, place
|
||||
them in a file called local/Demo.php. To customize a single page,
|
||||
use the full page name (e.g., local/Demo.MyPage.php).
|
||||
Per-page/per-group customizations can be handled at any time by adding
|
||||
include_once("scripts/pgcust.php");
|
||||
to config.php. It is automatically included by scripts/stdconfig.php
|
||||
unless $EnablePGCust is set to zero in config.php.
|
||||
|
||||
A page's customization is loaded first, followed by any group
|
||||
customization. If no page or group customizations are loaded,
|
||||
then 'local/default.php' is loaded.
|
||||
|
||||
A per-page configuration file can prevent its group's config from
|
||||
loading by setting $EnablePGCust=0;. A per-page configuration file
|
||||
can force group customizations to be loaded first by using include_once
|
||||
on the group customization file.
|
||||
|
||||
*/
|
||||
|
||||
$f = 1;
|
||||
for($p=$pagename;$p;$p=preg_replace('/\\.*[^.]*$/','',$p)) {
|
||||
if (!IsEnabled($EnablePGCust,1)) return;
|
||||
if (file_exists("$LocalDir/$p.php"))
|
||||
{ include_once("$LocalDir/$p.php"); $f=0; }
|
||||
}
|
||||
|
||||
if ($f && IsEnabled($EnablePGCust,1) && file_exists("$LocalDir/default.php"))
|
||||
include_once("$LocalDir/default.php");
|
||||
|
||||
|
||||
117
wiki/scripts/phpdiff.php
Executable file
117
wiki/scripts/phpdiff.php
Executable file
@@ -0,0 +1,117 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/*
|
||||
Copyright 2003,2004 Nils Knappmeier (nk@knappi.org)
|
||||
Copyright 2004-2010 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file implements a diff function in native PHP. It is based
|
||||
upon the PHPDiffEngine code written by Nils Knappmeier, who in turn
|
||||
had used Daniel Unterberger's diff
|
||||
(http://www.holomind.de/phpnet/diff.php) as the basis for his code.
|
||||
|
||||
Pm's revision of Nils' code simply attempts to streamline it
|
||||
for speed (eliminate function calls and unnecessary string ops)
|
||||
and place everything into a single file.
|
||||
|
||||
*/
|
||||
|
||||
## PHPDiff returns the differences between $old and $new, formatted
|
||||
## in the standard diff(1) output format.
|
||||
function PHPDiff($old, $new)
|
||||
{
|
||||
StopWatch("PHPDiff: begin");
|
||||
# split the source text into arrays of lines
|
||||
$t1 = explode("\n", $old);
|
||||
$x = array_pop($t1);
|
||||
if ($x > '') $t1[] = "$x\n\\ No newline at end of file";
|
||||
$t2 = explode("\n", $new);
|
||||
$x = array_pop($t2);
|
||||
if ($x > '') $t2[] = "$x\n\\ No newline at end of file";
|
||||
|
||||
$t1_start = 0; $t1_end = count($t1);
|
||||
$t2_start = 0; $t2_end = count($t2);
|
||||
|
||||
# stop with a common ending
|
||||
while ($t1_start < $t1_end && $t2_start < $t2_end
|
||||
&& $t1[$t1_end-1] == $t2[$t2_end-1]) { $t1_end--; $t2_end--; }
|
||||
|
||||
# skip over any common beginning
|
||||
while ($t1_start < $t1_end && $t2_start < $t2_end
|
||||
&& $t1[$t1_start] == $t2[$t2_start]) { $t1_start++; $t2_start++; }
|
||||
|
||||
# build a reverse-index array using the line as key and line number as value
|
||||
# don't store blank lines, so they won't be targets of the shortest distance
|
||||
# search
|
||||
for($i = $t1_start; $i < $t1_end; $i++) if ($t1[$i]>'') $r1[$t1[$i]][] = $i;
|
||||
for($i = $t2_start; $i < $t2_end; $i++) if ($t2[$i]>'') $r2[$t2[$i]][] = $i;
|
||||
|
||||
$a1 = $t1_start; $a2 = $t2_start; # start at beginning of each list
|
||||
$actions = array();
|
||||
|
||||
# walk this loop until we reach the end of one of the lists
|
||||
while ($a1 < $t1_end && $a2 < $t2_end) {
|
||||
# if we have a common element, save it and go to the next
|
||||
if ($t1[$a1] == $t2[$a2]) { $actions[] = 4; $a1++; $a2++; continue; }
|
||||
|
||||
# otherwise, find the shortest move (Manhattan-distance) from the
|
||||
# current location
|
||||
$best1 = $t1_end; $best2 = $t2_end;
|
||||
$s1 = $a1; $s2 = $a2;
|
||||
while(($s1 + $s2 - $a1 - $a2) < ($best1 + $best2 - $a1 - $a2)) {
|
||||
$d = -1;
|
||||
foreach((array)@$r1[$t2[$s2]] as $n)
|
||||
if ($n >= $s1) { $d = $n; break; }
|
||||
if ($d >= $s1 && ($d + $s2 - $a1 - $a2) < ($best1 + $best2 - $a1 - $a2))
|
||||
{ $best1 = $d; $best2 = $s2; }
|
||||
$d = -1;
|
||||
foreach((array)@$r2[$t1[$s1]] as $n)
|
||||
if ($n >= $s2) { $d = $n; break; }
|
||||
if ($d >= $s2 && ($s1 + $d - $a1 - $a2) < ($best1 + $best2 - $a1 - $a2))
|
||||
{ $best1 = $s1; $best2 = $d; }
|
||||
$s1++; $s2++;
|
||||
}
|
||||
while ($a1 < $best1) { $actions[] = 1; $a1++; } # deleted elements
|
||||
while ($a2 < $best2) { $actions[] = 2; $a2++; } # added elements
|
||||
}
|
||||
|
||||
# we've reached the end of one list, now walk to the end of the other
|
||||
while($a1 < $t1_end) { $actions[] = 1; $a1++; } # deleted elements
|
||||
while($a2 < $t2_end) { $actions[] = 2; $a2++; } # added elements
|
||||
|
||||
# and this marks our ending point
|
||||
$actions[] = 8;
|
||||
|
||||
# now, let's follow the path we just took and report the added/deleted
|
||||
# elements into $out.
|
||||
$op = 0;
|
||||
$x0 = $x1 = $t1_start; $y0 = $y1 = $t2_start;
|
||||
$out = array();
|
||||
foreach($actions as $act) {
|
||||
if ($act == 1) { $op |= $act; $x1++; continue; }
|
||||
if ($act == 2) { $op |= $act; $y1++; continue; }
|
||||
if ($op > 0) {
|
||||
$xstr = ($x1 == ($x0+1)) ? $x1 : ($x0+1) . ",$x1";
|
||||
$ystr = ($y1 == ($y0+1)) ? $y1 : ($y0+1) . ",$y1";
|
||||
if ($op == 1) $out[] = "{$xstr}d{$y1}";
|
||||
elseif ($op == 3) $out[] = "{$xstr}c{$ystr}";
|
||||
while ($x0 < $x1) { $out[] = '< ' . $t1[$x0]; $x0++; } # deleted elems
|
||||
if ($op == 2) $out[] = "{$x1}a{$ystr}";
|
||||
elseif ($op == 3) $out[] = '---';
|
||||
while ($y0 < $y1) { $out[] = '> '.$t2[$y0]; $y0++; } # added elems
|
||||
}
|
||||
$x1++; $x0 = $x1;
|
||||
$y1++; $y0 = $y1;
|
||||
$op = 0;
|
||||
}
|
||||
$out[] = '';
|
||||
StopWatch("PHPDiff: end");
|
||||
return join("\n",$out);
|
||||
}
|
||||
|
||||
if (!function_exists(@$DiffFunction))
|
||||
$DiffFunction = 'PHPDiff';
|
||||
|
||||
57
wiki/scripts/prefs.php
Executable file
57
wiki/scripts/prefs.php
Executable file
@@ -0,0 +1,57 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2005-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script handles per-browser preferences. Preference settings
|
||||
are stored in wiki pages as XLPage translations, and a cookie on
|
||||
the browser tells PmWiki where to find the browser's preferred
|
||||
settings.
|
||||
|
||||
This script looks for a ?setprefs= request parameter (e.g., in
|
||||
a url); when it finds one it sets a 'setprefs' cookie on the browser
|
||||
identifying the page to be used to load browser preferences,
|
||||
and loads the associated preferences.
|
||||
|
||||
If there is no ?setprefs= request, then the script uses the
|
||||
'setprefs' cookie from the browser to load the preference settings.
|
||||
*/
|
||||
|
||||
SDV($PrefsCookie, $CookiePrefix.'setprefs');
|
||||
SDV($PrefsCookieExpires, $Now + 60 * 60 * 24 * 365);
|
||||
$LogoutCookies[] = $PrefsCookie;
|
||||
|
||||
$sp = '';
|
||||
if (@$_COOKIE[$PrefsCookie]) $sp = $_COOKIE[$PrefsCookie];
|
||||
if (isset($_GET['setprefs'])) {
|
||||
$sp = MakePageName($pagename, $_GET['setprefs']);
|
||||
setcookie($PrefsCookie, $sp, $PrefsCookieExpires, '/');
|
||||
}
|
||||
if ($sp && PageExists($sp)) XLPage('prefs', $sp, true);
|
||||
|
||||
if(is_array($XL['prefs'])) {
|
||||
foreach($XL['prefs'] as $k=>$v) {
|
||||
if(! preg_match('/^(e_rows|e_cols|TimeFmt|Locale|Site\\.EditForm)$|^ak_/', $k))
|
||||
unset($XL['prefs'][$k]);
|
||||
}
|
||||
}
|
||||
|
||||
XLSDV('en', array(
|
||||
'ak_view' => '',
|
||||
'ak_edit' => 'e',
|
||||
'ak_history' => 'h',
|
||||
'ak_attach' => '',
|
||||
'ak_backlinks' => '',
|
||||
'ak_logout' => '',
|
||||
'ak_print' => '',
|
||||
'ak_recentchanges' => 'c',
|
||||
'ak_save' => 's',
|
||||
'ak_saveedit' => 'u',
|
||||
'ak_savedraft' => 'd',
|
||||
'ak_preview' => 'p',
|
||||
'ak_em' => '',
|
||||
'ak_strong' => '',
|
||||
));
|
||||
|
||||
121
wiki/scripts/refcount.php
Executable file
121
wiki/scripts/refcount.php
Executable file
@@ -0,0 +1,121 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2011 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file does simple reference counting on pages in a PmWiki site.
|
||||
Simply activate this script using
|
||||
include_once('scripts/refcount.php');
|
||||
in the config.php file and then use ?action=refcount to bring up
|
||||
the reference count form. The output is a table where each row
|
||||
of the table contains a page name or link reference, the number
|
||||
of (non-RecentChanges) pages that contain links to the page,
|
||||
the number of RecentChanges pages with links to the page, and the
|
||||
total number of references in all pages.
|
||||
*/
|
||||
|
||||
SDV($PageRefCountFmt,"<h2 class='wikiaction'>Reference Count Results</h2>");
|
||||
SDV($RefCountTimeFmt," <small>%Y-%b-%d %H:%M</small>");
|
||||
SDV($HandleActions['refcount'], 'HandleRefCount');
|
||||
|
||||
function PrintRefCount($pagename) {
|
||||
global $GroupPattern,$NamePattern,$PageRefCountFmt,$RefCountTimeFmt, $ScriptUrl;
|
||||
$pagelist = ListPages();
|
||||
$grouplist = array();
|
||||
foreach($pagelist as $pname) {
|
||||
if (!preg_match("/^($GroupPattern)[\\/.]($NamePattern)$/",$pname,$m))
|
||||
continue;
|
||||
$grouplist[$m[1]]=$m[1];
|
||||
}
|
||||
asort($grouplist);
|
||||
$grouplist = array_merge(array('all' => 'all groups'),$grouplist);
|
||||
|
||||
$wlist = array('all','missing','existing','orphaned');
|
||||
$tlist = isset($_REQUEST['tlist']) ? $_REQUEST['tlist'] : array('all');
|
||||
$flist = isset($_REQUEST['flist']) ? $_REQUEST['flist'] : array('all');
|
||||
$whichrefs = @$_REQUEST['whichrefs'];
|
||||
$showrefs = (@$_REQUEST['showrefs']=='checked')? "checked='checked'" : '';
|
||||
$submit = @$_REQUEST['submit'];
|
||||
|
||||
echo FmtPageName($PageRefCountFmt,$pagename);
|
||||
echo FmtPageName("<form method='post' action='{\$PageUrl}'><input type='hidden' name='action' value='refcount'/>
|
||||
<table cellspacing='10'><tr><td valign='top'>Show
|
||||
<br/><select name='whichrefs'>",$pagename);
|
||||
foreach($wlist as $w)
|
||||
echo "<option ",($whichrefs==$w) ? 'selected="selected"' : ''," value='$w'>$w</option>\n";
|
||||
echo "</select></td><td valign='top'> page names in group<br/>
|
||||
<select name='tlist[]' multiple='multiple' size='4'>";
|
||||
foreach($grouplist as $g=>$t)
|
||||
echo "<option ",in_array($g,$tlist) ? 'selected="selected"' : ''," value='$g'>$t</option>\n";
|
||||
echo "</select></td><td valign='top'> referenced from pages in<br/>
|
||||
<select name='flist[]' multiple='multiple' size='4'>";
|
||||
foreach($grouplist as $g=>$t)
|
||||
echo "<option ",in_array($g,$flist) ? 'selected="selected"' : ''," value='$g'>$t</option>\n";
|
||||
echo "</select></td></tr></table>
|
||||
<p><input type='checkbox' name='showrefs' value='checked' $showrefs/>
|
||||
Display referencing pages
|
||||
</p><p><input type='submit' name='submit' value='Search'/></p></form><hr/>";
|
||||
|
||||
if ($submit) {
|
||||
foreach($pagelist as $pname) {
|
||||
$ref = array();
|
||||
$page = ReadPage($pname, READPAGE_CURRENT);
|
||||
if (!$page) continue;
|
||||
$tref[$pname]['time'] = $page['time'];
|
||||
if (!in_array('all',$flist) &&
|
||||
!in_array(FmtPageName('$Group',$pname),$flist)) continue;
|
||||
$rc = preg_match('/RecentChanges$/',$pname);
|
||||
foreach(explode(',',@$page['targets']) as $r) {
|
||||
if ($r=='') continue;
|
||||
if ($rc) @$tref[$r]['rc']++;
|
||||
else { @$tref[$r]['page']++; @$pref[$r][$pname]++; }
|
||||
}
|
||||
}
|
||||
uasort($tref,'RefCountCmp');
|
||||
echo "<table >
|
||||
<tr><th></th><th colspan='2'>Referring pages</th></tr>
|
||||
<tr><th>Name / Time</th><th>All</th><th>R.C.</th></tr>";
|
||||
reset($tref);
|
||||
foreach($tref as $p=>$c) {
|
||||
if (!in_array('all',$tlist) &&
|
||||
!in_array(FmtPageName('$Group',$p),$tlist)) continue;
|
||||
if ($whichrefs=='missing' && PageExists($p)) continue;
|
||||
elseif ($whichrefs=='existing' && !PageExists($p)) continue;
|
||||
elseif ($whichrefs=='orphaned' &&
|
||||
(@$tref[$p]['page']>0 || !PageExists($p))) continue;
|
||||
echo "<tr><td valign='top'>",LinkPage($pagename, '', $p, '', $p);
|
||||
if (@$tref[$p]['time']) echo strftime($RefCountTimeFmt,$tref[$p]['time']);
|
||||
if ($showrefs && is_array(@$pref[$p])) {
|
||||
foreach($pref[$p] as $pr=>$pc)
|
||||
echo "<dd>", LinkPage($pagename, '', $pr, '', $pr);
|
||||
}
|
||||
echo "</td>";
|
||||
echo "<td align='center' valign='top'>",@$tref[$p]['page']+0,"</td>";
|
||||
echo "<td align='center' valign='top'>",@$tref[$p]['rc']+0,"</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
echo "</table>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function RefCountCmp($ua,$ub) {
|
||||
if (@($ua['page']!=$ub['page'])) return @($ub['page']-$ua['page']);
|
||||
if (@($ua['rc']!=$ub['rc'])) return @($ub['rc']-$ua['rc']);
|
||||
return @($ub['time']-$ua['time']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function HandleRefCount($pagename, $auth='read') {
|
||||
global $HandleRefCountFmt,$PageStartFmt,$PageEndFmt;
|
||||
$page = RetrieveAuthPage($pagename, $auth, true, READPAGE_CURRENT);
|
||||
if (!$page) Abort('?unauthorized');
|
||||
PCache($pagename, $page);
|
||||
SDV($HandleRefCountFmt,array(&$PageStartFmt,
|
||||
'function:PrintRefCount',&$PageEndFmt));
|
||||
PrintFmt($pagename,$HandleRefCountFmt);
|
||||
}
|
||||
|
||||
76
wiki/scripts/robots.php
Executable file
76
wiki/scripts/robots.php
Executable file
@@ -0,0 +1,76 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2005-2006 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file provides various features to allow PmWiki to control
|
||||
what web crawlers (robots) see when they visit the site. Of course
|
||||
it's still possible to control robots at the webserver level
|
||||
and via robots.txt, but this page provides some finer level
|
||||
of control.
|
||||
|
||||
The $MetaRobots variable controls generation of the
|
||||
<meta name='robots' ... /> tag in the head of the HTML document.
|
||||
By default $MetaRobots is set so that robots do not index pages in
|
||||
the Site, SiteAdmin, and PmWiki groups.
|
||||
|
||||
The $RobotPattern variable is used to determine if the user agent
|
||||
accessing the site is a robot, and $IsRobotAgent is set accordingly.
|
||||
By default this pattern identifies Googlebot, Yahoo! Slurp, msnbot,
|
||||
BecomeBot, and HTTrack as robots.
|
||||
|
||||
If the agent is deemed a robot, then the $RobotActions array is
|
||||
checked to see if robots are allowed to perform the given action,
|
||||
and if not the robot is immediately sent an HTTP 403 Forbidden
|
||||
response.
|
||||
|
||||
If $EnableRobotCloakActions is set, then a pattern is added to
|
||||
$FmtP to hide any "?action=" url parameters in page urls
|
||||
generated by PmWiki for actions that robots aren't allowed to
|
||||
access. This can greatly reduce the load on the server by
|
||||
not providing the robot with links to pages that it will be
|
||||
forbidden to index anyway.
|
||||
*/
|
||||
|
||||
## $MetaRobots provides the value for the <meta name='robots' ...> tag.
|
||||
SDV($MetaRobots,
|
||||
($action!='browse' || !PageExists($pagename)
|
||||
|| preg_match('#^PmWiki[./](?!PmWiki$)|^Site(Admin)?[./]#', $pagename))
|
||||
? 'noindex,nofollow' : 'index,follow');
|
||||
if ($MetaRobots)
|
||||
$HTMLHeaderFmt['robots'] =
|
||||
" <meta name='robots' content='\$MetaRobots' />\n";
|
||||
|
||||
## $RobotPattern is used to identify robots.
|
||||
SDV($RobotPattern,'Googlebot|Slurp|msnbot|Teoma|ia_archiver|BecomeBot|HTTrack|MJ12bot|XML Sitemaps|Yandex');
|
||||
SDV($IsRobotAgent,
|
||||
$RobotPattern && preg_match("!$RobotPattern!", @$_SERVER['HTTP_USER_AGENT']));
|
||||
if (!$IsRobotAgent) return;
|
||||
|
||||
## $RobotActions indicates which actions a robot is allowed to perform.
|
||||
SDVA($RobotActions, array('browse' => 1, 'rss' => 1, 'dc' => 1));
|
||||
if (!@$RobotActions[$action]) {
|
||||
$pagename = ResolvePageName($pagename);
|
||||
if (!PageExists($pagename)) {
|
||||
header("HTTP/1.1 404 Not Found");
|
||||
print("<h1>Not Found</h1>");
|
||||
exit();
|
||||
}
|
||||
header("HTTP/1.1 403 Forbidden");
|
||||
print("<h1>Forbidden</h1>");
|
||||
exit();
|
||||
}
|
||||
|
||||
## The following removes any ?action= parameters that robots aren't
|
||||
## allowed to access.
|
||||
if (IsEnabled($EnableRobotCloakActions, 0)) {
|
||||
$p = create_function('$a', 'return (boolean)$a;');
|
||||
$p = join('|', array_keys(array_filter($RobotActions, $p)));
|
||||
$FmtPV['$PageUrl'] =
|
||||
'PUE(($EnablePathInfo)
|
||||
? "\\$ScriptUrl/$group/$name"
|
||||
: "\\$ScriptUrl?n=$group.$name")';
|
||||
$FmtP["/(\\\$ScriptUrl[^#\"'\\s<>]+)\\?action=(?!$p)\\w+/"] = '$1';
|
||||
}
|
||||
74
wiki/scripts/simuledit.php
Executable file
74
wiki/scripts/simuledit.php
Executable file
@@ -0,0 +1,74 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file enables merging of concurrent edits, using the "diff3"
|
||||
program available on most Unix systems to merge the edits. If
|
||||
diff3 is not available or you'd like to use a different command,
|
||||
then set $SysMergeCmd accordingly.
|
||||
*/
|
||||
|
||||
array_unshift($EditFunctions,'MergeSimulEdits');
|
||||
$HTMLStylesFmt['simuledit'] = ".editconflict { color:green;
|
||||
font-style:italic; margin-top:1.33em; margin-bottom:1.33em; }\n";
|
||||
|
||||
function Merge($newtext,$oldtext,$pagetext) {
|
||||
global $WorkDir,$SysMergeCmd, $SysMergePassthru;
|
||||
SDV($SysMergeCmd,"/usr/bin/diff3 -L '' -L '' -L '' -m -E");
|
||||
if (substr($newtext,-1,1)!="\n") $newtext.="\n";
|
||||
if (substr($oldtext,-1,1)!="\n") $oldtext.="\n";
|
||||
if (substr($pagetext,-1,1)!="\n") $pagetext.="\n";
|
||||
$tempnew = tempnam($WorkDir,"new");
|
||||
$tempold = tempnam($WorkDir,"old");
|
||||
$temppag = tempnam($WorkDir,"page");
|
||||
if ($newfp=fopen($tempnew,'w')) { fputs($newfp,$newtext); fclose($newfp); }
|
||||
if ($oldfp=fopen($tempold,'w')) { fputs($oldfp,$oldtext); fclose($oldfp); }
|
||||
if ($pagfp=fopen($temppag,'w')) { fputs($pagfp,$pagetext); fclose($pagfp); }
|
||||
$mergetext = '';
|
||||
if (IsEnabled($SysMergePassthru, 0)) {
|
||||
ob_start();
|
||||
passthru("$SysMergeCmd $tempnew $tempold $temppag");
|
||||
$mergetext = ob_get_clean();
|
||||
}
|
||||
else {
|
||||
$merge_handle = popen("$SysMergeCmd $tempnew $tempold $temppag",'r');
|
||||
if ($merge_handle) {
|
||||
while (!feof($merge_handle)) $mergetext .= fread($merge_handle,4096);
|
||||
pclose($merge_handle);
|
||||
}
|
||||
}
|
||||
@unlink($tempnew); @unlink($tempold); @unlink($temppag);
|
||||
return $mergetext;
|
||||
}
|
||||
|
||||
function MergeSimulEdits($pagename,&$page,&$new) {
|
||||
global $Now, $EnablePost, $MessagesFmt, $WorkDir;
|
||||
if (@!$_POST['basetime'] || !PageExists($pagename)
|
||||
|| $page['time'] >= $Now
|
||||
|| $_POST['basetime']>=$page['time']
|
||||
|| $page['text'] == $new['text']) return;
|
||||
$EnablePost = 0;
|
||||
$old = array();
|
||||
RestorePage($pagename,$page,$old,"diff:{$_POST['basetime']}");
|
||||
$text = Merge($new['text'],$old['text'],$page['text']);
|
||||
if ($text > '') { $new['text'] = $text; $ec = '$[EditConflict]'; }
|
||||
else $ec = '$[EditWarning]';
|
||||
XLSDV('en', array(
|
||||
'EditConflict' => "The page you are
|
||||
editing has been modified since you started editing it.
|
||||
The modifications have been merged into the text below,
|
||||
you may want to verify the results of the merge before
|
||||
pressing save. Conflicts the system couldn't resolve are
|
||||
bracketed by <<<<<<< and
|
||||
>>>>>>>.",
|
||||
'EditWarning' => "The page you are editing has been modified
|
||||
since you started editing it. If you continue, your
|
||||
changes will overwrite any changes that others have made."));
|
||||
$MessagesFmt[] = "<p class='editconflict'>$ec
|
||||
(<a target='_blank' href='\$PageUrl?action=diff'>$[View changes]</a>)
|
||||
</p>\n";
|
||||
}
|
||||
|
||||
147
wiki/scripts/skins.php
Executable file
147
wiki/scripts/skins.php
Executable file
@@ -0,0 +1,147 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2007 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file implements the skin selection code for PmWiki. Skin
|
||||
selection is controlled by the $Skin variable, which can also
|
||||
be an array (in which case the first skin found is loaded).
|
||||
|
||||
In addition, $ActionSkin[$action] specifies other skins to be
|
||||
searched based on the current action.
|
||||
|
||||
*/
|
||||
|
||||
SDV($Skin, 'pmwiki');
|
||||
SDV($ActionSkin['print'], 'print');
|
||||
SDV($FarmPubDirUrl, $PubDirUrl);
|
||||
SDV($PageLogoUrl, "$FarmPubDirUrl/skins/pmwiki/pmwiki-32.gif");
|
||||
SDVA($TmplDisplay, array('PageEditFmt' => 0));
|
||||
|
||||
# $PageTemplateFmt is deprecated
|
||||
if (isset($PageTemplateFmt)) LoadPageTemplate($pagename,$PageTemplateFmt);
|
||||
else {
|
||||
$x = array_merge((array)@$ActionSkin[$action], (array)$Skin);
|
||||
SetSkin($pagename, $x);
|
||||
}
|
||||
|
||||
SDV($PageCSSListFmt,array(
|
||||
'pub/css/local.css' => '$PubDirUrl/css/local.css',
|
||||
'pub/css/{$Group}.css' => '$PubDirUrl/css/{$Group}.css',
|
||||
'pub/css/{$FullName}.css' => '$PubDirUrl/css/{$FullName}.css'));
|
||||
|
||||
foreach((array)$PageCSSListFmt as $k=>$v)
|
||||
if (file_exists(FmtPageName($k,$pagename)))
|
||||
$HTMLHeaderFmt[] = "<link rel='stylesheet' type='text/css' href='$v' />\n";
|
||||
|
||||
# SetSkin changes the current skin to the first available skin from
|
||||
# the $skin array.
|
||||
function SetSkin($pagename, $skin) {
|
||||
global $Skin, $SkinLibDirs, $SkinDir, $SkinDirUrl,
|
||||
$IsTemplateLoaded, $PubDirUrl, $FarmPubDirUrl, $FarmD, $GCount;
|
||||
SDV($SkinLibDirs, array(
|
||||
"./pub/skins/\$Skin" => "$PubDirUrl/skins/\$Skin",
|
||||
"$FarmD/pub/skins/\$Skin" => "$FarmPubDirUrl/skins/\$Skin"));
|
||||
foreach((array)$skin as $sfmt) {
|
||||
$Skin = FmtPageName($sfmt, $pagename); $GCount = 0;
|
||||
foreach($SkinLibDirs as $dirfmt => $urlfmt) {
|
||||
$SkinDir = FmtPageName($dirfmt, $pagename);
|
||||
if (is_dir($SkinDir))
|
||||
{ $SkinDirUrl = FmtPageName($urlfmt, $pagename); break 2; }
|
||||
}
|
||||
}
|
||||
if (!is_dir($SkinDir)) {
|
||||
unset($Skin);
|
||||
Abort("?unable to find skin from list ".implode(' ',(array)$skin));
|
||||
}
|
||||
$IsTemplateLoaded = 0;
|
||||
if (file_exists("$SkinDir/$Skin.php"))
|
||||
include_once("$SkinDir/$Skin.php");
|
||||
else if (file_exists("$SkinDir/skin.php"))
|
||||
include_once("$SkinDir/skin.php");
|
||||
if ($IsTemplateLoaded) return;
|
||||
if (file_exists("$SkinDir/$Skin.tmpl"))
|
||||
LoadPageTemplate($pagename, "$SkinDir/$Skin.tmpl");
|
||||
else if (file_exists("$SkinDir/skin.tmpl"))
|
||||
LoadPageTemplate($pagename, "$SkinDir/skin.tmpl");
|
||||
else if (($dh = opendir($SkinDir))) {
|
||||
while (($fname = readdir($dh)) !== false) {
|
||||
if ($fname[0] == '.') continue;
|
||||
if (substr($fname, -5) != '.tmpl') continue;
|
||||
if ($IsTemplateLoaded)
|
||||
Abort("?unable to find unique template in $SkinDir");
|
||||
LoadPageTemplate($pagename, "$SkinDir/$fname");
|
||||
}
|
||||
closedir($dh);
|
||||
}
|
||||
if (!$IsTemplateLoaded) Abort("Unable to load $Skin template", 'skin');
|
||||
}
|
||||
|
||||
|
||||
# LoadPageTemplate loads a template into $TmplFmt
|
||||
function LoadPageTemplate($pagename,$tfilefmt) {
|
||||
global $PageStartFmt, $PageEndFmt,
|
||||
$EnableSkinDiag, $HTMLHeaderFmt, $HTMLFooterFmt,
|
||||
$IsTemplateLoaded, $TmplFmt, $TmplDisplay,
|
||||
$PageTextStartFmt, $PageTextEndFmt, $SkinDirectivesPattern;
|
||||
|
||||
SDV($PageTextStartFmt, "\n<div id='wikitext'>\n");
|
||||
SDV($PageTextEndFmt, "</div>\n");
|
||||
SDV($SkinDirectivesPattern,
|
||||
"[[<]!--((?:wiki|file|function|markup):.*?)--[]>]");
|
||||
|
||||
$sddef = array('PageEditFmt' => 0);
|
||||
$k = implode('', file(FmtPageName($tfilefmt, $pagename)));
|
||||
|
||||
if (IsEnabled($EnableSkinDiag, 0)) {
|
||||
if (!preg_match('/<!--((No)?(HT|X)MLHeader|HeaderText)-->/i', $k))
|
||||
Abort("Skin template missing <!--HTMLHeader-->", 'htmlheader');
|
||||
if (!preg_match('/<!--(No)?(HT|X)MLFooter-->/i', $k))
|
||||
Abort("Skin template missing <!--HTMLFooter-->", 'htmlheader');
|
||||
}
|
||||
|
||||
$sect = preg_split(
|
||||
'#[[<]!--(/?(?:Page[A-Za-z]+Fmt|(?:HT|X)ML(?:Head|Foot)er|HeaderText|PageText).*?)--[]>]#',
|
||||
$k, 0, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$TmplFmt['Start'] = array_merge(array('headers:'),
|
||||
preg_split("/$SkinDirectivesPattern/s",
|
||||
array_shift($sect),0,PREG_SPLIT_DELIM_CAPTURE));
|
||||
$TmplFmt['End'] = array($PageTextEndFmt);
|
||||
$ps = 'Start';
|
||||
while (count($sect)>0) {
|
||||
$k = array_shift($sect);
|
||||
$v = preg_split("/$SkinDirectivesPattern/s",
|
||||
array_shift($sect),0,PREG_SPLIT_DELIM_CAPTURE);
|
||||
$TmplFmt[$ps][] = "<!--$k-->";
|
||||
if ($k{0} == '/')
|
||||
{ $TmplFmt[$ps][] = (count($v) > 1) ? $v : $v[0]; continue; }
|
||||
@list($var, $sd) = explode(' ', $k, 2);
|
||||
$GLOBALS[$var] = (count($v) > 1) ? $v : $v[0];
|
||||
if ($sd > '') $sddef[$var] = $sd;
|
||||
if ($var == 'PageText') { $ps = 'End'; }
|
||||
if ($var == 'HTMLHeader' || $var == 'XMLHeader')
|
||||
$TmplFmt[$ps][] = &$HTMLHeaderFmt;
|
||||
if ($var == 'HTMLFooter' || $var == 'XMLFooter')
|
||||
$TmplFmt[$ps][] = &$HTMLFooterFmt;
|
||||
## <!--HeaderText--> deprecated, 2.1.16
|
||||
if ($var == 'HeaderText') { $TmplFmt[$ps][] = &$HTMLHeaderFmt; }
|
||||
$TmplFmt[$ps][$var] =& $GLOBALS[$var];
|
||||
}
|
||||
array_push($TmplFmt['Start'], $PageTextStartFmt);
|
||||
$PageStartFmt = 'function:PrintSkin Start';
|
||||
$PageEndFmt = 'function:PrintSkin End';
|
||||
$IsTemplateLoaded = 1;
|
||||
SDVA($TmplDisplay, $sddef);
|
||||
}
|
||||
|
||||
# This function is called to print a portion of the skin template
|
||||
# according to the settings in $TmplDisplay.
|
||||
function PrintSkin($pagename, $arg) {
|
||||
global $TmplFmt, $TmplDisplay;
|
||||
foreach ($TmplFmt[$arg] as $k => $v)
|
||||
if (!isset($TmplDisplay[$k]) || $TmplDisplay[$k])
|
||||
PrintFmt($pagename, $v);
|
||||
}
|
||||
|
||||
99
wiki/scripts/stdconfig.php
Executable file
99
wiki/scripts/stdconfig.php
Executable file
@@ -0,0 +1,99 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2002-2007 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file allows features to be easily enabled/disabled in config.php.
|
||||
Simply set variables for the features to be enabled/disabled in config.php
|
||||
before including this file. For example:
|
||||
$EnableQAMarkup=0; #disable Q: and A: tags
|
||||
$EnableWikiStyles=1; #include default wikistyles
|
||||
Each feature has a default setting, if the corresponding $Enable
|
||||
variable is not set then you get the default.
|
||||
|
||||
To avoid processing any of the features of this file, set
|
||||
$EnableStdConfig = 0;
|
||||
in config.php.
|
||||
*/
|
||||
|
||||
$pagename = ResolvePageName($pagename);
|
||||
|
||||
if (!IsEnabled($EnableStdConfig,1)) return;
|
||||
|
||||
|
||||
if (!function_exists('session_start') && IsEnabled($EnableRequireSession, 1))
|
||||
Abort('PHP is lacking session support', 'session');
|
||||
|
||||
if (IsEnabled($EnablePGCust,1))
|
||||
include_once("$FarmD/scripts/pgcust.php");
|
||||
|
||||
if (isset($PostConfig) && is_array($PostConfig)) {
|
||||
asort($PostConfig, SORT_NUMERIC);
|
||||
foreach ($PostConfig as $k=>$v) {
|
||||
if (!$k || !$v || $v<0 || $v>=50) continue;
|
||||
if (function_exists($k)) $k($pagename);
|
||||
elseif (file_exists($k)) include_once($k);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsEnabled($EnableRobotControl,1))
|
||||
include_once("$FarmD/scripts/robots.php");
|
||||
|
||||
if (IsEnabled($EnableCaches, 1))
|
||||
include_once("$FarmD/scripts/caches.php");
|
||||
|
||||
## Scripts that are part of a standard PmWiki distribution.
|
||||
if (IsEnabled($EnableAuthorTracking,1))
|
||||
include_once("$FarmD/scripts/author.php");
|
||||
if (IsEnabled($EnablePrefs, 1))
|
||||
include_once("$FarmD/scripts/prefs.php");
|
||||
if (IsEnabled($EnableSimulEdit, 1))
|
||||
include_once("$FarmD/scripts/simuledit.php");
|
||||
if (IsEnabled($EnableDrafts, 0))
|
||||
include_once("$FarmD/scripts/draft.php"); # after simuledit + prefs
|
||||
if (IsEnabled($EnableSkinLayout,1))
|
||||
include_once("$FarmD/scripts/skins.php"); # must come after prefs
|
||||
if (@$Transition || IsEnabled($EnableTransitions, 0))
|
||||
include_once("$FarmD/scripts/transition.php"); # must come after skins
|
||||
if (@$LinkWikiWords || IsEnabled($EnableWikiWords, 0))
|
||||
include_once("$FarmD/scripts/wikiwords.php"); # must come before stdmarkup
|
||||
if (IsEnabled($EnableStdMarkup,1))
|
||||
include_once("$FarmD/scripts/stdmarkup.php"); # must come after transition
|
||||
if ($action=='diff' && @!$HandleActions['diff'])
|
||||
include_once("$FarmD/scripts/pagerev.php");
|
||||
if (IsEnabled($EnableWikiTrails,1))
|
||||
include_once("$FarmD/scripts/trails.php");
|
||||
if (IsEnabled($EnableWikiStyles,1))
|
||||
include_once("$FarmD/scripts/wikistyles.php");
|
||||
if (IsEnabled($EnableMarkupExpressions, 1)
|
||||
&& !function_exists('MarkupExpression'))
|
||||
include_once("$FarmD/scripts/markupexpr.php");
|
||||
if (IsEnabled($EnablePageList,1))
|
||||
include_once("$FarmD/scripts/pagelist.php");
|
||||
if (IsEnabled($EnableVarMarkup,1))
|
||||
include_once("$FarmD/scripts/vardoc.php");
|
||||
if (!function_exists(@$DiffFunction))
|
||||
include_once("$FarmD/scripts/phpdiff.php");
|
||||
if ($action=='crypt')
|
||||
include_once("$FarmD/scripts/crypt.php");
|
||||
if ($action=='edit' && IsEnabled($EnableGUIButtons,0))
|
||||
include_once("$FarmD/scripts/guiedit.php");
|
||||
if (IsEnabled($EnableForms,1))
|
||||
include_once("$FarmD/scripts/forms.php"); # must come after prefs
|
||||
if (IsEnabled($EnableUpload,0))
|
||||
include_once("$FarmD/scripts/upload.php"); # must come after forms
|
||||
if (IsEnabled($EnableBlocklist, 0))
|
||||
include_once("$FarmD/scripts/blocklist.php");
|
||||
if (IsEnabled($EnableNotify,0))
|
||||
include_once("$FarmD/scripts/notify.php");
|
||||
if (IsEnabled($EnableDiag,0))
|
||||
include_once("$FarmD/scripts/diag.php");
|
||||
|
||||
if (IsEnabled($EnableUpgradeCheck,1)) {
|
||||
SDV($StatusPageName, "$SiteAdminGroup.Status");
|
||||
$page = ReadPage($StatusPageName, READPAGE_CURRENT);
|
||||
if (@$page['updatedto'] != $VersionNum)
|
||||
{ $action = 'upgrade'; include_once("$FarmD/scripts/upgrades.php"); }
|
||||
}
|
||||
504
wiki/scripts/stdmarkup.php
Executable file
504
wiki/scripts/stdmarkup.php
Executable file
@@ -0,0 +1,504 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2015 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script defines PmWiki's standard markup. It is automatically
|
||||
included from stdconfig.php unless $EnableStdMarkup==0.
|
||||
|
||||
Each call to Markup() below adds a new rule to PmWiki's translation
|
||||
engine (unless a rule with the same name has already been defined).
|
||||
The form of the call is Markup($id,$where,$pat,$rep);
|
||||
$id is a unique name for the rule, $where is the position of the rule
|
||||
relative to another rule, $pat is the pattern to look for, and
|
||||
$rep is the string to replace it with.
|
||||
*/
|
||||
|
||||
## first we preserve text in [=...=] and [@...@]
|
||||
function PreserveText($sigil, $text, $lead) {
|
||||
if ($sigil=='=') return $lead.Keep($text);
|
||||
if (strpos($text, "\n")===false)
|
||||
return "$lead<code class='escaped'>".Keep($text)."</code>";
|
||||
$text = preg_replace("/\n[^\\S\n]+$/", "\n", $text);
|
||||
if ($lead == "" || $lead == "\n")
|
||||
return "$lead<pre class='escaped'>".Keep($text)."</pre>";
|
||||
return "$lead<:pre,1>".Keep($text);
|
||||
}
|
||||
|
||||
Markup_e('[=','_begin',"/(\n[^\\S\n]*)?\\[([=@])(.*?)\\2\\]/s",
|
||||
"PreserveText(\$m[2], \$m[3], \$m[1])");
|
||||
Markup_e('restore','<_end',"/$KeepToken(\\d.*?)$KeepToken/",
|
||||
'$GLOBALS[\'KPV\'][$m[1]]');
|
||||
Markup('<:', '>restore',
|
||||
'/<:[^>]*>/', '');
|
||||
Markup('<vspace>', '<restore',
|
||||
'/<vspace>/',
|
||||
"<div class='vspace'></div>");
|
||||
Markup('<vspace><p>', '<<vspace>',
|
||||
"/<vspace><p\\b(([^>]*)(\\s)class=(['\"])([^>]*?)\\4)?/",
|
||||
"<p$2 class='vspace$3$5'");
|
||||
|
||||
## remove carriage returns before preserving text
|
||||
Markup('\\r','<[=','/\\r/','');
|
||||
|
||||
# $[phrase] substitutions
|
||||
Markup_e('$[phrase]', '>[=',
|
||||
'/\\$\\[(?>([^\\]]+))\\]/', "NoCache(XL(\$m[1]))");
|
||||
|
||||
# {$var} substitutions
|
||||
Markup_e('{$var}', '>$[phrase]',
|
||||
'/\\{(\\*|!?[-\\w.\\/\\x80-\\xff]*)(\\$:?\\w[-\\w]*)\\}/',
|
||||
"PRR(PVSE(PageVar(\$pagename, \$m[2], \$m[1])))");
|
||||
|
||||
# invisible (:textvar:...:) definition
|
||||
Markup('textvar:', '<split',
|
||||
'/\\(: *\\w[-\\w]* *:(?!\\)).*?:\\)/s', '');
|
||||
|
||||
## handle relative text vars in includes
|
||||
if (IsEnabled($EnableRelativePageVars, 1))
|
||||
SDV($QualifyPatterns["/\\{([-\\w\\x80-\\xfe]*)(\\$:?\\w+\\})/"],
|
||||
PCCF("'{' . (\$m[1] ? MakePageName(\$pagename, \$m[1]) : \$pagename) . \$m[2]", 'qualify'));
|
||||
|
||||
|
||||
## character entities
|
||||
Markup('&','<if','/&(?>([A-Za-z0-9]+|#\\d+|#[xX][A-Fa-f0-9]+));/',
|
||||
'&$1;');
|
||||
Markup('&amp;', '<&', '/&amp;/', Keep('&'));
|
||||
|
||||
|
||||
## (:if:)/(:elseif:)/(:else:)
|
||||
SDV($CondTextPattern,
|
||||
"/ \\(:if (\d*) (?:end)? \\b[^\n]*?:\\)
|
||||
.*?
|
||||
(?: \\(: (?:if\\1|if\\1end) \\s* :\\)
|
||||
| (?=\\(:(?:if\\1|if\\1end)\\b[^\n]*?:\\) | $)
|
||||
)
|
||||
/six");
|
||||
SDV($CondTextReplacement, "CondText2(\$pagename, \$m[0], \$m[1])");
|
||||
Markup_e('if', 'fulltext', $CondTextPattern, $CondTextReplacement);
|
||||
|
||||
function CondText2($pagename, $text, $code = '') {
|
||||
global $Conditions, $CondTextPattern, $CondTextReplacement;
|
||||
$if = "if$code";
|
||||
$repl = str_replace('$pagename', "'$pagename'", $CondTextReplacement);
|
||||
|
||||
$parts = preg_split("/\\(:(?:{$if}end|$if|else *$if|else$code)\\b\\s*(.*?)\\s*:\\)/",
|
||||
$text, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$x = array_shift($parts);
|
||||
while ($parts) {
|
||||
list($condspec, $condtext) = array_splice($parts, 0, 2);
|
||||
if (!preg_match("/^\\s*(!?)\\s*(\\S*)\\s*(.*?)\\s*$/", $condspec, $match)) continue;
|
||||
list($x, $not, $condname, $condparm) = $match;
|
||||
|
||||
if (!isset($Conditions[$condname]))
|
||||
return PPRE($CondTextPattern, $repl, $condtext);
|
||||
$tf = @eval("return ({$Conditions[$condname]});");
|
||||
if ($tf xor $not)
|
||||
return PPRE($CondTextPattern, $repl, $condtext);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
## (:include:)
|
||||
Markup_e('include', '>if',
|
||||
'/\\(:include\\s+(\\S.*?):\\)/i',
|
||||
"PRR(IncludeText(\$pagename, \$m[1]))");
|
||||
|
||||
## (:redirect:)
|
||||
Markup_e('redirect', '<include',
|
||||
'/\\(:redirect\\s+(\\S.*?):\\)/i',
|
||||
"RedirectMarkup(\$pagename, \$m[1])");
|
||||
|
||||
$SaveAttrPatterns['/\\(:(if\\d*|include|redirect)(\\s.*?)?:\\)/i'] = ' ';
|
||||
|
||||
## GroupHeader/GroupFooter handling
|
||||
Markup_e('nogroupheader', '>include',
|
||||
'/\\(:nogroupheader:\\)/i',
|
||||
"PZZ(\$GLOBALS['GroupHeaderFmt']='')");
|
||||
Markup_e('nogroupfooter', '>include',
|
||||
'/\\(:nogroupfooter:\\)/i',
|
||||
"PZZ(\$GLOBALS['GroupFooterFmt']='')");
|
||||
Markup_e('groupheader', '>nogroupheader',
|
||||
'/\\(:groupheader:\\)/i',
|
||||
"PRR(FmtPageName(\$GLOBALS['GroupHeaderFmt'],\$pagename))");
|
||||
Markup_e('groupfooter','>nogroupfooter',
|
||||
'/\\(:groupfooter:\\)/i',
|
||||
"PRR(FmtPageName(\$GLOBALS['GroupFooterFmt'],\$pagename))");
|
||||
|
||||
## (:nl:)
|
||||
Markup('nl0','<split',"/([^\n])(?>(?:\\(:nl:\\))+)([^\n])/i","$1\n$2");
|
||||
Markup('nl1','>nl0',"/\\(:nl:\\)/i",'');
|
||||
|
||||
## \\$ (end of line joins)
|
||||
Markup_e('\\$','>nl1',"/\\\\(?>(\\\\*))\n/",
|
||||
"str_repeat('<br />',strlen(\$m[1]))");
|
||||
|
||||
## Remove one <:vspace> after !headings
|
||||
Markup('!vspace', '>\\$', "/^(!(?>[^\n]+)\n)<:vspace>/m", '$1');
|
||||
|
||||
## (:noheader:),(:nofooter:),(:notitle:)...
|
||||
Markup_e('noheader', 'directives',
|
||||
'/\\(:noheader:\\)/i',
|
||||
"SetTmplDisplay('PageHeaderFmt',0)");
|
||||
Markup_e('nofooter', 'directives',
|
||||
'/\\(:nofooter:\\)/i',
|
||||
"SetTmplDisplay('PageFooterFmt',0)");
|
||||
Markup_e('notitle', 'directives',
|
||||
'/\\(:notitle:\\)/i',
|
||||
"SetTmplDisplay('PageTitleFmt',0)");
|
||||
Markup_e('noleft', 'directives',
|
||||
'/\\(:noleft:\\)/i',
|
||||
"SetTmplDisplay('PageLeftFmt',0)");
|
||||
Markup_e('noright', 'directives',
|
||||
'/\\(:noright:\\)/i',
|
||||
"SetTmplDisplay('PageRightFmt',0)");
|
||||
Markup_e('noaction', 'directives',
|
||||
'/\\(:noaction:\\)/i',
|
||||
"SetTmplDisplay('PageActionFmt',0)");
|
||||
|
||||
## (:spacewikiwords:)
|
||||
Markup_e('spacewikiwords', 'directives',
|
||||
'/\\(:(no)?spacewikiwords:\\)/i',
|
||||
"PZZ(\$GLOBALS['SpaceWikiWords']=(\$m[1]!='no'))");
|
||||
|
||||
## (:linkwikiwords:)
|
||||
Markup_e('linkwikiwords', 'directives',
|
||||
'/\\(:(no)?linkwikiwords:\\)/i',
|
||||
"PZZ(\$GLOBALS['LinkWikiWords']=(\$m[1]!='no'))");
|
||||
|
||||
## (:linebreaks:)
|
||||
Markup_e('linebreaks', 'directives',
|
||||
'/\\(:(no)?linebreaks:\\)/i',
|
||||
"PZZ(\$GLOBALS['HTMLPNewline'] = (\$m[1]!='no') ? '<br />' : '')");
|
||||
|
||||
## (:messages:)
|
||||
Markup_e('messages', 'directives',
|
||||
'/^\\(:messages:\\)/i',
|
||||
"'<:block>'.Keep(
|
||||
FmtPageName(implode('',(array)\$GLOBALS['MessagesFmt']), \$pagename))");
|
||||
|
||||
## (:comment:)
|
||||
Markup('comment', 'directives', '/\\(:comment .*?:\\)/i', '');
|
||||
|
||||
## (:title:) +fix for PITS:00266, 00779
|
||||
$tmpwhen = IsEnabled($EnablePageTitlePriority, 0) ? '<include' : 'directives';
|
||||
$tmpkeep = IsEnabled($EnablePageTitlePriority, 0) ? '1' : 'NULL';
|
||||
Markup_e('title', $tmpwhen,
|
||||
'/\\(:title\\s(.*?):\\)/i',
|
||||
"PZZ(PCache(\$pagename,
|
||||
\$zz=array('title' => SetProperty(\$pagename, 'title', \$m[1], NULL, $tmpkeep))))");
|
||||
unset($tmpwhen, $tmpkeep);
|
||||
|
||||
## (:keywords:), (:description:)
|
||||
Markup_e('keywords', 'directives',
|
||||
"/\\(:keywords?\\s+(.+?):\\)/i",
|
||||
"PZZ(SetProperty(\$pagename, 'keywords', \$m[1], ', '))");
|
||||
Markup_e('description', 'directives',
|
||||
"/\\(:description\\s+(.+?):\\)/i",
|
||||
"PZZ(SetProperty(\$pagename, 'description', \$m[1], '\n'))");
|
||||
$HTMLHeaderFmt['meta'] = 'function:PrintMetaTags';
|
||||
function PrintMetaTags($pagename, $args) {
|
||||
global $PCache;
|
||||
foreach(array('keywords', 'description') as $n) {
|
||||
foreach((array)@$PCache[$pagename]["=p_$n"] as $v) {
|
||||
$v = str_replace("'", ''', $v);
|
||||
print "<meta name='$n' content='$v' />\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#### inline markups ####
|
||||
## ''emphasis''
|
||||
Markup("''",'inline',"/''(.*?)''/",'<em>$1</em>');
|
||||
|
||||
## '''strong'''
|
||||
Markup("'''","<''","/'''(.*?)'''/",'<strong>$1</strong>');
|
||||
|
||||
## '''''strong emphasis'''''
|
||||
Markup("'''''","<'''","/'''''(.*?)'''''/",'<strong><em>$1</em></strong>');
|
||||
|
||||
## @@code@@
|
||||
Markup('@@','inline','/@@(.*?)@@/','<code>$1</code>');
|
||||
|
||||
## '+big+', '-small-'
|
||||
Markup("'+","<'''''","/'\\+(.*?)\\+'/",'<big>$1</big>');
|
||||
Markup("'-","<'''''","/'\\-(.*?)\\-'/",'<small>$1</small>');
|
||||
|
||||
## '^superscript^', '_subscript_'
|
||||
Markup("'^","<'''''","/'\\^(.*?)\\^'/",'<sup>$1</sup>');
|
||||
Markup("'_","<'''''","/'_(.*?)_'/",'<sub>$1</sub>');
|
||||
|
||||
## [+big+], [-small-]
|
||||
Markup_e('[+','inline','/\\[(([-+])+)(.*?)\\1\\]/',
|
||||
"'<span style=\'font-size:'.(round(pow(6/5,(\$m[2]=='-'? -1:1)*strlen(\$m[1]))*100,0)).'%\'>'.
|
||||
\$m[3].'</span>'");
|
||||
|
||||
## {+ins+}, {-del-}
|
||||
Markup('{+','inline','/\\{\\+(.*?)\\+\\}/','<ins>$1</ins>');
|
||||
Markup('{-','inline','/\\{-(.*?)-\\}/','<del>$1</del>');
|
||||
|
||||
## [[<<]] (break)
|
||||
Markup('[[<<]]','inline','/\\[\\[<<\\]\\]/',"<br clear='all' />");
|
||||
|
||||
###### Links ######
|
||||
## [[free links]]
|
||||
Markup_e('[[','links',"/(?>\\[\\[\\s*(.*?)\\]\\])($SuffixPattern)/",
|
||||
"Keep(MakeLink(\$pagename,\$m[1],NULL,\$m[2]),'L')");
|
||||
|
||||
## [[!Category]]
|
||||
SDV($CategoryGroup,'Category');
|
||||
SDV($LinkCategoryFmt,"<a class='categorylink' href='\$LinkUrl'>\$LinkText</a>");
|
||||
Markup_e('[[!','<[[','/\\[\\[!(.*?)\\]\\]/',
|
||||
"Keep(MakeLink(\$pagename,'$CategoryGroup/'.\$m[1],NULL,'',\$GLOBALS['LinkCategoryFmt']),'L')");
|
||||
# This is a temporary workaround for blank category pages.
|
||||
# It may be removed in a future release (Pm, 2006-01-24)
|
||||
if (preg_match("/^$CategoryGroup\\./", $pagename)) {
|
||||
SDV($DefaultPageTextFmt, '');
|
||||
SDV($PageNotFoundHeaderFmt, 'HTTP/1.1 200 Ok');
|
||||
}
|
||||
|
||||
## [[target | text]]
|
||||
Markup_e('[[|','<[[',
|
||||
"/(?>\\[\\[([^|\\]]*)\\|\\s*)(.*?)\\s*\\]\\]($SuffixPattern)/",
|
||||
"Keep(MakeLink(\$pagename,\$m[1],\$m[2],\$m[3]),'L')");
|
||||
|
||||
## [[text -> target ]]
|
||||
Markup_e('[[->','>[[|',
|
||||
"/(?>\\[\\[([^\\]]+?)\\s*-+>\\s*)(.*?)\\]\\]($SuffixPattern)/",
|
||||
"Keep(MakeLink(\$pagename,\$m[2],\$m[1],\$m[3]),'L')");
|
||||
|
||||
if (IsEnabled($EnableRelativePageLinks, 1))
|
||||
SDV($QualifyPatterns['/(\\[\\[(?>[^\\]]+?->)?\\s*)([-\\w\\x80-\\xfe\\s\'()]+([|#?].*?)?\\]\\])/'],
|
||||
PCCF("\$m[1].\$group.'/'.\$m[2]", 'qualify'));
|
||||
|
||||
## [[#anchor]]
|
||||
Markup_e('[[#','<[[','/(?>\\[\\[#([A-Za-z][-.:\\w]*))\\]\\]/',
|
||||
"Keep(TrackAnchors(\$m[1]) ? '' : \"<a name='{\$m[1]}' id='{\$m[1]}'></a>\", 'L')");
|
||||
function TrackAnchors($x) { global $SeenAnchor; return @$SeenAnchor[$x]++; }
|
||||
|
||||
## [[target |#]] reference links
|
||||
Markup_e('[[|#', '<[[|',
|
||||
"/(?>\\[\\[([^|\\]]+))\\|\\s*#\\s*\\]\\]/",
|
||||
"Keep(MakeLink(\$pagename,\$m[1],'['.++\$GLOBALS['MarkupFrame'][0]['ref'].']'),'L')");
|
||||
|
||||
## [[target |+]] title links moved inside LinkPage()
|
||||
|
||||
## bare urllinks
|
||||
Markup_e('urllink','>[[',
|
||||
"/\\b(?>(\\L))[^\\s$UrlExcludeChars]*[^\\s.,?!$UrlExcludeChars]/",
|
||||
"Keep(MakeLink(\$pagename,\$m[0],\$m[0]),'L')");
|
||||
|
||||
## mailto: links
|
||||
Markup_e('mailto','<urllink',
|
||||
"/\\bmailto:([^\\s$UrlExcludeChars]*[^\\s.,?!$UrlExcludeChars])/",
|
||||
"Keep(MakeLink(\$pagename,\$m[0],\$m[1]),'L')");
|
||||
|
||||
## inline images
|
||||
Markup_e('img','<urllink',
|
||||
"/\\b(?>(\\L))([^\\s$UrlExcludeChars]+$ImgExtPattern)(\"([^\"]*)\")?/",
|
||||
"Keep(\$GLOBALS['LinkFunctions'][\$m[1]](\$pagename,\$m[1],\$m[2],\$m[4],\$m[1].\$m[2],
|
||||
\$GLOBALS['ImgTagFmt']),'L')");
|
||||
|
||||
## bare wikilinks
|
||||
## v2.2: markup rule moved to scripts/wikiwords.php)
|
||||
Markup('wikilink', '>urllink');
|
||||
|
||||
## escaped `WikiWords
|
||||
## v2.2: rule kept here for markup compatibility with 2.1 and earlier
|
||||
Markup_e('`wikiword', '<wikilink',
|
||||
"/`(($GroupPattern([\\/.]))?($WikiWordPattern))/",
|
||||
"Keep(\$m[1])");
|
||||
|
||||
#### Block markups ####
|
||||
## Completely blank lines don't do anything.
|
||||
Markup('blank', '<block', '/^\\s+$/', '');
|
||||
|
||||
## process any <:...> markup (after all other block markups)
|
||||
Markup_e('^<:','>block','/^(?=\\s*\\S)(<:([^>]+)>)?/',"Block(\$m[2])");
|
||||
|
||||
## unblocked lines w/block markup become anonymous <:block>
|
||||
Markup('^!<:', '<^<:',
|
||||
"/^(?!<:)(?=.*(<\\/?($BlockPattern)\\b)|$KeepToken\\d+B$KeepToken)/",
|
||||
'<:block>');
|
||||
|
||||
## Lines that begin with displayed images receive their own block. A
|
||||
## pipe following the image indicates a "caption" (generates a linebreak).
|
||||
Markup_e('^img', 'block',
|
||||
"/^((?>(\\s+|%%|%[A-Za-z][-,=:#\\w\\s'\".]*%)*)$KeepToken(\\d+L)$KeepToken)(\\s*\\|\\s?)?(.*)$/",
|
||||
"(strpos(\$GLOBALS['KPV'][\$m[3]],'<img')===false) ? \$m[0] :
|
||||
'<:block,1><div>'.\$m[1] . (\$m[4] ? '<br />' : '') .\$m[5].'</div>'");
|
||||
|
||||
|
||||
## Whitespace at the beginning of lines can be used to maintain the
|
||||
## indent level of a previous list item, or a preformatted text block.
|
||||
Markup_e('^ws', '<^img', '/^\\s+ #1/x', "WSIndent(\$m[0])");
|
||||
function WSIndent($i) {
|
||||
global $MarkupFrame;
|
||||
$icol = strlen($i);
|
||||
for($depth = count(@$MarkupFrame[0]['cs']); $depth > 0; $depth--)
|
||||
if (@$MarkupFrame[0]['is'][$depth] == $icol) {
|
||||
$MarkupFrame[0]['idep'] = $depth;
|
||||
$MarkupFrame[0]['icol'] = $icol;
|
||||
return '';
|
||||
}
|
||||
return $i;
|
||||
}
|
||||
|
||||
## The $EnableWSPre setting uses leading spaces on markup lines to indicate
|
||||
## blocks of preformatted text.
|
||||
SDV($EnableWSPre, 1);
|
||||
Markup_e('^ ', 'block',
|
||||
'/^\\s+ #2/x',
|
||||
"(\$GLOBALS['EnableWSPre'] > 0 && strlen(\$m[0]) >= \$GLOBALS['EnableWSPre'])
|
||||
? '<:pre,1>'.\$m[0] : \$m[0]");
|
||||
|
||||
## bullet lists
|
||||
Markup('^*','block','/^(\\*+)\\s?(\\s*)/','<:ul,$1,$0>$2');
|
||||
|
||||
## numbered lists
|
||||
Markup('^#','block','/^(#+)\\s?(\\s*)/','<:ol,$1,$0>$2');
|
||||
|
||||
## indented (->) /hanging indent (-<) text
|
||||
Markup('^->','block','/^(?>(-+))>\\s?(\\s*)/','<:indent,$1,$1 $2>$2');
|
||||
Markup('^-<','block','/^(?>(-+))<\\s?(\\s*)/','<:outdent,$1,$1 $2>$2');
|
||||
|
||||
## definition lists
|
||||
Markup('^::','block','/^(:+)(\s*)([^:]+):/','<:dl,$1,$1$2><dt>$2$3</dt><dd>');
|
||||
|
||||
## Q: and A:
|
||||
Markup('^Q:', 'block', '/^Q:(.*)$/', "<:block,1><p class='question'>$1</p>");
|
||||
Markup('^A:', 'block', '/^A:/', Keep(''));
|
||||
|
||||
## tables
|
||||
## ||cell||, ||!header cell||, ||!caption!||
|
||||
Markup_e('^||||', 'block',
|
||||
'/^\\|\\|.*\\|\\|.*$/',
|
||||
"FormatTableRow(\$m[0])");
|
||||
## ||table attributes
|
||||
Markup_e('^||','>^||||','/^\\|\\|(.*)$/',
|
||||
"PZZ(\$GLOBALS['BlockMarkups']['table'][0] = '<table '.PQA(\$m[1]).'>')
|
||||
.'<:block,1>'");
|
||||
|
||||
## headings
|
||||
Markup_e('^!', 'block',
|
||||
'/^(!{1,6})\\s?(.*)$/',
|
||||
"'<:block,1><h'.strlen(\$m[1]).'>'.\$m[2].'</h'.strlen(\$m[1]).'>'");
|
||||
|
||||
## horiz rule
|
||||
Markup('^----','>^->','/^----+/','<:block,1><hr />');
|
||||
|
||||
#### (:table:) markup (AdvancedTables)
|
||||
function Cells($name,$attr) {
|
||||
global $MarkupFrame, $EnableTableAutoValignTop;
|
||||
$attr = PQA($attr);
|
||||
$tattr = @$MarkupFrame[0]['tattr'];
|
||||
$name = strtolower($name);
|
||||
$key = preg_replace('/end$/', '', $name);
|
||||
if (preg_match("/^(?:head|cell)(nr)?$/", $name)) $key = 'cell';
|
||||
$out = '<:block>'.MarkupClose($key);
|
||||
if (substr($name, -3) == 'end') return $out;
|
||||
$cf = & $MarkupFrame[0]['closeall'];
|
||||
if ($name == 'table') $MarkupFrame[0]['tattr'] = $attr;
|
||||
else if ($key == 'cell') {
|
||||
if (IsEnabled($EnableTableAutoValignTop, 1) && strpos($attr, "valign=")===false)
|
||||
$attr .= " valign='top'";
|
||||
$t = (strpos($name, 'head')===0 ) ? 'th' : 'td';
|
||||
if (!@$cf['table']) {
|
||||
$tattr = @$MarkupFrame[0]['tattr'];
|
||||
$out .= "<table $tattr><tr><$t $attr>";
|
||||
$cf['table'] = '</tr></table>';
|
||||
} else if ( preg_match("/nr$/", $name)) $out .= "</tr><tr><$t $attr>";
|
||||
else $out .= "<$t $attr>";
|
||||
$cf['cell'] = "</$t>";
|
||||
} else {
|
||||
$tag = preg_replace('/\\d+$/', '', $key);
|
||||
$out .= "<$tag $attr>";
|
||||
$cf[$key] = "</$tag>";
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
Markup_e('table', '<block',
|
||||
'/^\\(:(table|cell|cellnr|head|headnr|tableend|(?:div\\d*|section\\d*|article\\d*|header|footer|nav|address|aside)(?:end)?)(\\s.*?)?:\\)/i',
|
||||
"Cells(\$m[1],\$m[2])");
|
||||
Markup('^>>', '<table',
|
||||
'/^>>(.+?)<<(.*)$/',
|
||||
'(:div:)%div $1 apply=div%$2 ');
|
||||
Markup('^>><<', '<^>>',
|
||||
'/^>><</',
|
||||
'(:divend:)');
|
||||
|
||||
#### special stuff ####
|
||||
## (:markup:) for displaying markup examples
|
||||
function MarkupMarkup($pagename, $text, $opt = '') {
|
||||
global $MarkupWordwrapFunction, $MarkupWrapTag;
|
||||
SDV($MarkupWordwrapFunction,
|
||||
PCCF('return str_replace(" ", " ", nl2br($m));'));
|
||||
SDV($MarkupWrapTag, 'code');
|
||||
$MarkupMarkupOpt = array('class' => 'vert');
|
||||
$opt = array_merge($MarkupMarkupOpt, ParseArgs($opt));
|
||||
$html = MarkupToHTML($pagename, $text, array('escape' => 0));
|
||||
if (@$opt['caption'])
|
||||
$caption = str_replace("'", ''',
|
||||
"<caption>{$opt['caption']}</caption>");
|
||||
$class = preg_replace('/[^-\\s\\w]+/', ' ', @$opt['class']);
|
||||
if (strpos($class, 'horiz') !== false)
|
||||
{ $sep = ''; $pretext = $MarkupWordwrapFunction($text, 40); }
|
||||
else
|
||||
{ $sep = '</tr><tr>'; $pretext = $MarkupWordwrapFunction($text, 75); }
|
||||
return Keep(@"<table class='markup $class' align='center'>$caption
|
||||
<tr><td class='markup1' valign='top'><$MarkupWrapTag>$pretext</$MarkupWrapTag></td>$sep<td
|
||||
class='markup2' valign='top'>$html</td></tr></table>");
|
||||
}
|
||||
|
||||
Markup_e('markup', '<[=',
|
||||
"/\\(:markup(\\s+([^\n]*?))?:\\)[^\\S\n]*\\[([=@])(.*?)\\3\\]/si",
|
||||
"MarkupMarkup(\$pagename, \$m[4], \$m[2])");
|
||||
Markup_e('markupend', '>markup',
|
||||
"/\\(:markup(\\s+([^\n]*?))?:\\)[^\\S\n]*\n(.*?)\\(:markupend:\\)/si",
|
||||
"MarkupMarkup(\$pagename, \$m[3], \$m[1])");
|
||||
|
||||
SDV($HTMLStylesFmt['markup'], "
|
||||
table.markup { border:2px dotted #ccf; width:90%; }
|
||||
td.markup1, td.markup2 { padding-left:10px; padding-right:10px; }
|
||||
table.vert td.markup1 { border-bottom:1px solid #ccf; }
|
||||
table.horiz td.markup1 { width:23em; border-right:1px solid #ccf; }
|
||||
table.markup caption { text-align:left; }
|
||||
div.faq p, div.faq pre { margin-left:2em; }
|
||||
div.faq p.question { margin:1em 0 0.75em 0; font-weight:bold; }
|
||||
div.faqtoc div.faq * { display:none; }
|
||||
div.faqtoc div.faq p.question
|
||||
{ display:block; font-weight:normal; margin:0.5em 0 0.5em 20px; line-height:normal; }
|
||||
div.faqtoc div.faq p.question * { display:inline; }
|
||||
");
|
||||
|
||||
#### Special conditions ####
|
||||
## The code below adds (:if date:) conditions to the markup.
|
||||
$Conditions['date'] = "CondDate(\$condparm)";
|
||||
|
||||
function CondDate($condparm) {
|
||||
global $Now;
|
||||
if (!preg_match('/^(\\S*?)(\\.\\.(\\S*))?(\\s+\\S.*)?$/',
|
||||
trim($condparm), $match))
|
||||
return false;
|
||||
if ($match[4] == '') { $x0 = $Now; NoCache(); }
|
||||
else { list($x0, $x1) = DRange($match[4]); }
|
||||
if ($match[1] > '') {
|
||||
list($t0, $t1) = DRange($match[1]);
|
||||
if ($x0 < $t0) return false;
|
||||
if ($match[2] == '' && $x0 >= $t1) return false;
|
||||
}
|
||||
if ($match[3] > '') {
|
||||
list($t0, $t1) = DRange($match[3]);
|
||||
if ($x0 >= $t1) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
# This pattern enables the (:encrypt <phrase>:) markup/replace-on-save
|
||||
# pattern.
|
||||
SDV($ROSPatterns['/\\(:encrypt\\s+([^\\s:=]+).*?:\\)/'], PCCF("return pmcrypt(\$m[1]);"));
|
||||
|
||||
126
wiki/scripts/trails.php
Executable file
126
wiki/scripts/trails.php
Executable file
@@ -0,0 +1,126 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2002-2013 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script enables markup of the form <<|TrailPage|>> to be
|
||||
used to build "trails" through wiki documents.
|
||||
|
||||
This feature is automatically included from stdconfig.php unless
|
||||
disabled by $EnableWikiTrails = 0; . To explicitly include this feature,
|
||||
execute
|
||||
include_once("scripts/trails.php");
|
||||
from config.php somewhere.
|
||||
|
||||
Once enabled, the <<|TrailPage|>> markup is replaced with
|
||||
<< PrevPage | TrailPage | NextPage >> on output. TrailPage should
|
||||
contain either a bullet or number list defining the sequence of pages
|
||||
in the "trail".
|
||||
|
||||
The ^|TrailPage|^ markup uses the depth of the bullets to display
|
||||
the ancestry of the TrailPage to the current one. The <|TrailPage|>
|
||||
markup is like <<|TrailPage|>> except that "< PrevPage |" and
|
||||
"| NextPage >" are omitted if at the beginning or end of the
|
||||
trail respectively. Thanks to John Rankin for contributing these
|
||||
markups and the original suggestion for WikiTrails.
|
||||
*/
|
||||
|
||||
Markup_e('<<|','<links','/<<\\|([^|]+|\\[\\[(.+?)\\]\\])\\|>>/',
|
||||
"PRR(MakeTrailStop(\$pagename,\$m[1]))");
|
||||
Markup_e('<|','><<|','/<\\|([^|]+|\\[\\[(.+?)\\]\\])\\|>/',
|
||||
"PRR(MakeTrailStopB(\$pagename,\$m[1]))");
|
||||
Markup_e('^|','<links','/\\^\\|([^|]+|\\[\\[(.+?)\\]\\])\\|\\^/',
|
||||
"PRR(MakeTrailPath(\$pagename,\$m[1]))");
|
||||
|
||||
SDVA($SaveAttrPatterns, array(
|
||||
'/<<\\|([^|]+|\\[\\[(.+?)\\]\\])\\|>>/' => '$1',
|
||||
'/<\\|([^|]+|\\[\\[(.+?)\\]\\])\\|>/' => '$1',
|
||||
'/\\^\\|([^|]+|\\[\\[(.+?)\\]\\])\\|\\^/' => '$1'));
|
||||
|
||||
$Conditions['ontrail'] = 'CondOnTrail($pagename, $condparm)';
|
||||
|
||||
function CondOnTrail($pagename, $condparm) {
|
||||
@list($trailname, $pn) = preg_split('/\\s+/', $condparm, 2);
|
||||
$trail = ReadTrail($pagename, $trailname);
|
||||
if (!$trail) return false;
|
||||
$pn = ($pn > '') ? MakePageName($pagename, $pn) : $pagename;
|
||||
foreach($trail as $t)
|
||||
if ($t['pagename'] == $pn) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function ReadTrail($pagename, $trailname) {
|
||||
global $RASPageName, $SuffixPattern, $GroupPattern, $WikiWordPattern,
|
||||
$LinkWikiWords;
|
||||
if (preg_match('/^\\[\\[(.+?)(->|\\|)(.+?)\\]\\]$/', $trailname, $m))
|
||||
$trailname = ($m[2] == '|') ? $m[1] : $m[3];
|
||||
$trailtext = RetrieveAuthSection($pagename, $trailname);
|
||||
$trailname = $RASPageName;
|
||||
$trailtext = Qualify($trailname, $trailtext);
|
||||
$t = array();
|
||||
$n = 0;
|
||||
foreach(explode("\n", PHSC(@$trailtext, ENT_NOQUOTES))
|
||||
as $x) {
|
||||
$x = preg_replace("/\\[\\[([^\\]]*)->([^\\]]*)\\]\\]/",'[[$2|$1]]',$x);
|
||||
if (!preg_match("/^([#*:]+) \\s*
|
||||
(\\[\\[([^:#!|][^|:]*?)(?:\".*?\")?(\\|.*?)?\\]\\]($SuffixPattern)
|
||||
| (($GroupPattern([\\/.]))?$WikiWordPattern)) (.*)/x",$x,$match))
|
||||
continue;
|
||||
if (@$match[6]) {
|
||||
if (!$LinkWikiWords) continue;
|
||||
$tgt = MakePageName($trailname, $match[6]);
|
||||
} else $tgt = MakePageName($trailname, $match[3]);
|
||||
$t[$n]['depth'] = $depth = strlen($match[1]);
|
||||
$t[$n]['pagename'] = $tgt;
|
||||
$t[$n]['markup'] = $match[2];
|
||||
$t[$n]['detail'] = $match[9];
|
||||
for($i=$depth;$i<10;$i++) $d[$i]=$n;
|
||||
if ($depth>1) $t[$n]['parent']=@$d[$depth-1];
|
||||
$n++;
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
|
||||
function MakeTrailStop($pagename,$trailname) {
|
||||
$t = ReadTrail($pagename,$trailname);
|
||||
$prev=''; $next='';
|
||||
for($i=0;$i<count($t);$i++) {
|
||||
if ($t[$i]['pagename']==$pagename) {
|
||||
if ($i>0) $prev = $t[$i-1]['markup'];
|
||||
if ($i+1<count($t)) $next = $t[$i+1]['markup'];
|
||||
}
|
||||
}
|
||||
return "<span class='wikitrail'><< $prev | $trailname | $next >></span>";
|
||||
}
|
||||
|
||||
function MakeTrailStopB($pagename,$trailname) {
|
||||
$t = ReadTrail($pagename,$trailname);
|
||||
$prev = ''; $next = '';
|
||||
for($i=0;$i<count($t);$i++) {
|
||||
if ($t[$i]['pagename']==$pagename) {
|
||||
if ($i>0) $prev = '< '.$t[$i-1]['markup'].' | ';
|
||||
if ($i+1<count($t)) $next = ' | '.$t[$i+1]['markup'].' >';
|
||||
}
|
||||
}
|
||||
return "<span class='wikitrail'>$prev$trailname$next</span>";
|
||||
}
|
||||
|
||||
function MakeTrailPath($pagename,$trailname) {
|
||||
global $TrailPathSep;
|
||||
SDV($TrailPathSep,' | ');
|
||||
$t = ReadTrail($pagename,$trailname);
|
||||
$crumbs = '';
|
||||
for($i=0;$i<count($t);$i++) {
|
||||
if ($t[$i]['pagename']==$pagename) {
|
||||
while (@$t[$i]['depth']>0) {
|
||||
$crumbs = $TrailPathSep.$t[$i]['markup'].$crumbs;
|
||||
$i = @$t[$i]['parent'];
|
||||
}
|
||||
return "<span class='wikitrail'>$trailname$crumbs</span>";
|
||||
}
|
||||
}
|
||||
return "<span class='wikitrail'>$trailname</span>";
|
||||
}
|
||||
|
||||
277
wiki/scripts/transition.php
Executable file
277
wiki/scripts/transition.php
Executable file
@@ -0,0 +1,277 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2005-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script handles various "fixup transitions" that might need to
|
||||
occur to help existing sites smoothly upgrade to newer releases of
|
||||
PmWiki. Rather than put the workarounds in the main code files, we
|
||||
try to centralize them here so we can see what's deprecated and a
|
||||
simple switch (?trans=0 in the url) can tell the admin if his site
|
||||
is relying on an outdated feature or way of doing things.
|
||||
|
||||
Transitions defined in this script:
|
||||
|
||||
$Transition['nosessionencode'] - turn off session encoding
|
||||
|
||||
$Transition['version'] < 2001967 - all transitions listed above
|
||||
|
||||
$Transition['wspre'] - leading spaces are pre text
|
||||
|
||||
$Transition['version'] < 2001941 - all transitions listed above
|
||||
|
||||
$Transition['wikiwords'] - 2.1-style WikiWord processing
|
||||
|
||||
$Transition['version'] < 2001924 - all transitions listed above
|
||||
|
||||
$Transition['abslinks'] - absolute links/page vars
|
||||
|
||||
$Transition['version'] < 2001901 - all transitions listed above
|
||||
|
||||
$Transition['vspace'] - restore <p class='vspace'></p>
|
||||
|
||||
$Transition['version'] < 2001006 - all transitions listed above
|
||||
|
||||
$Transition['fplbygroup'] - restore FPLByGroup function
|
||||
|
||||
$Transition['version'] < 2000915 - all transitions listed above
|
||||
|
||||
$Transition['mainrc'] - keep using Main.AllRecentChanges
|
||||
$Transition['mainapprovedurls'] - keep using Main.ApprovedUrls
|
||||
$Transition['pageeditfmt'] - default $PageEditFmt value
|
||||
$Transition['mainpages'] - other default pages in Main
|
||||
|
||||
$Transition['version'] < 1999944 - all transitions listed above
|
||||
|
||||
To get all of the transitions for compatibility with a previous
|
||||
version of PmWiki, simply set $Transition['version'] in a local
|
||||
configuration file to the version number you want compatibility
|
||||
with. All of the transitions associated with that version will
|
||||
then be enabled. Example:
|
||||
|
||||
# Keep compatibility with PmWiki version 2.0.13
|
||||
$Transition['version'] = 2000013;
|
||||
|
||||
To explicitly enable or disable specific transitions, set
|
||||
the corresponding $Transition[] element to 1 or 0. This will
|
||||
override the $Transition['version'] item listed above. For
|
||||
example, to enable just the 'pageeditfmt' transition, use
|
||||
|
||||
$Transition['pageeditfmt'] = 1;
|
||||
|
||||
*/
|
||||
|
||||
## if ?trans=0 is specified, then we don't do any fixups.
|
||||
if (@$_REQUEST['trans']==='0') return;
|
||||
|
||||
## set a default Transition version if we don't have one
|
||||
SDV($Transition['version'], $VersionNum);
|
||||
|
||||
## Transitions from 2.2.0-beta67
|
||||
if (@$Transition['version'] < 2001967)
|
||||
SDVA($Transition, array('nosessionencode' => 1));
|
||||
|
||||
if (@$Transition['nosessionencode']) {
|
||||
$SessionEncode = NULL;
|
||||
$SessionDecode = NULL;
|
||||
}
|
||||
|
||||
## Transitions from 2.2.0-beta41
|
||||
if (@$Transition['version'] < 2001941)
|
||||
SDVA($Transition, array('wspre' => 1));
|
||||
|
||||
if (@$Transition['wspre']) SDV($EnableWSPre, 1);
|
||||
|
||||
## Transitions from 2.2.0-beta24
|
||||
if (@$Transition['version'] < 2001924)
|
||||
SDVA($Transition, array('wikiwords' => 1));
|
||||
|
||||
## wikiwords:
|
||||
## This restores the PmWiki 2.1 behavior for WikiWord processing.
|
||||
## WikiWords aren't linked by default, but appear with
|
||||
## <span class='wikiword'>...</span> tags around them.
|
||||
if (@$Transition['wikiwords']) {
|
||||
SDV($EnableWikiWords, 1);
|
||||
SDV($LinkWikiWords, 0);
|
||||
}
|
||||
|
||||
## Transitions from 2.2.0-beta1
|
||||
if (@$Transition['version'] < 2001901)
|
||||
SDVA($Transition, array('abslinks' => 1));
|
||||
|
||||
## abslinks:
|
||||
## This restores settings so that PmWiki treats all links
|
||||
## as absolute (following the 2.1.x and earlier interpretation).
|
||||
if (@$Transition['abslinks']) {
|
||||
SDV($EnableRelativePageLinks, 0);
|
||||
SDV($EnableRelativePageVars, 0);
|
||||
}
|
||||
|
||||
## Transitions from 2.1.12
|
||||
|
||||
if (@$Transition['version'] < 2001012)
|
||||
SDVA($Transition, array('nodivnest' => 1));
|
||||
|
||||
## nodivnest:
|
||||
## This restores the PmWiki 2.1.11 behavior that doesn't
|
||||
## allow nesting of divs and tables.
|
||||
if (@$Transition['nodivnest']) {
|
||||
function TCells($name,$attr) {
|
||||
global $MarkupFrame;
|
||||
$attr = preg_replace('/([a-zA-Z]=)([^\'"]\\S*)/',"\$1'\$2'",$attr);
|
||||
$tattr = @$MarkupFrame[0]['tattr'];
|
||||
$name = strtolower($name);
|
||||
$out = '<:block>';
|
||||
if (strncmp($name, 'cell', 4) != 0 || @$MarkupFrame[0]['closeall']['div']) {
|
||||
$out .= @$MarkupFrame[0]['closeall']['div'];
|
||||
unset($MarkupFrame[0]['closeall']['div']);
|
||||
$out .= @$MarkupFrame[0]['closeall']['table'];
|
||||
unset($MarkupFrame[0]['closeall']['table']);
|
||||
}
|
||||
if ($name == 'div') {
|
||||
$MarkupFrame[0]['closeall']['div'] = "</div>";
|
||||
$out .= "<div $attr>";
|
||||
}
|
||||
if ($name == 'table') $MarkupFrame[0]['tattr'] = $attr;
|
||||
if (strncmp($name, 'cell', 4) == 0) {
|
||||
if (strpos($attr, "valign=")===false) $attr .= " valign='top'";
|
||||
if (!@$MarkupFrame[0]['closeall']['table']) {
|
||||
$MarkupFrame[0]['closeall']['table'] = "</td></tr></table>";
|
||||
$out .= "<table $tattr><tr><td $attr>";
|
||||
} else if ($name == 'cellnr') $out .= "</td></tr><tr><td $attr>";
|
||||
else $out .= "</td><td $attr>";
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
Markup_e('table', '<block',
|
||||
'/^\\(:(table|cell|cellnr|tableend|div|divend)(\\s.*?)?:\\)/i',
|
||||
"TCells(\$m[1],\$m[2])");
|
||||
}
|
||||
|
||||
|
||||
## Transitions from 2.1.7
|
||||
|
||||
if (@$Transition['version'] < 2001007)
|
||||
SDVA($Transition, array('vspace' => 1));
|
||||
|
||||
## vspace:
|
||||
## This restores PmWiki's use of <p class='vspace'></p> to mark
|
||||
## vertical space in the output.
|
||||
if (@$Transition['vspace']) $HTMLVSpace = "<p class='vspace'></p>";
|
||||
|
||||
|
||||
## Transitions from 2.1.beta15
|
||||
|
||||
if (@$Transition['version'] < 2000915)
|
||||
SDVA($Transition, array('fplbygroup' => 1));
|
||||
|
||||
## fplbygroup:
|
||||
## The FPLByGroup function was removed in 2.1.beta15, this restores it.
|
||||
if (@$Transition['fplbygroup'] && !function_exists('FPLByGroup')) {
|
||||
SDV($FPLFormatOpt['bygroup'], array('fn' => 'FPLByGroup'));
|
||||
function FPLByGroup($pagename, &$matches, $opt) {
|
||||
global $FPLByGroupStartFmt, $FPLByGroupEndFmt, $FPLByGroupGFmt,
|
||||
$FPLByGroupIFmt, $FPLByGroupOpt;
|
||||
SDV($FPLByGroupStartFmt,"<dl class='fplbygroup'>");
|
||||
SDV($FPLByGroupEndFmt,'</dl>');
|
||||
SDV($FPLByGroupGFmt,"<dt><a href='\$ScriptUrl/\$Group'>\$Group</a> /</dt>\n");
|
||||
SDV($FPLByGroupIFmt,"<dd><a href='\$PageUrl'>\$Name</a></dd>\n");
|
||||
SDVA($FPLByGroupOpt, array('readf' => 0, 'order' => 'name'));
|
||||
$matches = MakePageList($pagename,
|
||||
array_merge((array)$FPLByGroupOpt, $opt), 0);
|
||||
if (@$opt['count']) array_splice($matches, $opt['count']);
|
||||
if (count($matches)<1) return '';
|
||||
$out = '';
|
||||
foreach($matches as $pn) {
|
||||
$pgroup = FmtPageName($FPLByGroupGFmt, $pn);
|
||||
if ($pgroup != @$lgroup) { $out .= $pgroup; $lgroup = $pgroup; }
|
||||
$out .= FmtPageName($FPLByGroupIFmt, $pn);
|
||||
}
|
||||
return FmtPageName($FPLByGroupStartFmt, $pagename) . $out .
|
||||
FmtPageName($FPLByGroupEndFmt, $pagename);
|
||||
}
|
||||
}
|
||||
|
||||
## Transitions from 2.0.beta44
|
||||
|
||||
if (@$Transition['version'] < 1999944)
|
||||
SDVA($Transition, array('mainrc' => 1, 'mainapprovedurls' => 1,
|
||||
'pageeditfmt' => 1, 'mainpages' => 1));
|
||||
|
||||
## mainrc:
|
||||
## 2.0.beta44 switched Main.AllRecentChanges to be
|
||||
## $SiteGroup.AllRecentChanges. This setting keeps Main.AllRecentChanges
|
||||
## if it exists.
|
||||
if (@$Transition['mainrc'] && PageExists('Main.AllRecentChanges')) {
|
||||
SDV($RecentChangesFmt['Main.AllRecentChanges'],
|
||||
'* [[$Group.$Name]] . . . $CurrentTime $[by] $AuthorLink');
|
||||
}
|
||||
|
||||
## siteapprovedurls:
|
||||
## 2.0.beta44 switched Main.ApprovedUrls to be $SiteGroup.ApprovedUrls .
|
||||
## This setting keeps using Main.ApprovedUrls if it exists.
|
||||
if (@$Transition['mainapprovedurls'] && PageExists('Main.ApprovedUrls')) {
|
||||
$ApprovedUrlPagesFmt = (array)$ApprovedUrlPagesFmt;
|
||||
if (PageExists(FmtPageName($ApprovedUrlPagesFmt[0], $pagename)))
|
||||
$ApprovedUrlPagesFmt[] = 'Main.ApprovedUrls';
|
||||
else array_unshift($ApprovedUrlPagesFmt, 'Main.ApprovedUrls');
|
||||
}
|
||||
|
||||
## pageeditfmt:
|
||||
## 2.0.beta44 switched to using wiki markup forms for page editing.
|
||||
## However, some sites and skins have customized values of $PageEdit.
|
||||
## This setting restores the default values.
|
||||
if (@$Transition['pageeditfmt']) {
|
||||
SDV($PageEditFmt, "<div id='wikiedit'>
|
||||
<a id='top' name='top'></a>
|
||||
<h1 class='wikiaction'>$[Editing \$FullName]</h1>
|
||||
<form method='post' action='\$PageUrl?action=edit'>
|
||||
<input type='hidden' name='action' value='edit' />
|
||||
<input type='hidden' name='n' value='\$FullName' />
|
||||
<input type='hidden' name='basetime' value='\$EditBaseTime' />
|
||||
\$EditMessageFmt
|
||||
<textarea id='text' name='text' rows='25' cols='60'
|
||||
onkeydown='if (event.keyCode==27) event.returnValue=false;'
|
||||
>\$EditText</textarea><br />
|
||||
$[Author]: <input type='text' name='author' value='\$Author' />
|
||||
<input type='checkbox' name='diffclass' value='minor' \$DiffClassMinor />
|
||||
$[This is a minor edit]<br />
|
||||
<input type='submit' name='post' value=' $[Save] ' />
|
||||
<input type='submit' name='preview' value=' $[Preview] ' />
|
||||
<input type='reset' value=' $[Reset] ' /></form></div>");
|
||||
if (@$_POST['preview'])
|
||||
SDV($PagePreviewFmt, "<div id='wikipreview'>
|
||||
<h2 class='wikiaction'>$[Preview \$FullName]</h2>
|
||||
<p><b>$[Page is unsaved]</b></p>
|
||||
\$PreviewText
|
||||
<hr /><p><b>$[End of preview -- remember to save]</b><br />
|
||||
<a href='#top'>$[Top]</a></p></div>");
|
||||
SDV($HandleEditFmt, array(&$PageStartFmt,
|
||||
&$PageEditFmt, 'wiki:$[PmWiki.EditQuickReference]', &$PagePreviewFmt,
|
||||
&$PageEndFmt));
|
||||
$EditMessageFmt = implode('', $MessagesFmt) . $EditMessageFmt;
|
||||
if ($action=='edit' && IsEnabled($EnableGUIButtons, 0))
|
||||
array_push($EditFunctions, 'GUIEdit');
|
||||
} else $MessagesFmt[] = @$EditMessageFmt;
|
||||
|
||||
|
||||
function GUIEdit($pagename, &$page, &$new) {
|
||||
global $EditMessageFmt;
|
||||
$EditMessageFmt .= GUIButtonCode($pagename);
|
||||
}
|
||||
|
||||
## mainpages:
|
||||
## In 2.0.beta44 several utility pages change location to the new Site
|
||||
## group. These settings cause some skins (that use translations)
|
||||
## to know to link to the new locations.
|
||||
if (@$Transition['mainpages']) {
|
||||
XLSDV('en', array(
|
||||
'Main/SearchWiki' => XL('Site/Search'),
|
||||
'PmWiki.EditQuickReference' => XL('Site/EditQuickReference'),
|
||||
'PmWiki.UploadQuickReference' => XL('Site/UploadQuickReference'),
|
||||
));
|
||||
}
|
||||
|
||||
99
wiki/scripts/upgrades.php
Executable file
99
wiki/scripts/upgrades.php
Executable file
@@ -0,0 +1,99 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2007-2011 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
*/
|
||||
global $HandleActions, $HandleAuth;
|
||||
|
||||
$HandleActions['upgrade'] = 'HandleUpgrade';
|
||||
$HandleAuth['upgrade'] = 'read';
|
||||
|
||||
function HandleUpgrade($pagename, $auth = 'ALWAYS') {
|
||||
global $SiteGroup, $SiteAdminGroup, $StatusPageName, $ScriptUrl,
|
||||
$AuthUserPageFmt, $VersionNum, $Version;
|
||||
StopWatch('HandleUpgrade: begin');
|
||||
|
||||
$message = '';
|
||||
$done = '';
|
||||
## check for Site.* --> SiteAdmin.*
|
||||
foreach(array('AuthUser', 'NotifyList', 'Blocklist', 'ApprovedUrls') as $n) {
|
||||
$n0 = "$SiteGroup.$n"; $n1 = "$SiteAdminGroup.$n";
|
||||
StopWatch("HandleUpgrade: checking $n0 -> $n1");
|
||||
## checking AuthUser is special, because Site.AuthUser comes with the
|
||||
## distribution.
|
||||
if ($n == 'AuthUser') {
|
||||
## if we already have a user-modified SiteAdmin.AuthUser, we can skip
|
||||
SDV($AuthUserPageFmt, '$SiteAdminGroup.AuthUser');
|
||||
$n1 = FmtPageName($AuthUserPageFmt, $pagename);
|
||||
$page = ReadPage($n1, READPAGE_CURRENT);
|
||||
if (@$page['time'] > 1000000000) continue;
|
||||
## if there's not a user-modified Site.AuthUser, we can skip
|
||||
$page = ReadPage($n0, READPAGE_CURRENT);
|
||||
if (@$page['time'] == 1000000000) continue;
|
||||
} else if (!PageExists($n0) || PageExists($n1)) continue;
|
||||
|
||||
if (@$_REQUEST['migrate'] == 'yes') {
|
||||
## if the admin wants PmWiki to migrate, do it.
|
||||
$page = RetrieveAuthPage($n0, 'admin', true);
|
||||
StopWatch("HandleUpgrade: copying $n0 -> $n1");
|
||||
if ($page) {
|
||||
WritePage($n1, $page);
|
||||
$done .= "<li>Copied $n0 to $n1</li>";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$message .= "<li>$n0 -> $n1</li>";
|
||||
}
|
||||
|
||||
if ($message) {
|
||||
$migrateurl = "$ScriptUrl?action=upgrade&migrate=yes";
|
||||
$infourl = 'http://www.pmwiki.org/wiki/PmWiki/UpgradeToSiteAdmin';
|
||||
$message =
|
||||
"<h2>Upgrade notice -- SiteAdmin group</h2>
|
||||
<p>This version of PmWiki expects several administrative pages
|
||||
from the <em>Site</em> group to be found in a new <em>SiteAdmin</em> group.
|
||||
On this site, the following pages appear to need to be relocated:</p>
|
||||
<ul>$message</ul>
|
||||
|
||||
<p>For more information about this change, including the various
|
||||
options for proceeding, see</p>
|
||||
<blockquote><a target='_blank' href='$infourl'>$infourl</a></blockquote>
|
||||
|
||||
<form action='$ScriptUrl' method='post'>
|
||||
<p>If you would like PmWiki to attempt to automatically copy
|
||||
these pages into their new <br /> locations for you, try
|
||||
<input type='hidden' name='action' value='upgrade' />
|
||||
<input type='hidden' name='migrate' value='yes' />
|
||||
<input type='submit' value='Relocate pages listed above' />
|
||||
(admin password required) </p>
|
||||
</form>
|
||||
|
||||
<p>If you want to configure PmWiki so that it continues to
|
||||
look for the above pages in <em>$SiteGroup</em>, add the
|
||||
following line near the top of <em>local/config.php</em>:</p>
|
||||
|
||||
<blockquote><pre>\$SiteAdminGroup = \$SiteGroup;</pre></blockquote>
|
||||
|
||||
$Version
|
||||
";
|
||||
print $message;
|
||||
exit;
|
||||
}
|
||||
|
||||
StopWatch("UpgradeCheck: writing $StatusPageName");
|
||||
Lock(2);
|
||||
SDV($StatusPageName, "$SiteAdminGroup.Status");
|
||||
$page = ReadPage($StatusPageName);
|
||||
$page['updatedto'] = $VersionNum;
|
||||
WritePage($StatusPageName, $page);
|
||||
|
||||
if ($done) {
|
||||
$done .= "<li>Updated $StatusPageName</li>";
|
||||
echo "<h2>Upgrade to $Version ... ok</h2><ul>$done</ul>";
|
||||
$GLOBALS['EnableRedirect'] = 0;
|
||||
}
|
||||
Redirect($pagename);
|
||||
}
|
||||
374
wiki/scripts/upload.php
Executable file
374
wiki/scripts/upload.php
Executable file
@@ -0,0 +1,374 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2015 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script adds upload capabilities to PmWiki. Uploads can be
|
||||
enabled by setting
|
||||
$EnableUpload = 1;
|
||||
in config.php. In addition, an upload password must be set, as
|
||||
the default is to lock uploads. In some configurations it may also
|
||||
be necessary to set values for $UploadDir and $UploadUrlFmt,
|
||||
especially if any form of URL rewriting is being performed.
|
||||
See the PmWiki.UploadsAdmin page for more information.
|
||||
*/
|
||||
|
||||
## $EnableUploadOverwrite determines if we allow previously uploaded
|
||||
## files to be overwritten.
|
||||
SDV($EnableUploadOverwrite,1);
|
||||
|
||||
## $UploadExts contains the list of file extensions we're willing to
|
||||
## accept, along with the Content-Type: value appropriate for each.
|
||||
SDVA($UploadExts,array(
|
||||
'gif' => 'image/gif', 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg',
|
||||
'png' => 'image/png', 'bmp' => 'image/bmp', 'ico' => 'image/x-icon',
|
||||
'wbmp'=> 'image/vnd.wap.wbmp', 'svg' => 'image/svg+xml', 'xcf' => 'image/x-xcf',
|
||||
'mp3' => 'audio/mpeg', 'au' => 'audio/basic', 'wav' => 'audio/x-wav',
|
||||
'ogg' => 'audio/ogg', 'flac' => 'audio/x-flac',
|
||||
'ogv' => 'video/ogg', 'mp4' => 'video/mp4', 'webm' => 'video/webm',
|
||||
'mpg' => 'video/mpeg', 'mpeg' => 'video/mpeg',
|
||||
'mov' => 'video/quicktime', 'qt' => 'video/quicktime',
|
||||
'wmf' => 'text/plain', 'avi' => 'video/x-msvideo',
|
||||
'zip' => 'application/zip', '7z' => 'application/x-7z-compressed',
|
||||
'gz' => 'application/x-gzip', 'tgz' => 'application/x-gzip',
|
||||
'rpm' => 'application/x-rpm',
|
||||
'hqx' => 'application/mac-binhex40', 'sit' => 'application/x-stuffit',
|
||||
'doc' => 'application/msword', 'ppt' => 'application/vnd.ms-powerpoint',
|
||||
'xls' => 'application/vnd.ms-excel', 'mdb' => 'text/plain',
|
||||
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'exe' => 'application/octet-stream',
|
||||
'pdf' => 'application/pdf', 'psd' => 'text/plain',
|
||||
'ps' => 'application/postscript', 'ai' => 'application/postscript',
|
||||
'eps' => 'application/postscript',
|
||||
'htm' => 'text/html', 'html' => 'text/html', 'css' => 'text/css',
|
||||
'fla' => 'application/x-shockwave-flash',
|
||||
'swf' => 'application/x-shockwave-flash',
|
||||
'txt' => 'text/plain', 'rtf' => 'application/rtf',
|
||||
'tex' => 'application/x-tex', 'dvi' => 'application/x-dvi',
|
||||
'odt' => 'application/vnd.oasis.opendocument.text',
|
||||
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
|
||||
'odp' => 'application/vnd.oasis.opendocument.presentation',
|
||||
'odg' => 'application/vnd.oasis.opendocument.graphics',
|
||||
'epub'=> 'application/epub+zip',
|
||||
'kml' => 'application/vnd.google-earth.kml+xml',
|
||||
'kmz' => 'application/vnd.google-earth.kmz',
|
||||
'' => 'text/plain'));
|
||||
|
||||
# Array containing forbidden strings in a filename, array('.php', '.cgi')
|
||||
SDV($UploadBlacklist, array());
|
||||
|
||||
SDV($UploadMaxSize,50000);
|
||||
SDV($UploadPrefixQuota,0);
|
||||
SDV($UploadDirQuota,0);
|
||||
foreach($UploadExts as $k=>$v)
|
||||
if (!isset($UploadExtSize[$k])) $UploadExtSize[$k]=$UploadMaxSize;
|
||||
|
||||
SDV($UploadDir,'uploads');
|
||||
SDV($UploadPermAdd,0444);
|
||||
SDV($UploadPermSet,0);
|
||||
SDV($UploadPrefixFmt,'/$Group');
|
||||
SDV($UploadFileFmt,"$UploadDir$UploadPrefixFmt");
|
||||
$v = preg_replace('#^/(.*/)#', '', $UploadDir);
|
||||
SDV($UploadUrlFmt,preg_replace('#/[^/]*$#', "/$v", $PubDirUrl, 1));
|
||||
SDV($LinkUploadCreateFmt, "<a rel='nofollow' class='createlinktext' href='\$LinkUpload'>\$LinkText</a><a rel='nofollow' class='createlink' href='\$LinkUpload'> Δ</a>");
|
||||
SDVA($ActionTitleFmt, array('upload' => '| $[Attach]'));
|
||||
|
||||
SDV($PageUploadFmt,array("
|
||||
<div id='wikiupload'>
|
||||
<h2 class='wikiaction'>$[Attachments for] {\$FullName}</h2>
|
||||
<h3>\$UploadResult</h3>
|
||||
<form enctype='multipart/form-data' action='{\$PageUrl}' method='post'>
|
||||
<input type='hidden' name='n' value='{\$FullName}' />
|
||||
<input type='hidden' name='action' value='postupload' />
|
||||
<table border='0'>
|
||||
<tr><td align='right'>$[File to upload:]</td><td><input
|
||||
name='uploadfile' type='file' /></td></tr>
|
||||
<tr><td align='right'>$[Name attachment as:]</td>
|
||||
<td><input type='text' name='upname' value='\$UploadName' /><input
|
||||
type='submit' value=' $[Upload] ' /><br />
|
||||
</td></tr></table></form></div>",
|
||||
'wiki:$[{$SiteGroup}/UploadQuickReference]'));
|
||||
XLSDV('en',array(
|
||||
'ULsuccess' => 'successfully uploaded',
|
||||
'ULbadname' => 'invalid attachment name',
|
||||
'ULbadtype' => '\'$upext\' is not an allowed file extension',
|
||||
'ULtoobig' => 'file is larger than maximum allowed by webserver',
|
||||
'ULtoobigext' => 'file is larger than allowed maximum of $upmax
|
||||
bytes for \'$upext\' files',
|
||||
'ULpartial' => 'incomplete file received',
|
||||
'ULnofile' => 'no file uploaded',
|
||||
'ULexists' => 'file with that name already exists',
|
||||
'ULpquota' => 'group quota exceeded',
|
||||
'ULtquota' => 'upload quota exceeded'));
|
||||
SDV($PageAttributes['passwdupload'],'$[Set new upload password:]');
|
||||
SDV($DefaultPasswords['upload'],'*');
|
||||
SDV($AuthCascade['upload'], 'read');
|
||||
SDV($FmtPV['$PasswdUpload'], 'PasswdVar($pn, "upload")');
|
||||
|
||||
Markup_e('attachlist', 'directives',
|
||||
'/\\(:attachlist\\s*(.*?):\\)/i',
|
||||
"Keep('<ul>'.FmtUploadList('$pagename',\$m[1]).'</ul>')");
|
||||
SDV($GUIButtons['attach'], array(220, 'Attach:', '', '$[file.ext]',
|
||||
'$GUIButtonDirUrlFmt/attach.gif"$[Attach file]"'));
|
||||
SDV($LinkFunctions['Attach:'], 'LinkUpload');
|
||||
SDV($IMap['Attach:'], '$1');
|
||||
SDVA($HandleActions, array('upload' => 'HandleUpload',
|
||||
'postupload' => 'HandlePostUpload',
|
||||
'download' => 'HandleDownload'));
|
||||
SDVA($HandleAuth, array('upload' => 'upload',
|
||||
'download' => 'read'));
|
||||
SDV($HandleAuth['postupload'], $HandleAuth['upload']);
|
||||
SDV($UploadVerifyFunction, 'UploadVerifyBasic');
|
||||
|
||||
function MakeUploadName($pagename,$x) {
|
||||
global $UploadNameChars, $MakeUploadNamePatterns;
|
||||
SDV($UploadNameChars, "-\\w. ");
|
||||
SDV($MakeUploadNamePatterns, array(
|
||||
"/[^$UploadNameChars]/" => '',
|
||||
'/\\.[^.]*$/' => PCCF('return strtolower($m[0]);'),
|
||||
'/^[^[:alnum:]_]+/' => '',
|
||||
'/[^[:alnum:]_]+$/' => ''));
|
||||
return PPRA($MakeUploadNamePatterns, $x);
|
||||
}
|
||||
|
||||
function LinkUpload($pagename, $imap, $path, $alt, $txt, $fmt=NULL) {
|
||||
global $FmtV, $UploadFileFmt, $LinkUploadCreateFmt,
|
||||
$UploadUrlFmt, $UploadPrefixFmt, $EnableDirectDownload;
|
||||
if (preg_match('!^(.*)/([^/]+)$!', $path, $match)) {
|
||||
$pagename = MakePageName($pagename, $match[1]);
|
||||
$path = $match[2];
|
||||
}
|
||||
$upname = MakeUploadName($pagename, $path);
|
||||
$encname = rawurlencode($upname);
|
||||
$filepath = FmtPageName("$UploadFileFmt/$upname", $pagename);
|
||||
$FmtV['$LinkUpload'] =
|
||||
FmtPageName("\$PageUrl?action=upload&upname=$encname", $pagename);
|
||||
$FmtV['$LinkText'] = $txt;
|
||||
if (!file_exists($filepath))
|
||||
return FmtPageName($LinkUploadCreateFmt, $pagename);
|
||||
$path = PUE(FmtPageName(IsEnabled($EnableDirectDownload, 1)
|
||||
? "$UploadUrlFmt$UploadPrefixFmt/$encname"
|
||||
: "{\$PageUrl}?action=download&upname=$encname",
|
||||
$pagename));
|
||||
return LinkIMap($pagename, $imap, $path, $alt, $txt, $fmt);
|
||||
}
|
||||
|
||||
# Authenticate group downloads with the group password
|
||||
function UploadAuth($pagename, $auth, $cache=0){
|
||||
global $GroupAttributesFmt, $EnableUploadGroupAuth;
|
||||
if (IsEnabled($EnableUploadGroupAuth,0)){
|
||||
SDV($GroupAttributesFmt,'$Group/GroupAttributes');
|
||||
$pn_upload = FmtPageName($GroupAttributesFmt, $pagename);
|
||||
} else $pn_upload = $pagename;
|
||||
$page = RetrieveAuthPage($pn_upload, $auth, true, READPAGE_CURRENT);
|
||||
if(!$page) Abort("?No '$auth' permissions for $pagename");
|
||||
if($cache) PCache($pn_upload,$page);
|
||||
return true;
|
||||
}
|
||||
|
||||
function HandleUpload($pagename, $auth = 'upload') {
|
||||
global $FmtV,$UploadExtMax, $EnableReadOnly,
|
||||
$HandleUploadFmt,$PageStartFmt,$PageEndFmt,$PageUploadFmt;
|
||||
UploadAuth($pagename, $auth, 1);
|
||||
$FmtV['$UploadName'] = MakeUploadName($pagename,@$_REQUEST['upname']);
|
||||
$upresult = PHSC(@$_REQUEST['upresult']);
|
||||
$uprname = PHSC(@$_REQUEST['uprname']);
|
||||
$FmtV['$upext'] = PHSC(@$_REQUEST['upext']);
|
||||
$FmtV['$upmax'] = PHSC(@$_REQUEST['upmax']);
|
||||
$FmtV['$UploadResult'] = ($upresult) ?
|
||||
FmtPageName("<i>$uprname</i>: $[UL$upresult]",$pagename) :
|
||||
(@$EnableReadOnly ? XL('Cannot modify site -- $EnableReadOnly is set'): '');
|
||||
SDV($HandleUploadFmt,array(&$PageStartFmt,&$PageUploadFmt,&$PageEndFmt));
|
||||
PrintFmt($pagename,$HandleUploadFmt);
|
||||
}
|
||||
|
||||
function HandleDownload($pagename, $auth = 'read') {
|
||||
global $UploadFileFmt, $UploadExts, $DownloadDisposition, $EnableIMSCaching;
|
||||
SDV($DownloadDisposition, "inline");
|
||||
UploadAuth($pagename, $auth);
|
||||
$upname = MakeUploadName($pagename, @$_REQUEST['upname']);
|
||||
$filepath = FmtPageName("$UploadFileFmt/$upname", $pagename);
|
||||
if (!$upname || !file_exists($filepath)) {
|
||||
header("HTTP/1.0 404 Not Found");
|
||||
Abort("?requested file not found");
|
||||
exit();
|
||||
}
|
||||
if (IsEnabled($EnableIMSCaching, 0)) {
|
||||
header('Cache-Control: private');
|
||||
header('Expires: ');
|
||||
$filelastmod = gmdate('D, d M Y H:i:s \G\M\T', filemtime($filepath));
|
||||
if (@$_SERVER['HTTP_IF_MODIFIED_SINCE'] == $filelastmod)
|
||||
{ header("HTTP/1.0 304 Not Modified"); exit(); }
|
||||
header("Last-Modified: $filelastmod");
|
||||
}
|
||||
preg_match('/\\.([^.]+)$/',$filepath,$match);
|
||||
if ($UploadExts[@$match[1]])
|
||||
header("Content-Type: {$UploadExts[@$match[1]]}");
|
||||
header("Content-Length: ".filesize($filepath));
|
||||
header("Content-disposition: $DownloadDisposition; filename=\"$upname\"");
|
||||
$fp = fopen($filepath, "rb");
|
||||
if ($fp) {
|
||||
while (!feof($fp)) echo fread($fp, 4096);
|
||||
flush();
|
||||
fclose($fp);
|
||||
}
|
||||
exit();
|
||||
}
|
||||
|
||||
function HandlePostUpload($pagename, $auth = 'upload') {
|
||||
global $UploadVerifyFunction, $UploadFileFmt, $LastModFile,
|
||||
$EnableUploadVersions, $Now, $RecentUploadsFmt, $FmtV,
|
||||
$NotifyItemUploadFmt, $NotifyItemFmt, $IsUploadPosted,
|
||||
$UploadRedirectFunction, $UploadPermAdd, $UploadPermSet,
|
||||
$EnableReadOnly;
|
||||
|
||||
if(IsEnabled($EnableReadOnly, 0))
|
||||
Abort('Cannot modify site -- $EnableReadOnly is set', 'readonly');
|
||||
|
||||
UploadAuth($pagename, $auth);
|
||||
$uploadfile = $_FILES['uploadfile'];
|
||||
$upname = $_REQUEST['upname'];
|
||||
if ($upname=='') $upname=$uploadfile['name'];
|
||||
$upname = MakeUploadName($pagename,$upname);
|
||||
if (!function_exists($UploadVerifyFunction))
|
||||
Abort('?no UploadVerifyFunction available');
|
||||
$filepath = FmtPageName("$UploadFileFmt/$upname",$pagename);
|
||||
$result = $UploadVerifyFunction($pagename,$uploadfile,$filepath);
|
||||
if ($result=='') {
|
||||
$filedir = preg_replace('#/[^/]*$#','',$filepath);
|
||||
mkdirp($filedir);
|
||||
if (IsEnabled($EnableUploadVersions, 0))
|
||||
@rename($filepath, "$filepath,$Now");
|
||||
if (!move_uploaded_file($uploadfile['tmp_name'],$filepath))
|
||||
{ Abort("?cannot move uploaded file to $filepath"); return; }
|
||||
fixperms($filepath, $UploadPermAdd, $UploadPermSet);
|
||||
if ($LastModFile) { touch($LastModFile); fixperms($LastModFile); }
|
||||
$result = "upresult=success";
|
||||
$FmtV['$upname'] = $upname;
|
||||
$FmtV['$upsize'] = $uploadfile['size'];
|
||||
if (IsEnabled($RecentUploadsFmt, 0)) {
|
||||
PostRecentChanges($pagename, '', '', $RecentUploadsFmt);
|
||||
}
|
||||
if (IsEnabled($NotifyItemUploadFmt, 0) && function_exists('NotifyUpdate')) {
|
||||
$NotifyItemFmt = $NotifyItemUploadFmt;
|
||||
$IsUploadPosted = 1;
|
||||
register_shutdown_function('NotifyUpdate', $pagename, getcwd());
|
||||
}
|
||||
}
|
||||
SDV($UploadRedirectFunction, 'Redirect');
|
||||
$UploadRedirectFunction($pagename,"{\$PageUrl}?action=upload&uprname=$upname&$result");
|
||||
}
|
||||
|
||||
function UploadVerifyBasic($pagename,$uploadfile,$filepath) {
|
||||
global $EnableUploadOverwrite,$UploadExtSize,$UploadPrefixQuota,
|
||||
$UploadDirQuota,$UploadDir, $UploadBlacklist;
|
||||
if (count($UploadBlacklist)) {
|
||||
$tmp = explode("/", $filepath);
|
||||
$upname = strtolower(end($tmp));
|
||||
foreach($UploadBlacklist as $needle) {
|
||||
if (strpos($upname, $needle)!==false) return 'upresult=badname';
|
||||
}
|
||||
}
|
||||
if (!$EnableUploadOverwrite && file_exists($filepath))
|
||||
return 'upresult=exists';
|
||||
preg_match('/\\.([^.\\/]+)$/',$filepath,$match); $ext=@$match[1];
|
||||
$maxsize = $UploadExtSize[$ext];
|
||||
if ($maxsize<=0) return "upresult=badtype&upext=$ext";
|
||||
if ($uploadfile['size']>$maxsize)
|
||||
return "upresult=toobigext&upext=$ext&upmax=$maxsize";
|
||||
switch (@$uploadfile['error']) {
|
||||
case 1: return 'upresult=toobig';
|
||||
case 2: return 'upresult=toobig';
|
||||
case 3: return 'upresult=partial';
|
||||
case 4: return 'upresult=nofile';
|
||||
}
|
||||
if (!is_uploaded_file($uploadfile['tmp_name'])) return 'upresult=nofile';
|
||||
$filedir = preg_replace('#/[^/]*$#','',$filepath);
|
||||
if ($UploadPrefixQuota &&
|
||||
(dirsize($filedir)-@filesize($filepath)+$uploadfile['size']) >
|
||||
$UploadPrefixQuota) return 'upresult=pquota';
|
||||
if ($UploadDirQuota &&
|
||||
(dirsize($UploadDir)-@filesize($filepath)+$uploadfile['size']) >
|
||||
$UploadDirQuota) return 'upresult=tquota';
|
||||
return '';
|
||||
}
|
||||
|
||||
function dirsize($dir) {
|
||||
$size = 0;
|
||||
$dirp = @opendir($dir);
|
||||
if (!$dirp) return 0;
|
||||
while (($file=readdir($dirp)) !== false) {
|
||||
if ($file[0]=='.') continue;
|
||||
if (is_dir("$dir/$file")) $size+=dirsize("$dir/$file");
|
||||
else $size+=filesize("$dir/$file");
|
||||
}
|
||||
closedir($dirp);
|
||||
return $size;
|
||||
}
|
||||
|
||||
function FmtUploadList($pagename, $args) {
|
||||
global $UploadDir, $UploadPrefixFmt, $UploadUrlFmt, $EnableUploadOverwrite,
|
||||
$TimeFmt, $EnableDirectDownload, $IMapLinkFmt, $UrlLinkFmt, $FmtV;
|
||||
|
||||
$opt = ParseArgs($args);
|
||||
if (@$opt[''][0]) $pagename = MakePageName($pagename, $opt[''][0]);
|
||||
if (@$opt['ext'])
|
||||
$matchext = '/\\.('
|
||||
. implode('|', preg_split('/\\W+/', $opt['ext'], -1, PREG_SPLIT_NO_EMPTY))
|
||||
. ')$/i';
|
||||
|
||||
$uploaddir = FmtPageName("$UploadDir$UploadPrefixFmt", $pagename);
|
||||
$uploadurl = FmtPageName(IsEnabled($EnableDirectDownload, 1)
|
||||
? "$UploadUrlFmt$UploadPrefixFmt/"
|
||||
: "\$PageUrl?action=download&upname=",
|
||||
$pagename);
|
||||
|
||||
$dirp = @opendir($uploaddir);
|
||||
if (!$dirp) return '';
|
||||
$filelist = array();
|
||||
while (($file=readdir($dirp)) !== false) {
|
||||
if ($file{0} == '.') continue;
|
||||
if (@$matchext && !preg_match(@$matchext, $file)) continue;
|
||||
$filelist[$file] = rawurlencode($file);
|
||||
}
|
||||
closedir($dirp);
|
||||
$out = array();
|
||||
natcasesort($filelist);
|
||||
$overwrite = '';
|
||||
$fmt = IsEnabled($IMapLinkFmt['Attach:'], $UrlLinkFmt);
|
||||
foreach($filelist as $file=>$encfile) {
|
||||
$FmtV['$LinkUrl'] = PUE("$uploadurl$encfile");
|
||||
$FmtV['$LinkText'] = $file;
|
||||
$FmtV['$LinkUpload'] =
|
||||
FmtPageName("\$PageUrl?action=upload&upname=$encfile", $pagename);
|
||||
$stat = stat("$uploaddir/$file");
|
||||
if ($EnableUploadOverwrite)
|
||||
$overwrite = FmtPageName("<a rel='nofollow' class='createlink'
|
||||
href='\$LinkUpload'> Δ</a>",
|
||||
$pagename);
|
||||
$lnk = FmtPageName($fmt, $pagename);
|
||||
$out[] = "<li> $lnk$overwrite ... ".
|
||||
number_format($stat['size']) . " bytes ... " .
|
||||
strftime($TimeFmt, $stat['mtime']) . "</li>";
|
||||
}
|
||||
return implode("\n",$out);
|
||||
}
|
||||
|
||||
# this adds (:if [!]attachments:) to the markup
|
||||
$Conditions['attachments'] = "AttachExist(\$pagename)";
|
||||
function AttachExist($pagename) {
|
||||
global $UploadDir, $UploadPrefixFmt;
|
||||
$uploaddir = FmtPageName("$UploadDir$UploadPrefixFmt", $pagename);
|
||||
$count = 0;
|
||||
$dirp = @opendir($uploaddir);
|
||||
if ($dirp) {
|
||||
while (($file = readdir($dirp)) !== false)
|
||||
if ($file{0} != '.') $count++;
|
||||
closedir($dirp);
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
126
wiki/scripts/urlapprove.php
Executable file
126
wiki/scripts/urlapprove.php
Executable file
@@ -0,0 +1,126 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2013 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script provides a URL-approval capability. To enable this
|
||||
script, add the following line to a configuration file:
|
||||
|
||||
include_once('scripts/urlapprove.php');
|
||||
|
||||
The URL prefixes to be allowed are stored as patterns in
|
||||
$WhiteUrlPatterns. This array can be loaded from config.php, or
|
||||
from the wiki pages given by the $ApprovedUrlPagesFmt[] array.
|
||||
Any http: or https: URL that isn't in $WhiteUrlPatterns is rendered
|
||||
using $UnapprovedLinkFmt.
|
||||
|
||||
The script also provides ?action=approveurls and ?action=approvesites,
|
||||
which scan the current page for any new URLs to be automatically added
|
||||
the first page of $UrlApprovalPagesFmt.
|
||||
|
||||
Finally, the script will block any post containing more than
|
||||
$UnapprovedLinkCountMax unapproved urls in it. By default this
|
||||
is set to a very large number, leaving the posting of unapproved
|
||||
urls wide open, but by setting $UnapprovedLinkCountMax to a smaller
|
||||
number you can limit the number of unapproved urls that make it into
|
||||
a page. (Wikispammers seem to like to post long lists of urls, while
|
||||
more "normal" authors tend to only post a few.)
|
||||
*/
|
||||
|
||||
$LinkFunctions['http:'] = 'LinkHTTP';
|
||||
$LinkFunctions['https:'] = 'LinkHTTP';
|
||||
SDV($ApprovedUrlPagesFmt, array('$SiteAdminGroup.ApprovedUrls'));
|
||||
SDV($UnapprovedLinkFmt,
|
||||
"\$LinkText<a class='apprlink' href='{\$PageUrl}?action=approvesites'>$[(approve sites)]</a>");
|
||||
$HTMLStylesFmt['urlapprove'] = '.apprlink { font-size:smaller; }';
|
||||
SDV($ApproveUrlPattern,
|
||||
"\\bhttps?:[^\\s$UrlExcludeChars]*[^\\s.,?!$UrlExcludeChars]");
|
||||
$WhiteUrlPatterns = (array)$WhiteUrlPatterns;
|
||||
SDV($HandleActions['approveurls'], 'HandleApprove');
|
||||
SDV($HandleAuth['approveurls'], 'edit');
|
||||
SDV($HandleActions['approvesites'], 'HandleApprove');
|
||||
SDV($HandleAuth['approvesites'], 'edit');
|
||||
SDV($UnapprovedLinkCountMax, 1000000);
|
||||
array_splice($EditFunctions, array_search('PostPage', $EditFunctions),
|
||||
0, 'BlockUnapprovedPosts');
|
||||
|
||||
function LinkHTTP($pagename,$imap,$path,$alt,$txt,$fmt=NULL) {
|
||||
global $EnableUrlApprovalRequired, $IMap, $WhiteUrlPatterns, $FmtV,
|
||||
$UnapprovedLink, $UnapprovedLinkCount, $UnapprovedLinkFmt;
|
||||
if (!IsEnabled($EnableUrlApprovalRequired,1))
|
||||
return LinkIMap($pagename,$imap,$path,$alt,$txt,$fmt);
|
||||
static $havereadpages;
|
||||
if (!$havereadpages) { ReadApprovedUrls($pagename); $havereadpages=true; }
|
||||
$p = str_replace(' ','%20',$path);
|
||||
$url = str_replace('$1',$p,$IMap[$imap]);
|
||||
if (!isset($UnapprovedLink)) $UnapprovedLink = array();
|
||||
foreach((array)$WhiteUrlPatterns as $pat) {
|
||||
if (preg_match("!^$pat(/|$)!i",$url))
|
||||
return LinkIMap($pagename,$imap,$path,$alt,$txt,$fmt);
|
||||
}
|
||||
$FmtV['$LinkUrl'] = PUE(str_replace('$1',$path,$IMap[$imap]));
|
||||
$FmtV['$LinkText'] = $txt;
|
||||
$FmtV['$LinkAlt'] = str_replace(array('"',"'"),array('"','''),$alt);
|
||||
$UnapprovedLink[] = $url;
|
||||
@$UnapprovedLinkCount++;
|
||||
return FmtPageName($UnapprovedLinkFmt,$pagename);
|
||||
}
|
||||
|
||||
function ReadApprovedUrls($pagename) {
|
||||
global $ApprovedUrlPagesFmt,$ApproveUrlPattern,$WhiteUrlPatterns;
|
||||
foreach((array)$ApprovedUrlPagesFmt as $p) {
|
||||
$pn = FmtPageName($p, $pagename);
|
||||
StopWatch("ReadApprovedUrls $pn begin");
|
||||
$apage = ReadPage($pn, READPAGE_CURRENT);
|
||||
preg_match_all("/$ApproveUrlPattern/",@$apage['text'],$match);
|
||||
foreach($match[0] as $a)
|
||||
$WhiteUrlPatterns[] = preg_quote($a,'!');
|
||||
StopWatch("ReadApprovedUrls $pn end");
|
||||
}
|
||||
}
|
||||
|
||||
function HandleApprove($pagename, $auth='edit') {
|
||||
global $ApproveUrlPattern,$WhiteUrlPatterns,$ApprovedUrlPagesFmt,$action;
|
||||
Lock(2);
|
||||
$page = ReadPage($pagename);
|
||||
$text = preg_replace('/[()]/','',$page['text']);
|
||||
preg_match_all("/$ApproveUrlPattern/",$text,$match);
|
||||
ReadApprovedUrls($pagename);
|
||||
$addpat = array();
|
||||
foreach($match[0] as $a) {
|
||||
if ($action=='approvesites')
|
||||
$a=preg_replace("!^([^:]+://[^/]+).*$!",'$1',$a);
|
||||
$addpat[] = $a;
|
||||
}
|
||||
if (count($addpat)>0) {
|
||||
$aname = FmtPageName($ApprovedUrlPagesFmt[0],$pagename);
|
||||
$apage = RetrieveAuthPage($aname, $auth);
|
||||
if (!$apage) Abort("?cannot edit $aname");
|
||||
$new = $apage;
|
||||
if (substr($new['text'],-1,1)!="\n") $new['text'].="\n";
|
||||
foreach($addpat as $a) {
|
||||
foreach((array)$WhiteUrlPatterns as $pat)
|
||||
if (preg_match("!^$pat(/|$)!i",$a)) continue 2;
|
||||
$urlp = preg_quote($a,'!');
|
||||
$WhiteUrlPatterns[] = $urlp;
|
||||
$new['text'].=" $a\n";
|
||||
}
|
||||
$_POST['post'] = 'y';
|
||||
PostPage($aname,$apage,$new);
|
||||
}
|
||||
Redirect($pagename);
|
||||
}
|
||||
|
||||
function BlockUnapprovedPosts($pagename, &$page, &$new) {
|
||||
global $EnableUrlApprovalRequired, $UnapprovedLinkCount,
|
||||
$UnapprovedLinkCountMax, $EnablePost, $MessagesFmt, $BlockMessageFmt;
|
||||
if (!IsEnabled($EnableUrlApprovalRequired, 1)) return;
|
||||
if ($UnapprovedLinkCount <= $UnapprovedLinkCountMax) return;
|
||||
if ($page['=auth']['admin']) return;
|
||||
$EnablePost = 0;
|
||||
$MessagesFmt[] = $BlockMessageFmt;
|
||||
$MessagesFmt[] = XL('Too many unapproved external links.');
|
||||
}
|
||||
|
||||
78
wiki/scripts/vardoc.php
Executable file
78
wiki/scripts/vardoc.php
Executable file
@@ -0,0 +1,78 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2002-2013 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script provides special handling for WikiWords that are
|
||||
preceded by a $, treating them as PmWiki variables to be looked up
|
||||
in the variable documentation pages if such documentation exists.
|
||||
The $VarPagesFmt variable contains a list of pages to be searched
|
||||
to build an index of the variable documentation. This index is
|
||||
generated only once per browse request, and then only when needed.
|
||||
*/
|
||||
|
||||
SDV($VarPagesFmt,array('$[PmWiki.Variables]'));
|
||||
Markup_e('varlink','<wikilink',"/\\$($WikiWordPattern)\\b/",
|
||||
"Keep(VarLink(\$pagename,\$m[1],'$'.\$m[1]))");
|
||||
Markup('vardef','<links',"/^:\\$($WikiWordPattern):/",
|
||||
':[[#$1]]$$1:');
|
||||
Markup_e('varindex', 'directives',
|
||||
'/\\(:varindex:\\)/i',
|
||||
"Keep(VarIndexList(\$pagename))");
|
||||
|
||||
$HTMLStylesFmt['vardoc'] = "a.varlink { text-decoration:none; }\n";
|
||||
|
||||
function VarLink($pagename,$tgt,$txt) {
|
||||
global $VarIndex,$FmtV,$VarLinkMissingFmt,$VarLinkExistsFmt;
|
||||
SDV($VarLinkMissingFmt,'$LinkText');
|
||||
SDV($VarLinkExistsFmt,"<a class='varlink' href='\$LinkUrl'><code class='varlink'>\$LinkText</code></a>");
|
||||
VarIndexLoad($pagename);
|
||||
$FmtV['$LinkText'] = str_replace('$', '$', $txt);
|
||||
$FmtV['$LinkUrl'] = @$VarIndex[$tgt]['url'];
|
||||
if (@!$VarIndex[$tgt]['url'])
|
||||
return FmtPageName($VarLinkMissingFmt,$pagename);
|
||||
return FmtPageName($VarLinkExistsFmt,$pagename);
|
||||
}
|
||||
|
||||
function VarIndexLoad($pagename) {
|
||||
global $VarPagesFmt,$VarIndex,$WikiWordPattern;
|
||||
static $loaded;
|
||||
$VarIndex = (array)@$VarIndex;
|
||||
if ($loaded) return;
|
||||
foreach($VarPagesFmt as $vf) {
|
||||
$v = FmtPageName($vf, $pagename);
|
||||
if (@$loaded[$v]) continue;
|
||||
$vlist = array($v);
|
||||
$t = ReadTrail($pagename,$v);
|
||||
if ($t)
|
||||
for($i=0;$i<count($t);$i++)
|
||||
if (@!$loaded[$t[$i]['pagename']]) $vlist[]=$t[$i]['pagename'];
|
||||
foreach($vlist as $vname) {
|
||||
$vpage = ReadPage($vname, READPAGE_CURRENT); @$loaded[$vname]++;
|
||||
if (!$vpage) continue;
|
||||
if (!preg_match_all("/\n:\\$([[:upper:]]\\w+):/",@$vpage['text'],$match))
|
||||
continue;
|
||||
foreach($match[1] as $n) {
|
||||
$VarIndex[$n]['pagename'] = $vname;
|
||||
$VarIndex[$n]['url'] = FmtPageName("{\$PageUrl}#$n",$vname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# VarIndexList() generates a table of all indexed variables.
|
||||
function VarIndexList($pagename) {
|
||||
global $VarIndex;
|
||||
if (!isset($VarIndex)) VarIndexLoad($pagename);
|
||||
ksort($VarIndex);
|
||||
$out = "<table><tr><th>Variable</th><th>Documented in</th></tr>\n";
|
||||
foreach($VarIndex as $v=>$a)
|
||||
$out .= FmtPageName("<tr><td><a class='varlink'
|
||||
href='{$a['url']}'><code>$$v</code></a></td><td><a
|
||||
href='{\$PageUrl}'>{\$Name}</a></td></tr>\n",$a['pagename']);
|
||||
$out .= "</table>";
|
||||
return $out;
|
||||
}
|
||||
|
||||
1
wiki/scripts/version.php
Executable file
1
wiki/scripts/version.php
Executable file
@@ -0,0 +1 @@
|
||||
<?php $Version="pmwiki-2.2.75"; $VersionNum=2002075;
|
||||
193
wiki/scripts/wikistyles.php
Executable file
193
wiki/scripts/wikistyles.php
Executable file
@@ -0,0 +1,193 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2015 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
*/
|
||||
|
||||
SDV($WikiStylePattern,'%%|%[A-Za-z][-,=:#\\w\\s\'"().]*%');
|
||||
|
||||
## %% markup
|
||||
Markup('%%','style','%','return ApplyStyles($x);');
|
||||
|
||||
## %define=...% markup on a line by itself
|
||||
Markup_e('%define=', '>split',
|
||||
"/^(?=%define=)((?:$WikiStylePattern)\\s*)+$/",
|
||||
"PZZ(ApplyStyles(\$m[0]))");
|
||||
|
||||
## restore links before applying styles
|
||||
Markup_e('restorelinks','<%%',"/$KeepToken(\\d+L)$KeepToken/",
|
||||
'$GLOBALS[\'KPV\'][$m[1]]');
|
||||
|
||||
# define PmWiki's standard/default wikistyles
|
||||
if (IsEnabled($EnableStdWikiStyles,1)) {
|
||||
## standard colors
|
||||
foreach(array('black','white','red','yellow','blue','gray',
|
||||
'silver','maroon','green','navy','purple') as $c)
|
||||
SDV($WikiStyle[$c]['color'],$c);
|
||||
## %newwin% style opens links in a new window
|
||||
SDV($WikiStyle['newwin']['target'],'_blank');
|
||||
## %comment% style turns markup into a comment via display:none css
|
||||
SDV($WikiStyle['comment']['display'],'none');
|
||||
## display, margin, padding, and border css properties
|
||||
$WikiStyleCSS[] =
|
||||
'float|clear|display|(margin|padding|border)(-(left|right|top|bottom))?';
|
||||
$WikiStyleCSS[] = 'white-space';
|
||||
$WikiStyleCSS[] = '((min|max)-)?(width|height)';
|
||||
## list-styles
|
||||
$WikiStyleCSS[] = 'list-style';
|
||||
foreach(array('decimal'=>'decimal', 'roman'=>'lower-roman',
|
||||
'ROMAN'=>'upper-roman', 'alpha'=>'lower-alpha', 'ALPHA'=>'upper-alpha')
|
||||
as $k=>$v)
|
||||
SDV($WikiStyle[$k],array('apply'=>'list','list-style'=>$v));
|
||||
## apply ranges
|
||||
SDVA($WikiStyleApply,array(
|
||||
'item' => 'li|dt',
|
||||
'list' => 'ul|ol|dl',
|
||||
'div' => 'div',
|
||||
'article' => 'article',
|
||||
'section' => 'section',
|
||||
'nav' => 'nav',
|
||||
'aside' => 'aside',
|
||||
'header' => 'header',
|
||||
'footer' => 'footer',
|
||||
'address' => 'address',
|
||||
'pre' => 'pre',
|
||||
'img' => 'img',
|
||||
'block' => 'p(?!\\s+class=)|div|ul|ol|dl|li|dt|pre|h[1-6]|article|section|nav|aside|address|header|footer',
|
||||
'p' => 'p(?!\\s+class=)'));
|
||||
foreach(array('item', 'list', 'block', 'p', 'div') as $c)
|
||||
SDV($WikiStyle[$c],array('apply'=>$c));
|
||||
## block justifications
|
||||
foreach(array('left','right','center','justify') as $c)
|
||||
SDV($WikiStyle[$c],array('apply'=>'block','text-align'=>$c));
|
||||
## frames, floating frames, and floats
|
||||
SDV($HTMLStylesFmt['wikistyles'], "
|
||||
.frame
|
||||
{ border:1px solid #cccccc; padding:4px; background-color:#f9f9f9; }
|
||||
.lfloat { float:left; margin-right:0.5em; }
|
||||
.rfloat { float:right; margin-left:0.5em; }\n");
|
||||
SDV($WikiStyle['thumb'], array('width' => '100px'));
|
||||
SDV($WikiStyle['frame'], array('class' => 'frame'));
|
||||
SDV($WikiStyle['lframe'], array('class' => 'frame lfloat'));
|
||||
SDV($WikiStyle['rframe'], array('class' => 'frame rfloat'));
|
||||
SDV($WikiStyle['cframe'], array(
|
||||
'class' => 'frame', 'margin-left' => 'auto', 'margin-right' => 'auto',
|
||||
'width' => '200px', 'apply' => 'block', 'text-align' => 'center'));
|
||||
## preformatted text sections
|
||||
SDV($WikiStyle['pre'], array('apply' => 'block', 'white-space' => 'pre'));
|
||||
SDV($WikiStyle['sidehead'], array('apply' => 'block', 'class' => 'sidehead'));
|
||||
}
|
||||
|
||||
SDVA($WikiStyleAttr,array(
|
||||
'vspace' => 'img',
|
||||
'hspace' => 'img',
|
||||
'align' => 'img',
|
||||
'value' => 'li',
|
||||
'target' => 'a',
|
||||
'accesskey' => 'a',
|
||||
'rel' => 'a'));
|
||||
|
||||
SDVA($WikiStyleRepl,array(
|
||||
'/^%(.*)%$/' => '$1',
|
||||
'/\\bbgcolor([:=])/' => 'background-color$1',
|
||||
'/\\b(\d+)pct\\b/' => '$1%',
|
||||
));
|
||||
|
||||
$WikiStyleCSS[] = 'color|background-color';
|
||||
$WikiStyleCSS[] = 'text-align|text-decoration';
|
||||
$WikiStyleCSS[] = 'font-size|font-family|font-weight|font-style';
|
||||
|
||||
SDV($imgTag, '(?:img|object|embed)'); SDV($aTag, 'a'); SDV($spanTag, 'span');
|
||||
|
||||
function ApplyStyles($x) {
|
||||
global $UrlExcludeChars, $WikiStylePattern, $WikiStyleRepl, $WikiStyle,
|
||||
$WikiStyleAttr, $WikiStyleCSS, $WikiStyleApply, $BlockPattern,
|
||||
$WikiStyleTag, $imgTag, $aTag, $spanTag, $WikiStyleAttrPrefix;
|
||||
$wt = @$WikiStyleTag; $ns = $WikiStyleAttrPrefix; $ws = '';
|
||||
$x = PPRE("/\\b(href|src)=(['\"]?)[^$UrlExcludeChars]+\\2/",
|
||||
"Keep(\$m[0])", $x);
|
||||
$x = PPRE("/\\bhttps?:[^$UrlExcludeChars]+/", "Keep(\$m[0])", $x);
|
||||
$parts = preg_split("/($WikiStylePattern)/",$x,-1,PREG_SPLIT_DELIM_CAPTURE);
|
||||
$parts[] = NULL;
|
||||
$out = '';
|
||||
$style = array();
|
||||
$wikicsspat = '/^('.implode('|',(array)$WikiStyleCSS).')$/';
|
||||
while ($parts) {
|
||||
$p = array_shift($parts);
|
||||
if (preg_match("/^$WikiStylePattern\$/",$p)) {
|
||||
$WikiStyle['curr']=$style; $style=array();
|
||||
foreach((array)$WikiStyleRepl as $pat=>$rep)
|
||||
$p=preg_replace($pat,$rep,$p);
|
||||
preg_match_all(
|
||||
'/\\b([a-zA-Z][-\\w]*)([:=]([-#,\\w.()%]+|([\'"]).*?\\4))?/',
|
||||
$p, $match, PREG_SET_ORDER);
|
||||
while ($match) {
|
||||
$m = array_shift($match);
|
||||
if (@$m[2]) $style[$m[1]]=preg_replace('/^([\'"])(.*?)\\1$/','$2',$m[3]);
|
||||
else if (!isset($WikiStyle[$m[1]])) @$style['class'] .= ' ' . $m[1];
|
||||
else {
|
||||
$c = @$style['class'];
|
||||
$style=array_merge($style,(array)$WikiStyle[$m[1]]);
|
||||
if ($c && !preg_match("/(^| )$c( |$)/", $style['class']) )
|
||||
$style['class'] = $c . ' ' . $style['class'];
|
||||
}
|
||||
}
|
||||
if (@$style['define']) {
|
||||
$d = $style['define']; unset($style['define']);
|
||||
$WikiStyle[$d] = $style;
|
||||
}
|
||||
if (@$WikiStyleApply[$style['apply']]) {
|
||||
$apply[$style['apply']] =
|
||||
array_merge((array)@$apply[$style['apply']],$style);
|
||||
$style=array();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (is_null($p))
|
||||
{ $alist=@$apply; unset($alist['']); $p=$out; $out=''; }
|
||||
elseif ($p=='') continue;
|
||||
else { $alist=array(''=>$style); }
|
||||
foreach((array)$alist as $a=>$s) {
|
||||
$spanattr = ''; $stylev = array(); $id = '';
|
||||
foreach((array)$s as $k=>$v) {
|
||||
$v = trim($v);
|
||||
if ($wt) $ws = str_replace('$1', "$ns$k='$v'", $wt);
|
||||
if ($k == 'class' && $v) $spanattr = "{$ns}class='$v'";
|
||||
elseif ($k=='id') $id = preg_replace('/[^-A-Za-z0-9:_.]+/', '_', $v);
|
||||
elseif (($k=='width' || $k=='height') && !@$WikiStyleApply[$a]
|
||||
&& preg_match("/\\s*<$imgTag\\b/", $p))
|
||||
$p = preg_replace("/<($imgTag)\\b(?![^>]*\\s$k=)/",
|
||||
"$ws<$1 $ns$k='$v'", $p);
|
||||
elseif (@$WikiStyleAttr[$k])
|
||||
$p = preg_replace(
|
||||
"/<({$WikiStyleAttr[$k]}(?![^>]*\\s(?:$ns)?$k=))([^>]*)>/s",
|
||||
"$ws<$1 $ns$k='$v' $2>", $p);
|
||||
elseif (preg_match($wikicsspat,$k)) $stylev[]="$k: $v;";
|
||||
}
|
||||
if ($stylev) $spanattr .= " {$ns}style='".implode(' ',$stylev)."'";
|
||||
if ($id) $spanattr .= " {$ns}id='$id'";
|
||||
if ($spanattr) {
|
||||
if ($wt) $ws = str_replace('$1', $spanattr, $wt);
|
||||
if (!@$WikiStyleApply[$a]) {
|
||||
$p = preg_replace("!^(.*?)($|</?($BlockPattern))!s",
|
||||
"$ws<$spanTag $spanattr>$1</$spanTag>$2", $p, 1);
|
||||
}
|
||||
elseif (!preg_match('/^(\\s*<[^>]+>)*$/s',$p) ||
|
||||
preg_match("/<$imgTag\\b/", $p)) {
|
||||
$p = preg_replace("/<({$WikiStyleApply[$a]})\\b/",
|
||||
"$ws<$1 $spanattr", $p);
|
||||
}
|
||||
}
|
||||
if (@$s['color']) {
|
||||
$colorattr = "{$ns}style='color: {$s['color']}'";
|
||||
if ($wt) $ws = str_replace('$1', $colorattr, $wt);
|
||||
$p = preg_replace("/<$aTag\\b/", "$ws<$aTag $colorattr", $p);
|
||||
}
|
||||
}
|
||||
$out .= $p;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
69
wiki/scripts/wikiwords.php
Executable file
69
wiki/scripts/wikiwords.php
Executable file
@@ -0,0 +1,69 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2001-2013 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script adds WikiWord (CamelCase) processing to PmWiki.
|
||||
Originally WikiWords were part of the default configuration,
|
||||
but their usage has died out over time and so it's now optional.
|
||||
|
||||
To enable WikiWord links, simply add the following to
|
||||
a local customization file:
|
||||
|
||||
$EnableWikiWords = 1;
|
||||
|
||||
To have PmWiki recognize and process WikiWords but not link
|
||||
them (i.e., the default behavior in PmWiki 2.1), also add
|
||||
|
||||
$LinkWikiWords = 0;
|
||||
|
||||
If you want only the first occurrence of a WikiWord to be converted
|
||||
to a link, set $WikiWordCountMax=1.
|
||||
|
||||
$WikiWordCountMax = 1; # converts only first WikiWord
|
||||
$WikiWordCountMax = 0; # another way to disable WikiWord links
|
||||
|
||||
The $WikiWordCount array can be used to control the number of times
|
||||
a WikiWord is converted to a link. This is useful for disabling
|
||||
or limiting specific WikiWords.
|
||||
|
||||
$WikiWordCount['PhD'] = 0; # disables 'PhD'
|
||||
$WikiWordCount['PmWiki'] = 1; # convert only first 'PmWiki'
|
||||
$WikiWordCount['WikiWord'] = -1; # ignore $SpaceWikiWord setting
|
||||
|
||||
By default, PmWiki is configured such that only the first occurrence
|
||||
of 'PmWiki' in a page is treated as a WikiWord. If you want to
|
||||
restore 'PmWiki' to be treated like other WikiWords, uncomment the
|
||||
line below.
|
||||
unset($WikiWordCount['PmWiki']);
|
||||
|
||||
If you want to disable WikiWords matching a pattern, you can use
|
||||
something like the following. Note that the first argument has to
|
||||
be different for each call to Markup(). The example below disables
|
||||
WikiWord links like COM1, COM2, COM1234, etc.
|
||||
Markup('COM\d+', '<wikilink', '/\\bCOM\\d+/', "Keep('$0')");
|
||||
*/
|
||||
|
||||
SDV($LinkWikiWords, 1);
|
||||
|
||||
## bare wikilinks
|
||||
Markup_e('wikilink', '>urllink',
|
||||
"/\\b(?<![#&])($GroupPattern([\\/.]))?($WikiWordPattern)/",
|
||||
"Keep('<span class=\\'wikiword\\'>'.WikiLink(\$pagename,\$m[0]).'</span>',
|
||||
'L')");
|
||||
|
||||
function WikiLink($pagename, $word) {
|
||||
global $LinkWikiWords, $WikiWordCount, $SpaceWikiWords, $AsSpacedFunction,
|
||||
$MarkupFrame, $WikiWordCountMax;
|
||||
if (!$LinkWikiWords || ($WikiWordCount[$word] < 0)) return $word;
|
||||
$text = ($SpaceWikiWords) ? $AsSpacedFunction($word) : $word;
|
||||
$text = preg_replace('!.*/!', '', $text);
|
||||
if (!isset($MarkupFrame[0]['wwcount'][$word]))
|
||||
$MarkupFrame[0]['wwcount'][$word] = $WikiWordCountMax;
|
||||
if ($MarkupFrame[0]['wwcount'][$word]-- < 1) return $text;
|
||||
return MakeLink($pagename, $word, $text);
|
||||
}
|
||||
|
||||
|
||||
13
wiki/scripts/xlpage-iso-8859-13.php
Executable file
13
wiki/scripts/xlpage-iso-8859-13.php
Executable file
@@ -0,0 +1,13 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2005-2011 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
*/
|
||||
|
||||
global $HTTPHeaders, $Charset, $DefaultPageCharset;
|
||||
|
||||
$HTTPHeaders[] = "Content-type: text/html; charset=iso-8859-13;";
|
||||
$Charset = "ISO-8859-13";
|
||||
SDVA($DefaultPageCharset, array('ISO-8859-1'=>$Charset));
|
||||
65
wiki/scripts/xlpage-iso-8859-2.php
Executable file
65
wiki/scripts/xlpage-iso-8859-2.php
Executable file
@@ -0,0 +1,65 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2011 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file is used to enable the iso-8859-2 character set in PmWiki.
|
||||
The first part converts the charset to iso-8859-2 and removes
|
||||
conflicts for newline and keep tokens; the second part
|
||||
handles the conversion of pagenames from utf-8 (sent by browsers)
|
||||
into iso-8859-2 if needed.
|
||||
*/
|
||||
global $HTTPHeaders, $pagename, $KeepToken, $Charset, $DefaultPageCharset;
|
||||
|
||||
$HTTPHeaders[] = "Content-Type: text/html; charset=iso-8859-2;";
|
||||
$Charset = "ISO-8859-2";
|
||||
SDVA($DefaultPageCharset, array('ISO-8859-1'=>$Charset));
|
||||
|
||||
$KeepToken = "\263\263\263";
|
||||
|
||||
$pagename = $_REQUEST['n'];
|
||||
if (!$pagename) $pagename = @$_GET['pagename'];
|
||||
if ($pagename=='' && $EnablePathInfo)
|
||||
$pagename = @substr($_SERVER['PATH_INFO'],1);
|
||||
if (!$pagename &&
|
||||
preg_match('!^'.preg_quote($_SERVER['SCRIPT_NAME'],'!').'/?([^?]*)!',
|
||||
$_SERVER['REQUEST_URI'],$match))
|
||||
$pagename = urldecode($match[1]);
|
||||
$pagename = preg_replace('!/+$!','',$pagename);
|
||||
|
||||
if (!preg_match('/[\\x80-\\x9f]/', $pagename)) return;
|
||||
|
||||
if (function_exists('iconv'))
|
||||
$pagename = iconv('UTF-8','ISO-8859-2',$pagename);
|
||||
else {
|
||||
$conv = array(
|
||||
' '=>'<27>', 'Ą'=>'<27>', '˘'=>'<27>', 'Ł'=>'<27>',
|
||||
'¤'=>'<27>', 'Ľ'=>'<27>', 'Ś'=>'<27>', '§'=>'<27>',
|
||||
'¨'=>'<27>', 'Š'=>'<27>', 'Ş'=>'<27>', 'Ť'=>'<27>',
|
||||
'Ź'=>'<27>', ''=>'<27>', 'Ž'=>'<27>', 'Ż'=>'<27>',
|
||||
'°'=>'<27>', 'ą'=>'<27>', '˛'=>'<27>', 'ł'=>'<27>',
|
||||
'´'=>'<27>', 'ľ'=>'<27>', 'ś'=>'<27>', 'ˇ'=>'<27>',
|
||||
'¸'=>'<27>', 'š'=>'<27>', 'ş'=>'<27>', 'ť'=>'<27>',
|
||||
'ź'=>'<27>', '˝'=>'<27>', 'ž'=>'<27>', 'ż'=>'<27>',
|
||||
'Ŕ'=>'<27>', 'Á'=>'<27>', 'Â'=>'<27>', 'Ă'=>'<27>',
|
||||
'Ä'=>'<27>', 'Ĺ'=>'<27>', 'Ć'=>'<27>', 'Ç'=>'<27>',
|
||||
'Č'=>'<27>', 'É'=>'<27>', 'Ę'=>'<27>', 'Ë'=>'<27>',
|
||||
'Ě'=>'<27>', 'Í'=>'<27>', 'Î'=>'<27>', 'Ď'=>'<27>',
|
||||
'Đ'=>'<27>', 'Ń'=>'<27>', 'Ň'=>'<27>', 'Ó'=>'<27>',
|
||||
'Ô'=>'<27>', 'Ő'=>'<27>', 'Ö'=>'<27>', '×'=>'<27>',
|
||||
'Ř'=>'<27>', 'Ů'=>'<27>', 'Ú'=>'<27>', 'Ű'=>'<27>',
|
||||
'Ü'=>'<27>', 'Ý'=>'<27>', 'Ţ'=>'<27>', 'ß'=>'<27>',
|
||||
'ŕ'=>'<27>', 'á'=>'<27>', 'â'=>'<27>', 'ă'=>'<27>',
|
||||
'ä'=>'<27>', 'ĺ'=>'<27>', 'ć'=>'<27>', 'ç'=>'<27>',
|
||||
'č'=>'<27>', 'é'=>'<27>', 'ę'=>'<27>', 'ë'=>'<27>',
|
||||
'ě'=>'<27>', 'í'=>'<27>', 'î'=>'<27>', 'ď'=>'<27>',
|
||||
'đ'=>'<27>', 'ń'=>'<27>', 'ň'=>'<27>', 'ó'=>'<27>',
|
||||
'ô'=>'<27>', 'ő'=>'<27>', 'ö'=>'<27>', '÷'=>'<27>',
|
||||
'ř'=>'<27>', 'ů'=>'<27>', 'ú'=>'<27>', 'ű'=>'<27>',
|
||||
'ü'=>'<27>', 'ý'=>'<27>', 'ţ'=>'<27>', '˙'=>'<27>',
|
||||
);
|
||||
$pagename = str_replace(array_keys($conv),array_values($conv),$pagename);
|
||||
}
|
||||
|
||||
14
wiki/scripts/xlpage-iso-8859-9.php
Executable file
14
wiki/scripts/xlpage-iso-8859-9.php
Executable file
@@ -0,0 +1,14 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2005-2011 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
*/
|
||||
|
||||
global $HTTPHeaders, $Charset, $DefaultPageCharset;
|
||||
|
||||
$HTTPHeaders[] = "Content-type: text/html; charset=iso-8859-9;";
|
||||
$Charset = "ISO-8859-9";
|
||||
SDVA($DefaultPageCharset, array('ISO-8859-1'=>$Charset));
|
||||
|
||||
634
wiki/scripts/xlpage-utf-8.php
Executable file
634
wiki/scripts/xlpage-utf-8.php
Executable file
@@ -0,0 +1,634 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2013 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script configures PmWiki to use utf-8 in page content and
|
||||
pagenames. There are some unfortunate side effects about PHP's
|
||||
utf-8 implementation, however. First, since PHP doesn't have a
|
||||
way to do pattern matching on upper/lowercase UTF-8 characters,
|
||||
WikiWords are limited to the ASCII-7 set, and all links to page
|
||||
names with UTF-8 characters have to be in double brackets.
|
||||
Second, we have to assume that all non-ASCII characters are valid
|
||||
in pagenames, since there's no way to determine which UTF-8
|
||||
characters are "letters" and which are punctuation.
|
||||
*/
|
||||
|
||||
global $HTTPHeaders, $KeepToken, $pagename,
|
||||
$GroupPattern, $NamePattern, $WikiWordPattern, $SuffixPattern,
|
||||
$PageNameChars, $MakePageNamePatterns, $CaseConversions, $StringFolding,
|
||||
$Charset, $HTMLHeaderFmt, $StrFoldFunction, $AsSpacedFunction;
|
||||
|
||||
$Charset = 'UTF-8';
|
||||
$HTTPHeaders['utf-8'] = 'Content-type: text/html; charset=UTF-8';
|
||||
$HTMLHeaderFmt['utf-8'] =
|
||||
"<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />";
|
||||
$pagename = @$_REQUEST['n'];
|
||||
if (!$pagename) $pagename = @$_REQUEST['pagename'];
|
||||
if (!$pagename &&
|
||||
preg_match('!^'.preg_quote($_SERVER['SCRIPT_NAME'],'!').'/?([^?]*)!',
|
||||
$_SERVER['REQUEST_URI'],$match))
|
||||
$pagename = urldecode($match[1]);
|
||||
$pagename = preg_replace('!/+$!','',$pagename);
|
||||
$FmtPV['$RequestedPage'] = "'".PHSC($pagename, ENT_QUOTES)."'";
|
||||
|
||||
$GroupPattern = '[\\w\\x80-\\xfe]+(?:-[\\w\\x80-\\xfe]+)*';
|
||||
$NamePattern = '[\\w\\x80-\\xfe]+(?:-[\\w\\x80-\\xfe]+)*';
|
||||
$WikiWordPattern =
|
||||
'[A-Z][A-Za-z0-9]*(?:[A-Z][a-z0-9]|[a-z0-9][A-Z])[A-Za-z0-9]*';
|
||||
$SuffixPattern = '(?:-?[A-Za-z0-9\\x80-\\xd6]+)*';
|
||||
|
||||
SDV($PageNameChars, '-[:alnum:]\\x80-\\xfe');
|
||||
SDV($MakePageNamePatterns, array(
|
||||
'/[?#].*$/' => '', # strip everything after ? or #
|
||||
"/'/" => '', # strip single-quotes
|
||||
"/[^$PageNameChars]+/" => ' ', # convert everything else to space
|
||||
'/(?<=^| )([a-z])/' => PCCF("return strtoupper(\$m[1]);"),
|
||||
'/(?<=^| )([\\xc0-\\xdf].)/' => PCCF("return utf8toupper(\$m[1]);"),
|
||||
'/ /' => ''));
|
||||
SDV($StrFoldFunction, 'utf8fold');
|
||||
|
||||
$AsSpacedFunction = 'AsSpacedUTF8';
|
||||
|
||||
function utf8toupper($x) {
|
||||
global $CaseConversions;
|
||||
if (strlen($x) <= 2 && @$CaseConversions[$x])
|
||||
return $CaseConversions[$x];
|
||||
static $lower, $upper;
|
||||
if (!@$lower) {
|
||||
$lower = array_keys($CaseConversions);
|
||||
$upper = array_values($CaseConversions);
|
||||
}
|
||||
return str_replace($lower, $upper, $x);
|
||||
}
|
||||
|
||||
|
||||
function utf8fold($x) {
|
||||
global $StringFolding;
|
||||
static $source, $target;
|
||||
if (!@$source) {
|
||||
$source = array_keys($StringFolding);
|
||||
$target = array_values($StringFolding);
|
||||
}
|
||||
return str_replace($source, $target, $x);
|
||||
}
|
||||
|
||||
|
||||
function AsSpacedUTF8($text) {
|
||||
global $CaseConversions;
|
||||
static $lower, $upper;
|
||||
if (!@$CaseConversions) return AsSpaced($text);
|
||||
if (!@$lower) {
|
||||
$lower = implode('|', array_keys($CaseConversions));
|
||||
$upper = implode('|', array_values($CaseConversions));
|
||||
}
|
||||
$text = preg_replace("/($lower|\\d)($upper)/", '$1 $2', $text);
|
||||
$text = preg_replace('/([^-\\d])(\\d[-\\d]*( |$))/', '$1 $2', $text);
|
||||
return preg_replace("/($upper)(($upper)($lower|\\d))/", '$1 $2', $text);
|
||||
}
|
||||
|
||||
|
||||
SDVA($MarkupExpr, array(
|
||||
'substr' => 'call_user_func_array("utf8string", $args)',
|
||||
'strlen' => 'utf8string($args[0], "strlen")',
|
||||
'ucfirst' => 'utf8string($args[0], "ucfirst")',
|
||||
'ucwords' => 'utf8string($args[0], "ucwords")',
|
||||
'tolower' => 'utf8string($args[0], "tolower")',
|
||||
'toupper' => 'utf8string($args[0], "toupper")',
|
||||
));
|
||||
|
||||
function utf8string($str, $start=false, $len=false) { # strlen+substr++ combo for UTF-8
|
||||
global $CaseConversions;
|
||||
static $lower;
|
||||
if (!@$lower) $lower = implode('|', array_keys($CaseConversions));
|
||||
$ascii = preg_match('/[\\x80-\\xFF]/', $str)? 0:1;
|
||||
switch ((string)$start) {
|
||||
case 'ucfirst': return $ascii ? ucfirst($str) :
|
||||
PPRE("/^($lower)/", '$GLOBALS["CaseConversions"][$m[1]]', $str);
|
||||
case 'ucwords': return $ascii ? ucwords($str) :
|
||||
PPRE("/(^|\\s+)($lower)/", '$m[1].$GLOBALS["CaseConversions"][$m[2]]', $str);
|
||||
case 'tolower': return $ascii ? strtolower($str) : utf8fold($str);
|
||||
case 'toupper': return $ascii ? strtoupper($str) : utf8toupper($str);
|
||||
}
|
||||
if ($ascii) {
|
||||
if ($start==='strlen') return strlen($str);
|
||||
if ($len===false) return substr($str, $start);
|
||||
return substr($str, $start, $len);
|
||||
}
|
||||
$letters = preg_split("/([\\x00-\\x7f]|[\\xc2-\\xdf].|[\\xe0-\\xef]..|[\\xf0-\\xf4]...)/",
|
||||
$str, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
|
||||
if ($start==='strlen') return count($letters);
|
||||
if ($len===false) return implode('', array_slice($letters, $start));
|
||||
return implode('', array_slice($letters, $start, $len));
|
||||
}
|
||||
|
||||
## Conversion tables.
|
||||
## $CaseConversion maps lowercase utf8 sequences to
|
||||
## their uppercase equivalents. The table was derived from [1].
|
||||
## $StringFolding normalizes strings so that "equivalent"
|
||||
## forms will match using a binary comparison (derived from [2]).
|
||||
## [1] http://unicode.org/Public/UNIDATA/UnicodeData.txt
|
||||
## [2] http://unicode.org/Public/UNIDATA/CaseFolding.txt
|
||||
|
||||
SDV($CaseConversions, array(
|
||||
## U+0060
|
||||
"a" => "A", "b" => "B", "c" => "C", "d" => "D", "e" => "E", "f" => "F",
|
||||
"g" => "G", "h" => "H", "i" => "I", "j" => "J", "k" => "K", "l" => "L",
|
||||
"m" => "M", "n" => "N", "o" => "O", "p" => "P", "q" => "Q", "r" => "R",
|
||||
"s" => "S", "t" => "T", "u" => "U", "v" => "V", "w" => "W", "x" => "X",
|
||||
"y" => "Y", "z" => "Z",
|
||||
## U+00b5
|
||||
"\xc2\xb5" => "\xce\x9c",
|
||||
## U+00E0 to U+00FF
|
||||
"\xc3\xa0" => "\xc3\x80", "\xc3\xa1" => "\xc3\x81",
|
||||
"\xc3\xa2" => "\xc3\x82", "\xc3\xa3" => "\xc3\x83",
|
||||
"\xc3\xa4" => "\xc3\x84", "\xc3\xa5" => "\xc3\x85",
|
||||
"\xc3\xa6" => "\xc3\x86", "\xc3\xa7" => "\xc3\x87",
|
||||
"\xc3\xa8" => "\xc3\x88", "\xc3\xa9" => "\xc3\x89",
|
||||
"\xc3\xaa" => "\xc3\x8a", "\xc3\xab" => "\xc3\x8b",
|
||||
"\xc3\xac" => "\xc3\x8c", "\xc3\xad" => "\xc3\x8d",
|
||||
"\xc3\xae" => "\xc3\x8e", "\xc3\xaf" => "\xc3\x8f",
|
||||
"\xc3\xb0" => "\xc3\x90", "\xc3\xb1" => "\xc3\x91",
|
||||
"\xc3\xb2" => "\xc3\x92", "\xc3\xb3" => "\xc3\x93",
|
||||
"\xc3\xb4" => "\xc3\x94", "\xc3\xb5" => "\xc3\x95",
|
||||
"\xc3\xb6" => "\xc3\x96", "\xc3\xb8" => "\xc3\x98",
|
||||
"\xc3\xb9" => "\xc3\x99", "\xc3\xba" => "\xc3\x9a",
|
||||
"\xc3\xbb" => "\xc3\x9b", "\xc3\xbc" => "\xc3\x9c",
|
||||
"\xc3\xbd" => "\xc3\x9d", "\xc3\xbe" => "\xc3\x9e",
|
||||
"\xc3\xbf" => "\xc5\xb8",
|
||||
## U+0100
|
||||
"\xc4\x81" => "\xc4\x80", "\xc4\x83" => "\xc4\x82",
|
||||
"\xc4\x85" => "\xc4\x84", "\xc4\x87" => "\xc4\x86",
|
||||
"\xc4\x89" => "\xc4\x88", "\xc4\x8b" => "\xc4\x8a",
|
||||
"\xc4\x8d" => "\xc4\x8c", "\xc4\x8f" => "\xc4\x8e",
|
||||
"\xc4\x91" => "\xc4\x90", "\xc4\x93" => "\xc4\x92",
|
||||
"\xc4\x95" => "\xc4\x94", "\xc4\x97" => "\xc4\x96",
|
||||
"\xc4\x99" => "\xc4\x98", "\xc4\x9b" => "\xc4\x9a",
|
||||
"\xc4\x9d" => "\xc4\x9c", "\xc4\x9f" => "\xc4\x9e",
|
||||
"\xc4\xa1" => "\xc4\xa0", "\xc4\xa3" => "\xc4\xa2",
|
||||
"\xc4\xa5" => "\xc4\xa4", "\xc4\xa7" => "\xc4\xa6",
|
||||
"\xc4\xa9" => "\xc4\xa8", "\xc4\xab" => "\xc4\xaa",
|
||||
"\xc4\xad" => "\xc4\xac", "\xc4\xaf" => "\xc4\xae",
|
||||
"\xc4\xb1" => "I", "\xc4\xb3" => "\xc4\xb2",
|
||||
"\xc4\xb5" => "\xc4\xb4", "\xc4\xb7" => "\xc4\xb6",
|
||||
"\xc4\xba" => "\xc4\xb9", "\xc4\xbc" => "\xc4\xbb",
|
||||
"\xc4\xbe" => "\xc4\xbd",
|
||||
## U+0140
|
||||
"\xc5\x80" => "\xc4\xbf", "\xc5\x82" => "\xc5\x81",
|
||||
"\xc5\x84" => "\xc5\x83", "\xc5\x86" => "\xc5\x85",
|
||||
"\xc5\x88" => "\xc5\x87", "\xc5\x8b" => "\xc5\x8a",
|
||||
"\xc5\x8d" => "\xc5\x8c", "\xc5\x8f" => "\xc5\x8e",
|
||||
"\xc5\x91" => "\xc5\x90", "\xc5\x93" => "\xc5\x92",
|
||||
"\xc5\x95" => "\xc5\x94", "\xc5\x97" => "\xc5\x96",
|
||||
"\xc5\x99" => "\xc5\x98", "\xc5\x9b" => "\xc5\x9a",
|
||||
"\xc5\x9d" => "\xc5\x9c", "\xc5\x9f" => "\xc5\x9e",
|
||||
"\xc5\xa1" => "\xc5\xa0", "\xc5\xa3" => "\xc5\xa2",
|
||||
"\xc5\xa5" => "\xc5\xa4", "\xc5\xa7" => "\xc5\xa6",
|
||||
"\xc5\xa9" => "\xc5\xa8", "\xc5\xab" => "\xc5\xaa",
|
||||
"\xc5\xad" => "\xc5\xac", "\xc5\xaf" => "\xc5\xae",
|
||||
"\xc5\xb1" => "\xc5\xb0", "\xc5\xb3" => "\xc5\xb2",
|
||||
"\xc5\xb5" => "\xc5\xb4", "\xc5\xb7" => "\xc5\xb6",
|
||||
"\xc5\xba" => "\xc5\xb9", "\xc5\xbc" => "\xc5\xbb",
|
||||
"\xc5\xbe" => "\xc5\xbd", "\xc5\xbf" => "S",
|
||||
## U+0180
|
||||
"\xc6\x80" => "\xc9\x83", "\xc6\x83" => "\xc6\x82",
|
||||
"\xc6\x85" => "\xc6\x84", "\xc6\x88" => "\xc6\x87",
|
||||
"\xc6\x8c" => "\xc6\x8b", "\xc6\x92" => "\xc6\x91",
|
||||
"\xc6\x95" => "\xc7\xb6", "\xc6\x99" => "\xc6\x98",
|
||||
"\xc6\x9a" => "\xc8\xbd", "\xc6\x9e" => "\xc8\xa0",
|
||||
"\xc6\xa1" => "\xc6\xa0", "\xc6\xa3" => "\xc6\xa2",
|
||||
"\xc6\xa5" => "\xc6\xa4", "\xc6\xa8" => "\xc6\xa7",
|
||||
"\xc6\xad" => "\xc6\xac", "\xc6\xb0" => "\xc6\xaf",
|
||||
"\xc6\xb4" => "\xc6\xb3", "\xc6\xb6" => "\xc6\xb5",
|
||||
"\xc6\xb9" => "\xc6\xb8", "\xc6\xbd" => "\xc6\xbc",
|
||||
"\xc6\xbf" => "\xc7\xb7",
|
||||
## U+01c0
|
||||
"\xc7\x85" => "\xc7\x84", "\xc7\x86" => "\xc7\x84",
|
||||
"\xc7\x88" => "\xc7\x87", "\xc7\x89" => "\xc7\x87",
|
||||
"\xc7\x8b" => "\xc7\x8a", "\xc7\x8c" => "\xc7\x8a",
|
||||
"\xc7\x8e" => "\xc7\x8d", "\xc7\x90" => "\xc7\x8f",
|
||||
"\xc7\x92" => "\xc7\x91", "\xc7\x94" => "\xc7\x93",
|
||||
"\xc7\x96" => "\xc7\x95", "\xc7\x98" => "\xc7\x97",
|
||||
"\xc7\x9a" => "\xc7\x99", "\xc7\x9c" => "\xc7\x9b",
|
||||
"\xc7\x9d" => "\xc6\x8e", "\xc7\x9f" => "\xc7\x9e",
|
||||
"\xc7\xa1" => "\xc7\xa0", "\xc7\xa3" => "\xc7\xa2",
|
||||
"\xc7\xa5" => "\xc7\xa4", "\xc7\xa7" => "\xc7\xa6",
|
||||
"\xc7\xa9" => "\xc7\xa8", "\xc7\xab" => "\xc7\xaa",
|
||||
"\xc7\xad" => "\xc7\xac", "\xc7\xaf" => "\xc7\xae",
|
||||
"\xc7\xb2" => "\xc7\xb1", "\xc7\xb3" => "\xc7\xb1",
|
||||
"\xc7\xb5" => "\xc7\xb4", "\xc7\xb9" => "\xc7\xb8",
|
||||
"\xc7\xbb" => "\xc7\xba", "\xc7\xbd" => "\xc7\xbc",
|
||||
"\xc7\xbf" => "\xc7\xbe",
|
||||
## U+0200
|
||||
"\xc8\x81" => "\xc8\x80", "\xc8\x83" => "\xc8\x82",
|
||||
"\xc8\x85" => "\xc8\x84", "\xc8\x87" => "\xc8\x86",
|
||||
"\xc8\x89" => "\xc8\x88", "\xc8\x8b" => "\xc8\x8a",
|
||||
"\xc8\x8d" => "\xc8\x8c", "\xc8\x8f" => "\xc8\x8e",
|
||||
"\xc8\x91" => "\xc8\x90", "\xc8\x93" => "\xc8\x92",
|
||||
"\xc8\x95" => "\xc8\x94", "\xc8\x97" => "\xc8\x96",
|
||||
"\xc8\x99" => "\xc8\x98", "\xc8\x9b" => "\xc8\x9a",
|
||||
"\xc8\x9d" => "\xc8\x9c", "\xc8\x9f" => "\xc8\x9e",
|
||||
"\xc8\xa3" => "\xc8\xa2", "\xc8\xa5" => "\xc8\xa4",
|
||||
"\xc8\xa7" => "\xc8\xa6", "\xc8\xa9" => "\xc8\xa8",
|
||||
"\xc8\xab" => "\xc8\xaa", "\xc8\xad" => "\xc8\xac",
|
||||
"\xc8\xaf" => "\xc8\xae", "\xc8\xb1" => "\xc8\xb0",
|
||||
"\xc8\xb3" => "\xc8\xb2", "\xc8\xbc" => "\xc8\xbb",
|
||||
## U+0240
|
||||
"\xc9\x82" => "\xc9\x81", "\xc9\x87" => "\xc9\x86",
|
||||
"\xc9\x89" => "\xc9\x88", "\xc9\x8b" => "\xc9\x8a",
|
||||
"\xc9\x8d" => "\xc9\x8c", "\xc9\x8f" => "\xc9\x8e",
|
||||
"\xc9\x93" => "\xc6\x81", "\xc9\x94" => "\xc6\x86",
|
||||
"\xc9\x96" => "\xc6\x89", "\xc9\x97" => "\xc6\x8a",
|
||||
"\xc9\x99" => "\xc6\x8f", "\xc9\x9b" => "\xc6\x90",
|
||||
"\xc9\xa0" => "\xc6\x93", "\xc9\xa3" => "\xc6\x94",
|
||||
"\xc9\xa8" => "\xc6\x97", "\xc9\xa9" => "\xc6\x96",
|
||||
"\xc9\xab" => "\xe2\xb1\xa2", "\xc9\xaf" => "\xc6\x9c",
|
||||
"\xc9\xb2" => "\xc6\x9d", "\xc9\xb5" => "\xc6\x9f",
|
||||
"\xc9\xbd" => "\xe2\xb1\xa4",
|
||||
## U+0280
|
||||
"\xca\x80" => "\xc6\xa6", "\xca\x83" => "\xc6\xa9",
|
||||
"\xca\x88" => "\xc6\xae", "\xca\x89" => "\xc9\x84",
|
||||
"\xca\x8a" => "\xc6\xb1", "\xca\x8b" => "\xc6\xb2",
|
||||
"\xca\x8c" => "\xc9\x85", "\xca\x92" => "\xc6\xb7",
|
||||
## U+0340
|
||||
"\xcd\x85" => "\xce\x99", "\xcd\xbb" => "\xcf\xbd",
|
||||
"\xcd\xbc" => "\xcf\xbe", "\xcd\xbd" => "\xcf\xbf",
|
||||
## U+0380
|
||||
"\xce\xac" => "\xce\x86", "\xce\xad" => "\xce\x88",
|
||||
"\xce\xae" => "\xce\x89", "\xce\xaf" => "\xce\x8a",
|
||||
"\xce\xb1" => "\xce\x91", "\xce\xb2" => "\xce\x92",
|
||||
"\xce\xb3" => "\xce\x93", "\xce\xb4" => "\xce\x94",
|
||||
"\xce\xb5" => "\xce\x95", "\xce\xb6" => "\xce\x96",
|
||||
"\xce\xb7" => "\xce\x97", "\xce\xb8" => "\xce\x98",
|
||||
"\xce\xb9" => "\xce\x99", "\xce\xba" => "\xce\x9a",
|
||||
"\xce\xbb" => "\xce\x9b", "\xce\xbc" => "\xce\x9c",
|
||||
"\xce\xbd" => "\xce\x9d", "\xce\xbe" => "\xce\x9e",
|
||||
"\xce\xbf" => "\xce\x9f",
|
||||
## U+03c0
|
||||
"\xcf\x80" => "\xce\xa0", "\xcf\x81" => "\xce\xa1",
|
||||
"\xcf\x82" => "\xce\xa3", "\xcf\x83" => "\xce\xa3",
|
||||
"\xcf\x84" => "\xce\xa4", "\xcf\x85" => "\xce\xa5",
|
||||
"\xcf\x86" => "\xce\xa6", "\xcf\x87" => "\xce\xa7",
|
||||
"\xcf\x88" => "\xce\xa8", "\xcf\x89" => "\xce\xa9",
|
||||
"\xcf\x8a" => "\xce\xaa", "\xcf\x8b" => "\xce\xab",
|
||||
"\xcf\x8c" => "\xce\x8c", "\xcf\x8d" => "\xce\x8e",
|
||||
"\xcf\x8e" => "\xce\x8f", "\xcf\x90" => "\xce\x92",
|
||||
"\xcf\x91" => "\xce\x98", "\xcf\x95" => "\xce\xa6",
|
||||
"\xcf\x96" => "\xce\xa0", "\xcf\x99" => "\xcf\x98",
|
||||
"\xcf\x9b" => "\xcf\x9a", "\xcf\x9d" => "\xcf\x9c",
|
||||
"\xcf\x9f" => "\xcf\x9e", "\xcf\xa1" => "\xcf\xa0",
|
||||
"\xcf\xa3" => "\xcf\xa2", "\xcf\xa5" => "\xcf\xa4",
|
||||
"\xcf\xa7" => "\xcf\xa6", "\xcf\xa9" => "\xcf\xa8",
|
||||
"\xcf\xab" => "\xcf\xaa", "\xcf\xad" => "\xcf\xac",
|
||||
"\xcf\xaf" => "\xcf\xae", "\xcf\xb0" => "\xce\x9a",
|
||||
"\xcf\xb1" => "\xce\xa1", "\xcf\xb2" => "\xcf\xb9",
|
||||
"\xcf\xb5" => "\xce\x95", "\xcf\xb8" => "\xcf\xb7",
|
||||
"\xcf\xbb" => "\xcf\xba",
|
||||
## U+0400
|
||||
"\xd0\xb0" => "\xd0\x90", "\xd0\xb1" => "\xd0\x91",
|
||||
"\xd0\xb2" => "\xd0\x92", "\xd0\xb3" => "\xd0\x93",
|
||||
"\xd0\xb4" => "\xd0\x94", "\xd0\xb5" => "\xd0\x95",
|
||||
"\xd0\xb6" => "\xd0\x96", "\xd0\xb7" => "\xd0\x97",
|
||||
"\xd0\xb8" => "\xd0\x98", "\xd0\xb9" => "\xd0\x99",
|
||||
"\xd0\xba" => "\xd0\x9a", "\xd0\xbb" => "\xd0\x9b",
|
||||
"\xd0\xbc" => "\xd0\x9c", "\xd0\xbd" => "\xd0\x9d",
|
||||
"\xd0\xbe" => "\xd0\x9e", "\xd0\xbf" => "\xd0\x9f",
|
||||
## U+0440
|
||||
"\xd1\x80" => "\xd0\xa0", "\xd1\x81" => "\xd0\xa1",
|
||||
"\xd1\x82" => "\xd0\xa2", "\xd1\x83" => "\xd0\xa3",
|
||||
"\xd1\x84" => "\xd0\xa4", "\xd1\x85" => "\xd0\xa5",
|
||||
"\xd1\x86" => "\xd0\xa6", "\xd1\x87" => "\xd0\xa7",
|
||||
"\xd1\x88" => "\xd0\xa8", "\xd1\x89" => "\xd0\xa9",
|
||||
"\xd1\x8a" => "\xd0\xaa", "\xd1\x8b" => "\xd0\xab",
|
||||
"\xd1\x8c" => "\xd0\xac", "\xd1\x8d" => "\xd0\xad",
|
||||
"\xd1\x8e" => "\xd0\xae", "\xd1\x8f" => "\xd0\xaf",
|
||||
"\xd1\x90" => "\xd0\x80", "\xd1\x91" => "\xd0\x81",
|
||||
"\xd1\x92" => "\xd0\x82", "\xd1\x93" => "\xd0\x83",
|
||||
"\xd1\x94" => "\xd0\x84", "\xd1\x95" => "\xd0\x85",
|
||||
"\xd1\x96" => "\xd0\x86", "\xd1\x97" => "\xd0\x87",
|
||||
"\xd1\x98" => "\xd0\x88", "\xd1\x99" => "\xd0\x89",
|
||||
"\xd1\x9a" => "\xd0\x8a", "\xd1\x9b" => "\xd0\x8b",
|
||||
"\xd1\x9c" => "\xd0\x8c", "\xd1\x9d" => "\xd0\x8d",
|
||||
"\xd1\x9e" => "\xd0\x8e", "\xd1\x9f" => "\xd0\x8f",
|
||||
"\xd1\xa1" => "\xd1\xa0", "\xd1\xa3" => "\xd1\xa2",
|
||||
"\xd1\xa5" => "\xd1\xa4", "\xd1\xa7" => "\xd1\xa6",
|
||||
"\xd1\xa9" => "\xd1\xa8", "\xd1\xab" => "\xd1\xaa",
|
||||
"\xd1\xad" => "\xd1\xac", "\xd1\xaf" => "\xd1\xae",
|
||||
"\xd1\xb1" => "\xd1\xb0", "\xd1\xb3" => "\xd1\xb2",
|
||||
"\xd1\xb5" => "\xd1\xb4", "\xd1\xb7" => "\xd1\xb6",
|
||||
"\xd1\xb9" => "\xd1\xb8", "\xd1\xbb" => "\xd1\xba",
|
||||
"\xd1\xbd" => "\xd1\xbc", "\xd1\xbf" => "\xd1\xbe",
|
||||
## U+0480
|
||||
"\xd2\x81" => "\xd2\x80", "\xd2\x8b" => "\xd2\x8a",
|
||||
"\xd2\x8d" => "\xd2\x8c", "\xd2\x8f" => "\xd2\x8e",
|
||||
"\xd2\x91" => "\xd2\x90", "\xd2\x93" => "\xd2\x92",
|
||||
"\xd2\x95" => "\xd2\x94", "\xd2\x97" => "\xd2\x96",
|
||||
"\xd2\x99" => "\xd2\x98", "\xd2\x9b" => "\xd2\x9a",
|
||||
"\xd2\x9d" => "\xd2\x9c", "\xd2\x9f" => "\xd2\x9e",
|
||||
"\xd2\xa1" => "\xd2\xa0", "\xd2\xa3" => "\xd2\xa2",
|
||||
"\xd2\xa5" => "\xd2\xa4", "\xd2\xa7" => "\xd2\xa6",
|
||||
"\xd2\xa9" => "\xd2\xa8", "\xd2\xab" => "\xd2\xaa",
|
||||
"\xd2\xad" => "\xd2\xac", "\xd2\xaf" => "\xd2\xae",
|
||||
"\xd2\xb1" => "\xd2\xb0", "\xd2\xb3" => "\xd2\xb2",
|
||||
"\xd2\xb5" => "\xd2\xb4", "\xd2\xb7" => "\xd2\xb6",
|
||||
"\xd2\xb9" => "\xd2\xb8", "\xd2\xbb" => "\xd2\xba",
|
||||
"\xd2\xbd" => "\xd2\xbc", "\xd2\xbf" => "\xd2\xbe",
|
||||
## U+04c0
|
||||
"\xd3\x82" => "\xd3\x81", "\xd3\x84" => "\xd3\x83",
|
||||
"\xd3\x86" => "\xd3\x85", "\xd3\x88" => "\xd3\x87",
|
||||
"\xd3\x8a" => "\xd3\x89", "\xd3\x8c" => "\xd3\x8b",
|
||||
"\xd3\x8e" => "\xd3\x8d", "\xd3\x8f" => "\xd3\x80",
|
||||
"\xd3\x91" => "\xd3\x90", "\xd3\x93" => "\xd3\x92",
|
||||
"\xd3\x95" => "\xd3\x94", "\xd3\x97" => "\xd3\x96",
|
||||
"\xd3\x99" => "\xd3\x98", "\xd3\x9b" => "\xd3\x9a",
|
||||
"\xd3\x9d" => "\xd3\x9c", "\xd3\x9f" => "\xd3\x9e",
|
||||
"\xd3\xa1" => "\xd3\xa0", "\xd3\xa3" => "\xd3\xa2",
|
||||
"\xd3\xa5" => "\xd3\xa4", "\xd3\xa7" => "\xd3\xa6",
|
||||
"\xd3\xa9" => "\xd3\xa8", "\xd3\xab" => "\xd3\xaa",
|
||||
"\xd3\xad" => "\xd3\xac", "\xd3\xaf" => "\xd3\xae",
|
||||
"\xd3\xb1" => "\xd3\xb0", "\xd3\xb3" => "\xd3\xb2",
|
||||
"\xd3\xb5" => "\xd3\xb4", "\xd3\xb7" => "\xd3\xb6",
|
||||
"\xd3\xb9" => "\xd3\xb8", "\xd3\xbb" => "\xd3\xba",
|
||||
"\xd3\xbd" => "\xd3\xbc", "\xd3\xbf" => "\xd3\xbe",
|
||||
## U+0500
|
||||
"\xd4\x81" => "\xd4\x80", "\xd4\x83" => "\xd4\x82",
|
||||
"\xd4\x85" => "\xd4\x84", "\xd4\x87" => "\xd4\x86",
|
||||
"\xd4\x89" => "\xd4\x88", "\xd4\x8b" => "\xd4\x8a",
|
||||
"\xd4\x8d" => "\xd4\x8c", "\xd4\x8f" => "\xd4\x8e",
|
||||
"\xd4\x91" => "\xd4\x90", "\xd4\x93" => "\xd4\x92",
|
||||
## U+0560
|
||||
"\xd5\xa1" => "\xd4\xb1", "\xd5\xa2" => "\xd4\xb2",
|
||||
"\xd5\xa3" => "\xd4\xb3", "\xd5\xa4" => "\xd4\xb4",
|
||||
"\xd5\xa5" => "\xd4\xb5", "\xd5\xa6" => "\xd4\xb6",
|
||||
"\xd5\xa7" => "\xd4\xb7", "\xd5\xa8" => "\xd4\xb8",
|
||||
"\xd5\xa9" => "\xd4\xb9", "\xd5\xaa" => "\xd4\xba",
|
||||
"\xd5\xab" => "\xd4\xbb", "\xd5\xac" => "\xd4\xbc",
|
||||
"\xd5\xad" => "\xd4\xbd", "\xd5\xae" => "\xd4\xbe",
|
||||
"\xd5\xaf" => "\xd4\xbf", "\xd5\xb0" => "\xd5\x80",
|
||||
"\xd5\xb1" => "\xd5\x81", "\xd5\xb2" => "\xd5\x82",
|
||||
"\xd5\xb3" => "\xd5\x83", "\xd5\xb4" => "\xd5\x84",
|
||||
"\xd5\xb5" => "\xd5\x85", "\xd5\xb6" => "\xd5\x86",
|
||||
"\xd5\xb7" => "\xd5\x87", "\xd5\xb8" => "\xd5\x88",
|
||||
"\xd5\xb9" => "\xd5\x89", "\xd5\xba" => "\xd5\x8a",
|
||||
"\xd5\xbb" => "\xd5\x8b", "\xd5\xbc" => "\xd5\x8c",
|
||||
"\xd5\xbd" => "\xd5\x8d", "\xd5\xbe" => "\xd5\x8e",
|
||||
"\xd5\xbf" => "\xd5\x8f",
|
||||
## U+0580
|
||||
"\xd6\x80" => "\xd5\x90", "\xd6\x81" => "\xd5\x91",
|
||||
"\xd6\x82" => "\xd5\x92", "\xd6\x83" => "\xd5\x93",
|
||||
"\xd6\x84" => "\xd5\x94", "\xd6\x85" => "\xd5\x95",
|
||||
"\xd6\x86" => "\xd5\x96"
|
||||
));
|
||||
|
||||
SDV($StringFolding, array(
|
||||
## U+0040
|
||||
"A" => "a", "B" => "b", "C" => "c", "D" => "d", "E" => "e", "F" => "f",
|
||||
"G" => "g", "H" => "h", "I" => "i", "J" => "j", "K" => "k", "L" => "l",
|
||||
"M" => "m", "N" => "n", "O" => "o", "P" => "p", "Q" => "q", "R" => "r",
|
||||
"S" => "s", "T" => "t", "U" => "u", "V" => "v", "W" => "w", "X" => "x",
|
||||
"Y" => "y", "Z" => "z",
|
||||
## U+00B5
|
||||
"\xc2\xb5" => "\xce\xbc",
|
||||
## U+00C0
|
||||
"\xc3\x80" => "\xc3\xa0", "\xc3\x81" => "\xc3\xa1",
|
||||
"\xc3\x82" => "\xc3\xa2", "\xc3\x83" => "\xc3\xa3",
|
||||
"\xc3\x84" => "\xc3\xa4", "\xc3\x85" => "\xc3\xa5",
|
||||
"\xc3\x86" => "\xc3\xa6", "\xc3\x87" => "\xc3\xa7",
|
||||
"\xc3\x88" => "\xc3\xa8", "\xc3\x89" => "\xc3\xa9",
|
||||
"\xc3\x8a" => "\xc3\xaa", "\xc3\x8b" => "\xc3\xab",
|
||||
"\xc3\x8c" => "\xc3\xac", "\xc3\x8d" => "\xc3\xad",
|
||||
"\xc3\x8e" => "\xc3\xae", "\xc3\x8f" => "\xc3\xaf",
|
||||
"\xc3\x90" => "\xc3\xb0", "\xc3\x91" => "\xc3\xb1",
|
||||
"\xc3\x92" => "\xc3\xb2", "\xc3\x93" => "\xc3\xb3",
|
||||
"\xc3\x94" => "\xc3\xb4", "\xc3\x95" => "\xc3\xb5",
|
||||
"\xc3\x96" => "\xc3\xb6", "\xc3\x98" => "\xc3\xb8",
|
||||
"\xc3\x99" => "\xc3\xb9", "\xc3\x9a" => "\xc3\xba",
|
||||
"\xc3\x9b" => "\xc3\xbb", "\xc3\x9c" => "\xc3\xbc",
|
||||
"\xc3\x9d" => "\xc3\xbd", "\xc3\x9e" => "\xc3\xbe",
|
||||
"\xc3\x9f" => "ss",
|
||||
## U+0100
|
||||
"\xc4\x80" => "\xc4\x81", "\xc4\x82" => "\xc4\x83",
|
||||
"\xc4\x84" => "\xc4\x85", "\xc4\x86" => "\xc4\x87",
|
||||
"\xc4\x88" => "\xc4\x89", "\xc4\x8a" => "\xc4\x8b",
|
||||
"\xc4\x8c" => "\xc4\x8d", "\xc4\x8e" => "\xc4\x8f",
|
||||
"\xc4\x90" => "\xc4\x91", "\xc4\x92" => "\xc4\x93",
|
||||
"\xc4\x94" => "\xc4\x95", "\xc4\x96" => "\xc4\x97",
|
||||
"\xc4\x98" => "\xc4\x99", "\xc4\x9a" => "\xc4\x9b",
|
||||
"\xc4\x9c" => "\xc4\x9d", "\xc4\x9e" => "\xc4\x9f",
|
||||
"\xc4\xa0" => "\xc4\xa1", "\xc4\xa2" => "\xc4\xa3",
|
||||
"\xc4\xa4" => "\xc4\xa5", "\xc4\xa6" => "\xc4\xa7",
|
||||
"\xc4\xa8" => "\xc4\xa9", "\xc4\xaa" => "\xc4\xab",
|
||||
"\xc4\xac" => "\xc4\xad", "\xc4\xae" => "\xc4\xaf",
|
||||
"\xc4\xb0" => "i\xcc\x87", "\xc4\xb2" => "\xc4\xb3",
|
||||
"\xc4\xb4" => "\xc4\xb5", "\xc4\xb6" => "\xc4\xb7",
|
||||
"\xc4\xb9" => "\xc4\xba", "\xc4\xbb" => "\xc4\xbc",
|
||||
"\xc4\xbd" => "\xc4\xbe", "\xc4\xbf" => "\xc5\x80",
|
||||
## U+0140
|
||||
"\xc5\x81" => "\xc5\x82", "\xc5\x83" => "\xc5\x84",
|
||||
"\xc5\x85" => "\xc5\x86", "\xc5\x87" => "\xc5\x88",
|
||||
"\xc5\x89" => "\xca\xbcn", "\xc5\x8a" => "\xc5\x8b",
|
||||
"\xc5\x8c" => "\xc5\x8d", "\xc5\x8e" => "\xc5\x8f",
|
||||
"\xc5\x90" => "\xc5\x91", "\xc5\x92" => "\xc5\x93",
|
||||
"\xc5\x94" => "\xc5\x95", "\xc5\x96" => "\xc5\x97",
|
||||
"\xc5\x98" => "\xc5\x99", "\xc5\x9a" => "\xc5\x9b",
|
||||
"\xc5\x9c" => "\xc5\x9d", "\xc5\x9e" => "\xc5\x9f",
|
||||
"\xc5\xa0" => "\xc5\xa1", "\xc5\xa2" => "\xc5\xa3",
|
||||
"\xc5\xa4" => "\xc5\xa5", "\xc5\xa6" => "\xc5\xa7",
|
||||
"\xc5\xa8" => "\xc5\xa9", "\xc5\xaa" => "\xc5\xab",
|
||||
"\xc5\xac" => "\xc5\xad", "\xc5\xae" => "\xc5\xaf",
|
||||
"\xc5\xb0" => "\xc5\xb1", "\xc5\xb2" => "\xc5\xb3",
|
||||
"\xc5\xb4" => "\xc5\xb5", "\xc5\xb6" => "\xc5\xb7",
|
||||
"\xc5\xb8" => "\xc3\xbf", "\xc5\xb9" => "\xc5\xba",
|
||||
"\xc5\xbb" => "\xc5\xbc", "\xc5\xbd" => "\xc5\xbe",
|
||||
"\xc5\xbf" => "s",
|
||||
## U+0180
|
||||
"\xc6\x81" => "\xc9\x93", "\xc6\x82" => "\xc6\x83",
|
||||
"\xc6\x84" => "\xc6\x85", "\xc6\x86" => "\xc9\x94",
|
||||
"\xc6\x87" => "\xc6\x88", "\xc6\x89" => "\xc9\x96",
|
||||
"\xc6\x8a" => "\xc9\x97", "\xc6\x8b" => "\xc6\x8c",
|
||||
"\xc6\x8e" => "\xc7\x9d", "\xc6\x8f" => "\xc9\x99",
|
||||
"\xc6\x90" => "\xc9\x9b", "\xc6\x91" => "\xc6\x92",
|
||||
"\xc6\x93" => "\xc9\xa0", "\xc6\x94" => "\xc9\xa3",
|
||||
"\xc6\x96" => "\xc9\xa9", "\xc6\x97" => "\xc9\xa8",
|
||||
"\xc6\x98" => "\xc6\x99", "\xc6\x9c" => "\xc9\xaf",
|
||||
"\xc6\x9d" => "\xc9\xb2", "\xc6\x9f" => "\xc9\xb5",
|
||||
"\xc6\xa0" => "\xc6\xa1", "\xc6\xa2" => "\xc6\xa3",
|
||||
"\xc6\xa4" => "\xc6\xa5", "\xc6\xa6" => "\xca\x80",
|
||||
"\xc6\xa7" => "\xc6\xa8", "\xc6\xa9" => "\xca\x83",
|
||||
"\xc6\xac" => "\xc6\xad", "\xc6\xae" => "\xca\x88",
|
||||
"\xc6\xaf" => "\xc6\xb0", "\xc6\xb1" => "\xca\x8a",
|
||||
"\xc6\xb2" => "\xca\x8b", "\xc6\xb3" => "\xc6\xb4",
|
||||
"\xc6\xb5" => "\xc6\xb6", "\xc6\xb7" => "\xca\x92",
|
||||
"\xc6\xb8" => "\xc6\xb9", "\xc6\xbc" => "\xc6\xbd",
|
||||
## U+01c0
|
||||
"\xc7\x84" => "\xc7\x86", "\xc7\x85" => "\xc7\x86",
|
||||
"\xc7\x87" => "\xc7\x89", "\xc7\x88" => "\xc7\x89",
|
||||
"\xc7\x8a" => "\xc7\x8c", "\xc7\x8b" => "\xc7\x8c",
|
||||
"\xc7\x8d" => "\xc7\x8e", "\xc7\x8f" => "\xc7\x90",
|
||||
"\xc7\x91" => "\xc7\x92", "\xc7\x93" => "\xc7\x94",
|
||||
"\xc7\x95" => "\xc7\x96", "\xc7\x97" => "\xc7\x98",
|
||||
"\xc7\x99" => "\xc7\x9a", "\xc7\x9b" => "\xc7\x9c",
|
||||
"\xc7\x9e" => "\xc7\x9f", "\xc7\xa0" => "\xc7\xa1",
|
||||
"\xc7\xa2" => "\xc7\xa3", "\xc7\xa4" => "\xc7\xa5",
|
||||
"\xc7\xa6" => "\xc7\xa7", "\xc7\xa8" => "\xc7\xa9",
|
||||
"\xc7\xaa" => "\xc7\xab", "\xc7\xac" => "\xc7\xad",
|
||||
"\xc7\xae" => "\xc7\xaf", "\xc7\xb0" => "j\xcc\x8c",
|
||||
"\xc7\xb1" => "\xc7\xb3", "\xc7\xb2" => "\xc7\xb3",
|
||||
"\xc7\xb4" => "\xc7\xb5", "\xc7\xb6" => "\xc6\x95",
|
||||
"\xc7\xb7" => "\xc6\xbf", "\xc7\xb8" => "\xc7\xb9",
|
||||
"\xc7\xba" => "\xc7\xbb", "\xc7\xbc" => "\xc7\xbd",
|
||||
"\xc7\xbe" => "\xc7\xbf",
|
||||
## U+0200
|
||||
"\xc8\x80" => "\xc8\x81", "\xc8\x82" => "\xc8\x83",
|
||||
"\xc8\x84" => "\xc8\x85", "\xc8\x86" => "\xc8\x87",
|
||||
"\xc8\x88" => "\xc8\x89", "\xc8\x8a" => "\xc8\x8b",
|
||||
"\xc8\x8c" => "\xc8\x8d", "\xc8\x8e" => "\xc8\x8f",
|
||||
"\xc8\x90" => "\xc8\x91", "\xc8\x92" => "\xc8\x93",
|
||||
"\xc8\x94" => "\xc8\x95", "\xc8\x96" => "\xc8\x97",
|
||||
"\xc8\x98" => "\xc8\x99", "\xc8\x9a" => "\xc8\x9b",
|
||||
"\xc8\x9c" => "\xc8\x9d", "\xc8\x9e" => "\xc8\x9f",
|
||||
"\xc8\xa0" => "\xc6\x9e", "\xc8\xa2" => "\xc8\xa3",
|
||||
"\xc8\xa4" => "\xc8\xa5", "\xc8\xa6" => "\xc8\xa7",
|
||||
"\xc8\xa8" => "\xc8\xa9", "\xc8\xaa" => "\xc8\xab",
|
||||
"\xc8\xac" => "\xc8\xad", "\xc8\xae" => "\xc8\xaf",
|
||||
"\xc8\xb0" => "\xc8\xb1", "\xc8\xb2" => "\xc8\xb3",
|
||||
"\xc8\xba" => "\xe2\xb1\xa5", "\xc8\xbb" => "\xc8\xbc",
|
||||
"\xc8\xbd" => "\xc6\x9a", "\xc8\xbe" => "\xe2\xb1\xa6",
|
||||
## U+0240
|
||||
"\xc9\x81" => "\xc9\x82", "\xc9\x83" => "\xc6\x80",
|
||||
"\xc9\x84" => "\xca\x89", "\xc9\x85" => "\xca\x8c",
|
||||
"\xc9\x86" => "\xc9\x87", "\xc9\x88" => "\xc9\x89",
|
||||
"\xc9\x8a" => "\xc9\x8b", "\xc9\x8c" => "\xc9\x8d",
|
||||
"\xc9\x8e" => "\xc9\x8f",
|
||||
## U+0345
|
||||
"\xcd\x85" => "\xce\xb9",
|
||||
## U+0380
|
||||
"\xce\x86" => "\xce\xac", "\xce\x88" => "\xce\xad",
|
||||
"\xce\x89" => "\xce\xae", "\xce\x8a" => "\xce\xaf",
|
||||
"\xce\x8c" => "\xcf\x8c", "\xce\x8e" => "\xcf\x8d",
|
||||
"\xce\x8f" => "\xcf\x8e", "\xce\x90" => "\xce\xb9\xcc\x88\xcc\x81",
|
||||
"\xce\x91" => "\xce\xb1", "\xce\x92" => "\xce\xb2",
|
||||
"\xce\x93" => "\xce\xb3", "\xce\x94" => "\xce\xb4",
|
||||
"\xce\x95" => "\xce\xb5", "\xce\x96" => "\xce\xb6",
|
||||
"\xce\x97" => "\xce\xb7", "\xce\x98" => "\xce\xb8",
|
||||
"\xce\x99" => "\xce\xb9", "\xce\x9a" => "\xce\xba",
|
||||
"\xce\x9b" => "\xce\xbb", "\xce\x9c" => "\xce\xbc",
|
||||
"\xce\x9d" => "\xce\xbd", "\xce\x9e" => "\xce\xbe",
|
||||
"\xce\x9f" => "\xce\xbf", "\xce\xa0" => "\xcf\x80",
|
||||
"\xce\xa1" => "\xcf\x81", "\xce\xa3" => "\xcf\x83",
|
||||
"\xce\xa4" => "\xcf\x84", "\xce\xa5" => "\xcf\x85",
|
||||
"\xce\xa6" => "\xcf\x86", "\xce\xa7" => "\xcf\x87",
|
||||
"\xce\xa8" => "\xcf\x88", "\xce\xa9" => "\xcf\x89",
|
||||
"\xce\xaa" => "\xcf\x8a", "\xce\xab" => "\xcf\x8b",
|
||||
"\xce\xb0" => "\xcf\x85\xcc\x88\xcc\x81",
|
||||
## U+03c0
|
||||
"\xcf\x82" => "\xcf\x83", "\xcf\x90" => "\xce\xb2",
|
||||
"\xcf\x91" => "\xce\xb8", "\xcf\x95" => "\xcf\x86",
|
||||
"\xcf\x96" => "\xcf\x80", "\xcf\x98" => "\xcf\x99",
|
||||
"\xcf\x9a" => "\xcf\x9b", "\xcf\x9c" => "\xcf\x9d",
|
||||
"\xcf\x9e" => "\xcf\x9f", "\xcf\xa0" => "\xcf\xa1",
|
||||
"\xcf\xa2" => "\xcf\xa3", "\xcf\xa4" => "\xcf\xa5",
|
||||
"\xcf\xa6" => "\xcf\xa7", "\xcf\xa8" => "\xcf\xa9",
|
||||
"\xcf\xaa" => "\xcf\xab", "\xcf\xac" => "\xcf\xad",
|
||||
"\xcf\xae" => "\xcf\xaf", "\xcf\xb0" => "\xce\xba",
|
||||
"\xcf\xb1" => "\xcf\x81", "\xcf\xb4" => "\xce\xb8",
|
||||
"\xcf\xb5" => "\xce\xb5", "\xcf\xb7" => "\xcf\xb8",
|
||||
"\xcf\xb9" => "\xcf\xb2", "\xcf\xba" => "\xcf\xbb",
|
||||
"\xcf\xbd" => "\xcd\xbb", "\xcf\xbe" => "\xcd\xbc",
|
||||
"\xcf\xbf" => "\xcd\xbd",
|
||||
## U+0400
|
||||
"\xd0\x80" => "\xd1\x90", "\xd0\x81" => "\xd1\x91",
|
||||
"\xd0\x82" => "\xd1\x92", "\xd0\x83" => "\xd1\x93",
|
||||
"\xd0\x84" => "\xd1\x94", "\xd0\x85" => "\xd1\x95",
|
||||
"\xd0\x86" => "\xd1\x96", "\xd0\x87" => "\xd1\x97",
|
||||
"\xd0\x88" => "\xd1\x98", "\xd0\x89" => "\xd1\x99",
|
||||
"\xd0\x8a" => "\xd1\x9a", "\xd0\x8b" => "\xd1\x9b",
|
||||
"\xd0\x8c" => "\xd1\x9c", "\xd0\x8d" => "\xd1\x9d",
|
||||
"\xd0\x8e" => "\xd1\x9e", "\xd0\x8f" => "\xd1\x9f",
|
||||
"\xd0\x90" => "\xd0\xb0", "\xd0\x91" => "\xd0\xb1",
|
||||
"\xd0\x92" => "\xd0\xb2", "\xd0\x93" => "\xd0\xb3",
|
||||
"\xd0\x94" => "\xd0\xb4", "\xd0\x95" => "\xd0\xb5",
|
||||
"\xd0\x96" => "\xd0\xb6", "\xd0\x97" => "\xd0\xb7",
|
||||
"\xd0\x98" => "\xd0\xb8", "\xd0\x99" => "\xd0\xb9",
|
||||
"\xd0\x9a" => "\xd0\xba", "\xd0\x9b" => "\xd0\xbb",
|
||||
"\xd0\x9c" => "\xd0\xbc", "\xd0\x9d" => "\xd0\xbd",
|
||||
"\xd0\x9e" => "\xd0\xbe", "\xd0\x9f" => "\xd0\xbf",
|
||||
"\xd0\xa0" => "\xd1\x80", "\xd0\xa1" => "\xd1\x81",
|
||||
"\xd0\xa2" => "\xd1\x82", "\xd0\xa3" => "\xd1\x83",
|
||||
"\xd0\xa4" => "\xd1\x84", "\xd0\xa5" => "\xd1\x85",
|
||||
"\xd0\xa6" => "\xd1\x86", "\xd0\xa7" => "\xd1\x87",
|
||||
"\xd0\xa8" => "\xd1\x88", "\xd0\xa9" => "\xd1\x89",
|
||||
"\xd0\xaa" => "\xd1\x8a", "\xd0\xab" => "\xd1\x8b",
|
||||
"\xd0\xac" => "\xd1\x8c", "\xd0\xad" => "\xd1\x8d",
|
||||
"\xd0\xae" => "\xd1\x8e", "\xd0\xaf" => "\xd1\x8f",
|
||||
## U+0460
|
||||
"\xd1\xa0" => "\xd1\xa1", "\xd1\xa2" => "\xd1\xa3",
|
||||
"\xd1\xa4" => "\xd1\xa5", "\xd1\xa6" => "\xd1\xa7",
|
||||
"\xd1\xa8" => "\xd1\xa9", "\xd1\xaa" => "\xd1\xab",
|
||||
"\xd1\xac" => "\xd1\xad", "\xd1\xae" => "\xd1\xaf",
|
||||
"\xd1\xb0" => "\xd1\xb1", "\xd1\xb2" => "\xd1\xb3",
|
||||
"\xd1\xb4" => "\xd1\xb5", "\xd1\xb6" => "\xd1\xb7",
|
||||
"\xd1\xb8" => "\xd1\xb9", "\xd1\xba" => "\xd1\xbb",
|
||||
"\xd1\xbc" => "\xd1\xbd", "\xd1\xbe" => "\xd1\xbf",
|
||||
## U+0480
|
||||
"\xd2\x80" => "\xd2\x81", "\xd2\x8a" => "\xd2\x8b",
|
||||
"\xd2\x8c" => "\xd2\x8d", "\xd2\x8e" => "\xd2\x8f",
|
||||
"\xd2\x90" => "\xd2\x91", "\xd2\x92" => "\xd2\x93",
|
||||
"\xd2\x94" => "\xd2\x95", "\xd2\x96" => "\xd2\x97",
|
||||
"\xd2\x98" => "\xd2\x99", "\xd2\x9a" => "\xd2\x9b",
|
||||
"\xd2\x9c" => "\xd2\x9d", "\xd2\x9e" => "\xd2\x9f",
|
||||
"\xd2\xa0" => "\xd2\xa1", "\xd2\xa2" => "\xd2\xa3",
|
||||
"\xd2\xa4" => "\xd2\xa5", "\xd2\xa6" => "\xd2\xa7",
|
||||
"\xd2\xa8" => "\xd2\xa9", "\xd2\xaa" => "\xd2\xab",
|
||||
"\xd2\xac" => "\xd2\xad", "\xd2\xae" => "\xd2\xaf",
|
||||
"\xd2\xb0" => "\xd2\xb1", "\xd2\xb2" => "\xd2\xb3",
|
||||
"\xd2\xb4" => "\xd2\xb5", "\xd2\xb6" => "\xd2\xb7",
|
||||
"\xd2\xb8" => "\xd2\xb9", "\xd2\xba" => "\xd2\xbb",
|
||||
"\xd2\xbc" => "\xd2\xbd", "\xd2\xbe" => "\xd2\xbf",
|
||||
## U+04c0
|
||||
"\xd3\x80" => "\xd3\x8f", "\xd3\x81" => "\xd3\x82",
|
||||
"\xd3\x83" => "\xd3\x84", "\xd3\x85" => "\xd3\x86",
|
||||
"\xd3\x87" => "\xd3\x88", "\xd3\x89" => "\xd3\x8a",
|
||||
"\xd3\x8b" => "\xd3\x8c", "\xd3\x8d" => "\xd3\x8e",
|
||||
"\xd3\x90" => "\xd3\x91", "\xd3\x92" => "\xd3\x93",
|
||||
"\xd3\x94" => "\xd3\x95", "\xd3\x96" => "\xd3\x97",
|
||||
"\xd3\x98" => "\xd3\x99", "\xd3\x9a" => "\xd3\x9b",
|
||||
"\xd3\x9c" => "\xd3\x9d", "\xd3\x9e" => "\xd3\x9f",
|
||||
"\xd3\xa0" => "\xd3\xa1", "\xd3\xa2" => "\xd3\xa3",
|
||||
"\xd3\xa4" => "\xd3\xa5", "\xd3\xa6" => "\xd3\xa7",
|
||||
"\xd3\xa8" => "\xd3\xa9", "\xd3\xaa" => "\xd3\xab",
|
||||
"\xd3\xac" => "\xd3\xad", "\xd3\xae" => "\xd3\xaf",
|
||||
"\xd3\xb0" => "\xd3\xb1", "\xd3\xb2" => "\xd3\xb3",
|
||||
"\xd3\xb4" => "\xd3\xb5", "\xd3\xb6" => "\xd3\xb7",
|
||||
"\xd3\xb8" => "\xd3\xb9", "\xd3\xba" => "\xd3\xbb",
|
||||
"\xd3\xbc" => "\xd3\xbd", "\xd3\xbe" => "\xd3\xbf",
|
||||
## U+0500
|
||||
"\xd4\x80" => "\xd4\x81", "\xd4\x82" => "\xd4\x83",
|
||||
"\xd4\x84" => "\xd4\x85", "\xd4\x86" => "\xd4\x87",
|
||||
"\xd4\x88" => "\xd4\x89", "\xd4\x8a" => "\xd4\x8b",
|
||||
"\xd4\x8c" => "\xd4\x8d", "\xd4\x8e" => "\xd4\x8f",
|
||||
"\xd4\x90" => "\xd4\x91", "\xd4\x92" => "\xd4\x93",
|
||||
"\xd4\xb1" => "\xd5\xa1", "\xd4\xb2" => "\xd5\xa2",
|
||||
"\xd4\xb3" => "\xd5\xa3", "\xd4\xb4" => "\xd5\xa4",
|
||||
"\xd4\xb5" => "\xd5\xa5", "\xd4\xb6" => "\xd5\xa6",
|
||||
"\xd4\xb7" => "\xd5\xa7", "\xd4\xb8" => "\xd5\xa8",
|
||||
"\xd4\xb9" => "\xd5\xa9", "\xd4\xba" => "\xd5\xaa",
|
||||
"\xd4\xbb" => "\xd5\xab", "\xd4\xbc" => "\xd5\xac",
|
||||
"\xd4\xbd" => "\xd5\xad", "\xd4\xbe" => "\xd5\xae",
|
||||
"\xd4\xbf" => "\xd5\xaf",
|
||||
## U+0540
|
||||
"\xd5\x80" => "\xd5\xb0", "\xd5\x81" => "\xd5\xb1",
|
||||
"\xd5\x82" => "\xd5\xb2", "\xd5\x83" => "\xd5\xb3",
|
||||
"\xd5\x84" => "\xd5\xb4", "\xd5\x85" => "\xd5\xb5",
|
||||
"\xd5\x86" => "\xd5\xb6", "\xd5\x87" => "\xd5\xb7",
|
||||
"\xd5\x88" => "\xd5\xb8", "\xd5\x89" => "\xd5\xb9",
|
||||
"\xd5\x8a" => "\xd5\xba", "\xd5\x8b" => "\xd5\xbb",
|
||||
"\xd5\x8c" => "\xd5\xbc", "\xd5\x8d" => "\xd5\xbd",
|
||||
"\xd5\x8e" => "\xd5\xbe", "\xd5\x8f" => "\xd5\xbf",
|
||||
"\xd5\x90" => "\xd6\x80", "\xd5\x91" => "\xd6\x81",
|
||||
"\xd5\x92" => "\xd6\x82", "\xd5\x93" => "\xd6\x83",
|
||||
"\xd5\x94" => "\xd6\x84", "\xd5\x95" => "\xd6\x85",
|
||||
"\xd5\x96" => "\xd6\x86", "\xd6\x87" => "\xd5\xa5\xd6\x82"
|
||||
));
|
||||
Reference in New Issue
Block a user