1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/dokuwiki_ynh.git synced 2024-09-03 18:26:20 +02:00

first commit

This commit is contained in:
Adrien Beudin 2014-02-11 14:56:25 +01:00
commit 6762867dac
3580 changed files with 251063 additions and 0 deletions

16
conf/nginx.conf Normal file
View file

@ -0,0 +1,16 @@
location YNH_WWW_PATH {
alias YNH_WWW_ALIAS ;
if ($scheme = http) {
rewrite ^ https://$server_name$request_uri? permanent;
}
index index.php;
try_files $uri $uri/ index.php;
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param REMOTE_USER $remote_user;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}

38
manifest.json Normal file
View file

@ -0,0 +1,38 @@
{
"name": "Dokuwiki",
"id": "dokuwiki",
"description": {
"en": "DokuWiki is a simple to use and highly versatile Open Source wiki software that doesn't require a database"
},
"developer": {
"name": "loklin"
},
"multi_instance": "false",
"arguments": {
"install" : [
{
"name": "domain",
"ask": {
"en": "Choose a domain for DokuWiki"
},
"example": "domain.org"
},
{
"name": "path",
"ask": {
"en": "Choose a path for DokuWiki"
},
"example": "/DokuWiki",
"default": "/DokuWiki"
},
{
"name": "is_public",
"ask": {
"en": "Is it a public DokuWiki site ?"
},
"choices": ["Yes", "No"],
"default": "Yes"
}
]
}
}

40
scripts/install Executable file
View file

@ -0,0 +1,40 @@
#!/bin/bash
# Retrieve arguments
domain=$1
path=$2
is_public=$3
# Check domain/path availability
sudo yunohost app checkurl $domain$path -a dokuwiki
if [[ ! $? -eq 0 ]]; then
exit 1
fi
# Copy files to the right place
final_path=/var/www/dokuwiki
sudo mkdir -p $final_path
sudo cp -a ../sources/* $final_path
# Files owned by root, www-data can just read
sudo find $final_path -type f | xargs sudo chmod 644
sudo find $final_path -type d | xargs sudo chmod 755
sudo chown -R root: $final_path
# except for data, data/tmp and lib/plugin, where www-data must have write permissions
sudo chown www-data:root $final_path/{data,data/tmp,lib/plugins/}
sudo chmod 700 $final_path/{data,data/tmp,lib/plugins/}
# Modify Nginx configuration file and copy it to Nginx conf directory
sed -i "s@YNH_WWW_PATH@$path@g" ../conf/nginx.conf
sed -i "s@YNH_WWW_ALIAS@$final_path/@g" ../conf/nginx.conf
sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/dokuwiki.conf
if [ $is_public = "Yes" ];
then
sudo yunohost app setting dokuwiki skipped_uris -v "/"
fi
sudo service nginx reload
sudo yunohost app ssowatconf

6
scripts/remove Executable file
View file

@ -0,0 +1,6 @@
#!/bin/bash
domain=$(sudo yunohost app setting dokuwiki domain)
sudo rm -rf /var/www/dokuwiki
sudo rm -f /etc/nginx/conf.d/$domain.d/dokuwiki.conf

35
scripts/upgrade Normal file
View file

@ -0,0 +1,35 @@
#!/bin/bash
domain=$(sudo yunohost app setting dokuwiki domain)
path=$(sudo yunohost app setting dokuwiki path)
is_public=$(sudo yunohost app setting dokuwiki is_public)
# Remove trailing "/" for next commands
path=${path%/}
# Copy files to the right place
final_path=/var/www/dokuwiki
sudo mkdir -p $final_path
sudo cp -a ../sources/* $final_path
# Files owned by root, www-data can just read
sudo find $final_path -type f | xargs sudo chmod 644
sudo find $final_path -type d | xargs sudo chmod 755
sudo chown -R root: $final_path
# except for data and tmp subdir, where www-data must have write permissions
sudo chown www-data:root $final_path/{data,data/tmp,lib/plugins/}
sudo chmod 700 $final_path/{data,data/tmp,lib/plugins/}
# Modify Nginx configuration file and copy it to Nginx conf directory
sed -i "s@YNH_WWW_PATH@$path@g" ../conf/nginx.conf
sed -i "s@YNH_WWW_ALIAS@$final_path/@g" ../conf/nginx.conf
sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/dokuwiki.conf
if [ $is_public = "Yes" ];
then
sudo yunohost app setting dokuwiki skipped_uris -v "/"
fi
sudo service nginx reload
sudo yunohost app ssowatconf

35
sources/.htaccess.dist Normal file
View file

@ -0,0 +1,35 @@
## Enable this to restrict editing to logged in users only
## You should disable Indexes and MultiViews either here or in the
## global config. Symlinks maybe needed for URL rewriting.
#Options -Indexes -MultiViews +FollowSymLinks
## make sure nobody gets the htaccess, README, COPYING or VERSION files
<Files ~ "^([\._]ht|README$|VERSION$|COPYING$)">
Order allow,deny
Deny from all
</Files>
## Uncomment these rules if you want to have nice URLs using
## $conf['userewrite'] = 1 - not needed for rewrite mode 2
#RewriteEngine on
#
#RewriteRule ^_media/(.*) lib/exe/fetch.php?media=$1 [QSA,L]
#RewriteRule ^_detail/(.*) lib/exe/detail.php?media=$1 [QSA,L]
#RewriteRule ^_export/([^/]+)/(.*) doku.php?do=export_$1&id=$2 [QSA,L]
#RewriteRule ^$ doku.php [L]
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule (.*) doku.php?id=$1 [QSA,L]
#RewriteRule ^index.php$ doku.php
#
## Not all installations will require the following line. If you do,
## change "/dokuwiki" to the path to your dokuwiki directory relative
## to your document root.
#RewriteBase /dokuwiki
#
## If you enable DokuWikis XML-RPC interface, you should consider to
## restrict access to it over HTTPS only! Uncomment the following two
## rules if your server setup allows HTTPS.
#RewriteCond %{HTTPS} !=on
#RewriteRule ^lib/exe/xmlrpc.php$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301]

339
sources/COPYING Normal file
View file

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; 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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

10
sources/README Normal file
View file

@ -0,0 +1,10 @@
All documentation for DokuWiki is available online
at http://www.dokuwiki.org/
For Installation Instructions see
http://www.dokuwiki.org/install
DokuWiki - 2004-2013 (c) Andreas Gohr <andi@splitbrain.org>
and the DokuWiki Community
See COPYING and file headers for license info

1
sources/VERSION Normal file
View file

@ -0,0 +1 @@
2013-12-08 "Binky"

2
sources/bin/.htaccess Normal file
View file

@ -0,0 +1,2 @@
order allow,deny
deny from all

378
sources/bin/dwpage.php Executable file
View file

@ -0,0 +1,378 @@
#!/usr/bin/php
<?php
#------------------------------------------------------------------------------
if ('cli' != php_sapi_name()) die();
ini_set('memory_limit','128M');
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');
require_once DOKU_INC.'inc/init.php';
require_once DOKU_INC.'inc/common.php';
require_once DOKU_INC.'inc/cliopts.php';
#------------------------------------------------------------------------------
function usage($action) {
switch ( $action ) {
case 'checkout':
print "Usage: dwpage.php [opts] checkout <wiki:page> [working_file]
Checks out a file from the repository, using the wiki id and obtaining
a lock for the page.
If a working_file is specified, this is where the page is copied to.
Otherwise defaults to the same as the wiki page in the current
working directory.
EXAMPLE
$ ./dwpage.php checkout wiki:syntax ./new_syntax.txt
OPTIONS
-h, --help=<action>: get help
-f: force obtaining a lock for the page (generally bad idea)
";
break;
case 'commit':
print "Usage: dwpage.php [opts] -m \"Msg\" commit <working_file> <wiki:page>
Checks in the working_file into the repository using the specified
wiki id, archiving the previous version.
EXAMPLE
$ ./dwpage.php -m \"Some message\" commit ./new_syntax.txt wiki:syntax
OPTIONS
-h, --help=<action>: get help
-f: force obtaining a lock for the page (generally bad idea)
-t, trivial: minor change
-m (required): Summary message describing the change
";
break;
case 'lock':
print "Usage: dwpage.php [opts] lock <wiki:page>
Obtains or updates a lock for a wiki page
EXAMPLE
$ ./dwpage.php lock wiki:syntax
OPTIONS
-h, --help=<action>: get help
-f: force obtaining a lock for the page (generally bad idea)
";
break;
case 'unlock':
print "Usage: dwpage.php [opts] unlock <wiki:page>
Removes a lock for a wiki page.
EXAMPLE
$ ./dwpage.php unlock wiki:syntax
OPTIONS
-h, --help=<action>: get help
-f: force obtaining a lock for the page (generally bad idea)
";
break;
default:
print "Usage: dwpage.php [opts] <action>
Utility to help command line Dokuwiki page editing, allow
pages to be checked out for editing then committed after changes
Normal operation would be;
ACTIONS
checkout: see $ dwpage.php --help=checkout
commit: see $ dwpage.php --help=commit
lock: see $ dwpage.php --help=lock
OPTIONS
-h, --help=<action>: get help
e.g. $ ./dwpage.php -hcommit
e.g. $ ./dwpage.php --help=commit
";
break;
}
}
#------------------------------------------------------------------------------
function getUser() {
$user = getenv('USER');
if (empty ($user)) {
$user = getenv('USERNAME');
} else {
return $user;
}
if (empty ($user)) {
$user = 'admin';
}
return $user;
}
#------------------------------------------------------------------------------
function getSuppliedArgument($OPTS, $short, $long) {
$arg = $OPTS->get($short);
if ( is_null($arg) ) {
$arg = $OPTS->get($long);
}
return $arg;
}
#------------------------------------------------------------------------------
function obtainLock($WIKI_ID) {
global $USERNAME;
if ( !file_exists(wikiFN($WIKI_ID)) ) {
fwrite( STDERR, "$WIKI_ID does not yet exist\n");
}
$_SERVER['REMOTE_USER'] = $USERNAME;
if ( checklock($WIKI_ID) ) {
fwrite( STDERR, "Page $WIKI_ID is already locked by another user\n");
exit(1);
}
lock($WIKI_ID);
$_SERVER['REMOTE_USER'] = '_'.$USERNAME.'_';
if ( checklock($WIKI_ID) != $USERNAME ) {
fwrite( STDERR, "Unable to obtain lock for $WIKI_ID\n" );
exit(1);
}
}
#------------------------------------------------------------------------------
function clearLock($WIKI_ID) {
global $USERNAME ;
if ( !file_exists(wikiFN($WIKI_ID)) ) {
fwrite( STDERR, "$WIKI_ID does not yet exist\n");
}
$_SERVER['REMOTE_USER'] = $USERNAME;
if ( checklock($WIKI_ID) ) {
fwrite( STDERR, "Page $WIKI_ID is locked by another user\n");
exit(1);
}
unlock($WIKI_ID);
if ( file_exists(wikiLockFN($WIKI_ID)) ) {
fwrite( STDERR, "Unable to clear lock for $WIKI_ID\n" );
exit(1);
}
}
#------------------------------------------------------------------------------
function deleteLock($WIKI_ID) {
$wikiLockFN = wikiLockFN($WIKI_ID);
if ( file_exists($wikiLockFN) ) {
if ( !unlink($wikiLockFN) ) {
fwrite( STDERR, "Unable to delete $wikiLockFN\n" );
exit(1);
}
}
}
#------------------------------------------------------------------------------
$USERNAME = getUser();
$CWD = getcwd();
$SYSTEM_ID = '127.0.0.1';
#------------------------------------------------------------------------------
$OPTS = Doku_Cli_Opts::getOptions(
__FILE__,
'h::fm:u:s:t',
array(
'help==',
'user=',
'system=',
'trivial',
)
);
if ( $OPTS->isError() ) {
print $OPTS->getMessage()."\n";
exit(1);
}
if ( $OPTS->has('h') or $OPTS->has('help') or !$OPTS->hasArgs() ) {
usage(getSuppliedArgument($OPTS,'h','help'));
exit(0);
}
if ( $OPTS->has('u') or $OPTS->has('user') ) {
$USERNAME = getSuppliedArgument($OPTS,'u','user');
}
if ( $OPTS->has('s') or $OPTS->has('system') ) {
$SYSTEM_ID = getSuppliedArgument($OPTS,'s','system');
}
#------------------------------------------------------------------------------
switch ( $OPTS->arg(0) ) {
#----------------------------------------------------------------------
case 'checkout':
$WIKI_ID = $OPTS->arg(1);
if ( !$WIKI_ID ) {
fwrite( STDERR, "Wiki page ID required\n");
exit(1);
}
$WIKI_FN = wikiFN($WIKI_ID);
if ( !file_exists($WIKI_FN) ) {
fwrite( STDERR, "$WIKI_ID does not yet exist\n");
exit(1);
}
$TARGET_FN = $OPTS->arg(2);
if ( empty($TARGET_FN) ) {
$TARGET_FN = getcwd().'/'.utf8_basename($WIKI_FN);
}
if ( !file_exists(dirname($TARGET_FN)) ) {
fwrite( STDERR, "Directory ".dirname($TARGET_FN)." does not exist\n");
exit(1);
}
if ( stristr( realpath(dirname($TARGET_FN)), realpath($conf['datadir']) ) !== false ) {
fwrite( STDERR, "Attempt to check out file into data directory - not allowed\n");
exit(1);
}
if ( $OPTS->has('f') ) {
deleteLock($WIKI_ID);
}
obtainLock($WIKI_ID);
# Need to lock the file first?
if ( !copy($WIKI_FN, $TARGET_FN) ) {
fwrite( STDERR, "Unable to copy $WIKI_FN to $TARGET_FN\n");
clearLock($WIKI_ID);
exit(1);
}
print "$WIKI_ID > $TARGET_FN\n";
exit(0);
break;
#----------------------------------------------------------------------
case 'commit':
$TARGET_FN = $OPTS->arg(1);
if ( !$TARGET_FN ) {
fwrite( STDERR, "Target filename required\n");
exit(1);
}
if ( !file_exists($TARGET_FN) ) {
fwrite( STDERR, "$TARGET_FN does not exist\n");
exit(1);
}
if ( !is_readable($TARGET_FN) ) {
fwrite( STDERR, "Cannot read from $TARGET_FN\n");
exit(1);
}
$WIKI_ID = $OPTS->arg(2);
if ( !$WIKI_ID ) {
fwrite( STDERR, "Wiki page ID required\n");
exit(1);
}
if ( !$OPTS->has('m') ) {
fwrite( STDERR, "Summary message required\n");
exit(1);
}
if ( $OPTS->has('f') ) {
deleteLock($WIKI_ID);
}
$_SERVER['REMOTE_USER'] = $USERNAME;
if ( checklock($WIKI_ID) ) {
fwrite( STDERR, "$WIKI_ID is locked by another user\n");
exit(1);
}
obtainLock($WIKI_ID);
saveWikiText($WIKI_ID, file_get_contents($TARGET_FN), $OPTS->get('m'), $OPTS->has('t'));
clearLock($WIKI_ID);
exit(0);
break;
#----------------------------------------------------------------------
case 'lock':
$WIKI_ID = $OPTS->arg(1);
if ( !$WIKI_ID ) {
fwrite( STDERR, "Wiki page ID required\n");
exit(1);
}
if ( $OPTS->has('f') ) {
deleteLock($WIKI_ID);
}
obtainLock($WIKI_ID);
print "Locked : $WIKI_ID\n";
exit(0);
break;
#----------------------------------------------------------------------
case 'unlock':
$WIKI_ID = $OPTS->arg(1);
if ( !$WIKI_ID ) {
fwrite( STDERR, "Wiki page ID required\n");
exit(1);
}
if ( $OPTS->has('f') ) {
deleteLock($WIKI_ID);
} else {
clearLock($WIKI_ID);
}
print "Unlocked : $WIKI_ID\n";
exit(0);
break;
#----------------------------------------------------------------------
default:
fwrite( STDERR, "Invalid action ".$OPTS->arg(0)."\n" );
exit(1);
break;
}

98
sources/bin/indexer.php Executable file
View file

@ -0,0 +1,98 @@
#!/usr/bin/php
<?php
if ('cli' != php_sapi_name()) die();
ini_set('memory_limit','128M');
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');
require_once(DOKU_INC.'inc/init.php');
require_once(DOKU_INC.'inc/cliopts.php');
session_write_close();
// handle options
$short_opts = 'hcuq';
$long_opts = array('help', 'clear', 'update', 'quiet');
$OPTS = Doku_Cli_Opts::getOptions(__FILE__,$short_opts,$long_opts);
if ( $OPTS->isError() ) {
fwrite( STDERR, $OPTS->getMessage() . "\n");
_usage();
exit(1);
}
$CLEAR = false;
$QUIET = false;
$INDEXER = null;
foreach ($OPTS->options as $key => $val) {
switch ($key) {
case 'h':
case 'help':
_usage();
exit;
case 'c':
case 'clear':
$CLEAR = true;
break;
case 'q':
case 'quiet':
$QUIET = true;
break;
}
}
#------------------------------------------------------------------------------
# Action
if($CLEAR) _clearindex();
_update();
#------------------------------------------------------------------------------
function _usage() {
print "Usage: indexer.php <options>
Updates the searchindex by indexing all new or changed pages
when the -c option is given the index is cleared first.
OPTIONS
-h, --help show this help and exit
-c, --clear clear the index before updating
-q, --quiet don't produce any output
";
}
function _update(){
global $conf;
$data = array();
_quietecho("Searching pages... ");
search($data,$conf['datadir'],'search_allpages',array('skipacl' => true));
_quietecho(count($data)." pages found.\n");
foreach($data as $val){
_index($val['id']);
}
}
function _index($id){
global $CLEAR;
global $QUIET;
_quietecho("$id... ");
idx_addPage($id, !$QUIET, $CLEAR);
_quietecho("done.\n");
}
/**
* Clear all index files
*/
function _clearindex(){
_quietecho("Clearing index... ");
idx_get_indexer()->clear();
_quietecho("done.\n");
}
function _quietecho($msg) {
global $QUIET;
if(!$QUIET) echo $msg;
}
//Setup VIM: ex: et ts=2 :

67
sources/bin/render.php Executable file
View file

@ -0,0 +1,67 @@
#!/usr/bin/php
<?php
/**
* A simple commandline tool to render some DokuWiki syntax with a given
* renderer.
*
* This may not work for plugins that expect a certain environment to be
* set up before rendering, but should work for most or even all standard
* DokuWiki markup
*
* @license GPL2
* @author Andreas Gohr <andi@splitbrain.org>
*/
if ('cli' != php_sapi_name()) die();
ini_set('memory_limit','128M');
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');
define('NOSESSION',1);
require_once(DOKU_INC.'inc/init.php');
require_once(DOKU_INC.'inc/common.php');
require_once(DOKU_INC.'inc/parserutils.php');
require_once(DOKU_INC.'inc/cliopts.php');
// handle options
$short_opts = 'hr:';
$long_opts = array('help','renderer:');
$OPTS = Doku_Cli_Opts::getOptions(__FILE__,$short_opts,$long_opts);
if ( $OPTS->isError() ) {
fwrite( STDERR, $OPTS->getMessage() . "\n");
_usage();
exit(1);
}
$RENDERER = 'xhtml';
foreach ($OPTS->options as $key => $val) {
switch ($key) {
case 'h':
case 'help':
_usage();
exit;
case 'r':
case 'renderer':
$RENDERER = $val;
}
}
// do the action
$source = stream_get_contents(STDIN);
$info = array();
$result = p_render($RENDERER,p_get_instructions($source),$info);
if(is_null($result)) die("No such renderer $RENDERER\n");
echo $result;
/**
* Print usage info
*/
function _usage(){
print "Usage: render.php <options>
Reads DokuWiki syntax from STDIN and renders it with the given renderer
to STDOUT
OPTIONS
-h, --help show this help and exit
-r, --renderer <renderer> the render mode (default: xhtml)
";
}

148
sources/bin/striplangs.php Executable file
View file

@ -0,0 +1,148 @@
#!/usr/bin/php
<?php
/**
* Strip unwanted languages from the DokuWiki install
*
* @author Martin 'E.T.' Misuth <et.github@ethome.sk>
*/
if ('cli' != php_sapi_name()) die();
#------------------------------------------------------------------------------
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');
require_once DOKU_INC.'inc/cliopts.php';
#------------------------------------------------------------------------------
function usage($show_examples = false) {
print "Usage: striplangs.php [-h [-x]] [-e] [-k lang1[,lang2]..[,langN]]
Removes all languages from the instalation, besides the ones
after the -k option. English language is never removed!
OPTIONS
-h, --help get this help
-x, --examples get also usage examples
-k, --keep comma separated list of languages, -e is always implied
-e, --english keeps english, dummy to use without -k\n";
if ( $show_examples ) {
print "\n
EXAMPLES
Strips all languages, but keeps 'en' and 'de':
striplangs -k de
Strips all but 'en','ca-valencia','cs','de','is','sk':
striplangs --keep ca-valencia,cs,de,is,sk
Strips all but 'en':
striplangs -e
No option specified, prints usage and throws error:
striplangs\n";
}
}
function getSuppliedArgument($OPTS, $short, $long) {
$arg = $OPTS->get($short);
if ( is_null($arg) ) {
$arg = $OPTS->get($long);
}
return $arg;
}
function processPlugins($path, $keep_langs) {
if (is_dir($path)) {
$entries = scandir($path);
foreach ($entries as $entry) {
if ($entry != "." && $entry != "..") {
if ( is_dir($path.'/'.$entry) ) {
$plugin_langs = $path.'/'.$entry.'/lang';
if ( is_dir( $plugin_langs ) ) {
stripDirLangs($plugin_langs, $keep_langs);
}
}
}
}
}
}
function stripDirLangs($path, $keep_langs) {
$dir = dir($path);
while(($cur_dir = $dir->read()) !== false) {
if( $cur_dir != '.' and $cur_dir != '..' and is_dir($path.'/'.$cur_dir)) {
if ( !in_array($cur_dir, $keep_langs, true ) ) {
killDir($path.'/'.$cur_dir);
}
}
}
$dir->close();
}
function killDir($dir) {
if (is_dir($dir)) {
$entries = scandir($dir);
foreach ($entries as $entry) {
if ($entry != "." && $entry != "..") {
if ( is_dir($dir.'/'.$entry) ) {
killDir($dir.'/'.$entry);
} else {
unlink($dir.'/'.$entry);
}
}
}
reset($entries);
rmdir($dir);
}
}
#------------------------------------------------------------------------------
// handle options
$short_opts = 'hxk:e';
$long_opts = array('help', 'examples', 'keep=','english');
$OPTS = Doku_Cli_Opts::getOptions(__FILE__, $short_opts, $long_opts);
if ( $OPTS->isError() ) {
fwrite( STDERR, $OPTS->getMessage() . "\n");
exit(1);
}
// handle '--examples' option
$show_examples = ( $OPTS->has('x') or $OPTS->has('examples') ) ? true : false;
// handle '--help' option
if ( $OPTS->has('h') or $OPTS->has('help') ) {
usage($show_examples);
exit(0);
}
// handle both '--keep' and '--english' options
if ( $OPTS->has('k') or $OPTS->has('keep') ) {
$preserved_langs = getSuppliedArgument($OPTS,'k','keep');
$langs = explode(',', $preserved_langs);
// ! always enforce 'en' lang when using '--keep' (DW relies on it)
if ( !isset($langs['en']) ) {
$langs[]='en';
}
} elseif ( $OPTS->has('e') or $OPTS->has('english') ) {
// '--english' was specified strip everything besides 'en'
$langs = array ('en');
} else {
// no option was specified, print usage but don't do anything as
// this run might not be intented
usage();
print "\n
ERROR
No option specified, use either -h -x to get more info,
or -e to strip every language besides english.\n";
exit(1);
}
// Kill all language directories in /inc/lang and /lib/plugins besides those in $langs array
stripDirLangs(realpath(dirname(__FILE__).'/../inc/lang'), $langs);
processPlugins(realpath(dirname(__FILE__).'/../lib/plugins'), $langs);

134
sources/bin/wantedpages.php Executable file
View file

@ -0,0 +1,134 @@
#!/usr/bin/php
<?php
if ('cli' != php_sapi_name()) die();
#------------------------------------------------------------------------------
ini_set('memory_limit','128M');
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');
require_once DOKU_INC.'inc/init.php';
require_once DOKU_INC.'inc/common.php';
require_once DOKU_INC.'inc/search.php';
require_once DOKU_INC.'inc/cliopts.php';
#------------------------------------------------------------------------------
function usage() {
print "Usage: wantedpages.php [wiki:namespace]
Outputs a list of wanted pages (pages which have
internal links but do not yet exist).
If the optional [wiki:namespace] is not provided,
defaults to the root wiki namespace
OPTIONS
-h, --help get help
";
}
#------------------------------------------------------------------------------
define ('DW_DIR_CONTINUE',1);
define ('DW_DIR_NS',2);
define ('DW_DIR_PAGE',3);
#------------------------------------------------------------------------------
function dw_dir_filter($entry, $basepath) {
if ($entry == '.' || $entry == '..' ) {
return DW_DIR_CONTINUE;
}
if ( is_dir($basepath . '/' . $entry) ) {
if ( strpos($entry, '_') === 0 ) {
return DW_DIR_CONTINUE;
}
return DW_DIR_NS;
}
if ( preg_match('/\.txt$/',$entry) ) {
return DW_DIR_PAGE;
}
return DW_DIR_CONTINUE;
}
#------------------------------------------------------------------------------
function dw_get_pages($dir) {
static $trunclen = null;
if ( !$trunclen ) {
global $conf;
$trunclen = strlen($conf['datadir'].':');
}
if ( !is_dir($dir) ) {
fwrite( STDERR, "Unable to read directory $dir\n");
exit(1);
}
$pages = array();
$dh = opendir($dir);
while ( false !== ( $entry = readdir($dh) ) ) {
$status = dw_dir_filter($entry, $dir);
if ( $status == DW_DIR_CONTINUE ) {
continue;
} else if ( $status == DW_DIR_NS ) {
$pages = array_merge($pages, dw_get_pages($dir . '/' . $entry));
} else {
$page = array(
'id' => pathID(substr($dir.'/'.$entry,$trunclen)),
'file'=> $dir.'/'.$entry,
);
$pages[] = $page;
}
}
closedir($dh);
return $pages;
}
#------------------------------------------------------------------------------
function dw_internal_links($page) {
global $conf;
$instructions = p_get_instructions(file_get_contents($page['file']));
$links = array();
$cns = getNS($page['id']);
$exists = false;
foreach($instructions as $ins){
if($ins[0] == 'internallink' || ($conf['camelcase'] && $ins[0] == 'camelcaselink') ){
$mid = $ins[1][0];
resolve_pageid($cns,$mid,$exists);
if ( !$exists ) {
list($mid) = explode('#',$mid); //record pages without hashs
$links[] = $mid;
}
}
}
return $links;
}
#------------------------------------------------------------------------------
$OPTS = Doku_Cli_Opts::getOptions(__FILE__,'h',array('help'));
if ( $OPTS->isError() ) {
fwrite( STDERR, $OPTS->getMessage() . "\n");
exit(1);
}
if ( $OPTS->has('h') or $OPTS->has('help') ) {
usage();
exit(0);
}
$START_DIR = $conf['datadir'];
if ( $OPTS->numArgs() == 1 ) {
$START_DIR .= '/' . $OPTS->arg(0);
}
#------------------------------------------------------------------------------
$WANTED_PAGES = array();
foreach ( dw_get_pages($START_DIR) as $WIKI_PAGE ) {
$WANTED_PAGES = array_merge($WANTED_PAGES,dw_internal_links($WIKI_PAGE));
}
$WANTED_PAGES = array_unique($WANTED_PAGES);
sort($WANTED_PAGES);
foreach ( $WANTED_PAGES as $WANTED_PAGE ) {
print $WANTED_PAGE."\n";
}
exit(0);

3
sources/conf/.htaccess Normal file
View file

@ -0,0 +1,3 @@
## no access to the conf directory
order allow,deny
deny from all

View file

@ -0,0 +1,21 @@
# acl.auth.php
# <?php exit()?>
# Don't modify the lines above
#
# Access Control Lists
#
# Editing this file by hand shouldn't be necessary. Use the ACL
# Manager interface instead.
#
# If your auth backend allows special char like spaces in groups
# or user names you need to urlencode them (only chars <128, leave
# UTF-8 multibyte chars as is)
#
# none 0
# read 1
# edit 2
# create 4
# upload 8
# delete 16
* @ALL 8

View file

@ -0,0 +1,61 @@
# Acronyms.
ACL Access Control List
AFAICS As far as I can see
AFAIK As far as I know
AFAIR As far as I remember
API Application Programming Interface
ASAP As soon as possible
ASCII American Standard Code for Information Interchange
BTW By the way
CMS Content Management System
CSS Cascading Style Sheets
DNS Domain Name System
EOF End of file
EOL End of line
EOM End of message
EOT End of text
FAQ Frequently Asked Questions
FTP File Transfer Protocol
FOSS Free & Open-Source Software
FLOSS Free/Libre and Open Source Software
FUD Fear, Uncertainty, and Doubt
GB Gigabyte
GHz Gigahertz
GPL GNU General Public License
GUI Graphical User Interface
HTML HyperText Markup Language
IANAL I am not a lawyer (but)
IE Internet Explorer
IIRC If I remember correctly
IMHO In my humble opinion
IMO In my opinion
IOW In other words
IRC Internet Relay Chat
IRL In real life
KISS Keep it simple stupid
LAN Local Area Network
LGPL GNU Lesser General Public License
LOL Laughing out loud
MathML Mathematical Markup Language
MB Megabyte
MHz Megahertz
MSIE Microsoft Internet Explorer
OMG Oh my God
OS Operating System
OSS Open Source Software
OTOH On the other hand
PITA Pain in the Ass
RFC Request for Comments
ROTFL Rolling on the floor laughing
RTFM Read The Fine Manual
spec specification
TIA Thanks in advance
TL;DR Too long; didn't read
TOC Table of Contents
URI Uniform Resource Identifier
URL Uniform Resource Locator
W3C World Wide Web Consortium
WTF? What the f***
WYSIWYG What You See Is What You Get
YMMV Your mileage may vary

176
sources/conf/dokuwiki.php Normal file
View file

@ -0,0 +1,176 @@
<?php
/**
* This is DokuWiki's Main Configuration file
*
* All the default values are kept here, you should not modify it but use
* a local.php file instead to override the settings from here.
*
* This is a piece of PHP code so PHP syntax applies!
*
* For help with the configuration and a more detailed explanation of the various options
* see http://www.dokuwiki.org/config
*/
/* Basic Settings */
$conf['title'] = 'DokuWiki'; //what to show in the title
$conf['start'] = 'start'; //name of start page
$conf['lang'] = 'en'; //your language
$conf['template'] = 'dokuwiki'; //see lib/tpl directory
$conf['tagline'] = ''; //tagline in header (if template supports it)
$conf['sidebar'] = 'sidebar'; //name of sidebar in root namespace (if template supports it)
$conf['license'] = 'cc-by-nc-sa'; //see conf/license.php
$conf['savedir'] = './data'; //where to store all the files
$conf['basedir'] = ''; //absolute dir from serveroot - blank for autodetection
$conf['baseurl'] = ''; //URL to server including protocol - blank for autodetect
$conf['cookiedir'] = ''; //path to use in cookies - blank for basedir
$conf['dmode'] = 0755; //set directory creation mode
$conf['fmode'] = 0644; //set file creation mode
$conf['allowdebug'] = 0; //allow debug output, enable if needed 0|1
/* Display Settings */
$conf['recent'] = 20; //how many entries to show in recent
$conf['recent_days'] = 7; //How many days of recent changes to keep. (days)
$conf['breadcrumbs'] = 10; //how many recent visited pages to show
$conf['youarehere'] = 0; //show "You are here" navigation? 0|1
$conf['fullpath'] = 0; //show full path of the document or relative to datadir only? 0|1
$conf['typography'] = 1; //smartquote conversion 0=off, 1=doublequotes, 2=all quotes
$conf['dformat'] = '%Y/%m/%d %H:%M'; //dateformat accepted by PHPs strftime() function
$conf['signature'] = ' --- //[[@MAIL@|@NAME@]] @DATE@//'; //signature see wiki page for details
$conf['showuseras'] = 'loginname'; // 'loginname' users login name
// 'username' users full name
// 'email' e-mail address (will be obfuscated as per mailguard)
// 'email_link' e-mail address as a mailto: link (obfuscated)
$conf['toptoclevel'] = 1; //Level starting with and below to include in AutoTOC (max. 5)
$conf['tocminheads'] = 3; //Minimum amount of headlines that determines if a TOC is built
$conf['maxtoclevel'] = 3; //Up to which level include into AutoTOC (max. 5)
$conf['maxseclevel'] = 3; //Up to which level create editable sections (max. 5)
$conf['camelcase'] = 0; //Use CamelCase for linking? (I don't like it) 0|1
$conf['deaccent'] = 1; //deaccented chars in pagenames (1) or romanize (2) or keep (0)?
$conf['useheading'] = 0; //use the first heading in a page as its name
$conf['sneaky_index']= 0; //check for namespace read permission in index view (0|1) (1 might cause unexpected behavior)
$conf['hidepages'] = ''; //Regexp for pages to be skipped from RSS, Search and Recent Changes
/* Authentication Settings */
$conf['useacl'] = 0; //Use Access Control Lists to restrict access?
$conf['autopasswd'] = 1; //autogenerate passwords and email them to user
$conf['authtype'] = 'authplain'; //which authentication backend should be used
$conf['passcrypt'] = 'smd5'; //Used crypt method (smd5,md5,sha1,ssha,crypt,mysql,my411)
$conf['defaultgroup']= 'user'; //Default groups new Users are added to
$conf['superuser'] = '!!not set!!'; //The admin can be user or @group or comma separated list user1,@group1,user2
$conf['manager'] = '!!not set!!'; //The manager can be user or @group or comma separated list user1,@group1,user2
$conf['profileconfirm'] = 1; //Require current password to confirm changes to user profile
$conf['rememberme'] = 1; //Enable/disable remember me on login
$conf['disableactions'] = ''; //comma separated list of actions to disable
$conf['auth_security_timeout'] = 900; //time (seconds) auth data is considered valid, set to 0 to recheck on every page view
$conf['securecookie'] = 1; //never send HTTPS cookies via HTTP
$conf['remote'] = 0; //Enable/disable remote interfaces
$conf['remoteuser'] = '!!not set !!'; //user/groups that have access to remote interface (comma separated)
/* Antispam Features */
$conf['usewordblock']= 1; //block spam based on words? 0|1
$conf['relnofollow'] = 1; //use rel="nofollow" for external links?
$conf['indexdelay'] = 60*60*24*5; //allow indexing after this time (seconds) default is 5 days
$conf['mailguard'] = 'hex'; //obfuscate email addresses against spam harvesters?
//valid entries are:
// 'visible' - replace @ with [at], . with [dot] and - with [dash]
// 'hex' - use hex entities to encode the mail address
// 'none' - do not obfuscate addresses
$conf['iexssprotect']= 1; // check for JavaScript and HTML in uploaded files 0|1
/* Editing Settings */
$conf['usedraft'] = 1; //automatically save a draft while editing (0|1)
$conf['htmlok'] = 0; //may raw HTML be embedded? This may break layout and XHTML validity 0|1
$conf['phpok'] = 0; //may PHP code be embedded? Never do this on the internet! 0|1
$conf['locktime'] = 15*60; //maximum age for lockfiles (defaults to 15 minutes)
$conf['cachetime'] = 60*60*24; //maximum age for cachefile in seconds (defaults to a day)
/* Link Settings */
// Set target to use when creating links - leave empty for same window
$conf['target']['wiki'] = '';
$conf['target']['interwiki'] = '';
$conf['target']['extern'] = '';
$conf['target']['media'] = '';
$conf['target']['windows'] = '';
/* Media Settings */
$conf['mediarevisions'] = 1; //enable/disable media revisions
$conf['refcheck'] = 1; //check for references before deleting media files
$conf['gdlib'] = 2; //the GDlib version (0, 1 or 2) 2 tries to autodetect
$conf['im_convert'] = ''; //path to ImageMagicks convert (will be used instead of GD)
$conf['jpg_quality'] = '70'; //quality of compression when scaling jpg images (0-100)
$conf['fetchsize'] = 0; //maximum size (bytes) fetch.php may download from extern, disabled by default
/* Notification Settings */
$conf['subscribers'] = 0; //enable change notice subscription support
$conf['subscribe_time'] = 24*60*60; //Time after which digests / lists are sent (in sec, default 1 day)
//Should be smaller than the time specified in recent_days
$conf['notify'] = ''; //send change info to this email (leave blank for nobody)
$conf['registernotify'] = ''; //send info about newly registered users to this email (leave blank for nobody)
$conf['mailfrom'] = ''; //use this email when sending mails
$conf['mailprefix'] = ''; //use this as prefix of outgoing mails
$conf['htmlmail'] = 1; //send HTML multipart mails
/* Syndication Settings */
$conf['sitemap'] = 0; //Create a google sitemap? How often? In days.
$conf['rss_type'] = 'rss1'; //type of RSS feed to provide, by default:
// 'rss' - RSS 0.91
// 'rss1' - RSS 1.0
// 'rss2' - RSS 2.0
// 'atom' - Atom 0.3
// 'atom1' - Atom 1.0
$conf['rss_linkto'] = 'diff'; //what page RSS entries link to:
// 'diff' - page showing revision differences
// 'page' - the revised page itself
// 'rev' - page showing all revisions
// 'current' - most recent revision of page
$conf['rss_content'] = 'abstract'; //what to put in the items by default?
// 'abstract' - plain text, first paragraph or so
// 'diff' - plain text unified diff wrapped in <pre> tags
// 'htmldiff' - diff as HTML table
// 'html' - the full page rendered in XHTML
$conf['rss_media'] = 'both'; //what should be listed?
// 'both' - page and media changes
// 'pages' - page changes only
// 'media' - media changes only
$conf['rss_update'] = 5*60; //Update the RSS feed every n seconds (defaults to 5 minutes)
$conf['rss_show_summary'] = 1; //Add revision summary to title? 0|1
/* Advanced Settings */
$conf['updatecheck'] = 1; //automatically check for new releases?
$conf['userewrite'] = 0; //this makes nice URLs: 0: off 1: .htaccess 2: internal
$conf['useslash'] = 0; //use slash instead of colon? only when rewrite is on
$conf['sepchar'] = '_'; //word separator character in page names; may be a
// letter, a digit, '_', '-', or '.'.
$conf['canonical'] = 0; //Should all URLs use full canonical http://... style?
$conf['fnencode'] = 'url'; //encode filenames (url|safe|utf-8)
$conf['autoplural'] = 0; //try (non)plural form of nonexisting files?
$conf['compression'] = 'gz'; //compress old revisions: (0: off) ('gz': gnuzip) ('bz2': bzip)
// bz2 generates smaller files, but needs more cpu-power
$conf['gzip_output'] = 0; //use gzip content encodeing for the output xhtml (if allowed by browser)
$conf['compress'] = 1; //Strip whitespaces and comments from Styles and JavaScript? 1|0
$conf['cssdatauri'] = 0; //Maximum byte size of small images to embed into CSS, won't work on IE<8
$conf['send404'] = 0; //Send a HTTP 404 status for non existing pages?
$conf['broken_iua'] = 0; //Platform with broken ignore_user_abort (IIS+CGI) 0|1
$conf['xsendfile'] = 0; //Use X-Sendfile (1 = lighttpd, 2 = standard)
$conf['renderer_xhtml'] = 'xhtml'; //renderer to use for main page generation
$conf['readdircache'] = 0; //time cache in second for the readdir operation, 0 to deactivate.
/* Network Settings */
$conf['dnslookups'] = 1; //disable to disallow IP to hostname lookups
// Proxy setup - if your Server needs a proxy to access the web set these
$conf['proxy']['host'] = '';
$conf['proxy']['port'] = '';
$conf['proxy']['user'] = '';
$conf['proxy']['pass'] = '';
$conf['proxy']['ssl'] = 0;
$conf['proxy']['except'] = '';
// Safemode Hack - read http://www.dokuwiki.org/config:safemodehack !
$conf['safemodehack'] = 0;
$conf['ftp']['host'] = 'localhost';
$conf['ftp']['port'] = '21';
$conf['ftp']['user'] = 'user';
$conf['ftp']['pass'] = 'password';
$conf['ftp']['root'] = '/home/user/htdocs';

View file

@ -0,0 +1,22 @@
# Typography replacements
#
# Order does matter!
#
# You can use HTML entities here, but it is not recomended because it may break
# non-HTML renderers. Use UTF-8 chars directly instead.
<-> ↔
-> →
<- ←
<=> ⇔
=> ⇒
<= ⇐
>> »
<< «
--- —
--
(c) ©
(tm) ™
(r) ®
... …

View file

@ -0,0 +1,36 @@
# Each URL may contain one of the placeholders {URL} or {NAME}
# {URL} is replaced by the URL encoded representation of the wikiname
# this is the right thing to do in most cases
# {NAME} this is replaced by the wikiname as given in the document
# no further encoding is done
# If no placeholder is defined the urlencoded name is appended to the URL
# To prevent losing your added InterWiki shortcuts after an upgrade,
# you should add new ones to interwiki.local.conf
wp http://en.wikipedia.org/wiki/{NAME}
wpfr http://fr.wikipedia.org/wiki/{NAME}
wpde http://de.wikipedia.org/wiki/{NAME}
wpes http://es.wikipedia.org/wiki/{NAME}
wppl http://pl.wikipedia.org/wiki/{NAME}
wpjp http://ja.wikipedia.org/wiki/{NAME}
wpmeta http://meta.wikipedia.org/wiki/{NAME}
doku http://www.dokuwiki.org/
dokubug http://bugs.dokuwiki.org/index.php?do=details&amp;task_id=
rfc http://tools.ietf.org/html/rfc
man http://man.cx/
amazon http://www.amazon.com/exec/obidos/ASIN/{URL}/splitbrain-20/
amazon.de http://www.amazon.de/exec/obidos/ASIN/{URL}/splitbrain-21/
amazon.uk http://www.amazon.co.uk/exec/obidos/ASIN/
paypal https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=
phpfn http://www.php.net/{NAME}
coral http://{HOST}.{PORT}.nyud.net:8090/{PATH}?{QUERY}
freecache http://freecache.org/{NAME}
sb http://www.splitbrain.org/go/
skype skype:{NAME}
google.de http://www.google.de/search?q=
go http://www.google.com/search?q={URL}&amp;btnI=lucky
# To support VoIP/SIP links
callto callto://{NAME}

36
sources/conf/license.php Normal file
View file

@ -0,0 +1,36 @@
<?php
/**
* This file defines multiple available licenses you can license your
* wiki contents under. Do not change this file, but create a
* license.local.php instead.
*/
$license['cc-zero'] = array(
'name' => 'CC0 1.0 Universal',
'url' => 'http://creativecommons.org/publicdomain/zero/1.0/',
);
$license['publicdomain'] = array(
'name' => 'Public Domain',
'url' => 'http://creativecommons.org/licenses/publicdomain/',
);
$license['cc-by'] = array(
'name' => 'CC Attribution 3.0 Unported',
'url' => 'http://creativecommons.org/licenses/by/3.0/',
);
$license['cc-by-sa'] = array(
'name' => 'CC Attribution-Share Alike 3.0 Unported',
'url' => 'http://creativecommons.org/licenses/by-sa/3.0/',
);
$license['gnufdl'] = array(
'name' => 'GNU Free Documentation License 1.3',
'url' => 'http://www.gnu.org/licenses/fdl-1.3.html',
);
$license['cc-by-nc'] = array(
'name' => 'CC Attribution-Noncommercial 3.0 Unported',
'url' => 'http://creativecommons.org/licenses/by-nc/3.0/',
);
$license['cc-by-nc-sa'] = array(
'name' => 'CC Attribution-Noncommercial-Share Alike 3.0 Unported',
'url' => 'http://creativecommons.org/licenses/by-nc-sa/3.0/',
);

View file

@ -0,0 +1,16 @@
<?php
/**
* This is an example of how a local.php could look like.
* Simply copy the options you want to change from dokuwiki.php
* to this file and change them.
*
* When using the installer, a correct local.php file be generated for
* you automatically.
*/
//$conf['title'] = 'My Wiki'; //what to show in the title
//$conf['useacl'] = 1; //Use Access Control Lists to restrict access?
//$conf['superuser'] = 'joe';

View file

@ -0,0 +1,91 @@
<?php
/**
* This configures which meta data will be editable through
* the media manager. Each field of the array is an array with the
* following contents:
* fieldname - Where data will be saved (EXIF or IPTC field)
* label - key to lookup in the $lang var, if not found printed as is
* htmltype - 'text' or 'textarea'
* lookups - array additional fields to lookup the data (EXIF or IPTC fields)
*
* The fields are not ordered continously to make inserting additional items
* in between simpler.
*
* This is a PHP snippet, so PHP syntax applies.
*
* Note: $fields is not a global variable and will not be available to any
* other functions or templates later
*
* You may extend or overwrite this variable in a optional
* conf/mediameta.local.php file
*
* For a list of available EXIF/IPTC fields refer to
* http://www.dokuwiki.org/devel:templates:detail.php
*/
$fields = array(
10 => array('Iptc.Headline',
'img_title',
'text'),
20 => array('',
'img_date',
'date',
array('Date.EarliestTime')),
30 => array('',
'img_fname',
'text',
array('File.Name')),
40 => array('Iptc.Caption',
'img_caption',
'textarea',
array('Exif.UserComment',
'Exif.TIFFImageDescription',
'Exif.TIFFUserComment')),
50 => array('Iptc.Byline',
'img_artist',
'text',
array('Exif.TIFFArtist',
'Exif.Artist',
'Iptc.Credit')),
60 => array('Iptc.CopyrightNotice',
'img_copyr',
'text',
array('Exif.TIFFCopyright',
'Exif.Copyright')),
70 => array('',
'img_format',
'text',
array('File.Format')),
80 => array('',
'img_fsize',
'text',
array('File.NiceSize')),
90 => array('',
'img_width',
'text',
array('File.Width')),
100 => array('',
'img_height',
'text',
array('File.Height')),
110 => array('',
'img_camera',
'text',
array('Simple.Camera')),
120 => array('Iptc.Keywords',
'img_keywords',
'text',
array('Exif.Category')),
);

65
sources/conf/mime.conf Normal file
View file

@ -0,0 +1,65 @@
# Allowed uploadable file extensions and mimetypes are defined here.
# To extend this file it is recommended to create a mime.local.conf
# file. Mimetypes that should be downloadable and not be opened in the
# should be prefixed with a !
jpg image/jpeg
jpeg image/jpeg
gif image/gif
png image/png
ico image/vnd.microsoft.icon
swf application/x-shockwave-flash
mp3 audio/mpeg
ogg audio/ogg
wav audio/wav
tgz !application/octet-stream
tar !application/x-gtar
gz !application/octet-stream
bz2 !application/octet-stream
zip !application/zip
rar !application/rar
7z !application/x-7z-compressed
pdf application/pdf
ps !application/postscript
rpm !application/octet-stream
deb !application/octet-stream
doc !application/msword
xls !application/msexcel
ppt !application/mspowerpoint
rtf !application/msword
docx !application/vnd.openxmlformats-officedocument.wordprocessingml.document
xlsx !application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
pptx !application/vnd.openxmlformats-officedocument.presentationml.presentation
sxw !application/soffice
sxc !application/soffice
sxi !application/soffice
sxd !application/soffice
odc !application/vnd.oasis.opendocument.chart
odf !application/vnd.oasis.opendocument.formula
odg !application/vnd.oasis.opendocument.graphics
odi !application/vnd.oasis.opendocument.image
odp !application/vnd.oasis.opendocument.presentation
ods !application/vnd.oasis.opendocument.spreadsheet
odt !application/vnd.oasis.opendocument.text
# You should enable HTML and Text uploads only for restricted Wikis.
# Spammers are known to upload spam pages through unprotected Wikis.
# Note: Enabling HTML opens Cross Site Scripting vulnerabilities
# through JavaScript. Only enable this with trusted users. You
# need to disable the iexssprotect option additionally to
# adding the mime type here
#html text/html
#htm text/html
#txt text/plain
#conf text/plain
#xml text/xml
#csv text/csv

View file

@ -0,0 +1,253 @@
<?php
/*
* This is an example configuration for the mysql auth plugin.
*
* This SQL statements are optimized for following table structure.
* If you use a different one you have to change them accordingly.
* See comments of every statement for details.
*
* TABLE users
* uid login pass firstname lastname email
*
* TABLE groups
* gid name
*
* TABLE usergroup
* uid gid
*
* To use this configuration you have to copy them to local.protected.php
* or at least include this file in local.protected.php.
*/
/* Options to configure database access. You need to set up this
* options carefully, otherwise you won't be able to access you
* database.
*/
$conf['plugin']['authmysql']['server'] = '';
$conf['plugin']['authmysql']['user'] = '';
$conf['plugin']['authmysql']['password'] = '';
$conf['plugin']['authmysql']['database'] = '';
/* This option enables debug messages in the mysql plugin. It is
* mostly useful for system admins.
*/
$conf['plugin']['authmysql']['debug'] = 0;
/* Normally password encryption is done by DokuWiki (recommended) but for
* some reasons it might be usefull to let the database do the encryption.
* Set 'forwardClearPass' to '1' and the cleartext password is forwarded to
* the database, otherwise the encrypted one.
*/
$conf['plugin']['authmysql']['forwardClearPass'] = 0;
/* Multiple table operations will be protected by locks. This array tolds
* the plugin which tables to lock. If you use any aliases for table names
* these array must also contain these aliases. Any unamed alias will cause
* a warning during operation. See the example below.
*/
$conf['plugin']['authmysql']['TablesToLock']= array("users", "users AS u","groups", "groups AS g", "usergroup", "usergroup AS ug");
/***********************************************************************/
/* Basic SQL statements for user authentication (required) */
/***********************************************************************/
/* This statement is used to grant or deny access to the wiki. The result
* should be a table with exact one line containing at least the password
* of the user. If the result table is empty or contains more than one
* row, access will be denied.
*
* The plugin accesses the password as 'pass' so a alias might be necessary.
*
* Following patters will be replaced:
* %{user} user name
* %{pass} encrypted or clear text password (depends on 'encryptPass')
* %{dgroup} default group name
*/
$conf['plugin']['authmysql']['checkPass'] = "SELECT pass
FROM usergroup AS ug
JOIN users AS u ON u.uid=ug.uid
JOIN groups AS g ON g.gid=ug.gid
WHERE login='%{user}'
AND name='%{dgroup}'";
/* This statement should return a table with exact one row containing
* information about one user. The field needed are:
* 'pass' containing the encrypted or clear text password
* 'name' the user's full name
* 'mail' the user's email address
*
* Keep in mind that Dokuwiki will access thise information through the
* names listed above so aliasses might be neseccary.
*
* Following patters will be replaced:
* %{user} user name
*/
$conf['plugin']['authmysql']['getUserInfo'] = "SELECT pass, CONCAT(firstname,' ',lastname) AS name, email AS mail
FROM users
WHERE login='%{user}'";
/* This statement is used to get all groups a user is member of. The
* result should be a table containing all groups the given user is
* member of. The plugin accesses the group name as 'group' so an alias
* might be nessecary.
*
* Following patters will be replaced:
* %{user} user name
*/
$conf['plugin']['authmysql']['getGroups'] = "SELECT name as `group`
FROM groups g, users u, usergroup ug
WHERE u.uid = ug.uid
AND g.gid = ug.gid
AND u.login='%{user}'";
/***********************************************************************/
/* Additional minimum SQL statements to use the user manager */
/***********************************************************************/
/* This statement should return a table containing all user login names
* that meet certain filter criteria. The filter expressions will be added
* case dependend by the plugin. At the end a sort expression will be added.
* Important is that this list contains no double entries fo a user. Each
* user name is only allowed once in the table.
*
* The login name will be accessed as 'user' to a alias might be neseccary.
* No patterns will be replaced in this statement but following patters
* will be replaced in the filter expressions:
* %{user} in FilterLogin user's login name
* %{name} in FilterName user's full name
* %{email} in FilterEmail user's email address
* %{group} in FilterGroup group name
*/
$conf['plugin']['authmysql']['getUsers'] = "SELECT DISTINCT login AS user
FROM users AS u
LEFT JOIN usergroup AS ug ON u.uid=ug.uid
LEFT JOIN groups AS g ON ug.gid=g.gid";
$conf['plugin']['authmysql']['FilterLogin'] = "login LIKE '%{user}'";
$conf['plugin']['authmysql']['FilterName'] = "CONCAT(firstname,' ',lastname) LIKE '%{name}'";
$conf['plugin']['authmysql']['FilterEmail'] = "email LIKE '%{email}'";
$conf['plugin']['authmysql']['FilterGroup'] = "name LIKE '%{group}'";
$conf['plugin']['authmysql']['SortOrder'] = "ORDER BY login";
/***********************************************************************/
/* Additional SQL statements to add new users with the user manager */
/***********************************************************************/
/* This statement should add a user to the database. Minimum information
* to store are: login name, password, email address and full name.
*
* Following patterns will be replaced:
* %{user} user's login name
* %{pass} password (encrypted or clear text, depends on 'encryptPass')
* %{email} email address
* %{name} user's full name
*/
$conf['plugin']['authmysql']['addUser'] = "INSERT INTO users
(login, pass, email, firstname, lastname)
VALUES ('%{user}', '%{pass}', '%{email}',
SUBSTRING_INDEX('%{name}',' ', 1),
SUBSTRING_INDEX('%{name}',' ', -1))";
/* This statement should add a group to the database.
* Following patterns will be replaced:
* %{group} group name
*/
$conf['plugin']['authmysql']['addGroup'] = "INSERT INTO groups (name)
VALUES ('%{group}')";
/* This statement should connect a user to a group (a user become member
* of that group).
* Following patterns will be replaced:
* %{user} user's login name
* %{uid} id of a user dataset
* %{group} group name
* %{gid} id of a group dataset
*/
$conf['plugin']['authmysql']['addUserGroup']= "INSERT INTO usergroup (uid, gid)
VALUES ('%{uid}', '%{gid}')";
/* This statement should remove a group fom the database.
* Following patterns will be replaced:
* %{group} group name
* %{gid} id of a group dataset
*/
$conf['plugin']['authmysql']['delGroup'] = "DELETE FROM groups
WHERE gid='%{gid}'";
/* This statement should return the database index of a given user name.
* The plugin will access the index with the name 'id' so a alias might be
* necessary.
* following patters will be replaced:
* %{user} user name
*/
$conf['plugin']['authmysql']['getUserID'] = "SELECT uid AS id
FROM users
WHERE login='%{user}'";
/***********************************************************************/
/* Additional SQL statements to delete users with the user manager */
/***********************************************************************/
/* This statement should remove a user fom the database.
* Following patterns will be replaced:
* %{user} user's login name
* %{uid} id of a user dataset
*/
$conf['plugin']['authmysql']['delUser'] = "DELETE FROM users
WHERE uid='%{uid}'";
/* This statement should remove all connections from a user to any group
* (a user quits membership of all groups).
* Following patterns will be replaced:
* %{uid} id of a user dataset
*/
$conf['plugin']['authmysql']['delUserRefs'] = "DELETE FROM usergroup
WHERE uid='%{uid}'";
/***********************************************************************/
/* Additional SQL statements to modify users with the user manager */
/***********************************************************************/
/* This statements should modify a user entry in the database. The
* statements UpdateLogin, UpdatePass, UpdateEmail and UpdateName will be
* added to updateUser on demand. Only changed parameters will be used.
*
* Following patterns will be replaced:
* %{user} user's login name
* %{pass} password (encrypted or clear text, depends on 'encryptPass')
* %{email} email address
* %{name} user's full name
* %{uid} user id that should be updated
*/
$conf['plugin']['authmysql']['updateUser'] = "UPDATE users SET";
$conf['plugin']['authmysql']['UpdateLogin'] = "login='%{user}'";
$conf['plugin']['authmysql']['UpdatePass'] = "pass='%{pass}'";
$conf['plugin']['authmysql']['UpdateEmail'] = "email='%{email}'";
$conf['plugin']['authmysql']['UpdateName'] = "firstname=SUBSTRING_INDEX('%{name}',' ', 1),
lastname=SUBSTRING_INDEX('%{name}',' ', -1)";
$conf['plugin']['authmysql']['UpdateTarget']= "WHERE uid=%{uid}";
/* This statement should remove a single connection from a user to a
* group (a user quits membership of that group).
*
* Following patterns will be replaced:
* %{user} user's login name
* %{uid} id of a user dataset
* %{group} group name
* %{gid} id of a group dataset
*/
$conf['plugin']['authmysql']['delUserGroup']= "DELETE FROM usergroup
WHERE uid='%{uid}'
AND gid='%{gid}'";
/* This statement should return the database index of a given group name.
* The plugin will access the index with the name 'id' so a alias might
* be necessary.
*
* Following patters will be replaced:
* %{group} group name
*/
$conf['plugin']['authmysql']['getGroupID'] = "SELECT gid AS id
FROM groups
WHERE name='%{group}'";

6
sources/conf/plugins.php Normal file
View file

@ -0,0 +1,6 @@
<?php
/**
* This file configures the default states of available plugins. All settings in
* the plugins.*.php files will override those here.
*/
$plugins['testing'] = 0;

View file

@ -0,0 +1,11 @@
<?php
/**
* This file configures the enabled/disabled status of plugins, which are also protected
* from changes by the extention manager. These settings will override any local settings.
* It is not recommended to change this file, as it is overwritten on DokuWiki upgrades.
*/
$plugins['acl'] = 1;
$plugins['plugin'] = 1;
$plugins['config'] = 1;
$plugins['usermanager'] = 1;
$plugins['revert'] = 1;

11
sources/conf/scheme.conf Normal file
View file

@ -0,0 +1,11 @@
#Add URL schemes you want to be recognized as links here
http
https
telnet
gopher
wais
ftp
ed2k
irc
ldap

28
sources/conf/smileys.conf Normal file
View file

@ -0,0 +1,28 @@
# Smileys configured here will be replaced by the
# configured images in the smiley directory
8-) icon_cool.gif
8-O icon_eek.gif
8-o icon_eek.gif
:-( icon_sad.gif
:-) icon_smile.gif
=) icon_smile2.gif
:-/ icon_doubt.gif
:-\ icon_doubt2.gif
:-? icon_confused.gif
:-D icon_biggrin.gif
:-P icon_razz.gif
:-o icon_surprised.gif
:-O icon_surprised.gif
:-x icon_silenced.gif
:-X icon_silenced.gif
:-| icon_neutral.gif
;-) icon_wink.gif
m( facepalm.gif
^_^ icon_fun.gif
:?: icon_question.gif
:!: icon_exclaim.gif
LOL icon_lol.gif
FIXME fixme.gif
DELETEME delete.gif

View file

@ -0,0 +1,10 @@
# users.auth.php
# <?php exit()?>
# Don't modify the lines above
#
# Userfile
#
# Format:
#
# login:passwordhash:Real Name:email:groups,comma,seperated

View file

@ -0,0 +1,33 @@
# This blacklist is maintained by the DokuWiki community
# patches welcome
#
https?:\/\/(\S*?)(-side-effects|top|pharm|pill|discount|discount-|deal|price|order|now|best|cheap|cheap-|online|buy|buy-|sale|sell)(\S*?)(cialis|viagra|prazolam|xanax|zanax|soma|vicodin|zenical|xenical|meridia|paxil|prozac|claritin|allegra|lexapro|wellbutrin|zoloft|retin|valium|levitra|phentermine)
gay\s*sex
bi\s*sex
incest
zoosex
gang\s*bang
facials
ladyboy
fetish
\btits\b
\brape\b
bolea\.com
52crystal
baida\.org
web-directory\.awardspace\.us
korsan-team\.com
BUDA TAMAMDIR
wow-powerleveling-wow\.com
wow gold
wow-gold\.dinmo\.cn
downgrade-vista\.com
downgradetowindowsxp\.com
elegantugg\.com
classicedhardy\.com
research-service\.com
https?:\/\/(\S*?)(2-pay-secure|911essay|academia-research|anypapers|applicationessay|bestbuyessay|bestdissertation|bestessay|bestresume|besttermpaper|businessessay|college-paper|customessay|custom-made-paper|custom-writing|degree-?result|dissertationblog|dissertation-service|dissertations?expert|essaybank|essay-?blog|essaycapital|essaylogic|essaymill|essayontime|essaypaper|essays?land|essaytownsucks|essay-?writ|fastessays|freelancercareers|genuinecontent|genuineessay|genuinepaper|goessay|grandresume|killer-content|ma-dissertation|managementessay|masterpaper|mightystudent|needessay|researchedge|researchpaper-blog|resumecvservice|resumesexperts|resumesplanet|rushessay|samedayessay|superiorcontent|superiorpaper|superiorthesis|term-paper|termpaper-blog|term-paper-research|thesisblog|universalresearch|valwriting|vdwriters|wisetranslation|writersassembly|writers\.com\.ph|writers\.ph)
flatsinmumbai\.co\.in
https?:\/\/(\S*?)penny-?stock
mattressreview\.biz
(just|simply) (my|a) profile (site|webpage|page)

2
sources/data/.htaccess Normal file
View file

@ -0,0 +1,2 @@
order allow,deny
deny from all

1
sources/data/_dummy Normal file
View file

@ -0,0 +1 @@
You can safely delete this file.

View file

@ -0,0 +1 @@
You can safely delete this file.

1
sources/data/cache/_dummy vendored Normal file
View file

@ -0,0 +1 @@
You can safely delete this file.

337
sources/data/deleted.files Normal file
View file

@ -0,0 +1,337 @@
# This is a list of files that were present in previous DokuWiki releases
# but were removed later. An up to date DokuWiki should not have any of
# the files installed
# removed in 2013-11-18
lib/images/arrow_down.gif
lib/images/arrow_up.gif
lib/images/at.gif
lib/images/close.png
lib/images/del.png
lib/images/edit.gif
lib/images/list-minus.gif
lib/images/list-plus.gif
lib/images/pencil.png
# removed in 2013-10-28
lib/images/interwiki/meatball.gif
lib/images/interwiki/wiki.gif
lib/plugins/acl/ajax.php
lib/tpl/default/_admin.css
lib/tpl/default/_fileuploader.css
lib/tpl/default/_linkwiz.css
lib/tpl/default/_mediamanager.css
lib/tpl/default/_mediaoptions.css
lib/tpl/default/_subscription.css
lib/tpl/default/_tabs.css
lib/tpl/default/design.css
lib/tpl/default/detail.php
lib/tpl/default/footer.html
lib/tpl/default/images/UWEB.png
lib/tpl/default/images/UWEBshadow.png
lib/tpl/default/images/apple-touch-icon.png
lib/tpl/default/images/bullet.gif
lib/tpl/default/images/button-cc.gif
lib/tpl/default/images/button-css.png
lib/tpl/default/images/button-donate.gif
lib/tpl/default/images/button-dw.png
lib/tpl/default/images/button-php.gif
lib/tpl/default/images/button-rss.png
lib/tpl/default/images/button-xhtml.png
lib/tpl/default/images/buttonshadow.png
lib/tpl/default/images/closed.gif
lib/tpl/default/images/favicon.ico
lib/tpl/default/images/inputshadow.png
lib/tpl/default/images/link_icon.gif
lib/tpl/default/images/mail_icon.gif
lib/tpl/default/images/open.gif
lib/tpl/default/images/resizecol.png
lib/tpl/default/images/tocdot2.gif
lib/tpl/default/images/windows.gif
lib/tpl/default/layout.css
lib/tpl/default/main.php
lib/tpl/default/media.css
lib/tpl/default/mediamanager.php
lib/tpl/default/print.css
lib/tpl/default/rtl.css
lib/tpl/default/style.ini
lib/tpl/default/template.info.txt
lib/tpl/dokuwiki/css/basic.css
lib/tpl/dokuwiki/css/content.css
lib/tpl/dokuwiki/css/design.css
lib/tpl/dokuwiki/css/includes.css
lib/tpl/dokuwiki/css/mobile.css
lib/tpl/dokuwiki/css/pagetools.css
lib/tpl/dokuwiki/css/structure.css
# removed in 2013-05-10
lib/plugins/info/lang/sl/lang.php
# removed in 2013-04-06
inc/adLDAP.php
inc/auth/ad.class.php
inc/auth/basic.class.php
inc/auth/ldap.class.php
inc/auth/mysql.class.php
inc/auth/pgsql.class.php
inc/auth/plain.class.php
# removed in 2012-09-10
lib/images/icon-file.png
lib/images/icon-thumb.png
lib/images/interwiki/skype.png
lib/plugins/acl/rtl.css
lib/plugins/config/rtl.css
lib/plugins/plugin/rtl.css
# removed in 2011-11-10
lib/_fla/.htaccess
lib/_fla/MultipleUpload.as
lib/_fla/README
lib/_fla/index.html
lib/_fla/multipleUpload.fla
lib/exe/multipleUpload.swf
lib/images/multiupload.png
lib/scripts/ajax.js
lib/scripts/events.js
lib/scripts/subscriptions.js
# removed in 2011-05-25
conf/words.aspell.dist
lib/styles/style.css
# removed in 2010-11-07
inc/lang/ar/subscribermail.txt
inc/lang/az/subscribermail.txt
inc/lang/bg/subscribermail.txt
inc/lang/ca/subscribermail.txt
inc/lang/ca-valencia/subscribermail.txt
inc/lang/cs/subscribermail.txt
inc/lang/da/subscribermail.txt
inc/lang/de-informal/subscribermail.txt
inc/lang/el/subscribermail.txt
inc/lang/eo/subscribermail.txt
inc/lang/es/subscribermail.txt
inc/lang/et/subscribermail.txt
inc/lang/eu/subscribermail.txt
inc/lang/fa/subscribermail.txt
inc/lang/fi/subscribermail.txt
inc/lang/fo/subscribermail.txt
inc/lang/fr/subscribermail.txt
inc/lang/gl/subscribermail.txt
inc/lang/he/subscribermail.txt
inc/lang/hr/subscribermail.txt
inc/lang/hu/subscribermail.txt
inc/lang/id/subscribermail.txt
inc/lang/is/subscribermail.txt
inc/lang/it/subscribermail.txt
inc/lang/ja/subscribermail.txt
inc/lang/ko/subscribermail.txt
inc/lang/ku/subscribermail.txt
inc/lang/lt/subscribermail.txt
inc/lang/lv/subscribermail.txt
inc/lang/mr/subscribermail.txt
inc/lang/ne/subscribermail.txt
inc/lang/nl/subscribermail.txt
inc/lang/no/subscribermail.txt
inc/lang/pl/subscribermail.txt
inc/lang/pt-br/subscribermail.txt
inc/lang/pt/subscribermail.txt
inc/lang/ro/subscribermail.txt
inc/lang/ru/subscribermail.txt
inc/lang/sk/subscribermail.txt
inc/lang/sr/subscribermail.txt
inc/lang/sv/subscribermail.txt
inc/lang/th/subscribermail.txt
inc/lang/tr/subscribermail.txt
inc/lang/uk/subscribermail.txt
inc/lang/zh/subscribermail.txt
inc/lang/zh-tw/subscribermail.txt
# removed in rc2010-10-07
conf/msg
inc/lang/bg/wordblock.txt
inc/lang/ca-valencia/wordblock.txt
inc/lang/ca/wordblock.txt
inc/lang/cs/wordblock.txt
inc/lang/da/wordblock.txt
inc/lang/de-informal/wordblock.txt
inc/lang/de/subscribermail.txt
inc/lang/de/wordblock.txt
inc/lang/el/wordblock.txt
inc/lang/en/subscribermail.txt
inc/lang/en/wordblock.txt
inc/lang/eo/wordblock.txt
inc/lang/es/wordblock.txt
inc/lang/et/wordblock.txt
inc/lang/eu/wordblock.txt
inc/lang/fa/wordblock.txt
inc/lang/fi/wordblock.txt
inc/lang/fo/wordblock.txt
inc/lang/fr/wordblock.txt
inc/lang/he/wordblock.txt
inc/lang/hr/wordblock.txt
inc/lang/hu/wordblock.txt
inc/lang/id/wordblock.txt
inc/lang/it/wordblock.txt
inc/lang/ja/wordblock.txt
inc/lang/ko/wordblock.txt
inc/lang/ku/wordblock.txt
inc/lang/lt/wordblock.txt
inc/lang/lv/wordblock.txt
inc/lang/mg/wordblock.txt
inc/lang/mr/wordblock.txt
inc/lang/nl/wordblock.txt
inc/lang/no/wordblock.txt
inc/lang/pl/wordblock.txt
inc/lang/pt-br/wordblock.txt
inc/lang/pt/wordblock.txt
inc/lang/ro/wordblock.txt
inc/lang/sk/wordblock.txt
inc/lang/sl/wordblock.txt
inc/lang/sr/wordblock.txt
inc/lang/sv/wordblock.txt
inc/lang/th/wordblock.txt
inc/lang/tr/wordblock.txt
inc/lang/uk/wordblock.txt
inc/lang/vi/wordblock.txt
inc/lang/zh-tw/wordblock.txt
inc/lang/zh/wordblock.txt
lib/scripts/pngbehavior.htc
# removed in rc2009-12-02
inc/lang/ar/wordblock.txt
inc/lang/ca-va/
lib/plugins/acl/lang/ca-va/
lib/plugins/config/lang/ca-va/
lib/plugins/plugin/lang/ca-va/
lib/plugins/popularity/lang/ca-va/
lib/plugins/revert/lang/ca-va/
lib/plugins/usermanager/lang/ca-va/
# removed in rc2009-01-30
lib/plugins/upgradeplugindirectory
lib/plugins/upgradeplugindirectory/action.php
# removed in rc2009-01-26
inc/auth/punbb.class.php
inc/lang/ko/edit.txt_bak
inc/lang/ko/lang.php_bak
inc/lang/ku/admin_acl.txt
inc/lang/mg/admin_acl.txt
lib/plugins/importoldchangelog
lib/plugins/importoldchangelog/action.php
lib/plugins/importoldindex
lib/plugins/importoldindex/action.php
lib/plugins/usermanager/images/no_user_edit.png
lib/plugins/usermanager/images/user_edit.png
lib/tpl/default/UWEB.css
# removed in rc2008-03-31
inc/aspell.php
inc/geshi/css-gen.cfg
inc/lang/fr/admin_acl.txt
lib/exe/spellcheck.php
lib/images/toolbar/spellcheck.png
lib/images/toolbar/spellnoerr.png
lib/images/toolbar/spellstop.png
lib/images/toolbar/spellwait.gif
lib/plugins/acl/lang/ar/intro.txt
lib/plugins/acl/lang/bg/intro.txt
lib/plugins/acl/lang/ca/intro.txt
lib/plugins/acl/lang/cs/intro.txt
lib/plugins/acl/lang/da/intro.txt
lib/plugins/acl/lang/de/intro.txt
lib/plugins/acl/lang/el/intro.txt
lib/plugins/acl/lang/en/intro.txt
lib/plugins/acl/lang/es/intro.txt
lib/plugins/acl/lang/et/intro.txt
lib/plugins/acl/lang/eu/intro.txt
lib/plugins/acl/lang/fi/intro.txt
lib/plugins/acl/lang/fr/intro.txt
lib/plugins/acl/lang/gl/intro.txt
lib/plugins/acl/lang/he/intro.txt
lib/plugins/acl/lang/id/intro.txt
lib/plugins/acl/lang/it/intro.txt
lib/plugins/acl/lang/ja/intro.txt
lib/plugins/acl/lang/ko/intro.txt
lib/plugins/acl/lang/lt/intro.txt
lib/plugins/acl/lang/lv/intro.txt
lib/plugins/acl/lang/nl/intro.txt
lib/plugins/acl/lang/no/intro.txt
lib/plugins/acl/lang/pl/intro.txt
lib/plugins/acl/lang/pt/intro.txt
lib/plugins/acl/lang/ru/intro.txt
lib/plugins/acl/lang/sk/intro.txt
lib/plugins/acl/lang/sr/intro.txt
lib/plugins/acl/lang/sv/intro.txt
lib/plugins/acl/lang/tr/intro.txt
lib/plugins/acl/lang/uk/intro.txt
lib/plugins/acl/lang/vi/intro.txt
lib/plugins/acl/lang/zh/intro.txt
lib/plugins/acl/lang/zh-tw/intro.txt
lib/scripts/spellcheck.js
lib/styles/spellcheck.css
# removed in 2007-06-26
inc/parser/wiki.php
lib/images/interwiki/bug.gif
lib/plugins/base.php
lib/plugins/plugin/inc
lib/plugins/plugin/inc/tarlib.class.php
lib/plugins/plugin/inc/zip.lib.php
lib/scripts/domLib.js
lib/scripts/domTT.js
# removed in 2006-11-06
inc/admin_acl.php
inc/lang/lt/stopwords.txt
inc/magpie
inc/magpie/rss_cache.inc
inc/magpie/rss_fetch.inc
inc/magpie/rss_parse.inc
inc/magpie/rss_utils.inc
lib/exe/media.php
lib/tpl/default/mediaedit.php
lib/tpl/default/media.php
lib/tpl/default/mediaref.php
# removed in 2006-03-09
data/pages/wiki/playground.txt
inc/auth/ldap.php
inc/auth/mysql.php
inc/auth/pgsql.php
inc/auth/plain.php
inc/lang/ca/admin_acl.txt
inc/lang/cs/admin_acl.txt
inc/lang/da/admin_acl.txt
inc/lang/de/admin_acl.txt
inc/lang/en/admin_acl.txt
inc/lang/et/admin_acl.txt
inc/lang/eu/admin_acl.txt
inc/lang/fr/admin_acl.txt
inc/lang/it/admin_acl.txt
inc/lang/ja/admin_acl.txt
inc/lang/lt/admin_acl.txt
inc/lang/lv/admin_acl.txt
inc/lang/nl/admin_acl.txt
inc/lang/no/admin_acl.txt
inc/lang/pl/admin_acl.txt
inc/lang/pt/admin_acl.txt
inc/lang/vi/admin_acl.txt
inc/lang/zh-tw/admin_acl.txt
inc/parser/spamcheck.php
lib/images/favicon.ico
lib/images/thumbup.gif
lib/images/toolbar/code.png
lib/images/toolbar/empty.png
lib/images/toolbar/extlink.png
lib/images/toolbar/fonth1.png
lib/images/toolbar/fonth2.png
lib/images/toolbar/fonth3.png
lib/images/toolbar/fonth4.png
lib/images/toolbar/fonth5.png
lib/images/toolbar/list.png
lib/images/toolbar/list_ul.png
lib/images/toolbar/rule.png
lib/tpl/default/images/interwiki.png

View file

@ -0,0 +1 @@
You can safely delete this file.

View file

@ -0,0 +1 @@
You can safely delete this file.

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View file

@ -0,0 +1 @@
You can safely delete this file.

View file

@ -0,0 +1 @@
You can safely delete this file.

1
sources/data/meta/_dummy Normal file
View file

@ -0,0 +1 @@
You can safely delete this file.

View file

@ -0,0 +1 @@
====== PlayGround ======

View file

@ -0,0 +1,64 @@
====== DokuWiki ======
[[doku>wiki:dokuwiki|{{wiki:dokuwiki-128.png }}]] DokuWiki is a simple to use and highly versatile Open Source [[wp>wiki]] software that doesn't require a database. It is loved by users for its clean and readable [[wiki:syntax]]. The ease of maintenance, backup and integration makes it an administrator's favorite. Built in [[doku>acl|access controls]] and [[doku>auth|authentication connectors]] make DokuWiki especially useful in the enterprise context and the large number of [[doku>plugins]] contributed by its vibrant community allow for a broad range of use cases beyond a traditional wiki.
Read the [[doku>manual|DokuWiki Manual]] to unleash the full power of DokuWiki.
===== Download =====
DokuWiki is available at http://www.splitbrain.org/go/dokuwiki
===== Read More =====
All documentation and additional information besides the [[syntax|syntax description]] is maintained in the DokuWiki at [[doku>|www.dokuwiki.org]].
**About DokuWiki**
* [[doku>features|A feature list]] :!:
* [[doku>users|Happy Users]]
* [[doku>press|Who wrote about it]]
* [[doku>blogroll|What Bloggers think]]
* [[http://www.wikimatrix.org/show/DokuWiki|Compare it with other wiki software]]
**Installing DokuWiki**
* [[doku>requirements|System Requirements]]
* [[http://www.splitbrain.org/go/dokuwiki|Download DokuWiki]] :!:
* [[doku>changes|Change Log]]
* [[doku>Install|How to install or upgrade]] :!:
* [[doku>config|Configuration]]
**Using DokuWiki**
* [[doku>syntax|Wiki Syntax]]
* [[doku>manual|The manual]] :!:
* [[doku>FAQ|Frequently Asked Questions (FAQ)]]
* [[doku>glossary|Glossary]]
* [[http://search.dokuwiki.org|Search for DokuWiki help and documentation]]
**Customizing DokuWiki**
* [[doku>tips|Tips and Tricks]]
* [[doku>Template|How to create and use templates]]
* [[doku>plugins|Installing plugins]]
* [[doku>development|Development Resources]]
**DokuWiki Feedback and Community**
* [[doku>newsletter|Subscribe to the newsletter]] :!:
* [[doku>mailinglist|Join the mailing list]]
* [[http://forum.dokuwiki.org|Check out the user forum]]
* [[doku>irc|Talk to other users in the IRC channel]]
* [[http://bugs.splitbrain.org/index.php?project=1|Submit bugs and feature wishes]]
* [[http://www.wikimatrix.org/forum/viewforum.php?id=10|Share your experiences in the WikiMatrix forum]]
* [[doku>thanks|Some humble thanks]]
===== Copyright =====
2004-2013 (c) Andreas Gohr <andi@splitbrain.org>((Please do not contact me for help and support -- use the [[doku>mailinglist]] or [[http://forum.dokuwiki.org|forum]] instead)) and the DokuWiki Community
The DokuWiki engine is licensed under [[http://www.gnu.org/licenses/gpl.html|GNU General Public License]] Version 2. If you use DokuWiki in your company, consider [[doku>donate|donating]] a few bucks ;-).
Not sure what this means? See the [[doku>faq:license|FAQ on the Licenses]].

View file

@ -0,0 +1,486 @@
====== Formatting Syntax ======
[[doku>DokuWiki]] supports some simple markup language, which tries to make the datafiles to be as readable as possible. This page contains all possible syntax you may use when editing the pages. Simply have a look at the source of this page by pressing "Edit this page". If you want to try something, just use the [[playground:playground|playground]] page. The simpler markup is easily accessible via [[doku>toolbar|quickbuttons]], too.
===== Basic Text Formatting =====
DokuWiki supports **bold**, //italic//, __underlined__ and ''monospaced'' texts. Of course you can **__//''combine''//__** all these.
DokuWiki supports **bold**, //italic//, __underlined__ and ''monospaced'' texts.
Of course you can **__//''combine''//__** all these.
You can use <sub>subscript</sub> and <sup>superscript</sup>, too.
You can use <sub>subscript</sub> and <sup>superscript</sup>, too.
You can mark something as <del>deleted</del> as well.
You can mark something as <del>deleted</del> as well.
**Paragraphs** are created from blank lines. If you want to **force a newline** without a paragraph, you can use two backslashes followed by a whitespace or the end of line.
This is some text with some linebreaks\\ Note that the
two backslashes are only recognized at the end of a line\\
or followed by\\ a whitespace \\this happens without it.
This is some text with some linebreaks\\ Note that the
two backslashes are only recognized at the end of a line\\
or followed by\\ a whitespace \\this happens without it.
You should use forced newlines only if really needed.
===== Links =====
DokuWiki supports multiple ways of creating links.
==== External ====
External links are recognized automagically: http://www.google.com or simply www.google.com - You can set the link text as well: [[http://www.google.com|This Link points to google]]. Email addresses like this one: <andi@splitbrain.org> are recognized, too.
DokuWiki supports multiple ways of creating links. External links are recognized
automagically: http://www.google.com or simply www.google.com - You can set
link text as well: [[http://www.google.com|This Link points to google]]. Email
addresses like this one: <andi@splitbrain.org> are recognized, too.
==== Internal ====
Internal links are created by using square brackets. You can either just give a [[pagename]] or use an additional [[pagename|link text]].
Internal links are created by using square brackets. You can either just give
a [[pagename]] or use an additional [[pagename|link text]].
[[doku>pagename|Wiki pagenames]] are converted to lowercase automatically, special characters are not allowed.
You can use [[some:namespaces]] by using a colon in the pagename.
You can use [[some:namespaces]] by using a colon in the pagename.
For details about namespaces see [[doku>namespaces]].
Linking to a specific section is possible, too. Just add the section name behind a hash character as known from HTML. This links to [[syntax#internal|this Section]].
This links to [[syntax#internal|this Section]].
Notes:
* Links to [[syntax|existing pages]] are shown in a different style from [[nonexisting]] ones.
* DokuWiki does not use [[wp>CamelCase]] to automatically create links by default, but this behavior can be enabled in the [[doku>config]] file. Hint: If DokuWiki is a link, then it's enabled.
* When a section's heading is changed, its bookmark changes, too. So don't rely on section linking too much.
==== Interwiki ====
DokuWiki supports [[doku>Interwiki]] links. These are quick links to other Wikis. For example this is a link to Wikipedia's page about Wikis: [[wp>Wiki]].
DokuWiki supports [[doku>Interwiki]] links. These are quick links to other Wikis.
For example this is a link to Wikipedia's page about Wikis: [[wp>Wiki]].
==== Windows Shares ====
Windows shares like [[\\server\share|this]] are recognized, too. Please note that these only make sense in a homogeneous user group like a corporate [[wp>Intranet]].
Windows Shares like [[\\server\share|this]] are recognized, too.
Notes:
* For security reasons direct browsing of windows shares only works in Microsoft Internet Explorer per default (and only in the "local zone").
* For Mozilla and Firefox it can be enabled through different workaround mentioned in the [[http://kb.mozillazine.org/Links_to_local_pages_do_not_work|Mozilla Knowledge Base]]. However, there will still be a JavaScript warning about trying to open a Windows Share. To remove this warning (for all users), put the following line in ''conf/userscript.js'':
LANG.nosmblinks = '';
==== Image Links ====
You can also use an image to link to another internal or external page by combining the syntax for links and [[#images_and_other_files|images]] (see below) like this:
[[http://www.php.net|{{wiki:dokuwiki-128.png}}]]
[[http://www.php.net|{{wiki:dokuwiki-128.png}}]]
Please note: The image formatting is the only formatting syntax accepted in link names.
The whole [[#images_and_other_files|image]] and [[#links|link]] syntax is supported (including image resizing, internal and external images and URLs and interwiki links).
===== Footnotes =====
You can add footnotes ((This is a footnote)) by using double parentheses.
You can add footnotes ((This is a footnote)) by using double parentheses.
===== Sectioning =====
You can use up to five different levels of headlines to structure your content. If you have more than three headlines, a table of contents is generated automatically -- this can be disabled by including the string ''<nowiki>~~NOTOC~~</nowiki>'' in the document.
==== Headline Level 3 ====
=== Headline Level 4 ===
== Headline Level 5 ==
==== Headline Level 3 ====
=== Headline Level 4 ===
== Headline Level 5 ==
By using four or more dashes, you can make a horizontal line:
----
===== Images and Other Files =====
You can include external and internal [[doku>images]] with curly brackets. Optionally you can specify the size of them.
Real size: {{wiki:dokuwiki-128.png}}
Resize to given width: {{wiki:dokuwiki-128.png?50}}
Resize to given width and height((when the aspect ratio of the given width and height doesn't match that of the image, it will be cropped to the new ratio before resizing)): {{wiki:dokuwiki-128.png?200x50}}
Resized external image: {{http://de3.php.net/images/php.gif?200x50}}
Real size: {{wiki:dokuwiki-128.png}}
Resize to given width: {{wiki:dokuwiki-128.png?50}}
Resize to given width and height: {{wiki:dokuwiki-128.png?200x50}}
Resized external image: {{http://de3.php.net/images/php.gif?200x50}}
By using left or right whitespaces you can choose the alignment.
{{ wiki:dokuwiki-128.png}}
{{wiki:dokuwiki-128.png }}
{{ wiki:dokuwiki-128.png }}
{{ wiki:dokuwiki-128.png}}
{{wiki:dokuwiki-128.png }}
{{ wiki:dokuwiki-128.png }}
Of course, you can add a title (displayed as a tooltip by most browsers), too.
{{ wiki:dokuwiki-128.png |This is the caption}}
{{ wiki:dokuwiki-128.png |This is the caption}}
If you specify a filename (external or internal) that is not an image (''gif, jpeg, png''), then it will be displayed as a link instead.
For linking an image to another page see [[#Image Links]] above.
===== Lists =====
Dokuwiki supports ordered and unordered lists. To create a list item, indent your text by two spaces and use a ''*'' for unordered lists or a ''-'' for ordered ones.
* This is a list
* The second item
* You may have different levels
* Another item
- The same list but ordered
- Another item
- Just use indention for deeper levels
- That's it
<code>
* This is a list
* The second item
* You may have different levels
* Another item
- The same list but ordered
- Another item
- Just use indention for deeper levels
- That's it
</code>
Also take a look at the [[doku>faq:lists|FAQ on list items]].
===== Text Conversions =====
DokuWiki can convert certain pre-defined characters or strings into images or other text or HTML.
The text to image conversion is mainly done for smileys. And the text to HTML conversion is used for typography replacements, but can be configured to use other HTML as well.
==== Text to Image Conversions ====
DokuWiki converts commonly used [[wp>emoticon]]s to their graphical equivalents. Those [[doku>Smileys]] and other images can be configured and extended. Here is an overview of Smileys included in DokuWiki:
* 8-) %% 8-) %%
* 8-O %% 8-O %%
* :-( %% :-( %%
* :-) %% :-) %%
* =) %% =) %%
* :-/ %% :-/ %%
* :-\ %% :-\ %%
* :-? %% :-? %%
* :-D %% :-D %%
* :-P %% :-P %%
* :-O %% :-O %%
* :-X %% :-X %%
* :-| %% :-| %%
* ;-) %% ;-) %%
* ^_^ %% ^_^ %%
* :?: %% :?: %%
* :!: %% :!: %%
* LOL %% LOL %%
* FIXME %% FIXME %%
* DELETEME %% DELETEME %%
==== Text to HTML Conversions ====
Typography: [[DokuWiki]] can convert simple text characters to their typographically correct entities. Here is an example of recognized characters.
-> <- <-> => <= <=> >> << -- --- 640x480 (c) (tm) (r)
"He thought 'It's a man's world'..."
<code>
-> <- <-> => <= <=> >> << -- --- 640x480 (c) (tm) (r)
"He thought 'It's a man's world'..."
</code>
The same can be done to produce any kind of HTML, it just needs to be added to the [[doku>entities|pattern file]].
There are three exceptions which do not come from that pattern file: multiplication entity (640x480), 'single' and "double quotes". They can be turned off through a [[doku>config:typography|config option]].
===== Quoting =====
Some times you want to mark some text to show it's a reply or comment. You can use the following syntax:
I think we should do it
> No we shouldn't
>> Well, I say we should
> Really?
>> Yes!
>>> Then lets do it!
I think we should do it
> No we shouldn't
>> Well, I say we should
> Really?
>> Yes!
>>> Then lets do it!
===== Tables =====
DokuWiki supports a simple syntax to create tables.
^ Heading 1 ^ Heading 2 ^ Heading 3 ^
| Row 1 Col 1 | Row 1 Col 2 | Row 1 Col 3 |
| Row 2 Col 1 | some colspan (note the double pipe) ||
| Row 3 Col 1 | Row 3 Col 2 | Row 3 Col 3 |
Table rows have to start and end with a ''|'' for normal rows or a ''^'' for headers.
^ Heading 1 ^ Heading 2 ^ Heading 3 ^
| Row 1 Col 1 | Row 1 Col 2 | Row 1 Col 3 |
| Row 2 Col 1 | some colspan (note the double pipe) ||
| Row 3 Col 1 | Row 3 Col 2 | Row 3 Col 3 |
To connect cells horizontally, just make the next cell completely empty as shown above. Be sure to have always the same amount of cell separators!
Vertical tableheaders are possible, too.
| ^ Heading 1 ^ Heading 2 ^
^ Heading 3 | Row 1 Col 2 | Row 1 Col 3 |
^ Heading 4 | no colspan this time | |
^ Heading 5 | Row 2 Col 2 | Row 2 Col 3 |
As you can see, it's the cell separator before a cell which decides about the formatting:
| ^ Heading 1 ^ Heading 2 ^
^ Heading 3 | Row 1 Col 2 | Row 1 Col 3 |
^ Heading 4 | no colspan this time | |
^ Heading 5 | Row 2 Col 2 | Row 2 Col 3 |
You can have rowspans (vertically connected cells) by adding '':::'' into the cells below the one to which they should connect.
^ Heading 1 ^ Heading 2 ^ Heading 3 ^
| Row 1 Col 1 | this cell spans vertically | Row 1 Col 3 |
| Row 2 Col 1 | ::: | Row 2 Col 3 |
| Row 3 Col 1 | ::: | Row 2 Col 3 |
Apart from the rowspan syntax those cells should not contain anything else.
^ Heading 1 ^ Heading 2 ^ Heading 3 ^
| Row 1 Col 1 | this cell spans vertically | Row 1 Col 3 |
| Row 2 Col 1 | ::: | Row 2 Col 3 |
| Row 3 Col 1 | ::: | Row 2 Col 3 |
You can align the table contents, too. Just add at least two whitespaces at the opposite end of your text: Add two spaces on the left to align right, two spaces on the right to align left and two spaces at least at both ends for centered text.
^ Table with alignment ^^^
| right| center |left |
|left | right| center |
| xxxxxxxxxxxx | xxxxxxxxxxxx | xxxxxxxxxxxx |
This is how it looks in the source:
^ Table with alignment ^^^
| right| center |left |
|left | right| center |
| xxxxxxxxxxxx | xxxxxxxxxxxx | xxxxxxxxxxxx |
Note: Vertical alignment is not supported.
===== No Formatting =====
If you need to display text exactly like it is typed (without any formatting), enclose the area either with ''%%<nowiki>%%'' tags or even simpler, with double percent signs ''<nowiki>%%</nowiki>''.
<nowiki>
This is some text which contains addresses like this: http://www.splitbrain.org and **formatting**, but nothing is done with it.
</nowiki>
The same is true for %%//__this__ text// with a smiley ;-)%%.
<nowiki>
This is some text which contains addresses like this: http://www.splitbrain.org and **formatting**, but nothing is done with it.
</nowiki>
The same is true for %%//__this__ text// with a smiley ;-)%%.
===== Code Blocks =====
You can include code blocks into your documents by either indenting them by at least two spaces (like used for the previous examples) or by using the tags ''%%<code>%%'' or ''%%<file>%%''.
This is text is indented by two spaces.
<code>
This is preformatted code all spaces are preserved: like <-this
</code>
<file>
This is pretty much the same, but you could use it to show that you quoted a file.
</file>
Those blocks were created by this source:
This is text is indented by two spaces.
<code>
This is preformatted code all spaces are preserved: like <-this
</code>
<file>
This is pretty much the same, but you could use it to show that you quoted a file.
</file>
==== Syntax Highlighting ====
[[wiki:DokuWiki]] can highlight sourcecode, which makes it easier to read. It uses the [[http://qbnz.com/highlighter/|GeSHi]] Generic Syntax Highlighter -- so any language supported by GeSHi is supported. The syntax uses the same code and file blocks described in the previous section, but this time the name of the language syntax to be highlighted is included inside the tag, e.g. ''<nowiki><code java></nowiki>'' or ''<nowiki><file java></nowiki>''.
<code java>
/**
* The HelloWorldApp class implements an application that
* simply displays "Hello World!" to the standard output.
*/
class HelloWorldApp {
public static void main(String[] args) {
System.out.println("Hello World!"); //Display the string.
}
}
</code>
The following language strings are currently recognized: //4cs, 6502acme, 6502kickass, 6502tasm, 68000devpac, abap, actionscript-french, actionscript, actionscript3, ada, algol68, apache, applescript, asm, asp, autoconf, autohotkey, autoit, avisynth, awk, bascomavr, bash, basic4gl, bf, bibtex, blitzbasic, bnf, boo, c, c_loadrunner, c_mac, caddcl, cadlisp, cfdg, cfm, chaiscript, cil, clojure, cmake, cobol, coffeescript, cpp, cpp-qt, csharp, css, cuesheet, d, dcs, delphi, diff, div, dos, dot, e, epc, ecmascript, eiffel, email, erlang, euphoria, f1, falcon, fo, fortran, freebasic, fsharp, gambas, genero, genie, gdb, glsl, gml, gnuplot, go, groovy, gettext, gwbasic, haskell, hicest, hq9plus, html, html5, icon, idl, ini, inno, intercal, io, j, java5, java, javascript, jquery, kixtart, klonec, klonecpp, latex, lb, lisp, llvm, locobasic, logtalk, lolcode, lotusformulas, lotusscript, lscript, lsl2, lua, m68k, magiksf, make, mapbasic, matlab, mirc, modula2, modula3, mmix, mpasm, mxml, mysql, newlisp, nsis, oberon2, objc, objeck, ocaml-brief, ocaml, oobas, oracle8, oracle11, oxygene, oz, pascal, pcre, perl, perl6, per, pf, php-brief, php, pike, pic16, pixelbender, pli, plsql, postgresql, povray, powerbuilder, powershell, proftpd, progress, prolog, properties, providex, purebasic, pycon, python, q, qbasic, rails, rebol, reg, robots, rpmspec, rsplus, ruby, sas, scala, scheme, scilab, sdlbasic, smalltalk, smarty, sql, systemverilog, tcl, teraterm, text, thinbasic, tsql, typoscript, unicon, uscript, vala, vbnet, vb, verilog, vhdl, vim, visualfoxpro, visualprolog, whitespace, winbatch, whois, xbasic, xml, xorg_conf, xpp, yaml, z80, zxbasic//
==== Downloadable Code Blocks ====
When you use the ''%%<code>%%'' or ''%%<file>%%'' syntax as above, you might want to make the shown code available for download as well. You can do this by specifying a file name after language code like this:
<code>
<file php myexample.php>
<?php echo "hello world!"; ?>
</file>
</code>
<file php myexample.php>
<?php echo "hello world!"; ?>
</file>
If you don't want any highlighting but want a downloadable file, specify a dash (''-'') as the language code: ''%%<code - myfile.foo>%%''.
===== Embedding HTML and PHP =====
You can embed raw HTML or PHP code into your documents by using the ''%%<html>%%'' or ''%%<php>%%'' tags. (Use uppercase tags if you need to enclose block level elements.)
HTML example:
<code>
<html>
This is some <span style="color:red;font-size:150%;">inline HTML</span>
</html>
<HTML>
<p style="border:2px dashed red;">And this is some block HTML</p>
</HTML>
</code>
<html>
This is some <span style="color:red;font-size:150%;">inline HTML</span>
</html>
<HTML>
<p style="border:2px dashed red;">And this is some block HTML</p>
</HTML>
PHP example:
<code>
<php>
echo 'A logo generated by PHP:';
echo '<img src="' . $_SERVER['PHP_SELF'] . '?=' . php_logo_guid() . '" alt="PHP Logo !" />';
echo '(generated inline HTML)';
</php>
<PHP>
echo '<table class="inline"><tr><td>The same, but inside a block level element:</td>';
echo '<td><img src="' . $_SERVER['PHP_SELF'] . '?=' . php_logo_guid() . '" alt="PHP Logo !" /></td>';
echo '</tr></table>';
</PHP>
</code>
<php>
echo 'A logo generated by PHP:';
echo '<img src="' . $_SERVER['PHP_SELF'] . '?=' . php_logo_guid() . '" alt="PHP Logo !" />';
echo '(inline HTML)';
</php>
<PHP>
echo '<table class="inline"><tr><td>The same, but inside a block level element:</td>';
echo '<td><img src="' . $_SERVER['PHP_SELF'] . '?=' . php_logo_guid() . '" alt="PHP Logo !" /></td>';
echo '</tr></table>';
</PHP>
**Please Note**: HTML and PHP embedding is disabled by default in the configuration. If disabled, the code is displayed instead of executed.
===== RSS/ATOM Feed Aggregation =====
[[DokuWiki]] can integrate data from external XML feeds. For parsing the XML feeds, [[http://simplepie.org/|SimplePie]] is used. All formats understood by SimplePie can be used in DokuWiki as well. You can influence the rendering by multiple additional space separated parameters:
^ Parameter ^ Description ^
| any number | will be used as maximum number items to show, defaults to 8 |
| reverse | display the last items in the feed first |
| author | show item authors names |
| date | show item dates |
| description| show the item description. If [[doku>config:htmlok|HTML]] is disabled all tags will be stripped |
| //n//[dhm] | refresh period, where d=days, h=hours, m=minutes. (e.g. 12h = 12 hours). |
The refresh period defaults to 4 hours. Any value below 10 minutes will be treated as 10 minutes. [[wiki:DokuWiki]] will generally try to supply a cached version of a page, obviously this is inappropriate when the page contains dynamic external content. The parameter tells [[wiki:DokuWiki]] to re-render the page if it is more than //refresh period// since the page was last rendered.
**Example:**
{{rss>http://slashdot.org/index.rss 5 author date 1h }}
{{rss>http://slashdot.org/index.rss 5 author date 1h }}
===== Control Macros =====
Some syntax influences how DokuWiki renders a page without creating any output it self. The following control macros are availble:
^ Macro ^ Description |
| %%~~NOTOC~~%% | If this macro is found on the page, no table of contents will be created |
| %%~~NOCACHE~~%% | DokuWiki caches all output by default. Sometimes this might not be wanted (eg. when the %%<php>%% syntax above is used), adding this macro will force DokuWiki to rerender a page on every call |
===== Syntax Plugins =====
DokuWiki's syntax can be extended by [[doku>plugins|Plugins]]. How the installed plugins are used is described on their appropriate description pages. The following syntax plugins are available in this particular DokuWiki installation:
~~INFO:syntaxplugins~~

View file

@ -0,0 +1,30 @@
====== Welcome to your new DokuWiki ======
Congratulations, your wiki is now up and running. Here are a few more tips to get you started.
Enjoy your work with DokuWiki,\\
-- the developers
===== Create your first pages =====
Your wiki needs to have a start page. As long as it doesn't exist, this link will be red: [[:start]].
Go on, follow that link and create the page. If you need help with using the syntax you can always refer to the [[wiki:syntax|syntax page]].
You might also want to use a sidebar. To create it, just edit the [[:sidebar]] page. Everything in that page will be shown in a margin column on the side. Read our [[doku>faq:sidebar|FAQ on sidebars]] to learn more.
Please be aware that not all templates support sidebars.
===== Customize your Wiki =====
Once you're comfortable with creating and editing pages you might want to have a look at the [[this>doku.php?do=admin&page=config|configuration settings]] (be sure to login as superuser first).
You may also want to see what [[doku>plugins|plugins]] and [[doku>templates|templates]] are available at DokuWiki.org to extend the functionality and looks of your DokuWiki installation.
===== Join the Community =====
DokuWiki is an Open Source project that thrives through user contributions. A good way to stay informed on what's going on and to get useful tips in using DokuWiki is subscribing to the [[doku>newsletter]].
The [[http://forum.dokuwiki.org|DokuWiki User Forum]] is an excellent way to get in contact with other DokuWiki users and is just one of the many ways to get [[doku>faq:support|support]].
Of course we'd be more than happy to have you [[doku>teams:getting_involved|getting involved]] with DokuWiki.

BIN
sources/data/security.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
sources/data/security.xcf Normal file

Binary file not shown.

1
sources/data/tmp/_dummy Normal file
View file

@ -0,0 +1 @@
You can safely delete this file.

89
sources/doku.php Normal file
View file

@ -0,0 +1,89 @@
<?php
/**
* DokuWiki mainscript
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Andreas Gohr <andi@splitbrain.org>
*
* @global Input $INPUT
*/
// update message version
$updateVersion = 43;
// xdebug_start_profiling();
if(!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__).'/');
if(isset($_SERVER['HTTP_X_DOKUWIKI_DO'])) {
$ACT = trim(strtolower($_SERVER['HTTP_X_DOKUWIKI_DO']));
} elseif(!empty($_REQUEST['idx'])) {
$ACT = 'index';
} elseif(isset($_REQUEST['do'])) {
$ACT = $_REQUEST['do'];
} else {
$ACT = 'show';
}
// load and initialize the core system
require_once(DOKU_INC.'inc/init.php');
//import variables
$INPUT->set('id', str_replace("\xC2\xAD", '', $INPUT->str('id'))); //soft-hyphen
$QUERY = trim($INPUT->str('id'));
$ID = getID();
$REV = $INPUT->int('rev');
$IDX = $INPUT->str('idx');
$DATE = $INPUT->int('date');
$RANGE = $INPUT->str('range');
$HIGH = $INPUT->param('s');
if(empty($HIGH)) $HIGH = getGoogleQuery();
if($INPUT->post->has('wikitext')) {
$TEXT = cleanText($INPUT->post->str('wikitext'));
}
$PRE = cleanText(substr($INPUT->post->str('prefix'), 0, -1));
$SUF = cleanText($INPUT->post->str('suffix'));
$SUM = $INPUT->post->str('summary');
//make info about the selected page available
$INFO = pageinfo();
//export minimal info to JS, plugins can add more
$JSINFO['id'] = $ID;
$JSINFO['namespace'] = (string) $INFO['namespace'];
// handle debugging
if($conf['allowdebug'] && $ACT == 'debug') {
html_debug();
exit;
}
//send 404 for missing pages if configured or ID has special meaning to bots
if(!$INFO['exists'] &&
($conf['send404'] || preg_match('/^(robots\.txt|sitemap\.xml(\.gz)?|favicon\.ico|crossdomain\.xml)$/', $ID)) &&
($ACT == 'show' || (!is_array($ACT) && substr($ACT, 0, 7) == 'export_'))
) {
header('HTTP/1.0 404 Not Found');
}
//prepare breadcrumbs (initialize a static var)
if($conf['breadcrumbs']) breadcrumbs();
// check upstream
checkUpdateMessages();
$tmp = array(); // No event data
trigger_event('DOKUWIKI_STARTED', $tmp);
//close session
session_write_close();
//do the work (picks up what to do from global env)
act_dispatch();
$tmp = array(); // No event data
trigger_event('DOKUWIKI_DONE', $tmp);
// xdebug_dump_function_profile(1);

504
sources/feed.php Normal file
View file

@ -0,0 +1,504 @@
<?php
/**
* XML feed export
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Andreas Gohr <andi@splitbrain.org>
*
* @global array $conf
* @global Input $INPUT
*/
if(!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__).'/');
require_once(DOKU_INC.'inc/init.php');
//close session
session_write_close();
// get params
$opt = rss_parseOptions();
// the feed is dynamic - we need a cache for each combo
// (but most people just use the default feed so it's still effective)
$cache = getCacheName(join('', array_values($opt)).$_SERVER['REMOTE_USER'], '.feed');
$key = join('', array_values($opt)).$_SERVER['REMOTE_USER'];
$cache = new cache($key, '.feed');
// prepare cache depends
$depends['files'] = getConfigFiles('main');
$depends['age'] = $conf['rss_update'];
$depends['purge'] = $INPUT->bool('purge');
// check cacheage and deliver if nothing has changed since last
// time or the update interval has not passed, also handles conditional requests
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Type: application/xml; charset=utf-8');
header('X-Robots-Tag: noindex');
if($cache->useCache($depends)) {
http_conditionalRequest($cache->_time);
if($conf['allowdebug']) header("X-CacheUsed: $cache->cache");
print $cache->retrieveCache();
exit;
} else {
http_conditionalRequest(time());
}
// create new feed
$rss = new DokuWikiFeedCreator();
$rss->title = $conf['title'].(($opt['namespace']) ? ' '.$opt['namespace'] : '');
$rss->link = DOKU_URL;
$rss->syndicationURL = DOKU_URL.'feed.php';
$rss->cssStyleSheet = DOKU_URL.'lib/exe/css.php?s=feed';
$image = new FeedImage();
$image->title = $conf['title'];
$image->url = tpl_getMediaFile(array(':wiki:favicon.ico', ':favicon.ico', 'images/favicon.ico'), true);
$image->link = DOKU_URL;
$rss->image = $image;
$data = null;
$modes = array(
'list' => 'rssListNamespace',
'search' => 'rssSearch',
'recent' => 'rssRecentChanges'
);
if(isset($modes[$opt['feed_mode']])) {
$data = $modes[$opt['feed_mode']]($opt);
} else {
$eventData = array(
'opt' => &$opt,
'data' => &$data,
);
$event = new Doku_Event('FEED_MODE_UNKNOWN', $eventData);
if($event->advise_before(true)) {
echo sprintf('<error>Unknown feed mode %s</error>', hsc($opt['feed_mode']));
exit;
}
$event->advise_after();
}
rss_buildItems($rss, $data, $opt);
$feed = $rss->createFeed($opt['feed_type'], 'utf-8');
// save cachefile
$cache->storeCache($feed);
// finally deliver
print $feed;
// ---------------------------------------------------------------- //
/**
* Get URL parameters and config options and return an initialized option array
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function rss_parseOptions() {
global $conf;
global $INPUT;
$opt = array();
foreach(array(
// Basic feed properties
// Plugins may probably want to add new values to these
// properties for implementing own feeds
// One of: list, search, recent
'feed_mode' => array('str', 'mode', 'recent'),
// One of: diff, page, rev, current
'link_to' => array('str', 'linkto', $conf['rss_linkto']),
// One of: abstract, diff, htmldiff, html
'item_content' => array('str', 'content', $conf['rss_content']),
// Special feed properties
// These are only used by certain feed_modes
// String, used for feed title, in list and rc mode
'namespace' => array('str', 'ns', null),
// Positive integer, only used in rc mode
'items' => array('int', 'num', $conf['recent']),
// Boolean, only used in rc mode
'show_minor' => array('bool', 'minor', false),
// String, only used in search mode
'search_query' => array('str', 'q', null),
// One of: pages, media, both
'content_type' => array('str', 'view', $conf['rss_media'])
) as $name => $val) {
$opt[$name] = $INPUT->$val[0]($val[1], $val[2], true);
}
$opt['items'] = max(0, (int) $opt['items']);
$opt['show_minor'] = (bool) $opt['show_minor'];
$opt['guardmail'] = ($conf['mailguard'] != '' && $conf['mailguard'] != 'none');
$type = valid_input_set(
'type', array(
'rss', 'rss2', 'atom', 'atom1', 'rss1',
'default' => $conf['rss_type']
),
$_REQUEST
);
switch($type) {
case 'rss':
$opt['feed_type'] = 'RSS0.91';
$opt['mime_type'] = 'text/xml';
break;
case 'rss2':
$opt['feed_type'] = 'RSS2.0';
$opt['mime_type'] = 'text/xml';
break;
case 'atom':
$opt['feed_type'] = 'ATOM0.3';
$opt['mime_type'] = 'application/xml';
break;
case 'atom1':
$opt['feed_type'] = 'ATOM1.0';
$opt['mime_type'] = 'application/atom+xml';
break;
default:
$opt['feed_type'] = 'RSS1.0';
$opt['mime_type'] = 'application/xml';
}
$eventData = array(
'opt' => &$opt,
);
trigger_event('FEED_OPTS_POSTPROCESS', $eventData);
return $opt;
}
/**
* Add recent changed pages to a feed object
*
* @author Andreas Gohr <andi@splitbrain.org>
* @param FeedCreator $rss the FeedCreator Object
* @param array $data the items to add
* @param array $opt the feed options
*/
function rss_buildItems(&$rss, &$data, $opt) {
global $conf;
global $lang;
/* @var auth_basic $auth */
global $auth;
$eventData = array(
'rss' => &$rss,
'data' => &$data,
'opt' => &$opt,
);
$event = new Doku_Event('FEED_DATA_PROCESS', $eventData);
if($event->advise_before(false)) {
foreach($data as $ditem) {
if(!is_array($ditem)) {
// not an array? then only a list of IDs was given
$ditem = array('id' => $ditem);
}
$item = new FeedItem();
$id = $ditem['id'];
if(!$ditem['media']) {
$meta = p_get_metadata($id);
} else {
$meta = array();
}
// add date
if($ditem['date']) {
$date = $ditem['date'];
} elseif ($ditem['media']) {
$date = @filemtime(mediaFN($id));
} elseif (@file_exists(wikiFN($id))) {
$date = @filemtime(wikiFN($id));
} elseif($meta['date']['modified']) {
$date = $meta['date']['modified'];
} else {
$date = 0;
}
if($date) $item->date = date('r', $date);
// add title
if($conf['useheading'] && $meta['title']) {
$item->title = $meta['title'];
} else {
$item->title = $ditem['id'];
}
if($conf['rss_show_summary'] && !empty($ditem['sum'])) {
$item->title .= ' - '.strip_tags($ditem['sum']);
}
// add item link
switch($opt['link_to']) {
case 'page':
if($ditem['media']) {
$item->link = media_managerURL(
array(
'image' => $id,
'ns' => getNS($id),
'rev' => $date
), '&', true
);
} else {
$item->link = wl($id, 'rev='.$date, true, '&');
}
break;
case 'rev':
if($ditem['media']) {
$item->link = media_managerURL(
array(
'image' => $id,
'ns' => getNS($id),
'rev' => $date,
'tab_details' => 'history'
), '&', true
);
} else {
$item->link = wl($id, 'do=revisions&rev='.$date, true, '&');
}
break;
case 'current':
if($ditem['media']) {
$item->link = media_managerURL(
array(
'image' => $id,
'ns' => getNS($id)
), '&', true
);
} else {
$item->link = wl($id, '', true, '&');
}
break;
case 'diff':
default:
if($ditem['media']) {
$item->link = media_managerURL(
array(
'image' => $id,
'ns' => getNS($id),
'rev' => $date,
'tab_details' => 'history',
'mediado' => 'diff'
), '&', true
);
} else {
$item->link = wl($id, 'rev='.$date.'&do=diff', true, '&');
}
}
// add item content
switch($opt['item_content']) {
case 'diff':
case 'htmldiff':
if($ditem['media']) {
$revs = getRevisions($id, 0, 1, 8192, true);
$rev = $revs[0];
$src_r = '';
$src_l = '';
if($size = media_image_preview_size($id, false, new JpegMeta(mediaFN($id)), 300)) {
$more = 'w='.$size[0].'&h='.$size[1].'t='.@filemtime(mediaFN($id));
$src_r = ml($id, $more);
}
if($rev && $size = media_image_preview_size($id, $rev, new JpegMeta(mediaFN($id, $rev)), 300)) {
$more = 'rev='.$rev.'&w='.$size[0].'&h='.$size[1];
$src_l = ml($id, $more);
}
$content = '';
if($src_r) {
$content = '<table>';
$content .= '<tr><th width="50%">'.$rev.'</th>';
$content .= '<th width="50%">'.$lang['current'].'</th></tr>';
$content .= '<tr align="center"><td><img src="'.$src_l.'" alt="" /></td><td>';
$content .= '<img src="'.$src_r.'" alt="'.$id.'" /></td></tr>';
$content .= '</table>';
}
} else {
require_once(DOKU_INC.'inc/DifferenceEngine.php');
$revs = getRevisions($id, 0, 1);
$rev = $revs[0];
if($rev) {
$df = new Diff(explode("\n", rawWiki($id, $rev)),
explode("\n", rawWiki($id, '')));
} else {
$df = new Diff(array(''),
explode("\n", rawWiki($id, '')));
}
if($opt['item_content'] == 'htmldiff') {
// note: no need to escape diff output, TableDiffFormatter provides 'safe' html
$tdf = new TableDiffFormatter();
$content = '<table>';
$content .= '<tr><th colspan="2" width="50%">'.$rev.'</th>';
$content .= '<th colspan="2" width="50%">'.$lang['current'].'</th></tr>';
$content .= $tdf->format($df);
$content .= '</table>';
} else {
// note: diff output must be escaped, UnifiedDiffFormatter provides plain text
$udf = new UnifiedDiffFormatter();
$content = "<pre>\n".hsc($udf->format($df))."\n</pre>";
}
}
break;
case 'html':
if($ditem['media']) {
if($size = media_image_preview_size($id, false, new JpegMeta(mediaFN($id)))) {
$more = 'w='.$size[0].'&h='.$size[1].'t='.@filemtime(mediaFN($id));
$src = ml($id, $more);
$content = '<img src="'.$src.'" alt="'.$id.'" />';
} else {
$content = '';
}
} else {
if (@filemtime(wikiFN($id)) === $date) {
$content = p_wiki_xhtml($id, '', false);
} else {
$content = p_wiki_xhtml($id, $date, false);
}
// no TOC in feeds
$content = preg_replace('/(<!-- TOC START -->).*(<!-- TOC END -->)/s', '', $content);
// add alignment for images
$content = preg_replace('/(<img .*?class="medialeft")/s', '\\1 align="left"', $content);
$content = preg_replace('/(<img .*?class="mediaright")/s', '\\1 align="right"', $content);
// make URLs work when canonical is not set, regexp instead of rerendering!
if(!$conf['canonical']) {
$base = preg_quote(DOKU_REL, '/');
$content = preg_replace('/(<a href|<img src)="('.$base.')/s', '$1="'.DOKU_URL, $content);
}
}
break;
case 'abstract':
default:
if($ditem['media']) {
if($size = media_image_preview_size($id, false, new JpegMeta(mediaFN($id)))) {
$more = 'w='.$size[0].'&h='.$size[1].'t='.@filemtime(mediaFN($id));
$src = ml($id, $more);
$content = '<img src="'.$src.'" alt="'.$id.'" />';
} else {
$content = '';
}
} else {
$content = $meta['description']['abstract'];
}
}
$item->description = $content; //FIXME a plugin hook here could be senseful
// add user
# FIXME should the user be pulled from metadata as well?
$user = @$ditem['user']; // the @ spares time repeating lookup
$item->author = '';
if($user && $conf['useacl'] && $auth) {
$userInfo = $auth->getUserData($user);
if($userInfo) {
switch($conf['showuseras']) {
case 'username':
$item->author = $userInfo['name'];
break;
default:
$item->author = $user;
break;
}
} else {
$item->author = $user;
}
if($userInfo && !$opt['guardmail']) {
$item->authorEmail = $userInfo['mail'];
} else {
//cannot obfuscate because some RSS readers may check validity
$item->authorEmail = $user.'@'.$ditem['ip'];
}
} elseif($user) {
// this happens when no ACL but some Apache auth is used
$item->author = $user;
$item->authorEmail = $user.'@'.$ditem['ip'];
} else {
$item->authorEmail = 'anonymous@'.$ditem['ip'];
}
// add category
if(isset($meta['subject'])) {
$item->category = $meta['subject'];
} else {
$cat = getNS($id);
if($cat) $item->category = $cat;
}
// finally add the item to the feed object, after handing it to registered plugins
$evdata = array(
'item' => &$item,
'opt' => &$opt,
'ditem' => &$ditem,
'rss' => &$rss
);
$evt = new Doku_Event('FEED_ITEM_ADD', $evdata);
if($evt->advise_before()) {
$rss->addItem($item);
}
$evt->advise_after(); // for completeness
}
}
$event->advise_after();
}
/**
* Add recent changed pages to the feed object
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function rssRecentChanges($opt) {
global $conf;
$flags = RECENTS_SKIP_DELETED;
if(!$opt['show_minor']) $flags += RECENTS_SKIP_MINORS;
if($opt['content_type'] == 'media' && $conf['mediarevisions']) $flags += RECENTS_MEDIA_CHANGES;
if($opt['content_type'] == 'both' && $conf['mediarevisions']) $flags += RECENTS_MEDIA_PAGES_MIXED;
$recents = getRecents(0, $opt['items'], $opt['namespace'], $flags);
return $recents;
}
/**
* Add all pages of a namespace to the feed object
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function rssListNamespace($opt) {
require_once(DOKU_INC.'inc/search.php');
global $conf;
$ns = ':'.cleanID($opt['namespace']);
$ns = str_replace(':', '/', $ns);
$data = array();
$search_opts = array(
'depth' => 1,
'pagesonly' => true,
'listfiles' => true
);
search($data, $conf['datadir'], 'search_universal', $search_opts, $ns);
return $data;
}
/**
* Add the result of a full text search to the feed object
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function rssSearch($opt) {
if(!$opt['search_query']) return array();
require_once(DOKU_INC.'inc/fulltext.php');
$data = ft_pageSearch($opt['search_query'], $poswords);
$data = array_keys($data);
return $data;
}
//Setup VIM: ex: et ts=4 :

3
sources/inc/.htaccess Normal file
View file

@ -0,0 +1,3 @@
## no access to the inc directory
order allow,deny
deny from all

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,191 @@
<?php
/**
* EmailAddressValidator Class
*
* @author Dave Child <dave@addedbytes.com>
* @link http://code.google.com/p/php-email-address-validation/
* @license http://www.opensource.org/licenses/bsd-license.php
* @version SVN r10 + Issue 15 fix + Issue 12 fix
*/
class EmailAddressValidator {
/**
* Set true to allow addresses like me@localhost
*/
public $allowLocalAddresses = false;
/**
* Check email address validity
* @param strEmailAddress Email address to be checked
* @return True if email is valid, false if not
*/
public function check_email_address($strEmailAddress) {
// If magic quotes is "on", email addresses with quote marks will
// fail validation because of added escape characters. Uncommenting
// the next three lines will allow for this issue.
//if (get_magic_quotes_gpc()) {
// $strEmailAddress = stripslashes($strEmailAddress);
//}
// Control characters are not allowed
if (preg_match('/[\x00-\x1F\x7F-\xFF]/', $strEmailAddress)) {
return false;
}
// Check email length - min 3 (a@a), max 256
if (!$this->check_text_length($strEmailAddress, 3, 256)) {
return false;
}
// Split it into sections using last instance of "@"
$intAtSymbol = strrpos($strEmailAddress, '@');
if ($intAtSymbol === false) {
// No "@" symbol in email.
return false;
}
$arrEmailAddress[0] = substr($strEmailAddress, 0, $intAtSymbol);
$arrEmailAddress[1] = substr($strEmailAddress, $intAtSymbol + 1);
// Count the "@" symbols. Only one is allowed, except where
// contained in quote marks in the local part. Quickest way to
// check this is to remove anything in quotes. We also remove
// characters escaped with backslash, and the backslash
// character.
$arrTempAddress[0] = preg_replace('/\./'
,''
,$arrEmailAddress[0]);
$arrTempAddress[0] = preg_replace('/"[^"]+"/'
,''
,$arrTempAddress[0]);
$arrTempAddress[1] = $arrEmailAddress[1];
$strTempAddress = $arrTempAddress[0] . $arrTempAddress[1];
// Then check - should be no "@" symbols.
if (strrpos($strTempAddress, '@') !== false) {
// "@" symbol found
return false;
}
// Check local portion
if (!$this->check_local_portion($arrEmailAddress[0])) {
return false;
}
// Check domain portion
if (!$this->check_domain_portion($arrEmailAddress[1])) {
return false;
}
// If we're still here, all checks above passed. Email is valid.
return true;
}
/**
* Checks email section before "@" symbol for validity
* @param strLocalPortion Text to be checked
* @return True if local portion is valid, false if not
*/
protected function check_local_portion($strLocalPortion) {
// Local portion can only be from 1 to 64 characters, inclusive.
// Please note that servers are encouraged to accept longer local
// parts than 64 characters.
if (!$this->check_text_length($strLocalPortion, 1, 64)) {
return false;
}
// Local portion must be:
// 1) a dot-atom (strings separated by periods)
// 2) a quoted string
// 3) an obsolete format string (combination of the above)
$arrLocalPortion = explode('.', $strLocalPortion);
for ($i = 0, $max = sizeof($arrLocalPortion); $i < $max; $i++) {
if (!preg_match('.^('
. '([A-Za-z0-9!#$%&\'*+/=?^_`{|}~-]'
. '[A-Za-z0-9!#$%&\'*+/=?^_`{|}~-]{0,63})'
.'|'
. '("[^\\\"]{0,62}")'
.')$.'
,$arrLocalPortion[$i])) {
return false;
}
}
return true;
}
/**
* Checks email section after "@" symbol for validity
* @param strDomainPortion Text to be checked
* @return True if domain portion is valid, false if not
*/
protected function check_domain_portion($strDomainPortion) {
// Total domain can only be from 1 to 255 characters, inclusive
if (!$this->check_text_length($strDomainPortion, 1, 255)) {
return false;
}
// some IPv4/v6 regexps borrowed from Feyd
// see: http://forums.devnetwork.net/viewtopic.php?f=38&t=53479
$dec_octet = '(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|[0-9])';
$hex_digit = '[A-Fa-f0-9]';
$h16 = "{$hex_digit}{1,4}";
$IPv4Address = "$dec_octet\\.$dec_octet\\.$dec_octet\\.$dec_octet";
$ls32 = "(?:$h16:$h16|$IPv4Address)";
$IPv6Address =
"(?:(?:{$IPv4Address})|(?:".
"(?:$h16:){6}$ls32" .
"|::(?:$h16:){5}$ls32" .
"|(?:$h16)?::(?:$h16:){4}$ls32" .
"|(?:(?:$h16:){0,1}$h16)?::(?:$h16:){3}$ls32" .
"|(?:(?:$h16:){0,2}$h16)?::(?:$h16:){2}$ls32" .
"|(?:(?:$h16:){0,3}$h16)?::(?:$h16:){1}$ls32" .
"|(?:(?:$h16:){0,4}$h16)?::$ls32" .
"|(?:(?:$h16:){0,5}$h16)?::$h16" .
"|(?:(?:$h16:){0,6}$h16)?::" .
")(?:\\/(?:12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))?)";
// Check if domain is IP, possibly enclosed in square brackets.
if (preg_match("/^($IPv4Address|\[$IPv4Address\]|\[$IPv6Address\])$/",
$strDomainPortion)){
return true;
} else {
$arrDomainPortion = explode('.', $strDomainPortion);
if (!$this->allowLocalAddresses && sizeof($arrDomainPortion) < 2) {
return false; // Not enough parts to domain
}
for ($i = 0, $max = sizeof($arrDomainPortion); $i < $max; $i++) {
// Each portion must be between 1 and 63 characters, inclusive
if (!$this->check_text_length($arrDomainPortion[$i], 1, 63)) {
return false;
}
if (!preg_match('/^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|'
.'([A-Za-z0-9]+))$/', $arrDomainPortion[$i])) {
return false;
}
if ($i == $max - 1) { // TLD cannot be only numbers
if (strlen(preg_replace('/[0-9]/', '', $arrDomainPortion[$i])) <= 0) {
return false;
}
}
}
}
return true;
}
/**
* Check given text length is between defined bounds
* @param strText Text to be checked
* @param intMinimum Minimum acceptable length
* @param intMaximum Maximum acceptable length
* @return True if string is within bounds (inclusive), false if not
*/
protected function check_text_length($strText, $intMinimum, $intMaximum) {
// Minimum and maximum are both inclusive
$intTextLength = strlen($strText);
if (($intTextLength < $intMinimum) || ($intTextLength > $intMaximum)) {
return false;
} else {
return true;
}
}
}

View file

@ -0,0 +1,76 @@
<?php
/**
* Class used to parse RSS and ATOM feeds
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
if(!defined('DOKU_INC')) die('meh.');
/**
* We override some methods of the original SimplePie class here
*/
class FeedParser extends SimplePie {
/**
* Constructor. Set some defaults
*/
function __construct(){
parent::__construct();
$this->enable_cache(false);
$this->set_file_class('FeedParser_File');
}
/**
* Backward compatibility for older plugins
*/
function feed_url($url){
$this->set_feed_url($url);
}
}
/**
* Fetch an URL using our own HTTPClient
*
* Replaces SimplePie's own class
*/
class FeedParser_File extends SimplePie_File {
var $http;
var $useragent;
var $success = true;
var $headers = array();
var $body;
var $error;
/**
* Inititializes the HTTPClient
*
* We ignore all given parameters - they are set in DokuHTTPClient
*/
function __construct($url, $timeout=10, $redirects=5,
$headers=null, $useragent=null, $force_fsockopen=false) {
$this->http = new DokuHTTPClient();
$this->success = $this->http->sendRequest($url);
$this->headers = $this->http->resp_headers;
$this->body = $this->http->resp_body;
$this->error = $this->http->error;
$this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
return $this->success;
}
function headers(){
return $this->headers;
}
function body(){
return $this->body;
}
function close(){
return true;
}
}

856
sources/inc/HTTPClient.php Normal file
View file

@ -0,0 +1,856 @@
<?php
/**
* HTTP Client
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Andreas Goetz <cpuidle@gmx.de>
*/
define('HTTP_NL',"\r\n");
/**
* Adds DokuWiki specific configs to the HTTP client
*
* @author Andreas Goetz <cpuidle@gmx.de>
*/
class DokuHTTPClient extends HTTPClient {
/**
* Constructor.
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function __construct(){
global $conf;
// call parent constructor
parent::__construct();
// set some values from the config
$this->proxy_host = $conf['proxy']['host'];
$this->proxy_port = $conf['proxy']['port'];
$this->proxy_user = $conf['proxy']['user'];
$this->proxy_pass = conf_decodeString($conf['proxy']['pass']);
$this->proxy_ssl = $conf['proxy']['ssl'];
$this->proxy_except = $conf['proxy']['except'];
}
/**
* Wraps an event around the parent function
*
* @triggers HTTPCLIENT_REQUEST_SEND
* @author Andreas Gohr <andi@splitbrain.org>
*/
function sendRequest($url,$data='',$method='GET'){
$httpdata = array('url' => $url,
'data' => $data,
'method' => $method);
$evt = new Doku_Event('HTTPCLIENT_REQUEST_SEND',$httpdata);
if($evt->advise_before()){
$url = $httpdata['url'];
$data = $httpdata['data'];
$method = $httpdata['method'];
}
$evt->advise_after();
unset($evt);
return parent::sendRequest($url,$data,$method);
}
}
class HTTPClientException extends Exception { }
/**
* This class implements a basic HTTP client
*
* It supports POST and GET, Proxy usage, basic authentication,
* handles cookies and referers. It is based upon the httpclient
* function from the VideoDB project.
*
* @link http://www.splitbrain.org/go/videodb
* @author Andreas Goetz <cpuidle@gmx.de>
* @author Andreas Gohr <andi@splitbrain.org>
* @author Tobias Sarnowski <sarnowski@new-thoughts.org>
*/
class HTTPClient {
//set these if you like
var $agent; // User agent
var $http; // HTTP version defaults to 1.0
var $timeout; // read timeout (seconds)
var $cookies;
var $referer;
var $max_redirect;
var $max_bodysize;
var $max_bodysize_abort = true; // if set, abort if the response body is bigger than max_bodysize
var $header_regexp; // if set this RE must match against the headers, else abort
var $headers;
var $debug;
var $start = 0; // for timings
var $keep_alive = true; // keep alive rocks
// don't set these, read on error
var $error;
var $redirect_count;
// read these after a successful request
var $status;
var $resp_body;
var $resp_headers;
// set these to do basic authentication
var $user;
var $pass;
// set these if you need to use a proxy
var $proxy_host;
var $proxy_port;
var $proxy_user;
var $proxy_pass;
var $proxy_ssl; //boolean set to true if your proxy needs SSL
var $proxy_except; // regexp of URLs to exclude from proxy
// list of kept alive connections
static $connections = array();
// what we use as boundary on multipart/form-data posts
var $boundary = '---DokuWikiHTTPClient--4523452351';
/**
* Constructor.
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function __construct(){
$this->agent = 'Mozilla/4.0 (compatible; DokuWiki HTTP Client; '.PHP_OS.')';
$this->timeout = 15;
$this->cookies = array();
$this->referer = '';
$this->max_redirect = 3;
$this->redirect_count = 0;
$this->status = 0;
$this->headers = array();
$this->http = '1.0';
$this->debug = false;
$this->max_bodysize = 0;
$this->header_regexp= '';
if(extension_loaded('zlib')) $this->headers['Accept-encoding'] = 'gzip';
$this->headers['Accept'] = 'text/xml,application/xml,application/xhtml+xml,'.
'text/html,text/plain,image/png,image/jpeg,image/gif,*/*';
$this->headers['Accept-Language'] = 'en-us';
}
/**
* Simple function to do a GET request
*
* Returns the wanted page or false on an error;
*
* @param string $url The URL to fetch
* @param bool $sloppy304 Return body on 304 not modified
* @return bool|string response body, false on error
* @author Andreas Gohr <andi@splitbrain.org>
*/
function get($url,$sloppy304=false){
if(!$this->sendRequest($url)) return false;
if($this->status == 304 && $sloppy304) return $this->resp_body;
if($this->status < 200 || $this->status > 206) return false;
return $this->resp_body;
}
/**
* Simple function to do a GET request with given parameters
*
* Returns the wanted page or false on an error.
*
* This is a convenience wrapper around get(). The given parameters
* will be correctly encoded and added to the given base URL.
*
* @param string $url The URL to fetch
* @param array $data Associative array of parameters
* @param bool $sloppy304 Return body on 304 not modified
* @return bool|string response body, false on error
* @author Andreas Gohr <andi@splitbrain.org>
*/
function dget($url,$data,$sloppy304=false){
if(strpos($url,'?')){
$url .= '&';
}else{
$url .= '?';
}
$url .= $this->_postEncode($data);
return $this->get($url,$sloppy304);
}
/**
* Simple function to do a POST request
*
* Returns the resulting page or false on an error;
*
* @param string $url The URL to fetch
* @param array $data Associative array of parameters
* @return bool|string response body, false on error
* @author Andreas Gohr <andi@splitbrain.org>
*/
function post($url,$data){
if(!$this->sendRequest($url,$data,'POST')) return false;
if($this->status < 200 || $this->status > 206) return false;
return $this->resp_body;
}
/**
* Send an HTTP request
*
* This method handles the whole HTTP communication. It respects set proxy settings,
* builds the request headers, follows redirects and parses the response.
*
* Post data should be passed as associative array. When passed as string it will be
* sent as is. You will need to setup your own Content-Type header then.
*
* @param string $url - the complete URL
* @param mixed $data - the post data either as array or raw data
* @param string $method - HTTP Method usually GET or POST.
* @return bool - true on success
* @author Andreas Goetz <cpuidle@gmx.de>
* @author Andreas Gohr <andi@splitbrain.org>
*/
function sendRequest($url,$data='',$method='GET'){
$this->start = $this->_time();
$this->error = '';
$this->status = 0;
$this->status = 0;
$this->resp_body = '';
$this->resp_headers = array();
// don't accept gzip if truncated bodies might occur
if($this->max_bodysize &&
!$this->max_bodysize_abort &&
$this->headers['Accept-encoding'] == 'gzip'){
unset($this->headers['Accept-encoding']);
}
// parse URL into bits
$uri = parse_url($url);
$server = $uri['host'];
$path = $uri['path'];
if(empty($path)) $path = '/';
if(!empty($uri['query'])) $path .= '?'.$uri['query'];
if(!empty($uri['port'])) $port = $uri['port'];
if(isset($uri['user'])) $this->user = $uri['user'];
if(isset($uri['pass'])) $this->pass = $uri['pass'];
// proxy setup
if($this->proxy_host && (!$this->proxy_except || !preg_match('/'.$this->proxy_except.'/i',$url)) ){
$request_url = $url;
$server = $this->proxy_host;
$port = $this->proxy_port;
if (empty($port)) $port = 8080;
}else{
$request_url = $path;
$server = $server;
if (!isset($port)) $port = ($uri['scheme'] == 'https') ? 443 : 80;
}
// add SSL stream prefix if needed - needs SSL support in PHP
if($port == 443 || $this->proxy_ssl) $server = 'ssl://'.$server;
// prepare headers
$headers = $this->headers;
$headers['Host'] = $uri['host'];
if(!empty($uri['port'])) $headers['Host'].= ':'.$uri['port'];
$headers['User-Agent'] = $this->agent;
$headers['Referer'] = $this->referer;
if($method == 'POST'){
if(is_array($data)){
if($headers['Content-Type'] == 'multipart/form-data'){
$headers['Content-Type'] = 'multipart/form-data; boundary='.$this->boundary;
$data = $this->_postMultipartEncode($data);
}else{
$headers['Content-Type'] = 'application/x-www-form-urlencoded';
$data = $this->_postEncode($data);
}
}
$headers['Content-Length'] = strlen($data);
$rmethod = 'POST';
}elseif($method == 'GET'){
$data = ''; //no data allowed on GET requests
}
if($this->user) {
$headers['Authorization'] = 'Basic '.base64_encode($this->user.':'.$this->pass);
}
if($this->proxy_user) {
$headers['Proxy-Authorization'] = 'Basic '.base64_encode($this->proxy_user.':'.$this->proxy_pass);
}
// already connected?
$connectionId = $this->_uniqueConnectionId($server,$port);
$this->_debug('connection pool', self::$connections);
$socket = null;
if (isset(self::$connections[$connectionId])) {
$this->_debug('reusing connection', $connectionId);
$socket = self::$connections[$connectionId];
}
if (is_null($socket) || feof($socket)) {
$this->_debug('opening connection', $connectionId);
// open socket
$socket = @fsockopen($server,$port,$errno, $errstr, $this->timeout);
if (!$socket){
$this->status = -100;
$this->error = "Could not connect to $server:$port\n$errstr ($errno)";
return false;
}
// try establish a CONNECT tunnel for SSL
if($this->_ssltunnel($socket, $request_url)){
// no keep alive for tunnels
$this->keep_alive = false;
// tunnel is authed already
if(isset($headers['Proxy-Authentication'])) unset($headers['Proxy-Authentication']);
}
// keep alive?
if ($this->keep_alive) {
self::$connections[$connectionId] = $socket;
} else {
unset(self::$connections[$connectionId]);
}
}
if ($this->keep_alive && !$this->proxy_host) {
// RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive
// connection token to a proxy server. We still do keep the connection the
// proxy alive (well except for CONNECT tunnels)
$headers['Connection'] = 'Keep-Alive';
} else {
$headers['Connection'] = 'Close';
}
try {
//set non-blocking
stream_set_blocking($socket, false);
// build request
$request = "$method $request_url HTTP/".$this->http.HTTP_NL;
$request .= $this->_buildHeaders($headers);
$request .= $this->_getCookies();
$request .= HTTP_NL;
$request .= $data;
$this->_debug('request',$request);
$this->_sendData($socket, $request, 'request');
// read headers from socket
$r_headers = '';
do{
$r_line = $this->_readLine($socket, 'headers');
$r_headers .= $r_line;
}while($r_line != "\r\n" && $r_line != "\n");
$this->_debug('response headers',$r_headers);
// check if expected body size exceeds allowance
if($this->max_bodysize && preg_match('/\r?\nContent-Length:\s*(\d+)\r?\n/i',$r_headers,$match)){
if($match[1] > $this->max_bodysize){
if ($this->max_bodysize_abort)
throw new HTTPClientException('Reported content length exceeds allowed response size');
else
$this->error = 'Reported content length exceeds allowed response size';
}
}
// get Status
if (!preg_match('/^HTTP\/(\d\.\d)\s*(\d+).*?\n/', $r_headers, $m))
throw new HTTPClientException('Server returned bad answer');
$this->status = $m[2];
// handle headers and cookies
$this->resp_headers = $this->_parseHeaders($r_headers);
if(isset($this->resp_headers['set-cookie'])){
foreach ((array) $this->resp_headers['set-cookie'] as $cookie){
list($cookie) = explode(';',$cookie,2);
list($key,$val) = explode('=',$cookie,2);
$key = trim($key);
if($val == 'deleted'){
if(isset($this->cookies[$key])){
unset($this->cookies[$key]);
}
}elseif($key){
$this->cookies[$key] = $val;
}
}
}
$this->_debug('Object headers',$this->resp_headers);
// check server status code to follow redirect
if($this->status == 301 || $this->status == 302 ){
if (empty($this->resp_headers['location'])){
throw new HTTPClientException('Redirect but no Location Header found');
}elseif($this->redirect_count == $this->max_redirect){
throw new HTTPClientException('Maximum number of redirects exceeded');
}else{
// close the connection because we don't handle content retrieval here
// that's the easiest way to clean up the connection
fclose($socket);
unset(self::$connections[$connectionId]);
$this->redirect_count++;
$this->referer = $url;
// handle non-RFC-compliant relative redirects
if (!preg_match('/^http/i', $this->resp_headers['location'])){
if($this->resp_headers['location'][0] != '/'){
$this->resp_headers['location'] = $uri['scheme'].'://'.$uri['host'].':'.$uri['port'].
dirname($uri['path']).'/'.$this->resp_headers['location'];
}else{
$this->resp_headers['location'] = $uri['scheme'].'://'.$uri['host'].':'.$uri['port'].
$this->resp_headers['location'];
}
}
// perform redirected request, always via GET (required by RFC)
return $this->sendRequest($this->resp_headers['location'],array(),'GET');
}
}
// check if headers are as expected
if($this->header_regexp && !preg_match($this->header_regexp,$r_headers))
throw new HTTPClientException('The received headers did not match the given regexp');
//read body (with chunked encoding if needed)
$r_body = '';
if((isset($this->resp_headers['transfer-encoding']) && $this->resp_headers['transfer-encoding'] == 'chunked')
|| (isset($this->resp_headers['transfer-coding']) && $this->resp_headers['transfer-coding'] == 'chunked')){
$abort = false;
do {
$chunk_size = '';
while (preg_match('/^[a-zA-Z0-9]?$/',$byte=$this->_readData($socket,1,'chunk'))){
// read chunksize until \r
$chunk_size .= $byte;
if (strlen($chunk_size) > 128) // set an abritrary limit on the size of chunks
throw new HTTPClientException('Allowed response size exceeded');
}
$this->_readLine($socket, 'chunk'); // readtrailing \n
$chunk_size = hexdec($chunk_size);
if($this->max_bodysize && $chunk_size+strlen($r_body) > $this->max_bodysize){
if ($this->max_bodysize_abort)
throw new HTTPClientException('Allowed response size exceeded');
$this->error = 'Allowed response size exceeded';
$chunk_size = $this->max_bodysize - strlen($r_body);
$abort = true;
}
if ($chunk_size > 0) {
$r_body .= $this->_readData($socket, $chunk_size, 'chunk');
$byte = $this->_readData($socket, 2, 'chunk'); // read trailing \r\n
}
} while ($chunk_size && !$abort);
}elseif(isset($this->resp_headers['content-length']) && !isset($this->resp_headers['transfer-encoding'])){
/* RFC 2616
* If a message is received with both a Transfer-Encoding header field and a Content-Length
* header field, the latter MUST be ignored.
*/
// read up to the content-length or max_bodysize
// for keep alive we need to read the whole message to clean up the socket for the next read
if(!$this->keep_alive && $this->max_bodysize && $this->max_bodysize < $this->resp_headers['content-length']){
$length = $this->max_bodysize;
}else{
$length = $this->resp_headers['content-length'];
}
$r_body = $this->_readData($socket, $length, 'response (content-length limited)', true);
}elseif( !isset($this->resp_headers['transfer-encoding']) && $this->max_bodysize && !$this->keep_alive){
$r_body = $this->_readData($socket, $this->max_bodysize, 'response (content-length limited)', true);
}else{
// read entire socket
$r_size = 0;
while (!feof($socket)) {
$r_body .= $this->_readData($socket, 4096, 'response (unlimited)', true);
}
}
// recheck body size, we might had to read the whole body, so we abort late or trim here
if($this->max_bodysize){
if(strlen($r_body) > $this->max_bodysize){
if ($this->max_bodysize_abort) {
throw new HTTPClientException('Allowed response size exceeded');
} else {
$this->error = 'Allowed response size exceeded';
}
}
}
} catch (HTTPClientException $err) {
$this->error = $err->getMessage();
if ($err->getCode())
$this->status = $err->getCode();
unset(self::$connections[$connectionId]);
fclose($socket);
return false;
}
if (!$this->keep_alive ||
(isset($this->resp_headers['connection']) && $this->resp_headers['connection'] == 'Close')) {
// close socket
$status = socket_get_status($socket);
fclose($socket);
unset(self::$connections[$connectionId]);
}
// decode gzip if needed
if(isset($this->resp_headers['content-encoding']) &&
$this->resp_headers['content-encoding'] == 'gzip' &&
strlen($r_body) > 10 && substr($r_body,0,3)=="\x1f\x8b\x08"){
$this->resp_body = @gzinflate(substr($r_body, 10));
if($this->resp_body === false){
$this->error = 'Failed to decompress gzip encoded content';
$this->resp_body = $r_body;
}
}else{
$this->resp_body = $r_body;
}
$this->_debug('response body',$this->resp_body);
$this->redirect_count = 0;
return true;
}
/**
* Tries to establish a CONNECT tunnel via Proxy
*
* Protocol, Servername and Port will be stripped from the request URL when a successful CONNECT happened
*
* @param resource &$socket
* @param string &$requesturl
* @return bool true if a tunnel was established
*/
function _ssltunnel(&$socket, &$requesturl){
if(!$this->proxy_host) return false;
$requestinfo = parse_url($requesturl);
if($requestinfo['scheme'] != 'https') return false;
if(!$requestinfo['port']) $requestinfo['port'] = 443;
// build request
$request = "CONNECT {$requestinfo['host']}:{$requestinfo['port']} HTTP/1.0".HTTP_NL;
$request .= "Host: {$requestinfo['host']}".HTTP_NL;
if($this->proxy_user) {
'Proxy-Authorization Basic '.base64_encode($this->proxy_user.':'.$this->proxy_pass).HTTP_NL;
}
$request .= HTTP_NL;
$this->_debug('SSL Tunnel CONNECT',$request);
$this->_sendData($socket, $request, 'SSL Tunnel CONNECT');
// read headers from socket
$r_headers = '';
do{
$r_line = $this->_readLine($socket, 'headers');
$r_headers .= $r_line;
}while($r_line != "\r\n" && $r_line != "\n");
$this->_debug('SSL Tunnel Response',$r_headers);
if(preg_match('/^HTTP\/1\.[01] 200/i',$r_headers)){
if (stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_SSLv3_CLIENT)) {
$requesturl = $requestinfo['path'];
return true;
}
}
return false;
}
/**
* Safely write data to a socket
*
* @param resource $socket An open socket handle
* @param string $data The data to write
* @param string $message Description of what is being read
* @throws HTTPClientException
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function _sendData($socket, $data, $message) {
// send request
$towrite = strlen($data);
$written = 0;
while($written < $towrite){
// check timeout
$time_used = $this->_time() - $this->start;
if($time_used > $this->timeout)
throw new HTTPClientException(sprintf('Timeout while sending %s (%.3fs)',$message, $time_used), -100);
if(feof($socket))
throw new HTTPClientException("Socket disconnected while writing $message");
// select parameters
$sel_r = null;
$sel_w = array($socket);
$sel_e = null;
// wait for stream ready or timeout (1sec)
if(@stream_select($sel_r,$sel_w,$sel_e,1) === false){
usleep(1000);
continue;
}
// write to stream
$nbytes = fwrite($socket, substr($data,$written,4096));
if($nbytes === false)
throw new HTTPClientException("Failed writing to socket while sending $message", -100);
$written += $nbytes;
}
}
/**
* Safely read data from a socket
*
* Reads up to a given number of bytes or throws an exception if the
* response times out or ends prematurely.
*
* @param resource $socket An open socket handle in non-blocking mode
* @param int $nbytes Number of bytes to read
* @param string $message Description of what is being read
* @param bool $ignore_eof End-of-file is not an error if this is set
* @throws HTTPClientException
* @return string
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function _readData($socket, $nbytes, $message, $ignore_eof = false) {
$r_data = '';
// Does not return immediately so timeout and eof can be checked
if ($nbytes < 0) $nbytes = 0;
$to_read = $nbytes;
do {
$time_used = $this->_time() - $this->start;
if ($time_used > $this->timeout)
throw new HTTPClientException(
sprintf('Timeout while reading %s after %d bytes (%.3fs)', $message,
strlen($r_data), $time_used), -100);
if(feof($socket)) {
if(!$ignore_eof)
throw new HTTPClientException("Premature End of File (socket) while reading $message");
break;
}
if ($to_read > 0) {
// select parameters
$sel_r = array($socket);
$sel_w = null;
$sel_e = null;
// wait for stream ready or timeout (1sec)
if(@stream_select($sel_r,$sel_w,$sel_e,1) === false){
usleep(1000);
continue;
}
$bytes = fread($socket, $to_read);
if($bytes === false)
throw new HTTPClientException("Failed reading from socket while reading $message", -100);
$r_data .= $bytes;
$to_read -= strlen($bytes);
}
} while ($to_read > 0 && strlen($r_data) < $nbytes);
return $r_data;
}
/**
* Safely read a \n-terminated line from a socket
*
* Always returns a complete line, including the terminating \n.
*
* @param resource $socket An open socket handle in non-blocking mode
* @param string $message Description of what is being read
* @throws HTTPClientException
* @return string
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function _readLine($socket, $message) {
$r_data = '';
do {
$time_used = $this->_time() - $this->start;
if ($time_used > $this->timeout)
throw new HTTPClientException(
sprintf('Timeout while reading %s (%.3fs) >%s<', $message, $time_used, $r_data),
-100);
if(feof($socket))
throw new HTTPClientException("Premature End of File (socket) while reading $message");
// select parameters
$sel_r = array($socket);
$sel_w = null;
$sel_e = null;
// wait for stream ready or timeout (1sec)
if(@stream_select($sel_r,$sel_w,$sel_e,1) === false){
usleep(1000);
continue;
}
$r_data = fgets($socket, 1024);
} while (!preg_match('/\n$/',$r_data));
return $r_data;
}
/**
* print debug info
*
* Uses _debug_text or _debug_html depending on the SAPI name
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function _debug($info,$var=null){
if(!$this->debug) return;
if(php_sapi_name() == 'cli'){
$this->_debug_text($info, $var);
}else{
$this->_debug_html($info, $var);
}
}
/**
* print debug info as HTML
*
* @param $info
* @param null $var
*/
function _debug_html($info, $var=null){
print '<b>'.$info.'</b> '.($this->_time() - $this->start).'s<br />';
if(!is_null($var)){
ob_start();
print_r($var);
$content = htmlspecialchars(ob_get_contents());
ob_end_clean();
print '<pre>'.$content.'</pre>';
}
}
/**
* prints debug info as plain text
*
* @param $info
* @param null $var
*/
function _debug_text($info, $var=null){
print '*'.$info.'* '.($this->_time() - $this->start)."s\n";
if(!is_null($var)) print_r($var);
print "\n-----------------------------------------------\n";
}
/**
* Return current timestamp in microsecond resolution
*/
static function _time(){
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
/**
* convert given header string to Header array
*
* All Keys are lowercased.
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function _parseHeaders($string){
$headers = array();
$lines = explode("\n",$string);
array_shift($lines); //skip first line (status)
foreach($lines as $line){
@list($key, $val) = explode(':',$line,2);
$key = trim($key);
$val = trim($val);
$key = strtolower($key);
if(!$key) continue;
if(isset($headers[$key])){
if(is_array($headers[$key])){
$headers[$key][] = $val;
}else{
$headers[$key] = array($headers[$key],$val);
}
}else{
$headers[$key] = $val;
}
}
return $headers;
}
/**
* convert given header array to header string
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function _buildHeaders($headers){
$string = '';
foreach($headers as $key => $value){
if(empty($value)) continue;
$string .= $key.': '.$value.HTTP_NL;
}
return $string;
}
/**
* get cookies as http header string
*
* @author Andreas Goetz <cpuidle@gmx.de>
*/
function _getCookies(){
$headers = '';
foreach ($this->cookies as $key => $val){
$headers .= "$key=$val; ";
}
$headers = substr($headers, 0, -2);
if ($headers) $headers = "Cookie: $headers".HTTP_NL;
return $headers;
}
/**
* Encode data for posting
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function _postEncode($data){
return http_build_query($data,'','&');
}
/**
* Encode data for posting using multipart encoding
*
* @fixme use of urlencode might be wrong here
* @author Andreas Gohr <andi@splitbrain.org>
*/
function _postMultipartEncode($data){
$boundary = '--'.$this->boundary;
$out = '';
foreach($data as $key => $val){
$out .= $boundary.HTTP_NL;
if(!is_array($val)){
$out .= 'Content-Disposition: form-data; name="'.urlencode($key).'"'.HTTP_NL;
$out .= HTTP_NL; // end of headers
$out .= $val;
$out .= HTTP_NL;
}else{
$out .= 'Content-Disposition: form-data; name="'.urlencode($key).'"';
if($val['filename']) $out .= '; filename="'.urlencode($val['filename']).'"';
$out .= HTTP_NL;
if($val['mimetype']) $out .= 'Content-Type: '.$val['mimetype'].HTTP_NL;
$out .= HTTP_NL; // end of headers
$out .= $val['body'];
$out .= HTTP_NL;
}
}
$out .= "$boundary--".HTTP_NL;
return $out;
}
/**
* Generates a unique identifier for a connection.
*
* @param string $server
* @param string $port
* @return string unique identifier
*/
function _uniqueConnectionId($server, $port) {
return "$server:$port";
}
}
//Setup VIM: ex: et ts=4 :

817
sources/inc/IXR_Library.php Normal file
View file

@ -0,0 +1,817 @@
<?php
/**
* IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
*
* @version 1.61
* @author Simon Willison
* @date 11th July 2003
* @link http://scripts.incutio.com/xmlrpc/
* @link http://scripts.incutio.com/xmlrpc/manual.php
* @license Artistic License http://www.opensource.org/licenses/artistic-license.php
*
* Modified for DokuWiki
* @author Andreas Gohr <andi@splitbrain.org>
*/
class IXR_Value {
var $data;
var $type;
function IXR_Value ($data, $type = false) {
$this->data = $data;
if (!$type) {
$type = $this->calculateType();
}
$this->type = $type;
if ($type == 'struct') {
/* Turn all the values in the array in to new IXR_Value objects */
foreach ($this->data as $key => $value) {
$this->data[$key] = new IXR_Value($value);
}
}
if ($type == 'array') {
for ($i = 0, $j = count($this->data); $i < $j; $i++) {
$this->data[$i] = new IXR_Value($this->data[$i]);
}
}
}
function calculateType() {
if ($this->data === true || $this->data === false) {
return 'boolean';
}
if (is_integer($this->data)) {
return 'int';
}
if (is_double($this->data)) {
return 'double';
}
// Deal with IXR object types base64 and date
if (is_object($this->data) && is_a($this->data, 'IXR_Date')) {
return 'date';
}
if (is_object($this->data) && is_a($this->data, 'IXR_Base64')) {
return 'base64';
}
// If it is a normal PHP object convert it in to a struct
if (is_object($this->data)) {
$this->data = get_object_vars($this->data);
return 'struct';
}
if (!is_array($this->data)) {
return 'string';
}
/* We have an array - is it an array or a struct ? */
if ($this->isStruct($this->data)) {
return 'struct';
} else {
return 'array';
}
}
function getXml() {
/* Return XML for this value */
switch ($this->type) {
case 'boolean':
return '<boolean>'.(($this->data) ? '1' : '0').'</boolean>';
break;
case 'int':
return '<int>'.$this->data.'</int>';
break;
case 'double':
return '<double>'.$this->data.'</double>';
break;
case 'string':
return '<string>'.htmlspecialchars($this->data).'</string>';
break;
case 'array':
$return = '<array><data>'."\n";
foreach ($this->data as $item) {
$return .= ' <value>'.$item->getXml()."</value>\n";
}
$return .= '</data></array>';
return $return;
break;
case 'struct':
$return = '<struct>'."\n";
foreach ($this->data as $name => $value) {
$return .= " <member><name>$name</name><value>";
$return .= $value->getXml()."</value></member>\n";
}
$return .= '</struct>';
return $return;
break;
case 'date':
case 'base64':
return $this->data->getXml();
break;
}
return false;
}
function isStruct($array) {
/* Nasty function to check if an array is a struct or not */
$expected = 0;
foreach ($array as $key => $value) {
if ((string)$key != (string)$expected) {
return true;
}
$expected++;
}
return false;
}
}
class IXR_Message {
var $message;
var $messageType; // methodCall / methodResponse / fault
var $faultCode;
var $faultString;
var $methodName;
var $params;
// Current variable stacks
var $_arraystructs = array(); // The stack used to keep track of the current array/struct
var $_arraystructstypes = array(); // Stack keeping track of if things are structs or array
var $_currentStructName = array(); // A stack as well
var $_param;
var $_value;
var $_currentTag;
var $_currentTagContents;
var $_lastseen;
// The XML parser
var $_parser;
function IXR_Message ($message) {
$this->message = $message;
}
function parse() {
// first remove the XML declaration
$this->message = preg_replace('/<\?xml(.*)?\?'.'>/', '', $this->message);
// workaround for a bug in PHP/libxml2, see http://bugs.php.net/bug.php?id=45996
$this->message = str_replace('&lt;', '&#60;', $this->message);
$this->message = str_replace('&gt;', '&#62;', $this->message);
$this->message = str_replace('&amp;', '&#38;', $this->message);
$this->message = str_replace('&apos;', '&#39;', $this->message);
$this->message = str_replace('&quot;', '&#34;', $this->message);
$this->message = str_replace("\x0b", ' ', $this->message); //vertical tab
if (trim($this->message) == '') {
return false;
}
$this->_parser = xml_parser_create();
// Set XML parser to take the case of tags in to account
xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false);
// Set XML parser callback functions
xml_set_object($this->_parser, $this);
xml_set_element_handler($this->_parser, 'tag_open', 'tag_close');
xml_set_character_data_handler($this->_parser, 'cdata');
if (!xml_parse($this->_parser, $this->message)) {
/* die(sprintf('XML error: %s at line %d',
xml_error_string(xml_get_error_code($this->_parser)),
xml_get_current_line_number($this->_parser))); */
return false;
}
xml_parser_free($this->_parser);
// Grab the error messages, if any
if ($this->messageType == 'fault') {
$this->faultCode = $this->params[0]['faultCode'];
$this->faultString = $this->params[0]['faultString'];
}
return true;
}
function tag_open($parser, $tag, $attr) {
$this->currentTag = $tag;
$this->_currentTagContents = '';
switch($tag) {
case 'methodCall':
case 'methodResponse':
case 'fault':
$this->messageType = $tag;
break;
/* Deal with stacks of arrays and structs */
case 'data': // data is to all intents and puposes more interesting than array
$this->_arraystructstypes[] = 'array';
$this->_arraystructs[] = array();
break;
case 'struct':
$this->_arraystructstypes[] = 'struct';
$this->_arraystructs[] = array();
break;
}
$this->_lastseen = $tag;
}
function cdata($parser, $cdata) {
$this->_currentTagContents .= $cdata;
}
function tag_close($parser, $tag) {
$valueFlag = false;
switch($tag) {
case 'int':
case 'i4':
$value = (int)trim($this->_currentTagContents);
$this->_currentTagContents = '';
$valueFlag = true;
break;
case 'double':
$value = (double)trim($this->_currentTagContents);
$this->_currentTagContents = '';
$valueFlag = true;
break;
case 'string':
$value = (string)$this->_currentTagContents;
$this->_currentTagContents = '';
$valueFlag = true;
break;
case 'dateTime.iso8601':
$value = new IXR_Date(trim($this->_currentTagContents));
// $value = $iso->getTimestamp();
$this->_currentTagContents = '';
$valueFlag = true;
break;
case 'value':
// "If no type is indicated, the type is string."
if($this->_lastseen == 'value'){
$value = (string)$this->_currentTagContents;
$this->_currentTagContents = '';
$valueFlag = true;
}
break;
case 'boolean':
$value = (boolean)trim($this->_currentTagContents);
$this->_currentTagContents = '';
$valueFlag = true;
break;
case 'base64':
$value = base64_decode($this->_currentTagContents);
$this->_currentTagContents = '';
$valueFlag = true;
break;
/* Deal with stacks of arrays and structs */
case 'data':
case 'struct':
$value = array_pop($this->_arraystructs);
array_pop($this->_arraystructstypes);
$valueFlag = true;
break;
case 'member':
array_pop($this->_currentStructName);
break;
case 'name':
$this->_currentStructName[] = trim($this->_currentTagContents);
$this->_currentTagContents = '';
break;
case 'methodName':
$this->methodName = trim($this->_currentTagContents);
$this->_currentTagContents = '';
break;
}
if ($valueFlag) {
/*
if (!is_array($value) && !is_object($value)) {
$value = trim($value);
}
*/
if (count($this->_arraystructs) > 0) {
// Add value to struct or array
if ($this->_arraystructstypes[count($this->_arraystructstypes)-1] == 'struct') {
// Add to struct
$this->_arraystructs[count($this->_arraystructs)-1][$this->_currentStructName[count($this->_currentStructName)-1]] = $value;
} else {
// Add to array
$this->_arraystructs[count($this->_arraystructs)-1][] = $value;
}
} else {
// Just add as a paramater
$this->params[] = $value;
}
}
$this->_lastseen = $tag;
}
}
class IXR_Server {
var $data;
var $callbacks = array();
var $message;
var $capabilities;
function IXR_Server($callbacks = false, $data = false) {
$this->setCapabilities();
if ($callbacks) {
$this->callbacks = $callbacks;
}
$this->setCallbacks();
$this->serve($data);
}
function serve($data = false) {
if (!$data) {
$postData = trim(http_get_raw_post_data());
if (!$postData) {
die('XML-RPC server accepts POST requests only.');
}
$data = $postData;
}
$this->message = new IXR_Message($data);
if (!$this->message->parse()) {
$this->error(-32700, 'parse error. not well formed');
}
if ($this->message->messageType != 'methodCall') {
$this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall');
}
$result = $this->call($this->message->methodName, $this->message->params);
// Is the result an error?
if (is_a($result, 'IXR_Error')) {
$this->error($result);
}
// Encode the result
$r = new IXR_Value($result);
$resultxml = $r->getXml();
// Create the XML
$xml = <<<EOD
<methodResponse>
<params>
<param>
<value>
$resultxml
</value>
</param>
</params>
</methodResponse>
EOD;
// Send it
$this->output($xml);
}
function call($methodname, $args) {
if (!$this->hasMethod($methodname)) {
return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.');
}
$method = $this->callbacks[$methodname];
// Perform the callback and send the response
# Removed for DokuWiki to have a more consistent interface
# if (count($args) == 1) {
# // If only one paramater just send that instead of the whole array
# $args = $args[0];
# }
# Adjusted for DokuWiki to use call_user_func_array
// args need to be an array
$args = (array) $args;
// Are we dealing with a function or a method?
if (substr($method, 0, 5) == 'this:') {
// It's a class method - check it exists
$method = substr($method, 5);
if (!method_exists($this, $method)) {
return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.');
}
// Call the method
#$result = $this->$method($args);
$result = call_user_func_array(array(&$this,$method),$args);
} elseif (substr($method, 0, 7) == 'plugin:') {
list($pluginname, $callback) = explode(':', substr($method, 7), 2);
if(!plugin_isdisabled($pluginname)) {
$plugin = plugin_load('action', $pluginname);
return call_user_func_array(array($plugin, $callback), $args);
} else {
return new IXR_Error(-99999, 'server error');
}
} else {
// It's a function - does it exist?
if (!function_exists($method)) {
return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.');
}
// Call the function
#$result = $method($args);
$result = call_user_func_array($method,$args);
}
return $result;
}
function error($error, $message = false) {
// Accepts either an error object or an error code and message
if ($message && !is_object($error)) {
$error = new IXR_Error($error, $message);
}
$this->output($error->getXml());
}
function output($xml) {
header('Content-Type: text/xml; charset=utf-8');
echo '<?xml version="1.0"?>', "\n", $xml;
exit;
}
function hasMethod($method) {
return in_array($method, array_keys($this->callbacks));
}
function setCapabilities() {
// Initialises capabilities array
$this->capabilities = array(
'xmlrpc' => array(
'specUrl' => 'http://www.xmlrpc.com/spec',
'specVersion' => 1
),
'faults_interop' => array(
'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php',
'specVersion' => 20010516
),
'system.multicall' => array(
'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208',
'specVersion' => 1
),
);
}
function getCapabilities() {
return $this->capabilities;
}
function setCallbacks() {
$this->callbacks['system.getCapabilities'] = 'this:getCapabilities';
$this->callbacks['system.listMethods'] = 'this:listMethods';
$this->callbacks['system.multicall'] = 'this:multiCall';
}
function listMethods() {
// Returns a list of methods - uses array_reverse to ensure user defined
// methods are listed before server defined methods
return array_reverse(array_keys($this->callbacks));
}
function multiCall($methodcalls) {
// See http://www.xmlrpc.com/discuss/msgReader$1208
$return = array();
foreach ($methodcalls as $call) {
$method = $call['methodName'];
$params = $call['params'];
if ($method == 'system.multicall') {
$result = new IXR_Error(-32800, 'Recursive calls to system.multicall are forbidden');
} else {
$result = $this->call($method, $params);
}
if (is_a($result, 'IXR_Error')) {
$return[] = array(
'faultCode' => $result->code,
'faultString' => $result->message
);
} else {
$return[] = array($result);
}
}
return $return;
}
}
class IXR_Request {
var $method;
var $args;
var $xml;
function IXR_Request($method, $args) {
$this->method = $method;
$this->args = $args;
$this->xml = <<<EOD
<?xml version="1.0"?>
<methodCall>
<methodName>{$this->method}</methodName>
<params>
EOD;
foreach ($this->args as $arg) {
$this->xml .= '<param><value>';
$v = new IXR_Value($arg);
$this->xml .= $v->getXml();
$this->xml .= "</value></param>\n";
}
$this->xml .= '</params></methodCall>';
}
function getLength() {
return strlen($this->xml);
}
function getXml() {
return $this->xml;
}
}
/**
* Changed for DokuWiki to use DokuHTTPClient
*
* This should be compatible to the original class, but uses DokuWiki's
* HTTP client library which will respect proxy settings
*
* Because the XMLRPC client is not used in DokuWiki currently this is completely
* untested
*/
class IXR_Client extends DokuHTTPClient {
var $posturl = '';
var $message = false;
var $xmlerror = false;
function IXR_Client($server, $path = false, $port = 80) {
parent::__construct();
if (!$path) {
// Assume we have been given a URL instead
$this->posturl = $server;
}else{
$this->posturl = 'http://'.$server.':'.$port.$path;
}
}
function query() {
$args = func_get_args();
$method = array_shift($args);
$request = new IXR_Request($method, $args);
$xml = $request->getXml();
$this->headers['Content-Type'] = 'text/xml';
if(!$this->sendRequest($this->posturl,$xml,'POST')){
$this->xmlerror = new IXR_Error(-32300, 'transport error - '.$this->error);
return false;
}
// Check HTTP Response code
if($this->status < 200 || $this->status > 206){
$this->xmlerror = new IXR_Error(-32300, 'transport error - HTTP status '.$this->status);
return false;
}
// Now parse what we've got back
$this->message = new IXR_Message($this->resp_body);
if (!$this->message->parse()) {
// XML error
$this->xmlerror = new IXR_Error(-32700, 'parse error. not well formed');
return false;
}
// Is the message a fault?
if ($this->message->messageType == 'fault') {
$this->xmlerror = new IXR_Error($this->message->faultCode, $this->message->faultString);
return false;
}
// Message must be OK
return true;
}
function getResponse() {
// methodResponses can only have one param - return that
return $this->message->params[0];
}
function isError() {
return (is_object($this->xmlerror));
}
function getErrorCode() {
return $this->xmlerror->code;
}
function getErrorMessage() {
return $this->xmlerror->message;
}
}
class IXR_Error {
var $code;
var $message;
function IXR_Error($code, $message) {
$this->code = $code;
$this->message = $message;
}
function getXml() {
$xml = <<<EOD
<methodResponse>
<fault>
<value>
<struct>
<member>
<name>faultCode</name>
<value><int>{$this->code}</int></value>
</member>
<member>
<name>faultString</name>
<value><string>{$this->message}</string></value>
</member>
</struct>
</value>
</fault>
</methodResponse>
EOD;
return $xml;
}
}
class IXR_Date {
var $year;
var $month;
var $day;
var $hour;
var $minute;
var $second;
function IXR_Date($time) {
// $time can be a PHP timestamp or an ISO one
if (is_numeric($time)) {
$this->parseTimestamp($time);
} else {
$this->parseIso($time);
}
}
function parseTimestamp($timestamp) {
$this->year = gmdate('Y', $timestamp);
$this->month = gmdate('m', $timestamp);
$this->day = gmdate('d', $timestamp);
$this->hour = gmdate('H', $timestamp);
$this->minute = gmdate('i', $timestamp);
$this->second = gmdate('s', $timestamp);
}
function parseIso($iso) {
if(preg_match('/^(\d\d\d\d)-?(\d\d)-?(\d\d)([T ](\d\d):(\d\d)(:(\d\d))?)?/',$iso,$match)){
$this->year = (int) $match[1];
$this->month = (int) $match[2];
$this->day = (int) $match[3];
$this->hour = (int) $match[5];
$this->minute = (int) $match[6];
$this->second = (int) $match[8];
}
}
function getIso() {
return $this->year.$this->month.$this->day.'T'.$this->hour.':'.$this->minute.':'.$this->second;
}
function getXml() {
return '<dateTime.iso8601>'.$this->getIso().'</dateTime.iso8601>';
}
function getTimestamp() {
return gmmktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year);
}
}
class IXR_Base64 {
var $data;
function IXR_Base64($data) {
$this->data = $data;
}
function getXml() {
return '<base64>'.base64_encode($this->data).'</base64>';
}
}
class IXR_IntrospectionServer extends IXR_Server {
var $signatures;
var $help;
function IXR_IntrospectionServer() {
$this->setCallbacks();
$this->setCapabilities();
$this->capabilities['introspection'] = array(
'specUrl' => 'http://xmlrpc.usefulinc.com/doc/reserved.html',
'specVersion' => 1
);
$this->addCallback(
'system.methodSignature',
'this:methodSignature',
array('array', 'string'),
'Returns an array describing the return type and required parameters of a method'
);
$this->addCallback(
'system.getCapabilities',
'this:getCapabilities',
array('struct'),
'Returns a struct describing the XML-RPC specifications supported by this server'
);
$this->addCallback(
'system.listMethods',
'this:listMethods',
array('array'),
'Returns an array of available methods on this server'
);
$this->addCallback(
'system.methodHelp',
'this:methodHelp',
array('string', 'string'),
'Returns a documentation string for the specified method'
);
}
function addCallback($method, $callback, $args, $help) {
$this->callbacks[$method] = $callback;
$this->signatures[$method] = $args;
$this->help[$method] = $help;
}
function call($methodname, $args) {
// Make sure it's in an array
if ($args && !is_array($args)) {
$args = array($args);
}
// Over-rides default call method, adds signature check
if (!$this->hasMethod($methodname)) {
return new IXR_Error(-32601, 'server error. requested method "'.$this->message->methodName.'" not specified.');
}
$method = $this->callbacks[$methodname];
$signature = $this->signatures[$methodname];
$returnType = array_shift($signature);
// Check the number of arguments. Check only, if the minimum count of parameters is specified. More parameters are possible.
// This is a hack to allow optional parameters...
if (count($args) < count($signature)) {
// print 'Num of args: '.count($args).' Num in signature: '.count($signature);
return new IXR_Error(-32602, 'server error. wrong number of method parameters');
}
// Check the argument types
$ok = true;
$argsbackup = $args;
for ($i = 0, $j = count($args); $i < $j; $i++) {
$arg = array_shift($args);
$type = array_shift($signature);
switch ($type) {
case 'int':
case 'i4':
if (is_array($arg) || !is_int($arg)) {
$ok = false;
}
break;
case 'base64':
case 'string':
if (!is_string($arg)) {
$ok = false;
}
break;
case 'boolean':
if ($arg !== false && $arg !== true) {
$ok = false;
}
break;
case 'float':
case 'double':
if (!is_float($arg)) {
$ok = false;
}
break;
case 'date':
case 'dateTime.iso8601':
if (!is_a($arg, 'IXR_Date')) {
$ok = false;
}
break;
}
if (!$ok) {
return new IXR_Error(-32602, 'server error. invalid method parameters');
}
}
// It passed the test - run the "real" method call
return parent::call($methodname, $argsbackup);
}
function methodSignature($method) {
if (!$this->hasMethod($method)) {
return new IXR_Error(-32601, 'server error. requested method "'.$method.'" not specified.');
}
// We should be returning an array of types
$types = $this->signatures[$method];
$return = array();
foreach ($types as $type) {
switch ($type) {
case 'string':
$return[] = 'string';
break;
case 'int':
case 'i4':
$return[] = 42;
break;
case 'double':
$return[] = 3.1415;
break;
case 'dateTime.iso8601':
$return[] = new IXR_Date(time());
break;
case 'boolean':
$return[] = true;
break;
case 'base64':
$return[] = new IXR_Base64('base64');
break;
case 'array':
$return[] = array('array');
break;
case 'struct':
$return[] = array('struct' => 'struct');
break;
}
}
return $return;
}
function methodHelp($method) {
return $this->help[$method];
}
}
class IXR_ClientMulticall extends IXR_Client {
var $calls = array();
function IXR_ClientMulticall($server, $path = false, $port = 80) {
parent::IXR_Client($server, $path, $port);
//$this->useragent = 'The Incutio XML-RPC PHP Library (multicall client)';
}
function addCall() {
$args = func_get_args();
$methodName = array_shift($args);
$struct = array(
'methodName' => $methodName,
'params' => $args
);
$this->calls[] = $struct;
}
function query() {
// Prepare multicall, then call the parent::query() method
return parent::query('system.multicall', $this->calls);
}
}

262
sources/inc/Input.class.php Normal file
View file

@ -0,0 +1,262 @@
<?php
/**
* Encapsulates access to the $_REQUEST array, making sure used parameters are initialized and
* have the correct type.
*
* All function access the $_REQUEST array by default, if you want to access $_POST or $_GET
* explicitly use the $post and $get members.
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
class Input {
/** @var PostInput Access $_POST parameters */
public $post;
/** @var GetInput Access $_GET parameters */
public $get;
protected $access;
/**
* Intilizes the Input class and it subcomponents
*/
function __construct() {
$this->access = &$_REQUEST;
$this->post = new PostInput();
$this->get = new GetInput();
}
/**
* Check if a parameter was set
*
* Basically a wrapper around isset. When called on the $post and $get subclasses,
* the parameter is set to $_POST or $_GET and to $_REQUEST
*
* @see isset
* @param string $name Parameter name
* @return bool
*/
public function has($name) {
return isset($this->access[$name]);
}
/**
* Remove a parameter from the superglobals
*
* Basically a wrapper around unset. When NOT called on the $post and $get subclasses,
* the parameter will also be removed from $_POST or $_GET
*
* @see isset
* @param string $name Parameter name
* @return bool
*/
public function remove($name) {
if(isset($this->access[$name])) {
unset($this->access[$name]);
}
// also remove from sub classes
if(isset($this->post) && isset($_POST[$name])) {
unset($_POST[$name]);
}
if(isset($this->get) && isset($_GET[$name])) {
unset($_GET[$name]);
}
}
/**
* Access a request parameter without any type conversion
*
* @param string $name Parameter name
* @param mixed $default Default to return if parameter isn't set
* @param bool $nonempty Return $default if parameter is set but empty()
* @return mixed
*/
public function param($name, $default = null, $nonempty = false) {
if(!isset($this->access[$name])) return $default;
if($nonempty && empty($this->access[$name])) return $default;
return $this->access[$name];
}
/**
* Sets a parameter
*
* @param string $name Parameter name
* @param mixed $value Value to set
*/
public function set($name, $value) {
$this->access[$name] = $value;
}
/**
* Get a reference to a request parameter
*
* This avoids copying data in memory, when the parameter is not set it will be created
* and intialized with the given $default value before a reference is returned
*
* @param string $name Parameter name
* @param mixed $default If parameter is not set, initialize with this value
* @param bool $nonempty Init with $default if parameter is set but empty()
* @return &mixed
*/
public function &ref($name, $default = '', $nonempty = false) {
if(!isset($this->access[$name]) || ($nonempty && empty($this->access[$name]))) {
$this->set($name, $default);
}
return $this->access[$name];
}
/**
* Access a request parameter as int
*
* @param string $name Parameter name
* @param mixed $default Default to return if parameter isn't set or is an array
* @param bool $nonempty Return $default if parameter is set but empty()
* @return int
*/
public function int($name, $default = 0, $nonempty = false) {
if(!isset($this->access[$name])) return $default;
if(is_array($this->access[$name])) return $default;
if($this->access[$name] === '') return $default;
if($nonempty && empty($this->access[$name])) return $default;
return (int) $this->access[$name];
}
/**
* Access a request parameter as string
*
* @param string $name Parameter name
* @param mixed $default Default to return if parameter isn't set or is an array
* @param bool $nonempty Return $default if parameter is set but empty()
* @return string
*/
public function str($name, $default = '', $nonempty = false) {
if(!isset($this->access[$name])) return $default;
if(is_array($this->access[$name])) return $default;
if($nonempty && empty($this->access[$name])) return $default;
return (string) $this->access[$name];
}
/**
* Access a request parameter as bool
*
* Note: $nonempty is here for interface consistency and makes not much sense for booleans
*
* @param string $name Parameter name
* @param mixed $default Default to return if parameter isn't set
* @param bool $nonempty Return $default if parameter is set but empty()
* @return bool
*/
public function bool($name, $default = false, $nonempty = false) {
if(!isset($this->access[$name])) return $default;
if(is_array($this->access[$name])) return $default;
if($this->access[$name] === '') return $default;
if($nonempty && empty($this->access[$name])) return $default;
return (bool) $this->access[$name];
}
/**
* Access a request parameter as array
*
* @param string $name Parameter name
* @param mixed $default Default to return if parameter isn't set
* @param bool $nonempty Return $default if parameter is set but empty()
* @return array
*/
public function arr($name, $default = array(), $nonempty = false) {
if(!isset($this->access[$name])) return $default;
if(!is_array($this->access[$name])) return $default;
if($nonempty && empty($this->access[$name])) return $default;
return (array) $this->access[$name];
}
/**
* Create a simple key from an array key
*
* This is useful to access keys where the information is given as an array key or as a single array value.
* For example when the information was submitted as the name of a submit button.
*
* This function directly changes the access array.
*
* Eg. $_REQUEST['do']['save']='Speichern' becomes $_REQUEST['do'] = 'save'
*
* This function returns the $INPUT object itself for easy chaining
*
* @param $name
* @return Input
*/
public function extract($name){
if(!isset($this->access[$name])) return $this;
if(!is_array($this->access[$name])) return $this;
$keys = array_keys($this->access[$name]);
if(!$keys){
// this was an empty array
$this->remove($name);
return $this;
}
// get the first key
$value = array_shift($keys);
if($value === 0){
// we had a numeric array, assume the value is not in the key
$value = array_shift($this->access[$name]);
}
$this->set($name, $value);
return $this;
}
}
/**
* Internal class used for $_POST access in Input class
*/
class PostInput extends Input {
protected $access;
/**
* Initialize the $access array, remove subclass members
*/
function __construct() {
$this->access = &$_POST;
}
/**
* Sets a parameter in $_POST and $_REQUEST
*
* @param string $name Parameter name
* @param mixed $value Value to set
*/
public function set($name, $value) {
parent::set($name, $value);
$_REQUEST[$name] = $value;
}
}
/**
* Internal class used for $_GET access in Input class
*/
class GetInput extends Input {
protected $access;
/**
* Initialize the $access array, remove subclass members
*/
function __construct() {
$this->access = &$_GET;
}
/**
* Sets a parameter in $_GET and $_REQUEST
*
* @param string $name Parameter name
* @param mixed $value Value to set
*/
public function set($name, $value) {
parent::set($name, $value);
$_REQUEST[$name] = $value;
}
}

648
sources/inc/JSON.php Normal file
View file

@ -0,0 +1,648 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Converts to and from JSON format.
*
* JSON (JavaScript Object Notation) is a lightweight data-interchange
* format. It is easy for humans to read and write. It is easy for machines
* to parse and generate. It is based on a subset of the JavaScript
* Programming Language, Standard ECMA-262 3rd Edition - December 1999.
* This feature can also be found in Python. JSON is a text format that is
* completely language independent but uses conventions that are familiar
* to programmers of the C-family of languages, including C, C++, C#, Java,
* JavaScript, Perl, TCL, and many others. These properties make JSON an
* ideal data-interchange language.
*
* This package provides a simple encoder and decoder for JSON notation. It
* is intended for use with client-side Javascript applications that make
* use of HTTPRequest to perform server communication functions - data can
* be encoded into JSON notation for use in a client-side javascript, or
* decoded from incoming Javascript requests. JSON format is native to
* Javascript, and can be directly eval()'ed with no further parsing
* overhead
*
* All strings should be in ASCII or UTF-8 format!
*
* PHP versions 4 and 5
*
* LICENSE: Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met: Redistributions of source code must retain the
* above copyright notice, this list of conditions and the following
* disclaimer. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* @author Michal Migurski <mike-json@teczno.com>
* @author Matt Knapp <mdknapp[at]gmail[dot]com>
* @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
* @copyright 2005 Michal Migurski
* @license http://www.freebsd.org/copyright/freebsd-license.html
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
*/
// for DokuWiki
if(!defined('DOKU_INC')) die('meh.');
/**
* Marker constant for JSON::decode(), used to flag stack state
*/
define('JSON_SLICE', 1);
/**
* Marker constant for JSON::decode(), used to flag stack state
*/
define('JSON_IN_STR', 2);
/**
* Marker constant for JSON::decode(), used to flag stack state
*/
define('JSON_IN_ARR', 4);
/**
* Marker constant for JSON::decode(), used to flag stack state
*/
define('JSON_IN_OBJ', 8);
/**
* Marker constant for JSON::decode(), used to flag stack state
*/
define('JSON_IN_CMT', 16);
/**
* Behavior switch for JSON::decode()
*/
define('JSON_LOOSE_TYPE', 10);
/**
* Behavior switch for JSON::decode()
*/
define('JSON_STRICT_TYPE', 11);
/**
* Converts to and from JSON format.
*/
class JSON {
/**
* Disables the use of PHP5's native json_decode()
*
* You shouldn't change this usually because the native function is much
* faster. However, this non-native will also parse slightly broken JSON
* which might be handy when talking to a non-conform endpoint
*/
public $skipnative = false;
/**
* constructs a new JSON instance
*
* @param int $use object behavior: when encoding or decoding,
* be loose or strict about object/array usage
*
* possible values:
* JSON_STRICT_TYPE - strict typing, default
* "{...}" syntax creates objects in decode.
* JSON_LOOSE_TYPE - loose typing
* "{...}" syntax creates associative arrays in decode.
*/
function JSON($use=JSON_STRICT_TYPE) {
$this->use = $use;
}
/**
* encodes an arbitrary variable into JSON format
* If available the native PHP JSON implementation is used.
*
* @param mixed $var any number, boolean, string, array, or object to be encoded.
* see argument 1 to JSON() above for array-parsing behavior.
* if var is a strng, note that encode() always expects it
* to be in ASCII or UTF-8 format!
*
* @return string JSON string representation of input var
* @access public
*/
function encode($var) {
if (!$this->skipnative && function_exists('json_encode')){
return json_encode($var);
}
switch (gettype($var)) {
case 'boolean':
return $var ? 'true' : 'false';
case 'NULL':
return 'null';
case 'integer':
return sprintf('%d', $var);
case 'double':
case 'float':
return sprintf('%f', $var);
case 'string':
// STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
$ascii = '';
$strlen_var = strlen($var);
/*
* Iterate over every character in the string,
* escaping with a slash or encoding to UTF-8 where necessary
*/
for ($c = 0; $c < $strlen_var; ++$c) {
$ord_var_c = ord($var{$c});
switch ($ord_var_c) {
case 0x08:
$ascii .= '\b';
break;
case 0x09:
$ascii .= '\t';
break;
case 0x0A:
$ascii .= '\n';
break;
case 0x0C:
$ascii .= '\f';
break;
case 0x0D:
$ascii .= '\r';
break;
case 0x22:
case 0x2F:
case 0x5C:
// double quote, slash, slosh
$ascii .= '\\'.$var{$c};
break;
case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
// characters U-00000000 - U-0000007F (same as ASCII)
$ascii .= $var{$c};
break;
case (($ord_var_c & 0xE0) == 0xC0):
// characters U-00000080 - U-000007FF, mask 110XXXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c, ord($var{$c+1}));
$c+=1;
//$utf16 = mb_convert_encoding($char, 'UTF-16', 'UTF-8');
$utf16 = utf8_to_utf16be($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xF0) == 0xE0):
// characters U-00000800 - U-0000FFFF, mask 1110XXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c+1}),
ord($var{$c+2}));
$c+=2;
//$utf16 = mb_convert_encoding($char, 'UTF-16', 'UTF-8');
$utf16 = utf8_to_utf16be($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xF8) == 0xF0):
// characters U-00010000 - U-001FFFFF, mask 11110XXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c+1}),
ord($var{$c+2}),
ord($var{$c+3}));
$c+=3;
//$utf16 = mb_convert_encoding($char, 'UTF-16', 'UTF-8');
$utf16 = utf8_to_utf16be($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xFC) == 0xF8):
// characters U-00200000 - U-03FFFFFF, mask 111110XX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c+1}),
ord($var{$c+2}),
ord($var{$c+3}),
ord($var{$c+4}));
$c+=4;
//$utf16 = mb_convert_encoding($char, 'UTF-16', 'UTF-8');
$utf16 = utf8_to_utf16be($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
case (($ord_var_c & 0xFE) == 0xFC):
// characters U-04000000 - U-7FFFFFFF, mask 1111110X
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$char = pack('C*', $ord_var_c,
ord($var{$c+1}),
ord($var{$c+2}),
ord($var{$c+3}),
ord($var{$c+4}),
ord($var{$c+5}));
$c+=5;
//$utf16 = mb_convert_encoding($char, 'UTF-16', 'UTF-8');
$utf16 = utf8_to_utf16be($char);
$ascii .= sprintf('\u%04s', bin2hex($utf16));
break;
}
}
return '"'.$ascii.'"';
case 'array':
/*
* As per JSON spec if any array key is not an integer
* we must treat the the whole array as an object. We
* also try to catch a sparsely populated associative
* array with numeric keys here because some JS engines
* will create an array with empty indexes up to
* max_index which can cause memory issues and because
* the keys, which may be relevant, will be remapped
* otherwise.
*
* As per the ECMA and JSON specification an object may
* have any string as a property. Unfortunately due to
* a hole in the ECMA specification if the key is a
* ECMA reserved word or starts with a digit the
* parameter is only accessible using ECMAScript's
* bracket notation.
*/
// treat as a JSON object
if (is_array($var) && count($var) && (array_keys($var) !== range(0, count($var) - 1))) {
return sprintf('{%s}', join(',', array_map(array($this, 'name_value'),
array_keys($var),
array_values($var))));
}
// treat it like a regular array
return sprintf('[%s]', join(',', array_map(array($this, 'encode'), $var)));
case 'object':
$vars = get_object_vars($var);
return sprintf('{%s}', join(',', array_map(array($this, 'name_value'),
array_keys($vars),
array_values($vars))));
default:
return '';
}
}
/**
* encodes an arbitrary variable into JSON format, alias for encode()
*/
function enc($var) {
return $this->encode($var);
}
/** function name_value
* array-walking function for use in generating JSON-formatted name-value pairs
*
* @param string $name name of key to use
* @param mixed $value reference to an array element to be encoded
*
* @return string JSON-formatted name-value pair, like '"name":value'
* @access private
*/
function name_value($name, $value) {
return (sprintf("%s:%s", $this->encode(strval($name)), $this->encode($value)));
}
/**
* reduce a string by removing leading and trailing comments and whitespace
*
* @param $str string string value to strip of comments and whitespace
*
* @return string string value stripped of comments and whitespace
* @access private
*/
function reduce_string($str) {
$str = preg_replace(array(
// eliminate single line comments in '// ...' form
'#^\s*//(.+)$#m',
// eliminate multi-line comments in '/* ... */' form, at start of string
'#^\s*/\*(.+)\*/#Us',
// eliminate multi-line comments in '/* ... */' form, at end of string
'#/\*(.+)\*/\s*$#Us'
), '', $str);
// eliminate extraneous space
return trim($str);
}
/**
* decodes a JSON string into appropriate variable
* If available the native PHP JSON implementation is used.
*
* @param string $str JSON-formatted string
*
* @return mixed number, boolean, string, array, or object
* corresponding to given JSON input string.
* See argument 1 to JSON() above for object-output behavior.
* Note that decode() always returns strings
* in ASCII or UTF-8 format!
* @access public
*/
function decode($str) {
if (!$this->skipnative && function_exists('json_decode')){
return json_decode($str,($this->use == JSON_LOOSE_TYPE));
}
$str = $this->reduce_string($str);
switch (strtolower($str)) {
case 'true':
return true;
case 'false':
return false;
case 'null':
return null;
default:
if (is_numeric($str)) {
// Lookie-loo, it's a number
// This would work on its own, but I'm trying to be
// good about returning integers where appropriate:
// return (float)$str;
// Return float or int, as appropriate
return ((float)$str == (integer)$str)
? (integer)$str
: (float)$str;
} elseif (preg_match('/^("|\').+("|\')$/s', $str, $m) && $m[1] == $m[2]) {
// STRINGS RETURNED IN UTF-8 FORMAT
$delim = substr($str, 0, 1);
$chrs = substr($str, 1, -1);
$utf8 = '';
$strlen_chrs = strlen($chrs);
for ($c = 0; $c < $strlen_chrs; ++$c) {
$substr_chrs_c_2 = substr($chrs, $c, 2);
$ord_chrs_c = ord($chrs{$c});
switch ($substr_chrs_c_2) {
case '\b':
$utf8 .= chr(0x08);
$c+=1;
break;
case '\t':
$utf8 .= chr(0x09);
$c+=1;
break;
case '\n':
$utf8 .= chr(0x0A);
$c+=1;
break;
case '\f':
$utf8 .= chr(0x0C);
$c+=1;
break;
case '\r':
$utf8 .= chr(0x0D);
$c+=1;
break;
case '\\"':
case '\\\'':
case '\\\\':
case '\\/':
if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
($delim == "'" && $substr_chrs_c_2 != '\\"')) {
$utf8 .= $chrs{++$c};
}
break;
default:
if (preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6))) {
// single, escaped unicode character
$utf16 = chr(hexdec(substr($chrs, ($c+2), 2)))
. chr(hexdec(substr($chrs, ($c+4), 2)));
//$utf8 .= mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
$utf8 .= utf16be_to_utf8($utf16);
$c+=5;
} elseif(($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F)) {
$utf8 .= $chrs{$c};
} elseif(($ord_chrs_c & 0xE0) == 0xC0) {
// characters U-00000080 - U-000007FF, mask 110XXXXX
//see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 2);
$c += 1;
} elseif(($ord_chrs_c & 0xF0) == 0xE0) {
// characters U-00000800 - U-0000FFFF, mask 1110XXXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 3);
$c += 2;
} elseif(($ord_chrs_c & 0xF8) == 0xF0) {
// characters U-00010000 - U-001FFFFF, mask 11110XXX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 4);
$c += 3;
} elseif(($ord_chrs_c & 0xFC) == 0xF8) {
// characters U-00200000 - U-03FFFFFF, mask 111110XX
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 5);
$c += 4;
} elseif(($ord_chrs_c & 0xFE) == 0xFC) {
// characters U-04000000 - U-7FFFFFFF, mask 1111110X
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
$utf8 .= substr($chrs, $c, 6);
$c += 5;
}
break;
}
}
return $utf8;
} elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
// array, or object notation
if ($str{0} == '[') {
$stk = array(JSON_IN_ARR);
$arr = array();
} else {
if ($this->use == JSON_LOOSE_TYPE) {
$stk = array(JSON_IN_OBJ);
$obj = array();
} else {
$stk = array(JSON_IN_OBJ);
$obj = new stdClass();
}
}
array_push($stk, array('what' => JSON_SLICE,
'where' => 0,
'delim' => false));
$chrs = substr($str, 1, -1);
$chrs = $this->reduce_string($chrs);
if ($chrs == '') {
if (reset($stk) == JSON_IN_ARR) {
return $arr;
} else {
return $obj;
}
}
//print("\nparsing {$chrs}\n");
$strlen_chrs = strlen($chrs);
for ($c = 0; $c <= $strlen_chrs; ++$c) {
$top = end($stk);
$substr_chrs_c_2 = substr($chrs, $c, 2);
if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == JSON_SLICE))) {
// found a comma that is not inside a string, array, etc.,
// OR we've reached the end of the character list
$slice = substr($chrs, $top['where'], ($c - $top['where']));
array_push($stk, array('what' => JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
//print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
if (reset($stk) == JSON_IN_ARR) {
// we are in an array, so just push an element onto the stack
array_push($arr, $this->decode($slice));
} elseif (reset($stk) == JSON_IN_OBJ) {
// we are in an object, so figure
// out the property name and set an
// element in an associative array,
// for now
if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
// "name":value pair
$key = $this->decode($parts[1]);
$val = $this->decode($parts[2]);
if ($this->use == JSON_LOOSE_TYPE) {
$obj[$key] = $val;
} else {
$obj->$key = $val;
}
} elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
// name:value pair, where name is unquoted
$key = $parts[1];
$val = $this->decode($parts[2]);
if ($this->use == JSON_LOOSE_TYPE) {
$obj[$key] = $val;
} else {
$obj->$key = $val;
}
}
}
} elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != JSON_IN_STR)) {
// found a quote, and we are not inside a string
array_push($stk, array('what' => JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
//print("Found start of string at {$c}\n");
} elseif (($chrs{$c} == $top['delim']) &&
($top['what'] == JSON_IN_STR) &&
((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
// found a quote, we're in a string, and it's not escaped
// we know that it's not escaped becase there is _not_ an
// odd number of backslashes at the end of the string so far
array_pop($stk);
//print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
} elseif (($chrs{$c} == '[') &&
in_array($top['what'], array(JSON_SLICE, JSON_IN_ARR, JSON_IN_OBJ))) {
// found a left-bracket, and we are in an array, object, or slice
array_push($stk, array('what' => JSON_IN_ARR, 'where' => $c, 'delim' => false));
//print("Found start of array at {$c}\n");
} elseif (($chrs{$c} == ']') && ($top['what'] == JSON_IN_ARR)) {
// found a right-bracket, and we're in an array
array_pop($stk);
//print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
} elseif (($chrs{$c} == '{') &&
in_array($top['what'], array(JSON_SLICE, JSON_IN_ARR, JSON_IN_OBJ))) {
// found a left-brace, and we are in an array, object, or slice
array_push($stk, array('what' => JSON_IN_OBJ, 'where' => $c, 'delim' => false));
//print("Found start of object at {$c}\n");
} elseif (($chrs{$c} == '}') && ($top['what'] == JSON_IN_OBJ)) {
// found a right-brace, and we're in an object
array_pop($stk);
//print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
} elseif (($substr_chrs_c_2 == '/*') &&
in_array($top['what'], array(JSON_SLICE, JSON_IN_ARR, JSON_IN_OBJ))) {
// found a comment start, and we are in an array, object, or slice
array_push($stk, array('what' => JSON_IN_CMT, 'where' => $c, 'delim' => false));
$c++;
//print("Found start of comment at {$c}\n");
} elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == JSON_IN_CMT)) {
// found a comment end, and we're in one now
array_pop($stk);
$c++;
for ($i = $top['where']; $i <= $c; ++$i)
$chrs = substr_replace($chrs, ' ', $i, 1);
//print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
}
}
if (reset($stk) == JSON_IN_ARR) {
return $arr;
} elseif (reset($stk) == JSON_IN_OBJ) {
return $obj;
}
}
}
}
/**
* decodes a JSON string into appropriate variable; alias for decode()
*/
function dec($var) {
return $this->decode($var);
}
}

3010
sources/inc/JpegMeta.php Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,680 @@
<?php
/**
* A class to build and send multi part mails (with HTML content and embedded
* attachments). All mails are assumed to be in UTF-8 encoding.
*
* Attachments are handled in memory so this shouldn't be used to send huge
* files, but then again mail shouldn't be used to send huge files either.
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
// end of line for mail lines - RFC822 says CRLF but postfix (and other MTAs?)
// think different
if(!defined('MAILHEADER_EOL')) define('MAILHEADER_EOL', "\n");
#define('MAILHEADER_ASCIIONLY',1);
/**
* Mail Handling
*/
class Mailer {
protected $headers = array();
protected $attach = array();
protected $html = '';
protected $text = '';
protected $boundary = '';
protected $partid = '';
protected $sendparam = null;
/** @var EmailAddressValidator */
protected $validator = null;
protected $allowhtml = true;
/**
* Constructor
*
* Initializes the boundary strings and part counters
*/
public function __construct() {
global $conf;
$server = parse_url(DOKU_URL, PHP_URL_HOST);
if(strpos($server,'.') === false) $server = $server.'.localhost';
$this->partid = substr(md5(uniqid(rand(), true)),0, 8).'@'.$server;
$this->boundary = '__________'.md5(uniqid(rand(), true));
$listid = join('.', array_reverse(explode('/', DOKU_BASE))).$server;
$listid = strtolower(trim($listid, '.'));
$this->allowhtml = (bool)$conf['htmlmail'];
// add some default headers for mailfiltering FS#2247
$this->setHeader('X-Mailer', 'DokuWiki');
$this->setHeader('X-DokuWiki-User', $_SERVER['REMOTE_USER']);
$this->setHeader('X-DokuWiki-Title', $conf['title']);
$this->setHeader('X-DokuWiki-Server', $server);
$this->setHeader('X-Auto-Response-Suppress', 'OOF');
$this->setHeader('List-Id', $conf['title'].' <'.$listid.'>');
$this->setHeader('Date', date('r'), false);
}
/**
* Attach a file
*
* @param string $path Path to the file to attach
* @param string $mime Mimetype of the attached file
* @param string $name The filename to use
* @param string $embed Unique key to reference this file from the HTML part
*/
public function attachFile($path, $mime, $name = '', $embed = '') {
if(!$name) {
$name = utf8_basename($path);
}
$this->attach[] = array(
'data' => file_get_contents($path),
'mime' => $mime,
'name' => $name,
'embed' => $embed
);
}
/**
* Attach a file
*
* @param string $data The file contents to attach
* @param string $mime Mimetype of the attached file
* @param string $name The filename to use
* @param string $embed Unique key to reference this file from the HTML part
*/
public function attachContent($data, $mime, $name = '', $embed = '') {
if(!$name) {
list(, $ext) = explode('/', $mime);
$name = count($this->attach).".$ext";
}
$this->attach[] = array(
'data' => $data,
'mime' => $mime,
'name' => $name,
'embed' => $embed
);
}
/**
* Callback function to automatically embed images referenced in HTML templates
*/
protected function autoembed_cb($matches) {
static $embeds = 0;
$embeds++;
// get file and mime type
$media = cleanID($matches[1]);
list(, $mime) = mimetype($media);
$file = mediaFN($media);
if(!file_exists($file)) return $matches[0]; //bad reference, keep as is
// attach it and set placeholder
$this->attachFile($file, $mime, '', 'autoembed'.$embeds);
return '%%autoembed'.$embeds.'%%';
}
/**
* Add an arbitrary header to the mail
*
* If an empy value is passed, the header is removed
*
* @param string $header the header name (no trailing colon!)
* @param string $value the value of the header
* @param bool $clean remove all non-ASCII chars and line feeds?
*/
public function setHeader($header, $value, $clean = true) {
$header = str_replace(' ', '-', ucwords(strtolower(str_replace('-', ' ', $header)))); // streamline casing
if($clean) {
$header = preg_replace('/[^a-zA-Z0-9_ \-\.\+\@]+/', '', $header);
$value = preg_replace('/[^a-zA-Z0-9_ \-\.\+\@<>]+/', '', $value);
}
// empty value deletes
if(is_array($value)){
$value = array_map('trim', $value);
$value = array_filter($value);
if(!$value) $value = '';
}else{
$value = trim($value);
}
if($value === '') {
if(isset($this->headers[$header])) unset($this->headers[$header]);
} else {
$this->headers[$header] = $value;
}
}
/**
* Set additional parameters to be passed to sendmail
*
* Whatever is set here is directly passed to PHP's mail() command as last
* parameter. Depending on the PHP setup this might break mailing alltogether
*/
public function setParameters($param) {
$this->sendparam = $param;
}
/**
* Set the text and HTML body and apply replacements
*
* This function applies a whole bunch of default replacements in addition
* to the ones specidifed as parameters
*
* If you pass the HTML part or HTML replacements yourself you have to make
* sure you encode all HTML special chars correctly
*
* @param string $text plain text body
* @param array $textrep replacements to apply on the text part
* @param array $htmlrep replacements to apply on the HTML part, leave null to use $textrep
* @param array $html the HTML body, leave null to create it from $text
* @param bool $wrap wrap the HTML in the default header/Footer
*/
public function setBody($text, $textrep = null, $htmlrep = null, $html = null, $wrap = true) {
global $INFO;
global $conf;
$htmlrep = (array)$htmlrep;
$textrep = (array)$textrep;
// create HTML from text if not given
if(is_null($html)) {
$html = $text;
$html = hsc($html);
$html = preg_replace('/^-----*$/m', '<hr >', $html);
$html = nl2br($html);
}
if($wrap) {
$wrap = rawLocale('mailwrap', 'html');
$html = preg_replace('/\n-- <br \/>.*$/s', '', $html); //strip signature
$html = str_replace('@HTMLBODY@', $html, $wrap);
}
// copy over all replacements missing for HTML (autolink URLs)
foreach($textrep as $key => $value) {
if(isset($htmlrep[$key])) continue;
if(media_isexternal($value)) {
$htmlrep[$key] = '<a href="'.hsc($value).'">'.hsc($value).'</a>';
} else {
$htmlrep[$key] = hsc($value);
}
}
// embed media from templates
$html = preg_replace_callback(
'/@MEDIA\(([^\)]+)\)@/',
array($this, 'autoembed_cb'), $html
);
// prepare default replacements
$ip = clientIP();
$cip = gethostsbyaddrs($ip);
$trep = array(
'DATE' => dformat(),
'BROWSER' => $_SERVER['HTTP_USER_AGENT'],
'IPADDRESS' => $ip,
'HOSTNAME' => $cip,
'TITLE' => $conf['title'],
'DOKUWIKIURL' => DOKU_URL,
'USER' => $_SERVER['REMOTE_USER'],
'NAME' => $INFO['userinfo']['name'],
'MAIL' => $INFO['userinfo']['mail'],
);
$trep = array_merge($trep, (array)$textrep);
$hrep = array(
'DATE' => '<i>'.hsc(dformat()).'</i>',
'BROWSER' => hsc($_SERVER['HTTP_USER_AGENT']),
'IPADDRESS' => '<code>'.hsc($ip).'</code>',
'HOSTNAME' => '<code>'.hsc($cip).'</code>',
'TITLE' => hsc($conf['title']),
'DOKUWIKIURL' => '<a href="'.DOKU_URL.'">'.DOKU_URL.'</a>',
'USER' => hsc($_SERVER['REMOTE_USER']),
'NAME' => hsc($INFO['userinfo']['name']),
'MAIL' => '<a href="mailto:"'.hsc($INFO['userinfo']['mail']).'">'.
hsc($INFO['userinfo']['mail']).'</a>',
);
$hrep = array_merge($hrep, (array)$htmlrep);
// Apply replacements
foreach($trep as $key => $substitution) {
$text = str_replace('@'.strtoupper($key).'@', $substitution, $text);
}
foreach($hrep as $key => $substitution) {
$html = str_replace('@'.strtoupper($key).'@', $substitution, $html);
}
$this->setHTML($html);
$this->setText($text);
}
/**
* Set the HTML part of the mail
*
* Placeholders can be used to reference embedded attachments
*
* You probably want to use setBody() instead
*/
public function setHTML($html) {
$this->html = $html;
}
/**
* Set the plain text part of the mail
*
* You probably want to use setBody() instead
*/
public function setText($text) {
$this->text = $text;
}
/**
* Add the To: recipients
*
* @see setAddress
* @param string|array $address Multiple adresses separated by commas or as array
*/
public function to($address) {
$this->setHeader('To', $address, false);
}
/**
* Add the Cc: recipients
*
* @see setAddress
* @param string|array $address Multiple adresses separated by commas or as array
*/
public function cc($address) {
$this->setHeader('Cc', $address, false);
}
/**
* Add the Bcc: recipients
*
* @see setAddress
* @param string|array $address Multiple adresses separated by commas or as array
*/
public function bcc($address) {
$this->setHeader('Bcc', $address, false);
}
/**
* Add the From: address
*
* This is set to $conf['mailfrom'] when not specified so you shouldn't need
* to call this function
*
* @see setAddress
* @param string $address from address
*/
public function from($address) {
$this->setHeader('From', $address, false);
}
/**
* Add the mail's Subject: header
*
* @param string $subject the mail subject
*/
public function subject($subject) {
$this->headers['Subject'] = $subject;
}
/**
* Sets an email address header with correct encoding
*
* Unicode characters will be deaccented and encoded base64
* for headers. Addresses may not contain Non-ASCII data!
*
* Example:
* setAddress("föö <foo@bar.com>, me@somewhere.com","TBcc");
*
* @param string|array $address Multiple adresses separated by commas or as array
* @return bool|string the prepared header (can contain multiple lines)
*/
public function cleanAddress($addresses) {
// No named recipients for To: in Windows (see FS#652)
$names = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? false : true;
$headers = '';
if(!is_array($addresses)){
$addresses = explode(',', $addresses);
}
foreach($addresses as $part) {
$part = preg_replace('/[\r\n\0]+/', ' ', $part); // remove attack vectors
$part = trim($part);
// parse address
if(preg_match('#(.*?)<(.*?)>#', $part, $matches)) {
$text = trim($matches[1]);
$addr = $matches[2];
} else {
$addr = $part;
}
// skip empty ones
if(empty($addr)) {
continue;
}
// FIXME: is there a way to encode the localpart of a emailaddress?
if(!utf8_isASCII($addr)) {
msg(htmlspecialchars("E-Mail address <$addr> is not ASCII"), -1);
continue;
}
if(is_null($this->validator)) {
$this->validator = new EmailAddressValidator();
$this->validator->allowLocalAddresses = true;
}
if(!$this->validator->check_email_address($addr)) {
msg(htmlspecialchars("E-Mail address <$addr> is not valid"), -1);
continue;
}
// text was given
if(!empty($text) && $names) {
// add address quotes
$addr = "<$addr>";
if(defined('MAILHEADER_ASCIIONLY')) {
$text = utf8_deaccent($text);
$text = utf8_strip($text);
}
if(strpos($text, ',') !== false || !utf8_isASCII($text)) {
$text = '=?UTF-8?B?'.base64_encode($text).'?=';
}
} else {
$text = '';
}
// add to header comma seperated
if($headers != '') {
$headers .= ', ';
}
$headers .= $text.' '.$addr;
}
$headers = trim($headers);
if(empty($headers)) return false;
return $headers;
}
/**
* Prepare the mime multiparts for all attachments
*
* Replaces placeholders in the HTML with the correct CIDs
*/
protected function prepareAttachments() {
$mime = '';
$part = 1;
// embedded attachments
foreach($this->attach as $media) {
$media['name'] = str_replace(':', '_', cleanID($media['name'], true));
// create content id
$cid = 'part'.$part.'.'.$this->partid;
// replace wildcards
if($media['embed']) {
$this->html = str_replace('%%'.$media['embed'].'%%', 'cid:'.$cid, $this->html);
}
$mime .= '--'.$this->boundary.MAILHEADER_EOL;
$mime .= $this->wrappedHeaderLine('Content-Type', $media['mime'].'; id="'.$cid.'"');
$mime .= $this->wrappedHeaderLine('Content-Transfer-Encoding', 'base64');
$mime .= $this->wrappedHeaderLine('Content-ID',"<$cid>");
if($media['embed']) {
$mime .= $this->wrappedHeaderLine('Content-Disposition', 'inline; filename='.$media['name']);
} else {
$mime .= $this->wrappedHeaderLine('Content-Disposition', 'attachment; filename='.$media['name']);
}
$mime .= MAILHEADER_EOL; //end of headers
$mime .= chunk_split(base64_encode($media['data']), 74, MAILHEADER_EOL);
$part++;
}
return $mime;
}
/**
* Build the body and handles multi part mails
*
* Needs to be called before prepareHeaders!
*
* @return string the prepared mail body, false on errors
*/
protected function prepareBody() {
// no HTML mails allowed? remove HTML body
if(!$this->allowhtml) {
$this->html = '';
}
// check for body
if(!$this->text && !$this->html) {
return false;
}
// add general headers
$this->headers['MIME-Version'] = '1.0';
$body = '';
if(!$this->html && !count($this->attach)) { // we can send a simple single part message
$this->headers['Content-Type'] = 'text/plain; charset=UTF-8';
$this->headers['Content-Transfer-Encoding'] = 'base64';
$body .= chunk_split(base64_encode($this->text), 72, MAILHEADER_EOL);
} else { // multi part it is
$body .= "This is a multi-part message in MIME format.".MAILHEADER_EOL;
// prepare the attachments
$attachments = $this->prepareAttachments();
// do we have alternative text content?
if($this->text && $this->html) {
$this->headers['Content-Type'] = 'multipart/alternative;'.MAILHEADER_EOL.
' boundary="'.$this->boundary.'XX"';
$body .= '--'.$this->boundary.'XX'.MAILHEADER_EOL;
$body .= 'Content-Type: text/plain; charset=UTF-8'.MAILHEADER_EOL;
$body .= 'Content-Transfer-Encoding: base64'.MAILHEADER_EOL;
$body .= MAILHEADER_EOL;
$body .= chunk_split(base64_encode($this->text), 72, MAILHEADER_EOL);
$body .= '--'.$this->boundary.'XX'.MAILHEADER_EOL;
$body .= 'Content-Type: multipart/related;'.MAILHEADER_EOL.
' boundary="'.$this->boundary.'";'.MAILHEADER_EOL.
' type="text/html"'.MAILHEADER_EOL;
$body .= MAILHEADER_EOL;
}
$body .= '--'.$this->boundary.MAILHEADER_EOL;
$body .= 'Content-Type: text/html; charset=UTF-8'.MAILHEADER_EOL;
$body .= 'Content-Transfer-Encoding: base64'.MAILHEADER_EOL;
$body .= MAILHEADER_EOL;
$body .= chunk_split(base64_encode($this->html), 72, MAILHEADER_EOL);
$body .= MAILHEADER_EOL;
$body .= $attachments;
$body .= '--'.$this->boundary.'--'.MAILHEADER_EOL;
// close open multipart/alternative boundary
if($this->text && $this->html) {
$body .= '--'.$this->boundary.'XX--'.MAILHEADER_EOL;
}
}
return $body;
}
/**
* Cleanup and encode the headers array
*/
protected function cleanHeaders() {
global $conf;
// clean up addresses
if(empty($this->headers['From'])) $this->from($conf['mailfrom']);
$addrs = array('To', 'From', 'Cc', 'Bcc');
foreach($addrs as $addr) {
if(isset($this->headers[$addr])) {
$this->headers[$addr] = $this->cleanAddress($this->headers[$addr]);
}
}
if(isset($this->headers['Subject'])) {
// add prefix to subject
if(empty($conf['mailprefix'])) {
if(utf8_strlen($conf['title']) < 20) {
$prefix = '['.$conf['title'].']';
} else {
$prefix = '['.utf8_substr($conf['title'], 0, 20).'...]';
}
} else {
$prefix = '['.$conf['mailprefix'].']';
}
$len = strlen($prefix);
if(substr($this->headers['Subject'], 0, $len) != $prefix) {
$this->headers['Subject'] = $prefix.' '.$this->headers['Subject'];
}
// encode subject
if(defined('MAILHEADER_ASCIIONLY')) {
$this->headers['Subject'] = utf8_deaccent($this->headers['Subject']);
$this->headers['Subject'] = utf8_strip($this->headers['Subject']);
}
if(!utf8_isASCII($this->headers['Subject'])) {
$this->headers['Subject'] = '=?UTF-8?B?'.base64_encode($this->headers['Subject']).'?=';
}
}
}
/**
* Returns a complete, EOL terminated header line, wraps it if necessary
*
* @param $key
* @param $val
* @return string
*/
protected function wrappedHeaderLine($key, $val){
return wordwrap("$key: $val", 78, MAILHEADER_EOL.' ').MAILHEADER_EOL;
}
/**
* Create a string from the headers array
*
* @returns string the headers
*/
protected function prepareHeaders() {
$headers = '';
foreach($this->headers as $key => $val) {
if ($val === '' || is_null($val)) continue;
$headers .= $this->wrappedHeaderLine($key, $val);
}
return $headers;
}
/**
* return a full email with all headers
*
* This is mainly intended for debugging and testing but could also be
* used for MHT exports
*
* @return string the mail, false on errors
*/
public function dump() {
$this->cleanHeaders();
$body = $this->prepareBody();
if($body === false) return false;
$headers = $this->prepareHeaders();
return $headers.MAILHEADER_EOL.$body;
}
/**
* Send the mail
*
* Call this after all data was set
*
* @triggers MAIL_MESSAGE_SEND
* @return bool true if the mail was successfully passed to the MTA
*/
public function send() {
$success = false;
// prepare hook data
$data = array(
// pass the whole mail class to plugin
'mail' => $this,
// pass references for backward compatibility
'to' => &$this->headers['To'],
'cc' => &$this->headers['Cc'],
'bcc' => &$this->headers['Bcc'],
'from' => &$this->headers['From'],
'subject' => &$this->headers['Subject'],
'body' => &$this->text,
'params' => &$this->sendparam,
'headers' => '', // plugins shouldn't use this
// signal if we mailed successfully to AFTER event
'success' => &$success,
);
// do our thing if BEFORE hook approves
$evt = new Doku_Event('MAIL_MESSAGE_SEND', $data);
if($evt->advise_before(true)) {
// clean up before using the headers
$this->cleanHeaders();
// any recipients?
if(trim($this->headers['To']) === '' &&
trim($this->headers['Cc']) === '' &&
trim($this->headers['Bcc']) === ''
) return false;
// The To: header is special
if(array_key_exists('To', $this->headers)) {
$to = (string)$this->headers['To'];
unset($this->headers['To']);
} else {
$to = '';
}
// so is the subject
if(array_key_exists('Subject', $this->headers)) {
$subject = (string)$this->headers['Subject'];
unset($this->headers['Subject']);
} else {
$subject = '';
}
// make the body
$body = $this->prepareBody();
if($body === false) return false;
// cook the headers
$headers = $this->prepareHeaders();
// add any headers set by legacy plugins
if(trim($data['headers'])) {
$headers .= MAILHEADER_EOL.trim($data['headers']);
}
// send the thing
if(is_null($this->sendparam)) {
$success = @mail($to, $subject, $body, $headers);
} else {
$success = @mail($to, $subject, $body, $headers, $this->sendparam);
}
}
// any AFTER actions?
$evt->advise_after();
return $success;
}
}

View file

@ -0,0 +1,560 @@
<?php
/**
* Password Hashing Class
*
* This class implements various mechanisms used to hash passwords
*
* @author Andreas Gohr <andi@splitbrain.org>
* @license LGPL2
*/
class PassHash {
/**
* Verifies a cleartext password against a crypted hash
*
* The method and salt used for the crypted hash is determined automatically,
* then the clear text password is crypted using the same method. If both hashs
* match true is is returned else false
*
* @author Andreas Gohr <andi@splitbrain.org>
* @param $clear string Clear-Text password
* @param $hash string Hash to compare against
* @return bool
*/
function verify_hash($clear, $hash) {
$method = '';
$salt = '';
$magic = '';
//determine the used method and salt
$len = strlen($hash);
if(preg_match('/^\$1\$([^\$]{0,8})\$/', $hash, $m)) {
$method = 'smd5';
$salt = $m[1];
$magic = '1';
} elseif(preg_match('/^\$apr1\$([^\$]{0,8})\$/', $hash, $m)) {
$method = 'apr1';
$salt = $m[1];
$magic = 'apr1';
} elseif(preg_match('/^\$P\$(.{31})$/', $hash, $m)) {
$method = 'pmd5';
$salt = $m[1];
$magic = 'P';
} elseif(preg_match('/^\$H\$(.{31})$/', $hash, $m)) {
$method = 'pmd5';
$salt = $m[1];
$magic = 'H';
} elseif(preg_match('/^sha1\$(.{5})\$/', $hash, $m)) {
$method = 'djangosha1';
$salt = $m[1];
} elseif(preg_match('/^md5\$(.{5})\$/', $hash, $m)) {
$method = 'djangomd5';
$salt = $m[1];
} elseif(preg_match('/^\$2a\$(.{2})\$/', $hash, $m)) {
$method = 'bcrypt';
$salt = $hash;
} elseif(substr($hash, 0, 6) == '{SSHA}') {
$method = 'ssha';
$salt = substr(base64_decode(substr($hash, 6)), 20);
} elseif(substr($hash, 0, 6) == '{SMD5}') {
$method = 'lsmd5';
$salt = substr(base64_decode(substr($hash, 6)), 16);
} elseif(preg_match('/^:B:(.+?):.{32}$/', $hash, $m)) {
$method = 'mediawiki';
$salt = $m[1];
} elseif(preg_match('/^\$6\$(.+?)\$/', $hash, $m)) {
$method = 'sha512';
$salt = $m[1];
} elseif($len == 32) {
$method = 'md5';
} elseif($len == 40) {
$method = 'sha1';
} elseif($len == 16) {
$method = 'mysql';
} elseif($len == 41 && $hash[0] == '*') {
$method = 'my411';
} elseif($len == 34) {
$method = 'kmd5';
$salt = $hash;
} else {
$method = 'crypt';
$salt = substr($hash, 0, 2);
}
//crypt and compare
$call = 'hash_'.$method;
if($this->$call($clear, $salt, $magic) === $hash) {
return true;
}
return false;
}
/**
* Create a random salt
*
* @param int $len The length of the salt
* @return string
*/
public function gen_salt($len = 32) {
$salt = '';
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
for($i = 0; $i < $len; $i++) {
$salt .= $chars[$this->random(0, 61)];
}
return $salt;
}
/**
* Initialize the passed variable with a salt if needed.
*
* If $salt is not null, the value is kept, but the lenght restriction is
* applied (unless, $cut is false).
*
* @param string &$salt The salt, pass null if you want one generated
* @param int $len The length of the salt
* @param bool $cut Apply length restriction to existing salt?
*/
public function init_salt(&$salt, $len = 32, $cut = true) {
if(is_null($salt)) {
$salt = $this->gen_salt($len);
$cut = true; // for new hashes we alway apply length restriction
}
if(strlen($salt) > $len && $cut) $salt = substr($salt, 0, $len);
}
// Password hashing methods follow below
/**
* Password hashing method 'smd5'
*
* Uses salted MD5 hashs. Salt is 8 bytes long.
*
* The same mechanism is used by Apache's 'apr1' method. This will
* fallback to a implementation in pure PHP if MD5 support is not
* available in crypt()
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author <mikey_nich at hotmail dot com>
* @link http://de.php.net/manual/en/function.crypt.php#73619
* @param string $clear The clear text to hash
* @param string $salt The salt to use, null for random
* @return string Hashed password
*/
public function hash_smd5($clear, $salt = null) {
$this->init_salt($salt, 8);
if(defined('CRYPT_MD5') && CRYPT_MD5 && $salt !== '') {
return crypt($clear, '$1$'.$salt.'$');
} else {
// Fall back to PHP-only implementation
return $this->hash_apr1($clear, $salt, '1');
}
}
/**
* Password hashing method 'lsmd5'
*
* Uses salted MD5 hashs. Salt is 8 bytes long.
*
* This is the format used by LDAP.
*
* @param string $clear The clear text to hash
* @param string $salt The salt to use, null for random
* @return string Hashed password
*/
public function hash_lsmd5($clear, $salt = null) {
$this->init_salt($salt, 8);
return "{SMD5}".base64_encode(md5($clear.$salt, true).$salt);
}
/**
* Password hashing method 'apr1'
*
* Uses salted MD5 hashs. Salt is 8 bytes long.
*
* This is basically the same as smd1 above, but as used by Apache.
*
* @author <mikey_nich at hotmail dot com>
* @link http://de.php.net/manual/en/function.crypt.php#73619
* @param string $clear The clear text to hash
* @param string $salt The salt to use, null for random
* @param string $magic The hash identifier (apr1 or 1)
* @return string Hashed password
*/
public function hash_apr1($clear, $salt = null, $magic = 'apr1') {
$this->init_salt($salt, 8);
$len = strlen($clear);
$text = $clear.'$'.$magic.'$'.$salt;
$bin = pack("H32", md5($clear.$salt.$clear));
for($i = $len; $i > 0; $i -= 16) {
$text .= substr($bin, 0, min(16, $i));
}
for($i = $len; $i > 0; $i >>= 1) {
$text .= ($i & 1) ? chr(0) : $clear{0};
}
$bin = pack("H32", md5($text));
for($i = 0; $i < 1000; $i++) {
$new = ($i & 1) ? $clear : $bin;
if($i % 3) $new .= $salt;
if($i % 7) $new .= $clear;
$new .= ($i & 1) ? $bin : $clear;
$bin = pack("H32", md5($new));
}
$tmp = '';
for($i = 0; $i < 5; $i++) {
$k = $i + 6;
$j = $i + 12;
if($j == 16) $j = 5;
$tmp = $bin[$i].$bin[$k].$bin[$j].$tmp;
}
$tmp = chr(0).chr(0).$bin[11].$tmp;
$tmp = strtr(
strrev(substr(base64_encode($tmp), 2)),
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
);
return '$'.$magic.'$'.$salt.'$'.$tmp;
}
/**
* Password hashing method 'md5'
*
* Uses MD5 hashs.
*
* @param string $clear The clear text to hash
* @return string Hashed password
*/
public function hash_md5($clear) {
return md5($clear);
}
/**
* Password hashing method 'sha1'
*
* Uses SHA1 hashs.
*
* @param string $clear The clear text to hash
* @return string Hashed password
*/
public function hash_sha1($clear) {
return sha1($clear);
}
/**
* Password hashing method 'ssha' as used by LDAP
*
* Uses salted SHA1 hashs. Salt is 4 bytes long.
*
* @param string $clear The clear text to hash
* @param string $salt The salt to use, null for random
* @return string Hashed password
*/
public function hash_ssha($clear, $salt = null) {
$this->init_salt($salt, 4);
return '{SSHA}'.base64_encode(pack("H*", sha1($clear.$salt)).$salt);
}
/**
* Password hashing method 'crypt'
*
* Uses salted crypt hashs. Salt is 2 bytes long.
*
* @param string $clear The clear text to hash
* @param string $salt The salt to use, null for random
* @return string Hashed password
*/
public function hash_crypt($clear, $salt = null) {
$this->init_salt($salt, 2);
return crypt($clear, $salt);
}
/**
* Password hashing method 'mysql'
*
* This method was used by old MySQL systems
*
* @link http://www.php.net/mysql
* @author <soren at byu dot edu>
* @param string $clear The clear text to hash
* @return string Hashed password
*/
public function hash_mysql($clear) {
$nr = 0x50305735;
$nr2 = 0x12345671;
$add = 7;
$charArr = preg_split("//", $clear);
foreach($charArr as $char) {
if(($char == '') || ($char == ' ') || ($char == '\t')) continue;
$charVal = ord($char);
$nr ^= ((($nr & 63) + $add) * $charVal) + ($nr << 8);
$nr2 += ($nr2 << 8) ^ $nr;
$add += $charVal;
}
return sprintf("%08x%08x", ($nr & 0x7fffffff), ($nr2 & 0x7fffffff));
}
/**
* Password hashing method 'my411'
*
* Uses SHA1 hashs. This method is used by MySQL 4.11 and above
*
* @param string $clear The clear text to hash
* @return string Hashed password
*/
public function hash_my411($clear) {
return '*'.sha1(pack("H*", sha1($clear)));
}
/**
* Password hashing method 'kmd5'
*
* Uses salted MD5 hashs.
*
* Salt is 2 bytes long, but stored at position 16, so you need to pass at
* least 18 bytes. You can pass the crypted hash as salt.
*
* @param string $clear The clear text to hash
* @param string $salt The salt to use, null for random
* @return string Hashed password
*/
public function hash_kmd5($clear, $salt = null) {
$this->init_salt($salt);
$key = substr($salt, 16, 2);
$hash1 = strtolower(md5($key.md5($clear)));
$hash2 = substr($hash1, 0, 16).$key.substr($hash1, 16);
return $hash2;
}
/**
* Password hashing method 'pmd5'
*
* Uses salted MD5 hashs. Salt is 1+8 bytes long, 1st byte is the
* iteration count when given, for null salts $compute is used.
*
* The actual iteration count is the given count squared, maximum is
* 30 (-> 1073741824). If a higher one is given, the function throws
* an exception.
*
* @link http://www.openwall.com/phpass/
* @param string $clear The clear text to hash
* @param string $salt The salt to use, null for random
* @param string $magic The hash identifier (P or H)
* @param int $compute The iteration count for new passwords
* @throws Exception
* @return string Hashed password
*/
public function hash_pmd5($clear, $salt = null, $magic = 'P', $compute = 8) {
$itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
if(is_null($salt)) {
$this->init_salt($salt);
$salt = $itoa64[$compute].$salt; // prefix iteration count
}
$iterc = $salt[0]; // pos 0 of salt is iteration count
$iter = strpos($itoa64, $iterc);
if($iter > 30) {
throw new Exception("Too high iteration count ($iter) in ".
__CLASS__.'::'.__FUNCTION__);
}
$iter = 1 << $iter;
$salt = substr($salt, 1, 8);
// iterate
$hash = md5($salt.$clear, true);
do {
$hash = md5($hash.$clear, true);
} while(--$iter);
// encode
$output = '';
$count = 16;
$i = 0;
do {
$value = ord($hash[$i++]);
$output .= $itoa64[$value & 0x3f];
if($i < $count)
$value |= ord($hash[$i]) << 8;
$output .= $itoa64[($value >> 6) & 0x3f];
if($i++ >= $count)
break;
if($i < $count)
$value |= ord($hash[$i]) << 16;
$output .= $itoa64[($value >> 12) & 0x3f];
if($i++ >= $count)
break;
$output .= $itoa64[($value >> 18) & 0x3f];
} while($i < $count);
return '$'.$magic.'$'.$iterc.$salt.$output;
}
/**
* Alias for hash_pmd5
*/
public function hash_hmd5($clear, $salt = null, $magic = 'H', $compute = 8) {
return $this->hash_pmd5($clear, $salt, $magic, $compute);
}
/**
* Password hashing method 'djangosha1'
*
* Uses salted SHA1 hashs. Salt is 5 bytes long.
* This is used by the Django Python framework
*
* @link http://docs.djangoproject.com/en/dev/topics/auth/#passwords
* @param string $clear The clear text to hash
* @param string $salt The salt to use, null for random
* @return string Hashed password
*/
public function hash_djangosha1($clear, $salt = null) {
$this->init_salt($salt, 5);
return 'sha1$'.$salt.'$'.sha1($salt.$clear);
}
/**
* Password hashing method 'djangomd5'
*
* Uses salted MD5 hashs. Salt is 5 bytes long.
* This is used by the Django Python framework
*
* @link http://docs.djangoproject.com/en/dev/topics/auth/#passwords
* @param string $clear The clear text to hash
* @param string $salt The salt to use, null for random
* @return string Hashed password
*/
public function hash_djangomd5($clear, $salt = null) {
$this->init_salt($salt, 5);
return 'md5$'.$salt.'$'.md5($salt.$clear);
}
/**
* Passwordhashing method 'bcrypt'
*
* Uses a modified blowfish algorithm called eksblowfish
* This method works on PHP 5.3+ only and will throw an exception
* if the needed crypt support isn't available
*
* A full hash should be given as salt (starting with $a2$) or this
* will break. When no salt is given, the iteration count can be set
* through the $compute variable.
*
* @param string $clear The clear text to hash
* @param string $salt The salt to use, null for random
* @param int $compute The iteration count (between 4 and 31)
* @throws Exception
* @return string Hashed password
*/
public function hash_bcrypt($clear, $salt = null, $compute = 8) {
if(!defined('CRYPT_BLOWFISH') || CRYPT_BLOWFISH != 1) {
throw new Exception('This PHP installation has no bcrypt support');
}
if(is_null($salt)) {
if($compute < 4 || $compute > 31) $compute = 8;
$salt = '$2a$'.str_pad($compute, 2, '0', STR_PAD_LEFT).'$'.
$this->gen_salt(22);
}
return crypt($clear, $salt);
}
/**
* Password hashing method SHA512
*
* This is only supported on PHP 5.3.2 or higher and will throw an exception if
* the needed crypt support is not available
*
* @param string $clear The clear text to hash
* @param string $salt The salt to use, null for random
* @return string Hashed password
* @throws Exception
*/
public function hash_sha512($clear, $salt = null) {
if(!defined('CRYPT_SHA512') || CRYPT_SHA512 != 1) {
throw new Exception('This PHP installation has no SHA512 support');
}
$this->init_salt($salt, 8, false);
return crypt($clear, '$6$'.$salt.'$');
}
/**
* Password hashing method 'mediawiki'
*
* Uses salted MD5, this is referred to as Method B in MediaWiki docs. Unsalted md5
* method 'A' is not supported.
*
* @link http://www.mediawiki.org/wiki/Manual_talk:User_table#user_password_column
* @param string $clear The clear text to hash
* @param string $salt The salt to use, null for random
* @return string Hashed password
*/
public function hash_mediawiki($clear, $salt = null) {
$this->init_salt($salt, 8, false);
return ':B:'.$salt.':'.md5($salt.'-'.md5($clear));
}
/**
* Wraps around native hash_hmac() or reimplents it
*
* This is not directly used as password hashing method, and thus isn't callable via the
* verify_hash() method. It should be used to create signatures and might be used in other
* password hashing methods.
*
* @see hash_hmac()
* @author KC Cloyd
* @link http://www.php.net/manual/en/function.hash-hmac.php#93440
*
* @param string $algo Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4",
* etc..) See hash_algos() for a list of supported algorithms.
* @param string $data Message to be hashed.
* @param string $key Shared secret key used for generating the HMAC variant of the message digest.
* @param bool $raw_output When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits.
*
* @return string
*/
public static function hmac($algo, $data, $key, $raw_output = false) {
// use native function if available and not in unit test
if(function_exists('hash_hmac') && !defined('SIMPLE_TEST')){
return hash_hmac($algo, $data, $key, $raw_output);
}
$algo = strtolower($algo);
$pack = 'H' . strlen($algo('test'));
$size = 64;
$opad = str_repeat(chr(0x5C), $size);
$ipad = str_repeat(chr(0x36), $size);
if(strlen($key) > $size) {
$key = str_pad(pack($pack, $algo($key)), $size, chr(0x00));
} else {
$key = str_pad($key, $size, chr(0x00));
}
for($i = 0; $i < strlen($key) - 1; $i++) {
$opad[$i] = $opad[$i] ^ $key[$i];
$ipad[$i] = $ipad[$i] ^ $key[$i];
}
$output = $algo($opad . pack($pack, $algo($ipad . $data)));
return ($raw_output) ? pack($pack, $output) : $output;
}
/**
* Use DokuWiki's secure random generator if available
*
* @param $min
* @param $max
*
* @return int
*/
protected function random($min, $max){
if(function_exists('auth_random')){
return auth_random($min, $max);
}else{
return mt_rand($min, $max);
}
}
}

View file

@ -0,0 +1,780 @@
<?php
/**
* Increased whenever the API is changed
*/
define('DOKU_API_VERSION', 8);
class RemoteAPICore {
private $api;
public function __construct(RemoteAPI $api) {
$this->api = $api;
}
function __getRemoteInfo() {
return array(
'dokuwiki.getVersion' => array(
'args' => array(),
'return' => 'string',
'doc' => 'Returns the running DokuWiki version.'
), 'dokuwiki.login' => array(
'args' => array('string', 'string'),
'return' => 'int',
'doc' => 'Tries to login with the given credentials and sets auth cookies.',
'public' => '1'
), 'dokuwiki.getPagelist' => array(
'args' => array('string', 'array'),
'return' => 'array',
'doc' => 'List all pages within the given namespace.',
'name' => 'readNamespace'
), 'dokuwiki.search' => array(
'args' => array('string'),
'return' => 'array',
'doc' => 'Perform a fulltext search and return a list of matching pages'
), 'dokuwiki.getTime' => array(
'args' => array(),
'return' => 'int',
'doc' => 'Returns the current time at the remote wiki server as Unix timestamp.',
), 'dokuwiki.setLocks' => array(
'args' => array('array'),
'return' => 'array',
'doc' => 'Lock or unlock pages.'
), 'dokuwiki.getTitle' => array(
'args' => array(),
'return' => 'string',
'doc' => 'Returns the wiki title.',
'public' => '1'
), 'dokuwiki.appendPage' => array(
'args' => array('string', 'string', 'array'),
'return' => 'bool',
'doc' => 'Append text to a wiki page.'
), 'wiki.getPage' => array(
'args' => array('string'),
'return' => 'string',
'doc' => 'Get the raw Wiki text of page, latest version.',
'name' => 'rawPage',
), 'wiki.getPageVersion' => array(
'args' => array('string', 'int'),
'name' => 'rawPage',
'return' => 'string',
'doc' => 'Return a raw wiki page'
), 'wiki.getPageHTML' => array(
'args' => array('string'),
'return' => 'string',
'doc' => 'Return page in rendered HTML, latest version.',
'name' => 'htmlPage'
), 'wiki.getPageHTMLVersion' => array(
'args' => array('string', 'int'),
'return' => 'string',
'doc' => 'Return page in rendered HTML.',
'name' => 'htmlPage'
), 'wiki.getAllPages' => array(
'args' => array(),
'return' => 'array',
'doc' => 'Returns a list of all pages. The result is an array of utf8 pagenames.',
'name' => 'listPages'
), 'wiki.getAttachments' => array(
'args' => array('string', 'array'),
'return' => 'array',
'doc' => 'Returns a list of all media files.',
'name' => 'listAttachments'
), 'wiki.getBackLinks' => array(
'args' => array('string'),
'return' => 'array',
'doc' => 'Returns the pages that link to this page.',
'name' => 'listBackLinks'
), 'wiki.getPageInfo' => array(
'args' => array('string'),
'return' => 'array',
'doc' => 'Returns a struct with info about the page.',
'name' => 'pageInfo'
), 'wiki.getPageInfoVersion' => array(
'args' => array('string', 'int'),
'return' => 'array',
'doc' => 'Returns a struct with info about the page.',
'name' => 'pageInfo'
), 'wiki.getPageVersions' => array(
'args' => array('string', 'int'),
'return' => 'array',
'doc' => 'Returns the available revisions of the page.',
'name' => 'pageVersions'
), 'wiki.putPage' => array(
'args' => array('string', 'string', 'array'),
'return' => 'bool',
'doc' => 'Saves a wiki page.'
), 'wiki.listLinks' => array(
'args' => array('string'),
'return' => 'array',
'doc' => 'Lists all links contained in a wiki page.'
), 'wiki.getRecentChanges' => array(
'args' => array('int'),
'return' => 'array',
'Returns a struct about all recent changes since given timestamp.'
), 'wiki.getRecentMediaChanges' => array(
'args' => array('int'),
'return' => 'array',
'Returns a struct about all recent media changes since given timestamp.'
), 'wiki.aclCheck' => array(
'args' => array('string'),
'return' => 'int',
'doc' => 'Returns the permissions of a given wiki page.'
), 'wiki.putAttachment' => array(
'args' => array('string', 'file', 'array'),
'return' => 'array',
'doc' => 'Upload a file to the wiki.'
), 'wiki.deleteAttachment' => array(
'args' => array('string'),
'return' => 'int',
'doc' => 'Delete a file from the wiki.'
), 'wiki.getAttachment' => array(
'args' => array('string'),
'doc' => 'Return a media file',
'return' => 'file',
'name' => 'getAttachment',
), 'wiki.getAttachmentInfo' => array(
'args' => array('string'),
'return' => 'array',
'doc' => 'Returns a struct with info about the attachment.'
), 'dokuwiki.getXMLRPCAPIVersion' => array(
'args' => array(),
'name' => 'getAPIVersion',
'return' => 'int',
'doc' => 'Returns the XMLRPC API version.',
'public' => '1',
), 'wiki.getRPCVersionSupported' => array(
'args' => array(),
'name' => 'wiki_RPCVersion',
'return' => 'int',
'doc' => 'Returns 2 with the supported RPC API version.',
'public' => '1'
),
);
}
function getVersion() {
return getVersion();
}
function getTime() {
return time();
}
/**
* Return a raw wiki page
* @param string $id wiki page id
* @param string $rev revision number of the page
* @return page text.
*/
function rawPage($id,$rev=''){
$id = $this->resolvePageId($id);
if(auth_quickaclcheck($id) < AUTH_READ){
throw new RemoteAccessDeniedException('You are not allowed to read this file', 111);
}
$text = rawWiki($id,$rev);
if(!$text) {
return pageTemplate($id);
} else {
return $text;
}
}
/**
* Return a media file
*
* @author Gina Haeussge <osd@foosel.net>
* @param string $id file id
* @return media file
*/
function getAttachment($id){
$id = cleanID($id);
if (auth_quickaclcheck(getNS($id).':*') < AUTH_READ) {
throw new RemoteAccessDeniedException('You are not allowed to read this file', 211);
}
$file = mediaFN($id);
if (!@ file_exists($file)) {
throw new RemoteException('The requested file does not exist', 221);
}
$data = io_readFile($file, false);
return $this->api->toFile($data);
}
/**
* Return info about a media file
*
* @author Gina Haeussge <osd@foosel.net>
*/
function getAttachmentInfo($id){
$id = cleanID($id);
$info = array(
'lastModified' => $this->api->toDate(0),
'size' => 0,
);
$file = mediaFN($id);
if ((auth_quickaclcheck(getNS($id).':*') >= AUTH_READ) && file_exists($file)){
$info['lastModified'] = $this->api->toDate(filemtime($file));
$info['size'] = filesize($file);
}
return $info;
}
/**
* Return a wiki page rendered to html
*/
function htmlPage($id,$rev=''){
$id = $this->resolvePageId($id);
if(auth_quickaclcheck($id) < AUTH_READ){
throw new RemoteAccessDeniedException('You are not allowed to read this page', 111);
}
return p_wiki_xhtml($id,$rev,false);
}
/**
* List all pages - we use the indexer list here
*/
function listPages(){
$list = array();
$pages = idx_get_indexer()->getPages();
$pages = array_filter(array_filter($pages,'isVisiblePage'),'page_exists');
foreach(array_keys($pages) as $idx) {
$perm = auth_quickaclcheck($pages[$idx]);
if($perm < AUTH_READ) {
continue;
}
$page = array();
$page['id'] = trim($pages[$idx]);
$page['perms'] = $perm;
$page['size'] = @filesize(wikiFN($pages[$idx]));
$page['lastModified'] = $this->api->toDate(@filemtime(wikiFN($pages[$idx])));
$list[] = $page;
}
return $list;
}
/**
* List all pages in the given namespace (and below)
*/
function readNamespace($ns,$opts){
global $conf;
if(!is_array($opts)) $opts=array();
$ns = cleanID($ns);
$dir = utf8_encodeFN(str_replace(':', '/', $ns));
$data = array();
$opts['skipacl'] = 0; // no ACL skipping for XMLRPC
search($data, $conf['datadir'], 'search_allpages', $opts, $dir);
return $data;
}
/**
* List all pages in the given namespace (and below)
*/
function search($query){
$regex = '';
$data = ft_pageSearch($query,$regex);
$pages = array();
// prepare additional data
$idx = 0;
foreach($data as $id => $score){
$file = wikiFN($id);
if($idx < FT_SNIPPET_NUMBER){
$snippet = ft_snippet($id,$regex);
$idx++;
}else{
$snippet = '';
}
$pages[] = array(
'id' => $id,
'score' => intval($score),
'rev' => filemtime($file),
'mtime' => filemtime($file),
'size' => filesize($file),
'snippet' => $snippet,
'title' => useHeading('navigation') ? p_get_first_heading($id) : $id
);
}
return $pages;
}
/**
* Returns the wiki title.
*/
function getTitle(){
global $conf;
return $conf['title'];
}
/**
* List all media files.
*
* Available options are 'recursive' for also including the subnamespaces
* in the listing, and 'pattern' for filtering the returned files against
* a regular expression matching their name.
*
* @author Gina Haeussge <osd@foosel.net>
*/
function listAttachments($ns, $options = array()) {
global $conf;
$ns = cleanID($ns);
if (!is_array($options)) $options = array();
$options['skipacl'] = 0; // no ACL skipping for XMLRPC
if(auth_quickaclcheck($ns.':*') >= AUTH_READ) {
$dir = utf8_encodeFN(str_replace(':', '/', $ns));
$data = array();
search($data, $conf['mediadir'], 'search_media', $options, $dir);
$len = count($data);
if(!$len) return array();
for($i=0; $i<$len; $i++) {
unset($data[$i]['meta']);
$data[$i]['perms'] = $data[$i]['perm'];
unset($data[$i]['perm']);
$data[$i]['lastModified'] = $this->api->toDate($data[$i]['mtime']);
}
return $data;
} else {
throw new RemoteAccessDeniedException('You are not allowed to list media files.', 215);
}
}
/**
* Return a list of backlinks
*/
function listBackLinks($id){
return ft_backlinks($this->resolvePageId($id));
}
/**
* Return some basic data about a page
*/
function pageInfo($id,$rev=''){
$id = $this->resolvePageId($id);
if(auth_quickaclcheck($id) < AUTH_READ){
throw new RemoteAccessDeniedException('You are not allowed to read this page', 111);
}
$file = wikiFN($id,$rev);
$time = @filemtime($file);
if(!$time){
throw new RemoteException('The requested page does not exist', 121);
}
$info = getRevisionInfo($id, $time, 1024);
$data = array(
'name' => $id,
'lastModified' => $this->api->toDate($time),
'author' => (($info['user']) ? $info['user'] : $info['ip']),
'version' => $time
);
return ($data);
}
/**
* Save a wiki page
*
* @author Michael Klier <chi@chimeric.de>
*/
function putPage($id, $text, $params) {
global $TEXT;
global $lang;
$id = $this->resolvePageId($id);
$TEXT = cleanText($text);
$sum = $params['sum'];
$minor = $params['minor'];
if(empty($id)) {
throw new RemoteException('Empty page ID', 131);
}
if(!page_exists($id) && trim($TEXT) == '' ) {
throw new RemoteException('Refusing to write an empty new wiki page', 132);
}
if(auth_quickaclcheck($id) < AUTH_EDIT) {
throw new RemoteAccessDeniedException('You are not allowed to edit this page', 112);
}
// Check, if page is locked
if(checklock($id)) {
throw new RemoteException('The page is currently locked', 133);
}
// SPAM check
if(checkwordblock()) {
throw new RemoteException('Positive wordblock check', 134);
}
// autoset summary on new pages
if(!page_exists($id) && empty($sum)) {
$sum = $lang['created'];
}
// autoset summary on deleted pages
if(page_exists($id) && empty($TEXT) && empty($sum)) {
$sum = $lang['deleted'];
}
lock($id);
saveWikiText($id,$TEXT,$sum,$minor);
unlock($id);
// run the indexer if page wasn't indexed yet
idx_addPage($id);
return true;
}
/**
* Appends text to a wiki page.
*/
function appendPage($id, $text, $params) {
$currentpage = $this->rawPage($id);
if (!is_string($currentpage)) {
return $currentpage;
}
return $this->putPage($id, $currentpage.$text, $params);
}
/**
* Uploads a file to the wiki.
*
* Michael Klier <chi@chimeric.de>
*/
function putAttachment($id, $file, $params) {
$id = cleanID($id);
$auth = auth_quickaclcheck(getNS($id).':*');
if(!isset($id)) {
throw new RemoteException('Filename not given.', 231);
}
global $conf;
$ftmp = $conf['tmpdir'] . '/' . md5($id.clientIP());
// save temporary file
@unlink($ftmp);
io_saveFile($ftmp, $file);
$res = media_save(array('name' => $ftmp), $id, $params['ow'], $auth, 'rename');
if (is_array($res)) {
throw new RemoteException($res[0], -$res[1]);
} else {
return $res;
}
}
/**
* Deletes a file from the wiki.
*
* @author Gina Haeussge <osd@foosel.net>
*/
function deleteAttachment($id){
$id = cleanID($id);
$auth = auth_quickaclcheck(getNS($id).':*');
$res = media_delete($id, $auth);
if ($res & DOKU_MEDIA_DELETED) {
return 0;
} elseif ($res & DOKU_MEDIA_NOT_AUTH) {
throw new RemoteAccessDeniedException('You don\'t have permissions to delete files.', 212);
} elseif ($res & DOKU_MEDIA_INUSE) {
throw new RemoteException('File is still referenced', 232);
} else {
throw new RemoteException('Could not delete file', 233);
}
}
/**
* Returns the permissions of a given wiki page
*/
function aclCheck($id) {
$id = $this->resolvePageId($id);
return auth_quickaclcheck($id);
}
/**
* Lists all links contained in a wiki page
*
* @author Michael Klier <chi@chimeric.de>
*/
function listLinks($id) {
$id = $this->resolvePageId($id);
if(auth_quickaclcheck($id) < AUTH_READ){
throw new RemoteAccessDeniedException('You are not allowed to read this page', 111);
}
$links = array();
// resolve page instructions
$ins = p_cached_instructions(wikiFN($id));
// instantiate new Renderer - needed for interwiki links
include(DOKU_INC.'inc/parser/xhtml.php');
$Renderer = new Doku_Renderer_xhtml();
$Renderer->interwiki = getInterwiki();
// parse parse instructions
foreach($ins as $in) {
$link = array();
switch($in[0]) {
case 'internallink':
$link['type'] = 'local';
$link['page'] = $in[1][0];
$link['href'] = wl($in[1][0]);
array_push($links,$link);
break;
case 'externallink':
$link['type'] = 'extern';
$link['page'] = $in[1][0];
$link['href'] = $in[1][0];
array_push($links,$link);
break;
case 'interwikilink':
$url = $Renderer->_resolveInterWiki($in[1][2],$in[1][3]);
$link['type'] = 'extern';
$link['page'] = $url;
$link['href'] = $url;
array_push($links,$link);
break;
}
}
return ($links);
}
/**
* Returns a list of recent changes since give timestamp
*
* @author Michael Hamann <michael@content-space.de>
* @author Michael Klier <chi@chimeric.de>
*/
function getRecentChanges($timestamp) {
if(strlen($timestamp) != 10) {
throw new RemoteException('The provided value is not a valid timestamp', 311);
}
$recents = getRecentsSince($timestamp);
$changes = array();
foreach ($recents as $recent) {
$change = array();
$change['name'] = $recent['id'];
$change['lastModified'] = $this->api->toDate($recent['date']);
$change['author'] = $recent['user'];
$change['version'] = $recent['date'];
$change['perms'] = $recent['perms'];
$change['size'] = @filesize(wikiFN($recent['id']));
array_push($changes, $change);
}
if (!empty($changes)) {
return $changes;
} else {
// in case we still have nothing at this point
return new RemoteException('There are no changes in the specified timeframe', 321);
}
}
/**
* Returns a list of recent media changes since give timestamp
*
* @author Michael Hamann <michael@content-space.de>
* @author Michael Klier <chi@chimeric.de>
*/
function getRecentMediaChanges($timestamp) {
if(strlen($timestamp) != 10)
throw new RemoteException('The provided value is not a valid timestamp', 311);
$recents = getRecentsSince($timestamp, null, '', RECENTS_MEDIA_CHANGES);
$changes = array();
foreach ($recents as $recent) {
$change = array();
$change['name'] = $recent['id'];
$change['lastModified'] = $this->api->toDate($recent['date']);
$change['author'] = $recent['user'];
$change['version'] = $recent['date'];
$change['perms'] = $recent['perms'];
$change['size'] = @filesize(mediaFN($recent['id']));
array_push($changes, $change);
}
if (!empty($changes)) {
return $changes;
} else {
// in case we still have nothing at this point
throw new RemoteException('There are no changes in the specified timeframe', 321);
}
}
/**
* Returns a list of available revisions of a given wiki page
*
* @author Michael Klier <chi@chimeric.de>
*/
function pageVersions($id, $first) {
$id = $this->resolvePageId($id);
if(auth_quickaclcheck($id) < AUTH_READ) {
throw new RemoteAccessDeniedException('You are not allowed to read this page', 111);
}
global $conf;
$versions = array();
if(empty($id)) {
throw new RemoteException('Empty page ID', 131);
}
$revisions = getRevisions($id, $first, $conf['recent']+1);
if(count($revisions)==0 && $first!=0) {
$first=0;
$revisions = getRevisions($id, $first, $conf['recent']+1);
}
if(count($revisions)>0 && $first==0) {
array_unshift($revisions, ''); // include current revision
if ( count($revisions) > $conf['recent'] ){
array_pop($revisions); // remove extra log entry
}
}
if(count($revisions) > $conf['recent']) {
array_pop($revisions); // remove extra log entry
}
if(!empty($revisions)) {
foreach($revisions as $rev) {
$file = wikiFN($id,$rev);
$time = @filemtime($file);
// we check if the page actually exists, if this is not the
// case this can lead to less pages being returned than
// specified via $conf['recent']
if($time){
$info = getRevisionInfo($id, $time, 1024);
if(!empty($info)) {
$data['user'] = $info['user'];
$data['ip'] = $info['ip'];
$data['type'] = $info['type'];
$data['sum'] = $info['sum'];
$data['modified'] = $this->api->toDate($info['date']);
$data['version'] = $info['date'];
array_push($versions, $data);
}
}
}
return $versions;
} else {
return array();
}
}
/**
* The version of Wiki RPC API supported
*/
function wiki_RPCVersion(){
return 2;
}
/**
* Locks or unlocks a given batch of pages
*
* Give an associative array with two keys: lock and unlock. Both should contain a
* list of pages to lock or unlock
*
* Returns an associative array with the keys locked, lockfail, unlocked and
* unlockfail, each containing lists of pages.
*/
function setLocks($set){
$locked = array();
$lockfail = array();
$unlocked = array();
$unlockfail = array();
foreach((array) $set['lock'] as $id){
$id = $this->resolvePageId($id);
if(auth_quickaclcheck($id) < AUTH_EDIT || checklock($id)){
$lockfail[] = $id;
}else{
lock($id);
$locked[] = $id;
}
}
foreach((array) $set['unlock'] as $id){
$id = $this->resolvePageId($id);
if(auth_quickaclcheck($id) < AUTH_EDIT || !unlock($id)){
$unlockfail[] = $id;
}else{
$unlocked[] = $id;
}
}
return array(
'locked' => $locked,
'lockfail' => $lockfail,
'unlocked' => $unlocked,
'unlockfail' => $unlockfail,
);
}
function getAPIVersion(){
return DOKU_API_VERSION;
}
function login($user,$pass){
global $conf;
global $auth;
if(!$conf['useacl']) return 0;
if(!$auth) return 0;
@session_start(); // reopen session for login
if($auth->canDo('external')){
$ok = $auth->trustExternal($user,$pass,false);
}else{
$evdata = array(
'user' => $user,
'password' => $pass,
'sticky' => false,
'silent' => true,
);
$ok = trigger_event('AUTH_LOGIN_CHECK', $evdata, 'auth_login_wrapper');
}
session_write_close(); // we're done with the session
return $ok;
}
private function resolvePageId($id) {
$id = cleanID($id);
if(empty($id)) {
global $conf;
$id = cleanID($conf['start']);
}
return $id;
}
}

View file

@ -0,0 +1,158 @@
<?php
/**
* Class to safely store UTF-8 in a Filename
*
* Encodes a utf8 string using only the following characters 0-9a-z_.-%
* characters 0-9a-z in the original string are preserved, "plain".
* all other characters are represented in a substring that starts
* with '%' are "converted".
* The transition from converted substrings to plain characters is
* marked with a '.'
*
* @author Christopher Smith <chris@jalakai.co.uk>
* @date 2010-04-02
*/
class SafeFN {
// 'safe' characters are a superset of $plain, $pre_indicator and $post_indicator
private static $plain = '-./[_0123456789abcdefghijklmnopqrstuvwxyz'; // these characters aren't converted
private static $pre_indicator = '%';
private static $post_indicator = ']';
/**
* Convert an UTF-8 string to a safe ASCII String
*
* conversion process
* - if codepoint is a plain or post_indicator character,
* - if previous character was "converted", append post_indicator to output, clear "converted" flag
* - append ascii byte for character to output
* (continue to next character)
*
* - if codepoint is a pre_indicator character,
* - append ascii byte for character to output, set "converted" flag
* (continue to next character)
*
* (all remaining characters)
* - reduce codepoint value for non-printable ASCII characters (0x00 - 0x1f). Space becomes our zero.
* - convert reduced value to base36 (0-9a-z)
* - append $pre_indicator characater followed by base36 string to output, set converted flag
* (continue to next character)
*
* @param string $filename a utf8 string, should only include printable characters - not 0x00-0x1f
* @return string an encoded representation of $filename using only 'safe' ASCII characters
*
* @author Christopher Smith <chris@jalakai.co.uk>
*/
public static function encode($filename) {
return self::unicode_to_safe(utf8_to_unicode($filename));
}
/**
* decoding process
* - split the string into substrings at any occurrence of pre or post indicator characters
* - check the first character of the substring
* - if its not a pre_indicator character
* - if previous character was converted, skip over post_indicator character
* - copy codepoint values of remaining characters to the output array
* - clear any converted flag
* (continue to next substring)
*
* _ else (its a pre_indicator character)
* - if string length is 1, copy the post_indicator character to the output array
* (continue to next substring)
*
* - else (string length > 1)
* - skip the pre-indicator character and convert remaining string from base36 to base10
* - increase codepoint value for non-printable ASCII characters (add 0x20)
* - append codepoint to output array
* (continue to next substring)
*
* @param string $filename a 'safe' encoded ASCII string,
* @return string decoded utf8 representation of $filename
*
* @author Christopher Smith <chris@jalakai.co.uk>
*/
public static function decode($filename) {
return unicode_to_utf8(self::safe_to_unicode(strtolower($filename)));
}
public static function validate_printable_utf8($printable_utf8) {
return !preg_match('#[\x01-\x1f]#',$printable_utf8);
}
public static function validate_safe($safe) {
return !preg_match('#[^'.self::$plain.self::$post_indicator.self::$pre_indicator.']#',$safe);
}
/**
* convert an array of unicode codepoints into 'safe_filename' format
*
* @param array int $unicode an array of unicode codepoints
* @return string the unicode represented in 'safe_filename' format
*
* @author Christopher Smith <chris@jalakai.co.uk>
*/
private static function unicode_to_safe($unicode) {
$safe = '';
$converted = false;
foreach ($unicode as $codepoint) {
if ($codepoint < 127 && (strpos(self::$plain.self::$post_indicator,chr($codepoint))!==false)) {
if ($converted) {
$safe .= self::$post_indicator;
$converted = false;
}
$safe .= chr($codepoint);
} else if ($codepoint == ord(self::$pre_indicator)) {
$safe .= self::$pre_indicator;
$converted = true;
} else {
$safe .= self::$pre_indicator.base_convert((string)($codepoint-32),10,36);
$converted = true;
}
}
if($converted) $safe .= self::$post_indicator;
return $safe;
}
/**
* convert a 'safe_filename' string into an array of unicode codepoints
*
* @param string $safe a filename in 'safe_filename' format
* @return array int an array of unicode codepoints
*
* @author Christopher Smith <chris@jalakai.co.uk>
*/
private static function safe_to_unicode($safe) {
$unicode = array();
$split = preg_split('#(?=['.self::$post_indicator.self::$pre_indicator.'])#',$safe,-1,PREG_SPLIT_NO_EMPTY);
$converted = false;
foreach ($split as $sub) {
$len = strlen($sub);
if ($sub[0] != self::$pre_indicator) {
// plain (unconverted) characters, optionally starting with a post_indicator
// set initial value to skip any post_indicator
for ($i=($converted?1:0); $i < $len; $i++) {
$unicode[] = ord($sub[$i]);
}
$converted = false;
} else if ($len==1) {
// a pre_indicator character in the real data
$unicode[] = ord($sub);
$converted = true;
} else {
// a single codepoint in base36, adjusted for initial 32 non-printable chars
$unicode[] = 32 + (int)base_convert(substr($sub,1),36,10);
$converted = true;
}
}
return $unicode;
}
}

17772
sources/inc/SimplePie.php Normal file

File diff suppressed because it is too large Load diff

214
sources/inc/Sitemapper.php Normal file
View file

@ -0,0 +1,214 @@
<?php
/**
* Sitemap handling functions
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Michael Hamann <michael@content-space.de>
*/
if(!defined('DOKU_INC')) die('meh.');
/**
* A class for building sitemaps and pinging search engines with the sitemap URL.
*
* @author Michael Hamann
*/
class Sitemapper {
/**
* Builds a Google Sitemap of all public pages known to the indexer
*
* The map is placed in the cache directory named sitemap.xml.gz - This
* file needs to be writable!
*
* @author Michael Hamann
* @author Andreas Gohr
* @link https://www.google.com/webmasters/sitemaps/docs/en/about.html
* @link http://www.sitemaps.org/
*/
public static function generate(){
global $conf;
if($conf['sitemap'] < 1 || !is_numeric($conf['sitemap'])) return false;
$sitemap = Sitemapper::getFilePath();
if(@file_exists($sitemap)){
if(!is_writable($sitemap)) return false;
}else{
if(!is_writable(dirname($sitemap))) return false;
}
if(@filesize($sitemap) &&
@filemtime($sitemap) > (time()-($conf['sitemap']*86400))){ // 60*60*24=86400
dbglog('Sitemapper::generate(): Sitemap up to date');
return false;
}
dbglog("Sitemapper::generate(): using $sitemap");
$pages = idx_get_indexer()->getPages();
dbglog('Sitemapper::generate(): creating sitemap using '.count($pages).' pages');
$items = array();
// build the sitemap items
foreach($pages as $id){
//skip hidden, non existing and restricted files
if(isHiddenPage($id)) continue;
if(auth_aclcheck($id,'','') < AUTH_READ) continue;
$item = SitemapItem::createFromID($id);
if ($item !== null)
$items[] = $item;
}
$eventData = array('items' => &$items, 'sitemap' => &$sitemap);
$event = new Doku_Event('SITEMAP_GENERATE', $eventData);
if ($event->advise_before(true)) {
//save the new sitemap
$event->result = io_saveFile($sitemap, Sitemapper::getXML($items));
}
$event->advise_after();
return $event->result;
}
/**
* Builds the sitemap XML string from the given array auf SitemapItems.
*
* @param $items array The SitemapItems that shall be included in the sitemap.
* @return string The sitemap XML.
* @author Michael Hamann
*/
private static function getXML($items) {
ob_start();
echo '<?xml version="1.0" encoding="UTF-8"?>'.NL;
echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'.NL;
foreach ($items as $item) {
/** @var SitemapItem $item */
echo $item->toXML();
}
echo '</urlset>'.NL;
$result = ob_get_contents();
ob_end_clean();
return $result;
}
/**
* Helper function for getting the path to the sitemap file.
*
* @return string The path to the sitemap file.
* @author Michael Hamann
*/
public static function getFilePath() {
global $conf;
$sitemap = $conf['cachedir'].'/sitemap.xml';
if (self::sitemapIsCompressed()) {
$sitemap .= '.gz';
}
return $sitemap;
}
/**
* Helper function for checking if the sitemap is compressed
*
* @return bool If the sitemap file is compressed
*/
public static function sitemapIsCompressed() {
global $conf;
return $conf['compression'] === 'bz2' || $conf['compression'] === 'gz';
}
/**
* Pings search engines with the sitemap url. Plugins can add or remove
* urls to ping using the SITEMAP_PING event.
*
* @author Michael Hamann
*/
public static function pingSearchEngines() {
//ping search engines...
$http = new DokuHTTPClient();
$http->timeout = 8;
$encoded_sitemap_url = urlencode(wl('', array('do' => 'sitemap'), true, '&'));
$ping_urls = array(
'google' => 'http://www.google.com/webmasters/sitemaps/ping?sitemap='.$encoded_sitemap_url,
'yahoo' => 'http://search.yahooapis.com/SiteExplorerService/V1/updateNotification?appid=dokuwiki&url='.$encoded_sitemap_url,
'microsoft' => 'http://www.bing.com/webmaster/ping.aspx?siteMap='.$encoded_sitemap_url,
);
$data = array('ping_urls' => $ping_urls,
'encoded_sitemap_url' => $encoded_sitemap_url
);
$event = new Doku_Event('SITEMAP_PING', $data);
if ($event->advise_before(true)) {
foreach ($data['ping_urls'] as $name => $url) {
dbglog("Sitemapper::PingSearchEngines(): pinging $name");
$resp = $http->get($url);
if($http->error) dbglog("Sitemapper:pingSearchengines(): $http->error");
dbglog('Sitemapper:pingSearchengines(): '.preg_replace('/[\n\r]/',' ',strip_tags($resp)));
}
}
$event->advise_after();
return true;
}
}
/**
* An item of a sitemap.
*
* @author Michael Hamann
*/
class SitemapItem {
public $url;
public $lastmod;
public $changefreq;
public $priority;
/**
* Create a new item.
*
* @param $url string The url of the item
* @param $lastmod int Timestamp of the last modification
* @param $changefreq string How frequently the item is likely to change. Valid values: always, hourly, daily, weekly, monthly, yearly, never.
* @param $priority float|string The priority of the item relative to other URLs on your site. Valid values range from 0.0 to 1.0.
*/
public function __construct($url, $lastmod, $changefreq = null, $priority = null) {
$this->url = $url;
$this->lastmod = $lastmod;
$this->changefreq = $changefreq;
$this->priority = $priority;
}
/**
* Helper function for creating an item for a wikipage id.
*
* @param $id string A wikipage id.
* @param $changefreq string How frequently the item is likely to change. Valid values: always, hourly, daily, weekly, monthly, yearly, never.
* @param $priority float|string The priority of the item relative to other URLs on your site. Valid values range from 0.0 to 1.0.
* @return SitemapItem The sitemap item.
*/
public static function createFromID($id, $changefreq = null, $priority = null) {
$id = trim($id);
$date = @filemtime(wikiFN($id));
if(!$date) return null;
return new SitemapItem(wl($id, '', true), $date, $changefreq, $priority);
}
/**
* Get the XML representation of the sitemap item.
*
* @return string The XML representation.
*/
public function toXML() {
$result = ' <url>'.NL
.' <loc>'.hsc($this->url).'</loc>'.NL
.' <lastmod>'.date_iso8601($this->lastmod).'</lastmod>'.NL;
if ($this->changefreq !== null)
$result .= ' <changefreq>'.hsc($this->changefreq).'</changefreq>'.NL;
if ($this->priority !== null)
$result .= ' <priority>'.hsc($this->priority).'</priority>'.NL;
$result .= ' </url>'.NL;
return $result;
}
}

631
sources/inc/Tar.class.php Normal file
View file

@ -0,0 +1,631 @@
<?php
/**
* This class allows the extraction of existing and the creation of new Unix TAR archives.
* To keep things simple, the modification of existing archives is not supported. It handles
* uncompressed, gzip and bzip2 compressed tar files.
*
* Long pathnames (>100 chars) are supported in POSIX ustar and GNU longlink formats.
*
* To list the contents of an existing TAR archive, open() it and use contents() on it:
*
* $tar = new Tar();
* $tar->open('myfile.tgz');
* $toc = $tar->contents();
* print_r($toc);
*
* To extract the contents of an existing TAR archive, open() it and use extract() on it:
*
* $tar = new Tar();
* $tar->open('myfile.tgz');
* $tar->extract('/tmp');
*
* To create a new TAR archive directly on the filesystem (low memory requirements), create() it,
* add*() files and close() it:
*
* $tar = new Tar();
* $tar->create('myfile.tgz');
* $tar->addFile(...);
* $tar->addData(...);
* ...
* $tar->close();
*
* To create a TAR archive directly in memory, create() it, add*() files and then either save()
* or getData() it:
*
* $tar = new Tar();
* $tar->create();
* $tar->addFile(...);
* $tar->addData(...);
* ...
* $tar->save('myfile.tgz'); // compresses and saves it
* echo $tar->getArchive(Tar::COMPRESS_GZIP); // compresses and returns it
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author Bouchon <tarlib@bouchon.org> (Maxg)
* @license GPL 2
*/
class Tar {
const COMPRESS_AUTO = 0;
const COMPRESS_NONE = 1;
const COMPRESS_GZIP = 2;
const COMPRESS_BZIP = 3;
protected $file = '';
protected $comptype = Tar::COMPRESS_AUTO;
protected $fh;
protected $memory = '';
protected $closed = true;
protected $writeaccess = false;
/**
* Open an existing TAR file for reading
*
* @param string $file
* @param int $comptype
* @throws TarIOException
*/
public function open($file, $comptype = Tar::COMPRESS_AUTO) {
// determine compression
if($comptype == Tar::COMPRESS_AUTO) $comptype = $this->filetype($file);
$this->compressioncheck($comptype);
$this->comptype = $comptype;
$this->file = $file;
if($this->comptype === Tar::COMPRESS_GZIP) {
$this->fh = @gzopen($this->file, 'rb');
} elseif($this->comptype === Tar::COMPRESS_BZIP) {
$this->fh = @bzopen($this->file, 'r');
} else {
$this->fh = @fopen($this->file, 'rb');
}
if(!$this->fh) throw new TarIOException('Could not open file for reading: '.$this->file);
$this->closed = false;
}
/**
* Read the contents of a TAR archive
*
* This function lists the files stored in the archive, and returns an indexed array of associative
* arrays containing for each file the following information:
*
* checksum Tar Checksum of the file
* filename The full name of the stored file (up to 100 c.)
* mode UNIX permissions in DECIMAL, not octal
* uid The Owner ID
* gid The Group ID
* size Uncompressed filesize
* mtime Timestamp of last modification
* typeflag Empty for files, set for folders
* link Is it a symlink?
* uname Owner name
* gname Group name
*
* The archive is closed afer reading the contents, because rewinding is not possible in bzip2 streams.
* Reopen the file with open() again if you want to do additional operations
*/
public function contents() {
if($this->closed || !$this->file) throw new TarIOException('Can not read from a closed archive');
$result = array();
while($read = $this->readbytes(512)) {
$header = $this->parseHeader($read);
if(!is_array($header)) continue;
$this->skipbytes(ceil($header['size'] / 512) * 512, 1);
$result[] = $header;
}
$this->close();
return $result;
}
/**
* Extract an existing TAR archive
*
* The $strip parameter allows you to strip a certain number of path components from the filenames
* found in the tar file, similar to the --strip-components feature of GNU tar. This is triggered when
* an integer is passed as $strip.
* Alternatively a fixed string prefix may be passed in $strip. If the filename matches this prefix,
* the prefix will be stripped. It is recommended to give prefixes with a trailing slash.
*
* By default this will extract all files found in the archive. You can restrict the output using the $include
* and $exclude parameter. Both expect a full regular expression (including delimiters and modifiers). If
* $include is set only files that match this expression will be extracted. Files that match the $exclude
* expression will never be extracted. Both parameters can be used in combination. Expressions are matched against
* stripped filenames as described above.
*
* The archive is closed afer reading the contents, because rewinding is not possible in bzip2 streams.
* Reopen the file with open() again if you want to do additional operations
*
* @param string $outdir the target directory for extracting
* @param int|string $strip either the number of path components or a fixed prefix to strip
* @param string $exclude a regular expression of files to exclude
* @param string $include a regular expression of files to include
* @throws TarIOException
* @return array
*/
function extract($outdir, $strip = '', $exclude = '', $include = '') {
if($this->closed || !$this->file) throw new TarIOException('Can not read from a closed archive');
$outdir = rtrim($outdir, '/');
io_mkdir_p($outdir);
$striplen = strlen($strip);
$extracted = array();
while($dat = $this->readbytes(512)) {
// read the file header
$header = $this->parseHeader($dat);
if(!is_array($header)) continue;
if(!$header['filename']) continue;
// strip prefix
$filename = $this->cleanPath($header['filename']);
if(is_int($strip)) {
// if $strip is an integer we strip this many path components
$parts = explode('/', $filename);
if(!$header['typeflag']) {
$base = array_pop($parts); // keep filename itself
} else {
$base = '';
}
$filename = join('/', array_slice($parts, $strip));
if($base) $filename .= "/$base";
} else {
// ifstrip is a string, we strip a prefix here
if(substr($filename, 0, $striplen) == $strip) $filename = substr($filename, $striplen);
}
// check if this should be extracted
$extract = true;
if(!$filename) {
$extract = false;
} else {
if($include) {
if(preg_match($include, $filename)) {
$extract = true;
} else {
$extract = false;
}
}
if($exclude && preg_match($exclude, $filename)) {
$extract = false;
}
}
// Now do the extraction (or not)
if($extract) {
$extracted[] = $header;
$output = "$outdir/$filename";
$directory = ($header['typeflag']) ? $output : dirname($output);
io_mkdir_p($directory);
// is this a file?
if(!$header['typeflag']) {
$fp = fopen($output, "wb");
if(!$fp) throw new TarIOException('Could not open file for writing: '.$output);
$size = floor($header['size'] / 512);
for($i = 0; $i < $size; $i++) {
fwrite($fp, $this->readbytes(512), 512);
}
if(($header['size'] % 512) != 0) fwrite($fp, $this->readbytes(512), $header['size'] % 512);
fclose($fp);
touch($output, $header['mtime']);
chmod($output, $header['perm']);
} else {
$this->skipbytes(ceil($header['size'] / 512) * 512); // the size is usually 0 for directories
}
} else {
$this->skipbytes(ceil($header['size'] / 512) * 512);
}
}
$this->close();
return $extracted;
}
/**
* Create a new TAR file
*
* If $file is empty, the tar file will be created in memory
*
* @param string $file
* @param int $comptype
* @param int $complevel
* @throws TarIOException
* @throws TarIllegalCompressionException
*/
public function create($file = '', $comptype = Tar::COMPRESS_AUTO, $complevel = 9) {
// determine compression
if($comptype == Tar::COMPRESS_AUTO) $comptype = $this->filetype($file);
$this->compressioncheck($comptype);
$this->comptype = $comptype;
$this->file = $file;
$this->memory = '';
$this->fh = 0;
if($this->file) {
if($this->comptype === Tar::COMPRESS_GZIP) {
$this->fh = @gzopen($this->file, 'wb'.$complevel);
} elseif($this->comptype === Tar::COMPRESS_BZIP) {
$this->fh = @bzopen($this->file, 'w');
} else {
$this->fh = @fopen($this->file, 'wb');
}
if(!$this->fh) throw new TarIOException('Could not open file for writing: '.$this->file);
}
$this->writeaccess = true;
$this->closed = false;
}
/**
* Add a file to the current TAR archive using an existing file in the filesystem
*
* @todo handle directory adding
* @param string $file the original file
* @param string $name the name to use for the file in the archive
* @throws TarIOException
*/
public function addFile($file, $name = '') {
if($this->closed) throw new TarIOException('Archive has been closed, files can no longer be added');
if(!$name) $name = $file;
$name = $this->cleanPath($name);
$fp = fopen($file, 'rb');
if(!$fp) throw new TarIOException('Could not open file for reading: '.$file);
// create file header and copy all stat info from the original file
clearstatcache(false, $file);
$stat = stat($file);
$this->writeFileHeader(
$name,
$stat[4],
$stat[5],
fileperms($file),
filesize($file),
filemtime($file)
);
while(!feof($fp)) {
$data = fread($fp, 512);
if($data === false) break;
if($data === '') break;
$packed = pack("a512", $data);
$this->writebytes($packed);
}
fclose($fp);
}
/**
* Add a file to the current TAR archive using the given $data as content
*
* @param string $name
* @param string $data
* @param int $uid
* @param int $gid
* @param int $perm
* @param int $mtime
* @throws TarIOException
*/
public function addData($name, $data, $uid = 0, $gid = 0, $perm = 0666, $mtime = 0) {
if($this->closed) throw new TarIOException('Archive has been closed, files can no longer be added');
$name = $this->cleanPath($name);
$len = strlen($data);
$this->writeFileHeader(
$name,
$uid,
$gid,
$perm,
$len,
($mtime) ? $mtime : time()
);
for($s = 0; $s < $len; $s += 512) {
$this->writebytes(pack("a512", substr($data, $s, 512)));
}
}
/**
* Add the closing footer to the archive if in write mode, close all file handles
*
* After a call to this function no more data can be added to the archive, for
* read access no reading is allowed anymore
*
* "Physically, an archive consists of a series of file entries terminated by an end-of-archive entry, which
* consists of two 512 blocks of zero bytes"
*
* @link http://www.gnu.org/software/tar/manual/html_chapter/tar_8.html#SEC134
*/
public function close() {
if($this->closed) return; // we did this already
// write footer
if($this->writeaccess) {
$this->writebytes(pack("a512", ""));
$this->writebytes(pack("a512", ""));
}
// close file handles
if($this->file) {
if($this->comptype === Tar::COMPRESS_GZIP) {
gzclose($this->fh);
} elseif($this->comptype === Tar::COMPRESS_BZIP) {
bzclose($this->fh);
} else {
fclose($this->fh);
}
$this->file = '';
$this->fh = 0;
}
$this->closed = true;
}
/**
* Returns the created in-memory archive data
*
* This implicitly calls close() on the Archive
*/
public function getArchive($comptype = Tar::COMPRESS_AUTO, $complevel = 9) {
$this->close();
if($comptype === Tar::COMPRESS_AUTO) $comptype = $this->comptype;
$this->compressioncheck($comptype);
if($comptype === Tar::COMPRESS_GZIP) return gzcompress($this->memory, $complevel);
if($comptype === Tar::COMPRESS_BZIP) return bzcompress($this->memory);
return $this->memory;
}
/**
* Save the created in-memory archive data
*
* Note: It more memory effective to specify the filename in the create() function and
* let the library work on the new file directly.
*
* @param $file
* @param int $comptype
* @param int $complevel
* @throws TarIOException
*/
public function save($file, $comptype = Tar::COMPRESS_AUTO, $complevel = 9) {
if($comptype === Tar::COMPRESS_AUTO) $comptype = $this->filetype($file);
if(!file_put_contents($file, $this->getArchive($comptype, $complevel))) {
throw new TarIOException('Could not write to file: '.$file);
}
}
/**
* Read from the open file pointer
*
* @param int $length bytes to read
* @return string
*/
protected function readbytes($length) {
if($this->comptype === Tar::COMPRESS_GZIP) {
return @gzread($this->fh, $length);
} elseif($this->comptype === Tar::COMPRESS_BZIP) {
return @bzread($this->fh, $length);
} else {
return @fread($this->fh, $length);
}
}
/**
* Write to the open filepointer or memory
*
* @param string $data
* @throws TarIOException
* @return int number of bytes written
*/
protected function writebytes($data) {
if(!$this->file) {
$this->memory .= $data;
$written = strlen($data);
} elseif($this->comptype === Tar::COMPRESS_GZIP) {
$written = @gzwrite($this->fh, $data);
} elseif($this->comptype === Tar::COMPRESS_BZIP) {
$written = @bzwrite($this->fh, $data);
} else {
$written = @fwrite($this->fh, $data);
}
if($written === false) throw new TarIOException('Failed to write to archive stream');
return $written;
}
/**
* Skip forward in the open file pointer
*
* This is basically a wrapper around seek() (and a workaround for bzip2)
*
* @param int $bytes seek to this position
*/
function skipbytes($bytes) {
if($this->comptype === Tar::COMPRESS_GZIP) {
@gzseek($this->fh, $bytes, SEEK_CUR);
} elseif($this->comptype === Tar::COMPRESS_BZIP) {
// there is no seek in bzip2, we simply read on
@bzread($this->fh, $bytes);
} else {
@fseek($this->fh, $bytes, SEEK_CUR);
}
}
/**
* Write a file header
*
* @param string $name
* @param int $uid
* @param int $gid
* @param int $perm
* @param int $size
* @param int $mtime
* @param string $typeflag Set to '5' for directories
*/
protected function writeFileHeader($name, $uid, $gid, $perm, $size, $mtime, $typeflag = '') {
// handle filename length restrictions
$prefix = '';
$namelen = strlen($name);
if($namelen > 100) {
$file = basename($name);
$dir = dirname($name);
if(strlen($file) > 100 || strlen($dir) > 155) {
// we're still too large, let's use GNU longlink
$this->writeFileHeader('././@LongLink', 0, 0, 0, $namelen, 0, 'L');
for($s = 0; $s < $namelen; $s += 512) {
$this->writebytes(pack("a512", substr($name, $s, 512)));
}
$name = substr($name, 0, 100); // cut off name
} else {
// we're fine when splitting, use POSIX ustar
$prefix = $dir;
$name = $file;
}
}
// values are needed in octal
$uid = sprintf("%6s ", decoct($uid));
$gid = sprintf("%6s ", decoct($gid));
$perm = sprintf("%6s ", decoct($perm));
$size = sprintf("%11s ", decoct($size));
$mtime = sprintf("%11s", decoct($mtime));
$data_first = pack("a100a8a8a8a12A12", $name, $perm, $uid, $gid, $size, $mtime);
$data_last = pack("a1a100a6a2a32a32a8a8a155a12", $typeflag, '', 'ustar', '', '', '', '', '', $prefix, "");
for($i = 0, $chks = 0; $i < 148; $i++)
$chks += ord($data_first[$i]);
for($i = 156, $chks += 256, $j = 0; $i < 512; $i++, $j++)
$chks += ord($data_last[$j]);
$this->writebytes($data_first);
$chks = pack("a8", sprintf("%6s ", decoct($chks)));
$this->writebytes($chks.$data_last);
}
/**
* Decode the given tar file header
*
* @param string $block a 512 byte block containign the header data
* @return array|bool
*/
protected function parseHeader($block) {
if(!$block || strlen($block) != 512) return false;
for($i = 0, $chks = 0; $i < 148; $i++)
$chks += ord($block[$i]);
for($i = 156, $chks += 256; $i < 512; $i++)
$chks += ord($block[$i]);
$header = @unpack("a100filename/a8perm/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155prefix", $block);
if(!$header) return false;
$return['checksum'] = OctDec(trim($header['checksum']));
if($return['checksum'] != $chks) return false;
$return['filename'] = trim($header['filename']);
$return['perm'] = OctDec(trim($header['perm']));
$return['uid'] = OctDec(trim($header['uid']));
$return['gid'] = OctDec(trim($header['gid']));
$return['size'] = OctDec(trim($header['size']));
$return['mtime'] = OctDec(trim($header['mtime']));
$return['typeflag'] = $header['typeflag'];
$return['link'] = trim($header['link']);
$return['uname'] = trim($header['uname']);
$return['gname'] = trim($header['gname']);
// Handle ustar Posix compliant path prefixes
if(trim($header['prefix'])) $return['filename'] = trim($header['prefix']).'/'.$return['filename'];
// Handle Long-Link entries from GNU Tar
if($return['typeflag'] == 'L') {
// following data block(s) is the filename
$filename = trim($this->readbytes(ceil($header['size'] / 512) * 512));
// next block is the real header
$block = $this->readbytes(512);
$return = $this->parseHeader($block);
// overwrite the filename
$return['filename'] = $filename;
}
return $return;
}
/**
* Cleans up a path and removes relative parts, also strips leading slashes
*
* @param string $p_dir
* @return string
*/
public function cleanPath($path) {
$path=explode('/', $path);
$newpath=array();
foreach($path as $p) {
if ($p === '' || $p === '.') continue;
if ($p==='..') {
array_pop($newpath);
continue;
}
array_push($newpath, $p);
}
return trim(implode('/', $newpath), '/');
}
/**
* Checks if the given compression type is available and throws an exception if not
*
* @param $comptype
* @throws TarIllegalCompressionException
*/
protected function compressioncheck($comptype) {
if($comptype === Tar::COMPRESS_GZIP && !function_exists('gzopen')) {
throw new TarIllegalCompressionException('No gzip support available');
}
if($comptype === Tar::COMPRESS_BZIP && !function_exists('bzopen')) {
throw new TarIllegalCompressionException('No bzip2 support available');
}
}
/**
* Guesses the wanted compression from the given filename extension
*
* You don't need to call this yourself. It's used when you pass Tar::COMPRESS_AUTO somewhere
*
* @param string $file
* @return int
*/
public function filetype($file) {
$file = strtolower($file);
if(substr($file, -3) == '.gz' || substr($file, -4) == '.tgz') {
$comptype = Tar::COMPRESS_GZIP;
} elseif(substr($file, -4) == '.bz2' || substr($file, -4) == '.tbz') {
$comptype = Tar::COMPRESS_BZIP;
} else {
$comptype = Tar::COMPRESS_NONE;
}
return $comptype;
}
}
class TarIOException extends Exception {
}
class TarIllegalCompressionException extends Exception {
}

View file

@ -0,0 +1,87 @@
<?php
/**
* This is a compatibility wrapper around the new Tar class
*
* Use of this library is strongly discouraged. Only basic extraction is wrapped,
* everything else will fail.
*
* @deprecated 2012-11-06
*/
class TarLib {
const COMPRESS_GZIP = 1;
const COMPRESS_BZIP = 2;
const COMPRESS_AUTO = 3;
const COMPRESS_NONE = 0;
const TARLIB_VERSION = '1.2';
const FULL_ARCHIVE = -1;
const ARCHIVE_DYNAMIC = 0;
const ARCHIVE_RENAMECOMP = 5;
const COMPRESS_DETECT = -1;
private $file = '';
private $tar;
public $_result = true;
function __construct($file, $comptype = TarLib::COMPRESS_AUTO, $complevel = 9) {
if(!$file) $this->error('__construct', '$file');
$this->file = $file;
switch($comptype) {
case TarLib::COMPRESS_AUTO:
case TarLib::COMPRESS_DETECT:
$comptype = Tar::COMPRESS_AUTO;
break;
case TarLib::COMPRESS_GZIP:
$comptype = Tar::COMPRESS_GZIP;
break;
case TarLib::COMPRESS_BZIP:
$comptype = Tar::COMPRESS_BZIP;
break;
default:
$comptype = Tar::COMPRESS_NONE;
}
$this->complevel = $complevel;
try {
$this->tar = new Tar();
$this->tar->open($file, $comptype);
} catch(Exception $e) {
$this->_result = false;
}
}
function Extract($p_what = TarLib::FULL_ARCHIVE, $p_to = '.', $p_remdir = '', $p_mode = 0755) {
if($p_what != TarLib::FULL_ARCHIVE) {
$this->error('Extract', 'Ep_what');
return 0;
}
try {
$this->tar->extract($p_to, $p_remdir);
} catch(Exception $e) {
return 0;
}
return 1;
}
function error($func, $param = '') {
$error = 'TarLib is deprecated and should no longer be used.';
if($param) {
$error .= "In this compatibility wrapper, the function '$func' does not accept your value for".
"the parameter '$param' anymore.";
} else {
$error .= "The function '$func' no longer exists in this compatibility wrapper.";
}
msg($error, -1);
}
function __call($name, $arguments) {
$this->error($name);
}
}

View file

@ -0,0 +1,504 @@
<?php
/**
* @author bouchon
* @link http://dev.maxg.info
* @link http://forum.maxg.info
*
* Modified for Dokuwiki
* @author Christopher Smith <chris@jalakai.co.uk>
*/
class ZipLib {
var $datasec;
var $ctrl_dir = array();
var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
var $old_offset = 0;
var $dirs = Array(".");
function get_List($zip_name) {
$zip = @fopen($zip_name, 'rb');
if(!$zip) return(0);
$centd = $this->ReadCentralDir($zip,$zip_name);
@rewind($zip);
@fseek($zip, $centd['offset']);
for ($i=0; $i<$centd['entries']; $i++) {
$header = $this->ReadCentralFileHeaders($zip);
$header['index'] = $i;
$info['filename'] = $header['filename'];
$info['stored_filename'] = $header['stored_filename'];
$info['size'] = $header['size'];
$info['compressed_size'] = $header['compressed_size'];
$info['crc'] = strtoupper(dechex( $header['crc'] ));
$info['mtime'] = $header['mtime'];
$info['comment'] = $header['comment'];
$info['folder'] = ($header['external']==0x41FF0010||$header['external']==16)?1:0;
$info['index'] = $header['index'];
$info['status'] = $header['status'];
$ret[]=$info;
unset($header);
}
return $ret;
}
function Add($files,$compact) {
if(!is_array($files[0])) $files=Array($files);
for($i=0;$files[$i];$i++){
$fn = $files[$i];
if(!in_Array(dirname($fn[0]),$this->dirs))
$this->add_Dir(dirname($fn[0]));
if(utf8_basename($fn[0]))
$ret[utf8_basename($fn[0])]=$this->add_File($fn[1],$fn[0],$compact);
}
return $ret;
}
/**
* Zips recursively the $folder directory, from the $basedir directory
*/
function Compress($folder, $basedir=null, $parent=null) {
$full_path = $basedir."/".$parent.$folder;
$zip_path = $parent.$folder;
if ($zip_path) {
$zip_path .= "/";
$this->add_dir($zip_path);
}
$dir = new DirectoryIterator($full_path);
foreach($dir as $file) {
if(!$file->isDot()) {
$filename = $file->getFilename();
if($file->isDir()) {
$this->Compress($filename, $basedir, $zip_path);
} else {
$content = join('', file($full_path.'/'.$filename));
$this->add_File($content, $zip_path.$filename);
}
}
}
}
/**
* Returns the Zip file
*/
function get_file() {
$data = implode('', $this -> datasec);
$ctrldir = implode('', $this -> ctrl_dir);
return $data . $ctrldir . $this -> eof_ctrl_dir .
pack('v', count($this->ctrl_dir)).pack('v', count($this->ctrl_dir)).
pack('V', strlen($ctrldir)) . pack('V', strlen($data)) . "\x00\x00";
}
function add_dir($name) {
$name = str_replace("\\", "/", $name);
$fr = "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00";
$fr .= pack("V",0).pack("V",0).pack("V",0).pack("v", strlen($name) );
$fr .= pack("v", 0 ).$name.pack("V", 0).pack("V", 0).pack("V", 0);
$this -> datasec[] = $fr;
$new_offset = strlen(implode("", $this->datasec));
$cdrec = "\x50\x4b\x01\x02\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00";
$cdrec .= pack("V",0).pack("V",0).pack("V",0).pack("v", strlen($name) );
$cdrec .= pack("v", 0 ).pack("v", 0 ).pack("v", 0 ).pack("v", 0 );
$ext = "\xff\xff\xff\xff";
$cdrec .= pack("V", 16 ).pack("V", $this -> old_offset ).$name;
$this -> ctrl_dir[] = $cdrec;
$this -> old_offset = $new_offset;
$this -> dirs[] = $name;
}
/**
* Add a file named $name from a string $data
*/
function add_File($data, $name, $compact = 1) {
$name = str_replace('\\', '/', $name);
$dtime = dechex($this->DosTime());
$hexdtime = pack('H*',$dtime[6].$dtime[7].
$dtime[4].$dtime[5].
$dtime[2].$dtime[3].
$dtime[0].$dtime[1]);
if($compact){
$fr = "\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00".$hexdtime;
}else{
$fr = "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00".$hexdtime;
}
$unc_len = strlen($data);
$crc = crc32($data);
if($compact){
$zdata = gzcompress($data);
$c_len = strlen($zdata);
$zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2);
}else{
$zdata = $data;
}
$c_len=strlen($zdata);
$fr .= pack('V', $crc).pack('V', $c_len).pack('V', $unc_len);
$fr .= pack('v', strlen($name)).pack('v', 0).$name.$zdata;
$fr .= pack('V', $crc).pack('V', $c_len).pack('V', $unc_len);
$this -> datasec[] = $fr;
$new_offset = strlen(implode('', $this->datasec));
if($compact) {
$cdrec = "\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00";
} else {
$cdrec = "\x50\x4b\x01\x02\x14\x00\x0a\x00\x00\x00\x00\x00";
}
$cdrec .= $hexdtime.pack('V', $crc).pack('V', $c_len).pack('V', $unc_len);
$cdrec .= pack('v', strlen($name) ).pack('v', 0 ).pack('v', 0 );
$cdrec .= pack('v', 0 ).pack('v', 0 ).pack('V', 32 );
$cdrec .= pack('V', $this -> old_offset );
$this -> old_offset = $new_offset;
$cdrec .= $name;
$this -> ctrl_dir[] = $cdrec;
return true;
}
function DosTime() {
$timearray = getdate();
if ($timearray['year'] < 1980) {
$timearray['year'] = 1980;
$timearray['mon'] = 1;
$timearray['mday'] = 1;
$timearray['hours'] = 0;
$timearray['minutes'] = 0;
$timearray['seconds'] = 0;
}
return (($timearray['year'] - 1980) << 25) |
($timearray['mon'] << 21) |
($timearray['mday'] << 16) |
($timearray['hours'] << 11) |
($timearray['minutes'] << 5) |
($timearray['seconds'] >> 1);
}
/**
* Extract a zip file $zn to the $to directory
*/
function Extract ( $zn, $to, $index = Array(-1) ) {
if(!@is_dir($to)) $this->_mkdir($to);
$ok = 0;
$zip = @fopen($zn,'rb');
if(!$zip) return(-1);
$cdir = $this->ReadCentralDir($zip,$zn);
$pos_entry = $cdir['offset'];
if(!is_array($index)){
$index = array($index);
}
for($i=0; isset($index[$i]);$i++){
if(intval($index[$i])!=$index[$i]||$index[$i]>$cdir['entries'])
return(-1);
}
for ($i=0; $i<$cdir['entries']; $i++) {
@fseek($zip, $pos_entry);
$header = $this->ReadCentralFileHeaders($zip);
$header['index'] = $i;
$pos_entry = ftell($zip);
@rewind($zip);
fseek($zip, $header['offset']);
if(in_array("-1",$index)||in_array($i,$index)){
$stat[$header['filename']]=$this->ExtractFile($header, $to, $zip);
}
}
fclose($zip);
return $stat;
}
function ReadFileHeader($zip, $header) {
$binary_data = fread($zip, 30);
$data = unpack('vchk/vid/vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $binary_data);
$header['filename'] = fread($zip, $data['filename_len']);
if ($data['extra_len'] != 0) {
$header['extra'] = fread($zip, $data['extra_len']);
} else {
$header['extra'] = '';
}
$header['compression'] = $data['compression'];
foreach (array('size','compressed_size','crc') as $hd) { // On ODT files, these headers are 0. Keep the previous value.
if ($data[$hd] != 0) $header[$hd] = $data[$hd];
}
$header['flag'] = $data['flag'];
$header['mdate'] = $data['mdate'];
$header['mtime'] = $data['mtime'];
if ($header['mdate'] && $header['mtime']){
$hour = ($header['mtime']&0xF800)>>11;
$minute = ($header['mtime']&0x07E0)>>5;
$seconde = ($header['mtime']&0x001F)*2;
$year = (($header['mdate']&0xFE00)>>9)+1980;
$month = ($header['mdate']&0x01E0)>>5;
$day = $header['mdate']&0x001F;
$header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
} else {
$header['mtime'] = time();
}
$header['stored_filename'] = $header['filename'];
$header['status'] = "ok";
return $header;
}
function ReadCentralFileHeaders($zip){
$binary_data = fread($zip, 46);
$header = unpack('vchkid/vid/vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $binary_data);
if ($header['filename_len'] != 0){
$header['filename'] = fread($zip,$header['filename_len']);
}else{
$header['filename'] = '';
}
if ($header['extra_len'] != 0){
$header['extra'] = fread($zip, $header['extra_len']);
}else{
$header['extra'] = '';
}
if ($header['comment_len'] != 0){
$header['comment'] = fread($zip, $header['comment_len']);
}else{
$header['comment'] = '';
}
if ($header['mdate'] && $header['mtime']) {
$hour = ($header['mtime'] & 0xF800) >> 11;
$minute = ($header['mtime'] & 0x07E0) >> 5;
$seconde = ($header['mtime'] & 0x001F)*2;
$year = (($header['mdate'] & 0xFE00) >> 9) + 1980;
$month = ($header['mdate'] & 0x01E0) >> 5;
$day = $header['mdate'] & 0x001F;
$header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
} else {
$header['mtime'] = time();
}
$header['stored_filename'] = $header['filename'];
$header['status'] = 'ok';
if (substr($header['filename'], -1) == '/') $header['external'] = 0x41FF0010;
return $header;
}
function ReadCentralDir($zip,$zip_name) {
$size = filesize($zip_name);
if ($size < 277){
$maximum_size = $size;
} else {
$maximum_size=277;
}
@fseek($zip, $size-$maximum_size);
$pos = ftell($zip);
$bytes = 0x00000000;
while ($pos < $size) {
$byte = @fread($zip, 1);
$bytes=(($bytes << 8) & 0xFFFFFFFF) | Ord($byte);
if ($bytes == 0x504b0506){
$pos++;
break;
}
$pos++;
}
$data=unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size',
fread($zip, 18));
if ($data['comment_size'] != 0){
$centd['comment'] = fread($zip, $data['comment_size']);
} else {
$centd['comment'] = '';
}
$centd['entries'] = $data['entries'];
$centd['disk_entries'] = $data['disk_entries'];
$centd['offset'] = $data['offset'];
$centd['disk_start'] = $data['disk_start'];
$centd['size'] = $data['size'];
$centd['disk'] = $data['disk'];
return $centd;
}
function ExtractFile($header,$to,$zip) {
$header = $this->readfileheader($zip, $header);
if(substr($to,-1)!="/") $to.="/";
if(substr($header['filename'],-1)=="/") {
$this->_mkdir($to.$header['filename']);
return +2;
}
if (!$this->_mkdir($to.dirname($header['filename']))) return (-1);
if (!array_key_exists("external", $header) || (!($header['external']==0x41FF0010)&&!($header['external']==16))) {
if ($header['compression']==0) {
$fp = @fopen($to.$header['filename'], 'wb');
if(!$fp) return(-1);
$size = $header['compressed_size'];
while ($size != 0) {
$read_size = ($size < 2048 ? $size : 2048);
$buffer = fread($zip, $read_size);
$binary_data = pack('a'.$read_size, $buffer);
@fwrite($fp, $binary_data, $read_size);
$size -= $read_size;
}
fclose($fp);
touch($to.$header['filename'], $header['mtime']);
}else{
if (!is_dir(dirname($to.$header['filename']))) $this->_mkdir(dirname($to.$header['filename']));
$fp = fopen($to.$header['filename'].'.gz','wb');
if(!$fp) return(-1);
$binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($header['compression']),
Chr(0x00), time(), Chr(0x00), Chr(3));
fwrite($fp, $binary_data, 10);
$size = $header['compressed_size'];
while ($size != 0) {
$read_size = ($size < 1024 ? $size : 1024);
$buffer = fread($zip, $read_size);
$binary_data = pack('a'.$read_size, $buffer);
@fwrite($fp, $binary_data, $read_size);
$size -= $read_size;
}
$binary_data = pack('VV', $header['crc'], $header['size']);
fwrite($fp, $binary_data,8);
fclose($fp);
$gzp = @gzopen($to.$header['filename'].'.gz','rb');
if(!$gzp){
@gzclose($gzp);
@unlink($to.$header['filename']);
die("Archive is compressed whereas ZLIB is not enabled.");
}
$fp = @fopen($to.$header['filename'],'wb');
if(!$fp) return(-1);
$size = $header['size'];
while ($size != 0) {
$read_size = ($size < 2048 ? $size : 2048);
$buffer = gzread($gzp, $read_size);
$binary_data = pack('a'.$read_size, $buffer);
@fwrite($fp, $binary_data, $read_size);
$size -= $read_size;
}
fclose($fp);
gzclose($gzp);
touch($to.$header['filename'], $header['mtime']);
@unlink($to.$header['filename'].'.gz');
}
}
return true;
}
/**
* centralize mkdir calls and use dokuwiki io functions
*
* @author Christopher Smith <chris@jalakai.co.uk>
*/
function _mkdir($d) {
return io_mkdir_p($d);
}
function ExtractStr($zn, $name) {
$ok = 0;
$zip = @fopen($zn,'rb');
if(!$zip) return(null);
$cdir = $this->ReadCentralDir($zip,$zn);
$pos_entry = $cdir['offset'];
for ($i=0; $i<$cdir['entries']; $i++) {
@fseek($zip, $pos_entry);
$header = $this->ReadCentralFileHeaders($zip);
$header['index'] = $i;
$pos_entry = ftell($zip);
@rewind($zip);
fseek($zip, $header['offset']);
if ($name == $header['stored_filename'] || $name == $header['filename']) {
$str = $this->ExtractStrFile($header, $zip);
fclose($zip);
return $str;
}
}
fclose($zip);
return null;
}
function ExtractStrFile($header,$zip) {
$hdr = $this->readfileheader($zip);
$binary_data = '';
if (!($header['external']==0x41FF0010) && !($header['external']==16)) {
if ($header['compression']==0) {
while ($size != 0) {
$read_size = ($size < 2048 ? $size : 2048);
$buffer = fread($zip, $read_size);
$binary_data .= pack('a'.$read_size, $buffer);
$size -= $read_size;
}
return $binary_data;
} else {
$size = $header['compressed_size'];
if ($size == 0) {
return '';
}
//Just in case
if ($size > ($this->_ret_bytes(ini_get('memory_limit'))/2)) {
die("Compressed file is to huge to be uncompress in memory.");
}
while ($size != 0)
{
$read_size = ($size < 2048 ? $size : 2048);
$buffer = fread($zip, $read_size);
$binary_data .= pack('a'.$read_size, $buffer);
$size -= $read_size;
}
$str = gzinflate($binary_data, $header['size']);
if ($header['crc'] == crc32($str)) {
return $str;
} else {
die("Crc Error");
}
}
}
return null;
}
function _ret_bytes($val) {
$val = trim($val);
$last = $val{strlen($val)-1};
switch($last) {
case 'k':
case 'K':
return (int) $val * 1024;
break;
case 'm':
case 'M':
return (int) $val * 1048576;
break;
default:
return $val;
}
}
}

819
sources/inc/actions.php Normal file
View file

@ -0,0 +1,819 @@
<?php
/**
* DokuWiki Actions
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Andreas Gohr <andi@splitbrain.org>
*/
if(!defined('DOKU_INC')) die('meh.');
/**
* Call the needed action handlers
*
* @author Andreas Gohr <andi@splitbrain.org>
* @triggers ACTION_ACT_PREPROCESS
* @triggers ACTION_HEADERS_SEND
*/
function act_dispatch(){
global $ACT;
global $ID;
global $INFO;
global $QUERY;
global $INPUT;
global $lang;
global $conf;
$preact = $ACT;
// give plugins an opportunity to process the action
$evt = new Doku_Event('ACTION_ACT_PREPROCESS',$ACT);
if ($evt->advise_before()) {
//sanitize $ACT
$ACT = act_validate($ACT);
//check if searchword was given - else just show
$s = cleanID($QUERY);
if($ACT == 'search' && empty($s)){
$ACT = 'show';
}
//login stuff
if(in_array($ACT,array('login','logout'))){
$ACT = act_auth($ACT);
}
//check if user is asking to (un)subscribe a page
if($ACT == 'subscribe') {
try {
$ACT = act_subscription($ACT);
} catch (Exception $e) {
msg($e->getMessage(), -1);
}
}
//display some info
if($ACT == 'check'){
check();
$ACT = 'show';
}
//check permissions
$ACT = act_permcheck($ACT);
//sitemap
if ($ACT == 'sitemap'){
act_sitemap($ACT);
}
//recent changes
if ($ACT == 'recent'){
$show_changes = $INPUT->str('show_changes');
if (!empty($show_changes)) {
set_doku_pref('show_changes', $show_changes);
}
}
//diff
if ($ACT == 'diff'){
$difftype = $INPUT->str('difftype');
if (!empty($difftype)) {
set_doku_pref('difftype', $difftype);
}
}
//register
if($ACT == 'register' && $INPUT->post->bool('save') && register()){
$ACT = 'login';
}
if ($ACT == 'resendpwd' && act_resendpwd()) {
$ACT = 'login';
}
// user profile changes
if (in_array($ACT, array('profile','profile_delete'))) {
if(!$_SERVER['REMOTE_USER']) {
$ACT = 'login';
} else {
switch ($ACT) {
case 'profile' :
if(updateprofile()) {
msg($lang['profchanged'],1);
$ACT = 'show';
}
break;
case 'profile_delete' :
if(auth_deleteprofile()){
msg($lang['profdeleted'],1);
$ACT = 'show';
} else {
$ACT = 'profile';
}
break;
}
}
}
//revert
if($ACT == 'revert'){
if(checkSecurityToken()){
$ACT = act_revert($ACT);
}else{
$ACT = 'show';
}
}
//save
if($ACT == 'save'){
if(checkSecurityToken()){
$ACT = act_save($ACT);
}else{
$ACT = 'preview';
}
}
//cancel conflicting edit
if($ACT == 'cancel')
$ACT = 'show';
//draft deletion
if($ACT == 'draftdel')
$ACT = act_draftdel($ACT);
//draft saving on preview
if($ACT == 'preview')
$ACT = act_draftsave($ACT);
//edit
if(in_array($ACT, array('edit', 'preview', 'recover'))) {
$ACT = act_edit($ACT);
}else{
unlock($ID); //try to unlock
}
//handle export
if(substr($ACT,0,7) == 'export_')
$ACT = act_export($ACT);
//handle admin tasks
if($ACT == 'admin'){
// retrieve admin plugin name from $_REQUEST['page']
if (($page = $INPUT->str('page', '', true)) != '') {
$pluginlist = plugin_list('admin');
if (in_array($page, $pluginlist)) {
// attempt to load the plugin
if (($plugin = plugin_load('admin',$page)) !== null){
/** @var DokuWiki_Admin_Plugin $plugin */
if($plugin->forAdminOnly() && !$INFO['isadmin']){
// a manager tried to load a plugin that's for admins only
$INPUT->remove('page');
msg('For admins only',-1);
}else{
$plugin->handle();
}
}
}
}
}
// check permissions again - the action may have changed
$ACT = act_permcheck($ACT);
} // end event ACTION_ACT_PREPROCESS default action
$evt->advise_after();
// Make sure plugs can handle 'denied'
if($conf['send404'] && $ACT == 'denied') {
http_status(403);
}
unset($evt);
// when action 'show', the intial not 'show' and POST, do a redirect
if($ACT == 'show' && $preact != 'show' && strtolower($_SERVER['REQUEST_METHOD']) == 'post'){
act_redirect($ID,$preact);
}
global $INFO;
global $conf;
global $license;
//call template FIXME: all needed vars available?
$headers[] = 'Content-Type: text/html; charset=utf-8';
trigger_event('ACTION_HEADERS_SEND',$headers,'act_sendheaders');
include(template('main.php'));
// output for the commands is now handled in inc/templates.php
// in function tpl_content()
}
/**
* Send the given headers using header()
*
* @param array $headers The headers that shall be sent
*/
function act_sendheaders($headers) {
foreach ($headers as $hdr) header($hdr);
}
/**
* Sanitize the action command
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function act_clean($act){
// check if the action was given as array key
if(is_array($act)){
list($act) = array_keys($act);
}
//remove all bad chars
$act = strtolower($act);
$act = preg_replace('/[^1-9a-z_]+/','',$act);
if($act == 'export_html') $act = 'export_xhtml';
if($act == 'export_htmlbody') $act = 'export_xhtmlbody';
if($act === '') $act = 'show';
return $act;
}
/**
* Sanitize and validate action commands.
*
* Add all allowed commands here.
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function act_validate($act) {
global $conf;
global $INFO;
$act = act_clean($act);
// check if action is disabled
if(!actionOK($act)){
msg('Command disabled: '.htmlspecialchars($act),-1);
return 'show';
}
//disable all acl related commands if ACL is disabled
if(!$conf['useacl'] && in_array($act,array('login','logout','register','admin',
'subscribe','unsubscribe','profile','revert',
'resendpwd','profile_delete'))){
msg('Command unavailable: '.htmlspecialchars($act),-1);
return 'show';
}
//is there really a draft?
if($act == 'draft' && !file_exists($INFO['draft'])) return 'edit';
if(!in_array($act,array('login','logout','register','save','cancel','edit','draft',
'preview','search','show','check','index','revisions',
'diff','recent','backlink','admin','subscribe','revert',
'unsubscribe','profile','profile_delete','resendpwd','recover',
'draftdel','sitemap','media')) && substr($act,0,7) != 'export_' ) {
msg('Command unknown: '.htmlspecialchars($act),-1);
return 'show';
}
return $act;
}
/**
* Run permissionchecks
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function act_permcheck($act){
global $INFO;
global $conf;
if(in_array($act,array('save','preview','edit','recover'))){
if($INFO['exists']){
if($act == 'edit'){
//the edit function will check again and do a source show
//when no AUTH_EDIT available
$permneed = AUTH_READ;
}else{
$permneed = AUTH_EDIT;
}
}else{
$permneed = AUTH_CREATE;
}
}elseif(in_array($act,array('login','search','recent','profile','profile_delete','index', 'sitemap'))){
$permneed = AUTH_NONE;
}elseif($act == 'revert'){
$permneed = AUTH_ADMIN;
if($INFO['ismanager']) $permneed = AUTH_EDIT;
}elseif($act == 'register'){
$permneed = AUTH_NONE;
}elseif($act == 'resendpwd'){
$permneed = AUTH_NONE;
}elseif($act == 'admin'){
if($INFO['ismanager']){
// if the manager has the needed permissions for a certain admin
// action is checked later
$permneed = AUTH_READ;
}else{
$permneed = AUTH_ADMIN;
}
}else{
$permneed = AUTH_READ;
}
if($INFO['perm'] >= $permneed) return $act;
return 'denied';
}
/**
* Handle 'draftdel'
*
* Deletes the draft for the current page and user
*/
function act_draftdel($act){
global $INFO;
@unlink($INFO['draft']);
$INFO['draft'] = null;
return 'show';
}
/**
* Saves a draft on preview
*
* @todo this currently duplicates code from ajax.php :-/
*/
function act_draftsave($act){
global $INFO;
global $ID;
global $INPUT;
global $conf;
if($conf['usedraft'] && $INPUT->post->has('wikitext')) {
$draft = array('id' => $ID,
'prefix' => substr($INPUT->post->str('prefix'), 0, -1),
'text' => $INPUT->post->str('wikitext'),
'suffix' => $INPUT->post->str('suffix'),
'date' => $INPUT->post->int('date'),
'client' => $INFO['client'],
);
$cname = getCacheName($draft['client'].$ID,'.draft');
if(io_saveFile($cname,serialize($draft))){
$INFO['draft'] = $cname;
}
}
return $act;
}
/**
* Handle 'save'
*
* Checks for spam and conflicts and saves the page.
* Does a redirect to show the page afterwards or
* returns a new action.
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function act_save($act){
global $ID;
global $DATE;
global $PRE;
global $TEXT;
global $SUF;
global $SUM;
global $lang;
global $INFO;
global $INPUT;
//spam check
if(checkwordblock()) {
msg($lang['wordblock'], -1);
return 'edit';
}
//conflict check
if($DATE != 0 && $INFO['meta']['date']['modified'] > $DATE )
return 'conflict';
//save it
saveWikiText($ID,con($PRE,$TEXT,$SUF,1),$SUM,$INPUT->bool('minor')); //use pretty mode for con
//unlock it
unlock($ID);
//delete draft
act_draftdel($act);
session_write_close();
// when done, show page
return 'show';
}
/**
* Revert to a certain revision
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function act_revert($act){
global $ID;
global $REV;
global $lang;
// FIXME $INFO['writable'] currently refers to the attic version
// global $INFO;
// if (!$INFO['writable']) {
// return 'show';
// }
// when no revision is given, delete current one
// FIXME this feature is not exposed in the GUI currently
$text = '';
$sum = $lang['deleted'];
if($REV){
$text = rawWiki($ID,$REV);
if(!$text) return 'show'; //something went wrong
$sum = sprintf($lang['restored'], dformat($REV));
}
// spam check
if (checkwordblock($text)) {
msg($lang['wordblock'], -1);
return 'edit';
}
saveWikiText($ID,$text,$sum,false);
msg($sum,1);
//delete any draft
act_draftdel($act);
session_write_close();
// when done, show current page
$_SERVER['REQUEST_METHOD'] = 'post'; //should force a redirect
$REV = '';
return 'show';
}
/**
* Do a redirect after receiving post data
*
* Tries to add the section id as hash mark after section editing
*/
function act_redirect($id,$preact){
global $PRE;
global $TEXT;
$opts = array(
'id' => $id,
'preact' => $preact
);
//get section name when coming from section edit
if($PRE && preg_match('/^\s*==+([^=\n]+)/',$TEXT,$match)){
$check = false; //Byref
$opts['fragment'] = sectionID($match[0], $check);
}
trigger_event('ACTION_SHOW_REDIRECT',$opts,'act_redirect_execute');
}
/**
* Execute the redirect
*
* @param array $opts id and fragment for the redirect
*/
function act_redirect_execute($opts){
$go = wl($opts['id'],'',true);
if(isset($opts['fragment'])) $go .= '#'.$opts['fragment'];
//show it
send_redirect($go);
}
/**
* Handle 'login', 'logout'
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function act_auth($act){
global $ID;
global $INFO;
//already logged in?
if(isset($_SERVER['REMOTE_USER']) && $act=='login'){
return 'show';
}
//handle logout
if($act=='logout'){
$lockedby = checklock($ID); //page still locked?
if($lockedby == $_SERVER['REMOTE_USER'])
unlock($ID); //try to unlock
// do the logout stuff
auth_logoff();
// rebuild info array
$INFO = pageinfo();
act_redirect($ID,'login');
}
return $act;
}
/**
* Handle 'edit', 'preview', 'recover'
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function act_edit($act){
global $ID;
global $INFO;
global $TEXT;
global $RANGE;
global $PRE;
global $SUF;
global $REV;
global $SUM;
global $lang;
global $DATE;
if (!isset($TEXT)) {
if ($INFO['exists']) {
if ($RANGE) {
list($PRE,$TEXT,$SUF) = rawWikiSlices($RANGE,$ID,$REV);
} else {
$TEXT = rawWiki($ID,$REV);
}
} else {
$TEXT = pageTemplate($ID);
}
}
//set summary default
if(!$SUM){
if($REV){
$SUM = sprintf($lang['restored'], dformat($REV));
}elseif(!$INFO['exists']){
$SUM = $lang['created'];
}
}
// Use the date of the newest revision, not of the revision we edit
// This is used for conflict detection
if(!$DATE) $DATE = @filemtime(wikiFN($ID));
//check if locked by anyone - if not lock for my self
//do not lock when the user can't edit anyway
if ($INFO['writable']) {
$lockedby = checklock($ID);
if($lockedby) return 'locked';
lock($ID);
}
return $act;
}
/**
* Export a wiki page for various formats
*
* Triggers ACTION_EXPORT_POSTPROCESS
*
* Event data:
* data['id'] -- page id
* data['mode'] -- requested export mode
* data['headers'] -- export headers
* data['output'] -- export output
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author Michael Klier <chi@chimeric.de>
*/
function act_export($act){
global $ID;
global $REV;
global $conf;
global $lang;
$pre = '';
$post = '';
$output = '';
$headers = array();
// search engines: never cache exported docs! (Google only currently)
$headers['X-Robots-Tag'] = 'noindex';
$mode = substr($act,7);
switch($mode) {
case 'raw':
$headers['Content-Type'] = 'text/plain; charset=utf-8';
$headers['Content-Disposition'] = 'attachment; filename='.noNS($ID).'.txt';
$output = rawWiki($ID,$REV);
break;
case 'xhtml':
$pre .= '<!DOCTYPE html>' . DOKU_LF;
$pre .= '<html lang="'.$conf['lang'].'" dir="'.$lang['direction'].'">' . DOKU_LF;
$pre .= '<head>' . DOKU_LF;
$pre .= ' <meta charset="utf-8" />' . DOKU_LF;
$pre .= ' <title>'.$ID.'</title>' . DOKU_LF;
// get metaheaders
ob_start();
tpl_metaheaders();
$pre .= ob_get_clean();
$pre .= '</head>' . DOKU_LF;
$pre .= '<body>' . DOKU_LF;
$pre .= '<div class="dokuwiki export">' . DOKU_LF;
// get toc
$pre .= tpl_toc(true);
$headers['Content-Type'] = 'text/html; charset=utf-8';
$output = p_wiki_xhtml($ID,$REV,false);
$post .= '</div>' . DOKU_LF;
$post .= '</body>' . DOKU_LF;
$post .= '</html>' . DOKU_LF;
break;
case 'xhtmlbody':
$headers['Content-Type'] = 'text/html; charset=utf-8';
$output = p_wiki_xhtml($ID,$REV,false);
break;
default:
$output = p_cached_output(wikiFN($ID,$REV), $mode);
$headers = p_get_metadata($ID,"format $mode");
break;
}
// prepare event data
$data = array();
$data['id'] = $ID;
$data['mode'] = $mode;
$data['headers'] = $headers;
$data['output'] =& $output;
trigger_event('ACTION_EXPORT_POSTPROCESS', $data);
if(!empty($data['output'])){
if(is_array($data['headers'])) foreach($data['headers'] as $key => $val){
header("$key: $val");
}
print $pre.$data['output'].$post;
exit;
}
return 'show';
}
/**
* Handle sitemap delivery
*
* @author Michael Hamann <michael@content-space.de>
*/
function act_sitemap($act) {
global $conf;
if ($conf['sitemap'] < 1 || !is_numeric($conf['sitemap'])) {
http_status(404);
print "Sitemap generation is disabled.";
exit;
}
$sitemap = Sitemapper::getFilePath();
if (Sitemapper::sitemapIsCompressed()) {
$mime = 'application/x-gzip';
}else{
$mime = 'application/xml; charset=utf-8';
}
// Check if sitemap file exists, otherwise create it
if (!is_readable($sitemap)) {
Sitemapper::generate();
}
if (is_readable($sitemap)) {
// Send headers
header('Content-Type: '.$mime);
header('Content-Disposition: attachment; filename='.utf8_basename($sitemap));
http_conditionalRequest(filemtime($sitemap));
// Send file
//use x-sendfile header to pass the delivery to compatible webservers
if (http_sendfile($sitemap)) exit;
readfile($sitemap);
exit;
}
http_status(500);
print "Could not read the sitemap file - bad permissions?";
exit;
}
/**
* Handle page 'subscribe'
*
* Throws exception on error.
*
* @author Adrian Lang <lang@cosmocode.de>
*/
function act_subscription($act){
global $lang;
global $INFO;
global $ID;
global $INPUT;
// subcriptions work for logged in users only
if(!$_SERVER['REMOTE_USER']) return 'show';
// get and preprocess data.
$params = array();
foreach(array('target', 'style', 'action') as $param) {
if ($INPUT->has("sub_$param")) {
$params[$param] = $INPUT->str("sub_$param");
}
}
// any action given? if not just return and show the subscription page
if(!$params['action'] || !checkSecurityToken()) return $act;
// Handle POST data, may throw exception.
trigger_event('ACTION_HANDLE_SUBSCRIBE', $params, 'subscription_handle_post');
$target = $params['target'];
$style = $params['style'];
$action = $params['action'];
// Perform action.
$sub = new Subscription();
if($action == 'unsubscribe'){
$ok = $sub->remove($target, $_SERVER['REMOTE_USER'], $style);
}else{
$ok = $sub->add($target, $_SERVER['REMOTE_USER'], $style);
}
if($ok) {
msg(sprintf($lang["subscr_{$action}_success"], hsc($INFO['userinfo']['name']),
prettyprint_id($target)), 1);
act_redirect($ID, $act);
} else {
throw new Exception(sprintf($lang["subscr_{$action}_error"],
hsc($INFO['userinfo']['name']),
prettyprint_id($target)));
}
// Assure that we have valid data if act_redirect somehow fails.
$INFO['subscribed'] = $sub->user_subscription();
return 'show';
}
/**
* Validate POST data
*
* Validates POST data for a subscribe or unsubscribe request. This is the
* default action for the event ACTION_HANDLE_SUBSCRIBE.
*
* @author Adrian Lang <lang@cosmocode.de>
*/
function subscription_handle_post(&$params) {
global $INFO;
global $lang;
// Get and validate parameters.
if (!isset($params['target'])) {
throw new Exception('no subscription target given');
}
$target = $params['target'];
$valid_styles = array('every', 'digest');
if (substr($target, -1, 1) === ':') {
// Allow “list” subscribe style since the target is a namespace.
$valid_styles[] = 'list';
}
$style = valid_input_set('style', $valid_styles, $params,
'invalid subscription style given');
$action = valid_input_set('action', array('subscribe', 'unsubscribe'),
$params, 'invalid subscription action given');
// Check other conditions.
if ($action === 'subscribe') {
if ($INFO['userinfo']['mail'] === '') {
throw new Exception($lang['subscr_subscribe_noaddress']);
}
} elseif ($action === 'unsubscribe') {
$is = false;
foreach($INFO['subscribed'] as $subscr) {
if ($subscr['target'] === $target) {
$is = true;
}
}
if ($is === false) {
throw new Exception(sprintf($lang['subscr_not_subscribed'],
$_SERVER['REMOTE_USER'],
prettyprint_id($target)));
}
// subscription_set deletes a subscription if style = null.
$style = null;
}
$params = compact('target', 'style', 'action');
}
//Setup VIM: ex: et ts=2 :

1320
sources/inc/auth.php Normal file

File diff suppressed because it is too large Load diff

514
sources/inc/blowfish.php Normal file
View file

@ -0,0 +1,514 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* The Cipher_blowfish:: class implements the Cipher interface enryption data
* using the Blowfish algorithm.
*
* $Horde: horde/lib/Cipher/blowfish.php,v 1.2.2.3 2003/01/03 13:23:22 jan Exp $
*
* Copyright 2002-2003 Mike Cochrane <mike@graftonhall.co.nz>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Mike Cochrane <mike@graftonhall.co.nz>
* @version $Id: blowfish.php 11081 2008-01-25 09:35:48Z cybot_tm $
* @since Horde 2.2
* @package horde.cipher
*/
// Change for phpMyAdmin by lem9:
//class Horde_Cipher_blowfish extends Horde_Cipher {
class Horde_Cipher_blowfish
{
/* Pi Array */
var $p = array(
0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
0x9216D5D9, 0x8979FB1B);
/* S Boxes */
var $s1 = array(
0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E,
0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE,
0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF,
0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E,
0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440,
0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE,
0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E,
0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677,
0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032,
0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88,
0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E,
0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0,
0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98,
0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88,
0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6,
0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D,
0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7,
0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA,
0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F,
0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09,
0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB,
0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279,
0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB,
0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82,
0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573,
0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0,
0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790,
0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8,
0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0,
0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7,
0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD,
0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1,
0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9,
0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477,
0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49,
0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF,
0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5,
0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41,
0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,
0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915,
0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A);
var $s2 = array(
0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E,
0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6,
0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E,
0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8,
0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF,
0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701,
0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7,
0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41,
0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331,
0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF,
0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E,
0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C,
0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2,
0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16,
0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B,
0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509,
0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3,
0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F,
0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A,
0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4,
0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66,
0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28,
0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802,
0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510,
0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF,
0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14,
0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E,
0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50,
0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7,
0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8,
0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696,
0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128,
0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0,
0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0,
0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105,
0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250,
0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3,
0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00,
0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB,
0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E,
0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735,
0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9,
0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7);
var $s3 = array(
0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45,
0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504,
0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A,
0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB,
0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6,
0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42,
0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2,
0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB,
0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527,
0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33,
0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3,
0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC,
0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17,
0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564,
0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B,
0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922,
0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728,
0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37,
0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D,
0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804,
0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B,
0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3,
0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB,
0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D,
0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350,
0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9,
0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A,
0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D,
0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC,
0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F,
0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61,
0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9,
0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2,
0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E,
0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633,
0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10,
0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52,
0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5,
0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62,
0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634,
0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76,
0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24,
0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4,
0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C,
0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0);
var $s4 = array(
0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4,
0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8,
0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304,
0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22,
0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6,
0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9,
0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593,
0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51,
0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C,
0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B,
0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C,
0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD,
0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319,
0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB,
0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991,
0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32,
0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166,
0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE,
0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5,
0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47,
0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D,
0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84,
0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8,
0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD,
0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7,
0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38,
0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C,
0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525,
0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442,
0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964,
0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8,
0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D,
0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299,
0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02,
0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614,
0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A,
0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B,
0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0,
0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E,
0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9,
0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6);
/* The number of rounds to do */
var $_rounds = 16;
/**
* Set the key to be used for en/decryption
*
* @param String $key The key to use
*/
function setKey($key) {
$key = $this->_formatKey($key);
$keyPos = $keyXor = 0;
$iMax = count($this->p);
$keyLen = count($key);
for ($i = 0; $i < $iMax; $i++) {
for ($t = 0; $t < 4; $t++) {
$keyXor = ($keyXor << 8) | (($key[$keyPos]) & 0x0ff);
if (++$keyPos == $keyLen) {
$keyPos = 0;
}
}
$this->p[$i] = $this->p[$i] ^ $keyXor;
}
$encZero = array('L' => 0, 'R' => 0);
for ($i = 0; $i + 1 < $iMax; $i += 2) {
$encZero = $this->_encryptBlock($encZero['L'], $encZero['R']);
$this->p[$i] = $encZero['L'];
$this->p[$i + 1] = $encZero['R'];
}
$iMax = count($this->s1);
for ($i = 0; $i < $iMax; $i += 2) {
$encZero = $this->_encryptBlock($encZero['L'], $encZero['R']);
$this->s1[$i] = $encZero['L'];
$this->s1[$i + 1] = $encZero['R'];
}
$iMax = count($this->s2);
for ($i = 0; $i < $iMax; $i += 2) {
$encZero = $this->_encryptBlock($encZero['L'], $encZero['R']);
$this->s2[$i] = $encZero['L'];
$this->s2[$i + 1] = $encZero['R'];
}
$iMax = count($this->s3);
for ($i = 0; $i < $iMax; $i += 2) {
$encZero = $this->_encryptBlock($encZero['L'], $encZero['R']);
$this->s3[$i] = $encZero['L'];
$this->s3[$i + 1] = $encZero['R'];
}
$iMax = count($this->s4);
for ($i = 0; $i < $iMax; $i += 2) {
$encZero = $this->_encryptBlock($encZero['L'], $encZero['R']);
$this->s4[$i] = $encZero['L'];
$this->s4[$i + 1] = $encZero['R'];
}
}
/**
* Encrypt a block on data.
*
* @param String $block The data to encrypt
* @param optional String $key The key to use
*
* @return String the encrypted output
*/
function encryptBlock($block, $key = null) {
if (!is_null($key)) {
$this->setKey($key);
}
list($L, $R) = array_values(unpack('N*', $block));
$parts = $this->_encryptBlock($L, $R);
return pack("NN", $parts['L'], $parts['R']);
}
/**
* Encrypt a block on data.
*
* @param String $L The data to encrypt.
* @param String $R The data to encrypt.
*
* @return String The encrypted output.
*/
function _encryptBlock($L, $R) {
$L ^= $this->p[0];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[1];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[2];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[3];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[4];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[5];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[6];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[7];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[8];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[9];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[10];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[11];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[12];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[13];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[14];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[15];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[16];
$R ^= $this->p[17];
return array('L' => $R, 'R' => $L);
}
/**
* Decrypt a block on data.
*
* @param String $block The data to decrypt
* @param optional String $key The key to use
*
* @return String the decrypted output
*/
function decryptBlock($block, $key = null) {
if (!is_null($key)) {
$this->setKey($key);
}
// change for phpMyAdmin
$L = null;
$R = null;
$retarray = array_values(unpack('N*', $block));
if (isset($retarray[0])) {
$L = $retarray[0];
}
if (isset($retarray[1])) {
$R = $retarray[1];
}
// end change for phpMyAdmin
$L ^= $this->p[17];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[16];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[15];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[14];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[13];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[12];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[11];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[10];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[9];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[8];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[7];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[6];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[5];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[4];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[3];
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[2];
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[1];
$decrypted = pack("NN", $R ^ $this->p[0], $L);
return $decrypted;
}
/**
* Converts a text key into an array.
*
* @return array The key.
*/
function _formatKey($key) {
return array_values(unpack('C*', $key));
}
}
// higher-level functions:
/**
* Encryption using blowfish algorithm
*
* @param string original data
* @param string the secret
*
* @return string the encrypted result
*
* @access public
*
* @author lem9
*/
function PMA_blowfish_encrypt($data, $secret) {
$pma_cipher = new Horde_Cipher_blowfish;
$encrypt = '';
$data .= '_'; // triming fixed for DokuWiki FS#1690 FS#1713
$mod = strlen($data) % 8;
if ($mod > 0) {
$data .= str_repeat("\0", 8 - $mod);
}
foreach (str_split($data, 8) as $chunk) {
$encrypt .= $pma_cipher->encryptBlock($chunk, $secret);
}
return base64_encode($encrypt);
}
/**
* Decryption using blowfish algorithm
*
* @param string encrypted data
* @param string the secret
*
* @return string original data
*
* @access public
*
* @author lem9
*/
function PMA_blowfish_decrypt($encdata, $secret) {
$pma_cipher = new Horde_Cipher_blowfish;
$decrypt = '';
$data = base64_decode($encdata);
foreach (str_split($data, 8) as $chunk) {
$decrypt .= $pma_cipher->decryptBlock($chunk, $secret);
}
return substr(rtrim($decrypt, "\0"), 0, -1); // triming fixed for DokuWiki FS#1690 FS#1713
}

270
sources/inc/cache.php Normal file
View file

@ -0,0 +1,270 @@
<?php
/**
* Generic class to handle caching
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Chris Smith <chris@jalakai.co.uk>
*/
if(!defined('DOKU_INC')) die('meh.');
class cache {
var $key = ''; // primary identifier for this item
var $ext = ''; // file ext for cache data, secondary identifier for this item
var $cache = ''; // cache file name
var $depends = array(); // array containing cache dependency information,
// used by _useCache to determine cache validity
var $_event = ''; // event to be triggered during useCache
function cache($key,$ext) {
$this->key = $key;
$this->ext = $ext;
$this->cache = getCacheName($key,$ext);
}
/**
* public method to determine whether the cache can be used
*
* to assist in cetralisation of event triggering and calculation of cache statistics,
* don't override this function override _useCache()
*
* @param array $depends array of cache dependencies, support dependecies:
* 'age' => max age of the cache in seconds
* 'files' => cache must be younger than mtime of each file
* (nb. dependency passes if file doesn't exist)
*
* @return bool true if cache can be used, false otherwise
*/
function useCache($depends=array()) {
$this->depends = $depends;
$this->_addDependencies();
if ($this->_event) {
return $this->_stats(trigger_event($this->_event,$this,array($this,'_useCache')));
} else {
return $this->_stats($this->_useCache());
}
}
/**
* private method containing cache use decision logic
*
* this function processes the following keys in the depends array
* purge - force a purge on any non empty value
* age - expire cache if older than age (seconds)
* files - expire cache if any file in this array was updated more recently than the cache
*
* can be overridden
*
* @return bool see useCache()
*/
function _useCache() {
if (!empty($this->depends['purge'])) return false; // purge requested?
if (!($this->_time = @filemtime($this->cache))) return false; // cache exists?
// cache too old?
if (!empty($this->depends['age']) && ((time() - $this->_time) > $this->depends['age'])) return false;
if (!empty($this->depends['files'])) {
foreach ($this->depends['files'] as $file) {
if ($this->_time <= @filemtime($file)) return false; // cache older than files it depends on?
}
}
return true;
}
/**
* add dependencies to the depends array
*
* this method should only add dependencies,
* it should not remove any existing dependencies and
* it should only overwrite a dependency when the new value is more stringent than the old
*/
function _addDependencies() {
global $INPUT;
if ($INPUT->has('purge')) $this->depends['purge'] = true; // purge requested
}
/**
* retrieve the cached data
*
* @param bool $clean true to clean line endings, false to leave line endings alone
* @return string cache contents
*/
function retrieveCache($clean=true) {
return io_readFile($this->cache, $clean);
}
/**
* cache $data
*
* @param string $data the data to be cached
* @return bool true on success, false otherwise
*/
function storeCache($data) {
return io_savefile($this->cache, $data);
}
/**
* remove any cached data associated with this cache instance
*/
function removeCache() {
@unlink($this->cache);
}
/**
* Record cache hits statistics.
* (Only when debugging allowed, to reduce overhead.)
*
* @param bool $success result of this cache use attempt
* @return bool pass-thru $success value
*/
function _stats($success) {
global $conf;
static $stats = null;
static $file;
if (!$conf['allowdebug']) { return $success; }
if (is_null($stats)) {
$file = $conf['cachedir'].'/cache_stats.txt';
$lines = explode("\n",io_readFile($file));
foreach ($lines as $line) {
$i = strpos($line,',');
$stats[substr($line,0,$i)] = $line;
}
}
if (isset($stats[$this->ext])) {
list($ext,$count,$hits) = explode(',',$stats[$this->ext]);
} else {
$ext = $this->ext;
$count = 0;
$hits = 0;
}
$count++;
if ($success) $hits++;
$stats[$this->ext] = "$ext,$count,$hits";
io_saveFile($file,join("\n",$stats));
return $success;
}
}
class cache_parser extends cache {
var $file = ''; // source file for cache
var $mode = ''; // input mode (represents the processing the input file will undergo)
var $_event = 'PARSER_CACHE_USE';
function cache_parser($id, $file, $mode) {
if ($id) $this->page = $id;
$this->file = $file;
$this->mode = $mode;
parent::cache($file.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'],'.'.$mode);
}
function _useCache() {
if (!@file_exists($this->file)) return false; // source exists?
return parent::_useCache();
}
function _addDependencies() {
global $conf, $config_cascade;
$this->depends['age'] = isset($this->depends['age']) ?
min($this->depends['age'],$conf['cachetime']) : $conf['cachetime'];
// parser cache file dependencies ...
$files = array($this->file, // ... source
DOKU_INC.'inc/parser/parser.php', // ... parser
DOKU_INC.'inc/parser/handler.php', // ... handler
);
$files = array_merge($files, getConfigFiles('main')); // ... wiki settings
$this->depends['files'] = !empty($this->depends['files']) ? array_merge($files, $this->depends['files']) : $files;
parent::_addDependencies();
}
}
class cache_renderer extends cache_parser {
function _useCache() {
global $conf;
if (!parent::_useCache()) return false;
if (!isset($this->page)) {
return true;
}
if ($this->_time < @filemtime(metaFN($this->page,'.meta'))) return false; // meta cache older than file it depends on?
// check current link existence is consistent with cache version
// first check the purgefile
// - if the cache is more recent than the purgefile we know no links can have been updated
if ($this->_time >= @filemtime($conf['cachedir'].'/purgefile')) {
return true;
}
// for wiki pages, check metadata dependencies
$metadata = p_get_metadata($this->page);
if (!isset($metadata['relation']['references']) ||
empty($metadata['relation']['references'])) {
return true;
}
foreach ($metadata['relation']['references'] as $id => $exists) {
if ($exists != page_exists($id,'',false)) return false;
}
return true;
}
function _addDependencies() {
// renderer cache file dependencies ...
$files = array(
DOKU_INC.'inc/parser/'.$this->mode.'.php', // ... the renderer
);
// page implies metadata and possibly some other dependencies
if (isset($this->page)) {
$valid = p_get_metadata($this->page, 'date valid'); // for xhtml this will render the metadata if needed
if (!empty($valid['age'])) {
$this->depends['age'] = isset($this->depends['age']) ?
min($this->depends['age'],$valid['age']) : $valid['age'];
}
}
$this->depends['files'] = !empty($this->depends['files']) ? array_merge($files, $this->depends['files']) : $files;
parent::_addDependencies();
}
}
class cache_instructions extends cache_parser {
function cache_instructions($id, $file) {
parent::cache_parser($id, $file, 'i');
}
function retrieveCache($clean=true) {
$contents = io_readFile($this->cache, false);
return !empty($contents) ? unserialize($contents) : array();
}
function storeCache($instructions) {
return io_savefile($this->cache,serialize($instructions));
}
}

548
sources/inc/changelog.php Normal file
View file

@ -0,0 +1,548 @@
<?php
/**
* Changelog handling functions
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Andreas Gohr <andi@splitbrain.org>
*/
// Constants for known core changelog line types.
// Use these in place of string literals for more readable code.
define('DOKU_CHANGE_TYPE_CREATE', 'C');
define('DOKU_CHANGE_TYPE_EDIT', 'E');
define('DOKU_CHANGE_TYPE_MINOR_EDIT', 'e');
define('DOKU_CHANGE_TYPE_DELETE', 'D');
define('DOKU_CHANGE_TYPE_REVERT', 'R');
/**
* parses a changelog line into it's components
*
* @author Ben Coburn <btcoburn@silicodon.net>
*/
function parseChangelogLine($line) {
$tmp = explode("\t", $line);
if ($tmp!==false && count($tmp)>1) {
$info = array();
$info['date'] = (int)$tmp[0]; // unix timestamp
$info['ip'] = $tmp[1]; // IPv4 address (127.0.0.1)
$info['type'] = $tmp[2]; // log line type
$info['id'] = $tmp[3]; // page id
$info['user'] = $tmp[4]; // user name
$info['sum'] = $tmp[5]; // edit summary (or action reason)
$info['extra'] = rtrim($tmp[6], "\n"); // extra data (varies by line type)
return $info;
} else { return false; }
}
/**
* Add's an entry to the changelog and saves the metadata for the page
*
* @param int $date Timestamp of the change
* @param String $id Name of the affected page
* @param String $type Type of the change see DOKU_CHANGE_TYPE_*
* @param String $summary Summary of the change
* @param mixed $extra In case of a revert the revision (timestmp) of the reverted page
* @param array $flags Additional flags in a key value array.
* Availible flags:
* - ExternalEdit - mark as an external edit.
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author Esther Brunner <wikidesign@gmail.com>
* @author Ben Coburn <btcoburn@silicodon.net>
*/
function addLogEntry($date, $id, $type=DOKU_CHANGE_TYPE_EDIT, $summary='', $extra='', $flags=null){
global $conf, $INFO;
// check for special flags as keys
if (!is_array($flags)) { $flags = array(); }
$flagExternalEdit = isset($flags['ExternalEdit']);
$id = cleanid($id);
$file = wikiFN($id);
$created = @filectime($file);
$minor = ($type===DOKU_CHANGE_TYPE_MINOR_EDIT);
$wasRemoved = ($type===DOKU_CHANGE_TYPE_DELETE);
if(!$date) $date = time(); //use current time if none supplied
$remote = (!$flagExternalEdit)?clientIP(true):'127.0.0.1';
$user = (!$flagExternalEdit)?$_SERVER['REMOTE_USER']:'';
$strip = array("\t", "\n");
$logline = array(
'date' => $date,
'ip' => $remote,
'type' => str_replace($strip, '', $type),
'id' => $id,
'user' => $user,
'sum' => utf8_substr(str_replace($strip, '', $summary),0,255),
'extra' => str_replace($strip, '', $extra)
);
// update metadata
if (!$wasRemoved) {
$oldmeta = p_read_metadata($id);
$meta = array();
if (!$INFO['exists'] && empty($oldmeta['persistent']['date']['created'])){ // newly created
$meta['date']['created'] = $created;
if ($user){
$meta['creator'] = $INFO['userinfo']['name'];
$meta['user'] = $user;
}
} elseif (!$INFO['exists'] && !empty($oldmeta['persistent']['date']['created'])) { // re-created / restored
$meta['date']['created'] = $oldmeta['persistent']['date']['created'];
$meta['date']['modified'] = $created; // use the files ctime here
$meta['creator'] = $oldmeta['persistent']['creator'];
if ($user) $meta['contributor'][$user] = $INFO['userinfo']['name'];
} elseif (!$minor) { // non-minor modification
$meta['date']['modified'] = $date;
if ($user) $meta['contributor'][$user] = $INFO['userinfo']['name'];
}
$meta['last_change'] = $logline;
p_set_metadata($id, $meta);
}
// add changelog lines
$logline = implode("\t", $logline)."\n";
io_saveFile(metaFN($id,'.changes'),$logline,true); //page changelog
io_saveFile($conf['changelog'],$logline,true); //global changelog cache
}
/**
* Add's an entry to the media changelog
*
* @author Michael Hamann <michael@content-space.de>
* @author Andreas Gohr <andi@splitbrain.org>
* @author Esther Brunner <wikidesign@gmail.com>
* @author Ben Coburn <btcoburn@silicodon.net>
*/
function addMediaLogEntry($date, $id, $type=DOKU_CHANGE_TYPE_EDIT, $summary='', $extra='', $flags=null){
global $conf;
$id = cleanid($id);
if(!$date) $date = time(); //use current time if none supplied
$remote = clientIP(true);
$user = $_SERVER['REMOTE_USER'];
$strip = array("\t", "\n");
$logline = array(
'date' => $date,
'ip' => $remote,
'type' => str_replace($strip, '', $type),
'id' => $id,
'user' => $user,
'sum' => utf8_substr(str_replace($strip, '', $summary),0,255),
'extra' => str_replace($strip, '', $extra)
);
// add changelog lines
$logline = implode("\t", $logline)."\n";
io_saveFile($conf['media_changelog'],$logline,true); //global media changelog cache
io_saveFile(mediaMetaFN($id,'.changes'),$logline,true); //media file's changelog
}
/**
* returns an array of recently changed files using the
* changelog
*
* The following constants can be used to control which changes are
* included. Add them together as needed.
*
* RECENTS_SKIP_DELETED - don't include deleted pages
* RECENTS_SKIP_MINORS - don't include minor changes
* RECENTS_SKIP_SUBSPACES - don't include subspaces
* RECENTS_MEDIA_CHANGES - return media changes instead of page changes
* RECENTS_MEDIA_PAGES_MIXED - return both media changes and page changes
*
* @param int $first number of first entry returned (for paginating
* @param int $num return $num entries
* @param string $ns restrict to given namespace
* @param int $flags see above
* @return array recently changed files
*
* @author Ben Coburn <btcoburn@silicodon.net>
* @author Kate Arzamastseva <pshns@ukr.net>
*/
function getRecents($first,$num,$ns='',$flags=0){
global $conf;
$recent = array();
$count = 0;
if(!$num)
return $recent;
// read all recent changes. (kept short)
if ($flags & RECENTS_MEDIA_CHANGES) {
$lines = @file($conf['media_changelog']);
} else {
$lines = @file($conf['changelog']);
}
$lines_position = count($lines)-1;
$media_lines_position = 0;
$media_lines = array();
if ($flags & RECENTS_MEDIA_PAGES_MIXED) {
$media_lines = @file($conf['media_changelog']);
$media_lines_position = count($media_lines)-1;
}
$seen = array(); // caches seen lines, _handleRecent() skips them
// handle lines
while ($lines_position >= 0 || (($flags & RECENTS_MEDIA_PAGES_MIXED) && $media_lines_position >=0)) {
if (empty($rec) && $lines_position >= 0) {
$rec = _handleRecent(@$lines[$lines_position], $ns, $flags, $seen);
if (!$rec) {
$lines_position --;
continue;
}
}
if (($flags & RECENTS_MEDIA_PAGES_MIXED) && empty($media_rec) && $media_lines_position >= 0) {
$media_rec = _handleRecent(@$media_lines[$media_lines_position], $ns, $flags | RECENTS_MEDIA_CHANGES, $seen);
if (!$media_rec) {
$media_lines_position --;
continue;
}
}
if (($flags & RECENTS_MEDIA_PAGES_MIXED) && @$media_rec['date'] >= @$rec['date']) {
$media_lines_position--;
$x = $media_rec;
$x['media'] = true;
$media_rec = false;
} else {
$lines_position--;
$x = $rec;
if ($flags & RECENTS_MEDIA_CHANGES) $x['media'] = true;
$rec = false;
}
if(--$first >= 0) continue; // skip first entries
$recent[] = $x;
$count++;
// break when we have enough entries
if($count >= $num){ break; }
}
return $recent;
}
/**
* returns an array of files changed since a given time using the
* changelog
*
* The following constants can be used to control which changes are
* included. Add them together as needed.
*
* RECENTS_SKIP_DELETED - don't include deleted pages
* RECENTS_SKIP_MINORS - don't include minor changes
* RECENTS_SKIP_SUBSPACES - don't include subspaces
* RECENTS_MEDIA_CHANGES - return media changes instead of page changes
*
* @param int $from date of the oldest entry to return
* @param int $to date of the newest entry to return (for pagination, optional)
* @param string $ns restrict to given namespace (optional)
* @param int $flags see above (optional)
* @return array of files
*
* @author Michael Hamann <michael@content-space.de>
* @author Ben Coburn <btcoburn@silicodon.net>
*/
function getRecentsSince($from,$to=null,$ns='',$flags=0){
global $conf;
$recent = array();
if($to && $to < $from)
return $recent;
// read all recent changes. (kept short)
if ($flags & RECENTS_MEDIA_CHANGES) {
$lines = @file($conf['media_changelog']);
} else {
$lines = @file($conf['changelog']);
}
if(!$lines) return $recent;
// we start searching at the end of the list
$lines = array_reverse($lines);
// handle lines
$seen = array(); // caches seen lines, _handleRecent() skips them
foreach($lines as $line){
$rec = _handleRecent($line, $ns, $flags, $seen);
if($rec !== false) {
if ($rec['date'] >= $from) {
if (!$to || $rec['date'] <= $to) {
$recent[] = $rec;
}
} else {
break;
}
}
}
return array_reverse($recent);
}
/**
* Internal function used by getRecents
*
* don't call directly
*
* @see getRecents()
* @author Andreas Gohr <andi@splitbrain.org>
* @author Ben Coburn <btcoburn@silicodon.net>
*/
function _handleRecent($line,$ns,$flags,&$seen){
if(empty($line)) return false; //skip empty lines
// split the line into parts
$recent = parseChangelogLine($line);
if ($recent===false) { return false; }
// skip seen ones
if(isset($seen[$recent['id']])) return false;
// skip minors
if($recent['type']===DOKU_CHANGE_TYPE_MINOR_EDIT && ($flags & RECENTS_SKIP_MINORS)) return false;
// remember in seen to skip additional sights
$seen[$recent['id']] = 1;
// check if it's a hidden page
if(isHiddenPage($recent['id'])) return false;
// filter namespace
if (($ns) && (strpos($recent['id'],$ns.':') !== 0)) return false;
// exclude subnamespaces
if (($flags & RECENTS_SKIP_SUBSPACES) && (getNS($recent['id']) != $ns)) return false;
// check ACL
if ($flags & RECENTS_MEDIA_CHANGES) {
$recent['perms'] = auth_quickaclcheck(getNS($recent['id']).':*');
} else {
$recent['perms'] = auth_quickaclcheck($recent['id']);
}
if ($recent['perms'] < AUTH_READ) return false;
// check existance
if($flags & RECENTS_SKIP_DELETED){
$fn = (($flags & RECENTS_MEDIA_CHANGES) ? mediaFN($recent['id']) : wikiFN($recent['id']));
if(!@file_exists($fn)) return false;
}
return $recent;
}
/**
* Get the changelog information for a specific page id
* and revision (timestamp). Adjacent changelog lines
* are optimistically parsed and cached to speed up
* consecutive calls to getRevisionInfo. For large
* changelog files, only the chunk containing the
* requested changelog line is read.
*
* @author Ben Coburn <btcoburn@silicodon.net>
* @author Kate Arzamastseva <pshns@ukr.net>
*/
function getRevisionInfo($id, $rev, $chunk_size=8192, $media=false) {
global $cache_revinfo;
$cache =& $cache_revinfo;
if (!isset($cache[$id])) { $cache[$id] = array(); }
$rev = max($rev, 0);
// check if it's already in the memory cache
if (isset($cache[$id]) && isset($cache[$id][$rev])) {
return $cache[$id][$rev];
}
if ($media) {
$file = mediaMetaFN($id, '.changes');
} else {
$file = metaFN($id, '.changes');
}
if (!@file_exists($file)) { return false; }
if (filesize($file)<$chunk_size || $chunk_size==0) {
// read whole file
$lines = file($file);
if ($lines===false) { return false; }
} else {
// read by chunk
$fp = fopen($file, 'rb'); // "file pointer"
if ($fp===false) { return false; }
$head = 0;
fseek($fp, 0, SEEK_END);
$tail = ftell($fp);
$finger = 0;
$finger_rev = 0;
// find chunk
while ($tail-$head>$chunk_size) {
$finger = $head+floor(($tail-$head)/2.0);
fseek($fp, $finger);
fgets($fp); // slip the finger forward to a new line
$finger = ftell($fp);
$tmp = fgets($fp); // then read at that location
$tmp = parseChangelogLine($tmp);
$finger_rev = $tmp['date'];
if ($finger==$head || $finger==$tail) { break; }
if ($finger_rev>$rev) {
$tail = $finger;
} else {
$head = $finger;
}
}
if ($tail-$head<1) {
// cound not find chunk, assume requested rev is missing
fclose($fp);
return false;
}
// read chunk
$chunk = '';
$chunk_size = max($tail-$head, 0); // found chunk size
$got = 0;
fseek($fp, $head);
while ($got<$chunk_size && !feof($fp)) {
$tmp = @fread($fp, max($chunk_size-$got, 0));
if ($tmp===false) { break; } //error state
$got += strlen($tmp);
$chunk .= $tmp;
}
$lines = explode("\n", $chunk);
array_pop($lines); // remove trailing newline
fclose($fp);
}
// parse and cache changelog lines
foreach ($lines as $value) {
$tmp = parseChangelogLine($value);
if ($tmp!==false) {
$cache[$id][$tmp['date']] = $tmp;
}
}
if (!isset($cache[$id][$rev])) { return false; }
return $cache[$id][$rev];
}
/**
* Return a list of page revisions numbers
* Does not guarantee that the revision exists in the attic,
* only that a line with the date exists in the changelog.
* By default the current revision is skipped.
*
* id: the page of interest
* first: skip the first n changelog lines
* num: number of revisions to return
*
* The current revision is automatically skipped when the page exists.
* See $INFO['meta']['last_change'] for the current revision.
*
* For efficiency, the log lines are parsed and cached for later
* calls to getRevisionInfo. Large changelog files are read
* backwards in chunks until the requested number of changelog
* lines are recieved.
*
* @author Ben Coburn <btcoburn@silicodon.net>
* @author Kate Arzamastseva <pshns@ukr.net>
*/
function getRevisions($id, $first, $num, $chunk_size=8192, $media=false) {
global $cache_revinfo;
$cache =& $cache_revinfo;
if (!isset($cache[$id])) { $cache[$id] = array(); }
$revs = array();
$lines = array();
$count = 0;
if ($media) {
$file = mediaMetaFN($id, '.changes');
} else {
$file = metaFN($id, '.changes');
}
$num = max($num, 0);
if ($num == 0) { return $revs; }
$chunk_size = max($chunk_size, 0);
if ($first<0) {
$first = 0;
} else if (!$media && @file_exists(wikiFN($id)) || $media && @file_exists(mediaFN($id))) {
// skip current revision if the page exists
$first = max($first+1, 0);
}
if (!@file_exists($file)) { return $revs; }
if (filesize($file)<$chunk_size || $chunk_size==0) {
// read whole file
$lines = file($file);
if ($lines===false) { return $revs; }
} else {
// read chunks backwards
$fp = fopen($file, 'rb'); // "file pointer"
if ($fp===false) { return $revs; }
fseek($fp, 0, SEEK_END);
$tail = ftell($fp);
// chunk backwards
$finger = max($tail-$chunk_size, 0);
while ($count<$num+$first) {
fseek($fp, $finger);
$nl = $finger;
if ($finger>0) {
fgets($fp); // slip the finger forward to a new line
$nl = ftell($fp);
}
// was the chunk big enough? if not, take another bite
if($nl > 0 && $tail <= $nl){
$finger = max($finger-$chunk_size, 0);
continue;
}else{
$finger = $nl;
}
// read chunk
$chunk = '';
$read_size = max($tail-$finger, 0); // found chunk size
$got = 0;
while ($got<$read_size && !feof($fp)) {
$tmp = @fread($fp, max($read_size-$got, 0));
if ($tmp===false) { break; } //error state
$got += strlen($tmp);
$chunk .= $tmp;
}
$tmp = explode("\n", $chunk);
array_pop($tmp); // remove trailing newline
// combine with previous chunk
$count += count($tmp);
$lines = array_merge($tmp, $lines);
// next chunk
if ($finger==0) { break; } // already read all the lines
else {
$tail = $finger;
$finger = max($tail-$chunk_size, 0);
}
}
fclose($fp);
}
// skip parsing extra lines
$num = max(min(count($lines)-$first, $num), 0);
if ($first>0 && $num>0) { $lines = array_slice($lines, max(count($lines)-$first-$num, 0), $num); }
else if ($first>0 && $num==0) { $lines = array_slice($lines, 0, max(count($lines)-$first, 0)); }
else if ($first==0 && $num>0) { $lines = array_slice($lines, max(count($lines)-$num, 0)); }
// handle lines in reverse order
for ($i = count($lines)-1; $i >= 0; $i--) {
$tmp = parseChangelogLine($lines[$i]);
if ($tmp!==false) {
$cache[$id][$tmp['date']] = $tmp;
$revs[] = $tmp['date'];
}
}
return $revs;
}

502
sources/inc/cliopts.php Normal file
View file

@ -0,0 +1,502 @@
<?php
/**
* Brutally chopped and modified from http://pear.php.net/package/Console_Getopts
*
* PHP Version 5
*
* Copyright (c) 1997-2004 The PHP Group
*
* LICENSE: This source file is subject to the New BSD license that is
* available through the world-wide-web at the following URI:
* http://www.opensource.org/licenses/bsd-license.php. If you did not receive
* a copy of the New BSD License and are unable to obtain it through the web,
* please send a note to license@php.net so we can mail you a copy immediately.
*
* @category Console
* @package Console_Getopt
* @author Andrei Zmievski <andrei@php.net>
* @modified Harry Fuecks hfuecks gmail.com
* @modified Tanguy Ortolo <tanguy+dokuwiki@ortolo.eu>
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_Getopt
*
*/
//------------------------------------------------------------------------------
/**
* Sets up CLI environment based on SAPI and PHP version
* Helps resolve some issues between the CGI and CLI SAPIs
* as well is inconsistencies between PHP 4.3+ and older versions
*/
if (version_compare(phpversion(), '4.3.0', '<') || php_sapi_name() == 'cgi') {
// Handle output buffering
@ob_end_flush();
ob_implicit_flush(true);
// PHP ini settings
set_time_limit(0);
ini_set('track_errors', true);
ini_set('html_errors', false);
ini_set('magic_quotes_runtime', false);
// Define stream constants
define('STDIN', fopen('php://stdin', 'r'));
define('STDOUT', fopen('php://stdout', 'w'));
define('STDERR', fopen('php://stderr', 'w'));
// Close the streams on script termination
register_shutdown_function(
create_function('',
'fclose(STDIN); fclose(STDOUT); fclose(STDERR); return true;')
);
}
//------------------------------------------------------------------------------
/**
* Error codes
*/
define('DOKU_CLI_OPTS_UNKNOWN_OPT',1); //Unrecognized option
define('DOKU_CLI_OPTS_OPT_ARG_REQUIRED',2); //Option requires argument
define('DOKU_CLI_OPTS_OPT_ARG_DENIED',3); //Option not allowed argument
define('DOKU_CLI_OPTS_OPT_ABIGUOUS',4);//Option abiguous
define('DOKU_CLI_OPTS_ARG_READ',5);//Could not read argv
//------------------------------------------------------------------------------
/**
* Command-line options parsing class.
*
* @author Andrei Zmievski <andrei@php.net>
*
*/
class Doku_Cli_Opts {
/**
* <?php ?>
* @see http://www.sitepoint.com/article/php-command-line-1/3
* @param string executing file name - this MUST be passed the __FILE__ constant
* @param string short options
* @param array (optional) long options
* @return Doku_Cli_Opts_Container or Doku_Cli_Opts_Error
*/
function & getOptions($bin_file, $short_options, $long_options = null) {
$args = Doku_Cli_Opts::readPHPArgv();
if ( Doku_Cli_Opts::isError($args) ) {
return $args;
}
// Compatibility between "php extensions.php" and "./extensions.php"
if ( realpath($_SERVER['argv'][0]) == $bin_file ) {
$options = Doku_Cli_Opts::getOpt($args,$short_options,$long_options);
} else {
$options = Doku_Cli_Opts::getOpt2($args,$short_options,$long_options);
}
if ( Doku_Cli_Opts::isError($options) ) {
return $options;
}
$container = new Doku_Cli_Opts_Container($options);
return $container;
}
/**
* Parses the command-line options.
*
* The first parameter to this function should be the list of command-line
* arguments without the leading reference to the running program.
*
* The second parameter is a string of allowed short options. Each of the
* option letters can be followed by a colon ':' to specify that the option
* requires an argument, or a double colon '::' to specify that the option
* takes an optional argument.
*
* The third argument is an optional array of allowed long options. The
* leading '--' should not be included in the option name. Options that
* require an argument should be followed by '=', and options that take an
* option argument should be followed by '=='.
*
* The return value is an array of two elements: the list of parsed
* options and the list of non-option command-line arguments. Each entry in
* the list of parsed options is a pair of elements - the first one
* specifies the option, and the second one specifies the option argument,
* if there was one.
*
* Long and short options can be mixed.
*
* Most of the semantics of this function are based on GNU getopt_long().
*
* @param array $args an array of command-line arguments
* @param string $short_options specifies the list of allowed short options
* @param array $long_options specifies the list of allowed long options
*
* @return array two-element array containing the list of parsed options and
* the non-option arguments
* @access public
*/
function getopt2($args, $short_options, $long_options = null) {
return Doku_Cli_Opts::doGetopt(
2, $args, $short_options, $long_options
);
}
/**
* This function expects $args to start with the script name (POSIX-style).
* Preserved for backwards compatibility.
*
* @param array $args an array of command-line arguments
* @param string $short_options specifies the list of allowed short options
* @param array $long_options specifies the list of allowed long options
*
* @see getopt2()
* @return array two-element array containing the list of parsed options and
* the non-option arguments
*/
function getopt($args, $short_options, $long_options = null) {
return Doku_Cli_Opts::doGetopt(
1, $args, $short_options, $long_options
);
}
/**
* The actual implementation of the argument parsing code.
*
* @param int $version Version to use
* @param array $args an array of command-line arguments
* @param string $short_options specifies the list of allowed short options
* @param array $long_options specifies the list of allowed long options
*
* @return array
*/
function doGetopt($version, $args, $short_options, $long_options = null) {
// in case you pass directly readPHPArgv() as the first arg
if (Doku_Cli_Opts::isError($args)) {
return $args;
}
if (empty($args)) {
return array(array(), array());
}
$opts = array();
$non_opts = array();
settype($args, 'array');
if ($long_options && is_array($long_options)) {
sort($long_options);
}
/*
* Preserve backwards compatibility with callers that relied on
* erroneous POSIX fix.
*/
if ($version < 2) {
if (isset($args[0]{0}) && $args[0]{0} != '-') {
array_shift($args);
}
}
reset($args);
while (list($i, $arg) = each($args)) {
/* The special element '--' means explicit end of
options. Treat the rest of the arguments as non-options
and end the loop. */
if ($arg == '--') {
$non_opts = array_merge($non_opts, array_slice($args, $i + 1));
break;
}
if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) {
$non_opts = array_merge($non_opts, array_slice($args, $i));
break;
} elseif (strlen($arg) > 1 && $arg{1} == '-') {
$error = Doku_Cli_Opts::_parseLongOption(substr($arg, 2), $long_options, $opts, $args);
if (Doku_Cli_Opts::isError($error))
return $error;
} elseif ($arg == '-') {
// - is stdin
$non_opts = array_merge($non_opts, array_slice($args, $i));
break;
} else {
$error = Doku_Cli_Opts::_parseShortOption(substr($arg, 1), $short_options, $opts, $args);
if (Doku_Cli_Opts::isError($error))
return $error;
}
}
return array($opts, $non_opts);
}
/**
* Parse short option
*
* @param string $arg Argument
* @param string[] $short_options Available short options
* @param string[][] &$opts
* @param string[] &$args
*
* @access private
* @return void
*/
function _parseShortOption($arg, $short_options, &$opts, &$args) {
$len = strlen($arg);
for ($i = 0; $i < $len; $i++) {
$opt = $arg{$i};
$opt_arg = null;
/* Try to find the short option in the specifier string. */
if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':')
{
return Doku_Cli_Opts::raiseError(
DOKU_CLI_OPTS_UNKNOWN_OPT,
"Unrecognized option -- $opt"
);
}
if (strlen($spec) > 1 && $spec{1} == ':') {
if (strlen($spec) > 2 && $spec{2} == ':') {
if ($i + 1 < strlen($arg)) {
/* Option takes an optional argument. Use the remainder of
the arg string if there is anything left. */
$opts[] = array($opt, substr($arg, $i + 1));
break;
}
} else {
/* Option requires an argument. Use the remainder of the arg
string if there is anything left. */
if ($i + 1 < strlen($arg)) {
$opts[] = array($opt, substr($arg, $i + 1));
break;
} else if (list(, $opt_arg) = each($args)) {
/* Else use the next argument. */;
if (Doku_Cli_Opts::_isShortOpt($opt_arg) || Doku_Cli_Opts::_isLongOpt($opt_arg))
return Doku_Cli_Opts::raiseError(
DOKU_CLI_OPTS_OPT_ARG_REQUIRED,
"option requires an argument --$opt"
);
}
else
return Doku_Cli_Opts::raiseError(
DOKU_CLI_OPTS_OPT_ARG_REQUIRED,
"Option requires an argument -- $opt"
);
}
}
$opts[] = array($opt, $opt_arg);
}
}
/**
* Checks if an argument is a short option
*
* @param string $arg Argument to check
*
* @access private
* @return bool
*/
function _isShortOpt($arg){
return strlen($arg) == 2 && $arg[0] == '-'
&& preg_match('/[a-zA-Z]/', $arg[1]);
}
/**
* Checks if an argument is a long option
*
* @param string $arg Argument to check
*
* @access private
* @return bool
*/
function _isLongOpt($arg){
return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' &&
preg_match('/[a-zA-Z]+$/', substr($arg, 2));
}
/**
* Parse long option
*
* @param string $arg Argument
* @param string[] $long_options Available long options
* @param string[][] &$opts
* @param string[] &$args
*
* @access private
* @return void|PEAR_Error
*/
function _parseLongOption($arg, $long_options, &$opts, &$args) {
@list($opt, $opt_arg) = explode('=', $arg, 2);
$opt_len = strlen($opt);
$opt_cnt = count($long_options);
for ($i = 0; $i < $opt_cnt; $i++) {
$long_opt = $long_options[$i];
$opt_start = substr($long_opt, 0, $opt_len);
$long_opt_name = str_replace('=', '', $long_opt);
/* Option doesn't match. Go on to the next one. */
if ($opt_start != $opt)
continue;
$opt_rest = substr($long_opt, $opt_len);
/* Check that the options uniquely matches one of the allowed
options. */
if ($i + 1 < count($long_options)) {
$next_option_rest = substr($long_options[$i + 1], $opt_len);
} else {
$next_option_rest = '';
}
if ($opt_rest != '' && $opt{0} != '=' &&
$i + 1 < $opt_cnt &&
$opt == substr($long_options[$i+1], 0, $opt_len) &&
$next_option_rest != '' &&
$next_option_rest{0} != '=') {
return Doku_Cli_Opts::raiseError(
DOKU_CLI_OPTS_OPT_ABIGUOUS,
"Option --$opt is ambiguous"
);
}
if (substr($long_opt, -1) == '=') {
if (substr($long_opt, -2) != '==') {
/* Long option requires an argument.
Take the next argument if one wasn't specified. */;
if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) {
return Doku_Cli_Opts::raiseError(
DOKU_CLI_OPTS_OPT_ARG_REQUIRED,
"Option --$opt requires an argument"
);
}
if (Doku_Cli_Opts::_isShortOpt($opt_arg)
|| Doku_Cli_Opts::_isLongOpt($opt_arg))
return Doku_Cli_Opts::raiseError(
DOKU_CLI_OPTS_OPT_ARG_REQUIRED,
"Option --$opt requires an argument"
);
}
} else if ($opt_arg) {
return Doku_Cli_Opts::raiseError(
DOKU_CLI_OPTS_OPT_ARG_DENIED,
"Option --$opt doesn't allow an argument"
);
}
$opts[] = array('--' . $opt, $opt_arg);
return;
}
return Doku_Cli_Opts::raiseError(
DOKU_CLI_OPTS_UNKNOWN_OPT,
"Unrecognized option --$opt"
);
}
/**
* Safely read the $argv PHP array across different PHP configurations.
* Will take care on register_globals and register_argc_argv ini directives
*
* @access public
* @return mixed the $argv PHP array or PEAR error if not registered
*/
function readPHPArgv() {
global $argv;
if (!is_array($argv)) {
if (!@is_array($_SERVER['argv'])) {
if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
return Doku_Cli_Opts::raiseError(
DOKU_CLI_OPTS_ARG_READ,
"Could not read cmd args (register_argc_argv=Off?)"
);
}
return $GLOBALS['HTTP_SERVER_VARS']['argv'];
}
return $_SERVER['argv'];
}
return $argv;
}
function raiseError($code, $msg) {
return new Doku_Cli_Opts_Error($code, $msg);
}
function isError($obj) {
return is_a($obj, 'Doku_Cli_Opts_Error');
}
}
//------------------------------------------------------------------------------
class Doku_Cli_Opts_Error {
var $code;
var $msg;
function Doku_Cli_Opts_Error($code, $msg) {
$this->code = $code;
$this->msg = $msg;
}
function getMessage() {
return $this->msg;
}
function isError() {
return true;
}
}
//------------------------------------------------------------------------------
class Doku_Cli_Opts_Container {
var $options = array();
var $args = array();
function Doku_Cli_Opts_Container($options) {
foreach ( $options[0] as $option ) {
if ( false !== ( strpos($option[0], '--') ) ) {
$opt_name = substr($option[0], 2);
} else {
$opt_name = $option[0];
}
$this->options[$opt_name] = $option[1];
}
$this->args = $options[1];
}
function has($option) {
return array_key_exists($option, $this->options);
}
function get($option) {
if ( isset($this->options[$option]) ) {
return ( $this->options[$option] ) ;
}
}
function arg($index) {
if ( isset($this->args[$index]) ) {
return $this->args[$index];
}
}
function numArgs() {
return count($this->args);
}
function hasArgs() {
return count($this->args) !== 0;
}
function isError() {
return false;
}
}

1633
sources/inc/common.php Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,36 @@
<?php
/**
* compatibility functions
*
* This file contains a few functions that might be missing from the PHP build
*/
if(!function_exists('ctype_space')) {
/**
* Check for whitespace character(s)
*
* @see ctype_space
* @param string $text
* @return bool
*/
function ctype_space($text) {
if(!is_string($text)) return false; #FIXME original treats between -128 and 255 inclusive as ASCII chars
if(trim($text) === '') return true;
return false;
}
}
if(!function_exists('ctype_digit')) {
/**
* Check for numeric character(s)
*
* @see ctype_digit
* @param string $text
* @return bool
*/
function ctype_digit($text) {
if(!is_string($text)) return false; #FIXME original treats between -128 and 255 inclusive as ASCII chars
if(preg_match('/^\d+$/', $text)) return true;
return false;
}
}

View file

@ -0,0 +1,78 @@
<?php
/**
* The default config cascade
*
* This array configures the default locations of various files in the
* DokuWiki directory hierarchy. It can be overriden in inc/preload.php
*/
$config_cascade = array_merge(
array(
'main' => array(
'default' => array(DOKU_CONF.'dokuwiki.php'),
'local' => array(DOKU_CONF.'local.php'),
'protected' => array(DOKU_CONF.'local.protected.php'),
),
'acronyms' => array(
'default' => array(DOKU_CONF.'acronyms.conf'),
'local' => array(DOKU_CONF.'acronyms.local.conf'),
),
'entities' => array(
'default' => array(DOKU_CONF.'entities.conf'),
'local' => array(DOKU_CONF.'entities.local.conf'),
),
'interwiki' => array(
'default' => array(DOKU_CONF.'interwiki.conf'),
'local' => array(DOKU_CONF.'interwiki.local.conf'),
),
'license' => array(
'default' => array(DOKU_CONF.'license.php'),
'local' => array(DOKU_CONF.'license.local.php'),
),
'mediameta' => array(
'default' => array(DOKU_CONF.'mediameta.php'),
'local' => array(DOKU_CONF.'mediameta.local.php'),
),
'mime' => array(
'default' => array(DOKU_CONF.'mime.conf'),
'local' => array(DOKU_CONF.'mime.local.conf'),
),
'scheme' => array(
'default' => array(DOKU_CONF.'scheme.conf'),
'local' => array(DOKU_CONF.'scheme.local.conf'),
),
'smileys' => array(
'default' => array(DOKU_CONF.'smileys.conf'),
'local' => array(DOKU_CONF.'smileys.local.conf'),
),
'wordblock' => array(
'default' => array(DOKU_CONF.'wordblock.conf'),
'local' => array(DOKU_CONF.'wordblock.local.conf'),
),
'userstyle' => array(
'screen' => DOKU_CONF.'userstyle.css',
'print' => DOKU_CONF.'userprint.css',
'feed' => DOKU_CONF.'userfeed.css',
'all' => DOKU_CONF.'userall.css',
),
'userscript' => array(
'default' => DOKU_CONF.'userscript.js'
),
'acl' => array(
'default' => DOKU_CONF.'acl.auth.php',
),
'plainauth.users' => array(
'default' => DOKU_CONF.'users.auth.php',
),
'plugins' => array(
'default' => array(DOKU_CONF.'plugins.php'),
'local' => array(DOKU_CONF.'plugins.local.php'),
'protected' => array(
DOKU_CONF.'plugins.required.php',
DOKU_CONF.'plugins.protected.php',
),
),
),
$config_cascade
);

345
sources/inc/confutils.php Normal file
View file

@ -0,0 +1,345 @@
<?php
/**
* Utilities for collecting data from config files
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Harry Fuecks <hfuecks@gmail.com>
*/
/**
* Returns the (known) extension and mimetype of a given filename
*
* If $knownonly is true (the default), then only known extensions
* are returned.
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function mimetype($file, $knownonly=true){
$mtypes = getMimeTypes(); // known mimetypes
$ext = strrpos($file, '.');
if ($ext === false) {
return array(false, false, false);
}
$ext = strtolower(substr($file, $ext + 1));
if (!isset($mtypes[$ext])){
if ($knownonly) {
return array(false, false, false);
} else {
return array($ext, 'application/octet-stream', true);
}
}
if($mtypes[$ext][0] == '!'){
return array($ext, substr($mtypes[$ext],1), true);
}else{
return array($ext, $mtypes[$ext], false);
}
}
/**
* returns a hash of mimetypes
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function getMimeTypes() {
static $mime = null;
if ( !$mime ) {
$mime = retrieveConfig('mime','confToHash');
}
return $mime;
}
/**
* returns a hash of acronyms
*
* @author Harry Fuecks <hfuecks@gmail.com>
*/
function getAcronyms() {
static $acronyms = null;
if ( !$acronyms ) {
$acronyms = retrieveConfig('acronyms','confToHash');
}
return $acronyms;
}
/**
* returns a hash of smileys
*
* @author Harry Fuecks <hfuecks@gmail.com>
*/
function getSmileys() {
static $smileys = null;
if ( !$smileys ) {
$smileys = retrieveConfig('smileys','confToHash');
}
return $smileys;
}
/**
* returns a hash of entities
*
* @author Harry Fuecks <hfuecks@gmail.com>
*/
function getEntities() {
static $entities = null;
if ( !$entities ) {
$entities = retrieveConfig('entities','confToHash');
}
return $entities;
}
/**
* returns a hash of interwikilinks
*
* @author Harry Fuecks <hfuecks@gmail.com>
*/
function getInterwiki() {
static $wikis = null;
if ( !$wikis ) {
$wikis = retrieveConfig('interwiki','confToHash',array(true));
}
//add sepecial case 'this'
$wikis['this'] = DOKU_URL.'{NAME}';
return $wikis;
}
/**
* returns array of wordblock patterns
*
*/
function getWordblocks() {
static $wordblocks = null;
if ( !$wordblocks ) {
$wordblocks = retrieveConfig('wordblock','file');
}
return $wordblocks;
}
/**
* Gets the list of configured schemes
*
* @return array the schemes
*/
function getSchemes() {
static $schemes = null;
if ( !$schemes ) {
$schemes = retrieveConfig('scheme','file');
}
$schemes = array_map('trim', $schemes);
$schemes = preg_replace('/^#.*/', '', $schemes);
$schemes = array_filter($schemes);
return $schemes;
}
/**
* Builds a hash from an array of lines
*
* If $lower is set to true all hash keys are converted to
* lower case.
*
* @author Harry Fuecks <hfuecks@gmail.com>
* @author Andreas Gohr <andi@splitbrain.org>
* @author Gina Haeussge <gina@foosel.net>
*/
function linesToHash($lines, $lower=false) {
$conf = array();
// remove BOM
if (isset($lines[0]) && substr($lines[0],0,3) == pack('CCC',0xef,0xbb,0xbf))
$lines[0] = substr($lines[0],3);
foreach ( $lines as $line ) {
//ignore comments (except escaped ones)
$line = preg_replace('/(?<![&\\\\])#.*$/','',$line);
$line = str_replace('\\#','#',$line);
$line = trim($line);
if(empty($line)) continue;
$line = preg_split('/\s+/',$line,2);
// Build the associative array
if($lower){
$conf[strtolower($line[0])] = $line[1];
}else{
$conf[$line[0]] = $line[1];
}
}
return $conf;
}
/**
* Builds a hash from a configfile
*
* If $lower is set to true all hash keys are converted to
* lower case.
*
* @author Harry Fuecks <hfuecks@gmail.com>
* @author Andreas Gohr <andi@splitbrain.org>
* @author Gina Haeussge <gina@foosel.net>
*/
function confToHash($file,$lower=false) {
$conf = array();
$lines = @file( $file );
if ( !$lines ) return $conf;
return linesToHash($lines, $lower);
}
/**
* Retrieve the requested configuration information
*
* @author Chris Smith <chris@jalakai.co.uk>
*
* @param string $type the configuration settings to be read, must correspond to a key/array in $config_cascade
* @param callback $fn the function used to process the configuration file into an array
* @param array $params optional additional params to pass to the callback
* @return array configuration values
*/
function retrieveConfig($type,$fn,$params=null) {
global $config_cascade;
if(!is_array($params)) $params = array();
$combined = array();
if (!is_array($config_cascade[$type])) trigger_error('Missing config cascade for "'.$type.'"',E_USER_WARNING);
foreach (array('default','local','protected') as $config_group) {
if (empty($config_cascade[$type][$config_group])) continue;
foreach ($config_cascade[$type][$config_group] as $file) {
if (@file_exists($file)) {
$config = call_user_func_array($fn,array_merge(array($file),$params));
$combined = array_merge($combined, $config);
}
}
}
return $combined;
}
/**
* Include the requested configuration information
*
* @author Chris Smith <chris@jalakai.co.uk>
*
* @param string $type the configuration settings to be read, must correspond to a key/array in $config_cascade
* @return array list of files, default before local before protected
*/
function getConfigFiles($type) {
global $config_cascade;
$files = array();
if (!is_array($config_cascade[$type])) trigger_error('Missing config cascade for "'.$type.'"',E_USER_WARNING);
foreach (array('default','local','protected') as $config_group) {
if (empty($config_cascade[$type][$config_group])) continue;
$files = array_merge($files, $config_cascade[$type][$config_group]);
}
return $files;
}
/**
* check if the given action was disabled in config
*
* @author Andreas Gohr <andi@splitbrain.org>
* @returns boolean true if enabled, false if disabled
*/
function actionOK($action){
static $disabled = null;
if(is_null($disabled) || defined('SIMPLE_TEST')){
global $conf;
/** @var auth_basic $auth */
global $auth;
// prepare disabled actions array and handle legacy options
$disabled = explode(',',$conf['disableactions']);
$disabled = array_map('trim',$disabled);
if((isset($conf['openregister']) && !$conf['openregister']) || is_null($auth) || !$auth->canDo('addUser')) {
$disabled[] = 'register';
}
if((isset($conf['resendpasswd']) && !$conf['resendpasswd']) || is_null($auth) || !$auth->canDo('modPass')) {
$disabled[] = 'resendpwd';
}
if((isset($conf['subscribers']) && !$conf['subscribers']) || is_null($auth)) {
$disabled[] = 'subscribe';
}
if (is_null($auth) || !$auth->canDo('Profile')) {
$disabled[] = 'profile';
}
if (is_null($auth) || !$auth->canDo('delUser')) {
$disabled[] = 'profile_delete';
}
if (is_null($auth)) {
$disabled[] = 'login';
}
if (is_null($auth) || !$auth->canDo('logout')) {
$disabled[] = 'logout';
}
$disabled = array_unique($disabled);
}
return !in_array($action,$disabled);
}
/**
* check if headings should be used as link text for the specified link type
*
* @author Chris Smith <chris@jalakai.co.uk>
*
* @param string $linktype 'content'|'navigation', content applies to links in wiki text
* navigation applies to all other links
* @return boolean true if headings should be used for $linktype, false otherwise
*/
function useHeading($linktype) {
static $useHeading = null;
if (is_null($useHeading)) {
global $conf;
if (!empty($conf['useheading'])) {
switch ($conf['useheading']) {
case 'content':
$useHeading['content'] = true;
break;
case 'navigation':
$useHeading['navigation'] = true;
break;
default:
$useHeading['content'] = true;
$useHeading['navigation'] = true;
}
} else {
$useHeading = array();
}
}
return (!empty($useHeading[$linktype]));
}
/**
* obscure config data so information isn't plain text
*
* @param string $str data to be encoded
* @param string $code encoding method, values: plain, base64, uuencode.
* @return string the encoded value
*/
function conf_encodeString($str,$code) {
switch ($code) {
case 'base64' : return '<b>'.base64_encode($str);
case 'uuencode' : return '<u>'.convert_uuencode($str);
case 'plain':
default:
return $str;
}
}
/**
* return obscured data as plain text
*
* @param string $str encoded data
* @return string plain text
*/
function conf_decodeString($str) {
switch (substr($str,0,3)) {
case '<b>' : return base64_decode(substr($str,3));
case '<u>' : return convert_uudecode(substr($str,3));
default: // not encode (or unknown)
return $str;
}
}
//Setup VIM: ex: et ts=4 :

197
sources/inc/events.php Normal file
View file

@ -0,0 +1,197 @@
<?php
/**
* DokuWiki Events
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Christopher Smith <chris@jalakai.co.uk>
*/
if(!defined('DOKU_INC')) die('meh.');
class Doku_Event {
// public properties
var $name = ''; // READONLY event name, objects must register against this name to see the event
var $data = null; // READWRITE data relevant to the event, no standardised format (YET!)
var $result = null; // READWRITE the results of the event action, only relevant in "_AFTER" advise
// event handlers may modify this if they are preventing the default action
// to provide the after event handlers with event results
var $canPreventDefault = true; // READONLY if true, event handlers can prevent the events default action
// private properties, event handlers can effect these through the provided methods
var $_default = true; // whether or not to carry out the default action associated with the event
var $_continue = true; // whether or not to continue propagating the event to other handlers
/**
* event constructor
*/
function Doku_Event($name, &$data) {
$this->name = $name;
$this->data =& $data;
}
/**
* advise functions
*
* advise all registered handlers of this event
*
* if these methods are used by functions outside of this object, they must
* properly handle correct processing of any default action and issue an
* advise_after() signal. e.g.
* $evt = new Doku_Event(name, data);
* if ($evt->advise_before(canPreventDefault) {
* // default action code block
* }
* $evt->advise_after();
* unset($evt);
*
* @return results of processing the event, usually $this->_default
*/
function advise_before($enablePreventDefault=true) {
global $EVENT_HANDLER;
$this->canPreventDefault = $enablePreventDefault;
$EVENT_HANDLER->process_event($this,'BEFORE');
return (!$enablePreventDefault || $this->_default);
}
function advise_after() {
global $EVENT_HANDLER;
$this->_continue = true;
$EVENT_HANDLER->process_event($this,'AFTER');
}
/**
* trigger
*
* - advise all registered (<event>_BEFORE) handlers that this event is about to take place
* - carry out the default action using $this->data based on $enablePrevent and
* $this->_default, all of which may have been modified by the event handlers.
* - advise all registered (<event>_AFTER) handlers that the event has taken place
*
* @return $event->results
* the value set by any <event>_before or <event> handlers if the default action is prevented
* or the results of the default action (as modified by <event>_after handlers)
* or NULL no action took place and no handler modified the value
*/
function trigger($action=null, $enablePrevent=true) {
if (!is_callable($action)) $enablePrevent = false;
if ($this->advise_before($enablePrevent) && is_callable($action)) {
if (is_array($action)) {
list($obj,$method) = $action;
$this->result = $obj->$method($this->data);
} else {
$this->result = $action($this->data);
}
}
$this->advise_after();
return $this->result;
}
/**
* stopPropagation
*
* stop any further processing of the event by event handlers
* this function does not prevent the default action taking place
*/
function stopPropagation() { $this->_continue = false; }
/**
* preventDefault
*
* prevent the default action taking place
*/
function preventDefault() { $this->_default = false; }
}
class Doku_Event_Handler {
// public properties: none
// private properties
var $_hooks = array(); // array of events and their registered handlers
/**
* event_handler
*
* constructor, loads all action plugins and calls their register() method giving them
* an opportunity to register any hooks they require
*/
function Doku_Event_Handler() {
// load action plugins
$plugin = null;
$pluginlist = plugin_list('action');
foreach ($pluginlist as $plugin_name) {
$plugin = plugin_load('action',$plugin_name);
if ($plugin !== null) $plugin->register($this);
}
}
/**
* register_hook
*
* register a hook for an event
*
* @param $event (string) name used by the event, (incl '_before' or '_after' for triggers)
* @param $obj (obj) object in whose scope method is to be executed,
* if NULL, method is assumed to be a globally available function
* @param $method (function) event handler function
* @param $param (mixed) data passed to the event handler
*/
function register_hook($event, $advise, $obj, $method, $param=null) {
$this->_hooks[$event.'_'.$advise][] = array($obj, $method, $param);
}
function process_event(&$event,$advise='') {
$evt_name = $event->name . ($advise ? '_'.$advise : '_BEFORE');
if (!empty($this->_hooks[$evt_name])) {
foreach ($this->_hooks[$evt_name] as $hook) {
// list($obj, $method, $param) = $hook;
$obj =& $hook[0];
$method = $hook[1];
$param = $hook[2];
if (is_null($obj)) {
$method($event, $param);
} else {
$obj->$method($event, $param);
}
if (!$event->_continue) break;
}
}
}
}
/**
* trigger_event
*
* function wrapper to process (create, trigger and destroy) an event
*
* @param $name (string) name for the event
* @param $data (mixed) event data
* @param $action (callback) (optional, default=NULL) default action, a php callback function
* @param $canPreventDefault (bool) (optional, default=true) can hooks prevent the default action
*
* @return (mixed) the event results value after all event processing is complete
* by default this is the return value of the default action however
* it can be set or modified by event handler hooks
*/
function trigger_event($name, &$data, $action=null, $canPreventDefault=true) {
$evt = new Doku_Event($name, $data);
return $evt->trigger($action, $canPreventDefault);
}

146
sources/inc/farm.php Normal file
View file

@ -0,0 +1,146 @@
<?php
/**
* This overwrites DOKU_CONF. Each animal gets its own configuration and data directory.
* This can be used together with preload.php. See preload.php.dist for an example setup.
* For more information see http://www.dokuwiki.org/farms.
*
* The farm directory (constant DOKU_FARMDIR) can be any directory and needs to be set.
* Animals are direct subdirectories of the farm directory.
* There are two different approaches:
* * An .htaccess based setup can use any animal directory name:
* http://example.org/<path_to_farm>/subdir/ will need the subdirectory '$farm/subdir/'.
* * A virtual host based setup needs animal directory names which have to reflect
* the domain name: If an animal resides in http://www.example.org:8080/mysite/test/,
* directories that will match range from '$farm/8080.www.example.org.mysite.test/'
* to a simple '$farm/domain/'.
*
* @author Anika Henke <anika@selfthinker.org>
* @author Michael Klier <chi@chimeric.de>
* @author Christopher Smith <chris@jalakai.co.uk>
* @author virtual host part of farm_confpath() based on conf_path() from Drupal.org's /includes/bootstrap.inc
* (see https://github.com/drupal/drupal/blob/7.x/includes/bootstrap.inc#L537)
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*/
// DOKU_FARMDIR needs to be set in preload.php, here the fallback is the same as DOKU_INC would be (if it was set already)
if(!defined('DOKU_FARMDIR')) define('DOKU_FARMDIR', fullpath(dirname(__FILE__).'/../').'/');
if(!defined('DOKU_CONF')) define('DOKU_CONF', farm_confpath(DOKU_FARMDIR));
if(!defined('DOKU_FARM')) define('DOKU_FARM', false);
/**
* Find the appropriate configuration directory.
*
* If the .htaccess based setup is used, the configuration directory can be
* any subdirectory of the farm directory.
*
* Otherwise try finding a matching configuration directory by stripping the
* website's hostname from left to right and pathname from right to left. The
* first configuration file found will be used; the remaining will ignored.
* If no configuration file is found, return the default confdir './conf'.
*/
function farm_confpath($farm) {
// htaccess based or cli
// cli usage example: animal=your_animal bin/indexer.php
if(isset($_REQUEST['animal']) || ('cli' == php_sapi_name() && isset($_SERVER['animal']))) {
$mode = isset($_REQUEST['animal']) ? 'htaccess' : 'cli';
$animal = $mode == 'htaccess' ? $_REQUEST['animal'] : $_SERVER['animal'];
// check that $animal is a string and just a directory name and not a path
if (!is_string($animal) || strpbrk($animal, '\\/') !== false)
nice_die('Sorry! Invalid animal name!');
if(!is_dir($farm.'/'.$animal))
nice_die("Sorry! This Wiki doesn't exist!");
if(!defined('DOKU_FARM')) define('DOKU_FARM', $mode);
return $farm.'/'.$animal.'/conf/';
}
// virtual host based
$uri = explode('/', $_SERVER['SCRIPT_NAME'] ? $_SERVER['SCRIPT_NAME'] : $_SERVER['SCRIPT_FILENAME']);
$server = explode('.', implode('.', array_reverse(explode(':', rtrim($_SERVER['HTTP_HOST'], '.')))));
for ($i = count($uri) - 1; $i > 0; $i--) {
for ($j = count($server); $j > 0; $j--) {
$dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i));
if(is_dir("$farm/$dir/conf/")) {
if(!defined('DOKU_FARM')) define('DOKU_FARM', 'virtual');
return "$farm/$dir/conf/";
}
}
}
// default conf directory in farm
if(is_dir("$farm/default/conf/")) {
if(!defined('DOKU_FARM')) define('DOKU_FARM', 'default');
return "$farm/default/conf/";
}
// farmer
return DOKU_INC.'conf/';
}
/* Use default config files and local animal config files */
$config_cascade = array(
'main' => array(
'default' => array(DOKU_INC.'conf/dokuwiki.php'),
'local' => array(DOKU_CONF.'local.php'),
'protected' => array(DOKU_CONF.'local.protected.php'),
),
'acronyms' => array(
'default' => array(DOKU_INC.'conf/acronyms.conf'),
'local' => array(DOKU_CONF.'acronyms.local.conf'),
),
'entities' => array(
'default' => array(DOKU_INC.'conf/entities.conf'),
'local' => array(DOKU_CONF.'entities.local.conf'),
),
'interwiki' => array(
'default' => array(DOKU_INC.'conf/interwiki.conf'),
'local' => array(DOKU_CONF.'interwiki.local.conf'),
),
'license' => array(
'default' => array(DOKU_INC.'conf/license.php'),
'local' => array(DOKU_CONF.'license.local.php'),
),
'mediameta' => array(
'default' => array(DOKU_INC.'conf/mediameta.php'),
'local' => array(DOKU_CONF.'mediameta.local.php'),
),
'mime' => array(
'default' => array(DOKU_INC.'conf/mime.conf'),
'local' => array(DOKU_CONF.'mime.local.conf'),
),
'scheme' => array(
'default' => array(DOKU_INC.'conf/scheme.conf'),
'local' => array(DOKU_CONF.'scheme.local.conf'),
),
'smileys' => array(
'default' => array(DOKU_INC.'conf/smileys.conf'),
'local' => array(DOKU_CONF.'smileys.local.conf'),
),
'wordblock' => array(
'default' => array(DOKU_INC.'conf/wordblock.conf'),
'local' => array(DOKU_CONF.'wordblock.local.conf'),
),
'acl' => array(
'default' => DOKU_CONF.'acl.auth.php',
),
'plainauth.users' => array(
'default' => DOKU_CONF.'users.auth.php',
),
'plugins' => array( // needed since Angua
'default' => array(DOKU_INC.'conf/plugins.php'),
'local' => array(DOKU_CONF.'plugins.local.php'),
'protected' => array(
DOKU_INC.'conf/plugins.required.php',
DOKU_CONF.'plugins.protected.php',
),
),
'userstyle' => array(
'screen' => DOKU_CONF.'userstyle.css',
'print' => DOKU_CONF.'userprint.css',
'feed' => DOKU_CONF.'userfeed.css',
'all' => DOKU_CONF.'userall.css',
),
'userscript' => array(
'default' => DOKU_CONF.'userscript.js'
),
);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,152 @@
<?php
/**
* Functions used by lib/exe/fetch.php
* (not included by other parts of dokuwiki)
*/
/**
* Set headers and send the file to the client
*
* The $cache parameter influences how long files may be kept in caches, the $public parameter
* influences if this caching may happen in public proxis or in the browser cache only FS#2734
*
* This function will abort the current script when a 304 is sent or file sending is handled
* through x-sendfile
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author Ben Coburn <btcoburn@silicodon.net>
* @param string $file local file to send
* @param string $mime mime type of the file
* @param bool $dl set to true to force a browser download
* @param int $cache remaining cache time in seconds (-1 for $conf['cache'], 0 for no-cache)
* @param bool $public is this a public ressource or a private one?
*/
function sendFile($file, $mime, $dl, $cache, $public = false) {
global $conf;
// send mime headers
header("Content-Type: $mime");
// calculate cache times
if($cache == -1) {
$maxage = max($conf['cachetime'], 3600); // cachetime or one hour
$expires = time() + $maxage;
} else if($cache > 0) {
$maxage = $cache; // given time
$expires = time() + $maxage;
} else { // $cache == 0
$maxage = 0;
$expires = 0; // 1970-01-01
}
// smart http caching headers
if($maxage) {
if($public) {
// cache publically
header('Expires: '.gmdate("D, d M Y H:i:s", $expires).' GMT');
header('Cache-Control: public, proxy-revalidate, no-transform, max-age='.$maxage);
header('Pragma: public');
} else {
// cache in browser
header('Expires: '.gmdate("D, d M Y H:i:s", $expires).' GMT');
header('Cache-Control: private, no-transform, max-age='.$maxage);
header('Pragma: no-cache');
}
} else {
// no cache at all
header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
header('Cache-Control: no-cache, no-transform');
header('Pragma: no-cache');
}
//send important headers first, script stops here if '304 Not Modified' response
$fmtime = @filemtime($file);
http_conditionalRequest($fmtime);
//download or display?
if($dl) {
header('Content-Disposition: attachment; filename="'.utf8_basename($file).'";');
} else {
header('Content-Disposition: inline; filename="'.utf8_basename($file).'";');
}
//use x-sendfile header to pass the delivery to compatible webservers
if(http_sendfile($file)) exit;
// send file contents
$fp = @fopen($file, "rb");
if($fp) {
http_rangeRequest($fp, filesize($file), $mime);
} else {
http_status(500);
print "Could not read $file - bad permissions?";
}
}
/**
* Check for media for preconditions and return correct status code
*
* READ: MEDIA, MIME, EXT, CACHE
* WRITE: MEDIA, FILE, array( STATUS, STATUSMESSAGE )
*
* @author Gerry Weissbach <gerry.w@gammaproduction.de>
* @param string $media reference to the media id
* @param string $file reference to the file variable
* @param string $rev
* @param int $width
* @param int $height
* @return array(STATUS, STATUSMESSAGE)
*/
function checkFileStatus(&$media, &$file, $rev = '', $width=0, $height=0) {
global $MIME, $EXT, $CACHE, $INPUT;
//media to local file
if(media_isexternal($media)) {
//check token for external image and additional for resized and cached images
if(media_get_token($media, $width, $height) !== $INPUT->str('tok')) {
return array(412, 'Precondition Failed');
}
//handle external images
if(strncmp($MIME, 'image/', 6) == 0) $file = media_get_from_URL($media, $EXT, $CACHE);
if(!$file) {
//download failed - redirect to original URL
return array(302, $media);
}
} else {
$media = cleanID($media);
if(empty($media)) {
return array(400, 'Bad request');
}
// check token for resized images
if (($width || $height) && media_get_token($media, $width, $height) !== $INPUT->str('tok')) {
return array(412, 'Precondition Failed');
}
//check permissions (namespace only)
if(auth_quickaclcheck(getNS($media).':X') < AUTH_READ) {
return array(403, 'Forbidden');
}
$file = mediaFN($media, $rev);
}
//check file existance
if(!@file_exists($file)) {
return array(404, 'Not Found');
}
return array(200, null);
}
/**
* Returns the wanted cachetime in seconds
*
* Resolves named constants
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function calc_cache($cache) {
global $conf;
if(strtolower($cache) == 'nocache') return 0; //never cache
if(strtolower($cache) == 'recache') return $conf['cachetime']; //use standard cache
return -1; //cache endless
}

951
sources/inc/form.php Normal file
View file

@ -0,0 +1,951 @@
<?php
/**
* DokuWiki XHTML Form
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
if(!defined('DOKU_INC')) die('meh.');
/**
* Class for creating simple HTML forms.
*
* The forms is built from a list of pseudo-tags (arrays with expected keys).
* Every pseudo-tag must have the key '_elem' set to the name of the element.
* When printed, the form class calls functions named 'form_$type' for each
* element it contains.
*
* Standard practice is for non-attribute keys in a pseudo-element to start
* with '_'. Other keys are HTML attributes that will be included in the element
* tag. That way, the element output functions can pass the pseudo-element
* directly to buildAttributes.
*
* See the form_make* functions later in this file.
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
class Doku_Form {
// Form id attribute
var $params = array();
// Draw a border around form fields.
// Adds <fieldset></fieldset> around the elements
var $_infieldset = false;
// Hidden form fields.
var $_hidden = array();
// Array of pseudo-tags
var $_content = array();
/**
* Constructor
*
* Sets parameters and autoadds a security token. The old calling convention
* with up to four parameters is deprecated, instead the first parameter
* should be an array with parameters.
*
* @param mixed $params Parameters for the HTML form element; Using the
* deprecated calling convention this is the ID
* attribute of the form
* @param string $action (optional, deprecated) submit URL, defaults to
* current page
* @param string $method (optional, deprecated) 'POST' or 'GET', default
* is POST
* @param string $enctype (optional, deprecated) Encoding type of the
* data
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function Doku_Form($params, $action=false, $method=false, $enctype=false) {
if(!is_array($params)) {
$this->params = array('id' => $params);
if ($action !== false) $this->params['action'] = $action;
if ($method !== false) $this->params['method'] = strtolower($method);
if ($enctype !== false) $this->params['enctype'] = $enctype;
} else {
$this->params = $params;
}
if (!isset($this->params['method'])) {
$this->params['method'] = 'post';
} else {
$this->params['method'] = strtolower($this->params['method']);
}
if (!isset($this->params['action'])) {
$this->params['action'] = '';
}
$this->addHidden('sectok', getSecurityToken());
}
/**
* startFieldset
*
* Add <fieldset></fieldset> tags around fields.
* Usually results in a border drawn around the form.
*
* @param string $legend Label that will be printed with the border.
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function startFieldset($legend) {
if ($this->_infieldset) {
$this->addElement(array('_elem'=>'closefieldset'));
}
$this->addElement(array('_elem'=>'openfieldset', '_legend'=>$legend));
$this->_infieldset = true;
}
/**
* endFieldset
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function endFieldset() {
if ($this->_infieldset) {
$this->addElement(array('_elem'=>'closefieldset'));
}
$this->_infieldset = false;
}
/**
* addHidden
*
* Adds a name/value pair as a hidden field.
* The value of the field (but not the name) will be passed to
* formText() before printing.
*
* @param string $name Field name.
* @param string $value Field value. If null, remove a previously added field.
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function addHidden($name, $value) {
if (is_null($value))
unset($this->_hidden[$name]);
else
$this->_hidden[$name] = $value;
}
/**
* addElement
*
* Appends a content element to the form.
* The element can be either a pseudo-tag or string.
* If string, it is printed without escaping special chars. *
*
* @param string $elem Pseudo-tag or string to add to the form.
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function addElement($elem) {
$this->_content[] = $elem;
}
/**
* insertElement
*
* Inserts a content element at a position.
*
* @param string $pos 0-based index where the element will be inserted.
* @param string $elem Pseudo-tag or string to add to the form.
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function insertElement($pos, $elem) {
array_splice($this->_content, $pos, 0, array($elem));
}
/**
* replaceElement
*
* Replace with NULL to remove an element.
*
* @param int $pos 0-based index the element will be placed at.
* @param string $elem Pseudo-tag or string to add to the form.
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function replaceElement($pos, $elem) {
$rep = array();
if (!is_null($elem)) $rep[] = $elem;
array_splice($this->_content, $pos, 1, $rep);
}
/**
* findElementByType
*
* Gets the position of the first of a type of element.
*
* @param string $type Element type to look for.
* @return array pseudo-element if found, false otherwise
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function findElementByType($type) {
foreach ($this->_content as $pos=>$elem) {
if (is_array($elem) && $elem['_elem'] == $type)
return $pos;
}
return false;
}
/**
* findElementById
*
* Gets the position of the element with an ID attribute.
*
* @param string $id ID of the element to find.
* @return array pseudo-element if found, false otherwise
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function findElementById($id) {
foreach ($this->_content as $pos=>$elem) {
if (is_array($elem) && isset($elem['id']) && $elem['id'] == $id)
return $pos;
}
return false;
}
/**
* findElementByAttribute
*
* Gets the position of the first element with a matching attribute value.
*
* @param string $name Attribute name.
* @param string $value Attribute value.
* @return array pseudo-element if found, false otherwise
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function findElementByAttribute($name, $value) {
foreach ($this->_content as $pos=>$elem) {
if (is_array($elem) && isset($elem[$name]) && $elem[$name] == $value)
return $pos;
}
return false;
}
/**
* getElementAt
*
* Returns a reference to the element at a position.
* A position out-of-bounds will return either the
* first (underflow) or last (overflow) element.
*
* @param int $pos 0-based index
* @return arrayreference pseudo-element
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function &getElementAt($pos) {
if ($pos < 0) $pos = count($this->_content) + $pos;
if ($pos < 0) $pos = 0;
if ($pos >= count($this->_content)) $pos = count($this->_content) - 1;
return $this->_content[$pos];
}
/**
* Return the assembled HTML for the form.
*
* Each element in the form will be passed to a function named
* 'form_$type'. The function should return the HTML to be printed.
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function getForm() {
global $lang;
$form = '';
$this->params['accept-charset'] = $lang['encoding'];
$form .= '<form ' . buildAttributes($this->params,false) . '><div class="no">' . DOKU_LF;
if (!empty($this->_hidden)) {
foreach ($this->_hidden as $name=>$value)
$form .= form_hidden(array('name'=>$name, 'value'=>$value));
}
foreach ($this->_content as $element) {
if (is_array($element)) {
$elem_type = $element['_elem'];
if (function_exists('form_'.$elem_type)) {
$form .= call_user_func('form_'.$elem_type, $element).DOKU_LF;
}
} else {
$form .= $element;
}
}
if ($this->_infieldset) $form .= form_closefieldset().DOKU_LF;
$form .= '</div></form>'.DOKU_LF;
return $form;
}
/**
* Print the assembled form
*
* wraps around getForm()
*/
function printForm(){
echo $this->getForm();
}
/**
* Add a radio set
*
* This function adds a set of radio buttons to the form. If $_POST[$name]
* is set, this radio is preselected, else the first radio button.
*
* @param string $name The HTML field name
* @param array $entries An array of entries $value => $caption
*
* @author Adrian Lang <lang@cosmocode.de>
*/
function addRadioSet($name, $entries) {
global $INPUT;
$value = (array_key_exists($INPUT->post->str($name), $entries)) ?
$INPUT->str($name) : key($entries);
foreach($entries as $val => $cap) {
$data = ($value === $val) ? array('checked' => 'checked') : array();
$this->addElement(form_makeRadioField($name, $val, $cap, '', '', $data));
}
}
}
/**
* form_makeTag
*
* Create a form element for a non-specific empty tag.
*
* @param string $tag Tag name.
* @param array $attrs Optional attributes.
* @return array pseudo-tag
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_makeTag($tag, $attrs=array()) {
$elem = array('_elem'=>'tag', '_tag'=>$tag);
return array_merge($elem, $attrs);
}
/**
* form_makeOpenTag
*
* Create a form element for a non-specific opening tag.
* Remember to put a matching close tag after this as well.
*
* @param string $tag Tag name.
* @param array $attrs Optional attributes.
* @return array pseudo-tag
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_makeOpenTag($tag, $attrs=array()) {
$elem = array('_elem'=>'opentag', '_tag'=>$tag);
return array_merge($elem, $attrs);
}
/**
* form_makeCloseTag
*
* Create a form element for a non-specific closing tag.
* Careless use of this will result in invalid XHTML.
*
* @param string $tag Tag name.
* @return array pseudo-tag
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_makeCloseTag($tag) {
return array('_elem'=>'closetag', '_tag'=>$tag);
}
/**
* form_makeWikiText
*
* Create a form element for a textarea containing wiki text.
* Only one wikitext element is allowed on a page. It will have
* a name of 'wikitext' and id 'wiki__text'. The text will
* be passed to formText() before printing.
*
* @param string $text Text to fill the field with.
* @param array $attrs Optional attributes.
* @return array pseudo-tag
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_makeWikiText($text, $attrs=array()) {
$elem = array('_elem'=>'wikitext', '_text'=>$text,
'class'=>'edit', 'cols'=>'80', 'rows'=>'10');
return array_merge($elem, $attrs);
}
/**
* form_makeButton
*
* Create a form element for an action button.
* A title will automatically be generated using the value and
* accesskey attributes, unless you provide one.
*
* @param string $type Type attribute. 'submit' or 'cancel'
* @param string $act Wiki action of the button, will be used as the do= parameter
* @param string $value (optional) Displayed label. Uses $act if not provided.
* @param array $attrs Optional attributes.
* @return array pseudo-tag
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_makeButton($type, $act, $value='', $attrs=array()) {
if ($value == '') $value = $act;
$elem = array('_elem'=>'button', 'type'=>$type, '_action'=>$act,
'value'=>$value, 'class'=>'button');
if (!empty($attrs['accesskey']) && empty($attrs['title'])) {
$attrs['title'] = $value . ' ['.strtoupper($attrs['accesskey']).']';
}
return array_merge($elem, $attrs);
}
/**
* form_makeField
*
* Create a form element for a labelled input element.
* The label text will be printed before the input.
*
* @param string $type Type attribute of input.
* @param string $name Name attribute of the input.
* @param string $value (optional) Default value.
* @param string $class Class attribute of the label. If this is 'block',
* then a line break will be added after the field.
* @param string $label Label that will be printed before the input.
* @param string $id ID attribute of the input. If set, the label will
* reference it with a 'for' attribute.
* @param array $attrs Optional attributes.
* @return array pseudo-tag
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_makeField($type, $name, $value='', $label=null, $id='', $class='', $attrs=array()) {
if (is_null($label)) $label = $name;
$elem = array('_elem'=>'field', '_text'=>$label, '_class'=>$class,
'type'=>$type, 'id'=>$id, 'name'=>$name, 'value'=>$value);
return array_merge($elem, $attrs);
}
/**
* form_makeFieldRight
*
* Create a form element for a labelled input element.
* The label text will be printed after the input.
*
* @see form_makeField
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_makeFieldRight($type, $name, $value='', $label=null, $id='', $class='', $attrs=array()) {
if (is_null($label)) $label = $name;
$elem = array('_elem'=>'fieldright', '_text'=>$label, '_class'=>$class,
'type'=>$type, 'id'=>$id, 'name'=>$name, 'value'=>$value);
return array_merge($elem, $attrs);
}
/**
* form_makeTextField
*
* Create a form element for a text input element with label.
*
* @see form_makeField
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_makeTextField($name, $value='', $label=null, $id='', $class='', $attrs=array()) {
if (is_null($label)) $label = $name;
$elem = array('_elem'=>'textfield', '_text'=>$label, '_class'=>$class,
'id'=>$id, 'name'=>$name, 'value'=>$value, 'class'=>'edit');
return array_merge($elem, $attrs);
}
/**
* form_makePasswordField
*
* Create a form element for a password input element with label.
* Password elements have no default value, for obvious reasons.
*
* @see form_makeField
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_makePasswordField($name, $label=null, $id='', $class='', $attrs=array()) {
if (is_null($label)) $label = $name;
$elem = array('_elem'=>'passwordfield', '_text'=>$label, '_class'=>$class,
'id'=>$id, 'name'=>$name, 'class'=>'edit');
return array_merge($elem, $attrs);
}
/**
* form_makeFileField
*
* Create a form element for a file input element with label
*
* @see form_makeField
* @author Michael Klier <chi@chimeric.de>
*/
function form_makeFileField($name, $label=null, $id='', $class='', $attrs=array()) {
if (is_null($label)) $label = $name;
$elem = array('_elem'=>'filefield', '_text'=>$label, '_class'=>$class,
'id'=>$id, 'name'=>$name, 'class'=>'edit');
return array_merge($elem, $attrs);
}
/**
* form_makeCheckboxField
*
* Create a form element for a checkbox input element with label.
* If $value is an array, a hidden field with the same name and the value
* $value[1] is constructed as well.
*
* @see form_makeFieldRight
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_makeCheckboxField($name, $value='1', $label=null, $id='', $class='', $attrs=array()) {
if (is_null($label)) $label = $name;
if (is_null($value) || $value=='') $value='0';
$elem = array('_elem'=>'checkboxfield', '_text'=>$label, '_class'=>$class,
'id'=>$id, 'name'=>$name, 'value'=>$value);
return array_merge($elem, $attrs);
}
/**
* form_makeRadioField
*
* Create a form element for a radio button input element with label.
*
* @see form_makeFieldRight
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_makeRadioField($name, $value='1', $label=null, $id='', $class='', $attrs=array()) {
if (is_null($label)) $label = $name;
if (is_null($value) || $value=='') $value='0';
$elem = array('_elem'=>'radiofield', '_text'=>$label, '_class'=>$class,
'id'=>$id, 'name'=>$name, 'value'=>$value);
return array_merge($elem, $attrs);
}
/**
* form_makeMenuField
*
* Create a form element for a drop-down menu with label.
* The list of values can be strings, arrays of (value,text),
* or an associative array with the values as keys and labels as values.
* An item is selected by supplying its value or integer index.
* If the list of values is an associative array, the selected item must be
* a string.
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_makeMenuField($name, $values, $selected='', $label=null, $id='', $class='', $attrs=array()) {
if (is_null($label)) $label = $name;
$options = array();
reset($values);
// FIXME: php doesn't know the difference between a string and an integer
if (is_string(key($values))) {
foreach ($values as $val=>$text) {
$options[] = array($val,$text, (!is_null($selected) && $val==$selected));
}
} else {
if (is_integer($selected)) $selected = $values[$selected];
foreach ($values as $val) {
if (is_array($val))
@list($val,$text) = $val;
else
$text = null;
$options[] = array($val,$text,$val===$selected);
}
}
$elem = array('_elem'=>'menufield', '_options'=>$options, '_text'=>$label, '_class'=>$class,
'id'=>$id, 'name'=>$name);
return array_merge($elem, $attrs);
}
/**
* form_makeListboxField
*
* Create a form element for a list box with label.
* The list of values can be strings, arrays of (value,text),
* or an associative array with the values as keys and labels as values.
* Items are selected by supplying its value or an array of values.
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_makeListboxField($name, $values, $selected='', $label=null, $id='', $class='', $attrs=array()) {
if (is_null($label)) $label = $name;
$options = array();
reset($values);
if (is_null($selected) || $selected == '')
$selected = array();
elseif (!is_array($selected))
$selected = array($selected);
// FIXME: php doesn't know the difference between a string and an integer
if (is_string(key($values))) {
foreach ($values as $val=>$text) {
$options[] = array($val,$text,in_array($val,$selected));
}
} else {
foreach ($values as $val) {
if (is_array($val))
@list($val,$text) = $val;
else
$text = null;
$options[] = array($val,$text,in_array($val,$selected));
}
}
$elem = array('_elem'=>'listboxfield', '_options'=>$options, '_text'=>$label, '_class'=>$class,
'id'=>$id, 'name'=>$name);
return array_merge($elem, $attrs);
}
/**
* form_tag
*
* Print the HTML for a generic empty tag.
* Requires '_tag' key with name of the tag.
* Attributes are passed to buildAttributes()
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_tag($attrs) {
return '<'.$attrs['_tag'].' '.buildAttributes($attrs,true).'/>';
}
/**
* form_opentag
*
* Print the HTML for a generic opening tag.
* Requires '_tag' key with name of the tag.
* Attributes are passed to buildAttributes()
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_opentag($attrs) {
return '<'.$attrs['_tag'].' '.buildAttributes($attrs,true).'>';
}
/**
* form_closetag
*
* Print the HTML for a generic closing tag.
* Requires '_tag' key with name of the tag.
* There are no attributes.
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_closetag($attrs) {
return '</'.$attrs['_tag'].'>';
}
/**
* form_openfieldset
*
* Print the HTML for an opening fieldset tag.
* Uses the '_legend' key.
* Attributes are passed to buildAttributes()
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_openfieldset($attrs) {
$s = '<fieldset '.buildAttributes($attrs,true).'>';
if (!is_null($attrs['_legend'])) $s .= '<legend>'.$attrs['_legend'].'</legend>';
return $s;
}
/**
* form_closefieldset
*
* Print the HTML for a closing fieldset tag.
* There are no attributes.
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_closefieldset() {
return '</fieldset>';
}
/**
* form_hidden
*
* Print the HTML for a hidden input element.
* Uses only 'name' and 'value' attributes.
* Value is passed to formText()
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_hidden($attrs) {
return '<input type="hidden" name="'.$attrs['name'].'" value="'.formText($attrs['value']).'" />';
}
/**
* form_wikitext
*
* Print the HTML for the wiki textarea.
* Requires '_text' with default text of the field.
* Text will be passed to formText(), attributes to buildAttributes()
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_wikitext($attrs) {
// mandatory attributes
unset($attrs['name']);
unset($attrs['id']);
return '<textarea name="wikitext" id="wiki__text" dir="auto" '
.buildAttributes($attrs,true).'>'.DOKU_LF
.formText($attrs['_text'])
.'</textarea>';
}
/**
* form_button
*
* Print the HTML for a form button.
* If '_action' is set, the button name will be "do[_action]".
* Other attributes are passed to buildAttributes()
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_button($attrs) {
$p = (!empty($attrs['_action'])) ? 'name="do['.$attrs['_action'].']" ' : '';
return '<input '.$p.buildAttributes($attrs,true).' />';
}
/**
* form_field
*
* Print the HTML for a form input field.
* _class : class attribute used on the label tag
* _text : Text to display before the input. Not escaped.
* Other attributes are passed to buildAttributes() for the input tag.
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_field($attrs) {
$s = '<label';
if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
$s .= '><span>'.$attrs['_text'].'</span>';
$s .= ' <input '.buildAttributes($attrs,true).' /></label>';
if (preg_match('/(^| )block($| )/', $attrs['_class']))
$s .= '<br />';
return $s;
}
/**
* form_fieldright
*
* Print the HTML for a form input field. (right-aligned)
* _class : class attribute used on the label tag
* _text : Text to display after the input. Not escaped.
* Other attributes are passed to buildAttributes() for the input tag.
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_fieldright($attrs) {
$s = '<label';
if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
$s .= '><input '.buildAttributes($attrs,true).' />';
$s .= ' <span>'.$attrs['_text'].'</span></label>';
if (preg_match('/(^| )block($| )/', $attrs['_class']))
$s .= '<br />';
return $s;
}
/**
* form_textfield
*
* Print the HTML for a text input field.
* _class : class attribute used on the label tag
* _text : Text to display before the input. Not escaped.
* Other attributes are passed to buildAttributes() for the input tag.
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_textfield($attrs) {
// mandatory attributes
unset($attrs['type']);
$s = '<label';
if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
$s .= '><span>'.$attrs['_text'].'</span> ';
$s .= '<input type="text" '.buildAttributes($attrs,true).' /></label>';
if (preg_match('/(^| )block($| )/', $attrs['_class']))
$s .= '<br />';
return $s;
}
/**
* form_passwordfield
*
* Print the HTML for a password input field.
* _class : class attribute used on the label tag
* _text : Text to display before the input. Not escaped.
* Other attributes are passed to buildAttributes() for the input tag.
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_passwordfield($attrs) {
// mandatory attributes
unset($attrs['type']);
$s = '<label';
if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
$s .= '><span>'.$attrs['_text'].'</span> ';
$s .= '<input type="password" '.buildAttributes($attrs,true).' /></label>';
if (preg_match('/(^| )block($| )/', $attrs['_class']))
$s .= '<br />';
return $s;
}
/**
* form_filefield
*
* Print the HTML for a file input field.
* _class : class attribute used on the label tag
* _text : Text to display before the input. Not escaped
* _maxlength : Allowed size in byte
* _accept : Accepted mime-type
* Other attributes are passed to buildAttributes() for the input tag
*
* @author Michael Klier <chi@chimeric.de>
*/
function form_filefield($attrs) {
$s = '<label';
if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
$s .= '><span>'.$attrs['_text'].'</span> ';
$s .= '<input type="file" '.buildAttributes($attrs,true);
if (!empty($attrs['_maxlength'])) $s .= ' maxlength="'.$attrs['_maxlength'].'"';
if (!empty($attrs['_accept'])) $s .= ' accept="'.$attrs['_accept'].'"';
$s .= ' /></label>';
if (preg_match('/(^| )block($| )/', $attrs['_class']))
$s .= '<br />';
return $s;
}
/**
* form_checkboxfield
*
* Print the HTML for a checkbox input field.
* _class : class attribute used on the label tag
* _text : Text to display after the input. Not escaped.
* Other attributes are passed to buildAttributes() for the input tag.
* If value is an array, a hidden field with the same name and the value
* $attrs['value'][1] is constructed as well.
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_checkboxfield($attrs) {
// mandatory attributes
unset($attrs['type']);
$s = '<label';
if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
$s .= '>';
if (is_array($attrs['value'])) {
echo '<input type="hidden" name="' . hsc($attrs['name']) .'"'
. ' value="' . hsc($attrs['value'][1]) . '" />';
$attrs['value'] = $attrs['value'][0];
}
$s .= '<input type="checkbox" '.buildAttributes($attrs,true).' />';
$s .= ' <span>'.$attrs['_text'].'</span></label>';
if (preg_match('/(^| )block($| )/', $attrs['_class']))
$s .= '<br />';
return $s;
}
/**
* form_radiofield
*
* Print the HTML for a radio button input field.
* _class : class attribute used on the label tag
* _text : Text to display after the input. Not escaped.
* Other attributes are passed to buildAttributes() for the input tag.
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_radiofield($attrs) {
// mandatory attributes
unset($attrs['type']);
$s = '<label';
if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
$s .= '><input type="radio" '.buildAttributes($attrs,true).' />';
$s .= ' <span>'.$attrs['_text'].'</span></label>';
if (preg_match('/(^| )block($| )/', $attrs['_class']))
$s .= '<br />';
return $s;
}
/**
* form_menufield
*
* Print the HTML for a drop-down menu.
* _options : Array of (value,text,selected) for the menu.
* Text can be omitted. Text and value are passed to formText()
* Only one item can be selected.
* _class : class attribute used on the label tag
* _text : Text to display before the menu. Not escaped.
* Other attributes are passed to buildAttributes() for the input tag.
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_menufield($attrs) {
$attrs['size'] = '1';
$s = '<label';
if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
$s .= '><span>'.$attrs['_text'].'</span>';
$s .= ' <select '.buildAttributes($attrs,true).'>'.DOKU_LF;
if (!empty($attrs['_options'])) {
$selected = false;
$cnt = count($attrs['_options']);
for($n=0; $n < $cnt; $n++){
@list($value,$text,$select) = $attrs['_options'][$n];
$p = '';
if (!is_null($text))
$p .= ' value="'.formText($value).'"';
else
$text = $value;
if (!empty($select) && !$selected) {
$p .= ' selected="selected"';
$selected = true;
}
$s .= '<option'.$p.'>'.formText($text).'</option>';
}
} else {
$s .= '<option></option>';
}
$s .= DOKU_LF.'</select></label>';
if (preg_match('/(^| )block($| )/', $attrs['_class']))
$s .= '<br />';
return $s;
}
/**
* form_listboxfield
*
* Print the HTML for a list box.
* _options : Array of (value,text,selected) for the list.
* Text can be omitted. Text and value are passed to formText()
* _class : class attribute used on the label tag
* _text : Text to display before the menu. Not escaped.
* Other attributes are passed to buildAttributes() for the input tag.
*
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function form_listboxfield($attrs) {
$s = '<label';
if ($attrs['_class']) $s .= ' class="'.$attrs['_class'].'"';
if (!empty($attrs['id'])) $s .= ' for="'.$attrs['id'].'"';
$s .= '><span>'.$attrs['_text'].'</span> ';
$s .= '<select '.buildAttributes($attrs,true).'>'.DOKU_LF;
if (!empty($attrs['_options'])) {
foreach ($attrs['_options'] as $opt) {
@list($value,$text,$select) = $opt;
$p = '';
if(is_null($text)) $text = $value;
$p .= ' value="'.formText($value).'"';
if (!empty($select)) $p .= ' selected="selected"';
$s .= '<option'.$p.'>'.formText($text).'</option>';
}
} else {
$s .= '<option></option>';
}
$s .= DOKU_LF.'</select></label>';
if (preg_match('/(^| )block($| )/', $attrs['_class']))
$s .= '<br />';
return $s;
}

756
sources/inc/fulltext.php Normal file
View file

@ -0,0 +1,756 @@
<?php
/**
* DokuWiki fulltextsearch functions using the index
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Andreas Gohr <andi@splitbrain.org>
*/
if(!defined('DOKU_INC')) die('meh.');
/**
* create snippets for the first few results only
*/
if(!defined('FT_SNIPPET_NUMBER')) define('FT_SNIPPET_NUMBER',15);
/**
* The fulltext search
*
* Returns a list of matching documents for the given query
*
* refactored into ft_pageSearch(), _ft_pageSearch() and trigger_event()
*
*/
function ft_pageSearch($query,&$highlight){
$data['query'] = $query;
$data['highlight'] =& $highlight;
return trigger_event('SEARCH_QUERY_FULLPAGE', $data, '_ft_pageSearch');
}
/**
* Returns a list of matching documents for the given query
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author Kazutaka Miyasaka <kazmiya@gmail.com>
*/
function _ft_pageSearch(&$data) {
$Indexer = idx_get_indexer();
// parse the given query
$q = ft_queryParser($Indexer, $data['query']);
$data['highlight'] = $q['highlight'];
if (empty($q['parsed_ary'])) return array();
// lookup all words found in the query
$lookup = $Indexer->lookup($q['words']);
// get all pages in this dokuwiki site (!: includes nonexistent pages)
$pages_all = array();
foreach ($Indexer->getPages() as $id) {
$pages_all[$id] = 0; // base: 0 hit
}
// process the query
$stack = array();
foreach ($q['parsed_ary'] as $token) {
switch (substr($token, 0, 3)) {
case 'W+:':
case 'W-:':
case 'W_:': // word
$word = substr($token, 3);
$stack[] = (array) $lookup[$word];
break;
case 'P+:':
case 'P-:': // phrase
$phrase = substr($token, 3);
// since phrases are always parsed as ((W1)(W2)...(P)),
// the end($stack) always points the pages that contain
// all words in this phrase
$pages = end($stack);
$pages_matched = array();
foreach(array_keys($pages) as $id){
$text = utf8_strtolower(rawWiki($id));
if (strpos($text, $phrase) !== false) {
$pages_matched[$id] = 0; // phrase: always 0 hit
}
}
$stack[] = $pages_matched;
break;
case 'N+:':
case 'N-:': // namespace
$ns = substr($token, 3);
$pages_matched = array();
foreach (array_keys($pages_all) as $id) {
if (strpos($id, $ns) === 0) {
$pages_matched[$id] = 0; // namespace: always 0 hit
}
}
$stack[] = $pages_matched;
break;
case 'AND': // and operation
list($pages1, $pages2) = array_splice($stack, -2);
$stack[] = ft_resultCombine(array($pages1, $pages2));
break;
case 'OR': // or operation
list($pages1, $pages2) = array_splice($stack, -2);
$stack[] = ft_resultUnite(array($pages1, $pages2));
break;
case 'NOT': // not operation (unary)
$pages = array_pop($stack);
$stack[] = ft_resultComplement(array($pages_all, $pages));
break;
}
}
$docs = array_pop($stack);
if (empty($docs)) return array();
// check: settings, acls, existence
foreach (array_keys($docs) as $id) {
if (isHiddenPage($id) || auth_quickaclcheck($id) < AUTH_READ || !page_exists($id, '', false)) {
unset($docs[$id]);
}
}
// sort docs by count
arsort($docs);
return $docs;
}
/**
* Returns the backlinks for a given page
*
* Uses the metadata index.
*
* @param string $id The id for which links shall be returned
* @param bool $ignore_perms Ignore the fact that pages are hidden or read-protected
* @return array The pages that contain links to the given page
*/
function ft_backlinks($id, $ignore_perms = false){
$result = idx_get_indexer()->lookupKey('relation_references', $id);
if(!count($result)) return $result;
// check ACL permissions
foreach(array_keys($result) as $idx){
if(($ignore_perms !== true && (
isHiddenPage($result[$idx]) || auth_quickaclcheck($result[$idx]) < AUTH_READ
)) || !page_exists($result[$idx], '', false)){
unset($result[$idx]);
}
}
sort($result);
return $result;
}
/**
* Returns the pages that use a given media file
*
* Uses the relation media metadata property and the metadata index.
*
* Note that before 2013-07-31 the second parameter was the maximum number of results and
* permissions were ignored. That's why the parameter is now checked to be explicitely set
* to true (with type bool) in order to be compatible with older uses of the function.
*
* @param string $id The media id to look for
* @param bool $ignore_perms Ignore hidden pages and acls (optional, default: false)
* @return array A list of pages that use the given media file
*/
function ft_mediause($id, $ignore_perms = false){
$result = idx_get_indexer()->lookupKey('relation_media', $id);
if(!count($result)) return $result;
// check ACL permissions
foreach(array_keys($result) as $idx){
if(($ignore_perms !== true && (
isHiddenPage($result[$idx]) || auth_quickaclcheck($result[$idx]) < AUTH_READ
)) || !page_exists($result[$idx], '', false)){
unset($result[$idx]);
}
}
sort($result);
return $result;
}
/**
* Quicksearch for pagenames
*
* By default it only matches the pagename and ignores the
* namespace. This can be changed with the second parameter.
* The third parameter allows to search in titles as well.
*
* The function always returns titles as well
*
* @triggers SEARCH_QUERY_PAGELOOKUP
* @author Andreas Gohr <andi@splitbrain.org>
* @author Adrian Lang <lang@cosmocode.de>
*/
function ft_pageLookup($id, $in_ns=false, $in_title=false){
$data = compact('id', 'in_ns', 'in_title');
$data['has_titles'] = true; // for plugin backward compatibility check
return trigger_event('SEARCH_QUERY_PAGELOOKUP', $data, '_ft_pageLookup');
}
function _ft_pageLookup(&$data){
// split out original parameters
$id = $data['id'];
if (preg_match('/(?:^| )@(\w+)/', $id, $matches)) {
$ns = cleanID($matches[1]) . ':';
$id = str_replace($matches[0], '', $id);
}
$in_ns = $data['in_ns'];
$in_title = $data['in_title'];
$cleaned = cleanID($id);
$Indexer = idx_get_indexer();
$page_idx = $Indexer->getPages();
$pages = array();
if ($id !== '' && $cleaned !== '') {
foreach ($page_idx as $p_id) {
if ((strpos($in_ns ? $p_id : noNSorNS($p_id), $cleaned) !== false)) {
if (!isset($pages[$p_id]))
$pages[$p_id] = p_get_first_heading($p_id, METADATA_DONT_RENDER);
}
}
if ($in_title) {
foreach ($Indexer->lookupKey('title', $id, '_ft_pageLookupTitleCompare') as $p_id) {
if (!isset($pages[$p_id]))
$pages[$p_id] = p_get_first_heading($p_id, METADATA_DONT_RENDER);
}
}
}
if (isset($ns)) {
foreach (array_keys($pages) as $p_id) {
if (strpos($p_id, $ns) !== 0) {
unset($pages[$p_id]);
}
}
}
// discard hidden pages
// discard nonexistent pages
// check ACL permissions
foreach(array_keys($pages) as $idx){
if(!isVisiblePage($idx) || !page_exists($idx) ||
auth_quickaclcheck($idx) < AUTH_READ) {
unset($pages[$idx]);
}
}
uksort($pages,'ft_pagesorter');
return $pages;
}
/**
* Tiny helper function for comparing the searched title with the title
* from the search index. This function is a wrapper around stripos with
* adapted argument order and return value.
*/
function _ft_pageLookupTitleCompare($search, $title) {
return stripos($title, $search) !== false;
}
/**
* Sort pages based on their namespace level first, then on their string
* values. This makes higher hierarchy pages rank higher than lower hierarchy
* pages.
*/
function ft_pagesorter($a, $b){
$ac = count(explode(':',$a));
$bc = count(explode(':',$b));
if($ac < $bc){
return -1;
}elseif($ac > $bc){
return 1;
}
return strcmp ($a,$b);
}
/**
* Creates a snippet extract
*
* @author Andreas Gohr <andi@splitbrain.org>
* @triggers FULLTEXT_SNIPPET_CREATE
*/
function ft_snippet($id,$highlight){
$text = rawWiki($id);
$text = str_replace("\xC2\xAD",'',$text); // remove soft-hyphens
$evdata = array(
'id' => $id,
'text' => &$text,
'highlight' => &$highlight,
'snippet' => '',
);
$evt = new Doku_Event('FULLTEXT_SNIPPET_CREATE',$evdata);
if ($evt->advise_before()) {
$match = array();
$snippets = array();
$utf8_offset = $offset = $end = 0;
$len = utf8_strlen($text);
// build a regexp from the phrases to highlight
$re1 = '('.join('|',array_map('ft_snippet_re_preprocess', array_map('preg_quote_cb',array_filter((array) $highlight)))).')';
$re2 = "$re1.{0,75}(?!\\1)$re1";
$re3 = "$re1.{0,45}(?!\\1)$re1.{0,45}(?!\\1)(?!\\2)$re1";
for ($cnt=4; $cnt--;) {
if (0) {
} else if (preg_match('/'.$re3.'/iu',$text,$match,PREG_OFFSET_CAPTURE,$offset)) {
} else if (preg_match('/'.$re2.'/iu',$text,$match,PREG_OFFSET_CAPTURE,$offset)) {
} else if (preg_match('/'.$re1.'/iu',$text,$match,PREG_OFFSET_CAPTURE,$offset)) {
} else {
break;
}
list($str,$idx) = $match[0];
// convert $idx (a byte offset) into a utf8 character offset
$utf8_idx = utf8_strlen(substr($text,0,$idx));
$utf8_len = utf8_strlen($str);
// establish context, 100 bytes surrounding the match string
// first look to see if we can go 100 either side,
// then drop to 50 adding any excess if the other side can't go to 50,
$pre = min($utf8_idx-$utf8_offset,100);
$post = min($len-$utf8_idx-$utf8_len,100);
if ($pre>50 && $post>50) {
$pre = $post = 50;
} else if ($pre>50) {
$pre = min($pre,100-$post);
} else if ($post>50) {
$post = min($post, 100-$pre);
} else {
// both are less than 50, means the context is the whole string
// make it so and break out of this loop - there is no need for the
// complex snippet calculations
$snippets = array($text);
break;
}
// establish context start and end points, try to append to previous
// context if possible
$start = $utf8_idx - $pre;
$append = ($start < $end) ? $end : false; // still the end of the previous context snippet
$end = $utf8_idx + $utf8_len + $post; // now set it to the end of this context
if ($append) {
$snippets[count($snippets)-1] .= utf8_substr($text,$append,$end-$append);
} else {
$snippets[] = utf8_substr($text,$start,$end-$start);
}
// set $offset for next match attempt
// substract strlen to avoid splitting a potential search success,
// this is an approximation as the search pattern may match strings
// of varying length and it will fail if the context snippet
// boundary breaks a matching string longer than the current match
$utf8_offset = $utf8_idx + $post;
$offset = $idx + strlen(utf8_substr($text,$utf8_idx,$post));
$offset = utf8_correctIdx($text,$offset);
}
$m = "\1";
$snippets = preg_replace('/'.$re1.'/iu',$m.'$1'.$m,$snippets);
$snippet = preg_replace('/'.$m.'([^'.$m.']*?)'.$m.'/iu','<strong class="search_hit">$1</strong>',hsc(join('... ',$snippets)));
$evdata['snippet'] = $snippet;
}
$evt->advise_after();
unset($evt);
return $evdata['snippet'];
}
/**
* Wraps a search term in regex boundary checks.
*/
function ft_snippet_re_preprocess($term) {
// do not process asian terms where word boundaries are not explicit
if(preg_match('/'.IDX_ASIAN.'/u',$term)){
return $term;
}
if (UTF8_PROPERTYSUPPORT) {
// unicode word boundaries
// see http://stackoverflow.com/a/2449017/172068
$BL = '(?<!\pL)';
$BR = '(?!\pL)';
} else {
// not as correct as above, but at least won't break
$BL = '\b';
$BR = '\b';
}
if(substr($term,0,2) == '\\*'){
$term = substr($term,2);
}else{
$term = $BL.$term;
}
if(substr($term,-2,2) == '\\*'){
$term = substr($term,0,-2);
}else{
$term = $term.$BR;
}
if($term == $BL || $term == $BR || $term == $BL.$BR) $term = '';
return $term;
}
/**
* Combine found documents and sum up their scores
*
* This function is used to combine searched words with a logical
* AND. Only documents available in all arrays are returned.
*
* based upon PEAR's PHP_Compat function for array_intersect_key()
*
* @param array $args An array of page arrays
*/
function ft_resultCombine($args){
$array_count = count($args);
if($array_count == 1){
return $args[0];
}
$result = array();
if ($array_count > 1) {
foreach ($args[0] as $key => $value) {
$result[$key] = $value;
for ($i = 1; $i !== $array_count; $i++) {
if (!isset($args[$i][$key])) {
unset($result[$key]);
break;
}
$result[$key] += $args[$i][$key];
}
}
}
return $result;
}
/**
* Unites found documents and sum up their scores
*
* based upon ft_resultCombine() function
*
* @param array $args An array of page arrays
* @author Kazutaka Miyasaka <kazmiya@gmail.com>
*/
function ft_resultUnite($args) {
$array_count = count($args);
if ($array_count === 1) {
return $args[0];
}
$result = $args[0];
for ($i = 1; $i !== $array_count; $i++) {
foreach (array_keys($args[$i]) as $id) {
$result[$id] += $args[$i][$id];
}
}
return $result;
}
/**
* Computes the difference of documents using page id for comparison
*
* nearly identical to PHP5's array_diff_key()
*
* @param array $args An array of page arrays
* @author Kazutaka Miyasaka <kazmiya@gmail.com>
*/
function ft_resultComplement($args) {
$array_count = count($args);
if ($array_count === 1) {
return $args[0];
}
$result = $args[0];
foreach (array_keys($result) as $id) {
for ($i = 1; $i !== $array_count; $i++) {
if (isset($args[$i][$id])) unset($result[$id]);
}
}
return $result;
}
/**
* Parses a search query and builds an array of search formulas
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author Kazutaka Miyasaka <kazmiya@gmail.com>
*/
function ft_queryParser($Indexer, $query){
/**
* parse a search query and transform it into intermediate representation
*
* in a search query, you can use the following expressions:
*
* words:
* include
* -exclude
* phrases:
* "phrase to be included"
* -"phrase you want to exclude"
* namespaces:
* @include:namespace (or ns:include:namespace)
* ^exclude:namespace (or -ns:exclude:namespace)
* groups:
* ()
* -()
* operators:
* and ('and' is the default operator: you can always omit this)
* or (or pipe symbol '|', lower precedence than 'and')
*
* e.g. a query [ aa "bb cc" @dd:ee ] means "search pages which contain
* a word 'aa', a phrase 'bb cc' and are within a namespace 'dd:ee'".
* this query is equivalent to [ -(-aa or -"bb cc" or -ns:dd:ee) ]
* as long as you don't mind hit counts.
*
* intermediate representation consists of the following parts:
*
* ( ) - group
* AND - logical and
* OR - logical or
* NOT - logical not
* W+:, W-:, W_: - word (underscore: no need to highlight)
* P+:, P-: - phrase (minus sign: logically in NOT group)
* N+:, N-: - namespace
*/
$parsed_query = '';
$parens_level = 0;
$terms = preg_split('/(-?".*?")/u', utf8_strtolower($query), -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach ($terms as $term) {
$parsed = '';
if (preg_match('/^(-?)"(.+)"$/u', $term, $matches)) {
// phrase-include and phrase-exclude
$not = $matches[1] ? 'NOT' : '';
$parsed = $not.ft_termParser($Indexer, $matches[2], false, true);
} else {
// fix incomplete phrase
$term = str_replace('"', ' ', $term);
// fix parentheses
$term = str_replace(')' , ' ) ', $term);
$term = str_replace('(' , ' ( ', $term);
$term = str_replace('- (', ' -(', $term);
// treat pipe symbols as 'OR' operators
$term = str_replace('|', ' or ', $term);
// treat ideographic spaces (U+3000) as search term separators
// FIXME: some more separators?
$term = preg_replace('/[ \x{3000}]+/u', ' ', $term);
$term = trim($term);
if ($term === '') continue;
$tokens = explode(' ', $term);
foreach ($tokens as $token) {
if ($token === '(') {
// parenthesis-include-open
$parsed .= '(';
++$parens_level;
} elseif ($token === '-(') {
// parenthesis-exclude-open
$parsed .= 'NOT(';
++$parens_level;
} elseif ($token === ')') {
// parenthesis-any-close
if ($parens_level === 0) continue;
$parsed .= ')';
$parens_level--;
} elseif ($token === 'and') {
// logical-and (do nothing)
} elseif ($token === 'or') {
// logical-or
$parsed .= 'OR';
} elseif (preg_match('/^(?:\^|-ns:)(.+)$/u', $token, $matches)) {
// namespace-exclude
$parsed .= 'NOT(N+:'.$matches[1].')';
} elseif (preg_match('/^(?:@|ns:)(.+)$/u', $token, $matches)) {
// namespace-include
$parsed .= '(N+:'.$matches[1].')';
} elseif (preg_match('/^-(.+)$/', $token, $matches)) {
// word-exclude
$parsed .= 'NOT('.ft_termParser($Indexer, $matches[1]).')';
} else {
// word-include
$parsed .= ft_termParser($Indexer, $token);
}
}
}
$parsed_query .= $parsed;
}
// cleanup (very sensitive)
$parsed_query .= str_repeat(')', $parens_level);
do {
$parsed_query_old = $parsed_query;
$parsed_query = preg_replace('/(NOT)?\(\)/u', '', $parsed_query);
} while ($parsed_query !== $parsed_query_old);
$parsed_query = preg_replace('/(NOT|OR)+\)/u', ')' , $parsed_query);
$parsed_query = preg_replace('/(OR)+/u' , 'OR' , $parsed_query);
$parsed_query = preg_replace('/\(OR/u' , '(' , $parsed_query);
$parsed_query = preg_replace('/^OR|OR$/u' , '' , $parsed_query);
$parsed_query = preg_replace('/\)(NOT)?\(/u' , ')AND$1(', $parsed_query);
// adjustment: make highlightings right
$parens_level = 0;
$notgrp_levels = array();
$parsed_query_new = '';
$tokens = preg_split('/(NOT\(|[()])/u', $parsed_query, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach ($tokens as $token) {
if ($token === 'NOT(') {
$notgrp_levels[] = ++$parens_level;
} elseif ($token === '(') {
++$parens_level;
} elseif ($token === ')') {
if ($parens_level-- === end($notgrp_levels)) array_pop($notgrp_levels);
} elseif (count($notgrp_levels) % 2 === 1) {
// turn highlight-flag off if terms are logically in "NOT" group
$token = preg_replace('/([WPN])\+\:/u', '$1-:', $token);
}
$parsed_query_new .= $token;
}
$parsed_query = $parsed_query_new;
/**
* convert infix notation string into postfix (Reverse Polish notation) array
* by Shunting-yard algorithm
*
* see: http://en.wikipedia.org/wiki/Reverse_Polish_notation
* see: http://en.wikipedia.org/wiki/Shunting-yard_algorithm
*/
$parsed_ary = array();
$ope_stack = array();
$ope_precedence = array(')' => 1, 'OR' => 2, 'AND' => 3, 'NOT' => 4, '(' => 5);
$ope_regex = '/([()]|OR|AND|NOT)/u';
$tokens = preg_split($ope_regex, $parsed_query, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach ($tokens as $token) {
if (preg_match($ope_regex, $token)) {
// operator
$last_ope = end($ope_stack);
while ($ope_precedence[$token] <= $ope_precedence[$last_ope] && $last_ope != '(') {
$parsed_ary[] = array_pop($ope_stack);
$last_ope = end($ope_stack);
}
if ($token == ')') {
array_pop($ope_stack); // this array_pop always deletes '('
} else {
$ope_stack[] = $token;
}
} else {
// operand
$token_decoded = str_replace(array('OP', 'CP'), array('(', ')'), $token);
$parsed_ary[] = $token_decoded;
}
}
$parsed_ary = array_values(array_merge($parsed_ary, array_reverse($ope_stack)));
// cleanup: each double "NOT" in RPN array actually does nothing
$parsed_ary_count = count($parsed_ary);
for ($i = 1; $i < $parsed_ary_count; ++$i) {
if ($parsed_ary[$i] === 'NOT' && $parsed_ary[$i - 1] === 'NOT') {
unset($parsed_ary[$i], $parsed_ary[$i - 1]);
}
}
$parsed_ary = array_values($parsed_ary);
// build return value
$q = array();
$q['query'] = $query;
$q['parsed_str'] = $parsed_query;
$q['parsed_ary'] = $parsed_ary;
foreach ($q['parsed_ary'] as $token) {
if ($token[2] !== ':') continue;
$body = substr($token, 3);
switch (substr($token, 0, 3)) {
case 'N+:':
$q['ns'][] = $body; // for backward compatibility
break;
case 'N-:':
$q['notns'][] = $body; // for backward compatibility
break;
case 'W_:':
$q['words'][] = $body;
break;
case 'W-:':
$q['words'][] = $body;
$q['not'][] = $body; // for backward compatibility
break;
case 'W+:':
$q['words'][] = $body;
$q['highlight'][] = $body;
$q['and'][] = $body; // for backward compatibility
break;
case 'P-:':
$q['phrases'][] = $body;
break;
case 'P+:':
$q['phrases'][] = $body;
$q['highlight'][] = $body;
break;
}
}
foreach (array('words', 'phrases', 'highlight', 'ns', 'notns', 'and', 'not') as $key) {
$q[$key] = empty($q[$key]) ? array() : array_values(array_unique($q[$key]));
}
return $q;
}
/**
* Transforms given search term into intermediate representation
*
* This function is used in ft_queryParser() and not for general purpose use.
*
* @author Kazutaka Miyasaka <kazmiya@gmail.com>
*/
function ft_termParser($Indexer, $term, $consider_asian = true, $phrase_mode = false) {
$parsed = '';
if ($consider_asian) {
// successive asian characters need to be searched as a phrase
$words = preg_split('/('.IDX_ASIAN.'+)/u', $term, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach ($words as $word) {
$phrase_mode = $phrase_mode ? true : preg_match('/'.IDX_ASIAN.'/u', $word);
$parsed .= ft_termParser($Indexer, $word, false, $phrase_mode);
}
} else {
$term_noparen = str_replace(array('(', ')'), ' ', $term);
$words = $Indexer->tokenizer($term_noparen, true);
// W_: no need to highlight
if (empty($words)) {
$parsed = '()'; // important: do not remove
} elseif ($words[0] === $term) {
$parsed = '(W+:'.$words[0].')';
} elseif ($phrase_mode) {
$term_encoded = str_replace(array('(', ')'), array('OP', 'CP'), $term);
$parsed = '((W_:'.implode(')(W_:', $words).')(P+:'.$term_encoded.'))';
} else {
$parsed = '((W+:'.implode(')(W+:', $words).'))';
}
}
return $parsed;
}
//Setup VIM: ex: et ts=4 :

4775
sources/inc/geshi.php Normal file

File diff suppressed because it is too large Load diff

139
sources/inc/geshi/4cs.php Normal file
View file

@ -0,0 +1,139 @@
<?php
/*************************************************************************************
* 4cs.php
* ------
* Author: Jason Curl (jason.curl@continental-corporation.com)
* Copyright: (c) 2009 Jason Curl
* Release Version: 1.0.8.11
* Date Started: 2009/09/05
*
* 4CS language file for GeSHi.
*
* CHANGES
* -------
* 2009/09/05
* - First Release
*
* TODO (updated 2009/09/01)
* -------------------------
*
*************************************************************************************
*
* This file is part of GeSHi.
*
* GeSHi is free software; 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.
*
* GeSHi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GeSHi; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
************************************************************************************/
$language_data = array (
'LANG_NAME' => 'GADV 4CS',
'COMMENT_SINGLE' => array(1 => "//"),
'COMMENT_MULTI' => array(),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array('"'),
'ESCAPE_CHAR' => '',
'KEYWORDS' => array(
1 => array(
'All', 'AllMatches', 'And', 'And_Filters', 'As', 'Asc', 'BasedOn',
'BestMatch', 'Block', 'Buffer', 'ByRef', 'ByVal', 'Call', 'Channel',
'Chr', 'Clear', 'Close', 'Confirm', 'Const', 'Continue', 'Cos',
'Critical', 'Declare', 'Default', 'DefaultChannel', 'DefaultDelayTime',
'DefaultReceiveMode', 'DefaultResponseTime', '#Define', 'DelayTime',
'Delete', 'Div', 'Else', '#Else', 'ElseIf', '#ElseIf', 'End', 'EndCritical',
'EndInlineC', 'EndFunction', 'EndIf', '#EndIf', 'EndInputList',
'EndLocalChannel', 'EndScenario', 'EndSub', 'EndWhile', 'Error',
'ErrorLevelOff', 'ErrorLevelOn', 'ErrorLevelSet', 'ErrorLevelSetRaw',
'Event', 'EventMode', 'EventOff', 'EventOn', 'EventSet', 'EventSetRaw',
'Execute', 'Exit', 'Exp', 'FileClose', 'FilterClear', 'FileEOF', 'FileOpen',
'FileRead', 'FileSize', 'FileWrite', 'FilterAdd', 'FilterMode',
'FilterOff', 'FilterOn', 'For', 'Format', 'Function', 'GoOnline', 'GoTo',
'Handle', 'Hide', 'If', '#If', '#IfDef', '#IfNDef', 'Ignore', '#Include',
'InlineC', 'Input', 'InputItem', 'InputList', 'Kill', 'LBound', 'LocalChannel',
'Local', 'Log', 'Log10', 'LogOff', 'LogOn', 'Loop', 'Message', 'Mod',
'MonitorChannel', 'MostFormat', 'MostMessage', 'Named', 'Never', 'Next',
'NoOrder', 'Not', 'Nothing', 'NoWait', 'Numeric', 'OnError', 'OnEvent',
'Or', 'Or_Filters', 'Order', 'Pass', 'Pow', 'Prototype', 'Quit', 'Raise',
'Random', 'Receive', 'ReceiveMode', 'ReceiveRaw', 'Redim', 'Remote', 'Repeat',
'Repeated', 'ResponseTime', 'Resume', 'ResumeCritical', 'RT_Common',
'RT_Dll_Call', 'RT_FILEIO', 'RT_General', 'RT_HardwareAccess',
'RT_MessageVariableAccess', 'RT_Scenario', 'RT_VariableAccess', 'Runtime',
'Scenario', 'ScenarioEnd', 'ScenarioStart', 'ScenarioStatus', 'ScenarioTerminate',
'Send', 'SendRaw', 'Set', 'SetError', 'Sin', 'Single', 'Show', 'Start',
'StartCritical', 'Starts', 'Static', 'Step', 'Stop', 'String', 'Sub',
'System_Error', 'TerminateAllChilds', 'Terminates', 'Then', 'Throw', 'TimeOut',
'To', 'TooLate', 'Trunc', 'UBound', 'Unexpected', 'Until', 'User_Error',
'View', 'Wait', 'Warning', 'While', 'XOr'
),
2 => array(
'alias', 'winapi', 'long', 'char', 'double', 'float', 'int', 'short', 'lib'
)
),
'SYMBOLS' => array(
'=', ':=', '<', '>', '<>'
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => false,
2 => false
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #0000C0; font-weight: bold;',
2 => 'color: #808080;'
),
'COMMENTS' => array(
1 => 'color: #008000;'
),
'BRACKETS' => array(
0 => 'color: #000080;'
),
'STRINGS' => array(
0 => 'color: #800080;'
),
'NUMBERS' => array(
0 => 'color: #cc66cc;'
),
'METHODS' => array(
1 => 'color: #66cc66;'
),
'SYMBOLS' => array(
0 => 'color: #000080;'
),
'ESCAPE_CHAR' => array(
0 => 'color: #000099;'
),
'SCRIPT' => array(
),
'REGEXPS' => array(
)
),
'URLS' => array(
1 => '',
2 => ''
),
'OOLANG' => true,
'OBJECT_SPLITTERS' => array(
1 => '.'
),
'REGEXPS' => array(
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(
),
'HIGHLIGHT_STRICT_BLOCK' => array(
)
);
?>

View file

@ -0,0 +1,230 @@
<?php
/*************************************************************************************
* 6502acme.php
* -------
* Author: Warren Willmey
* Copyright: (c) 2010 Warren Willmey.
* Release Version: 1.0.8.11
* Date Started: 2010/05/26
*
* MOS 6502 (more specifically 6510) ACME Cross Assembler 0.93 by Marco Baye language file for GeSHi.
*
* CHANGES
* -------
* 2010/07/22
* - First Release
*
* TODO (updated 2010/07/22)
* -------------------------
*
*************************************************************************************
*
* This file is part of GeSHi.
*
* GeSHi is free software; 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.
*
* GeSHi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GeSHi; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
************************************************************************************/
$language_data = array (
'LANG_NAME' => 'MOS 6502 (6510) ACME Cross Assembler format',
'COMMENT_SINGLE' => array(1 => ';'),
'COMMENT_MULTI' => array(),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'", '"'),
'ESCAPE_CHAR' => '',
'KEYWORDS' => array(
/* 6502/6510 Opcodes. */
1 => array(
'adc', 'and', 'asl', 'bcc', 'bcs', 'beq', 'bit', 'bmi',
'bne', 'bpl', 'brk', 'bvc', 'bvs', 'clc', 'cld', 'cli',
'clv', 'cmp', 'cpx', 'cpy', 'dec', 'dex', 'dey', 'eor',
'inc', 'inx', 'iny', 'jmp', 'jsr', 'lda', 'ldx', 'ldy',
'lsr', 'nop', 'ora', 'pha', 'php', 'pla', 'plp', 'rol',
'ror', 'rti', 'rts', 'sbc', 'sec', 'sed', 'sei', 'sta',
'stx', 'sty', 'tax', 'tay', 'tsx', 'txa', 'txs', 'tya',
),
/* Index Registers, yes the 6502 has other registers by they are only
* accessable by specific opcodes. The 65816 also has access to the stack pointer S. */
2 => array(
'x', 'y', 's'
),
/* Directives or "pseudo opcodes" as defined by ACME 0.93 file AllPOs.txt. */
3 => array(
'!8', '!08', '!by', '!byte',
'!16', '!wo', '!word',
'!24', '!32',
'!fi', '!fill',
'!align',
'!ct', '!convtab',
'!tx', '!text',
'!pet',
'!raw',
'!scrxor',
'!to',
'!source',
'!bin', '!binary',
'!zn', '!zone',
'!sl',
'!svl',
'!sal',
'!if', '!ifdef',
'!for',
'!set',
'!do', 'while', 'until',
'!eof', '!endoffile',
'!warn', '!error', '!serious',
'!macro',
// , '*=' // Not a valid keyword (uses both * and = signs) moved to symbols instead.
'!initmem',
'!pseudopc',
'!cpu',
'!al', '!as', '!rl', '!rs',
),
/* 6502/6510 undocumented opcodes (often referred to as illegal instructions).
* These are present in the 6502/6510 but NOT in the newer CMOS revisions of the 65C02 or 65816.
* As they are undocumented instructions there are no "official" names for them, there are also
* several more that mainly perform various forms of crash and are not supported by ACME 0.93.
*/
4 => array(
'anc', 'arr', 'asr', 'dcp', 'dop', 'isc', 'jam', 'lax',
'rla', 'rra', 'sax', 'sbx', 'slo', 'sre', 'top',
),
/* 65c02 instructions, MOS added a few (much needed) instructions in the CMOS version of the 6502, but stupidly removed the undocumented/illegal opcodes.
* ACME 0.93 does not support the rmb0-7 and smb0-7 instructions (they are currently rem'ed out). */
5 => array(
'bra', 'phx', 'phy', 'plx', 'ply', 'stz', 'trb', 'tsb'
),
/* 65816 instructions. */
6 => array(
'brl', 'cop', 'jml', 'jsl', 'mvn', 'mvp', 'pea', 'pei',
'per', 'phb', 'phd', 'phk', 'plb', 'pld', 'rep', 'rtl',
'sep', 'tcd', 'tcs', 'tdc', 'tsc', 'txy', 'tyx', 'wdm',
'xba', 'xce',
),
/* Deprecated directives or "pseudo opcodes" as defined by ACME 0.93 file AllPOs.txt. */
7 => array(
'!cbm',
'!sz', '!subzone',
'!realpc',
),
/* Math functions, some are aliases for the symbols. */
8 => array(
'not', 'div', 'mod', 'xor', 'or', 'sin', 'cos', 'tan',
'arcsin', 'arccos', 'arctan', 'int', 'float',
),
),
'SYMBOLS' => array(
// '[', ']', '(', ')', '{', '}', // These are already defined by GeSHi as BRACKETS.
'*=', '#', '!', '^', '-', '*', '/',
'%', '+', '-', '<<', '>>', '>>>',
'<', '>', '^', '<=', '<', '>=', '>', '!=',
'=', '&', '|', '<>',
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
8 => false,
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #00f; font-weight:bold;',
2 => 'color: #00f; font-weight:bold;',
3 => 'color: #080; font-weight:bold;',
4 => 'color: #f00; font-weight:bold;',
5 => 'color: #80f; font-weight:bold;',
6 => 'color: #f08; font-weight:bold;',
7 => 'color: #a04; font-weight:bold; font-style: italic;',
8 => 'color: #000;',
),
'COMMENTS' => array(
1 => 'color: #999; font-style: italic;',
),
'ESCAPE_CHAR' => array(
0 => 'color: #009; font-weight: bold;'
),
'BRACKETS' => array(
0 => 'color: #000;'
),
'STRINGS' => array(
0 => 'color: #080;'
),
'NUMBERS' => array(
GESHI_NUMBER_INT_BASIC => 'color: #f00;',
GESHI_NUMBER_HEX_PREFIX_DOLLAR => 'color: #f00;',
GESHI_NUMBER_HEX_PREFIX => 'color: #f00;',
GESHI_NUMBER_BIN_PREFIX_PERCENT => 'color: #f00;',
GESHI_NUMBER_FLT_NONSCI => 'color: #f00;',
),
'METHODS' => array(
),
'SYMBOLS' => array(
0 => 'color: #080;'
),
'REGEXPS' => array(
0 => 'color: #f00;'
, 1 => 'color: #933;'
),
'SCRIPT' => array(
)
),
'URLS' => array(
1 => '',
2 => '',
3 => '',
4 => '',
5 => '',
6 => '',
7 => '',
8 => '',
),
'OOLANG' => false,
'OBJECT_SPLITTERS' => array(
),
'NUMBERS' =>
GESHI_NUMBER_INT_BASIC |
GESHI_NUMBER_FLT_NONSCI |
GESHI_NUMBER_HEX_PREFIX_DOLLAR |
GESHI_NUMBER_HEX_PREFIX |
GESHI_NUMBER_BIN_PREFIX_PERCENT,
// AMCE Octal format not support and gets picked up as Decimal unfortunately.
'REGEXPS' => array(
//ACME .# Binary number format. e.g. %..##..##..##
0 => '\%[\.\#]{1,64}',
//ACME Local Labels
1 => '\.[_a-zA-Z][_a-zA-Z0-9]*',
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(
),
'HIGHLIGHT_STRICT_BLOCK' => array(
),
'TAB_WIDTH' => 8,
'PARSER_CONTROL' => array(
'NUMBERS' => array(
'PRECHECK_RX' => '/[\da-fA-F\.\$\%]/'
)
)
);
?>

View file

@ -0,0 +1,241 @@
<?php
/*************************************************************************************
* 6502kickass.php
* -------
* Author: Warren Willmey
* Copyright: (c) 2010 Warren Willmey.
* Release Version: 1.0.8.11
* Date Started: 2010/06/07
*
* MOS 6502 (6510) Kick Assembler 3.13 language file for GeSHi.
*
* CHANGES
* -------
* 2010/07/22
* - First Release
*
* TODO (updated 2010/07/22)
* -------------------------
*
*************************************************************************************
*
* This file is part of GeSHi.
*
* GeSHi is free software; 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.
*
* GeSHi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GeSHi; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
************************************************************************************/
$language_data = array (
'LANG_NAME' => 'MOS 6502 (6510) Kick Assembler format',
'COMMENT_SINGLE' => array(1 => '//'),
'COMMENT_MULTI' => array('/*' => '*/'),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'", '"'),
'ESCAPE_CHAR' => '',
'KEYWORDS' => array(
/* 6502/6510 Opcodes including undocumented opcodes as Kick Assembler 3.13 does not make a distinction - they are ALL valid. */
1 => array(
'adc', 'ahx', 'alr', 'anc', 'anc2', 'and', 'arr', 'asl',
'axs', 'bcc', 'bcs', 'beq', 'bit', 'bmi', 'bne', 'bpl',
'brk', 'bvc', 'bvs', 'clc', 'cld', 'cli', 'clv', 'cmp',
'cpx', 'cpy', 'dcp', 'dec', 'dex', 'dey', 'eor', 'inc',
'inx', 'iny', 'isc', 'jmp', 'jsr', 'las', 'lax', 'lda',
'ldx', 'ldy', 'lsr', 'nop', 'ora', 'pha', 'php', 'pla',
'plp', 'rla', 'rol', 'ror', 'rra', 'rti', 'rts', 'sax',
'sbc', 'sbc2', 'sec', 'sed', 'sei', 'shx', 'shy', 'slo',
'sre', 'sta', 'stx', 'sty', 'tas', 'tax', 'tay', 'tsx',
'txa', 'txs', 'tya', 'xaa',
),
/* DTV additional Opcodes. */
2 => array(
'bra', 'sac', 'sir'
),
/* Index Registers, yes the 6502 has other registers by they are only
* accessable by specific opcodes. */
3 => array(
'x', 'y'
),
/* Directives. */
4 => array(
'.pc', '.pseudopc', 'virtual', '.align', '.byte', '.word', '.text', '.fill',
'.import source', '.import binary', '.import c64', '.import text', '.import', '.print', '.printnow',
'.error', '.var', '.eval', '.const', '.eval const', '.enum', '.label', '.define', '.struct',
'if', '.for', '.macro', '.function', '.return', '.pseudocommand', '.namespace', '.filenamespace',
'.assert', '.asserterror',
),
/* Kick Assembler 3.13 Functions/Operators. */
5 => array(
'size', 'charAt', 'substring', 'asNumber', 'asBoolean', 'toIntString', 'toBinaryString', 'toOctalString',
'toHexString', 'lock', // String functions/operators.
'get', 'set', 'add', 'remove', 'shuffle', // List functions.
'put', 'keys', // Hashtable functions.
'getType', 'getValue', 'CmdArgument', // Pseudo Commands functions.
'asmCommandSize', // Opcode Constants functions.
'LoadBinary', 'getSize',
'LoadSid', 'getData',
'LoadPicture', 'width', 'height', 'getPixel', 'getSinglecolorByte', 'getMulticolorByte',
'createFile', 'writeln',
'cmdLineVars',
'getX', 'getY', 'getZ', // Vector functions.
'RotationMatrix', 'ScaleMatrix', 'MoveMatrix', 'PerspectiveMatrix', // Matrix functions.
),
/* Kick Assembler 3.13 Math Functions. */
6 => array(
'abs', 'acos', 'asin', 'atan', 'atan2', 'cbrt', 'ceil', 'cos', 'cosh',
'exp', 'expm1', 'floor', 'hypot', 'IEEEremainder', 'log', 'log10',
'log1p', 'max', 'min', 'pow', 'mod', 'random', 'round', 'signum',
'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'toDegrees', 'toRadians',
),
/* Kick Assembler 3.13 Objects/Data Types. */
7 => array(
'List', // List() Object.
'Hashtable', // Hashtable() Object.
'Vector', // Vector() Object.
'Matrix', // Matrix() Object.
),
/* Kick Assembler 3.13 Constants. */
8 => array(
'PI', 'E', // Math Constants.
'AT_ABSOLUTE' , 'AT_ABSOLUTEX' , 'AT_ABSOLUTEY' , 'AT_IMMEDIATE', // Pseudo Commands Constants.
'AT_INDIRECT' , 'AT_IZEROPAGEX' , 'AT_IZEROPAGEY' , 'AT_NONE',
'BLACK', 'WHITE', 'RED', 'CYAN', 'PURPLE', 'GREEN', 'BLUE', // Colour Constants.
'YELLOW', 'ORANGE', 'BROWN', 'LIGHT_RED', 'DARK_GRAY', 'GRAY',
'LIGHT_GREEN', 'LIGHT_BLUE', 'LIGHT_GRAY',
'C64FILE', // Template Tag names.
'BF_C64FILE', 'BF_BITMAP_SINGLECOLOR', 'BF_KOALA' , 'BF_FLI', // Binary format constant
),
),
'SYMBOLS' => array(
// '[', ']', '(', ')', '{', '}', // These are already defined by GeSHi as BRACKETS.
'-', '+', '-', '*', '/', '>', '<', '<<', '>>', '&', '|', '^', '=', '==',
'!=', '>=', '<=', '!', '&&', '||', '#',
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => false,
2 => false,
3 => false,
4 => true,
5 => true,
6 => true,
7 => true,
8 => true,
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #00f; font-weight:bold;',
2 => 'color: #00f; font-weight:bold;',
3 => 'color: #00f; font-weight:bold;',
4 => 'color: #080; font-weight:bold;',
5 => 'color: #80f; font-weight:bold;',
6 => 'color: #f08; font-weight:bold;',
7 => 'color: #a04; font-weight:bold; font-style: italic;',
8 => 'color: #f08; font-weight:bold;',
),
'COMMENTS' => array(
1 => 'color: #999; font-style: italic;',
),
'ESCAPE_CHAR' => array(
0 => 'color: #009; font-weight: bold;'
),
'BRACKETS' => array(
0 => 'color: #000;'
),
'STRINGS' => array(
0 => 'color: #080;'
),
'NUMBERS' => array(
GESHI_NUMBER_INT_BASIC => 'color: #f00;',
GESHI_NUMBER_HEX_PREFIX_DOLLAR => 'color: #f00;',
GESHI_NUMBER_BIN_PREFIX_PERCENT => 'color: #f00;',
GESHI_NUMBER_FLT_NONSCI => 'color: #f00;',
),
'METHODS' => array(
),
'SYMBOLS' => array(
0 => 'color: #080;'
),
'REGEXPS' => array(
0 => 'color: #933;',
1 => 'color: #933;',
2 => 'color: #933;',
3 => 'color: #00f; font-weight:bold;',
),
'SCRIPT' => array(
)
),
'URLS' => array(
1 => '',
2 => '',
3 => '',
4 => '',
5 => '',
6 => '',
7 => '',
8 => '',
),
'OOLANG' => false,
'OBJECT_SPLITTERS' => array(
),
'NUMBERS' =>
GESHI_NUMBER_INT_BASIC |
GESHI_NUMBER_FLT_NONSCI |
GESHI_NUMBER_HEX_PREFIX_DOLLAR |
GESHI_NUMBER_BIN_PREFIX_PERCENT,
// AMCE Octal format not support and gets picked up as Decimal unfortunately.
'REGEXPS' => array(
//Labels end with a collon.
0 => '[!]{0,1}[_a-zA-Z][_a-zA-Z0-9]*\:',
//Multi Labels (local labels) references start with ! and end with + or - for forward/backward reference.
1 => '![_a-zA-Z][_a-zA-Z0-9]*[+-]',
//Macros start with a colon :Macro.
2 => ':[_a-zA-Z][_a-zA-Z0-9]*',
// Opcode Constants, such as LDA_IMM, STA_IZPY are basically all 6502 opcodes
// in UPPER case followed by _underscore_ and the ADDRESS MODE.
// As you might imagine that is rather a lot ( 78 supported Opcodes * 12 Addressing modes = 936 variations)
// So I thought it better and easier to maintain as a regular expression.
// NOTE: The order of the Address Modes must be maintained or it wont work properly (eg. place ZP first and find out!)
3 => '[A-Z]{3}[2]?_(?:IMM|IND|IZPX|IZPY|ZPX|ZPY|ABSX|ABSY|REL|ABS|ZP)',
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(
),
'HIGHLIGHT_STRICT_BLOCK' => array(
),
'TAB_WIDTH' => 8,
'PARSER_CONTROL' => array(
'NUMBERS' => array(
'PRECHECK_RX' => '/[\da-fA-F\.\$\%]/'
),
'KEYWORDS' => array(
5 => array (
'DISALLOWED_BEFORE' => "(?<![a-zA-Z0-9\$_\|\;>|^&'\"])"
),
6 => array (
'DISALLOWED_BEFORE' => "(?<![a-zA-Z0-9\$_\|\;>|^&'\"])"
),
8 => array (
'DISALLOWED_BEFORE' => "(?<![a-zA-Z0-9\$_\|\;>|^&'\"])"
)
)
),
);
?>

View file

@ -0,0 +1,189 @@
<?php
/*************************************************************************************
* 6502tasm.php
* -------
* Author: Warren Willmey
* Copyright: (c) 2010 Warren Willmey.
* Release Version: 1.0.8.11
* Date Started: 2010/06/02
*
* MOS 6502 (6510) TASM/64TASS (64TASS being the super set of TASM) language file for GeSHi.
*
* CHANGES
* -------
* 2010/07/22
* - First Release
*
* TODO (updated 2010/07/22)
* -------------------------
*
*************************************************************************************
*
* This file is part of GeSHi.
*
* GeSHi is free software; 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.
*
* GeSHi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GeSHi; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
************************************************************************************/
$language_data = array (
'LANG_NAME' => 'MOS 6502 (6510) TASM/64TASS 1.46 Assembler format',
'COMMENT_SINGLE' => array(1 => ';'),
'COMMENT_MULTI' => array(),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'", '"'),
'ESCAPE_CHAR' => '',
'KEYWORDS' => array(
/* 6502/6510 Opcodes. */
1 => array(
'adc', 'and', 'asl', 'bcc', 'bcs', 'beq', 'bit', 'bmi',
'bne', 'bpl', 'brk', 'bvc', 'bvs', 'clc', 'cld', 'cli',
'clv', 'cmp', 'cpx', 'cpy', 'dec', 'dex', 'dey', 'eor',
'inc', 'inx', 'iny', 'jmp', 'jsr', 'lda', 'ldx', 'ldy',
'lsr', 'nop', 'ora', 'pha', 'php', 'pla', 'plp', 'rol',
'ror', 'rti', 'rts', 'sbc', 'sec', 'sed', 'sei', 'sta',
'stx', 'sty', 'tax', 'tay', 'tsx', 'txa', 'txs', 'tya',
),
/* Index Registers, yes the 6502 has other registers by they are only
* accessable by specific opcodes. The 65816 also has access to the stack pointer S. */
2 => array(
'x', 'y', 's'
),
/* Directives. */
3 => array(
'.al', '.align', '.as', '.assert', '.binary', '.byte', '.cerror', '.char',
'.comment', '.cpu', '.cwarn', '.databank', '.dpage', '.else', '.elsif',
'.enc', '.endc', '.endif', '.endm', '.endp', '.error', '.fi', '.fill',
'.for', '.here', '.if', '.ifeq', '.ifmi', '.ifne', '.ifpl',
'.include', '.int', '.logical', '.long', '.macro', '.next', '.null', '.offs',
'.page', '.pend', '.proc', '.rept', '.rta', '.shift', '.text', '.warn', '.word',
'.xl', '.xs',
// , '*=' // Not a valid keyword (uses both * and = signs) moved to symbols instead.
),
/* 6502/6510 undocumented opcodes (often referred to as illegal instructions).
* These are present in the 6502/6510 but NOT in the newer CMOS revisions of the 65C02 or 65816.
* As they are undocumented instructions there are no "official" names for them, these are the names
* used by 64TASS V1.46.
*/
4 => array(
'ahx', 'alr', 'anc', 'ane', 'arr', 'asr', 'axs', 'dcm',
'dcp', 'ins', 'isb', 'isc', 'jam', 'lae', 'las', 'lax',
'lds', 'lxa', 'rla', 'rra', 'sax', 'sbx', 'sha', 'shs',
'shx', 'shy', 'slo', 'sre', 'tas', 'xaa',
),
/* 65c02 instructions, MOS added a few (much needed) instructions in the
* CMOS version of the 6502, but stupidly removed the undocumented/illegal opcodes. */
5 => array(
'bra', 'dea', 'gra', 'ina', 'phx', 'phy', 'plx', 'ply',
'stz', 'trb', 'tsb',
),
/* 65816 instructions. */
6 => array(
'brl', 'cop', 'jml', 'jsl', 'mvn', 'mvp', 'pea', 'pei',
'per', 'phb', 'phd', 'phk', 'plb', 'pld', 'rep', 'rtl',
'sep', 'stp', 'swa', 'tad', 'tcd', 'tcs', 'tda',
'tdc', 'tsa', 'tsc', 'txy', 'tyx', 'wai', 'xba', 'xce',
),
/* Deprecated directives (or yet to be implemented). */
7 => array(
'.global', '.check'
),
),
'SYMBOLS' => array(
// '[', ']', '(', ')', '{', '}', // These are already defined by GeSHi as BRACKETS.
'*=', '#', '<', '>', '`', '=', '<', '>',
'!=', '>=', '<=', '+', '-', '*', '/', '//', '|',
'^', '&', '<<', '>>', '-', '~', '!',
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #00f; font-weight:bold;',
2 => 'color: #00f; font-weight:bold;',
3 => 'color: #080; font-weight:bold;',
4 => 'color: #f00; font-weight:bold;',
5 => 'color: #80f; font-weight:bold;',
6 => 'color: #f08; font-weight:bold;',
7 => 'color: #a04; font-weight:bold; font-style: italic;',
),
'COMMENTS' => array(
1 => 'color: #999; font-style: italic;',
),
'ESCAPE_CHAR' => array(
0 => 'color: #009; font-weight: bold;'
),
'BRACKETS' => array(
0 => 'color: #000;'
),
'STRINGS' => array(
0 => 'color: #080;'
),
'NUMBERS' => array(
GESHI_NUMBER_INT_BASIC => 'color: #f00;',
GESHI_NUMBER_HEX_PREFIX_DOLLAR => 'color: #f00;',
GESHI_NUMBER_BIN_PREFIX_PERCENT => 'color: #f00;',
),
'METHODS' => array(
),
'SYMBOLS' => array(
0 => 'color: #080;'
),
'REGEXPS' => array(
),
'SCRIPT' => array(
)
),
'URLS' => array(
1 => '',
2 => '',
3 => '',
4 => '',
5 => '',
6 => '',
7 => '',
),
'OOLANG' => false,
'OBJECT_SPLITTERS' => array(
),
'NUMBERS' =>
GESHI_NUMBER_INT_BASIC |
GESHI_NUMBER_HEX_PREFIX_DOLLAR |
GESHI_NUMBER_BIN_PREFIX_PERCENT,
// AMCE Octal format not support and gets picked up as Decimal unfortunately.
'REGEXPS' => array(
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(
),
'HIGHLIGHT_STRICT_BLOCK' => array(
),
'TAB_WIDTH' => 8,
'PARSER_CONTROL' => array(
'NUMBERS' => array(
'PRECHECK_RX' => '/[\da-fA-F\.\$\%]/'
)
)
);
?>

View file

@ -0,0 +1,168 @@
<?php
/*************************************************************************************
* 68000devpac.php
* -------
* Author: Warren Willmey
* Copyright: (c) 2010 Warren Willmey.
* Release Version: 1.0.8.11
* Date Started: 2010/06/09
*
* Motorola 68000 - HiSoft Devpac ST 2 Assembler language file for GeSHi.
*
* CHANGES
* -------
* 2010/07/22
* - First Release
*
* TODO (updated 2010/07/22)
* -------------------------
*
*************************************************************************************
*
* This file is part of GeSHi.
*
* GeSHi is free software; 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.
*
* GeSHi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GeSHi; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
************************************************************************************/
$language_data = array (
'LANG_NAME' => 'Motorola 68000 - HiSoft Devpac ST 2 Assembler format',
'COMMENT_SINGLE' => array(1 => ';'),
'COMMENT_MULTI' => array(),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'", '"'),
'ESCAPE_CHAR' => '',
'KEYWORDS' => array(
/* Directives. */
1 => array(
'end', 'include', 'incbin', 'opt', 'even', 'cnop', 'dc.b', 'dc.w',
'dc.l', 'ds.b', 'ds.w', 'ds.l', 'dcb.b', 'dcb.w', 'dcb.l',
'fail', 'output', '__g2', 'rept', 'endr', 'list', 'nolist', 'plen',
'llen', 'ttl', 'subttl', 'spc', 'page', 'listchar', 'format',
'equ', 'equr', 'set', 'reg', 'rs.b', 'rs.w', 'rs.l', 'rsreset',
'rsset', '__rs', 'ifeq', 'ifne', 'ifgt', 'ifge', 'iflt', 'ifle', 'endc',
'ifd', 'ifnd', 'ifc', 'ifnc', 'elseif', 'iif', 'macro', 'endm', 'mexit',
'narg', '\@', 'section', 'text', 'data', 'bss', 'xdef', 'xref', 'org',
'offset', '__lk', 'comment',
),
/* 68000 Opcodes. */
2 => array(
'abcd', 'add', 'adda', 'addi', 'addq', 'addx', 'and', 'andi',
'asl', 'asr', 'bcc', 'bchg', 'bclr', 'bcs', 'beq', 'bge',
'bgt', 'bhi', 'ble', 'bls', 'blt', 'bmi', 'bne', 'bpl',
'bra', 'bset', 'bsr', 'btst', 'bvc', 'bvs', 'chk', 'clr',
'cmp', 'cmpa', 'cmpi', 'cmpm', 'dbcc', 'dbcs', 'dbeq', 'dbf',
'dbge', 'dbgt', 'dbhi', 'dble', 'dbls', 'dblt', 'dbmi', 'dbne',
'dbpl', 'dbra', 'dbt', 'dbvc', 'dbvs', 'divs', 'divu', 'eor',
'eori', 'exg', 'ext','illegal','jmp', 'jsr', 'lea', 'link',
'lsl', 'lsr', 'move','movea','movem','movep','moveq', 'muls',
'mulu', 'nbcd', 'neg', 'negx', 'nop', 'not', 'or', 'ori',
'pea', 'reset', 'rol', 'ror', 'roxl', 'roxr', 'rte', 'rtr',
'rts', 'sbcd', 'scc', 'scs', 'seq', 'sf', 'sge', 'sgt',
'shi', 'sle', 'sls', 'slt', 'smi', 'sne', 'spl', 'st',
'stop', 'sub', 'suba', 'subi', 'subq', 'subx', 'svc', 'svs',
'swap', 'tas', 'trap','trapv', 'tst', 'unlk',
),
/* oprand sizes. */
3 => array(
'b', 'w', 'l' , 's'
),
/* 68000 Registers. */
4 => array(
'd0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7',
'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'sp', 'usp', 'ssp',
'pc', 'ccr', 'sr',
),
),
'SYMBOLS' => array(
// '[', ']', '(', ')', '{', '}', // These are already defined by GeSHi as BRACKETS.
'+', '-', '~', '<<', '>>', '&',
'!', '^', '*', '/', '=', '<', '>',
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => false,
2 => false,
3 => false,
4 => false,
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #f08; font-weight:bold;',
2 => 'color: #00f; font-weight:bold;',
3 => 'color: #00f; font-weight:bold;',
4 => 'color: #080; font-weight:bold;',
),
'COMMENTS' => array(
1 => 'color: #999; font-style: italic;',
),
'ESCAPE_CHAR' => array(
0 => 'color: #009; font-weight: bold;'
),
'BRACKETS' => array(
0 => 'color: #000;'
),
'STRINGS' => array(
0 => 'color: #080;'
),
'NUMBERS' => array(
GESHI_NUMBER_INT_BASIC => 'color: #f00;',
GESHI_NUMBER_HEX_PREFIX_DOLLAR => 'color: #f00;',
GESHI_NUMBER_BIN_PREFIX_PERCENT => 'color: #f00;',
GESHI_NUMBER_OCT_PREFIX_AT => 'color: #f00;',
),
'METHODS' => array(
),
'SYMBOLS' => array(
0 => 'color: #080;'
),
'REGEXPS' => array(
0 => 'color: #933;'
),
'SCRIPT' => array(
)
),
'URLS' => array(
1 => '',
2 => '',
3 => '',
4 => '',
),
'OOLANG' => false,
'OBJECT_SPLITTERS' => array(
),
'NUMBERS' =>
GESHI_NUMBER_INT_BASIC |
GESHI_NUMBER_HEX_PREFIX_DOLLAR |
GESHI_NUMBER_OCT_PREFIX_AT |
GESHI_NUMBER_BIN_PREFIX_PERCENT,
'REGEXPS' => array(
//Labels may end in a colon.
0 => '(?<=\A\x20|\r|\n|^)[\._a-zA-Z][\._a-zA-Z0-9]*[\:]?[\s]'
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(
),
'HIGHLIGHT_STRICT_BLOCK' => array(
),
'TAB_WIDTH' => 8,
'PARSER_CONTROL' => array(
'NUMBERS' => array(
'PRECHECK_RX' => '/[\da-fA-F\.\$\%\@]/'
)
)
);
?>

1409
sources/inc/geshi/abap.php Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,957 @@
<?php
/*************************************************************************************
* actionscript.php
* ----------------
* Author: Steffen Krause (Steffen.krause@muse.de)
* Copyright: (c) 2004 Steffen Krause, Nigel McNie (http://qbnz.com/highlighter)
* Release Version: 1.0.7.9
* CVS Revision Version: $Revision: 1.9 $
* Date Started: 2004/06/20
* Last Modified: $Date: 2006/04/23 01:14:41 $
*
* Actionscript language file for GeSHi.
*
* CHANGES
* -------
* 2005/08/25 (1.0.2)
* Author [ NikO ] - http://niko.informatif.org
* - add full link for myInstance.methods to http://wiki.media-box.net/documentation/flash
* 2004/11/27 (1.0.1)
* - Added support for multiple object splitters
* 2004/10/27 (1.0.0)
* - First Release
*
* TODO (updated 2004/11/27)
* -------------------------
*
*************************************************************************************
*
* This file is part of GeSHi.
*
* GeSHi is free software; 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.
*
* GeSHi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GeSHi; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
************************************************************************************/
$language_data = array (
'LANG_NAME' => 'Actionscript',
'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
'COMMENT_MULTI' => array('/*' => '*/'),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'", '"'),
'ESCAPE_CHAR' => '\\',
'KEYWORDS' => array(
1 => array(
'#include',
'for',
'foreach',
'if',
'elseif',
'else',
'while',
'do',
'dowhile',
'endwhile',
'endif',
'switch',
'case',
'endswitch',
'break',
'continue',
'in',
'null',
'false',
'true',
'var',
'default',
'new',
'_global',
'undefined',
'super'
),
2 => array(
'static',
'private',
'public',
'class',
'extends',
'implements',
'import',
'return',
'trace',
'_quality',
'_root',
'set',
'setInterval',
'setProperty',
'stopAllSounds',
'targetPath',
'this',
'typeof',
'unescape',
'updateAfterEvent'
),
3 => array (
'Accessibility',
'Array',
'Boolean',
'Button',
'Camera',
'Color',
'ContextMenuItem',
'ContextMenu',
'Cookie',
'Date',
'Error',
'function',
'FWEndCommand',
'FWJavascript',
'Key',
'LoadMovieNum',
'LoadMovie',
'LoadVariablesNum',
'LoadVariables',
'LoadVars',
'LocalConnection',
'Math',
'Microphone',
'MMExecute',
'MMEndCommand',
'MMSave',
'Mouse',
'MovieClipLoader',
'MovieClip',
'NetConnexion',
'NetStream',
'Number',
'Object',
'printAsBitmapNum',
'printNum',
'printAsBitmap',
'printJob',
'print',
'Selection',
'SharedObject',
'Sound',
'Stage',
'String',
'System',
'TextField',
'TextFormat',
'Tween',
'Video',
'XMLUI',
'XMLNode',
'XMLSocket',
'XML'
),
4 => array (
'isactive',
'updateProperties'
),
5 => array (
'callee',
'caller',
),
6 => array (
'concat',
'join',
'pop',
'push',
'reverse',
'shift',
'slice',
'sort',
'sortOn',
'splice',
'toString',
'unshift'
),
7 => array (
'valueOf'
),
8 => array (
'onDragOut',
'onDragOver',
'onKeyUp',
'onKillFocus',
'onPress',
'onRelease',
'onReleaseOutside',
'onRollOut',
'onRollOver',
'onSetFocus'
),
9 => array (
'setMode',
'setMotionLevel',
'setQuality',
'activityLevel',
'bandwidth',
'currentFps',
'fps',
'index',
'motionLevel',
'motionTimeOut',
'muted',
'names',
'quality',
'onActivity',
'onStatus'
),
10 => array (
'getRGB',
'setRGB',
'getTransform',
'setTransform'
),
11 => array (
'caption',
'enabled',
'separatorBefore',
'visible',
'onSelect'
),
12 => array (
'setCookie',
'getcookie'
),
13 => array (
'hideBuiltInItems',
'builtInItems',
'customItems',
'onSelect'
),
14 => array (
'CustomActions.get',
'CustomActions.install',
'CustomActions.list',
'CustomActions.uninstall',
),
15 => array (
'getDate',
'getDay',
'getFullYear',
'getHours',
'getMilliseconds',
'getMinutes',
'getMonth',
'getSeconds',
'getTime',
'getTimezoneOffset',
'getUTCDate',
'getUTCDay',
'getUTCFullYear',
'getUTCHours',
'getUTCMinutes',
'getUTCMilliseconds',
'getUTCMonth',
'getUTCSeconds',
'getYear',
'setDate',
'setFullYear',
'setHours',
'setMilliseconds',
'setMinutes',
'setMonth',
'setSeconds',
'setTime',
'setUTCDate',
'setUTCDay',
'setUTCFullYear',
'setUTCHours',
'setUTCMinutes',
'setUTCMilliseconds',
'setUTCMonth',
'setUTCSeconds',
'setYear',
'UTC'
),
16 => array (
'message',
'name',
'throw',
'try',
'catch',
'finally'
),
17 => array (
'apply',
'call'
),
18 => array (
'BACKSPACE',
'CAPSLOCK',
'CONTROL',
'DELETEKEY',
'DOWN',
'END',
'ENTER',
'ESCAPE',
'getAscii',
'getCode',
'HOME',
'INSERT',
'isDown',
'isToggled',
'LEFT',
'onKeyDown',
'onKeyUp',
'PGDN',
'PGUP',
'RIGHT',
'SPACE',
'TAB',
'UP'
),
19 => array (
'addRequestHeader',
'contentType',
'decode'
),
20 => array (
'allowDomain',
'allowInsecureDomain',
'close',
'domain'
),
21 => array (
'abs',
'acos',
'asin',
'atan',
'atan2',
'ceil',
'cos',
'exp',
'floor',
'log',
'LN2',
'LN10',
'LOG2E',
'LOG10E',
'max',
'min',
'PI',
'pow',
'random',
'sin',
'SQRT1_2',
'sqrt',
'tan',
'round',
'SQRT2'
),
22 => array (
'activityLevel',
'muted',
'names',
'onActivity',
'onStatus',
'setRate',
'setGain',
'gain',
'rate',
'setSilenceLevel',
'setUseEchoSuppression',
'silenceLevel',
'silenceTimeOut',
'useEchoSuppression'
),
23 => array (
'hide',
'onMouseDown',
'onMouseMove',
'onMouseUp',
'onMouseWeel',
'show'
),
24 => array (
'_alpha',
'attachAudio',
'attachMovie',
'beginFill',
'beginGradientFill',
'clear',
'createEmptyMovieClip',
'createTextField',
'_current',
'curveTo',
'_dropTarget',
'duplicateMovieClip',
'endFill',
'focusEnabled',
'enabled',
'_focusrec',
'_framesLoaded',
'getBounds',
'getBytesLoaded',
'getBytesTotal',
'getDepth',
'getInstanceAtDepth',
'getNextHighestDepth',
'getSWFVersion',
'getTextSnapshot',
'getURL',
'globalToLocal',
'gotoAndPlay',
'gotoAndStop',
'_height',
'hitArea',
'hitTest',
'lineStyle',
'lineTo',
'localToGlobal',
'_lockroot',
'menu',
'onUnload',
'_parent',
'play',
'prevFrame',
'_quality',
'removeMovieClip',
'_rotation',
'setMask',
'_soundbuftime',
'startDrag',
'stopDrag',
'stop',
'swapDepths',
'tabChildren',
'_target',
'_totalFrames',
'trackAsMenu',
'unloadMovie',
'useHandCursor',
'_visible',
'_width',
'_xmouse',
'_xscale',
'_x',
'_ymouse',
'_yscale',
'_y'
),
25 => array (
'getProgress',
'loadClip',
'onLoadComplete',
'onLoadError',
'onLoadInit',
'onLoadProgress',
'onLoadStart'
),
26 => array (
'bufferLength',
'currentFps',
'seek',
'setBufferTime',
'bufferTime',
'time',
'pause'
),
27 => array (
'MAX_VALUE',
'MIN_VALUE',
'NEGATIVE_INFINITY',
'POSITIVE_INFINITY'
),
28 => array (
'addProperty',
'constructor',
'__proto__',
'registerClass',
'__resolve',
'unwatch',
'watch',
'onUpDate'
),
29 => array (
'addPage'
),
30 => array (
'getBeginIndex',
'getCaretIndex',
'getEndIndex',
'setSelection'
),
31 => array (
'flush',
'getLocal',
'getSize'
),
32 => array (
'attachSound',
'duration',
'getPan',
'getVolume',
'onID3',
'loadSound',
'id3',
'onSoundComplete',
'position',
'setPan',
'setVolume'
),
33 => array (
'getBeginIndex',
'getCaretIndex',
'getEndIndex',
'setSelection'
),
34 => array (
'getEndIndex',
),
35 => array (
'align',
'height',
'width',
'onResize',
'scaleMode',
'showMenu'
),
36 => array (
'charAt',
'charCodeAt',
'concat',
'fromCharCode',
'indexOf',
'lastIndexOf',
'substr',
'substring',
'toLowerCase',
'toUpperCase'
),
37 => array (
'avHardwareDisable',
'hasAccessibility',
'hasAudioEncoder',
'hasAudio',
'hasEmbeddedVideo',
'hasMP3',
'hasPrinting',
'hasScreenBroadcast',
'hasScreenPlayback',
'hasStreamingAudio',
'hasStreamingVideo',
'hasVideoEncoder',
'isDebugger',
'language',
'localFileReadDisable',
'manufacturer',
'os',
'pixelAspectRatio',
'playerType',
'screenColor',
'screenDPI',
'screenResolutionX',
'screenResolutionY',
'serverString',
'version'
),
38 => array (
'allowDomain',
'allowInsecureDomain',
'loadPolicyFile'
),
39 => array (
'exactSettings',
'setClipboard',
'showSettings',
'useCodepage'
),
40 => array (
'getStyle',
'getStyleNames',
'parseCSS',
'setStyle',
'transform'
),
41 => array (
'autoSize',
'background',
'backgroundColor',
'border',
'borderColor',
'bottomScroll',
'condenseWhite',
'embedFonts',
'getFontList',
'getNewTextFormat',
'getTextFormat',
'hscroll',
'htmlText',
'html',
'maxChars',
'maxhscroll',
'maxscroll',
'mouseWheelEnabled',
'multiline',
'onScroller',
'password',
'removeTextField',
'replaceSel',
'replaceText',
'restrict',
'scroll',
'selectable',
'setNewTextFormat',
'setTextFormat',
'styleSheet',
'tabEnabled',
'tabIndex',
'textColor',
'textHeight',
'textWidth',
'text',
'type',
'_url',
'variable',
'wordWrap'
),
42 => array (
'blockIndent',
'bold',
'bullet',
'font',
'getTextExtent',
'indent',
'italic',
'leading',
'leftMargin',
'rightMargin',
'size',
'tabStops',
'underline'
),
43 => array (
'findText',
'getCount',
'getSelected',
'getSelectedText',
'getText',
'hitTestTextNearPos',
'setSelectColor',
'setSelected'
),
44 => array (
'begin',
'change',
'continueTo',
'fforward',
'finish',
'func',
'FPS',
'getPosition',
'isPlaying',
'looping',
'obj',
'onMotionChanged',
'onMotionFinished',
'onMotionLooped',
'onMotionStarted',
'onMotionResumed',
'onMotionStopped',
'prop',
'rewind',
'resume',
'setPosition',
'time',
'userSeconds',
'yoyo'
),
45 => array (
'attachVideo',
'deblocking',
'smoothing'
),
46 => array (
'addRequestHeader',
'appendChild',
'attributes',
'childNodes',
'cloneNode',
'contentType',
'createElement',
'createTextNode',
'docTypeDecl',
'firstChild',
'hasChildNodes',
'ignoreWhite',
'insertBefore',
'lastChild',
'nextSibling',
'nodeName',
'nodeType',
'nodeValue',
'parentNode',
'parseXML',
'previousSibling',
'removeNode',
'xmlDecl'
),
47 => array (
'onClose',
'onXML'
),
48 => array (
'add',
'and',
'_highquality',
'chr',
'eq',
'ge',
'ifFrameLoaded',
'int',
'le',
'it',
'mbchr',
'mblength',
'mbord',
'ne',
'not',
'or',
'ord',
'tellTarget',
'toggleHighQuality'
),
49 => array (
'ASSetPropFlags',
'ASnative',
'ASconstructor',
'AsSetupError',
'FWEndCommand',
'FWJavascript',
'MMEndCommand',
'MMSave',
'XMLUI'
),
50 => array (
'System.capabilities'
),
51 => array (
'System.security'
),
52 => array (
'TextField.StyleSheet'
)
),
'SYMBOLS' => array(
'(', ')', '[', ']', '{', '}', '!', '@', '%', '&', '*', '|', '/', '<', '>','='
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => true,
2 => true,
3 => true,
4 => true,
5 => true,
6 => true,
7 => true,
8 => true,
9 => true,
10 => true,
11 => true,
12 => true,
13 => true,
14 => true,
15 => true,
16 => true,
17 => true,
18 => true,
19 => true,
20 => true,
21 => true,
22 => true,
23 => true,
24 => true,
25 => true,
26 => true,
27 => true,
28 => true,
29 => true,
30 => true,
31 => true,
32 => true,
33 => true,
34 => true,
35 => true,
36 => true,
37 => true,
38 => true,
39 => true,
40 => true,
41 => true,
42 => true,
43 => true,
44 => true,
45 => true,
46 => true,
47 => true,
48 => true,
49 => true,
50 => true,
51 => true,
52 => true
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #0000ff;',
2 => 'color: #006600;',
3 => 'color: #000080;',
4 => 'color: #006600;',
5 => 'color: #006600;',
6 => 'color: #006600;',
7 => 'color: #006600;',
8 => 'color: #006600;',
9 => 'color: #006600;',
10 => 'color: #006600;',
11 => 'color: #006600;',
12 => 'color: #006600;',
13 => 'color: #006600;',
14 => 'color: #006600;',
15 => 'color: #006600;',
16 => 'color: #006600;',
17 => 'color: #006600;',
18 => 'color: #006600;',
19 => 'color: #006600;',
20 => 'color: #006600;',
21 => 'color: #006600;',
22 => 'color: #006600;',
23 => 'color: #006600;',
24 => 'color: #006600;',
25 => 'color: #006600;',
26 => 'color: #006600;',
27 => 'color: #006600;',
28 => 'color: #006600;',
29 => 'color: #006600;',
30 => 'color: #006600;',
31 => 'color: #006600;',
32 => 'color: #006600;',
33 => 'color: #006600;',
34 => 'color: #006600;',
35 => 'color: #006600;',
36 => 'color: #006600;',
37 => 'color: #006600;',
38 => 'color: #006600;',
39 => 'color: #006600;',
40 => 'color: #006600;',
41 => 'color: #006600;',
42 => 'color: #006600;',
43 => 'color: #006600;',
44 => 'color: #006600;',
45 => 'color: #006600;',
46 => 'color: #006600;',
47 => 'color: #006600;',
48 => 'color: #CC0000;',
49 => 'color: #5700d1;',
50 => 'color: #006600;',
51 => 'color: #006600;',
52 => 'color: #CC0000;'
),
'COMMENTS' => array(
1 => 'color: #ff8000; font-style: italic;',
2 => 'color: #ff8000; font-style: italic;',
'MULTI' => 'color: #ff8000; font-style: italic;'
),
'ESCAPE_CHAR' => array(
0 => 'color: #000099; font-weight: bold;'
),
'BRACKETS' => array(
0 => 'color: #333333;'
),
'STRINGS' => array(
0 => 'color: #333333; background-color: #eeeeee;'
),
'NUMBERS' => array(
0 => 'color: #c50000;'
),
'SYMBOLS' => array(
0 => 'color: #000000;'
),
'METHODS' => array(
1 => 'color: #006600;'
),
'REGEXPS' => array(
),
'SCRIPT' => array(
)
),
'URLS' => array(
1 => 'http://wiki.media-box.net/documentation/flash/{FNAME}',
2 => 'http://wiki.media-box.net/documentation/flash/{FNAME}',
3 => 'http://wiki.media-box.net/documentation/flash/{FNAME}',
4 => 'http://wiki.media-box.net/documentation/flash/accessibility/{FNAME}',
5 => 'http://wiki.media-box.net/documentation/flash/arguments/{FNAME}',
6 => 'http://wiki.media-box.net/documentation/flash/array/{FNAME}',
7 => 'http://wiki.media-box.net/documentation/flash/boolean/{FNAME}',
8 => 'http://wiki.media-box.net/documentation/flash/button/{FNAME}',
9 => 'http://wiki.media-box.net/documentation/flash/camera/{FNAME}',
10 => 'http://wiki.media-box.net/documentation/flash/color/{FNAME}',
11 => 'http://wiki.media-box.net/documentation/flash/contextmenuitem/{FNAME}',
12 => 'http://wiki.media-box.net/documentation/flash/contextmenu/{FNAME}',
13 => 'http://wiki.media-box.net/documentation/flash/cookie/{FNAME}',
14 => 'http://wiki.media-box.net/documentation/flash/customactions/{FNAME}',
15 => 'http://wiki.media-box.net/documentation/flash/date/{FNAME}',
16 => 'http://wiki.media-box.net/documentation/flash/error/{FNAME}',
17 => 'http://wiki.media-box.net/documentation/flash/function/{FNAME}',
18 => 'http://wiki.media-box.net/documentation/flash/key/{FNAME}',
19 => 'http://wiki.media-box.net/documentation/flash/loadvars/{FNAME}',
20 => 'http://wiki.media-box.net/documentation/flash/localconnection/{FNAME}',
21 => 'http://wiki.media-box.net/documentation/flash/math/{FNAME}',
22 => 'http://wiki.media-box.net/documentation/flash/microphone/{FNAME}',
23 => 'http://wiki.media-box.net/documentation/flash/mouse/{FNAME}',
24 => 'http://wiki.media-box.net/documentation/flash/movieclip/{FNAME}',
25 => 'http://wiki.media-box.net/documentation/flash/moviecliploader/{FNAME}',
26 => 'http://wiki.media-box.net/documentation/flash/netstream/{FNAME}',
27 => 'http://wiki.media-box.net/documentation/flash/number/{FNAME}',
28 => 'http://wiki.media-box.net/documentation/flash/object/{FNAME}',
29 => 'http://wiki.media-box.net/documentation/flash/printJob/{FNAME}',
30 => 'http://wiki.media-box.net/documentation/flash/selection/{FNAME}',
31 => 'http://wiki.media-box.net/documentation/flash/sharedobject/{FNAME}',
32 => 'http://wiki.media-box.net/documentation/flash/sound/{FNAME}',
33 => 'http://wiki.media-box.net/documentation/flash/selection/{FNAME}',
34 => 'http://wiki.media-box.net/documentation/flash/sharedobject/{FNAME}',
35 => 'http://wiki.media-box.net/documentation/flash/stage/{FNAME}',
36 => 'http://wiki.media-box.net/documentation/flash/string/{FNAME}',
37 => 'http://wiki.media-box.net/documentation/flash/system/capabilities/{FNAME}',
38 => 'http://wiki.media-box.net/documentation/flash/system/security/{FNAME}',
39 => 'http://wiki.media-box.net/documentation/flash/system/{FNAME}',
40 => 'http://wiki.media-box.net/documentation/flash/textfield/stylesheet/{FNAME}',
41 => 'http://wiki.media-box.net/documentation/flash/textfield/{FNAME}',
42 => 'http://wiki.media-box.net/documentation/flash/textformat/{FNAME}',
43 => 'http://wiki.media-box.net/documentation/flash/textsnapshot/{FNAME}',
44 => 'http://wiki.media-box.net/documentation/flash/tween/{FNAME}',
45 => 'http://wiki.media-box.net/documentation/flash/video/{FNAME}',
46 => 'http://wiki.media-box.net/documentation/flash/xml/{FNAME}',
47 => 'http://wiki.media-box.net/documentation/flash/xmlsocket/{FNAME}',
48 => 'http://wiki.media-box.net/documentation/flash/{FNAME}',
49 => 'http://wiki.media-box.net/documentation/flash/{FNAME}',
50 => 'http://wiki.media-box.net/documentation/flash/system/capabilities',
51 => 'http://wiki.media-box.net/documentation/flash/system/security',
52 => 'http://wiki.media-box.net/documentation/flash/textfield/stylesheet'
),
'OOLANG' => true,
'OBJECT_SPLITTERS' => array(
1 => '.'
),
'REGEXPS' => array(
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(),
'HIGHLIGHT_STRICT_BLOCK' => array()
);
?>

View file

@ -0,0 +1,197 @@
<?php
/*************************************************************************************
* actionscript.php
* ----------------
* Author: Steffen Krause (Steffen.krause@muse.de)
* Copyright: (c) 2004 Steffen Krause, Nigel McNie (http://qbnz.com/highlighter)
* Release Version: 1.0.8.11
* Date Started: 2004/06/20
*
* Actionscript language file for GeSHi.
*
* CHANGES
* -------
* 2004/11/27 (1.0.1)
* - Added support for multiple object splitters
* 2004/10/27 (1.0.0)
* - First Release
*
* TODO (updated 2004/11/27)
* -------------------------
*
*************************************************************************************
*
* This file is part of GeSHi.
*
* GeSHi is free software; 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.
*
* GeSHi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GeSHi; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
************************************************************************************/
$language_data = array (
'LANG_NAME' => 'ActionScript',
'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
'COMMENT_MULTI' => array('/*' => '*/'),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'", '"'),
'ESCAPE_CHAR' => '\\',
'KEYWORDS' => array(
1 => array(
'#include', 'for', 'foreach', 'each', 'if', 'elseif', 'else', 'while', 'do', 'dowhile',
'endwhile', 'endif', 'switch', 'case', 'endswitch', 'return', 'break', 'continue', 'in'
),
2 => array(
'null', 'false', 'true', 'var',
'default', 'function', 'class',
'new', '_global'
),
3 => array(
'#endinitclip', '#initclip', '__proto__', '_accProps', '_alpha', '_currentframe',
'_droptarget', '_focusrect', '_framesloaded', '_height', '_highquality', '_lockroot',
'_name', '_parent', '_quality', '_root', '_rotation', '_soundbuftime', '_target', '_totalframes',
'_url', '_visible', '_width', '_x', '_xmouse', '_xscale', '_y', '_ymouse', '_yscale', 'abs',
'Accessibility', 'acos', 'activityLevel', 'add', 'addListener', 'addPage', 'addProperty',
'addRequestHeader', 'align', 'allowDomain', 'allowInsecureDomain', 'and', 'appendChild',
'apply', 'Arguments', 'Array', 'asfunction', 'asin', 'atan', 'atan2', 'attachAudio', 'attachMovie',
'attachSound', 'attachVideo', 'attributes', 'autosize', 'avHardwareDisable', 'background',
'backgroundColor', 'BACKSPACE', 'bandwidth', 'beginFill', 'beginGradientFill', 'blockIndent',
'bold', 'Boolean', 'border', 'borderColor', 'bottomScroll', 'bufferLength', 'bufferTime',
'builtInItems', 'bullet', 'Button', 'bytesLoaded', 'bytesTotal', 'call', 'callee', 'caller',
'Camera', 'capabilities', 'CAPSLOCK', 'caption', 'catch', 'ceil', 'charAt', 'charCodeAt',
'childNodes', 'chr', 'clear', 'clearInterval', 'cloneNode', 'close', 'Color', 'concat',
'connect', 'condenseWhite', 'constructor', 'contentType', 'ContextMenu', 'ContextMenuItem',
'CONTROL', 'copy', 'cos', 'createElement', 'createEmptyMovieClip', 'createTextField',
'createTextNode', 'currentFps', 'curveTo', 'CustomActions', 'customItems', 'data', 'Date',
'deblocking', 'delete', 'DELETEKEY', 'docTypeDecl', 'domain', 'DOWN',
'duplicateMovieClip', 'duration', 'dynamic', 'E', 'embedFonts', 'enabled',
'END', 'endFill', 'ENTER', 'eq', 'Error', 'ESCAPE(Konstante)', 'escape(Funktion)', 'eval',
'exactSettings', 'exp', 'extends', 'finally', 'findText', 'firstChild', 'floor',
'flush', 'focusEnabled', 'font', 'fps', 'fromCharCode', 'fscommand',
'gain', 'ge', 'get', 'getAscii', 'getBeginIndex', 'getBounds', 'getBytesLoaded', 'getBytesTotal',
'getCaretIndex', 'getCode', 'getCount', 'getDate', 'getDay', 'getDepth', 'getEndIndex', 'getFocus',
'getFontList', 'getFullYear', 'getHours', 'getInstanceAtDepth', 'getLocal', 'getMilliseconds',
'getMinutes', 'getMonth', 'getNewTextFormat', 'getNextHighestDepth', 'getPan', 'getProgress',
'getProperty', 'getRGB', 'getSeconds', 'getSelected', 'getSelectedText', 'getSize', 'getStyle',
'getStyleNames', 'getSWFVersion', 'getText', 'getTextExtent', 'getTextFormat', 'getTextSnapshot',
'getTime', 'getTimer', 'getTimezoneOffset', 'getTransform', 'getURL', 'getUTCDate', 'getUTCDay',
'getUTCFullYear', 'getUTCHours', 'getUTCMilliseconds', 'getUTCMinutes', 'getUTCMonth', 'getUTCSeconds',
'getVersion', 'getVolume', 'getYear', 'globalToLocal', 'goto', 'gotoAndPlay', 'gotoAndStop',
'hasAccessibility', 'hasAudio', 'hasAudioEncoder', 'hasChildNodes', 'hasEmbeddedVideo', 'hasMP3',
'hasPrinting', 'hasScreenBroadcast', 'hasScreenPlayback', 'hasStreamingAudio', 'hasStreamingVideo',
'hasVideoEncoder', 'height', 'hide', 'hideBuiltInItems', 'hitArea', 'hitTest', 'hitTestTextNearPos',
'HOME', 'hscroll', 'html', 'htmlText', 'ID3', 'ifFrameLoaded', 'ignoreWhite', 'implements',
'import', 'indent', 'index', 'indexOf', 'Infinity', '-Infinity', 'INSERT', 'insertBefore', 'install',
'instanceof', 'int', 'interface', 'isActive', 'isDebugger', 'isDown', 'isFinite', 'isNaN', 'isToggled',
'italic', 'join', 'Key', 'language', 'lastChild', 'lastIndexOf', 'le', 'leading', 'LEFT', 'leftMargin',
'length', 'level', 'lineStyle', 'lineTo', 'list', 'LN10', 'LN2', 'load', 'loadClip', 'loaded', 'loadMovie',
'loadMovieNum', 'loadSound', 'loadVariables', 'loadVariablesNum', 'LoadVars', 'LocalConnection',
'localFileReadDisable', 'localToGlobal', 'log', 'LOG10E', 'LOG2E', 'manufacturer', 'Math', 'max',
'MAX_VALUE', 'maxChars', 'maxhscroll', 'maxscroll', 'mbchr', 'mblength', 'mbord', 'mbsubstring', 'menu',
'message', 'Microphone', 'min', 'MIN_VALUE', 'MMExecute', 'motionLevel', 'motionTimeOut', 'Mouse',
'mouseWheelEnabled', 'moveTo', 'Movieclip', 'MovieClipLoader', 'multiline', 'muted', 'name', 'names', 'NaN',
'ne', 'NEGATIVE_INFINITY', 'NetConnection', 'NetStream', 'newline', 'nextFrame',
'nextScene', 'nextSibling', 'nodeName', 'nodeType', 'nodeValue', 'not', 'Number', 'Object',
'on', 'onActivity', 'onChanged', 'onClipEvent', 'onClose', 'onConnect', 'onData', 'onDragOut',
'onDragOver', 'onEnterFrame', 'onID3', 'onKeyDown', 'onKeyUp', 'onKillFocus', 'onLoad', 'onLoadComplete',
'onLoadError', 'onLoadInit', 'onLoadProgress', 'onLoadStart', 'onMouseDown', 'onMouseMove', 'onMouseUp',
'onMouseWheel', 'onPress', 'onRelease', 'onReleaseOutside', 'onResize', 'onRollOut', 'onRollOver',
'onScroller', 'onSelect', 'onSetFocus', 'onSoundComplete', 'onStatus', 'onUnload', 'onUpdate', 'onXML',
'or(logischesOR)', 'ord', 'os', 'parentNode', 'parseCSS', 'parseFloat', 'parseInt', 'parseXML', 'password',
'pause', 'PGDN', 'PGUP', 'PI', 'pixelAspectRatio', 'play', 'playerType', 'pop', 'position',
'POSITIVE_INFINITY', 'pow', 'prevFrame', 'previousSibling', 'prevScene', 'print', 'printAsBitmap',
'printAsBitmapNum', 'PrintJob', 'printNum', 'private', 'prototype', 'public', 'push', 'quality',
'random', 'rate', 'registerClass', 'removeListener', 'removeMovieClip', 'removeNode', 'removeTextField',
'replaceSel', 'replaceText', 'resolutionX', 'resolutionY', 'restrict', 'reverse', 'RIGHT',
'rightMargin', 'round', 'scaleMode', 'screenColor', 'screenDPI', 'screenResolutionX', 'screenResolutionY',
'scroll', 'seek', 'selectable', 'Selection', 'send', 'sendAndLoad', 'separatorBefore', 'serverString',
'set', 'setvariable', 'setBufferTime', 'setClipboard', 'setDate', 'setFocus', 'setFullYear', 'setGain',
'setHours', 'setInterval', 'setMask', 'setMilliseconds', 'setMinutes', 'setMode', 'setMonth',
'setMotionLevel', 'setNewTextFormat', 'setPan', 'setProperty', 'setQuality', 'setRate', 'setRGB',
'setSeconds', 'setSelectColor', 'setSelected', 'setSelection', 'setSilenceLevel', 'setStyle',
'setTextFormat', 'setTime', 'setTransform', 'setUseEchoSuppression', 'setUTCDate', 'setUTCFullYear',
'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', 'setVolume',
'setYear', 'SharedObject', 'SHIFT(Konstante)', 'shift(Methode)', 'show', 'showMenu', 'showSettings',
'silenceLevel', 'silenceTimeout', 'sin', 'size', 'slice', 'smoothing', 'sort', 'sortOn', 'Sound', 'SPACE',
'splice', 'split', 'sqrt', 'SQRT1_2', 'SQRT2', 'Stage', 'start', 'startDrag', 'static', 'status', 'stop',
'stopAllSounds', 'stopDrag', 'String', 'StyleSheet(Klasse)', 'styleSheet(Eigenschaft)', 'substr',
'substring', 'super', 'swapDepths', 'System', 'TAB', 'tabChildren', 'tabEnabled', 'tabIndex',
'tabStops', 'tan', 'target', 'targetPath', 'tellTarget', 'text', 'textColor', 'TextField', 'TextFormat',
'textHeight', 'TextSnapshot', 'textWidth', 'this', 'throw', 'time', 'toggleHighQuality', 'toLowerCase',
'toString', 'toUpperCase', 'trace', 'trackAsMenu', 'try', 'type', 'typeof', 'undefined',
'underline', 'unescape', 'uninstall', 'unloadClip', 'unloadMovie', 'unLoadMovieNum', 'unshift', 'unwatch',
'UP', 'updateAfterEvent', 'updateProperties', 'url', 'useCodePage', 'useEchoSuppression', 'useHandCursor',
'UTC', 'valueOf', 'variable', 'version', 'Video', 'visible', 'void', 'watch', 'width',
'with', 'wordwrap', 'XML', 'xmlDecl', 'XMLNode', 'XMLSocket'
)
),
'SYMBOLS' => array(
'(', ')', '[', ']', '{', '}', '!', '@', '%', '&', '*', '|', '/', '<', '>'
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => false,
2 => false,
3 => false,
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #b1b100;',
2 => 'color: #000000; font-weight: bold;',
3 => 'color: #0066CC;'
),
'COMMENTS' => array(
1 => 'color: #808080; font-style: italic;',
2 => 'color: #808080; font-style: italic;',
'MULTI' => 'color: #808080; font-style: italic;'
),
'ESCAPE_CHAR' => array(
0 => 'color: #000099; font-weight: bold;'
),
'BRACKETS' => array(
0 => 'color: #66cc66;'
),
'STRINGS' => array(
0 => 'color: #ff0000;'
),
'NUMBERS' => array(
0 => 'color: #cc66cc;'
),
'METHODS' => array(
1 => 'color: #006600;'
),
'SYMBOLS' => array(
0 => 'color: #66cc66;'
),
'REGEXPS' => array(
),
'SCRIPT' => array(
)
),
'URLS' => array(
1 => '',
2 => '',
3 => ''
),
'OOLANG' => true,
'OBJECT_SPLITTERS' => array(
1 => '.'
),
'REGEXPS' => array(
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(),
'HIGHLIGHT_STRICT_BLOCK' => array()
);
?>

View file

@ -0,0 +1,473 @@
<?php
/*************************************************************************************
* actionscript3.php
* ----------------
* Author: Jordi Boggiano (j.boggiano@seld.be)
* Copyright: (c) 2007 Jordi Boggiano (http://www.seld.be/), Benny Baumann (http://qbnz.com/highlighter)
* Release Version: 1.0.8.11
* Date Started: 2007/11/26
*
* ActionScript3 language file for GeSHi.
*
* All keywords scraped from the Flex 2.0.1 Documentation
*
* The default style is based on FlexBuilder2 coloring, with the addition of class, package, method and
* constant names that are highlighted to help identifying problem when used on public pastebins.
*
* For styling, keywords data from 0 to 1 (accessible through .kw1, etc.) are described here :
*
* 1 : operators
* 2 : 'var' keyword
* 3 : 'function' keyword
* 4 : 'class' and 'package' keywords
* 5 : all flash.* class names plus Top Level classes, mx are excluded
* 6 : all flash.* package names, mx are excluded
* 7 : valid flash method names and properties (there is no type checks sadly, for example String().x will be highlighted as 'x' is valid, but obviously strings don't have a x property)
* 8 : valid flash constant names (again, no type check)
*
*
* CHANGES
* -------
* 2007/12/06 (1.0.7.22)
* - Added the 'this' keyword (oops)
*
* TODO (updated 2007/11/30)
* -------------------------
*
*************************************************************************************
*
* This file is part of GeSHi.
*
* GeSHi is free software; 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.
*
* GeSHi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GeSHi; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
************************************************************************************/
$language_data = array (
'LANG_NAME' => 'ActionScript 3',
'COMMENT_SINGLE' => array(1 => '//'),
'COMMENT_MULTI' => array('/*' => '*/'),
'COMMENT_REGEXP' => array(
//Regular expressions
2 => "/(?<=[\\s^])(s|tr|y)\\/(?!\s)(?:\\\\.|(?!\n)[^\\/\\\\])+(?<!\s)\\/(?!\s)(?:\\\\.|(?!\n)[^\\/\\\\])*(?<!\s)\\/[msixpogcde]*(?=[\\s$\\.\\;])|(?<=[\\s^(=])(m|q[qrwx]?)?\\/(?!\s)(?:\\\\.|(?!\n)[^\\/\\\\])+(?<!\s)\\/[msixpogc]*(?=[\\s$\\.\\,\\;\\)])/iU",
),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'", '"'),
'ESCAPE_CHAR' => '\\',
'KEYWORDS' => array(
1 => array(
'with', 'while', 'void', 'undefined', 'typeof', 'try', 'true',
'throw', 'this', 'switch', 'super', 'set', 'return', 'public', 'protected',
'private', 'null', 'new', 'is', 'internal', 'instanceof', 'in',
'import', 'if', 'get', 'for', 'false', 'else', 'each', 'do',
'delete', 'default', 'continue', 'catch', 'case', 'break', 'as',
'extends', 'override'
),
2 => array(
'var'
),
3 => array(
'function'
),
4 => array(
'class', 'package'
),
6 => array(
'flash.xml', 'flash.utils', 'flash.ui', 'flash.text',
'flash.system', 'flash.profiler', 'flash.printing', 'flash.net',
'flash.media', 'flash.geom', 'flash.filters', 'flash.external',
'flash.events', 'flash.errors', 'flash.display',
'flash.accessibility'
),
7 => array(
'zoom', 'year', 'y', 'xmlDecl', 'x', 'writeUnsignedInt',
'writeUTFBytes', 'writeUTF', 'writeShort', 'writeObject',
'writeMultiByte', 'writeInt', 'writeFloat', 'writeExternal',
'writeDynamicProperty', 'writeDynamicProperties', 'writeDouble',
'writeBytes', 'writeByte', 'writeBoolean', 'wordWrap',
'willTrigger', 'width', 'volume', 'visible', 'videoWidth',
'videoHeight', 'version', 'valueOf', 'value', 'usingTLS',
'useRichTextClipboard', 'useHandCursor', 'useEchoSuppression',
'useCodePage', 'url', 'uri', 'uploadCompleteData', 'upload',
'updateProperties', 'updateAfterEvent', 'upState', 'unshift',
'unlock', 'unload', 'union', 'unescapeMultiByte', 'unescape',
'underline', 'uncompress', 'type', 'ty', 'tx', 'transparent',
'translate', 'transformPoint', 'transform', 'trackAsMenu', 'track',
'trace', 'totalMemory', 'totalFrames', 'topLeft', 'top',
'togglePause', 'toXMLString', 'toUpperCase', 'toUTCString',
'toTimeString', 'toString', 'toPrecision', 'toLowerCase',
'toLocaleUpperCase', 'toLocaleTimeString', 'toLocaleString',
'toLocaleLowerCase', 'toLocaleDateString', 'toFixed',
'toExponential', 'toDateString', 'timezoneOffset', 'timerComplete',
'timer', 'time', 'threshold', 'thickness', 'textWidth',
'textSnapshot', 'textInput', 'textHeight', 'textColor', 'text',
'test', 'target', 'tan', 'tabStops', 'tabIndexChange', 'tabIndex',
'tabEnabledChange', 'tabEnabled', 'tabChildrenChange',
'tabChildren', 'sync', 'swfVersion', 'swapChildrenAt',
'swapChildren', 'subtract', 'substring', 'substr', 'styleSheet',
'styleNames', 'strength', 'stopPropagation',
'stopImmediatePropagation', 'stopDrag', 'stopAll', 'stop', 'status',
'startDrag', 'start', 'stageY', 'stageX', 'stageWidth',
'stageHeight', 'stageFocusRect', 'stage', 'sqrt', 'split', 'splice',
'source', 'soundTransform', 'soundComplete', 'sortOn', 'sort',
'songName', 'some', 'socketData', 'smoothing', 'slice', 'size',
'sin', 'silent', 'silenceTimeout', 'silenceLevel', 'showSettings',
'showRedrawRegions', 'showDefaultContextMenu', 'show', 'shortcut',
'shiftKey', 'shift', 'sharpness', 'sharedEvents', 'shadowColor',
'shadowAlpha', 'settings', 'setUseEchoSuppression', 'setUTCSeconds',
'setUTCMonth', 'setUTCMinutes', 'setUTCMilliseconds', 'setUTCHours',
'setUTCFullYear', 'setUTCDate', 'setTimeout', 'setTime',
'setTextFormat', 'setStyle', 'setSilenceLevel', 'setSettings',
'setSelection', 'setSelected', 'setSelectColor', 'setSeconds',
'setQuality', 'setPropertyIsEnumerable', 'setProperty', 'setPixels',
'setPixel32', 'setPixel', 'setNamespace', 'setName',
'setMotionLevel', 'setMonth', 'setMode', 'setMinutes',
'setMilliseconds', 'setLoopback', 'setLoopBack', 'setLocalName',
'setKeyFrameInterval', 'setInterval', 'setHours', 'setFullYear',
'setEmpty', 'setDirty', 'setDate', 'setCompositionString',
'setClipboard', 'setChildren', 'setChildIndex',
'setAdvancedAntiAliasingTable', 'serverString', 'separatorBefore',
'sendToURL', 'send', 'selectionEndIndex', 'selectionBeginIndex',
'selectable', 'select', 'seek', 'securityError', 'securityDomain',
'secondsUTC', 'seconds', 'search', 'scrollV', 'scrollRect',
'scrollH', 'scroll', 'screenResolutionY', 'screenResolutionX',
'screenDPI', 'screenColor', 'scenes', 'scaleY', 'scaleX',
'scaleMode', 'scale9Grid', 'scale', 'save', 'sandboxType',
'sameDomain', 'running', 'round', 'rotation', 'rotate', 'root',
'rollOver', 'rollOut', 'rightToRight', 'rightToLeft', 'rightPeak',
'rightMargin', 'right', 'rewind', 'reverse', 'resume', 'restrict',
'resize', 'reset', 'requestHeaders', 'replaceText',
'replaceSelectedText', 'replace', 'repeatCount', 'render',
'removedFromStage', 'removed', 'removeNode', 'removeNamespace',
'removeEventListener', 'removeChildAt', 'removeChild',
'relatedObject', 'registerFont', 'registerClassAlias', 'redOffset',
'redMultiplier', 'rect', 'receiveVideo', 'receiveAudio',
'readUnsignedShort', 'readUnsignedInt', 'readUnsignedByte',
'readUTFBytes', 'readUTF', 'readShort', 'readObject',
'readMultiByte', 'readInt', 'readFloat', 'readExternal',
'readDouble', 'readBytes', 'readByte', 'readBoolean', 'ratios',
'rate', 'random', 'quality', 'push', 'publish', 'proxyType',
'prototype', 'propertyIsEnumerable', 'progress',
'processingInstructions', 'printAsBitmap', 'print',
'previousSibling', 'preventDefault', 'prevScene', 'prevFrame',
'prettyPrinting', 'prettyIndent', 'preserveAlpha', 'prependChild',
'prefix', 'pow', 'position', 'pop', 'polar', 'playerType', 'play',
'pixelSnapping', 'pixelDissolve', 'pixelBounds', 'pixelAspectRatio',
'perlinNoise', 'pause', 'parseXML', 'parseInt', 'parseFloat',
'parseCSS', 'parse', 'parentNode', 'parentDomain',
'parentAllowsChild', 'parent', 'parameters', 'paperWidth',
'paperHeight', 'pan', 'paletteMap', 'pageWidth', 'pageHeight',
'overState', 'outsideCutoff', 'os', 'orientation', 'open',
'opaqueBackground', 'onPlayStatus', 'onMetaData', 'onCuePoint',
'offsetPoint', 'offset', 'objectID', 'objectEncoding', 'numLock',
'numLines', 'numFrames', 'numChildren', 'normalize', 'noise',
'nodeValue', 'nodeType', 'nodeName', 'nodeKind', 'noAutoLabeling',
'nextValue', 'nextSibling', 'nextScene', 'nextNameIndex',
'nextName', 'nextFrame', 'netStatus', 'navigateToURL',
'namespaceURI', 'namespaceDeclarations', 'namespace', 'names',
'name', 'muted', 'multiline', 'moveTo', 'mouseY', 'mouseX',
'mouseWheelEnabled', 'mouseWheel', 'mouseUp', 'mouseTarget',
'mouseOver', 'mouseOut', 'mouseMove', 'mouseLeave',
'mouseFocusChange', 'mouseEnabled', 'mouseDown', 'mouseChildren',
'motionTimeout', 'motionLevel', 'monthUTC', 'month',
'modificationDate', 'mode', 'minutesUTC', 'minutes', 'min',
'millisecondsUTC', 'milliseconds', 'method', 'message', 'merge',
'menuSelect', 'menuItemSelect', 'maxScrollV', 'maxScrollH',
'maxLevel', 'maxChars', 'max', 'matrixY', 'matrixX', 'matrix',
'match', 'mask', 'mapPoint', 'mapBitmap', 'map', 'manufacturer',
'macType', 'loopback', 'loop', 'log', 'lock', 'localeCompare',
'localY', 'localX', 'localToGlobal', 'localName',
'localFileReadDisable', 'loaderURL', 'loaderInfo', 'loader',
'loadPolicyFile', 'loadBytes', 'load', 'liveDelay', 'link',
'lineTo', 'lineStyle', 'lineGradientStyle', 'level',
'letterSpacing', 'length', 'leftToRight', 'leftToLeft', 'leftPeak',
'leftMargin', 'left', 'leading', 'lastIndexOf', 'lastIndex',
'lastChild', 'language', 'labels', 'knockout', 'keyUp',
'keyLocation', 'keyFrameInterval', 'keyFocusChange', 'keyDown',
'keyCode', 'kerning', 'join', 'italic', 'isXMLName',
'isPrototypeOf', 'isNaN', 'isFocusInaccessible', 'isFinite',
'isEmpty', 'isDefaultPrevented', 'isDebugger', 'isBuffering',
'isAttribute', 'isAccessible', 'ioError', 'invert', 'invalidate',
'intersects', 'intersection', 'interpolate', 'insideCutoff',
'insertChildBefore', 'insertChildAfter', 'insertBefore', 'inner',
'init', 'info', 'inflatePoint', 'inflate', 'indexOf', 'index',
'indent', 'inScopeNamespaces', 'imeComposition', 'ime',
'ignoreWhitespace', 'ignoreWhite', 'ignoreProcessingInstructions',
'ignoreComments', 'ignoreCase', 'identity', 'idMap', 'id3',
'httpStatus', 'htmlText', 'hoursUTC', 'hours', 'hitTestTextNearPos',
'hitTestState', 'hitTestPoint', 'hitTestObject', 'hitTest',
'hitArea', 'highlightColor', 'highlightAlpha', 'hideObject',
'hideBuiltInItems', 'hide', 'height', 'hasVideoEncoder', 'hasTLS',
'hasStreamingVideo', 'hasStreamingAudio', 'hasSimpleContent',
'hasScreenPlayback', 'hasScreenBroadcast', 'hasProperty',
'hasPrinting', 'hasOwnProperty', 'hasMP3', 'hasIME', 'hasGlyphs',
'hasEventListener', 'hasEmbeddedVideo', 'hasDefinition',
'hasComplexContent', 'hasChildNodes', 'hasAudioEncoder', 'hasAudio',
'hasAccessibility', 'gridFitType', 'greenOffset', 'greenMultiplier',
'graphics', 'gotoAndStop', 'gotoAndPlay', 'globalToLocal', 'global',
'getUTCSeconds', 'getUTCMonth', 'getUTCMinutes',
'getUTCMilliseconds', 'getUTCHours', 'getUTCFullYear', 'getUTCDay',
'getUTCDate', 'getTimezoneOffset', 'getTimer', 'getTime',
'getTextRunInfo', 'getTextFormat', 'getText', 'getStyle',
'getStackTrace', 'getSelectedText', 'getSelected', 'getSeconds',
'getRemote', 'getRect', 'getQualifiedSuperclassName',
'getQualifiedClassName', 'getProperty', 'getPrefixForNamespace',
'getPixels', 'getPixel32', 'getPixel', 'getParagraphLength',
'getObjectsUnderPoint', 'getNamespaceForPrefix', 'getMonth',
'getMinutes', 'getMilliseconds', 'getMicrophone', 'getLocal',
'getLineText', 'getLineOffset', 'getLineMetrics', 'getLineLength',
'getLineIndexOfChar', 'getLineIndexAtPoint', 'getImageReference',
'getHours', 'getFullYear', 'getFirstCharInParagraph',
'getDescendants', 'getDefinitionByName', 'getDefinition', 'getDay',
'getDate', 'getColorBoundsRect', 'getClassByAlias', 'getChildIndex',
'getChildByName', 'getChildAt', 'getCharIndexAtPoint',
'getCharBoundaries', 'getCamera', 'getBounds', 'genre',
'generateFilterRect', 'gain', 'fullYearUTC', 'fullYear',
'fullScreen', 'fscommand', 'fromCharCode', 'framesLoaded',
'frameRate', 'frame', 'fps', 'forwardAndBack', 'formatToString',
'forceSimple', 'forEach', 'fontType', 'fontStyle', 'fontSize',
'fontName', 'font', 'focusRect', 'focusOut', 'focusIn', 'focus',
'flush', 'floor', 'floodFill', 'firstChild', 'findText', 'filters',
'filter', 'fillRect', 'fileList', 'extension', 'extended', 'exp',
'exec', 'exactSettings', 'every', 'eventPhase', 'escapeMultiByte',
'escape', 'errorID', 'error', 'equals', 'enumerateFonts',
'enterFrame', 'endian', 'endFill', 'encodeURIComponent',
'encodeURI', 'enabled', 'embedFonts', 'elements',
'dynamicPropertyWriter', 'dropTarget', 'drawRoundRect', 'drawRect',
'drawEllipse', 'drawCircle', 'draw', 'download', 'downState',
'doubleClickEnabled', 'doubleClick', 'dotall', 'domain',
'docTypeDecl', 'doConversion', 'divisor', 'distance', 'dispose',
'displayState', 'displayMode', 'displayAsPassword', 'dispatchEvent',
'description', 'describeType', 'descent', 'descendants',
'deltaTransformPoint', 'delta', 'deleteProperty', 'delay',
'defaultTextFormat', 'defaultSettings', 'defaultObjectEncoding',
'decodeURIComponent', 'decodeURI', 'decode', 'deblocking',
'deactivate', 'dayUTC', 'day', 'dateUTC', 'date', 'dataFormat',
'data', 'd', 'customItems', 'curveTo', 'currentTarget',
'currentScene', 'currentLabels', 'currentLabel', 'currentFrame',
'currentFPS', 'currentDomain', 'currentCount', 'ctrlKey', 'creator',
'creationDate', 'createTextNode', 'createGradientBox',
'createElement', 'createBox', 'cos', 'copyPixels', 'copyChannel',
'copy', 'conversionMode', 'contextMenuOwner', 'contextMenu',
'contentType', 'contentLoaderInfo', 'content', 'containsRect',
'containsPoint', 'contains', 'constructor', 'connectedProxyType',
'connected', 'connect', 'condenseWhite', 'concatenatedMatrix',
'concatenatedColorTransform', 'concat', 'computeSpectrum',
'compress', 'componentY', 'componentX', 'complete', 'compare',
'comments', 'comment', 'colors', 'colorTransform', 'color', 'code',
'close', 'cloneNode', 'clone', 'client', 'click', 'clearTimeout',
'clearInterval', 'clear', 'clamp', 'children', 'childNodes',
'childIndex', 'childAllowsParent', 'child', 'checkPolicyFile',
'charCount', 'charCodeAt', 'charCode', 'charAt', 'changeList',
'change', 'ceil', 'caretIndex', 'caption', 'capsLock', 'cancelable',
'cancel', 'callee', 'callProperty', 'call', 'cacheAsBitmap', 'c',
'bytesTotal', 'bytesLoaded', 'bytesAvailable', 'buttonMode',
'buttonDown', 'bullet', 'builtInItems', 'bufferTime',
'bufferLength', 'bubbles', 'browse', 'bottomScrollV', 'bottomRight',
'bottom', 'borderColor', 'border', 'bold', 'blurY', 'blurX',
'blueOffset', 'blueMultiplier', 'blockIndent', 'blendMode',
'bitmapData', 'bias', 'beginGradientFill', 'beginFill',
'beginBitmapFill', 'bandwidth', 'backgroundColor', 'background',
'b', 'available', 'avHardwareDisable', 'autoSize', 'attributes',
'attribute', 'attachNetStream', 'attachCamera', 'attachAudio',
'atan2', 'atan', 'asyncError', 'asin', 'ascent', 'artist',
'areSoundsInaccessible', 'areInaccessibleObjectsUnderPoint',
'applyFilter', 'apply', 'applicationDomain', 'appendText',
'appendChild', 'antiAliasType', 'angle', 'alwaysShowSelection',
'altKey', 'alphas', 'alphaOffset', 'alphaMultiplier', 'alpha',
'allowInsecureDomain', 'allowDomain', 'align', 'album',
'addedToStage', 'added', 'addPage', 'addNamespace', 'addHeader',
'addEventListener', 'addChildAt', 'addChild', 'addCallback', 'add',
'activityLevel', 'activity', 'active', 'activating', 'activate',
'actionScriptVersion', 'acos', 'accessibilityProperties', 'abs'
),
8 => array(
'WRAP', 'VERTICAL', 'VARIABLES',
'UTC', 'UPLOAD_COMPLETE_DATA', 'UP', 'UNLOAD', 'UNKNOWN',
'UNIQUESORT', 'TOP_RIGHT', 'TOP_LEFT', 'TOP', 'TIMER_COMPLETE',
'TIMER', 'TEXT_NODE', 'TEXT_INPUT', 'TEXT', 'TAB_INDEX_CHANGE',
'TAB_ENABLED_CHANGE', 'TAB_CHILDREN_CHANGE', 'TAB', 'SYNC',
'SUBTRACT', 'SUBPIXEL', 'STATUS', 'STANDARD', 'SQUARE', 'SQRT2',
'SQRT1_2', 'SPACE', 'SOUND_COMPLETE', 'SOCKET_DATA', 'SHOW_ALL',
'SHIFT', 'SETTINGS_MANAGER', 'SELECT', 'SECURITY_ERROR', 'SCROLL',
'SCREEN', 'ROUND', 'ROLL_OVER', 'ROLL_OUT', 'RIGHT', 'RGB',
'RETURNINDEXEDARRAY', 'RESIZE', 'REPEAT', 'RENDER',
'REMOVED_FROM_STAGE', 'REMOVED', 'REMOTE', 'REGULAR', 'REFLECT',
'RED', 'RADIAL', 'PROGRESS', 'PRIVACY', 'POST', 'POSITIVE_INFINITY',
'PORTRAIT', 'PIXEL', 'PI', 'PENDING', 'PAGE_UP', 'PAGE_DOWN', 'PAD',
'OVERLAY', 'OUTER', 'OPEN', 'NaN', 'NUM_PAD', 'NUMPAD_SUBTRACT',
'NUMPAD_MULTIPLY', 'NUMPAD_ENTER', 'NUMPAD_DIVIDE',
'NUMPAD_DECIMAL', 'NUMPAD_ADD', 'NUMPAD_9', 'NUMPAD_8', 'NUMPAD_7',
'NUMPAD_6', 'NUMPAD_5', 'NUMPAD_4', 'NUMPAD_3', 'NUMPAD_2',
'NUMPAD_1', 'NUMPAD_0', 'NUMERIC', 'NO_SCALE', 'NO_BORDER',
'NORMAL', 'NONE', 'NEVER', 'NET_STATUS', 'NEGATIVE_INFINITY',
'MULTIPLY', 'MOUSE_WHEEL', 'MOUSE_UP', 'MOUSE_OVER', 'MOUSE_OUT',
'MOUSE_MOVE', 'MOUSE_LEAVE', 'MOUSE_FOCUS_CHANGE', 'MOUSE_DOWN',
'MITER', 'MIN_VALUE', 'MICROPHONE', 'MENU_SELECT',
'MENU_ITEM_SELECT', 'MEDIUM', 'MAX_VALUE', 'LOW', 'LOG2E', 'LOG10E',
'LOCAL_WITH_NETWORK', 'LOCAL_WITH_FILE', 'LOCAL_TRUSTED',
'LOCAL_STORAGE', 'LN2', 'LN10', 'LITTLE_ENDIAN', 'LINK',
'LINEAR_RGB', 'LINEAR', 'LIGHT_COLOR', 'LIGHTEN', 'LEFT', 'LCD',
'LAYER', 'LANDSCAPE', 'KOREAN', 'KEY_UP', 'KEY_FOCUS_CHANGE',
'KEY_DOWN', 'JUSTIFY', 'JAPANESE_KATAKANA_HALF',
'JAPANESE_KATAKANA_FULL', 'JAPANESE_HIRAGANA', 'Infinity', 'ITALIC',
'IO_ERROR', 'INVERT', 'INSERT', 'INPUT', 'INNER', 'INIT',
'IME_COMPOSITION', 'IGNORE', 'ID3', 'HTTP_STATUS', 'HORIZONTAL',
'HOME', 'HIGH', 'HARDLIGHT', 'GREEN', 'GET', 'FULLSCREEN', 'FULL',
'FOCUS_OUT', 'FOCUS_IN', 'FLUSHED', 'FLASH9', 'FLASH8', 'FLASH7',
'FLASH6', 'FLASH5', 'FLASH4', 'FLASH3', 'FLASH2', 'FLASH1', 'F9',
'F8', 'F7', 'F6', 'F5', 'F4', 'F3', 'F2', 'F15', 'F14', 'F13',
'F12', 'F11', 'F10', 'F1', 'EXACT_FIT', 'ESCAPE', 'ERROR', 'ERASE',
'ENTER_FRAME', 'ENTER', 'END', 'EMBEDDED', 'ELEMENT_NODE', 'E',
'DYNAMIC', 'DOWN', 'DOUBLE_CLICK', 'DIFFERENCE', 'DEVICE',
'DESCENDING', 'DELETE', 'DEFAULT', 'DEACTIVATE', 'DATA',
'DARK_COLOR', 'DARKEN', 'CRT', 'CONTROL', 'CONNECT', 'COMPLETE',
'COLOR', 'CLOSE', 'CLICK', 'CLAMP', 'CHINESE', 'CHANGE', 'CENTER',
'CASEINSENSITIVE', 'CAPTURING_PHASE', 'CAPS_LOCK', 'CANCEL',
'CAMERA', 'BUBBLING_PHASE', 'BOTTOM_RIGHT', 'BOTTOM_LEFT', 'BOTTOM',
'BOLD_ITALIC', 'BOLD', 'BLUE', 'BINARY', 'BIG_ENDIAN', 'BEVEL',
'BEST', 'BACKSPACE', 'AUTO', 'AT_TARGET', 'ASYNC_ERROR', 'AMF3',
'AMF0', 'ALWAYS', 'ALPHANUMERIC_HALF', 'ALPHANUMERIC_FULL', 'ALPHA',
'ADVANCED', 'ADDED_TO_STAGE', 'ADDED', 'ADD', 'ACTIVITY',
'ACTIONSCRIPT3', 'ACTIONSCRIPT2'
),
//FIX: Must be last in order to avoid conflicts with keywords present
//in other keyword groups, that might get highlighted as part of the URL.
//I know this is not a proper work-around, but should do just fine.
5 => array(
'uint', 'int', 'arguments', 'XMLSocket', 'XMLNodeType', 'XMLNode',
'XMLList', 'XMLDocument', 'XML', 'Video', 'VerifyError',
'URLVariables', 'URLStream', 'URLRequestMethod', 'URLRequestHeader',
'URLRequest', 'URLLoaderDataFormat', 'URLLoader', 'URIError',
'TypeError', 'Transform', 'TimerEvent', 'Timer', 'TextSnapshot',
'TextRenderer', 'TextLineMetrics', 'TextFormatAlign', 'TextFormat',
'TextFieldType', 'TextFieldAutoSize', 'TextField', 'TextEvent',
'TextDisplayMode', 'TextColorType', 'System', 'SyntaxError',
'SyncEvent', 'StyleSheet', 'String', 'StatusEvent', 'StaticText',
'StageScaleMode', 'StageQuality', 'StageAlign', 'Stage',
'StackOverflowError', 'Sprite', 'SpreadMethod', 'SoundTransform',
'SoundMixer', 'SoundLoaderContext', 'SoundChannel', 'Sound',
'Socket', 'SimpleButton', 'SharedObjectFlushStatus', 'SharedObject',
'Shape', 'SecurityPanel', 'SecurityErrorEvent', 'SecurityError',
'SecurityDomain', 'Security', 'ScriptTimeoutError', 'Scene',
'SWFVersion', 'Responder', 'RegExp', 'ReferenceError', 'Rectangle',
'RangeError', 'QName', 'Proxy', 'ProgressEvent',
'PrintJobOrientation', 'PrintJobOptions', 'PrintJob', 'Point',
'PixelSnapping', 'ObjectEncoding', 'Object', 'Number', 'NetStream',
'NetStatusEvent', 'NetConnection', 'Namespace', 'MovieClip',
'MouseEvent', 'Mouse', 'MorphShape', 'Microphone', 'MemoryError',
'Matrix', 'Math', 'LocalConnection', 'LoaderInfo', 'LoaderContext',
'Loader', 'LineScaleMode', 'KeyboardEvent', 'Keyboard',
'KeyLocation', 'JointStyle', 'InvalidSWFError',
'InterpolationMethod', 'InteractiveObject', 'IllegalOperationError',
'IOErrorEvent', 'IOError', 'IMEEvent', 'IMEConversionMode', 'IME',
'IExternalizable', 'IEventDispatcher', 'IDynamicPropertyWriter',
'IDynamicPropertyOutput', 'IDataOutput', 'IDataInput', 'ID3Info',
'IBitmapDrawable', 'HTTPStatusEvent', 'GridFitType', 'Graphics',
'GradientType', 'GradientGlowFilter', 'GradientBevelFilter',
'GlowFilter', 'Function', 'FrameLabel', 'FontType', 'FontStyle',
'Font', 'FocusEvent', 'FileReferenceList', 'FileReference',
'FileFilter', 'ExternalInterface', 'EventPhase', 'EventDispatcher',
'Event', 'EvalError', 'ErrorEvent', 'Error', 'Endian', 'EOFError',
'DropShadowFilter', 'DisplayObjectContainer', 'DisplayObject',
'DisplacementMapFilterMode', 'DisplacementMapFilter', 'Dictionary',
'DefinitionError', 'Date', 'DataEvent', 'ConvolutionFilter',
'ContextMenuItem', 'ContextMenuEvent', 'ContextMenuBuiltInItems',
'ContextMenu', 'ColorTransform', 'ColorMatrixFilter', 'Class',
'CapsStyle', 'Capabilities', 'Camera', 'CSMSettings', 'ByteArray',
'Boolean', 'BlurFilter', 'BlendMode', 'BitmapFilterType',
'BitmapFilterQuality', 'BitmapFilter', 'BitmapDataChannel',
'BitmapData', 'Bitmap', 'BevelFilter', 'AsyncErrorEvent', 'Array',
'ArgumentError', 'ApplicationDomain', 'AntiAliasType',
'ActivityEvent', 'ActionScriptVersion', 'AccessibilityProperties',
'Accessibility', 'AVM1Movie'
)
),
'SYMBOLS' => array(
'(', ')', '[', ']', '{', '}', '!', '%', '&', '*', '|', '/', '<', '>', '^', '-', '+', '~', '?', ':', ';', '.', ','
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => true,
2 => true,
3 => true,
4 => true,
5 => true,
6 => true,
7 => true,
8 => true
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #0033ff; font-weight: bold;',
2 => 'color: #6699cc; font-weight: bold;',
3 => 'color: #339966; font-weight: bold;',
4 => 'color: #9900cc; font-weight: bold;',
5 => 'color: #004993;',
6 => 'color: #004993;',
7 => 'color: #004993;',
8 => 'color: #004993;'
),
'COMMENTS' => array(
1 => 'color: #009900; font-style: italic;',
2 => 'color: #009966; font-style: italic;',
'MULTI' => 'color: #3f5fbf;'
),
'ESCAPE_CHAR' => array(
0 => ''
),
'BRACKETS' => array(
0 => 'color: #000000;'
),
'STRINGS' => array(
0 => 'color: #990000;'
),
'NUMBERS' => array(
0 => 'color: #000000; font-weight:bold;'
),
'METHODS' => array(
0 => 'color: #000000;',
),
'SYMBOLS' => array(
0 => 'color: #000066; font-weight: bold;'
),
'REGEXPS' => array(
),
'SCRIPT' => array(
)
),
'URLS' => array(
1 => '',
2 => '',
3 => '',
4 => '',
5 => 'http://www.google.com/search?q={FNAMEL}%20inurl:http://livedocs.adobe.com/flex/201/langref/%20inurl:{FNAMEL}.html',
6 => '',
7 => '',
8 => ''
),
'OOLANG' => false,//Save some time as OO identifiers aren't used
'OBJECT_SPLITTERS' => array(
// commented out because it's not very relevant for AS, as all properties, methods and constants are dot-accessed.
// I believe it's preferable to have package highlighting for example, which is not possible with this enabled.
// 0 => '.'
),
'REGEXPS' => array(
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(),
'HIGHLIGHT_STRICT_BLOCK' => array()
);
?>

135
sources/inc/geshi/ada.php Normal file
View file

@ -0,0 +1,135 @@
<?php
/*************************************************************************************
* ada.php
* -------
* Author: Tux (tux@inmail.cz)
* Copyright: (c) 2004 Tux (http://tux.a4.cz/), Nigel McNie (http://qbnz.com/highlighter)
* Release Version: 1.0.8.11
* Date Started: 2004/07/29
*
* Ada language file for GeSHi.
* Words are from SciTe configuration file
*
* CHANGES
* -------
* 2004/11/27 (1.0.2)
* - Added support for multiple object splitters
* 2004/10/27 (1.0.1)
* - Removed apostrophe as string delimiter
* - Added URL support
* 2004/08/05 (1.0.0)
* - First Release
*
* TODO (updated 2004/11/27)
* -------------------------
*
*************************************************************************************
*
* This file is part of GeSHi.
*
* GeSHi is free software; 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.
*
* GeSHi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GeSHi; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
************************************************************************************/
$language_data = array (
'LANG_NAME' => 'Ada',
'COMMENT_SINGLE' => array(1 => '--'),
'COMMENT_MULTI' => array('/*' => '*/'),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array('"'),
'ESCAPE_CHAR' => '\\',
'KEYWORDS' => array(
1 => array(
'begin', 'declare', 'do', 'else', 'elsif', 'exception', 'for', 'if',
'is', 'loop', 'while', 'then', 'end', 'select', 'case', 'until',
'goto', 'return'
),
2 => array(
'abs', 'and', 'at', 'mod', 'not', 'or', 'rem', 'xor'
),
3 => array(
'abort', 'abstract', 'accept', 'access', 'aliased', 'all', 'array',
'body', 'constant', 'delay', 'delta', 'digits', 'entry', 'exit',
'function', 'generic', 'in', 'interface', 'limited', 'new', 'null',
'of', 'others', 'out', 'overriding', 'package', 'pragma', 'private',
'procedure', 'protected', 'raise', 'range', 'record', 'renames',
'requeue', 'reverse', 'separate', 'subtype', 'synchronized',
'tagged', 'task', 'terminate', 'type', 'use', 'when', 'with'
)
),
'SYMBOLS' => array(
'(', ')'
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => false,
2 => false,
3 => false,
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #00007f;',
2 => 'color: #0000ff;',
3 => 'color: #46aa03; font-weight:bold;',
),
'BRACKETS' => array(
0 => 'color: #66cc66;'
),
'COMMENTS' => array(
1 => 'color: #adadad; font-style: italic;',
'MULTI' => 'color: #808080; font-style: italic;'
),
'ESCAPE_CHAR' => array(
0 => 'color: #000099; font-weight: bold;'
),
'BRACKETS' => array(
0 => 'color: #66cc66;'
),
'STRINGS' => array(
0 => 'color: #7f007f;'
),
'NUMBERS' => array(
0 => 'color: #ff0000;'
),
'METHODS' => array(
1 => 'color: #202020;'
),
'SYMBOLS' => array(
0 => 'color: #66cc66;'
),
'REGEXPS' => array(
),
'SCRIPT' => array(
)
),
'URLS' => array(
1 => '',
2 => '',
3 => ''
),
'OOLANG' => true,
'OBJECT_SPLITTERS' => array(
1 => '.'
),
'REGEXPS' => array(
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(
),
'HIGHLIGHT_STRICT_BLOCK' => array(
)
);
?>

View file

@ -0,0 +1,329 @@
<?php
/*************************************************************************************
* algol68.php
* --------
* Author: Neville Dempsey (NevilleD.sourceforge@sgr-a.net)
* Copyright: (c) 2010 Neville Dempsey (https://sourceforge.net/projects/algol68/files/)
* Release Version: 1.0.8.11
* Date Started: 2010/04/24
*
* ALGOL 68 language file for GeSHi.
*
* CHANGES
* -------
* 2010/04/24 (1.0.8.8.0)
* - First Release - machine generated by http://rosettacode.org/geshi/
* 2010/05/24 (1.0.8.8.1)
* - #2324 - converted comment detection to RegEx
* 2010/06/16 (1.0.8.8.2)
* - separate symbols from keywords - quick fix
* 2010/06/16 (1.0.8.8.3)
* - reverse length order symbols
* - Add RegEx for BITS and REAL literals (INT to do)
* - recognise LONG and SHORT prefixes to literals
* 2010/07/23 (1.0.8.8.4)
* - fix errors detected by langcheck.php, eg rm tab, fix indenting, rm duplicate keywords, fix symbols as keywords etc
* - removed bulk of local variables from name space.
* - unfolded arrays
*
* TODO (updated yyyy/mm/dd)
* -------------------------
* - Use "Parser Control" to fix KEYWORD parsing, eg: (INT minus one= -1; print(ABSminus one))
* - Parse $FORMATS$ more fully - if possible.
* - Pull reserved words from the source of A68G and A68RS
* - Pull stdlib PROC/OP/MODE symbols from the soruce of A68G and A68RS
* - Pull PROC/OP/MODE extensions from the soruce of A68G and A68RS
* - Use RegEx to detect extended precision PROC names, eg 'long long sin' etc
* - Use RegEx to detect white space std PROC names, eg 'new line'
* - Use RegEx to detect white space ext PROC names, eg 'cgs speed of light'
* - Use RegEx to detect BOLD symbols, eg userdefined MODEs and OPs
* - Add REgEx for INT literals - Adding INT breaks formatting...
* - Adding PIPE as a key word breaks formatting of "|" symbols!!
*
*************************************************************************************
*
* This file is part of GeSHi.
*
* GeSHi is free software; 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.
*
* GeSHi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GeSHi; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
************************************************************************************/
if(!function_exists('geshi_langfile_algol68_vars')) {
function geshi_langfile_algol68_vars(){
$pre='(?<![0-9a-z_\.])';
$post='?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)';
$post=""; # assuming the RegEx is greedy #
$_="\s*";
$srad="Rr"; $rrad="[".$srad."]"; # either one digit, OR opt-space in digits #
$sbin="0-1"; $rbin="[".$sbin."]"; $_bin=$rbin."(?:[".$sbin."\s]*".$rbin."|)";
$snib="0-3"; $rnib="[".$snib."]"; $_nib=$rnib."(?:[".$snib."\s]*".$rnib."|)";
$soct="0-7"; $roct="[".$soct."]"; $_oct=$roct."(?:[".$soct."\s]*".$roct."|)";
$sdec="0-9"; $rdec="[".$sdec."]"; $_dec=$rdec."(?:[".$sdec."\s]*".$rdec."|)";
$shex="0-9A-Fa-f"; $rhex="[".$shex."]"; $_hex=$rhex."(?:[".$shex."\s]*".$rhex."|)";
# Define BITS: #
$prebits=$pre; $postbits=$post;
$bl="2".$_.$rrad.$_.$_bin;
$bl=$bl."|"."2".$_.$rrad.$_.$_bin;
$bl=$bl."|"."4".$_.$rrad.$_.$_nib;
$bl=$bl."|"."8".$_.$rrad.$_.$_oct;
$bl=$bl."|"."1".$_."0".$_.$rrad.$_.$_dec;
$bl=$bl."|"."1".$_."6".$_.$rrad.$_.$_hex;
# Define INT: #
$preint=$pre; $postint=$post;
# for some reason ".0 e - 2" is not recognised, but ".0 e + 2" IS!
# work around: remove spaces between sign and digits! Maybe because
# of the Unary '-' Operator
$sign_="(?:-|\-|[-]|[\-]|\+|)"; # attempts #
$sign_="(?:-\s*|\+\s*|)"; # n.b. sign is followed by white space #
$_int=$sign_.$_dec;
$il= $_int; # +_9 #
$GESHI_NUMBER_INT_BASIC='(?:(?<![0-9a-z_\.%])|(?<=\.\.))(?<![\d\.]e[+\-])([1-9]\d*?|0)(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)';
# Define REAL: #
$prereal=$pre; $postreal=$post;
$sexp="Ee\\\\"; $_exp="(?:⏨|[".$sexp."])".$_.$_int;
$_decimal="[.]".$_.$_dec;
# Add permitted permutations of various parts #
$rl= $_int.$_.$_decimal.$_.$_exp; # +_9_._9_e_+_9 #
$rl=$rl."|".$_int.$_."[.]".$_.$_exp; # +_9_.___e_+_9 #
$rl=$rl."|".$_int.$_.$_exp; # +_9_____e_+_9 #
$rl=$rl."|".$sign_.$_decimal.$_.$_exp; # +___._9_e_+_9 #
$rl=$rl."|".$_int.$_.$_decimal; # +_9_._9 #
$rl=$rl."|".$sign_.$_decimal; # +___._9 #
# The following line damaged formatting...
#$rl=$rl."|".$_int; # +_9 #
# Apparently Algol68 does not support '2.', c.f. Algol 68G
#$rl=$rl."|".$_int.$_."[.]"; # +_9_. #
# Literal prefixes are overridden by KEYWORDS :-(
$LONGS="(?:(?:(LONG\s+)*|(SHORT\s+))*|)";
return array(
"BITS" => $prebits.$LONGS."(?:".$bl.")".$postbits,
"INT" => $preint.$LONGS."(?:".$il.")".$postint,
"REAL" => $prereal.$LONGS."(?:".$rl.")".$postreal,
"BOLD" => 'color: #b1b100; font-weight: bold;',
"ITALIC" => 'color: #b1b100;', # procedures traditionally italic #
"NONSTD" => 'color: #FF0000; font-weight: bold;', # RED #
"COMMENT" => 'color: #666666; font-style: italic;'
);
}
}
$a68=geshi_langfile_algol68_vars();
$language_data = array(
'LANG_NAME' => 'ALGOL 68',
'COMMENT_SINGLE' => array(),
'COMMENT_MULTI' => array(
'¢' => '¢',
'£' => '£',
'#' => '#',
),
'COMMENT_REGEXP' => array(
1 => '/\bCO((?:MMENT)?)\b.*?\bCO\\1\b/i',
2 => '/\bPR((?:AGMAT)?)\b.*?\bPR\\1\b/i',
3 => '/\bQUOTE\b.*?\bQUOTE\b/i'
),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array('"'),
'ESCAPE_CHAR' => '"',
'NUMBERS' => GESHI_NUMBER_HEX_SUFFIX, # Warning: Feature!! #
# GESHI_NUMBER_HEX_SUFFIX, # Attempt ignore default #
'KEYWORDS' => array(
# Extensions
1 => array('KEEP', 'FINISH', 'USE', 'SYSPROCS', 'IOSTATE', 'USING', 'ENVIRON', 'PROGRAM', 'CONTEXT'),
# 2 => array('CASE', 'IN', 'OUSE', 'IN', 'OUT', 'ESAC', '(', '|', '|:', ')', 'FOR', 'FROM', 'TO', 'BY', 'WHILE', 'DO', 'OD', 'IF', 'THEN', 'ELIF', 'THEN', 'ELSE', 'FI', 'PAR', 'BEGIN', 'EXIT', 'END', 'GO', 'GOTO', 'FORALL', 'UPTO', 'DOWNTO', 'FOREACH', 'ASSERT'), #
2 => array('CASE', 'IN', 'OUSE', /* 'IN',*/ 'OUT', 'ESAC', 'PAR', 'BEGIN', 'EXIT', 'END', 'GO TO', 'GOTO', 'FOR', 'FROM', 'TO', 'BY', 'WHILE', 'DO', 'OD', 'IF', 'THEN', 'ELIF', /* 'THEN',*/ 'ELSE', 'FI' ),
3 => array('BITS', 'BOOL', 'BYTES', 'CHAR', 'COMPL', 'INT', 'REAL', 'SEMA', 'STRING', 'VOID'),
4 => array('MODE', 'OP', 'PRIO', 'PROC', 'FLEX', 'HEAP', 'LOC', 'REF', 'LONG', 'SHORT', 'EITHER'),
# Extensions or deprecated keywords
# 'PIPE': keyword somehow interferes with the internal operation of GeSHi
5 => array('FORALL', 'UPTO', 'DOWNTO', 'FOREACH', 'ASSERT', 'CTB', 'CT', 'CTAB', 'COMPLEX', 'VECTOR', 'SOUND' /*, 'PIPE'*/),
6 => array('CHANNEL', 'FILE', 'FORMAT', 'STRUCT', 'UNION', 'OF'),
# '(', '|', '|:', ')', #
# 7 => array('OF', 'AT', '@', 'IS', ':=:', 'ISNT', ':/=:', ':≠:', 'CTB', 'CT', '::', 'CTAB', '::=', 'TRUE', 'FALSE', 'EMPTY', 'NIL', '○', 'SKIP', '~'),
7 => array('AT', 'IS', 'ISNT', 'TRUE', 'FALSE', 'EMPTY', 'NIL', 'SKIP'),
8 => array('NOT', 'UP', 'DOWN', 'LWB', 'UPB', /* '-',*/ 'ABS', 'ARG', 'BIN', 'ENTIER', 'LENG', 'LEVEL', 'ODD', 'REPR', 'ROUND', 'SHORTEN', 'CONJ', 'SIGN'),
# OPERATORS ordered roughtly by PRIORITY #
# 9 => array('¬', '↑', '↓', '⌊', '⌈', '~', '⎩', '⎧'),
# 10 => array('+*', 'I', '+×', '⊥', '!', '⏨'),
10 => array('I'),
# 11 => array('SHL', 'SHR', '**', 'UP', 'DOWN', 'LWB', 'UPB', '↑', '↓', '⌊', '⌈', '⎩', '⎧'),
11 => array('SHL', 'SHR', /*'UP', 'DOWN', 'LWB', 'UPB'*/),
# 12 => array('*', '/', '%', 'OVER', '%*', 'MOD', 'ELEM', '×', '÷', '÷×', '÷*', '%×', '□', '÷:'),
12 => array('OVER', 'MOD', 'ELEM'),
# 13 => array('-', '+'),
# 14 => array('<', 'LT', '<=', 'LE', '>=', 'GE', '>', 'GT', '≤', '≥'),
14 => array('LT', 'LE', 'GE', 'GT'),
# 15 => array('=', 'EQ', '/=', 'NE', '≠', '~='),
15 => array('EQ', 'NE'),
# 16 => array('&', 'AND', '∧', 'OR', '', '/\\', '\\/'),
16 => array('AND', 'OR'),
17 => array('MINUSAB', 'PLUSAB', 'TIMESAB', 'DIVAB', 'OVERAB', 'MODAB', 'PLUSTO'),
# 18 => array('-:=', '+:=', '*:=', '/:=', '%:=', '%*:=', '+=:', '×:=', '÷:=', '÷×:=', '÷*:=', '%×:=', '÷::=', 'MINUS', 'PLUS', 'DIV', 'MOD', 'PRUS'),
# Extensions or deprecated keywords
18 => array('MINUS', 'PLUS', 'DIV', /* 'MOD',*/ 'PRUS', 'IS NOT'),
# Extensions or deprecated keywords
19 => array('THEF', 'ANDF', 'ORF', 'ANDTH', 'OREL', 'ANDTHEN', 'ORELSE'),
# Built in procedures - from standard prelude #
20 => array('int lengths', 'intlengths', 'int shorths', 'intshorths', 'max int', 'maxint', 'real lengths', 'reallengths', 'real shorths', 'realshorths', 'bits lengths', 'bitslengths', 'bits shorths', 'bitsshorths', 'bytes lengths', 'byteslengths', 'bytes shorths', 'bytesshorths', 'max abs char', 'maxabschar', 'int width', 'intwidth', 'long int width', 'longintwidth', 'long long int width', 'longlongintwidth', 'real width', 'realwidth', 'long real width', 'longrealwidth', 'long long real width', 'longlongrealwidth', 'exp width', 'expwidth', 'long exp width', 'longexpwidth', 'long long exp width', 'longlongexpwidth', 'bits width', 'bitswidth', 'long bits width', 'longbitswidth', 'long long bits width', 'longlongbitswidth', 'bytes width', 'byteswidth', 'long bytes width', 'longbyteswidth', 'max real', 'maxreal', 'small real', 'smallreal', 'long max int', 'longmaxint', 'long long max int', 'longlongmaxint', 'long max real', 'longmaxreal', 'long small real', 'longsmallreal', 'long long max real', 'longlongmaxreal', 'long long small real', 'longlongsmallreal', 'long max bits', 'longmaxbits', 'long long max bits', 'longlongmaxbits', 'null character', 'nullcharacter', 'blank', 'flip', 'flop', 'error char', 'errorchar', 'exp char', 'expchar', 'newline char', 'newlinechar', 'formfeed char', 'formfeedchar', 'tab char', 'tabchar'),
21 => array('stand in channel', 'standinchannel', 'stand out channel', 'standoutchannel', 'stand back channel', 'standbackchannel', 'stand draw channel', 'standdrawchannel', 'stand error channel', 'standerrorchannel'),
22 => array('put possible', 'putpossible', 'get possible', 'getpossible', 'bin possible', 'binpossible', 'set possible', 'setpossible', 'reset possible', 'resetpossible', 'reidf possible', 'reidfpossible', 'draw possible', 'drawpossible', 'compressible', 'on logical file end', 'onlogicalfileend', 'on physical file end', 'onphysicalfileend', 'on line end', 'onlineend', 'on page end', 'onpageend', 'on format end', 'onformatend', 'on value error', 'onvalueerror', 'on open error', 'onopenerror', 'on transput error', 'ontransputerror', 'on format error', 'onformaterror', 'open', 'establish', 'create', 'associate', 'close', 'lock', 'scratch', 'space', 'new line', 'newline', 'print', 'write f', 'writef', 'print f', 'printf', 'write bin', 'writebin', 'print bin', 'printbin', 'read f', 'readf', 'read bin', 'readbin', 'put f', 'putf', 'get f', 'getf', 'make term', 'maketerm', 'make device', 'makedevice', 'idf', 'term', 'read int', 'readint', 'read long int', 'readlongint', 'read long long int', 'readlonglongint', 'read real', 'readreal', 'read long real', 'readlongreal', 'read long long real', 'readlonglongreal', 'read complex', 'readcomplex', 'read long complex', 'readlongcomplex', 'read long long complex', 'readlonglongcomplex', 'read bool', 'readbool', 'read bits', 'readbits', 'read long bits', 'readlongbits', 'read long long bits', 'readlonglongbits', 'read char', 'readchar', 'read string', 'readstring', 'print int', 'printint', 'print long int', 'printlongint', 'print long long int', 'printlonglongint', 'print real', 'printreal', 'print long real', 'printlongreal', 'print long long real', 'printlonglongreal', 'print complex', 'printcomplex', 'print long complex', 'printlongcomplex', 'print long long complex', 'printlonglongcomplex', 'print bool', 'printbool', 'print bits', 'printbits', 'print long bits', 'printlongbits', 'print long long bits', 'printlonglongbits', 'print char', 'printchar', 'print string', 'printstring', 'whole', 'fixed', 'float'),
23 => array('pi', 'long pi', 'longpi', 'long long pi', 'longlongpi'),
24 => array('sqrt', 'curt', 'cbrt', 'exp', 'ln', 'log', 'sin', 'arc sin', 'arcsin', 'cos', 'arc cos', 'arccos', 'tan', 'arc tan', 'arctan', 'long sqrt', 'longsqrt', 'long curt', 'longcurt', 'long cbrt', 'longcbrt', 'long exp', 'longexp', 'long ln', 'longln', 'long log', 'longlog', 'long sin', 'longsin', 'long arc sin', 'longarcsin', 'long cos', 'longcos', 'long arc cos', 'longarccos', 'long tan', 'longtan', 'long arc tan', 'longarctan', 'long long sqrt', 'longlongsqrt', 'long long curt', 'longlongcurt', 'long long cbrt', 'longlongcbrt', 'long long exp', 'longlongexp', 'long long ln', 'longlongln', 'long long log', 'longlonglog', 'long long sin', 'longlongsin', 'long long arc sin', 'longlongarcsin', 'long long cos', 'longlongcos', 'long long arc cos', 'longlongarccos', 'long long tan', 'longlongtan', 'long long arc tan', 'longlongarctan'),
25 => array('first random', 'firstrandom', 'next random', 'nextrandom', 'long next random', 'longnextrandom', 'long long next random', 'longlongnextrandom'),
26 => array('real', 'bits pack', 'bitspack', 'long bits pack', 'longbitspack', 'long long bits pack', 'longlongbitspack', 'bytes pack', 'bytespack', 'long bytes pack', 'longbytespack', 'char in string', 'charinstring', 'last char in string', 'lastcharinstring', 'string in string', 'stringinstring'),
27 => array('utc time', 'utctime', 'local time', 'localtime', 'argc', 'argv', 'get env', 'getenv', 'reset errno', 'reseterrno', 'errno', 'strerror'),
28 => array('sinh', 'long sinh', 'longsinh', 'long long sinh', 'longlongsinh', 'arc sinh', 'arcsinh', 'long arc sinh', 'longarcsinh', 'long long arc sinh', 'longlongarcsinh', 'cosh', 'long cosh', 'longcosh', 'long long cosh', 'longlongcosh', 'arc cosh', 'arccosh', 'long arc cosh', 'longarccosh', 'long long arc cosh', 'longlongarccosh', 'tanh', 'long tanh', 'longtanh', 'long long tanh', 'longlongtanh', 'arc tanh', 'arctanh', 'long arc tanh', 'longarctanh', 'long long arc tanh', 'longlongarctanh', 'arc tan2', 'arctan2', 'long arc tan2', 'longarctan2', 'long long arc tan2', 'longlongarctan2'),
29 => array('complex sqrt', 'complexsqrt', 'long complex sqrt', 'longcomplexsqrt', 'long long complex sqrt', 'longlongcomplexsqrt', 'complex exp', 'complexexp', 'long complex exp', 'longcomplexexp', 'long long complex exp', 'longlongcomplexexp', 'complex ln', 'complexln', 'long complex ln', 'longcomplexln', 'long long complex ln', 'longlongcomplexln', 'complex sin', 'complexsin', 'long complex sin', 'longcomplexsin', 'long long complex sin', 'longlongcomplexsin', 'complex arc sin', 'complexarcsin', 'long complex arc sin', 'longcomplexarcsin', 'long long complex arc sin', 'longlongcomplexarcsin', 'complex cos', 'complexcos', 'long complex cos', 'longcomplexcos', 'long long complex cos', 'longlongcomplexcos', 'complex arc cos', 'complexarccos', 'long complex arc cos', 'longcomplexarccos', 'long long complex arc cos', 'longlongcomplexarccos', 'complex tan', 'complextan', 'long complex tan', 'longcomplextan', 'long long complex tan', 'longlongcomplextan', 'complex arc tan', 'complexarctan', 'long complex arc tan', 'longcomplexarctan', 'long long complex arc tan', 'longlongcomplexarctan', 'complex sinh', 'complexsinh', 'complex arc sinh', 'complexarcsinh', 'complex cosh', 'complexcosh', 'complex arc cosh', 'complexarccosh', 'complex tanh', 'complextanh', 'complex arc tanh', 'complexarctanh')
),
'SYMBOLS' => array(
1 => array( /* reverse length sorted... */ '÷×:=', '%×:=', ':≠:', '÷*:=', '÷::=', '%*:=', ':/=:', '×:=', '÷:=', '÷×', '%:=', '%×', '*:=', '+:=', '+=:', '+×', '-:=', '/:=', '::=', ':=:', '÷*', '÷:', '↑', '↓', '∧', '', '≠', '≤', '≥', '⊥', '⌈', '⌊', '⎧', '⎩', /* '⏨', */ '□', '○', '%*', '**', '+*', '/=', '::', '/\\', '\\/', '<=', '>=', '|:', '~=', '¬', '×', '÷', '!', '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '=', '>', '?', '@', '[', ']', '^', '{', '|', '}', '~')
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => true,
2 => true,
3 => true,
4 => true,
5 => true,
6 => true,
7 => true,
8 => true,
# 9 => true,
10 => true,
11 => true,
12 => true,
# 13 => true,
14 => true,
15 => true,
16 => true,
17 => true,
18 => true,
19 => true,
20 => true,
21 => true,
22 => true,
23 => true,
24 => true,
25 => true,
26 => true,
27 => true,
28 => true,
29 => true
),
'STYLES' => array(
'KEYWORDS' => array(
1 => $a68['NONSTD'], 2 => $a68['BOLD'], 3 => $a68['BOLD'], 4 => $a68['BOLD'],
5 => $a68['NONSTD'], 6 => $a68['BOLD'], 7 => $a68['BOLD'], 8 => $a68['BOLD'],
/* 9 => $a68['BOLD'],*/ 10 => $a68['BOLD'], 11 => $a68['BOLD'], 12 => $a68['BOLD'],
/* 13 => $a68['BOLD'],*/ 14 => $a68['BOLD'], 15 => $a68['BOLD'], 16 => $a68['BOLD'], 17 => $a68['BOLD'],
18 => $a68['NONSTD'], 19 => $a68['NONSTD'],
20 => $a68['ITALIC'], 21 => $a68['ITALIC'], 22 => $a68['ITALIC'], 23 => $a68['ITALIC'],
24 => $a68['ITALIC'], 25 => $a68['ITALIC'], 26 => $a68['ITALIC'], 27 => $a68['ITALIC'],
28 => $a68['ITALIC'], 29 => $a68['ITALIC']
),
'COMMENTS' => array(
1 => $a68['COMMENT'], 2 => $a68['COMMENT'], 3 => $a68['COMMENT'], /* 4 => $a68['COMMENT'],
5 => $a68['COMMENT'],*/ 'MULTI' => $a68['COMMENT']
),
'ESCAPE_CHAR' => array(
0 => 'color: #000099; font-weight: bold;'
),
'BRACKETS' => array(
0 => 'color: #009900;'
),
'STRINGS' => array(
0 => 'color: #0000ff;'
),
'NUMBERS' => array(
0 => 'color: #cc66cc;',
),
'METHODS' => array(
0 => 'color: #004000;',
1 => 'color: #004000;'
),
'SYMBOLS' => array(
0 => 'color: #339933;',
1 => 'color: #339933;'
),
'REGEXPS' => array(
0 => 'color: #cc66cc;', # BITS #
1 => 'color: #cc66cc;', # REAL #
/* 2 => 'color: #cc66cc;', # INT # */
),
'SCRIPT' => array()
),
'URLS' => array(
1 => '',
2 => '',
3 => '',
4 => '',
5 => '',
6 => '',
7 => '',
8 => '',
# 9 => '',
10 => '',
11 => '',
12 => '',
# 13 => '',
14 => '',
15 => '',
16 => '',
17 => '',
18 => '',
19 => '',
20 => '',
21 => '',
22 => '',
23 => '',
24 => '',
25 => '',
26 => '',
27 => '',
28 => '',
29 => ''
),
'OOLANG' => true,
'OBJECT_SPLITTERS' => array(
0 => '→',
1 => 'OF'
),
'REGEXPS' => array(
0 => $a68['BITS'],
1 => $a68['REAL']
# 2 => $a68['INT'], # Breaks formatting for some reason #
# 2 => $GESHI_NUMBER_INT_BASIC # Also breaks formatting #
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(),
'HIGHLIGHT_STRICT_BLOCK' => array()
);
unset($a68);
?>

View file

@ -0,0 +1,483 @@
<?php
/*************************************************************************************
* apache.php
* ----------
* Author: Tux (tux@inmail.cz)
* Copyright: (c) 2004 Tux (http://tux.a4.cz/), Nigel McNie (http://qbnz.com/highlighter)
* Release Version: 1.0.8.11
* Date Started: 2004/29/07
*
* Apache language file for GeSHi.
* Words are from SciTe configuration file
*
* CHANGES
* -------
* 2008/17/06 (1.0.8)
* - Added support for apache configuration sections (milian)
* - Added missing php keywords (milian)
* - Added some more keywords
* - Disabled highlighting of brackets by default
* 2004/11/27 (1.0.2)
* - Added support for multiple object splitters
* 2004/10/27 (1.0.1)
* - Added support for URLs
* 2004/08/05 (1.0.0)
* - First Release
*
* TODO (updated 2004/07/29)
* -------------------------
*
*************************************************************************************
*
* This file is part of GeSHi.
*
* GeSHi is free software; 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.
*
* GeSHi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GeSHi; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
************************************************************************************/
$language_data = array (
'LANG_NAME' => 'Apache configuration',
'COMMENT_SINGLE' => array(1 => '#'),
'COMMENT_MULTI' => array(),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'", '"'),
'ESCAPE_CHAR' => '\\',
'KEYWORDS' => array(
/*keywords*/
1 => array(
//core.c
'AcceptFilter','AcceptPathInfo','AccessConfig','AccessFileName',
'AddDefaultCharset','AddOutputFilterByType','AllowEncodedSlashes',
'AllowOverride','AuthName','AuthType','ContentDigest',
'CoreDumpDirectory','DefaultType','DocumentRoot','EnableMMAP',
'EnableSendfile','ErrorDocument','ErrorLog','FileETag','ForceType',
'HostnameLookups','Include','LimitInternalRecursion',
'LimitRequestBody','LimitRequestFields','LimitRequestFieldsize',
'LimitRequestLine','LimitXMLRequestBody','LogLevel','MaxMemFree',
'MaxRequestsPerChild','NameVirtualHost','Options','PidFile','Port',
'Protocol','Require','RLimitCPU','RLimitMEM','RLimitNPROC',
'Satisfy','ScoreBoardFile','ServerAdmin','ServerAlias','ServerName',
'ServerPath','ServerRoot','ServerSignature','ServerTokens',
'SetHandler','SetInputFilter','SetOutputFilter','ThreadStackSize',
'Timeout','TraceEnable','UseCanonicalName',
'UseCanonicalPhysicalPort',
//http_core.c
'KeepAlive','KeepAliveTimeout','MaxKeepAliveRequests',
//mod_actions.c
'Action','Script',
//mod_alias.c
'Alias','AliasMatch','Redirect','RedirectMatch','RedirectPermanent',
'RedirectTemp','ScriptAlias','ScriptAliasMatch',
//mod_asis.c
//mod_auth_basic.c
'AuthBasicAuthoritative','AuthBasicProvider',
//mod_auth_digest.c
'AuthDigestAlgorithm','AuthDigestDomain','AuthDigestNcCheck',
'AuthDigestNonceFormat','AuthDigestNonceLifetime',
'AuthDigestProvider','AuthDigestQop','AuthDigestShmemSize',
//mod_authn_alias.c
//mod_authn_anon.c
'Anonymous','Anonymous_LogEmail','Anonymous_MustGiveEmail',
'Anonymous_NoUserId','Anonymous_VerifyEmail',
//mod_authn_dbd.c
'AuthDBDUserPWQuery','AuthDBDUserRealmQuery',
//mod_authn_dbm.c
'AuthDBMType','AuthDBMUserFile',
//mod_authn_default.c
'AuthDefaultAuthoritative',
//mod_authn_file.c
'AuthUserFile',
//mod_authnz_ldap.c
'AuthLDAPBindDN','AuthLDAPBindPassword','AuthLDAPCharsetConfig',
'AuthLDAPCompareDNOnServer','AuthLDAPDereferenceAliases',
'AuthLDAPGroupAttribute','AuthLDAPGroupAttributeIsDN',
'AuthLDAPRemoteUserAttribute','AuthLDAPRemoteUserIsDN',
'AuthLDAPURL','AuthzLDAPAuthoritative',
//mod_authz_dbm.c
'AuthDBMGroupFile','AuthzDBMAuthoritative','AuthzDBMType',
//mod_authz_default.c
'AuthzDefaultAuthoritative',
//mod_authz_groupfile.c
'AuthGroupFile','AuthzGroupFileAuthoritative',
//mod_authz_host.c
'Allow','Deny','Order',
//mod_authz_owner.c
'AuthzOwnerAuthoritative',
//mod_authz_svn.c
'AuthzForceUsernameCase','AuthzSVNAccessFile','AuthzSVNAnonymous',
'AuthzSVNAuthoritative','AuthzSVNNoAuthWhenAnonymousAllowed',
//mod_authz_user.c
'AuthzUserAuthoritative',
//mod_autoindex.c
'AddAlt','AddAltByEncoding','AddAltByType','AddDescription',
'AddIcon','AddIconByEncoding','AddIconByType','DefaultIcon',
'FancyIndexing','HeaderName','IndexHeadInsert','IndexIgnore',
'IndexOptions','IndexOrderDefault','IndexStyleSheet','ReadmeName',
//mod_bt.c
'Tracker','TrackerDetailURL','TrackerFlags','TrackerHashMaxAge',
'TrackerHashMinAge','TrackerHashWatermark','TrackerHome',
'TrackerReturnInterval','TrackerReturnMax',
'TrackerReturnPeerFactor','TrackerReturnPeers','TrackerRootInclude',
'TrackerStyleSheet',
//mod_bw.c
'BandWidth','BandWidthError','BandWidthModule','BandWidthPacket',
'ForceBandWidthModule','LargeFileLimit','MaxConnection',
'MinBandWidth',
//mod_cache.c
'CacheDefaultExpire','CacheDisable','CacheEnable',
'CacheIgnoreCacheControl','CacheIgnoreHeaders',
'CacheIgnoreNoLastMod','CacheIgnoreQueryString',
'CacheLastModifiedFactor','CacheMaxExpire','CacheStoreNoStore',
'CacheStorePrivate',
//mod_cern_meta.c
'MetaDir','MetaFiles','MetaSuffix',
//mod_cgi.c
'ScriptLog','ScriptLogBuffer','ScriptLogLength',
//mod_charset_lite.c
'CharsetDefault','CharsetOptions','CharsetSourceEnc',
//mod_dav.c
'DAV','DAVDepthInfinity','DAVMinTimeout',
//mod_dav_fs.c
'DAVLockDB',
//mod_dav_lock.c
'DAVGenericLockDB',
//mod_dav_svn.c
'SVNActivitiesDB','SVNAllowBulkUpdates','SVNAutoversioning',
'SVNIndexXSLT','SVNListParentPath','SVNMasterURI','SVNParentPath',
'SVNPath','SVNPathAuthz','SVNReposName','SVNSpecialURI',
//mod_dbd.c
'DBDExptime','DBDKeep','DBDMax','DBDMin','DBDParams','DBDPersist',
'DBDPrepareSQL','DBDriver',
//mod_deflate.c
'DeflateBufferSize','DeflateCompressionLevel','DeflateFilterNote',
'DeflateMemLevel','DeflateWindowSize',
//mod_dir.c
'DirectoryIndex','DirectorySlash',
//mod_disk_cache.c
'CacheDirLength','CacheDirLevels','CacheMaxFileSize',
'CacheMinFileSize','CacheRoot',
//mod_dumpio.c
'DumpIOInput','DumpIOLogLevel','DumpIOOutput',
//mod_env.c
'PassEnv','SetEnv','UnsetEnv',
//mod_expires.c
'ExpiresActive','ExpiresByType','ExpiresDefault',
//mod_ext_filter.c
'ExtFilterDefine','ExtFilterOptions',
//mod_file_cache.c
'cachefile','mmapfile',
//mod_filter.c
'FilterChain','FilterDeclare','FilterProtocol','FilterProvider',
'FilterTrace',
//mod_gnutls.c
'GnuTLSCache','GnuTLSCacheTimeout','GnuTLSCertificateFile',
'GnuTLSKeyFile','GnuTLSPGPCertificateFile','GnuTLSPGPKeyFile',
'GnuTLSClientVerify','GnuTLSClientCAFile','GnuTLSPGPKeyringFile',
'GnuTLSEnable','GnuTLSDHFile','GnuTLSRSAFile','GnuTLSSRPPasswdFile',
'GnuTLSSRPPasswdConfFile','GnuTLSPriorities',
'GnuTLSExportCertificates',
//mod_headers.c
'Header','RequestHeader',
//mod_imagemap.c
'ImapBase','ImapDefault','ImapMenu',
//mod_include.c
'SSIAccessEnable','SSIEndTag','SSIErrorMsg','SSIStartTag',
'SSITimeFormat','SSIUndefinedEcho','XBitHack',
//mod_ident.c
'IdentityCheck','IdentityCheckTimeout',
//mod_info.c
'AddModuleInfo',
//mod_isapi.c
'ISAPIAppendLogToErrors','ISAPIAppendLogToQuery','ISAPICacheFile',
'ISAPIFakeAsync','ISAPILogNotSupported','ISAPIReadAheadBuffer',
//mod_log_config.c
'BufferedLogs','CookieLog','CustomLog','LogFormat','TransferLog',
//mod_log_forensic.c
'ForensicLog',
//mod_log_rotate.c
'RotateInterval','RotateLogs','RotateLogsLocalTime',
//mod_logio.c
//mod_mem_cache.c
'MCacheMaxObjectCount','MCacheMaxObjectSize',
'MCacheMaxStreamingBuffer','MCacheMinObjectSize',
'MCacheRemovalAlgorithm','MCacheSize',
//mod_mime.c
'AddCharset','AddEncoding','AddHandler','AddInputFilter',
'AddLanguage','AddOutputFilter','AddType','DefaultLanguage',
'ModMimeUsePathInfo','MultiviewsMatch','RemoveCharset',
'RemoveEncoding','RemoveHandler','RemoveInputFilter',
'RemoveLanguage','RemoveOutputFilter','RemoveType','TypesConfig',
//mod_mime_magic.c
'MimeMagicFile',
//mod_negotiation.c
'CacheNegotiatedDocs','ForceLanguagePriority','LanguagePriority',
//mod_php5.c
'php_admin_flag','php_admin_value','php_flag','php_value',
'PHPINIDir',
//mod_proxy.c
'AllowCONNECT','BalancerMember','NoProxy','ProxyBadHeader',
'ProxyBlock','ProxyDomain','ProxyErrorOverride',
'ProxyFtpDirCharset','ProxyIOBufferSize','ProxyMaxForwards',
'ProxyPass','ProxyPassInterpolateEnv','ProxyPassMatch',
'ProxyPassReverse','ProxyPassReverseCookieDomain',
'ProxyPassReverseCookiePath','ProxyPreserveHost',
'ProxyReceiveBufferSize','ProxyRemote','ProxyRemoteMatch',
'ProxyRequests','ProxySet','ProxyStatus','ProxyTimeout','ProxyVia',
//mod_proxy_ajp.c
//mod_proxy_balancer.c
//mod_proxy_connect.c
//mod_proxy_ftp.c
//mod_proxy_http.c
//mod_rewrite.c
'RewriteBase','RewriteCond','RewriteEngine','RewriteLock',
'RewriteLog','RewriteLogLevel','RewriteMap','RewriteOptions',
'RewriteRule',
//mod_setenvif.c
'BrowserMatch','BrowserMatchNoCase','SetEnvIf','SetEnvIfNoCase',
//mod_so.c
'LoadFile','LoadModule',
//mod_speling.c
'CheckCaseOnly','CheckSpelling',
//mod_ssl.c
'SSLCACertificateFile','SSLCACertificatePath','SSLCADNRequestFile',
'SSLCADNRequestPath','SSLCARevocationFile','SSLCARevocationPath',
'SSLCertificateChainFile','SSLCertificateFile',
'SSLCertificateKeyFile','SSLCipherSuite','SSLCryptoDevice',
'SSLEngine','SSLHonorCipherOrder','SSLMutex','SSLOptions',
'SSLPassPhraseDialog','SSLProtocol','SSLProxyCACertificateFile',
'SSLProxyCACertificatePath','SSLProxyCARevocationFile',
'SSLProxyCARevocationPath','SSLProxyCipherSuite','SSLProxyEngine',
'SSLProxyMachineCertificateFile','SSLProxyMachineCertificatePath',
'SSLProxyProtocol','SSLProxyVerify','SSLProxyVerifyDepth',
'SSLRandomSeed','SSLRenegBufferSize','SSLRequire','SSLRequireSSL',
'SSLSessionCache','SSLSessionCacheTimeout','SSLUserName',
'SSLVerifyClient','SSLVerifyDepth',
//mod_status.c
'ExtendedStatus','SeeRequestTail',
//mod_substitute.c
'Substitute',
//mod_suexec.c
'SuexecUserGroup',
//mod_unique_id.c
//mod_upload_progress
'ReportUploads', 'TrackUploads', 'UploadProgressSharedMemorySize',
//mod_userdir.c
'UserDir',
//mod_usertrack.c
'CookieDomain','CookieExpires','CookieName','CookieStyle',
'CookieTracking',
//mod_version.c
//mod_vhost_alias.c
'VirtualDocumentRoot','VirtualDocumentRootIP',
'VirtualScriptAlias','VirtualScriptAliasIP',
//mod_view.c
'ViewEnable',
//mod_win32.c
'ScriptInterpreterSource',
//mpm_winnt.c
'Listen','ListenBacklog','ReceiveBufferSize','SendBufferSize',
'ThreadLimit','ThreadsPerChild','Win32DisableAcceptEx',
//mpm_common.c
'AcceptMutex','AddModule','ClearModuleList','EnableExceptionHook',
'Group','LockFile','MaxClients','MaxSpareServers','MaxSpareThreads',
'MinSpareServers','MinSpareThreads','ServerLimit','StartServers',
'StartThreads','User',
//util_ldap.c
'LDAPCacheEntries','LDAPCacheTTL','LDAPConnectionTimeout',
'LDAPOpCacheEntries','LDAPOpCacheTTL','LDAPSharedCacheFile',
'LDAPSharedCacheSize','LDAPTrustedClientCert',
'LDAPTrustedGlobalCert','LDAPTrustedMode','LDAPVerifyServerCert',
//Unknown Mods ...
'AgentLog','BindAddress','bs2000account','CacheForceCompletion',
'CacheGCInterval','CacheSize','NoCache','qsc','RefererIgnore',
'RefererLog','Resourceconfig','ServerType','SingleListen'
),
/*keywords 2*/
2 => array(
'all','on','off','standalone','inetd','indexes',
'force-response-1.0','downgrade-1.0','nokeepalive',
'includes','followsymlinks','none',
'x-compress','x-gzip'
),
/*keywords 3*/
3 => array(
//core.c
'Directory','DirectoryMatch','Files','FilesMatch','IfDefine',
'IfModule','Limit','LimitExcept','Location','LocationMatch',
'VirtualHost',
//mod_authn_alias.c
'AuthnProviderAlias',
//mod_proxy.c
'Proxy','ProxyMatch',
//mod_version.c
'IfVersion'
)
),
'SYMBOLS' => array(
'+', '-'
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => false,
2 => false,
3 => false,
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #00007f;',
2 => 'color: #0000ff;',
3 => 'color: #000000; font-weight:bold;',
),
'COMMENTS' => array(
1 => 'color: #adadad; font-style: italic;',
),
'ESCAPE_CHAR' => array(
0 => 'color: #000099; font-weight: bold;'
),
'BRACKETS' => array(
0 => 'color: #339933;'
),
'STRINGS' => array(
0 => 'color: #7f007f;'
),
'NUMBERS' => array(
0 => 'color: #ff0000;'
),
'METHODS' => array(
),
'SYMBOLS' => array(
0 => 'color: #008000;'
),
'REGEXPS' => array(
),
'SCRIPT' => array(
)
),
'URLS' => array(
1 => '',
2 => '',
3 => ''
),
'OOLANG' => false,
'OBJECT_SPLITTERS' => array(
),
'REGEXPS' => array(
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(
),
'HIGHLIGHT_STRICT_BLOCK' => array(
),
'PARSER_CONTROL' => array(
'ENABLE_FLAGS' => array(
'BRACKETS' => GESHI_NEVER,
'SYMBOLS' => GESHI_NEVER
),
'KEYWORDS' => array(
3 => array(
'DISALLOWED_BEFORE' => '(?<=&lt;|&lt;\/)',
'DISALLOWED_AFTER' => '(?=\s|\/|&gt;)',
)
)
)
);
?>

View file

@ -0,0 +1,157 @@
<?php
/*************************************************************************************
* applescript.php
* --------
* Author: Stephan Klimek (http://www.initware.org)
* Copyright: Stephan Klimek (http://www.initware.org)
* Release Version: 1.0.8.11
* Date Started: 2005/07/20
*
* AppleScript language file for GeSHi.
*
* CHANGES
* -------
* 2008/05/23 (1.0.7.22)
* - Added description of extra language features (SF#1970248)
*
* TODO
* -------------------------
* URL settings to references
*
**************************************************************************************
*
* This file is part of GeSHi.
*
* GeSHi is free software; 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.
*
* GeSHi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GeSHi; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
************************************************************************************/
$language_data = array (
'LANG_NAME' => 'AppleScript',
'COMMENT_SINGLE' => array(1 => '--'),
'COMMENT_MULTI' => array( '(*' => '*)'),
'COMMENT_REGEXP' => array(
2 => '/(?<=[a-z])\'/i',
3 => '/(?<![a-z])\'.*?\'/i',
),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array('"'),
'ESCAPE_CHAR' => '\\',
'KEYWORDS' => array(
1 => array(
'application','close','count','delete','duplicate','exists','launch','make','move','open',
'print','quit','reopen','run','save','saving', 'idle', 'path to', 'number', 'alias', 'list', 'text', 'string',
'integer', 'it','me','version','pi','result','space','tab','anything','case','diacriticals','expansion',
'hyphens','punctuation','bold','condensed','expanded','hidden','italic','outline','plain',
'shadow','strikethrough','subscript','superscript','underline','ask','no','yes','false', 'id',
'true','weekday','monday','mon','tuesday','tue','wednesday','wed','thursday','thu','friday',
'fri','saturday','sat','sunday','sun','month','january','jan','february','feb','march',
'mar','april','apr','may','june','jun','july','jul','august','aug','september', 'quote', 'do JavaScript',
'sep','october','oct','november','nov','december','dec','minutes','hours', 'name', 'default answer',
'days','weeks', 'folder', 'folders', 'file', 'files', 'window', 'eject', 'disk', 'reveal', 'sleep',
'shut down', 'restart', 'display dialog', 'buttons', 'invisibles', 'item', 'items', 'delimiters', 'offset of',
'AppleScript\'s', 'choose file', 'choose folder', 'choose from list', 'beep', 'contents', 'do shell script',
'paragraph', 'paragraphs', 'missing value', 'quoted form', 'desktop', 'POSIX path', 'POSIX file',
'activate', 'document', 'adding', 'receiving', 'content', 'new', 'properties', 'info for', 'bounds',
'selection', 'extension', 'into', 'onto', 'by', 'between', 'against', 'set the clipboard to', 'the clipboard'
),
2 => array(
'each','some','every','whose','where','index','first','second','third','fourth',
'fifth','sixth','seventh','eighth','ninth','tenth','last','front','back','st','nd',
'rd','th','middle','named','through','thru','before','after','beginning','the', 'as',
'div','mod','and','not','or','contains','equal','equals','isnt', 'less', 'greater'
),
3 => array(
'script','property','prop','end','to','set','global','local','on','of',
'in','given','with','without','return','continue','tell','if','then','else','repeat',
'times','while','until','from','exit','try','error','considering','ignoring','timeout',
'transaction','my','get','put','is', 'copy'
)
),
'SYMBOLS' => array(
')','+','-','^','*','/','&','<','>=','<','<=','=','<27>'
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => false,
2 => false,
3 => false,
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #0066ff;',
2 => 'color: #ff0033;',
3 => 'color: #ff0033; font-weight: bold;'
),
'COMMENTS' => array(
1 => 'color: #808080; font-style: italic;',
2 => '',
3 => 'color: #ff0000;',
'MULTI' => 'color: #808080; font-style: italic;'
),
'ESCAPE_CHAR' => array(
0 => 'color: #000000; font-weight: bold;'
),
'BRACKETS' => array(
0 => 'color: #000000;'
),
'STRINGS' => array(
0 => 'color: #009900;'
),
'NUMBERS' => array(
0 => 'color: #000000;'
),
'METHODS' => array(
1 => 'color: #006600;',
2 => 'color: #006600;'
),
'SYMBOLS' => array(
0 => 'color: #000000;'
),
'REGEXPS' => array(
0 => 'color: #339933;',
4 => 'color: #0066ff;',
),
'SCRIPT' => array(
)
),
'URLS' => array(
1 => '',
2 => '',
3 => ''
),
'OOLANG' => true,
'OBJECT_SPLITTERS' => array(
1 => ',+-=&lt;&gt;/?^&amp;*'
),
'REGEXPS' => array(
//Variables
0 => '[\\$%@]+[a-zA-Z_][a-zA-Z0-9_]*',
//File descriptors
4 => '&lt;[a-zA-Z_][a-zA-Z0-9_]*&gt;',
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(
),
'HIGHLIGHT_STRICT_BLOCK' => array(
),
'PARSER_CONTROL' => array(
'KEYWORDS' => array(
'SPACE_AS_WHITESPACE' => true
)
)
);
?>

Some files were not shown because too many files have changed in this diff Show more