first commit
@@ -0,0 +1,10 @@
|
||||
# Use mod_rewrite to enable "Clean URLs" for a PmWiki installation.
|
||||
RewriteEngine On
|
||||
# Define the rewrite base.
|
||||
RewriteBase /wiki
|
||||
# Send requests without parameters to pmwiki.php.
|
||||
RewriteRule ^$ pmwiki.php [L]
|
||||
# Send requests for index.php to pmwiki.php.
|
||||
RewriteRule ^index\.php$ pmwiki.php [L]
|
||||
# Send requests to pmwiki.php, appending the query string part.
|
||||
RewriteRule ^([A-Z0-9\xa0-\xff].*)$ pmwiki.php?n=$1 [QSA,L]
|
||||
@@ -0,0 +1,48 @@
|
||||
This is the README.txt file for PmWiki, a wiki-based system for
|
||||
collaborative creation and maintenance of websites.
|
||||
|
||||
PmWiki is distributed with the following directories:
|
||||
|
||||
docs/ Brief documentation, sample configuration scripts
|
||||
local/ Configuration scripts
|
||||
cookbook/ Recipes (add-ons) from the PmWiki Cookbook
|
||||
pub/skins/ Layout templates ("skins" for custom look and feel)
|
||||
pub/css/ Extra CSS stylesheet files
|
||||
pub/guiedit/ Files for the Edit Form's GUIEdit module
|
||||
scripts/ Scripts that are part of PmWiki
|
||||
wikilib.d/ Bundled wiki pages, including
|
||||
* a default Home Page
|
||||
* PmWiki documentation pages
|
||||
* some Site-oriented pages
|
||||
|
||||
After PmWiki is installed the following directories may also exist:
|
||||
|
||||
wiki.d/ Wiki pages
|
||||
uploads/ Uploaded files (page attachments)
|
||||
|
||||
For quick installation advice, see docs/INSTALL.txt.
|
||||
|
||||
For more extensive information about installing PmWiki, visit
|
||||
http://pmwiki.org/wiki/PmWiki/Installation
|
||||
|
||||
For information about running PmWiki in standalone mode without
|
||||
requiring a webserver, visit
|
||||
http://pmwiki.org/wiki/Cookbook/Standalone
|
||||
|
||||
PmWiki is Copyright 2001-2006 Patrick R. Michaud
|
||||
pmichaud@pobox.com
|
||||
http://www.pmichaud.com/
|
||||
|
||||
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.
|
||||
|
||||
The GNU General Public License is distributed with this program
|
||||
(see docs/COPYING.txt) and it is also available online at
|
||||
http://www.fsf.org/licensing/licenses/gpl.txt .
|
||||
@@ -0,0 +1,12 @@
|
||||
# This file is cookbook/.htaccess -- the default distribution contains this
|
||||
# file to prevent cookbook/ scripts from being accessed directly by browsers
|
||||
# (this is a potential, albeit very unlikely, security hole).
|
||||
#
|
||||
# If you alter or replace this file, it will likely be overwritten when
|
||||
# you upgrade from one version of PmWiki to another. Be sure to save
|
||||
# a copy of your alterations in another location so you can restore them,
|
||||
# and you might try changing this file to be read-only to prevent a PmWiki
|
||||
# upgrade from overwriting your altered version.
|
||||
|
||||
Order Deny,Allow
|
||||
Deny from all
|
||||
@@ -0,0 +1 @@
|
||||
AddType text/plain .php
|
||||
@@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library General
|
||||
Public License instead of this License.
|
||||
@@ -0,0 +1,10 @@
|
||||
Where is the documentation?
|
||||
|
||||
PmWiki maintains its documentation as wiki pages.
|
||||
If you already have PmWiki installed, then a local copy of
|
||||
the documentation is available through PmWiki itself --
|
||||
see the "PmWiki.DocumentationIndex" page on your site.
|
||||
|
||||
The documentation is also available online at
|
||||
http://www.pmwiki.org/wiki/PmWiki/DocumentationIndex .
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
This is the INSTALL.txt file for PmWiki. This document provides
|
||||
convenient steps so an administrator can have a PmWiki site up and
|
||||
running quickly. More extensive information about installing PmWiki
|
||||
is available at http://www.pmwiki.org/wiki/PmWiki/Installation .
|
||||
|
||||
Once your site is up and running you will be able to read the bundled
|
||||
documentation pages.
|
||||
|
||||
Here are some quick steps to start you on your path toward a complete,
|
||||
customized installation:
|
||||
|
||||
1a) Put the software in a location accessible by your webserver.
|
||||
|
||||
1b) PmWiki can also be run if no webserver is installed. See
|
||||
http://pmwiki.org/wiki/Cookbook/Standalone
|
||||
|
||||
2) Point your browser to pmwiki.php.
|
||||
|
||||
3) You may see an error message saying that PmWiki needs to have
|
||||
a writable wiki.d/ directory. If so, follow the directions to
|
||||
establish one. This directory will hold your wiki page files.
|
||||
|
||||
4) If you want a directory index file, create a file called index.php
|
||||
in the main directory that contains the following single line of
|
||||
text, purposefully without a closing "?>":
|
||||
|
||||
<?php include('pmwiki.php');
|
||||
|
||||
5) Sitewide configuration settings will go in a "local configuration
|
||||
file" named local/config.php. Copy the well-commented sample
|
||||
configuration file from docs/sample-config.php to the local/
|
||||
subdirectory, then rename the copy to config.php. Edit your
|
||||
new local/config.php file to suit your preferences.
|
||||
|
||||
That's it. Next you'll probably want to browse your new site and
|
||||
read the bundled documentation. A good place to start is the
|
||||
PmWiki.InitialSetupTasks page.
|
||||
|
||||
Enjoy!
|
||||
@@ -0,0 +1,50 @@
|
||||
This UPGRADE.txt file is a command-line syntax reminder for
|
||||
experienced PmWiki administrators. For full documentation on
|
||||
upgrading Pmwiki, see the bundled PmWiki.Upgrades page or visit
|
||||
|
||||
http://www.pmwiki.org/wiki/PmWiki/Upgrades
|
||||
|
||||
See also these related pages:
|
||||
|
||||
http://www.pmwiki.org/wiki/PmWiki/BackupAndRestore
|
||||
http://www.pmwiki.org/wiki/PmWiki/Subversion
|
||||
|
||||
The examples assume your PmWiki site is in a ./pmwiki/
|
||||
directory (a directory named "pmwiki" immediately below the
|
||||
working directory).
|
||||
|
||||
Backing up (always a good idea!):
|
||||
|
||||
tar -zcvf ~/pmwiki-backup.tar.gz pmwiki
|
||||
zip -9r ~/pmwiki-backup.zip pmwiki
|
||||
|
||||
Or, to keep backups organized by date:
|
||||
|
||||
tar -zcvf ~/pmwiki-site-`date +%Y%m%d%M`.tar.gz pmwiki
|
||||
zip -9r ~/pmwiki-site-`date +%Y%m%d%M`.zip pmwiki
|
||||
|
||||
The latest release is available here:
|
||||
|
||||
http://www.pmichaud.com/pub/pmwiki/pmwiki-latest.tgz
|
||||
http://www.pmichaud.com/pub/pmwiki/pmwiki-latest.zip
|
||||
|
||||
Example download commands:
|
||||
|
||||
wget http://www.pmichaud.com/pub/pmwiki/pmwiki-latest.tgz
|
||||
lftpget http://www.pmichaud.com/pub/pmwiki/pmwiki-latest.tgz
|
||||
links http://www.pmichaud.com/pub/pmwiki/pmwiki-latest.tgz
|
||||
lynx http://www.pmichaud.com/pub/pmwiki/pmwiki-latest.tgz
|
||||
|
||||
Expanding the archive:
|
||||
|
||||
tar -zxvf pmwiki-latest.tgz # for the gzipped tarball
|
||||
unzip pmwiki-latest.zip # for the .zip archive
|
||||
|
||||
Copying the files (two ways to do it):
|
||||
|
||||
cp -av pmwiki-2.1.x/. pmwiki
|
||||
cp -Rpv pmwiki-2.1.x/. pmwiki
|
||||
|
||||
Subversion upgrade:
|
||||
|
||||
svn export svn://pmwiki.org/pmwiki/tags/latest pmwiki --force
|
||||
@@ -0,0 +1,161 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
## This is a sample config.php file. To use this file, copy it to
|
||||
## local/config.php, then edit it for whatever customizations you want.
|
||||
## Also, be sure to take a look at http://www.pmwiki.org/wiki/Cookbook
|
||||
## for more details on the types of customizations that can be added
|
||||
## to PmWiki.
|
||||
|
||||
## $WikiTitle is the name that appears in the browser's title bar.
|
||||
$WikiTitle = 'PmWiki';
|
||||
|
||||
## $ScriptUrl is your preferred URL for accessing wiki pages
|
||||
## $PubDirUrl is the URL for the pub directory.
|
||||
# $ScriptUrl = 'http://www.mydomain.com/path/to/pmwiki.php';
|
||||
# $PubDirUrl = 'http://www.mydomain.com/path/to/pub';
|
||||
|
||||
## If you want to use URLs of the form .../pmwiki.php/Group/PageName
|
||||
## instead of .../pmwiki.php?p=Group.PageName, try setting
|
||||
## $EnablePathInfo below. Note that this doesn't work in all environments,
|
||||
## it depends on your webserver and PHP configuration. You might also
|
||||
## want to check http://www.pmwiki.org/wiki/Cookbook/CleanUrls more
|
||||
## details about this setting and other ways to create nicer-looking urls.
|
||||
# $EnablePathInfo = 1;
|
||||
|
||||
## $PageLogoUrl is the URL for a logo image -- you can change this
|
||||
## to your own logo if you wish.
|
||||
# $PageLogoUrl = "$PubDirUrl/skins/pmwiki/pmwiki-32.gif";
|
||||
|
||||
## If you want to have a custom skin, then set $Skin to the name
|
||||
## of the directory (in pub/skins/) that contains your skin files.
|
||||
## See PmWiki.Skins and Cookbook.Skins.
|
||||
# $Skin = 'pmwiki';
|
||||
|
||||
## You'll probably want to set an administrative password that you
|
||||
## can use to get into password-protected pages. Also, by default
|
||||
## the "attr" passwords for the PmWiki and Main groups are locked, so
|
||||
## an admin password is a good way to unlock those. See PmWiki.Passwords
|
||||
## and PmWiki.PasswordsAdmin.
|
||||
# $DefaultPasswords['admin'] = pmcrypt('secret');
|
||||
|
||||
## Unicode (UTF-8) allows the display of all languages and all alphabets.
|
||||
## Highly recommended for new wikis.
|
||||
include_once("scripts/xlpage-utf-8.php");
|
||||
|
||||
## If you're running a publicly available site and allow anyone to
|
||||
## edit without requiring a password, you probably want to put some
|
||||
## blocklists in place to avoid wikispam. See PmWiki.Blocklist.
|
||||
# $EnableBlocklist = 1; # enable manual blocklists
|
||||
# $EnableBlocklist = 10; # enable automatic blocklists
|
||||
|
||||
## PmWiki comes with graphical user interface buttons for editing;
|
||||
## to enable these buttons, set $EnableGUIButtons to 1.
|
||||
# $EnableGUIButtons = 1;
|
||||
|
||||
## To enable markup syntax from the Creole common wiki markup language
|
||||
## (http://www.wikicreole.org/), include it here:
|
||||
# include_once("scripts/creole.php");
|
||||
|
||||
## Some sites may want leading spaces on markup lines to indicate
|
||||
## "preformatted text blocks", set $EnableWSPre=1 if you want to do
|
||||
## this. Setting it to a higher number increases the number of
|
||||
## space characters required on a line to count as "preformatted text".
|
||||
# $EnableWSPre = 1; # lines beginning with space are preformatted (default)
|
||||
# $EnableWSPre = 4; # lines with 4 or more spaces are preformatted
|
||||
# $EnableWSPre = 0; # disabled
|
||||
|
||||
## If you want uploads enabled on your system, set $EnableUpload=1.
|
||||
## You'll also need to set a default upload password, or else set
|
||||
## passwords on individual groups and pages. For more information
|
||||
## see PmWiki.UploadsAdmin.
|
||||
# $EnableUpload = 1;
|
||||
# $UploadPermAdd = 0;
|
||||
# $DefaultPasswords['upload'] = pmcrypt('secret');
|
||||
|
||||
## Setting $EnableDiag turns on the ?action=diag and ?action=phpinfo
|
||||
## actions, which often helps others to remotely troubleshoot
|
||||
## various configuration and execution problems.
|
||||
# $EnableDiag = 1; # enable remote diagnostics
|
||||
|
||||
## By default, PmWiki doesn't allow browsers to cache pages. Setting
|
||||
## $EnableIMSCaching=1; will re-enable browser caches in a somewhat
|
||||
## smart manner. Note that you may want to have caching disabled while
|
||||
## adjusting configuration files or layout templates.
|
||||
# $EnableIMSCaching = 1; # allow browser caching
|
||||
|
||||
## Set $SpaceWikiWords if you want WikiWords to automatically
|
||||
## have spaces before each sequence of capital letters.
|
||||
# $SpaceWikiWords = 1; # turn on WikiWord spacing
|
||||
|
||||
## Set $EnableWikiWords if you want to allow WikiWord links.
|
||||
## For more options with WikiWords, see scripts/wikiwords.php .
|
||||
# $EnableWikiWords = 1; # enable WikiWord links
|
||||
|
||||
## $DiffKeepDays specifies the minimum number of days to keep a page's
|
||||
## revision history. The default is 3650 (approximately 10 years).
|
||||
# $DiffKeepDays=30; # keep page history at least 30 days
|
||||
|
||||
## By default, viewers are prevented from seeing the existence
|
||||
## of read-protected pages in search results and page listings,
|
||||
## but this can be slow as PmWiki has to check the permissions
|
||||
## of each page. Setting $EnablePageListProtect to zero will
|
||||
## speed things up considerably, but it will also mean that
|
||||
## viewers may learn of the existence of read-protected pages.
|
||||
## (It does not enable them to access the contents of the pages.)
|
||||
# $EnablePageListProtect = 0;
|
||||
|
||||
## The refcount.php script enables ?action=refcount, which helps to
|
||||
## find missing and orphaned pages. See PmWiki.RefCount.
|
||||
# if ($action == 'refcount') include_once("scripts/refcount.php");
|
||||
|
||||
## The feeds.php script enables ?action=rss, ?action=atom, ?action=rdf,
|
||||
## and ?action=dc, for generation of syndication feeds in various formats.
|
||||
# if ($action == 'rss') include_once("scripts/feeds.php"); # RSS 2.0
|
||||
# if ($action == 'atom') include_once("scripts/feeds.php"); # Atom 1.0
|
||||
# if ($action == 'dc') include_once("scripts/feeds.php"); # Dublin Core
|
||||
# if ($action == 'rdf') include_once("scripts/feeds.php"); # RSS 1.0
|
||||
|
||||
## In the 2.2.0-beta series, {$var} page variables were absolute, but now
|
||||
## relative page variables provide greater flexibility and are recommended.
|
||||
## (If you're starting a new site, it's best to leave this setting alone.)
|
||||
# $EnableRelativePageVars = 1; # 1=relative; 0=absolute
|
||||
|
||||
## By default, pages in the Category group are manually created.
|
||||
## Uncomment the following line to have blank category pages
|
||||
## automatically created whenever a link to a non-existent
|
||||
## category page is saved. (The page is created only if
|
||||
## the author has edit permissions to the Category group.)
|
||||
# $AutoCreate['/^Category\\./'] = array('ctime' => $Now);
|
||||
|
||||
## PmWiki allows a great deal of flexibility for creating custom markup.
|
||||
## To add support for '*bold*' and '~italic~' markup (the single quotes
|
||||
## are part of the markup), uncomment the following lines.
|
||||
## (See PmWiki.CustomMarkup and the Cookbook for details and examples.)
|
||||
# Markup("'~", "inline", "/'~(.*?)~'/", "<i>$1</i>"); # '~italic~'
|
||||
# Markup("'*", "inline", "/'\\*(.*?)\\*'/", "<b>$1</b>"); # '*bold*'
|
||||
|
||||
## If you want to have to approve links to external sites before they
|
||||
## are turned into links, uncomment the line below. See PmWiki.UrlApprovals.
|
||||
## Also, setting $UnapprovedLinkCountMax limits the number of unapproved
|
||||
## links that are allowed in a page (useful to control wikispam).
|
||||
# $UnapprovedLinkCountMax = 10;
|
||||
# include_once("scripts/urlapprove.php");
|
||||
|
||||
## The following lines make additional editing buttons appear in the
|
||||
## edit page for subheadings, lists, tables, etc.
|
||||
# $GUIButtons['h2'] = array(400, '\\n!! ', '\\n', '$[Heading]',
|
||||
# '$GUIButtonDirUrlFmt/h2.gif"$[Heading]"');
|
||||
# $GUIButtons['h3'] = array(402, '\\n!!! ', '\\n', '$[Subheading]',
|
||||
# '$GUIButtonDirUrlFmt/h3.gif"$[Subheading]"');
|
||||
# $GUIButtons['indent'] = array(500, '\\n->', '\\n', '$[Indented text]',
|
||||
# '$GUIButtonDirUrlFmt/indent.gif"$[Indented text]"');
|
||||
# $GUIButtons['outdent'] = array(510, '\\n-<', '\\n', '$[Hanging indent]',
|
||||
# '$GUIButtonDirUrlFmt/outdent.gif"$[Hanging indent]"');
|
||||
# $GUIButtons['ol'] = array(520, '\\n# ', '\\n', '$[Ordered list]',
|
||||
# '$GUIButtonDirUrlFmt/ol.gif"$[Ordered (numbered) list]"');
|
||||
# $GUIButtons['ul'] = array(530, '\\n* ', '\\n', '$[Unordered list]',
|
||||
# '$GUIButtonDirUrlFmt/ul.gif"$[Unordered (bullet) list]"');
|
||||
# $GUIButtons['hr'] = array(540, '\\n----\\n', '', '',
|
||||
# '$GUIButtonDirUrlFmt/hr.gif"$[Horizontal rule]"');
|
||||
# $GUIButtons['table'] = array(600,
|
||||
# '||border=1 width=80%\\n||!Hdr ||!Hdr ||!Hdr ||\\n|| || || ||\\n|| || || ||\\n', '', '',
|
||||
# '$GUIButtonDirUrlFmt/table.gif"$[Table]"');
|
||||
@@ -0,0 +1,12 @@
|
||||
# This file is local/.htaccess -- the default distribution contains this
|
||||
# file to prevent local/ scripts from being accessed directly by browsers
|
||||
# (this is a potential, albeit very unlikely, security hole).
|
||||
#
|
||||
# If you alter or replace this file, it will likely be overwritten when
|
||||
# you upgrade from one version of PmWiki to another. Be sure to save
|
||||
# a copy of your alterations in another location so you can restore them,
|
||||
# and you might try changing this file to be read-only to prevent a PmWiki
|
||||
# upgrade from overwriting your altered version.
|
||||
|
||||
Order Deny,Allow
|
||||
Deny from all
|
||||
@@ -0,0 +1,178 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
## This is a sample config.php file. To use this file, copy it to
|
||||
## local/config.php, then edit it for whatever customizations you want.
|
||||
## Also, be sure to take a look at http://www.pmwiki.org/wiki/Cookbook
|
||||
## for more details on the types of customizations that can be added
|
||||
## to PmWiki.
|
||||
|
||||
## $WikiTitle is the name that appears in the browser's title bar.
|
||||
$WikiTitle = 'Вики справка Graph Online';
|
||||
|
||||
## $ScriptUrl is your preferred URL for accessing wiki pages
|
||||
## $PubDirUrl is the URL for the pub directory.
|
||||
$ScriptUrl = '/wiki';
|
||||
# $PubDirUrl = 'http://www.mydomain.com/path/to/pub';
|
||||
$HeaderLink = 'http://graphonline.ru';
|
||||
|
||||
## If you want to use URLs of the form .../pmwiki.php/Group/PageName
|
||||
## instead of .../pmwiki.php?p=Group.PageName, try setting
|
||||
## $EnablePathInfo below. Note that this doesn't work in all environments,
|
||||
## it depends on your webserver and PHP configuration. You might also
|
||||
## want to check http://www.pmwiki.org/wiki/Cookbook/CleanUrls more
|
||||
## details about this setting and other ways to create nicer-looking urls.
|
||||
$EnablePathInfo = 1;
|
||||
|
||||
## $PageLogoUrl is the URL for a logo image -- you can change this
|
||||
## to your own logo if you wish.
|
||||
$PageLogoUrl = "$PubDirUrl/graphonline.png";
|
||||
|
||||
## If you want to have a custom skin, then set $Skin to the name
|
||||
## of the directory (in pub/skins/) that contains your skin files.
|
||||
## See PmWiki.Skins and Cookbook.Skins.
|
||||
$Skin = 'graph';
|
||||
|
||||
## You'll probably want to set an administrative password that you
|
||||
## can use to get into password-protected pages. Also, by default
|
||||
## the "attr" passwords for the PmWiki and Main groups are locked, so
|
||||
## an admin password is a good way to unlock those. See PmWiki.Passwords
|
||||
## and PmWiki.PasswordsAdmin.
|
||||
$DefaultPasswords['admin'] = pmcrypt('pas');
|
||||
$DefaultPasswords['edit'] = pmcrypt('pas');
|
||||
|
||||
## Unicode (UTF-8) allows the display of all languages and all alphabets.
|
||||
## Highly recommended for new wikis.
|
||||
include_once("scripts/xlpage-utf-8.php");
|
||||
|
||||
## If you're running a publicly available site and allow anyone to
|
||||
## edit without requiring a password, you probably want to put some
|
||||
## blocklists in place to avoid wikispam. See PmWiki.Blocklist.
|
||||
# $EnableBlocklist = 1; # enable manual blocklists
|
||||
$EnableBlocklist = 10; # enable automatic blocklists
|
||||
|
||||
## PmWiki comes with graphical user interface buttons for editing;
|
||||
## to enable these buttons, set $EnableGUIButtons to 1.
|
||||
$EnableGUIButtons = 1;
|
||||
|
||||
## To enable markup syntax from the Creole common wiki markup language
|
||||
## (http://www.wikicreole.org/), include it here:
|
||||
# include_once("scripts/creole.php");
|
||||
|
||||
## Some sites may want leading spaces on markup lines to indicate
|
||||
## "preformatted text blocks", set $EnableWSPre=1 if you want to do
|
||||
## this. Setting it to a higher number increases the number of
|
||||
## space characters required on a line to count as "preformatted text".
|
||||
# $EnableWSPre = 1; # lines beginning with space are preformatted (default)
|
||||
# $EnableWSPre = 4; # lines with 4 or more spaces are preformatted
|
||||
# $EnableWSPre = 0; # disabled
|
||||
|
||||
## If you want uploads enabled on your system, set $EnableUpload=1.
|
||||
## You'll also need to set a default upload password, or else set
|
||||
## passwords on individual groups and pages. For more information
|
||||
## see PmWiki.UploadsAdmin.
|
||||
$EnableUpload = 1;
|
||||
$UploadExts = array(
|
||||
'gif' => 'image/gif',
|
||||
'jpeg' => 'image/jpeg',
|
||||
'jpg' => 'image/jpeg',
|
||||
'png' => 'image/png',
|
||||
'xxx' => 'yyyy/zzz'
|
||||
);
|
||||
|
||||
# $UploadPermAdd = 0;
|
||||
# $DefaultPasswords['upload'] = pmcrypt('uploADme');
|
||||
|
||||
## Setting $EnableDiag turns on the ?action=diag and ?action=phpinfo
|
||||
## actions, which often helps others to remotely troubleshoot
|
||||
## various configuration and execution problems.
|
||||
# $EnableDiag = 1; # enable remote diagnostics
|
||||
|
||||
## By default, PmWiki doesn't allow browsers to cache pages. Setting
|
||||
## $EnableIMSCaching=1; will re-enable browser caches in a somewhat
|
||||
## smart manner. Note that you may want to have caching disabled while
|
||||
## adjusting configuration files or layout templates.
|
||||
# $EnableIMSCaching = 1; # allow browser caching
|
||||
|
||||
## Set $SpaceWikiWords if you want WikiWords to automatically
|
||||
## have spaces before each sequence of capital letters.
|
||||
# $SpaceWikiWords = 1; # turn on WikiWord spacing
|
||||
|
||||
## Set $EnableWikiWords if you want to allow WikiWord links.
|
||||
## For more options with WikiWords, see scripts/wikiwords.php .
|
||||
# $EnableWikiWords = 1; # enable WikiWord links
|
||||
|
||||
## $DiffKeepDays specifies the minimum number of days to keep a page's
|
||||
## revision history. The default is 3650 (approximately 10 years).
|
||||
$DiffKeepDays=30; # keep page history at least 30 days
|
||||
|
||||
## By default, viewers are prevented from seeing the existence
|
||||
## of read-protected pages in search results and page listings,
|
||||
## but this can be slow as PmWiki has to check the permissions
|
||||
## of each page. Setting $EnablePageListProtect to zero will
|
||||
## speed things up considerably, but it will also mean that
|
||||
## viewers may learn of the existence of read-protected pages.
|
||||
## (It does not enable them to access the contents of the pages.)
|
||||
# $EnablePageListProtect = 0;
|
||||
|
||||
## The refcount.php script enables ?action=refcount, which helps to
|
||||
## find missing and orphaned pages. See PmWiki.RefCount.
|
||||
# if ($action == 'refcount') include_once("scripts/refcount.php");
|
||||
|
||||
## The feeds.php script enables ?action=rss, ?action=atom, ?action=rdf,
|
||||
## and ?action=dc, for generation of syndication feeds in various formats.
|
||||
# if ($action == 'rss') include_once("scripts/feeds.php"); # RSS 2.0
|
||||
# if ($action == 'atom') include_once("scripts/feeds.php"); # Atom 1.0
|
||||
# if ($action == 'dc') include_once("scripts/feeds.php"); # Dublin Core
|
||||
# if ($action == 'rdf') include_once("scripts/feeds.php"); # RSS 1.0
|
||||
|
||||
## In the 2.2.0-beta series, {$var} page variables were absolute, but now
|
||||
## relative page variables provide greater flexibility and are recommended.
|
||||
## (If you're starting a new site, it's best to leave this setting alone.)
|
||||
# $EnableRelativePageVars = 1; # 1=relative; 0=absolute
|
||||
|
||||
## By default, pages in the Category group are manually created.
|
||||
## Uncomment the following line to have blank category pages
|
||||
## automatically created whenever a link to a non-existent
|
||||
## category page is saved. (The page is created only if
|
||||
## the author has edit permissions to the Category group.)
|
||||
# $AutoCreate['/^Category\\./'] = array('ctime' => $Now);
|
||||
|
||||
## PmWiki allows a great deal of flexibility for creating custom markup.
|
||||
## To add support for '*bold*' and '~italic~' markup (the single quotes
|
||||
## are part of the markup), uncomment the following lines.
|
||||
## (See PmWiki.CustomMarkup and the Cookbook for details and examples.)
|
||||
# Markup("'~", "inline", "/'~(.*?)~'/", "<i>$1</i>"); # '~italic~'
|
||||
# Markup("'*", "inline", "/'\\*(.*?)\\*'/", "<b>$1</b>"); # '*bold*'
|
||||
|
||||
## If you want to have to approve links to external sites before they
|
||||
## are turned into links, uncomment the line below. See PmWiki.UrlApprovals.
|
||||
## Also, setting $UnapprovedLinkCountMax limits the number of unapproved
|
||||
## links that are allowed in a page (useful to control wikispam).
|
||||
$UnapprovedLinkCountMax = 1;
|
||||
include_once("scripts/urlapprove.php");
|
||||
|
||||
## The following lines make additional editing buttons appear in the
|
||||
## edit page for subheadings, lists, tables, etc.
|
||||
$GUIButtons['h2'] = array(400, '\\n!! ', '\\n', '$[Heading]',
|
||||
'$GUIButtonDirUrlFmt/h2.gif"$[Heading]"');
|
||||
$GUIButtons['h3'] = array(402, '\\n!!! ', '\\n', '$[Subheading]',
|
||||
'$GUIButtonDirUrlFmt/h3.gif"$[Subheading]"');
|
||||
$GUIButtons['indent'] = array(500, '\\n->', '\\n', '$[Indented text]',
|
||||
'$GUIButtonDirUrlFmt/indent.gif"$[Indented text]"');
|
||||
$GUIButtons['outdent'] = array(510, '\\n-<', '\\n', '$[Hanging indent]',
|
||||
'$GUIButtonDirUrlFmt/outdent.gif"$[Hanging indent]"');
|
||||
$GUIButtons['ol'] = array(520, '\\n# ', '\\n', '$[Ordered list]',
|
||||
'$GUIButtonDirUrlFmt/ol.gif"$[Ordered (numbered) list]"');
|
||||
$GUIButtons['ul'] = array(530, '\\n* ', '\\n', '$[Unordered list]',
|
||||
'$GUIButtonDirUrlFmt/ul.gif"$[Unordered (bullet) list]"');
|
||||
$GUIButtons['hr'] = array(540, '\\n----\\n', '', '',
|
||||
'$GUIButtonDirUrlFmt/hr.gif"$[Horizontal rule]"');
|
||||
$GUIButtons['table'] = array(600,
|
||||
'||border=1 width=80%\\n||!Hdr ||!Hdr ||!Hdr ||\\n|| || || ||\\n|| || || ||\\n', '', '',
|
||||
'$GUIButtonDirUrlFmt/table.gif"$[Table]"');
|
||||
|
||||
|
||||
$DefaultGroup = "Справка";
|
||||
$DefaultPage = "Справка.Справка";
|
||||
|
||||
|
||||
$UploadMaxSize = 2000000;
|
||||
|
After Width: | Height: | Size: 6.0 KiB |
@@ -0,0 +1,6 @@
|
||||
The images in this directory are part of the GUIEdit module
|
||||
for PmWiki, Copyright 2005-2006 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
These images are part of PmWiki; you can redistribute it and/or modify
|
||||
them under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
After Width: | Height: | Size: 772 B |
|
After Width: | Height: | Size: 724 B |
|
After Width: | Height: | Size: 663 B |
|
After Width: | Height: | Size: 651 B |
|
After Width: | Height: | Size: 710 B |
|
After Width: | Height: | Size: 716 B |
@@ -0,0 +1,62 @@
|
||||
/* Copyright 2004 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file provides Javascript functions to support WYSIWYG-style
|
||||
editing. The concepts are borrowed from the editor used in Wikipedia,
|
||||
but the code has been rewritten from scratch to integrate better with
|
||||
PHP and PmWiki's codebase.
|
||||
*/
|
||||
|
||||
function insButton(mopen, mclose, mtext, mlabel, mkey) {
|
||||
if (mkey > '') { mkey = 'accesskey="' + mkey + '" ' }
|
||||
document.write("<a tabindex='-1' " + mkey + "onclick=\"insMarkup('"
|
||||
+ mopen + "','"
|
||||
+ mclose + "','"
|
||||
+ mtext + "');\">"
|
||||
+ mlabel + "</a>");
|
||||
}
|
||||
|
||||
function insMarkup(mopen, mclose, mtext) {
|
||||
var tarea = document.getElementById('text');
|
||||
if (tarea.setSelectionRange > '') {
|
||||
var p0 = tarea.selectionStart;
|
||||
var p1 = tarea.selectionEnd;
|
||||
var top = tarea.scrollTop;
|
||||
var str = mtext;
|
||||
var cur0 = p0 + mopen.length;
|
||||
var cur1 = p0 + mopen.length + str.length;
|
||||
while (p1 > p0 && tarea.value.substring(p1-1, p1) == ' ') p1--;
|
||||
if (p1 > p0) {
|
||||
str = tarea.value.substring(p0, p1);
|
||||
cur0 = p0 + mopen.length + str.length + mclose.length;
|
||||
cur1 = cur0;
|
||||
}
|
||||
tarea.value = tarea.value.substring(0,p0)
|
||||
+ mopen + str + mclose
|
||||
+ tarea.value.substring(p1);
|
||||
tarea.focus();
|
||||
tarea.selectionStart = cur0;
|
||||
tarea.selectionEnd = cur1;
|
||||
tarea.scrollTop = top;
|
||||
} else if (document.selection) {
|
||||
var str = document.selection.createRange().text;
|
||||
tarea.focus();
|
||||
range = document.selection.createRange()
|
||||
if (str == '') {
|
||||
range.text = mopen + mtext + mclose;
|
||||
range.moveStart('character', -mclose.length - mtext.length );
|
||||
range.moveEnd('character', -mclose.length );
|
||||
} else {
|
||||
if (str.charAt(str.length - 1) == " ") {
|
||||
mclose = mclose + " ";
|
||||
str = str.substr(0, str.length - 1);
|
||||
}
|
||||
range.text = mopen + str + mclose;
|
||||
}
|
||||
range.select();
|
||||
} else { tarea.value += mopen + mtext + mclose; }
|
||||
return;
|
||||
}
|
||||
|
After Width: | Height: | Size: 691 B |
|
After Width: | Height: | Size: 696 B |
|
After Width: | Height: | Size: 699 B |
|
After Width: | Height: | Size: 700 B |
|
After Width: | Height: | Size: 664 B |
|
After Width: | Height: | Size: 662 B |
|
After Width: | Height: | Size: 649 B |
|
After Width: | Height: | Size: 741 B |
|
After Width: | Height: | Size: 677 B |
|
After Width: | Height: | Size: 657 B |
|
After Width: | Height: | Size: 707 B |
|
After Width: | Height: | Size: 722 B |
|
After Width: | Height: | Size: 648 B |
|
After Width: | Height: | Size: 643 B |
|
After Width: | Height: | Size: 703 B |
|
After Width: | Height: | Size: 752 B |
|
After Width: | Height: | Size: 712 B |
|
After Width: | Height: | Size: 716 B |
|
After Width: | Height: | Size: 719 B |
|
After Width: | Height: | Size: 654 B |
|
After Width: | Height: | Size: 668 B |
|
After Width: | Height: | Size: 712 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1,16 @@
|
||||
Built May 2014, starting with source from:
|
||||
http://purecss.io/layouts/side-menu/
|
||||
The hard part was done by the YUI and Normalise.js developers.
|
||||
|
||||
This skin's page on PmWiki.org:
|
||||
http://www.pmwiki.org/wiki/PmWiki/Skins/Adapt
|
||||
The CMS Mode recipe works well with this skin:
|
||||
http://www.pmwiki.org/wiki/Cookbook/CMSMode
|
||||
|
||||
Install by copying the directory to pub/skins/ and putting
|
||||
this in your config.php configuration file:
|
||||
|
||||
## Use the Adapt Skin
|
||||
$Skin = 'adapt';
|
||||
|
||||
Enjoy.
|
||||
@@ -0,0 +1,203 @@
|
||||
body { color: #333; }
|
||||
|
||||
.pure-img-responsive { max-width: 100%; height: auto; }
|
||||
|
||||
/*
|
||||
Add transition to containers so they can push in and out.
|
||||
*/
|
||||
#layout, #menu, .menu-link {
|
||||
-webkit-transition: all 0.2s ease-out;
|
||||
-moz-transition: all 0.2s ease-out;
|
||||
-ms-transition: all 0.2s ease-out;
|
||||
-o-transition: all 0.2s ease-out;
|
||||
transition: all 0.2s ease-out;
|
||||
}
|
||||
|
||||
/*
|
||||
This is the parent `<div>` that contains the menu and the content area.
|
||||
Hamburger Menu styles are first, wider @media styles are below.
|
||||
*/
|
||||
#layout { position: relative; padding-left: 0; }
|
||||
#layout.active { position: relative; left: 180px; }
|
||||
#layout.active #menu { left: 180px; width: 180px; }
|
||||
#layout.active .menu-link { left: 180px; }
|
||||
|
||||
/*
|
||||
The content `<div>` is where all your content goes.
|
||||
*/
|
||||
.content { margin: 0 auto; padding: 0 2em; max-width: 800px;
|
||||
margin-bottom: 50px; line-height: 1.6em; }
|
||||
.content a { max-width:100%; height:auto; } /*TODO wiki needs to style it*/
|
||||
|
||||
/* Wiki page actions */
|
||||
#wikicmds { float:right; white-space:nowrap; font-size:90%; }
|
||||
#wikicmds ul { list-style:none; margin:0px; padding:0px; }
|
||||
#wikicmds li { display:inline; margin:0px 5px; }
|
||||
#wikicmds li a { text-decoration:none; color:#333; border:none; }
|
||||
#wikicmds li a.createlink { display:none; }
|
||||
#wikicmds li a:hover { text-decoration:underline; color:blue; }
|
||||
|
||||
/* The headerlogo element is (Site|Group).HeaderLogo TODO */
|
||||
.headerlogo { border-bottom:1px #ccc solid; }
|
||||
|
||||
/* Wiki Header - Logo and Search box */
|
||||
#wikihead { position:absolute; right:10px; top:10px; font-size:85%; }
|
||||
#wikihead form { display:none; }
|
||||
#wikihead input { font-size:85%; }
|
||||
/* The #wikilogo element is the logo from $PageLogoFmt */
|
||||
#wikilogo { padding:10px 2em 6px 75px; text-align:right;
|
||||
background: #eee; border-bottom:1px #ccc solid; }
|
||||
|
||||
/* Wiki page title */
|
||||
.title { margin: 0 auto; color: #000; padding: 1em 2em 0.5em;
|
||||
max-width: 800px; border-bottom: 1px solid #eee; }
|
||||
.title h1 { margin: 0em 0; font-size: 2em; font-weight: 300; }
|
||||
|
||||
/*TODO Wikify this*/
|
||||
.content-subhead { margin: 50px 0 20px 0; font-weight: 300; color: #888;}
|
||||
|
||||
/* Edit Form */
|
||||
#wikiedit form { margin:0px; width:100%; line-height:1.1em; }
|
||||
#wikiedit textarea { margin:0px; width:99.5%; height:18em; }
|
||||
#wikiedit input[type=text] { margin:0px; width:99.5%; }
|
||||
h2.wikiaction { margin:0px }
|
||||
.wikimessage { margin-top:3px; margin-bottom:3px; font-style:italic;
|
||||
color:black; background-color:#ffffcc; padding:2px; }
|
||||
|
||||
/* For the (Site.)Search page */
|
||||
.searchbox { margin-right:2px; max-width:100%; }
|
||||
|
||||
#wikifoot { font-size:80%; padding-top:2em; text-align:center; }
|
||||
.footnav a { text-decoration:none; color:black; }
|
||||
.footnav a:hover { text-decoration:underline; color:blue; }
|
||||
.lastmod { color:#999; }
|
||||
|
||||
/*
|
||||
The `#menu` `<div>` is the parent `<div>` that contains the `.pure-menu` that
|
||||
appears on the left side of the page.
|
||||
*/
|
||||
|
||||
#menu {
|
||||
margin-left: -180px; /* "#menu" width */
|
||||
width: 180px;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 1000; /* so the menu or its navicon stays above all content */
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
background: #eee;
|
||||
border-right: 1px solid #ccc;
|
||||
}
|
||||
/* All anchors inside the menu should be styled like this. */
|
||||
#menu a { color: #000; border: none; padding: 0.6em 0 0.3em 0.6em; }
|
||||
/* Sidebar Headings too TODO */
|
||||
#menu .sidehead { color: #000; border: none; padding: 0.6em 0 0.3em 0.6em; }
|
||||
/* Remove all background/borders, since we are applying them to #menu.*/
|
||||
#menu .pure-menu,
|
||||
#menu .pure-menu ul {
|
||||
border: none; background: transparent; }
|
||||
/* Add that light border to separate items into groups. */
|
||||
#menu .pure-menu ul,
|
||||
#menu .pure-menu .menu-item-divided {
|
||||
padding-top: 0.5em; }
|
||||
/* Change color of the anchor links on hover/focus. */
|
||||
#menu .pure-menu li a:hover,
|
||||
#menu .pure-menu li a:focus {
|
||||
background: #ccc; }
|
||||
/* This styles the selected menu item `<li>`. */
|
||||
#menu .pure-menu-selected,
|
||||
#menu .pure-menu-heading {
|
||||
background: #1f8dd6; }
|
||||
/* This styles a link within a selected menu item `<li>`. */
|
||||
#menu .pure-menu-selected a { color: #444; }
|
||||
/* This styles the menu heading. */
|
||||
#menu .pure-menu-heading {
|
||||
font-size: 110%; color: #444; margin: 0; }
|
||||
|
||||
/* Sidebar headings */
|
||||
#menu .sidehead {
|
||||
color: #000; border: none; padding: 0.6em 0 0 0.6em; background: #eee; }
|
||||
#menu .sidehead a { color:#000; }
|
||||
#menu .sidehead a:hover { text-decoration:underline; }
|
||||
/* Side menu search form TODO */
|
||||
#menu .sidesearch {
|
||||
background: #eee; color: #000; padding-bottom: 0.2em; padding-top: 0.5em; }
|
||||
#menu .sidesearch a:hover {
|
||||
text-decoration:underline; }
|
||||
|
||||
|
||||
/* -- Dynamic Button For Responsive Menu -------------------------------------*/
|
||||
|
||||
/*
|
||||
The button to open/close the Menu is custom-made and not part of Pure. Here's
|
||||
how it works:
|
||||
*/
|
||||
|
||||
/*
|
||||
`.menu-link` represents the responsive menu toggle that shows/hides on
|
||||
small screens.
|
||||
*/
|
||||
.menu-link {
|
||||
position: fixed;
|
||||
display: block; /* show this only on small screens */
|
||||
top: 0;
|
||||
left: 0; /* "#menu width" */
|
||||
background: #000;
|
||||
background: rgba(0,0,0,0.7);
|
||||
font-size: 10px; /* change this value to increase/decrease button size */
|
||||
z-index: 10;
|
||||
width: 2em;
|
||||
height: auto;
|
||||
padding: 2.1em 1.6em;
|
||||
}
|
||||
|
||||
.menu-link:hover,
|
||||
.menu-link:focus {
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.menu-link span {
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.menu-link span,
|
||||
.menu-link span:before,
|
||||
.menu-link span:after {
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
height: 0.2em;
|
||||
}
|
||||
|
||||
.menu-link span:before,
|
||||
.menu-link span:after {
|
||||
position: absolute;
|
||||
margin-top: -0.6em;
|
||||
content: " ";
|
||||
}
|
||||
|
||||
.menu-link span:after {
|
||||
margin-top: 0.6em;
|
||||
}
|
||||
|
||||
/*
|
||||
Responsive Styles (Media Queries)
|
||||
These styles are activated when the display is wider; the Hamburger
|
||||
will disappear and the Side Menu for larger displays will be visible.
|
||||
|
||||
/* Hide the menu at `48em`, but modify this based on your app's needs. */
|
||||
#menu .sidesearch { display: none; }
|
||||
#wikilogo { padding-left: 1em; text-align:left; }
|
||||
#wikihead form { margin-top: 0.3em; display:block; }
|
||||
.title,
|
||||
.content { padding-left: 2em; padding-right: 2em; }
|
||||
/* width of the left (menu) column */
|
||||
#layout { padding-left: 180px; left: 0; }
|
||||
#menu { left: 180px; }
|
||||
|
||||
.menu-link {
|
||||
position: fixed; left: 180px; display: none; }
|
||||
|
||||
#layout.active .menu-link { left: 180px; }
|
||||
@@ -0,0 +1,219 @@
|
||||
body { color: #333; }
|
||||
|
||||
.pure-img-responsive { max-width: 100%; height: auto; }
|
||||
|
||||
/*
|
||||
Add transition to containers so they can push in and out.
|
||||
*/
|
||||
#layout, #menu, .menu-link {
|
||||
-webkit-transition: all 0.2s ease-out;
|
||||
-moz-transition: all 0.2s ease-out;
|
||||
-ms-transition: all 0.2s ease-out;
|
||||
-o-transition: all 0.2s ease-out;
|
||||
transition: all 0.2s ease-out;
|
||||
}
|
||||
|
||||
/*
|
||||
This is the parent `<div>` that contains the menu and the content area.
|
||||
Hamburger Menu styles are first, wider @media styles are below.
|
||||
*/
|
||||
#layout { position: relative; padding-left: 0; }
|
||||
#layout.active { position: relative; left: 175px; }
|
||||
#layout.active #menu { left: 175px; width: 175px; }
|
||||
#layout.active .menu-link { left: 175px; }
|
||||
|
||||
/*
|
||||
The content `<div>` is where all your content goes.
|
||||
*/
|
||||
.content { margin: 0 auto; padding: 0 2em; max-width: 800px;
|
||||
margin-bottom: 50px; line-height: 1.6em; }
|
||||
.content img { max-width:100%; height:auto; } /*TODO wiki needs to style it*/
|
||||
/* links in the content area */
|
||||
.content a { font-weight:bold; color:#0055bb; text-decoration:none; }
|
||||
.content a:visited { font-weight:bold; color:#003399; text-decoration:none; }
|
||||
.content a:hover {color:#0066cc; text-decoration:underline; }
|
||||
.content a:active { color#9c0606; }
|
||||
/* Wiki page actions */
|
||||
#wikicmds { float:right; white-space:nowrap; font-size:90%; }
|
||||
#wikicmds ul { list-style:none; margin:0px; padding:0px; }
|
||||
#wikicmds li { display:inline; margin:0px 5px; }
|
||||
#wikicmds li a { text-decoration:none; color:#333; border:none; }
|
||||
#wikicmds li a.createlink { display:none; }
|
||||
#wikicmds li a:hover { text-decoration:underline; color:blue; }
|
||||
|
||||
/* The headerlogo element is (Site|Group).HeaderLogo TODO */
|
||||
.headerlogo { border-bottom:1px #ccc solid; }
|
||||
|
||||
/* Wiki Header - Logo and Search box */
|
||||
#wikihead { position:absolute; right:10px; top:10px; font-size:85%; }
|
||||
#wikihead form { display:none; }
|
||||
#wikihead input { font-size:85%; }
|
||||
/* The #wikilogo element is the logo from $PageLogoFmt */
|
||||
#wikilogo { padding:10px 2em 6px 75px; text-align:right;
|
||||
background: #eee; border-bottom:1px #ccc solid; }
|
||||
|
||||
/* Wiki page title */
|
||||
.title { margin: 0 auto; color: #000; padding: 1em 2em 0.5em;
|
||||
max-width: 800px; border-bottom: 1px solid #eee; }
|
||||
.title h1 { margin: 0em 0; font-size: 2em; font-weight: 300; }
|
||||
|
||||
/*TODO Wikify this*/
|
||||
.content-subhead { margin: 50px 0 20px 0; font-weight: 300; color: #888;}
|
||||
|
||||
/* Edit Form */
|
||||
#wikiedit form { margin:0px; width:100%; line-height:1.1em; }
|
||||
#wikiedit textarea { margin:0px; width:99.5%; height:18em; }
|
||||
#wikiedit input[type=text] { margin:0px; width:99.5%; }
|
||||
h2.wikiaction { margin:0px }
|
||||
.wikimessage { margin-top:3px; margin-bottom:3px; font-style:italic;
|
||||
color:black; background-color:#ffffcc; padding:2px; }
|
||||
|
||||
/* For the (Site.)Search page */
|
||||
.searchbox { margin-right:2px; max-width:100%; }
|
||||
|
||||
#wikifoot { font-size:80%; padding-top:2em; text-align:center; }
|
||||
.footnav a,
|
||||
.footnav a:visited {
|
||||
font-weight:normal; text-decoration:none; color:black; }
|
||||
.footnav a:hover { text-decoration:underline; color:blue; }
|
||||
.lastmod { color:#999; }
|
||||
|
||||
/*
|
||||
The `#menu` `<div>` is the parent `<div>` that contains the `.pure-menu` that
|
||||
appears on the left side of the page.
|
||||
*/
|
||||
|
||||
#menu {
|
||||
margin-left: -175px; /* "#menu" width */
|
||||
width: 175px;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 1000; /* so the menu or its navicon stays above all content */
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
background: #eee;
|
||||
border-right: 1px solid #ccc;
|
||||
}
|
||||
/* All anchors inside the menu should be styled like this. */
|
||||
#menu a { color: #000; border: none; padding: 0.6em 0 0.3em 0.6em; font-size:85%; }
|
||||
/* Sidebar Headings too TODO */
|
||||
#menu .sidehead { color: #000; border: none; padding: 0.6em 0 0.3em 0.6em; }
|
||||
/* Remove all background/borders, since we are applying them to #menu.*/
|
||||
#menu .pure-menu,
|
||||
#menu .pure-menu ul {
|
||||
border: none; background: transparent; }
|
||||
/* Add that light border to separate items into groups. */
|
||||
#menu .pure-menu ul,
|
||||
#menu .pure-menu .menu-item-divided {
|
||||
padding-top: 0.5em; }
|
||||
/* Change color of the anchor links on hover/focus. */
|
||||
#menu .pure-menu li a:hover,
|
||||
#menu .pure-menu li a:focus {
|
||||
background: #ccc; }
|
||||
/* This styles the selected menu item `<li>`. */
|
||||
#menu .pure-menu-selected,
|
||||
#menu .pure-menu-heading {
|
||||
background: #1f8dd6; }
|
||||
/* This styles a link within a selected menu item `<li>`. */
|
||||
#menu .pure-menu-selected a { color: #444; }
|
||||
/* This styles the menu heading. */
|
||||
#menu .pure-menu-heading {
|
||||
font-size: 110%; color: #444; margin: 0; }
|
||||
|
||||
/* Sidebar headings */
|
||||
#menu .sidehead {
|
||||
color: #000; border: none; padding: 0.6em 0 0 0.6em; background: #eee; }
|
||||
#menu .sidehead a { color:#000; }
|
||||
#menu .sidehead a:hover { text-decoration:underline; }
|
||||
/* Side menu search form TODO */
|
||||
#menu .sidesearch {
|
||||
background: #eee; color: #000; padding-bottom: 0.2em; padding-top: 0.5em; }
|
||||
#menu .sidesearch a:hover {
|
||||
text-decoration:underline; }
|
||||
|
||||
|
||||
/* -- Dynamic Button For Responsive Menu -------------------------------------*/
|
||||
|
||||
/*
|
||||
The button to open/close the Menu is custom-made and not part of Pure. Here's
|
||||
how it works:
|
||||
*/
|
||||
|
||||
/*
|
||||
`.menu-link` represents the responsive menu toggle that shows/hides on
|
||||
small screens.
|
||||
*/
|
||||
.menu-link {
|
||||
position: fixed;
|
||||
display: block; /* show this only on small screens */
|
||||
top: 0;
|
||||
left: 0; /* "#menu width" */
|
||||
background: #000;
|
||||
background: rgba(0,0,0,0.7);
|
||||
font-size: 10px; /* change this value to increase/decrease button size */
|
||||
z-index: 10;
|
||||
width: 2em;
|
||||
height: auto;
|
||||
padding: 2.1em 1.6em;
|
||||
}
|
||||
|
||||
.menu-link:hover,
|
||||
.menu-link:focus {
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.menu-link span {
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.menu-link span,
|
||||
.menu-link span:before,
|
||||
.menu-link span:after {
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
height: 0.2em;
|
||||
}
|
||||
|
||||
.menu-link span:before,
|
||||
.menu-link span:after {
|
||||
position: absolute;
|
||||
margin-top: -0.6em;
|
||||
content: " ";
|
||||
}
|
||||
|
||||
.menu-link span:after {
|
||||
margin-top: 0.6em;
|
||||
}
|
||||
|
||||
/*
|
||||
Responsive Styles (Media Queries)
|
||||
These styles are activated when the display is wider; the Hamburger
|
||||
will disappear and the Side Menu for larger displays will be visible.
|
||||
|
||||
/* Hide the menu at `48em`, but modify this based on your app's needs. */
|
||||
@media (min-width: 48em) {
|
||||
#menu .sidesearch { display: none; }
|
||||
#wikilogo { padding-left: 1em; text-align:left; }
|
||||
#wikihead form { margin-top: 0.3em; display:block; }
|
||||
.title,
|
||||
.content { padding-left: 2em; padding-right: 2em; }
|
||||
/* width of the left (menu) column */
|
||||
#layout { padding-left: 175px; left: 0; }
|
||||
#menu { left: 175px; }
|
||||
|
||||
.menu-link {
|
||||
position: fixed; left: 175px; display: none; }
|
||||
|
||||
#layout.active .menu-link { left: 175px; }
|
||||
}
|
||||
|
||||
@media print {
|
||||
#menu, #wikihead, #wikilogo { display:none; }
|
||||
.headerlogo, .content, .title {
|
||||
margin-left: -175px; }
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{$Title} | $WikiTitle $ActionTitle </title></title>
|
||||
<link rel="stylesheet" href="$SkinDirUrl/pure-min.css">
|
||||
<!--[if lte IE 8]>
|
||||
<link rel="stylesheet" href="$SkinDirUrl/adapt-old-ie.css">
|
||||
<![endif]-->
|
||||
<!--[if gt IE 8]><!-->
|
||||
<link rel="stylesheet" href="$SkinDirUrl/adapt.css">
|
||||
<!--<![endif]-->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="$SkinDirUrl/html5shiv.js"></script>
|
||||
<![endif]-->
|
||||
<!--HTMLHeader-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="layout">
|
||||
<!--PageLeftFmt-->
|
||||
<!-- HeaderLogo Menu toggle -->
|
||||
<a href="#menu" id="menuLink" class="menu-link">
|
||||
<!-- Hamburger icon -->
|
||||
<span></span>
|
||||
</a>
|
||||
<div id="menu">
|
||||
<div class="pure-menu pure-menu-open">
|
||||
<div class='sidesearch'><a href='http://www.haganfox.net/Site/Search'>Search</a></div>
|
||||
<!--wiki:{$Group}.AdaptSideBar {$SiteGroup}.AdaptSideBar-->
|
||||
<!--wiki:{$Group}.SideBar {$SiteGroup}.SideBar-->
|
||||
</div>
|
||||
</div>
|
||||
<!--/PageLeftFmt-->
|
||||
<div id="main">
|
||||
<!--PageHeaderFmt-->
|
||||
<div id='wikilogo'><a href='{$HeaderLink}'><img src='$PageLogoUrl'
|
||||
alt='$WikiTitle' border='0' /></a></div>
|
||||
<div id='wikihead'>
|
||||
<form action='{$ScriptUrl}'>
|
||||
<span class='headnav'><a href='{$ScriptUrl}/$[{$Group}/RecentChanges]'
|
||||
accesskey='$[ak_recentchanges]'>$[Recent Changes]</a> -</span>
|
||||
<input type='hidden' name='n' value='{$FullName}' />
|
||||
<input type='hidden' name='action' value='search' />
|
||||
<a href='{$ScriptUrl}/$[{$SiteGroup}/Search]'>$[Search]</a>:
|
||||
<input type='text' name='q' value='' class='inputbox searchbox' />
|
||||
<input type='submit' class='inputbutton searchbutton'
|
||||
value='$[Go]' /></form></div>
|
||||
<!--PageActionFmt-->
|
||||
<div id='wikicmds'><!--wiki:{$Group}.PageActions {$SiteGroup}.PageActions--></div>
|
||||
<!--PageTitleFmt-->
|
||||
<div class="title">
|
||||
<div class='pagegroup'><a href='{$ScriptUrl}/{$Group}'>{$Group}</a> /</div>
|
||||
<h1 class='pagetitle'>{$Title}</h1>
|
||||
</div>
|
||||
<!--/PageTitleFmt-->
|
||||
<div class="content">
|
||||
<!--PageText-->
|
||||
<!--PageFooterFmt-->
|
||||
<div id='wikifoot'><div class='footnav'>
|
||||
<a rel="nofollow" href='{$PageUrl}?action=edit'>$[Edit]</a> -
|
||||
<a rel="nofollow" href='{$PageUrl}?action=diff'>$[History]</a> -
|
||||
<a rel="nofollow" href='{$PageUrl}?action=print' target='_blank'>$[Print]</a> -
|
||||
<a href='{$ScriptUrl}/$[{$Group}/RecentChanges]'>$[Recent Changes]</a> -
|
||||
<a href='{$ScriptUrl}/$[{$SiteGroup}/Search]'>$[Search]</a></div>
|
||||
<div class='lastmod'>$[Page last modified on {$LastModified}]</div>
|
||||
</div>
|
||||
<!--/PageFooterFmt-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="$SkinDirUrl/ui.js"></script>
|
||||
<!--HTMLFooter-->
|
||||
<!-- Yandex.Metrika counter -->
|
||||
<script type="text/javascript">
|
||||
(function (d, w, c) {
|
||||
(w[c] = w[c] || []).push(function() {
|
||||
try {
|
||||
w.yaCounter25827098 = new Ya.Metrika({id:25827098,
|
||||
clickmap:true,
|
||||
accurateTrackBounce:true});
|
||||
} catch(e) { }
|
||||
});
|
||||
|
||||
var n = d.getElementsByTagName("script")[0],
|
||||
s = d.createElement("script"),
|
||||
f = function () { n.parentNode.insertBefore(s, n); };
|
||||
s.type = "text/javascript";
|
||||
s.async = true;
|
||||
s.src = (d.location.protocol == "https:" ? "https:" : "http:") + "//mc.yandex.ru/metrika/watch.js";
|
||||
|
||||
if (w.opera == "[object Opera]") {
|
||||
d.addEventListener("DOMContentLoaded", f, false);
|
||||
} else { f(); }
|
||||
})(document, window, "yandex_metrika_callbacks");
|
||||
</script>
|
||||
<noscript><div><img src="//mc.yandex.ru/watch/25827098" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
||||
<!-- /Yandex.Metrika counter -->
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,301 @@
|
||||
/**
|
||||
* @preserve HTML5 Shiv v3.7.0 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
||||
*/
|
||||
;(function(window, document) {
|
||||
/*jshint evil:true */
|
||||
/** version */
|
||||
var version = '3.7.0';
|
||||
|
||||
/** Preset options */
|
||||
var options = window.html5 || {};
|
||||
|
||||
/** Used to skip problem elements */
|
||||
var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
|
||||
|
||||
/** Not all elements can be cloned in IE **/
|
||||
var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
|
||||
|
||||
/** Detect whether the browser supports default html5 styles */
|
||||
var supportsHtml5Styles;
|
||||
|
||||
/** Name of the expando, to work with multiple documents or to re-shiv one document */
|
||||
var expando = '_html5shiv';
|
||||
|
||||
/** The id for the the documents expando */
|
||||
var expanID = 0;
|
||||
|
||||
/** Cached data for each document */
|
||||
var expandoData = {};
|
||||
|
||||
/** Detect whether the browser supports unknown elements */
|
||||
var supportsUnknownElements;
|
||||
|
||||
(function() {
|
||||
try {
|
||||
var a = document.createElement('a');
|
||||
a.innerHTML = '<xyz></xyz>';
|
||||
//if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
|
||||
supportsHtml5Styles = ('hidden' in a);
|
||||
|
||||
supportsUnknownElements = a.childNodes.length == 1 || (function() {
|
||||
// assign a false positive if unable to shiv
|
||||
(document.createElement)('a');
|
||||
var frag = document.createDocumentFragment();
|
||||
return (
|
||||
typeof frag.cloneNode == 'undefined' ||
|
||||
typeof frag.createDocumentFragment == 'undefined' ||
|
||||
typeof frag.createElement == 'undefined'
|
||||
);
|
||||
}());
|
||||
} catch(e) {
|
||||
// assign a false positive if detection fails => unable to shiv
|
||||
supportsHtml5Styles = true;
|
||||
supportsUnknownElements = true;
|
||||
}
|
||||
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Creates a style sheet with the given CSS text and adds it to the document.
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
* @param {String} cssText The CSS text.
|
||||
* @returns {StyleSheet} The style element.
|
||||
*/
|
||||
function addStyleSheet(ownerDocument, cssText) {
|
||||
var p = ownerDocument.createElement('p'),
|
||||
parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
|
||||
|
||||
p.innerHTML = 'x<style>' + cssText + '</style>';
|
||||
return parent.insertBefore(p.lastChild, parent.firstChild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of `html5.elements` as an array.
|
||||
* @private
|
||||
* @returns {Array} An array of shived element node names.
|
||||
*/
|
||||
function getElements() {
|
||||
var elements = html5.elements;
|
||||
return typeof elements == 'string' ? elements.split(' ') : elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data associated to the given document
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
* @returns {Object} An object of data.
|
||||
*/
|
||||
function getExpandoData(ownerDocument) {
|
||||
var data = expandoData[ownerDocument[expando]];
|
||||
if (!data) {
|
||||
data = {};
|
||||
expanID++;
|
||||
ownerDocument[expando] = expanID;
|
||||
expandoData[expanID] = data;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a shived element for the given nodeName and document
|
||||
* @memberOf html5
|
||||
* @param {String} nodeName name of the element
|
||||
* @param {Document} ownerDocument The context document.
|
||||
* @returns {Object} The shived element.
|
||||
*/
|
||||
function createElement(nodeName, ownerDocument, data){
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
if(supportsUnknownElements){
|
||||
return ownerDocument.createElement(nodeName);
|
||||
}
|
||||
if (!data) {
|
||||
data = getExpandoData(ownerDocument);
|
||||
}
|
||||
var node;
|
||||
|
||||
if (data.cache[nodeName]) {
|
||||
node = data.cache[nodeName].cloneNode();
|
||||
} else if (saveClones.test(nodeName)) {
|
||||
node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
|
||||
} else {
|
||||
node = data.createElem(nodeName);
|
||||
}
|
||||
|
||||
// Avoid adding some elements to fragments in IE < 9 because
|
||||
// * Attributes like `name` or `type` cannot be set/changed once an element
|
||||
// is inserted into a document/fragment
|
||||
// * Link elements with `src` attributes that are inaccessible, as with
|
||||
// a 403 response, will cause the tab/window to crash
|
||||
// * Script elements appended to fragments will execute when their `src`
|
||||
// or `text` property is set
|
||||
return node.canHaveChildren && !reSkip.test(nodeName) ? data.frag.appendChild(node) : node;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a shived DocumentFragment for the given document
|
||||
* @memberOf html5
|
||||
* @param {Document} ownerDocument The context document.
|
||||
* @returns {Object} The shived DocumentFragment.
|
||||
*/
|
||||
function createDocumentFragment(ownerDocument, data){
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
if(supportsUnknownElements){
|
||||
return ownerDocument.createDocumentFragment();
|
||||
}
|
||||
data = data || getExpandoData(ownerDocument);
|
||||
var clone = data.frag.cloneNode(),
|
||||
i = 0,
|
||||
elems = getElements(),
|
||||
l = elems.length;
|
||||
for(;i<l;i++){
|
||||
clone.createElement(elems[i]);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shivs the `createElement` and `createDocumentFragment` methods of the document.
|
||||
* @private
|
||||
* @param {Document|DocumentFragment} ownerDocument The document.
|
||||
* @param {Object} data of the document.
|
||||
*/
|
||||
function shivMethods(ownerDocument, data) {
|
||||
if (!data.cache) {
|
||||
data.cache = {};
|
||||
data.createElem = ownerDocument.createElement;
|
||||
data.createFrag = ownerDocument.createDocumentFragment;
|
||||
data.frag = data.createFrag();
|
||||
}
|
||||
|
||||
|
||||
ownerDocument.createElement = function(nodeName) {
|
||||
//abort shiv
|
||||
if (!html5.shivMethods) {
|
||||
return data.createElem(nodeName);
|
||||
}
|
||||
return createElement(nodeName, ownerDocument, data);
|
||||
};
|
||||
|
||||
ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
|
||||
'var n=f.cloneNode(),c=n.createElement;' +
|
||||
'h.shivMethods&&(' +
|
||||
// unroll the `createElement` calls
|
||||
getElements().join().replace(/[\w\-]+/g, function(nodeName) {
|
||||
data.createElem(nodeName);
|
||||
data.frag.createElement(nodeName);
|
||||
return 'c("' + nodeName + '")';
|
||||
}) +
|
||||
');return n}'
|
||||
)(html5, data.frag);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Shivs the given document.
|
||||
* @memberOf html5
|
||||
* @param {Document} ownerDocument The document to shiv.
|
||||
* @returns {Document} The shived document.
|
||||
*/
|
||||
function shivDocument(ownerDocument) {
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
var data = getExpandoData(ownerDocument);
|
||||
|
||||
if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
|
||||
data.hasCSS = !!addStyleSheet(ownerDocument,
|
||||
// corrects block display not defined in IE6/7/8/9
|
||||
'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
|
||||
// adds styling not present in IE6/7/8/9
|
||||
'mark{background:#FF0;color:#000}' +
|
||||
// hides non-rendered elements
|
||||
'template{display:none}'
|
||||
);
|
||||
}
|
||||
if (!supportsUnknownElements) {
|
||||
shivMethods(ownerDocument, data);
|
||||
}
|
||||
return ownerDocument;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* The `html5` object is exposed so that more elements can be shived and
|
||||
* existing shiving can be detected on iframes.
|
||||
* @type Object
|
||||
* @example
|
||||
*
|
||||
* // options can be changed before the script is included
|
||||
* html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
|
||||
*/
|
||||
var html5 = {
|
||||
|
||||
/**
|
||||
* An array or space separated string of node names of the elements to shiv.
|
||||
* @memberOf html5
|
||||
* @type Array|String
|
||||
*/
|
||||
'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video',
|
||||
|
||||
/**
|
||||
* current version of html5shiv
|
||||
*/
|
||||
'version': version,
|
||||
|
||||
/**
|
||||
* A flag to indicate that the HTML5 style sheet should be inserted.
|
||||
* @memberOf html5
|
||||
* @type Boolean
|
||||
*/
|
||||
'shivCSS': (options.shivCSS !== false),
|
||||
|
||||
/**
|
||||
* Is equal to true if a browser supports creating unknown/HTML5 elements
|
||||
* @memberOf html5
|
||||
* @type boolean
|
||||
*/
|
||||
'supportsUnknownElements': supportsUnknownElements,
|
||||
|
||||
/**
|
||||
* A flag to indicate that the document's `createElement` and `createDocumentFragment`
|
||||
* methods should be overwritten.
|
||||
* @memberOf html5
|
||||
* @type Boolean
|
||||
*/
|
||||
'shivMethods': (options.shivMethods !== false),
|
||||
|
||||
/**
|
||||
* A string to describe the type of `html5` object ("default" or "default print").
|
||||
* @memberOf html5
|
||||
* @type String
|
||||
*/
|
||||
'type': 'default',
|
||||
|
||||
// shivs the document according to the specified `html5` object options
|
||||
'shivDocument': shivDocument,
|
||||
|
||||
//creates a shived element
|
||||
createElement: createElement,
|
||||
|
||||
//creates a shived documentFragment
|
||||
createDocumentFragment: createDocumentFragment
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
// expose html5
|
||||
window.html5 = html5;
|
||||
|
||||
// shiv the document
|
||||
shivDocument(document);
|
||||
|
||||
}(this, document));
|
||||
@@ -0,0 +1,52 @@
|
||||
Software License Agreement (BSD License)
|
||||
========================================
|
||||
|
||||
Copyright 2014 Yahoo! Inc. All rights reserved.
|
||||
|
||||
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.
|
||||
|
||||
* Neither the name of the Yahoo! Inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 YAHOO! INC. 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.
|
||||
|
||||
|
||||
Normalize.css License
|
||||
=====================
|
||||
|
||||
Copyright (c) Nicolas Gallagher and Jonathan Neal
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,35 @@
|
||||
(function (window, document) {
|
||||
|
||||
var layout = document.getElementById('layout'),
|
||||
menu = document.getElementById('menu'),
|
||||
menuLink = document.getElementById('menuLink');
|
||||
|
||||
function toggleClass(element, className) {
|
||||
var classes = element.className.split(/\s+/),
|
||||
length = classes.length,
|
||||
i = 0;
|
||||
|
||||
for(; i < length; i++) {
|
||||
if (classes[i] === className) {
|
||||
classes.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// The className is not found
|
||||
if (length === classes.length) {
|
||||
classes.push(className);
|
||||
}
|
||||
|
||||
element.className = classes.join(' ');
|
||||
}
|
||||
|
||||
menuLink.onclick = function (e) {
|
||||
var active = 'active';
|
||||
|
||||
e.preventDefault();
|
||||
toggleClass(layout, active);
|
||||
toggleClass(menu, active);
|
||||
toggleClass(menuLink, active);
|
||||
};
|
||||
|
||||
}(this, this.document));
|
||||
@@ -0,0 +1,148 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" dir="ltr">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{$Title} | $WikiTitle $ActionTitle </title>
|
||||
<meta name="description" content="$WikiTitle $ActionTitle" />
|
||||
<meta name="keywords" content="$Title, $WikiTitle $ActionTitle. graph wikipedia" />
|
||||
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/i/image/touch_icon/favicon_144x144.png" />
|
||||
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/i/image/touch_icon/favicon_114x114.png" />
|
||||
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/i/image/touch_icon/favicon_72x72.png" />
|
||||
<link rel="apple-touch-icon-precomposed" href="/i/image/touch_icon/favicon_57x57.png" />
|
||||
|
||||
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
|
||||
|
||||
<meta http-equiv="cleartype" content="on">
|
||||
|
||||
|
||||
|
||||
<!-- Следущая строчка нужна для обозначения места вставки объеденённых css/js файлов. Её не следует удалять.-->
|
||||
<!-- extraPacker --><link rel="stylesheet" charset="UTF-8" type="text/css" href="/tmp/wiki/css1486493398.css" /><script type="text/javascript" charset="UTF-8" src="/i/js/dev/jquery-2.0.3.js"></script>
|
||||
|
||||
<link media="screen" rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=PT+Sans:400,700,400italic,700italic&subset=latin,cyrillic" />
|
||||
|
||||
<link rel="stylesheet" href="$SkinDirUrl/style.css">
|
||||
<!--HTMLHeader-->
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="container page-wrap">
|
||||
<!-- <div class="header"> -->
|
||||
<nav class="navbar navbar-default">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/"><span class="fa fa-sitemap fa-fw"></span> Graph Online</a>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class=""><a href="/">Главная</a></li>
|
||||
<li class="dropdown"> <a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-expanded="false"> Создать граф <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/create_graph_by_matrix">По матрице смежности</a></li>
|
||||
<li><a href="/create_graph_by_incidence_matrix">По матрице инцидентности</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown"> <a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-expanded="false"> Справка <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/help">Быстрый старт</a></li>
|
||||
<li><a href="/wiki">Вики</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class=""><a href="/news">Новости</a></li>
|
||||
<li class=""><a href="/contacts">Обратная связь</a></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><img src="/i/image/flags/enru.png" alt=""> Язык <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/en/wiki" title="English" class=""><img src="/i/image/flags/en.png" alt="English"> English</a></li>
|
||||
<li><a href="/wiki" title="Русский" class="selected"><img src="/i/image/flags/ru.png" alt="Русский"> Русский</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="content">
|
||||
<a href='{$ScriptUrl}/{$Group}' class="navbar-brand" style="padding-right: 0px;">{$Group}<span class="fa fa-chevron-right fa-fw"></span></a><h1 style="display: inline-block;">{$Title}</h1>
|
||||
|
||||
<form action='{$ScriptUrl}' style="float:right">
|
||||
<input type='hidden' name='n' value='{$FullName}' />
|
||||
<input type='hidden' name='action' value='search' />
|
||||
<a href='{$ScriptUrl}/$[{$SiteGroup}/Search]'><span class="fa fa-search" ></span></a>
|
||||
<input type='text' name='q' value='' class='inputbox searchbox' />
|
||||
<input type='submit' class="btn btn-primary"
|
||||
value='найти' /></form>
|
||||
|
||||
<!--PageText-->
|
||||
|
||||
<div class="page-btns">
|
||||
<a class="btn btn-default" onclick="window.history.back(); return false;" href="#"><i class="fa fa-lg fa-angle-left"></i> Назад</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Футер приходится обрамить в .container, потому что у него position:absolute и он занимает всю ширину игнорируя паддинги родителя -->
|
||||
<footer class="footer" id="footer">
|
||||
<div class="container">
|
||||
<p>© <a href="/">Граф Online</a> - создание и визуализация графа в два клика или по матрице смежности и <a href="http://graphonline.ru/">поиск кратчайшего пути</a>, поиск компоненты связности, поиск Эйлеровго цикла. Поделиться: <a href="https://twitter.com/intent/tweet?url=http://graphonline.ru/&text=Визуализация графа и поиск кратчайшего пути" target="_blank">Twitter</a>, <a href="http://www.facebook.com/sharer.php?u=http://graphonline.ru/&text=Визуализация графа и поиск кратчайшего пути" target="_blank">Facebook</a>, <a href="http://vkontakte.ru/share.php?url=u=http://graphonline.ru/&text=Визуализация графа и поиск кратчайшего пути" target="_blank">В Контакте</a>.
|
||||
2016. (<a rel="nofollow" href='{$PageUrl}?action=edit'>$[Edit]</a> -
|
||||
<a rel="nofollow" href='{$PageUrl}?action=diff'>$[History]</a> -
|
||||
<a rel="nofollow" href='{$PageUrl}?action=print' target='_blank'>$[Print]</a> -
|
||||
<a href='{$ScriptUrl}/$[{$Group}/RecentChanges]'>$[Recent Changes]</a> -
|
||||
<a href='{$ScriptUrl}/$[{$SiteGroup}/Search]'>$[Search]</a>)
|
||||
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- Yandex.Metrika counter -->
|
||||
<script type="text/javascript">
|
||||
(function (d, w, c) {
|
||||
(w[c] = w[c] || []).push(function() {
|
||||
try {
|
||||
w.yaCounter25827098 = new Ya.Metrika({id:25827098,
|
||||
clickmap:true,
|
||||
accurateTrackBounce:true});
|
||||
} catch(e) { }
|
||||
});
|
||||
|
||||
var n = d.getElementsByTagName("script")[0],
|
||||
s = d.createElement("script"),
|
||||
f = function () { n.parentNode.insertBefore(s, n); };
|
||||
s.type = "text/javascript";
|
||||
s.async = true;
|
||||
s.src = (d.location.protocol == "https:" ? "https:" : "http:") + "//mc.yandex.ru/metrika/watch.js";
|
||||
|
||||
if (w.opera == "[object Opera]") {
|
||||
d.addEventListener("DOMContentLoaded", f, false);
|
||||
} else { f(); }
|
||||
})(document, window, "yandex_metrika_callbacks");
|
||||
</script>
|
||||
<noscript><div><img src="//mc.yandex.ru/watch/25827098" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
||||
<!-- /Yandex.Metrika counter -->
|
||||
|
||||
<script>
|
||||
if (typeof preLoadPage == 'function')
|
||||
{
|
||||
preLoadPage();
|
||||
}
|
||||
</script>
|
||||
<script src="/i/js/dev/bootstrap3/bootstrap.min.js" >
|
||||
$('.dropdown-toggle').dropdown();
|
||||
</script>
|
||||
<script>
|
||||
if (typeof postLoadPage == 'function')
|
||||
{
|
||||
postLoadPage();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
pre{
|
||||
border-color: transparent;
|
||||
background-color: transparent;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
This directory contains the files to display pages in PmWiki according
|
||||
to the default layout.
|
||||
|
||||
==>Don't edit these files directly, as you may lose your edits the
|
||||
next time you upgrade PmWiki!
|
||||
|
||||
Instead, copy the files to another directory in pub/skins/ and edit
|
||||
them there. You can then configure PmWiki to use your modified layout
|
||||
files by setting the $Skin variable in your local/config.php. For
|
||||
example, if you copy your custom skin to pub/skins/custom, then you
|
||||
would set
|
||||
$Skin = 'custom';
|
||||
in local/config.php.
|
||||
|
||||
The files in this directory:
|
||||
pmwiki.tmpl -- the default template for page layouts
|
||||
pmwiki.css -- PmWiki's default css
|
||||
pmwiki-32.gif -- the PmWiki logo
|
||||
|
||||
If you just want to change the logo, you can do it by setting $PageLogoUrl
|
||||
to the url location of your logo.
|
||||
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,102 @@
|
||||
/***********************************************************************
|
||||
** pmwiki.css
|
||||
** Copyright 2004-2006 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
** Copyright 2006 Hagan Fox
|
||||
** This file is part of PmWiki; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published
|
||||
** by the Free Software Foundation; either version 2 of the License, or
|
||||
** (at your option) any later version. See pmwiki.php for full details.
|
||||
***********************************************************************/
|
||||
|
||||
/* This sets the overall frame for the site */
|
||||
body {
|
||||
margin:0px; background-color:#f7f7f7;
|
||||
font-family:Arial,Helvetica,sans-serif; font-size:11pt;
|
||||
}
|
||||
|
||||
/* These control the fixed-width text elements of the page */
|
||||
textarea, pre, code { font-size:0.9em; }
|
||||
pre, code { font-family:'Lucida Console','Andale Mono','Courier New',Courier,monospace; }
|
||||
pre { line-height:1.2em; }
|
||||
pre code, code code, pre pre { font-size:100%; }
|
||||
|
||||
/* These primarily adjust the size and spacing of heading elements,
|
||||
** most browsers have atrocious defaults for these. */
|
||||
h1, h2, h3, h4, h5, h6 { margin-top:1.0em; margin-bottom:0.6em; }
|
||||
h1, h2, h3, h6 { font-weight:normal; }
|
||||
h4, h5 { font-weight:bold; }
|
||||
h1 code, h2 code, h3 code, h4 code { font-size:1em; }
|
||||
h1 { font-size:1.8em; }
|
||||
h2 { font-size:1.44em; }
|
||||
h3 { font-size:1.22em; }
|
||||
h4 { font-size:1.07em; }
|
||||
h5 { font-size:1.0em; }
|
||||
h6 { font-size:1.0em; }
|
||||
|
||||
/* The #wikilogo element is the logo from $PageLogoFmt */
|
||||
#wikilogo { margin-top:4px; padding:6px; border-bottom:1px #cccccc solid; }
|
||||
|
||||
/* This controls the rest of the heading (primarily the search box) */
|
||||
#wikihead {
|
||||
position:absolute; right:10px; top:10px;
|
||||
font-family:Verdana,sans-serif; font-size:85%;
|
||||
}
|
||||
#wikihead input { font-size:85%; }
|
||||
|
||||
/* These are for the left-sidebar. */
|
||||
#wikileft {
|
||||
width:155px;
|
||||
padding:6px; border-right:1px #cccccc solid;
|
||||
line-height:1.33em;
|
||||
font-size:9.4pt; font-family:Verdana,sans-serif;
|
||||
}
|
||||
#wikileft .vspace { margin-top:1.125em; }
|
||||
#wikileft a { text-decoration:none; color:black; }
|
||||
#wikileft a:hover { text-decoration:underline; color:blue; }
|
||||
#wikileft ul { list-style:none; padding:0px; margin:0px; }
|
||||
#wikileft li { margin:0px; padding-left: 6px; }
|
||||
.sidehead {
|
||||
margin:0px; padding:4px 2px 2px 2px;
|
||||
font-size:11pt; font-weight:bold; font-style:normal;
|
||||
}
|
||||
.sidehead a
|
||||
{ color:#505050; font-weight:bold; font-style:normal; }
|
||||
|
||||
/* These affect the main content area. */
|
||||
#wikibody {
|
||||
padding:0px 10px 10px 10px; background-color:white;
|
||||
font-size:11pt;
|
||||
}
|
||||
#wikicmds {
|
||||
float:right; white-space:nowrap;
|
||||
font-family:Verdana,sans-serif; font-size:80%;
|
||||
}
|
||||
#wikicmds ul { list-style:none; margin:0px; padding:0px; }
|
||||
#wikicmds li { display:inline; margin:0px 5px; }
|
||||
#wikicmds li a { text-decoration:none; color:black; border:none; }
|
||||
#wikicmds li a.createlink { display:none; }
|
||||
#wikicmds li a:hover { text-decoration:underline; color:blue; }
|
||||
.pagegroup { margin-top:8px; margin-bottom:2px; }
|
||||
.pagetitle { line-height:1em; margin:0px; font-size:1.6em; font-weight:normal; }
|
||||
.wikiaction { margin-top:4px; margin-bottom:4px; }
|
||||
#wikitext { margin-top:12px; line-height:1.33em; }
|
||||
#wikitext table { font-size:100%; line-height:1.33em; } /* For MSIE 5.5 */
|
||||
|
||||
/* These are for the edit form. */
|
||||
#wikiedit form { margin:0px; width:100%; }
|
||||
#wikiedit textarea { width:100%; }
|
||||
.wikimessage { margin-top:4px; margin-bottom:4px; font-style:italic; }
|
||||
|
||||
/* These affect the lines at the very bottom. */
|
||||
#wikifoot {
|
||||
padding-left:178px; padding-bottom:4px; border-top:1px #cccccc solid;
|
||||
font-family:Verdana,sans-serif; font-size:80%;
|
||||
}
|
||||
|
||||
/* These affect the printed appearance of the web view (not the separate
|
||||
** print view) of pages. The sidebar and action links aren't printed. */
|
||||
@media print {
|
||||
body { width:auto; margin:0px; padding:0.5em; }
|
||||
#wikihead, #wikileft, #wikicmds, .footnav { display:none; }
|
||||
#wikifoot { padding:2px; }
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>$WikiTitle | {$Group} / {$Title} $ActionTitle</title>
|
||||
<meta http-equiv='Content-Style-Type' content='text/css' />
|
||||
<link rel='stylesheet' href='$SkinDirUrl/pmwiki.css' type='text/css' />
|
||||
<!--HTMLHeader-->
|
||||
</head>
|
||||
<body>
|
||||
<!--PageHeaderFmt-->
|
||||
<div id='wikilogo'><a href='{$ScriptUrl}'><img src='$PageLogoUrl'
|
||||
alt='$WikiTitle' border='0' /></a></div>
|
||||
<div id='wikihead'>
|
||||
<form action='{$ScriptUrl}'>
|
||||
<span class='headnav'><a href='{$ScriptUrl}/$[{$Group}/RecentChanges]'
|
||||
accesskey='$[ak_recentchanges]'>$[Recent Changes]</a> -</span>
|
||||
<input type='hidden' name='n' value='{$FullName}' />
|
||||
<input type='hidden' name='action' value='search' />
|
||||
<a href='{$ScriptUrl}/$[{$SiteGroup}/Search]'>$[Search]</a>:
|
||||
<input type='text' name='q' value='' class='inputbox searchbox' />
|
||||
<input type='submit' class='inputbutton searchbutton'
|
||||
value='$[Go]' /></form></div>
|
||||
<!--/PageHeaderFmt-->
|
||||
<table id='wikimid' width='100%' cellspacing='0' cellpadding='0'><tr>
|
||||
<!--PageLeftFmt-->
|
||||
<td id='wikileft' valign='top'>
|
||||
<!--wiki:{$Group}.SideBar {$SiteGroup}.SideBar--></td>
|
||||
<!--/PageLeftFmt-->
|
||||
<td id='wikibody' valign='top'>
|
||||
<!--PageActionFmt-->
|
||||
<div id='wikicmds'><!--wiki:{$Group}.PageActions {$SiteGroup}.PageActions--></div>
|
||||
<!--PageTitleFmt-->
|
||||
<div id='wikititle'>
|
||||
<div class='pagegroup'><a href='{$ScriptUrl}/{$Group}'>{$Group}</a> /</div>
|
||||
<h1 class='pagetitle'>{$Title}</h1></div>
|
||||
<!--PageText-->
|
||||
</td>
|
||||
</tr></table>
|
||||
<!--PageFooterFmt-->
|
||||
<div id='wikifoot'>
|
||||
<div class='footnav'>
|
||||
<a rel="nofollow" href='{$PageUrl}?action=edit'>$[Edit]</a> -
|
||||
<a rel="nofollow" href='{$PageUrl}?action=diff'>$[History]</a> -
|
||||
<a rel="nofollow" href='{$PageUrl}?action=print' target='_blank'>$[Print]</a> -
|
||||
<a href='{$ScriptUrl}/$[{$Group}/RecentChanges]'>$[Recent Changes]</a> -
|
||||
<a href='{$ScriptUrl}/$[{$SiteGroup}/Search]'>$[Search]</a></div>
|
||||
<div class='lastmod'>$[Page last modified on {$LastModified}]</div></div>
|
||||
<!--HTMLFooter-->
|
||||
|
||||
<!-- Yandex.Metrika counter -->
|
||||
<script type="text/javascript">
|
||||
(function (d, w, c) {
|
||||
(w[c] = w[c] || []).push(function() {
|
||||
try {
|
||||
w.yaCounter25827098 = new Ya.Metrika({id:25827098,
|
||||
clickmap:true,
|
||||
accurateTrackBounce:true});
|
||||
} catch(e) { }
|
||||
});
|
||||
|
||||
var n = d.getElementsByTagName("script")[0],
|
||||
s = d.createElement("script"),
|
||||
f = function () { n.parentNode.insertBefore(s, n); };
|
||||
s.type = "text/javascript";
|
||||
s.async = true;
|
||||
s.src = (d.location.protocol == "https:" ? "https:" : "http:") + "//mc.yandex.ru/metrika/watch.js";
|
||||
|
||||
if (w.opera == "[object Opera]") {
|
||||
d.addEventListener("DOMContentLoaded", f, false);
|
||||
} else { f(); }
|
||||
})(document, window, "yandex_metrika_callbacks");
|
||||
</script>
|
||||
<noscript><div><img src="//mc.yandex.ru/watch/25827098" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
||||
<!-- /Yandex.Metrika counter -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,20 @@
|
||||
This directory contains the files to print pages in PmWiki for ?action=print.
|
||||
This is a template just like any other layout skin, except that for
|
||||
?action=print PmWiki looks for print.tmpl instead of screen.tmpl.
|
||||
|
||||
==>Don't edit these files directly, as you may lose your edits the
|
||||
next time you upgrade PmWiki!
|
||||
|
||||
Instead, copy the files to another directory in pub/skins/ and edit
|
||||
them there. You can then configure PmWiki to use your modified layout
|
||||
files by setting $ActionSkin['print'] to the name of your new skin.
|
||||
For example, if you copy your custom print skin to pub/skins/custom,
|
||||
then you would set
|
||||
$ActionSkin['print'] = 'custom';
|
||||
in local/config.php.
|
||||
|
||||
The files in this directory:
|
||||
print.tmpl -- the default template for ?action=print
|
||||
print.css -- the print template's css
|
||||
print.php -- loaded when the skin is loaded, it redefines the link
|
||||
formats to a form better suited for printing
|
||||
@@ -0,0 +1,50 @@
|
||||
/***********************************************************************
|
||||
** print.css
|
||||
** Copyright 2004 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
** This file is part of PmWiki; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published
|
||||
** by the Free Software Foundation; either version 2 of the License, or
|
||||
** (at your option) any later version. See pmwiki.php for full details.
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
** These settings are part of the ?action=print skin. If you want
|
||||
** to change these settings, create a new print template and set
|
||||
** $PrintTemplateFmt in the config.php file to point to your new
|
||||
** printing skin.
|
||||
***********************************************************************/
|
||||
|
||||
body {
|
||||
width:auto;
|
||||
background-color:white;
|
||||
color:black;
|
||||
font-family:serif;
|
||||
}
|
||||
|
||||
#printhead {
|
||||
font-family:sans-serif;
|
||||
border-top:3px solid #a0a0a0;
|
||||
border-bottom:5px solid #a0a0a0;
|
||||
margin-bottom:1em;
|
||||
}
|
||||
#printhead h3 { margin-top:0px; }
|
||||
#printhead h1 { margin-bottom:0px; }
|
||||
|
||||
#printtitle {
|
||||
}
|
||||
|
||||
#printfoot {
|
||||
clear:both;
|
||||
margin-top:1em;
|
||||
border-top:5px solid #a0a0a0;
|
||||
font-size:smaller;
|
||||
}
|
||||
|
||||
|
||||
a:link { color:#444444; font-weight:bold; text-decoration:none; }
|
||||
a:visited { color:#444444; font-weight:bold; text-decoration:none; }
|
||||
a.wikilink:hover { color: #444444; text-decoration:underline; }
|
||||
a.createlink { color:#444444; }
|
||||
a.createlink:visited { color:#444444; }
|
||||
a.createlink:hover { color:#ff2222; }
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script defines additional settings needed when the 'print'
|
||||
skin is loaded (usually in response to ?action=print, as controlled
|
||||
by the $ActionSkin['print'] setting. See scripts/skins.php for
|
||||
more details.
|
||||
|
||||
The changes made are:
|
||||
- Redefines the standard layout to a format suitable for printing
|
||||
- Redefines internal links to keep ?action=print
|
||||
- Changes the display of URL and mailto: links
|
||||
- Uses GroupPrintHeader and GroupPrintFooter pages instead
|
||||
of GroupHeader and GroupFooter
|
||||
*/
|
||||
|
||||
global $LinkPageExistsFmt, $GroupPrintHeaderFmt,
|
||||
$GroupPrintFooterFmt, $GroupHeaderFmt, $GroupFooterFmt;
|
||||
|
||||
$LinkPageExistsFmt = "<a class='wikilink' href='\$PageUrl?action=print'>\$LinkText</a>";
|
||||
SDV($GroupPrintHeaderFmt,'(:include $Group.GroupPrintHeader basepage={*$FullName}:)(:nl:)');
|
||||
SDV($GroupPrintFooterFmt,'(:nl:)(:include $Group.GroupPrintFooter basepage={*$FullName}:)');
|
||||
$GroupHeaderFmt = $GroupPrintHeaderFmt;
|
||||
$GroupFooterFmt = $GroupPrintFooterFmt;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head>
|
||||
<title>$WikiTitle | {$Group} / {$Title}</title>
|
||||
<link rel='stylesheet' href='$SkinDirUrl/print.css' type='text/css' />
|
||||
<!--HTMLHeader-->
|
||||
</head>
|
||||
<body>
|
||||
<div id='printhead'>
|
||||
<h3>$[From $WikiTitle]</h3>
|
||||
<h1 class='pagename'><a href='$ScriptUrl/{$Group}'>{$Group}: {$Title}</a></h1>
|
||||
</div>
|
||||
<!--PageText-->
|
||||
<div id='printfoot'>
|
||||
<div class='from'>$[Retrieved from {$PageUrl}]</div>
|
||||
<div class='lastmod'>$[Page last modified on {$LastModified}]</div></div>
|
||||
<!--HTMLFooter-->
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,12 @@
|
||||
# This file is script/.htaccess -- the default distribution contains this
|
||||
# file to prevent script/ files from being accessed directly by browsers
|
||||
# (this is a potential, albeit very unlikely, security hole).
|
||||
#
|
||||
# If you alter or replace this file, it will likely be overwritten when
|
||||
# you upgrade from one version of PmWiki to another. Be sure to save
|
||||
# a copy of your alterations in another location so you can restore them,
|
||||
# and you might try changing this file to be read-only to prevent a PmWiki
|
||||
# upgrade from overwriting your altered version.
|
||||
|
||||
Order Deny,Allow
|
||||
Deny from all
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2013 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script handles author tracking.
|
||||
*/
|
||||
|
||||
SDV($AuthorNameChars, "- '\\w\\x80-\\xff");
|
||||
SDV($AuthorCookie, $CookiePrefix.'author');
|
||||
SDV($AuthorCookieExpires,$Now+60*60*24*30);
|
||||
SDV($AuthorCookieDir,'/');
|
||||
SDV($AuthorGroup,'Profiles');
|
||||
SDV($AuthorRequiredFmt,
|
||||
"<h3 class='wikimessage'>$[An author name is required.]</h3>");
|
||||
Markup('[[~','<links','/\\[\\[~(.*?)\\]\\]/',"[[$AuthorGroup/$1]]");
|
||||
|
||||
$LogoutCookies[] = $AuthorCookie;
|
||||
|
||||
if (!isset($Author)) {
|
||||
if (isset($_POST['author'])) {
|
||||
$x = stripmagic($_POST['author']);
|
||||
setcookie($AuthorCookie, $x, $AuthorCookieExpires, $AuthorCookieDir);
|
||||
} elseif (@$_COOKIE[$AuthorCookie]) {
|
||||
$x = stripmagic(@$_COOKIE[$AuthorCookie]);
|
||||
} else $x = @$AuthId;
|
||||
$Author = PHSC(preg_replace("/[^$AuthorNameChars]/", '', $x),
|
||||
ENT_COMPAT);
|
||||
}
|
||||
if (!isset($AuthorPage)) $AuthorPage =
|
||||
FmtPageName('$AuthorGroup/$Name', MakePageName("$AuthorGroup.$AuthorGroup", $Author));
|
||||
SDV($AuthorLink,($Author) ? "[[~$Author]]" : '?');
|
||||
|
||||
if (IsEnabled($EnableAuthorSignature,1)) {
|
||||
SDVA($ROSPatterns, array(
|
||||
'/(?<!~)~~~~(?!~)/' => "[[~$Author]] $CurrentTime",
|
||||
'/(?<!~)~~~(?!~)/' => "[[~$Author]]",
|
||||
));
|
||||
Markup('~~~~','<[[~','/(?<!~)~~~~(?!~)/',"[[~$Author]] $CurrentTime");
|
||||
Markup('~~~','>~~~~','/(?<!~)~~~(?!~)/',"[[~$Author]]");
|
||||
}
|
||||
if (IsEnabled($EnablePostAuthorRequired,0))
|
||||
array_unshift($EditFunctions,'RequireAuthor');
|
||||
|
||||
## RequireAuthor forces an author to enter a name before posting.
|
||||
function RequireAuthor($pagename, &$page, &$new) {
|
||||
global $Author, $MessagesFmt, $AuthorRequiredFmt, $EnablePost;
|
||||
if (!$Author) {
|
||||
$MessagesFmt[] = $AuthorRequiredFmt;
|
||||
$EnablePost = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2005-2015 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
The APR compatible MD5 encryption algorithm in _crypt() below is
|
||||
based on code Copyright 2005 by D. Faure and the File::Passwd
|
||||
PEAR library module by Mike Wallner <mike@php.net>.
|
||||
|
||||
This script enables simple authentication based on username and
|
||||
password combinations. At present this script can authenticate
|
||||
from passwords held in arrays or in .htpasswd-formatted files,
|
||||
but eventually it will support authentication via sources such
|
||||
as LDAP and Active Directory.
|
||||
|
||||
To configure a .htpasswd-formatted file for authentication, do
|
||||
$AuthUser['htpasswd'] = '/path/to/.htpasswd';
|
||||
prior to including this script.
|
||||
|
||||
Individual username/password combinations can also be placed
|
||||
directly in the $AuthUser array, such as:
|
||||
$AuthUser['pmichaud'] = pmcrypt('secret');
|
||||
|
||||
To authenticate against an LDAP server, put the url for
|
||||
the server in $AuthUser['ldap'], as in:
|
||||
$AuthUser['ldap'] = 'ldap://ldap.example.com/ou=People,o=example?uid';
|
||||
*/
|
||||
|
||||
# let Site.AuthForm know that we're doing user-based authorization
|
||||
$EnableAuthUser = 1;
|
||||
|
||||
if (@$_POST['authid'])
|
||||
AuthUserId($pagename, stripmagic(@$_POST['authid']),
|
||||
stripmagic(@$_POST['authpw']));
|
||||
else SessionAuth($pagename);
|
||||
|
||||
function AuthUserId($pagename, $id, $pw=NULL) {
|
||||
global $AuthUser, $AuthUserPageFmt, $AuthUserFunctions,
|
||||
$AuthId, $MessagesFmt, $AuthUserPat;
|
||||
|
||||
$auth = array();
|
||||
foreach((array)$AuthUser as $k=>$v) $auth[$k] = (array)$v;
|
||||
$authid = '';
|
||||
|
||||
# load information from SiteAdmin.AuthUser (or page in $AuthUserPageFmt)
|
||||
SDV($AuthUserPageFmt, '$SiteAdminGroup.AuthUser');
|
||||
SDVA($AuthUserFunctions, array(
|
||||
'htpasswd' => 'AuthUserHtPasswd',
|
||||
'ldap' => 'AuthUserLDAP',
|
||||
# 'mysql' => 'AuthUserMySQL',
|
||||
$id => 'AuthUserConfig'));
|
||||
|
||||
SDV($AuthUserPat, "/^\\s*([@\\w][^\\s:]*):(.*)/m");
|
||||
$pn = FmtPageName($AuthUserPageFmt, $pagename);
|
||||
$apage = ReadPage($pn, READPAGE_CURRENT);
|
||||
if ($apage && preg_match_all($AuthUserPat,
|
||||
$apage['text'], $matches, PREG_SET_ORDER)) {
|
||||
foreach($matches as $m) {
|
||||
if (!preg_match_all('/\\bldaps?:\\S+|[^\\s,]+/', $m[2], $v))
|
||||
continue;
|
||||
if ($m[1]{0} == '@')
|
||||
foreach($v[0] as $g) $auth[$g][] = $m[1];
|
||||
else $auth[$m[1]] = array_merge((array)@$auth[$m[1]], $v[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (func_num_args()==2) $authid = $id;
|
||||
else
|
||||
foreach($AuthUserFunctions as $k => $fn)
|
||||
if (@$auth[$k] && $fn($pagename, $id, $pw, $auth[$k], $authlist))
|
||||
{ $authid = $id; break; }
|
||||
|
||||
if (!$authid) { $GLOBALS['InvalidLogin'] = 1; return; }
|
||||
if (!isset($AuthId)) $AuthId = $authid;
|
||||
$authlist["id:$authid"] = 1;
|
||||
$authlist["id:-$authid"] = -1;
|
||||
foreach(preg_grep('/^@/', (array)@$auth[$authid]) as $g)
|
||||
$authlist[$g] = 1;
|
||||
foreach(preg_grep('/^@/', (array)@$auth['*']) as $g)
|
||||
$authlist[$g] = 1;
|
||||
foreach(preg_grep('/^@/', array_keys($auth)) as $g) # useless? PITS:01201
|
||||
if (in_array($authid, $auth[$g])) $authlist[$g] = 1;
|
||||
if ($auth['htgroup']) {
|
||||
foreach(AuthUserHtGroup($pagename, $id, $pw, $auth['htgroup']) as $g)
|
||||
$authlist["@$g"] = 1;
|
||||
}
|
||||
foreach(preg_grep('/^@/', (array)@$auth["-$authid"]) as $g)
|
||||
unset($authlist[$g]);
|
||||
SessionAuth($pagename, array('authid' => $authid, 'authlist' => $authlist));
|
||||
}
|
||||
|
||||
|
||||
function AuthUserConfig($pagename, $id, $pw, $pwlist) {
|
||||
foreach ((array)$pwlist as $chal)
|
||||
if (_crypt($pw, $chal) == $chal) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function AuthUserHtPasswd($pagename, $id, $pw, $pwlist) {
|
||||
foreach ((array)$pwlist as $f) {
|
||||
$fp = fopen($f, "r"); if (!$fp) continue;
|
||||
while ($x = fgets($fp, 1024)) {
|
||||
$x = rtrim($x);
|
||||
@list($i, $c, $r) = explode(':', $x, 3);
|
||||
if ($i == $id && _crypt($pw, $c) == $c) { fclose($fp); return true; }
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function AuthUserHtGroup($pagename, $id, $pw, $pwlist) {
|
||||
$groups = array();
|
||||
foreach ((array)$pwlist as $f) {
|
||||
$fp = fopen($f, 'r'); if (!$fp) continue;
|
||||
while ($x = fgets($fp, 4096)) {
|
||||
if (preg_match('/^(\\w[^\\s:]+)\\s*:(.*)$/', trim($x), $match)) {
|
||||
$glist = preg_split('/[\\s,]+/', $match[2], -1, PREG_SPLIT_NO_EMPTY);
|
||||
if (in_array($id, $glist)) $groups[$match[1]] = 1;
|
||||
}
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
return array_keys($groups);
|
||||
}
|
||||
|
||||
|
||||
function AuthUserLDAP($pagename, $id, $pw, $pwlist) {
|
||||
global $AuthLDAPBindDN, $AuthLDAPBindPassword;
|
||||
if (!$pw) return false;
|
||||
if (!function_exists('ldap_connect'))
|
||||
Abort('authuser: LDAP authentication requires PHP ldap functions','ldapfn');
|
||||
foreach ((array)$pwlist as $ldap) {
|
||||
if (!preg_match('!(ldaps?://[^/]+)/(.*)$!', $ldap, $match))
|
||||
continue;
|
||||
## connect to the LDAP server
|
||||
list($z, $url, $path) = $match;
|
||||
$ds = ldap_connect($url);
|
||||
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
## For Active Directory, don't specify a path and we simply
|
||||
## attempt to bind with the username and password directly
|
||||
if (!$path && @ldap_bind($ds, $id, $pw)) { ldap_close($ds); return true; }
|
||||
## Otherwise, we use Apache-style urls for LDAP authentication
|
||||
## Split the path into its search components
|
||||
list($basedn, $attr, $sub, $filter) = explode('?', $path);
|
||||
if (!$attr) $attr = 'uid';
|
||||
if (!$sub) $sub = 'one';
|
||||
if (!$filter) $filter = '(objectClass=*)';
|
||||
$binddn = @$AuthLDAPBindDN;
|
||||
$bindpw = @$AuthLDAPBindPassword;
|
||||
if (ldap_bind($ds, $binddn, $bindpw)) {
|
||||
## Search for the appropriate uid
|
||||
$fn = ($sub == 'sub') ? 'ldap_search' : 'ldap_list';
|
||||
$sr = $fn($ds, $basedn, "(&$filter($attr=$id))", array($attr));
|
||||
$x = ldap_get_entries($ds, $sr);
|
||||
## If we find a unique id, bind to it for success
|
||||
if ($x['count'] == 1) {
|
||||
$dn = $x[0]['dn'];
|
||||
if (@ldap_bind($ds, $dn, $pw)) { ldap_close($ds); return true; }
|
||||
}
|
||||
}
|
||||
ldap_close($ds);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
# The _crypt function provides support for SHA1 encrypted passwords
|
||||
# (keyed by '{SHA}') and Apache MD5 encrypted passwords (keyed by
|
||||
# '$apr1$'); otherwise it just calls PHP's crypt() for the rest.
|
||||
# The APR MD5 encryption code was contributed by D. Faure.
|
||||
|
||||
function _crypt($plain, $salt=null) {
|
||||
if (strncmp($salt, '{SHA}', 5) == 0)
|
||||
return '{SHA}'.base64_encode(pack('H*', sha1($plain)));
|
||||
if (strncmp($salt, '$apr1$', 6) == 0) {
|
||||
preg_match('/^\\$apr1\\$([^$]+)/', $salt, $match);
|
||||
$salt = $match[1];
|
||||
$length = strlen($plain);
|
||||
$context = $plain . '$apr1$' . $salt;
|
||||
$binary = pack('H32', md5($plain . $salt . $plain));
|
||||
for($i = $length; $i > 0; $i -= 16)
|
||||
$context .= substr($binary, 0, min(16, $i));
|
||||
for($i = $length; $i > 0; $i >>= 1)
|
||||
$context .= ($i & 1) ? chr(0) : $plain{0};
|
||||
$binary = pack('H32', md5($context));
|
||||
for($i = 0; $i < 1000; $i++) {
|
||||
$new = ($i & 1) ? $plain : $binary;
|
||||
if ($i % 3) $new .= $salt;
|
||||
if ($i % 7) $new .= $plain;
|
||||
$new .= ($i & 1) ? $binary : $plain;
|
||||
$binary = pack('H32', md5($new));
|
||||
}
|
||||
$q = '';
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$k = $i + 6;
|
||||
$j = $i + 12;
|
||||
if ($j == 16) $j = 5;
|
||||
$q = $binary{$i}.$binary{$k}.$binary{$j} . $q;
|
||||
}
|
||||
$q = chr(0).chr(0).$binary{11} . $q;
|
||||
$q = strtr(strrev(substr(base64_encode($q), 2)),
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
|
||||
'./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
|
||||
return "\$apr1\$$salt\$$q";
|
||||
}
|
||||
if (md5($plain) == $salt) return $salt;
|
||||
return pmcrypt($plain, $salt);
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2006-2013 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script adds blocklisting capabilities to PmWiki, and can
|
||||
be enabled by simply setting the following in local/config.php:
|
||||
|
||||
$EnableBlocklist = 1;
|
||||
|
||||
With $EnableBlocklist set to 1, this module will search through
|
||||
the SiteAdmin.Blocklist page, as well as any other pages given by
|
||||
the $Blocklist pages variable, looking for lines of the
|
||||
form "block:some phrase" or "block:/regex/", with "some phrase"
|
||||
and "/regex/" indicating things to be excluded from any
|
||||
posting to the site.
|
||||
|
||||
In addition, if a page contains IP addresses of the form
|
||||
"a.b.c.d" or "a.b.c.*", then any posts coming from hosts
|
||||
matching the address will be blocked.
|
||||
|
||||
There is also an "unblock:..." form, which removes an entry
|
||||
from the blocklist. This is useful for removing specific
|
||||
block items in wikifarms and with automatically downloaded
|
||||
blocklists (below).
|
||||
|
||||
The script also has the capability of automatically downloading
|
||||
blocklists from other sources, such as chongqed.org and
|
||||
and the MoinMaster blocklist. These are configured using
|
||||
the $BlocklistDownload array. An $EnableBlocklist value
|
||||
of at least 10 configures PmWiki to automatically download
|
||||
these external blocklists and refresh them daily.
|
||||
|
||||
More information about blocklists is available in the
|
||||
PmWiki.Blocklist page.
|
||||
*/
|
||||
|
||||
|
||||
## Some recipes do page updates outside of the built-in posting
|
||||
## cycle, so $EnableBlocklistImmediate is used to determine if
|
||||
## we need to catch these. Currently this defaults to enabled,
|
||||
## but at some point we may change the default to disabled.
|
||||
if (IsEnabled($EnableBlocklistImmediate, 1)) {
|
||||
SDVA($BlocklistActions, array('comment' => 1));
|
||||
$ptext = implode(' ', @$_POST);
|
||||
if ($ptext && @$BlocklistActions[$action]) {
|
||||
Blocklist($pagename, $ptext);
|
||||
if (!$EnablePost) {
|
||||
unset($_POST['post']);
|
||||
unset($_POST['postattr']);
|
||||
unset($_POST['postedit']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
## If $EnableBlocklist is set to 10 or higher, then arrange to
|
||||
## periodically download the "chongqed" and "moinmaster" blacklists.
|
||||
if ($EnableBlocklist >= 10) {
|
||||
# SDVA($BlocklistDownload['SiteAdmin.Blocklist-Chongqed'], array(
|
||||
# 'url' => 'http://blacklist.chongqed.org/',
|
||||
# 'format' => 'regex'));
|
||||
SDVA($BlocklistDownload['SiteAdmin.Blocklist-MoinMaster'], array(
|
||||
'url' => 'http://moinmo.in/BadContent?action=raw',
|
||||
'format' => 'regex'));
|
||||
}
|
||||
|
||||
|
||||
## CheckBlocklist is inserted into $EditFunctions, to automatically
|
||||
## check for blocks on anything being posted through the normal
|
||||
## "update a page cycle"
|
||||
array_unshift($EditFunctions, 'CheckBlocklist');
|
||||
function CheckBlocklist($pagename, &$page, &$new) {
|
||||
StopWatch("CheckBlocklist: begin $pagename");
|
||||
$ptext = implode(' ', @$_POST);
|
||||
if (@$ptext) Blocklist($pagename, $ptext);
|
||||
StopWatch("CheckBlocklist: end $pagename");
|
||||
}
|
||||
|
||||
|
||||
## Blocklist is the function that does all of the work of
|
||||
## checking for reasons to block a posting. It reads
|
||||
## the available blocklist pages ($BlocklistPages) and
|
||||
## builds an array of strings and regular expressiongs to
|
||||
## be checked against the page; if any are found, then
|
||||
## posting is blocked (via $EnablePost=0). The function
|
||||
## also checks the REMOTE_ADDR against any blocked IP addresses.
|
||||
function Blocklist($pagename, $text) {
|
||||
global $BlocklistPages, $BlockedMessagesFmt, $BlocklistDownload,
|
||||
$BlocklistDownloadRefresh, $Now, $EnablePost, $WhyBlockedFmt,
|
||||
$MessagesFmt, $BlocklistMessageFmt, $EnableWhyBlocked, $IsBlocked;
|
||||
|
||||
StopWatch("Blocklist: begin $pagename");
|
||||
|
||||
$BlocklistDownload = (array)@$BlocklistDownload;
|
||||
SDV($BlocklistPages,
|
||||
array_merge(array('$SiteAdminGroup.Blocklist',
|
||||
'$SiteAdminGroup.Blocklist-Farm'),
|
||||
array_keys($BlocklistDownload)));
|
||||
SDV($BlocklistMessageFmt, "<h3 class='wikimessage'>$[This post has been blocked by the administrator]</h3>");
|
||||
SDVA($BlockedMessagesFmt, array(
|
||||
'ip' => '$[Address blocked from posting]: ',
|
||||
'text' => '$[Text blocked from posting]: '));
|
||||
SDV($BlocklistDownloadRefresh, 86400);
|
||||
|
||||
## Loop over all blocklist pages
|
||||
foreach((array)$BlocklistPages as $b) {
|
||||
|
||||
## load the current blocklist page
|
||||
$pn = FmtPageName($b, $pagename);
|
||||
$page = ReadPage($pn, READPAGE_CURRENT);
|
||||
if (!$page) continue;
|
||||
|
||||
## if the page being checked is a blocklist page, stop blocking
|
||||
if ($pagename == $pn) return;
|
||||
|
||||
## If the blocklist page is managed by automatic download,
|
||||
## schedule any new downloads here
|
||||
if (@$BlocklistDownload[$pn]) {
|
||||
$bd = &$BlocklistDownload[$pn];
|
||||
SDVA($bd, array(
|
||||
'refresh' => $BlocklistDownloadRefresh,
|
||||
'url' => "http://www.pmwiki.org/blocklists/$pn" ));
|
||||
if (!@$page['text'] || $page['time'] < $Now - $bd['refresh'])
|
||||
register_shutdown_function('BlocklistDownload', $pn, getcwd());
|
||||
}
|
||||
|
||||
## If the blocklist is simply a list of regexes to be matched, load
|
||||
## them into $terms['block'] and continue to the next blocklist page.
|
||||
## Some regexes from remote sites aren't well-formed, so we have
|
||||
## to escape any slashes that aren't already escaped.
|
||||
if (strpos(@$page['text'], 'blocklist-format: regex') !==false) {
|
||||
if (preg_match_all('/^([^\\s#].+)/m', $page['text'], $match))
|
||||
foreach($match[0] as $m) {
|
||||
$m = preg_replace('#(?<!\\\\)/#', '\\/', trim($m));
|
||||
$terms['block'][] = "/$m/";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
## Treat the page as a pmwiki-format blocklist page, with
|
||||
## IP addresses and "block:"-style declarations. First, see
|
||||
## if we need to block the author based on a.b.c.d or a.b.c.*
|
||||
## IP addresses.
|
||||
$ip = preg_quote($_SERVER['REMOTE_ADDR']);
|
||||
$ip = preg_replace('/\\d+$/', '($0\\b|\\*)', $ip);
|
||||
if (preg_match("/\\b$ip/", @$page['text'], $match)) {
|
||||
$EnablePost = 0;
|
||||
$IsBlocked = 1;
|
||||
$WhyBlockedFmt[] = $BlockedMessagesFmt['ip'] . $match[0];
|
||||
}
|
||||
|
||||
## Now we'll load any "block:" or "unblock:" specifications
|
||||
## from the page text.
|
||||
if (preg_match_all('/(un)?(?:block|regex):(.*)/', @$page['text'],
|
||||
$match, PREG_SET_ORDER))
|
||||
foreach($match as $m) $terms[$m[1].'block'][] = trim($m[2]);
|
||||
}
|
||||
|
||||
## okay, we've loaded all of the terms, now subtract any 'unblock'
|
||||
## terms from the block set.
|
||||
StopWatch("Blocklist: diff unblock");
|
||||
$blockterms = array_diff((array)@$terms['block'], (array)@$terms['unblock']);
|
||||
|
||||
## go through each of the remaining blockterms and see if it matches the
|
||||
## text -- if so, disable posting and add a message to $WhyBlockedFmt.
|
||||
StopWatch('Blocklist: blockterms (count='.count($blockterms).')');
|
||||
$itext = strtolower($text);
|
||||
foreach($blockterms as $b) {
|
||||
if ($b{0} == '/') {
|
||||
if (!preg_match($b, $text)) continue;
|
||||
} else if (strpos($itext, strtolower($b)) === false) continue;
|
||||
$EnablePost = 0;
|
||||
$IsBlocked = 1;
|
||||
$WhyBlockedFmt[] = $BlockedMessagesFmt['text'] . $b;
|
||||
}
|
||||
StopWatch('Blocklist: blockterms done');
|
||||
|
||||
## If we came across any reasons to block, let's provide a message
|
||||
## to the author that it was blocked. If $EnableWhyBlocked is set,
|
||||
## we'll even tell the author why. :-)
|
||||
if (@$WhyBlockedFmt) {
|
||||
$MessagesFmt[] = $BlocklistMessageFmt;
|
||||
if (IsEnabled($EnableWhyBlocked, 0))
|
||||
foreach((array)$WhyBlockedFmt as $why)
|
||||
$MessagesFmt[] = "<pre class='blocklistmessage'>$why</pre>\n";
|
||||
}
|
||||
StopWatch("Blocklist: end $pagename");
|
||||
}
|
||||
|
||||
|
||||
## BlocklistDownload() handles retrieving blocklists from
|
||||
## external sources into PmWiki pages. If it's able to
|
||||
## download an updated list, it uses that; otherwise it leaves
|
||||
## any existing list alone.
|
||||
function BlocklistDownload($pagename, $dir = '') {
|
||||
global $BlocklistDownloadFmt, $BlocklistDownload, $FmtV;
|
||||
|
||||
if ($dir) { flush(); chdir($dir); }
|
||||
SDV($BlocklistDownloadFmt, "
|
||||
[@
|
||||
## blocklist-note: NOTE: This page is automatically generated by blocklist.php
|
||||
## blocklist-note: NOTE: Any edits to this page may be lost!
|
||||
## blocklist-url: \$BlocklistDownloadUrl
|
||||
## blocklist-when: \$CurrentTimeISO
|
||||
# blocklist-format: \$BlocklistFormat
|
||||
\$BlocklistData
|
||||
@]
|
||||
");
|
||||
|
||||
## get the existing blocklist page
|
||||
$bd = &$BlocklistDownload[$pagename];
|
||||
$page = ReadPage($pagename, READPAGE_CURRENT);
|
||||
|
||||
## try to retrieve the remote data
|
||||
$blocklistdata = @file($bd['url']);
|
||||
|
||||
## if we didn't get it, and we don't already have text, save a
|
||||
## note in the page so we know what happened
|
||||
if (!$blocklistdata && !@$page['text']) {
|
||||
$auf = ini_get('allow_url_fopen');
|
||||
$blocklistdata = "#### Unable to download blocklist (allow_url_fopen=$auf)";
|
||||
}
|
||||
|
||||
## if we have some new text to save, let's format it and save it
|
||||
if ($blocklistdata) {
|
||||
$blocklistdata = implode('', (array)$blocklistdata);
|
||||
$blocklistdata = preg_replace('/^##blocklist.*/m', '', $blocklistdata);
|
||||
$FmtV['$BlocklistData'] = $blocklistdata;
|
||||
$FmtV['$BlocklistDownloadUrl'] = $bd['url'];
|
||||
$FmtV['$BlocklistFormat'] = $bd['format'];
|
||||
$page['text'] = FmtPageName($BlocklistDownloadFmt, $pagename);
|
||||
SDV($page['passwdread'], '@lock');
|
||||
}
|
||||
|
||||
## save our updated(?) blocklist page
|
||||
WritePage($pagename, $page);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2006-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
*/
|
||||
|
||||
## Browser cache-control. If this is a cacheable action (e.g., browse,
|
||||
## diff), then set the Last-Modified header to the time the site was
|
||||
## last modified. If the browser has provided us with a matching
|
||||
## If-Modified-Since request header, we can return 304 Not Modified.
|
||||
SDV($LastModFile,"$WorkDir/.lastmod");
|
||||
if (!$LastModFile) return;
|
||||
|
||||
$LastModTime = @filemtime($LastModFile);
|
||||
foreach(get_included_files() as $f)
|
||||
{ $v = @filemtime($f); if ($v > $LastModTime) $LastModTime = $v; }
|
||||
|
||||
if (@$EnableIMSCaching) {
|
||||
SDV($IMSCookie, $CookiePrefix.'imstime');
|
||||
SDV($IMSCookieExpires, $Now + 60*60*24*30);
|
||||
SDV($IMSInvalidators, array('authpw', 'author'));
|
||||
$LogoutCookies[] = $IMSCookie;
|
||||
|
||||
if ($IMSCookie) {
|
||||
$IMSTime = @$_COOKIE[$IMSCookie];
|
||||
if ($IMSTime < $LastModTime
|
||||
|| array_intersect($IMSInvalidators, array_keys($_POST))) {
|
||||
$IMSTime = $Now;
|
||||
setcookie($IMSCookie, $IMSTime, $IMSCookieExpires, '/');
|
||||
}
|
||||
} else $IMSTime = $LastModTime;
|
||||
|
||||
if (in_array($action, (array)$CacheActions)) {
|
||||
$HTTPLastMod = gmdate('D, d M Y H:i:s \G\M\T',$IMSTime);
|
||||
$HTTPHeaders[] = "Cache-Control: no-cache";
|
||||
$HTTPHeaders[] = "Last-Modified: $HTTPLastMod";
|
||||
if (@$_SERVER['HTTP_IF_MODIFIED_SINCE']==$HTTPLastMod) {
|
||||
header("HTTP/1.0 304 Not Modified");
|
||||
header("Cache-Control: no-cache");
|
||||
header("Expires: ");
|
||||
header("Last-Modified: $HTTPLastMod");
|
||||
exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($NoHTMLCache
|
||||
|| !@$PageCacheDir
|
||||
|| count($_POST) > 0
|
||||
|| count($_GET) > 1
|
||||
|| (count($_GET) == 1 && !@$_GET['n'])) { $NoHTMLCache |= 1; return; }
|
||||
|
||||
mkdirp($PageCacheDir);
|
||||
if (!file_exists("$PageCacheDir/.htaccess")
|
||||
&& $fp = @fopen("$PageCacheDir/.htaccess", "w"))
|
||||
{ fwrite($fp, "Order Deny,Allow\nDeny from all\n"); fclose($fp); }
|
||||
$PageCacheFile = "$PageCacheDir/$pagename,cache";
|
||||
if (file_exists($PageCacheFile) && @filemtime($PageCacheFile) < $LastModTime)
|
||||
@unlink($PageCacheFile);
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2007-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script adds Creole v0.4 markup (http://www.wikicreole.org/)
|
||||
to PmWiki. To activate this script, simply add the following into
|
||||
a local customization file:
|
||||
|
||||
include_once('scripts/creole.php');
|
||||
|
||||
*/
|
||||
|
||||
## **strong**
|
||||
Markup('**', 'inline',
|
||||
'/^\\*\\*(?>(.+?)\\*\\*)(?!\\S)|(?<!^)\\*\\*(.+?)\\*\\*/',
|
||||
'<strong>$1$2</strong>');
|
||||
|
||||
## //emphasized//
|
||||
Markup('//', 'inline',
|
||||
'/(?<!http:|https:|ftp:)\\/\\/(.*?)\\/\\//',
|
||||
'<em>$1</em>');
|
||||
|
||||
## == Headings ==
|
||||
Markup_e('^=', 'block',
|
||||
'/^(={1,6})\\s?(.*?)(\\s*=*\\s*)$/',
|
||||
"'<:block,1><h'.strlen(\$m[1]).'>'.\$m[2].'</h'.strlen(\$m[1]).'>'");
|
||||
|
||||
## Line breaks
|
||||
Markup('\\\\', 'inline', '/\\\\\\\\/', '<br />');
|
||||
|
||||
## Preformatted
|
||||
Markup_e('^{{{', '[=',
|
||||
"/^\\{\\{\\{\n(.*?\n)\\}\\}\\}[^\\S\n]*\n/sm",
|
||||
"Keep('<pre class=\"escaped\">'.\$m[1].'</pre>')");
|
||||
Markup_e('{{{', '>{{{',
|
||||
'/\\{\\{\\{(.*?)\\}\\}\\}/s',
|
||||
"Keep('<code class=\"escaped\">'.\$m[1].'</code>')");
|
||||
|
||||
## Tables
|
||||
Markup_e('|-table', '>^||',
|
||||
'/^\\|(.*)$/',
|
||||
"FormatTableRow(\$m[0], '\\|')");
|
||||
|
||||
## Images
|
||||
Markup_e('{{', 'inline',
|
||||
'/\\{\\{(?>(\\L))([^|\\]]*)(?:\\|\\s*(.*?)\\s*)?\\}\\}/',
|
||||
"Keep(\$GLOBALS['LinkFunctions'][\$m[1]](\$pagename, \$m[1], \$m[2], \$m[3],
|
||||
\$m[1].\$m[2], \$GLOBALS['ImgTagFmt']),'L')");
|
||||
|
||||
|
||||
## GUIButtons
|
||||
SDVA($GUIButtons, array(
|
||||
'em' => array(100, "//", "//", '$[Emphasized]',
|
||||
'$GUIButtonDirUrlFmt/em.gif"$[Emphasized (italic)]"',
|
||||
'$[ak_em]'),
|
||||
'strong' => array(110, "**", "**", '$[Strong]',
|
||||
'$GUIButtonDirUrlFmt/strong.gif"$[Strong (bold)]"',
|
||||
'$[ak_strong]'),
|
||||
'h2' => array(400, '\\n== ', ' ==\\n', '$[Heading]',
|
||||
'$GUIButtonDirUrlFmt/h.gif"$[Heading]"'),
|
||||
|
||||
));
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2002-2015 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script defines ?action=crypt, providing help for WikiAdministrators
|
||||
to set up site-wide passwords in the installation.
|
||||
*/
|
||||
|
||||
SDV($HandleActions['crypt'],'HandleCrypt');
|
||||
SDV($ActionTitleFmt['crypt'],'| $[Password encryption]');
|
||||
|
||||
function HandleCrypt($pagename, $auth='read') {
|
||||
global $ScriptUrl,$HTMLStartFmt,$HTMLEndFmt;
|
||||
PrintFmt($pagename,$HTMLStartFmt);
|
||||
$passwd = stripmagic(@$_POST["passwd"]);
|
||||
echo FmtPageName(
|
||||
"<form action='{\$ScriptUrl}' method='POST'><p>
|
||||
Enter password to encrypt:
|
||||
<input type='text' name='passwd' value='"
|
||||
. PHSC($passwd, ENT_QUOTES) ."' />
|
||||
<input type='submit' />
|
||||
<input type='hidden' name='n' value='{\$FullName}' />
|
||||
<input type='hidden' name='action' value='crypt' /></p></form>",
|
||||
$pagename);
|
||||
if ($passwd) {
|
||||
$crypt = pmcrypt($passwd);
|
||||
echo "<p class='vspace'>Encrypted password = $crypt</p>";
|
||||
echo "<p class='vspace'>To set a site-wide password, insert the line below
|
||||
in your <i>config.php</i> file, <br />replacing <tt>'type'</tt> with
|
||||
one of <tt>'admin'</tt>, <tt>'read'</tt>, <tt>'edit'</tt>,
|
||||
or <tt>'attr'</tt>. <br />See <a
|
||||
href='$ScriptUrl?n=PmWiki.PasswordsAdmin'>PasswordsAdmin</a> for more
|
||||
details.</p>
|
||||
<pre class='vspace'> \$DefaultPasswords['type']='$crypt';</pre>";
|
||||
}
|
||||
PrintFmt($pagename,$HTMLEndFmt);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2003-2005, 2007 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file adds "?action=diag" and "?action=phpinfo" actions to PmWiki.
|
||||
This produces lots of diagnostic output that may be helpful to the
|
||||
software authors when debugging PmWiki or other scripts.
|
||||
*/
|
||||
|
||||
@ini_set('display_errors', '1');
|
||||
@ini_set('track_errors','1');
|
||||
|
||||
if ($action=='diag') {
|
||||
@session_start();
|
||||
header('Content-type: text/plain');
|
||||
print_r($GLOBALS);
|
||||
exit();
|
||||
}
|
||||
|
||||
if ($action=='phpinfo') { phpinfo(); exit(); }
|
||||
|
||||
function Ruleset() {
|
||||
global $MarkupTable;
|
||||
$out = '';
|
||||
$dbg = 0;
|
||||
BuildMarkupRules();
|
||||
foreach($MarkupTable as $id=>$m) {
|
||||
$out .= sprintf("%-16s %-16s %-16s %s\n",$id,@$m['cmd'],@$m['seq'], @$m['dbg']);
|
||||
if(@$m['dbg']) $dbg++;
|
||||
}
|
||||
if($dbg) $out .= "
|
||||
[!] Markup rules possibly incompatible with PHP 5.5 or newer.
|
||||
Please contact the recipe maintainer for update
|
||||
or see www.pmwiki.org/wiki/PmWiki/CustomMarkup";
|
||||
return $out;
|
||||
}
|
||||
|
||||
$HandleActions['ruleset'] = 'HandleRuleset';
|
||||
|
||||
function HandleRuleset($pagename) {
|
||||
header("Content-type: text/plain");
|
||||
print Ruleset();
|
||||
}
|
||||
|
||||
function StopWatchHTML($pagename, $print = 0) {
|
||||
global $StopWatch;
|
||||
StopWatch('now');
|
||||
$l = strlen(count($StopWatch));
|
||||
$out = '<pre>';
|
||||
foreach((array)$StopWatch as $i => $x)
|
||||
$out .= sprintf("%{$l}d: %s\n", $i, $x);
|
||||
$out .= '</pre>';
|
||||
if (is_array($StopWatch)) array_pop($StopWatch);
|
||||
if ($print) print $out;
|
||||
return $out;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2006-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
*/
|
||||
|
||||
SDV($DraftSuffix, '-Draft');
|
||||
if ($DraftSuffix)
|
||||
SDV($SearchPatterns['normal']['draft'], "!$DraftSuffix\$!");
|
||||
|
||||
## set up a 'publish' authorization level, defaulting to 'edit' authorization
|
||||
SDV($DefaultPasswords['publish'], '');
|
||||
SDV($AuthCascade['publish'], 'edit');
|
||||
SDV($FmtPV['$PasswdPublish'], 'PasswdVar($pn, "publish")');
|
||||
if ($AuthCascade['attr'] == 'edit') $AuthCascade['attr'] = 'publish';
|
||||
|
||||
## Add a 'publish' page attribute if desired
|
||||
if (IsEnabled($EnablePublishAttr, 0))
|
||||
SDV($PageAttributes['passwdpublish'], '$[Set new publish password:]');
|
||||
|
||||
|
||||
$basename = preg_replace("/$DraftSuffix\$/", '', $pagename);
|
||||
## if no -Draft page, switch to $basename
|
||||
if (!PageExists($pagename) && PageExists($basename)) $pagename = $basename;
|
||||
|
||||
## The section below handles specialized EditForm pages and handler.
|
||||
## We don't bother to load it if we're not editing.
|
||||
SDV($DraftActionsPattern, 'edit');
|
||||
if (! preg_match("/($DraftActionsPattern)/", $action)) return;
|
||||
|
||||
## set edit form button labels to reflect draft prompts
|
||||
SDVA($InputTags['e_savebutton'], array('value' => ' '.XL('Publish').' '));
|
||||
SDVA($InputTags['e_saveeditbutton'], array('value' => ' '.XL('Save draft and edit').' '));
|
||||
SDVA($InputTags['e_savedraftbutton'], array(
|
||||
':html' => "<input type='submit' \$InputFormArgs />",
|
||||
'name' => 'postdraft', 'value' => ' '.XL('Save draft').' ',
|
||||
'accesskey' => XL('ak_savedraft')));
|
||||
|
||||
## with drafts enabled, the 'post' operation requires 'publish' permissions
|
||||
if ($_POST['post'] && $HandleAuth['edit'] == 'edit')
|
||||
$HandleAuth['edit'] = 'publish';
|
||||
|
||||
## disable the 'publish' button if not authorized to publish
|
||||
if (!CondAuth($basename, 'publish'))
|
||||
SDVA($InputTags['e_savebutton'], array('disabled' => 'disabled'));
|
||||
|
||||
## add the draft handler into $EditFunctions
|
||||
array_unshift($EditFunctions, 'EditDraft');
|
||||
function EditDraft(&$pagename, &$page, &$new) {
|
||||
global $WikiDir, $DraftSuffix, $DeleteKeyPattern, $EnableDraftAtomicDiff,
|
||||
$DraftRecentChangesFmt, $RecentChangesFmt, $Now;
|
||||
SDV($DeleteKeyPattern, "^\\s*delete\\s*$");
|
||||
$basename = preg_replace("/$DraftSuffix\$/", '', $pagename);
|
||||
$draftname = $basename . $DraftSuffix;
|
||||
if ($_POST['postdraft'] || $_POST['postedit']) $pagename = $draftname;
|
||||
else if ($_POST['post'] && !preg_match("/$DeleteKeyPattern/", $new['text'])) {
|
||||
$pagename = $basename;
|
||||
if(IsEnabled($EnableDraftAtomicDiff, 0)) {
|
||||
$page = ReadPage($basename);
|
||||
foreach($new as $k=>$v) # delete draft history
|
||||
if(preg_match('/:\\d+(:\\d+:)?$/', $k) && ! preg_match("/:$Now(:\\d+:)?$/", $k)) unset($new[$k]);
|
||||
unset($new['rev']);
|
||||
SDVA($new, $page);
|
||||
}
|
||||
$WikiDir->delete($draftname);
|
||||
}
|
||||
else if (PageExists($draftname) && $pagename != $draftname)
|
||||
{ Redirect($draftname, '$PageUrl?action=edit'); exit(); }
|
||||
if ($pagename == $draftname && isset($DraftRecentChangesFmt))
|
||||
$RecentChangesFmt = $DraftRecentChangesFmt;
|
||||
}
|
||||
@@ -0,0 +1,544 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2005-2010 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script provides a number of syndication feed and xml-based
|
||||
metadata options to PmWiki, including Atom, RSS 2.0, RSS 1.0 (RDF),
|
||||
and the Dublin Core Metadata extensions. This module is typically
|
||||
activated from a local configuration file via a line such as
|
||||
|
||||
if ($action == 'atom') include_once("$FarmD/scripts/feeds.php");
|
||||
if ($action == 'dc') include_once("$FarmD/scripts/feeds.php");
|
||||
|
||||
When enabled, ?action=atom, ?action=rss, and ?action=rdf produce
|
||||
syndication feeds based on any wikitrail contained in the page,
|
||||
or, for Category pages, on the pages in the category. The feeds
|
||||
are generated using pagelist, thus one can include parameters such
|
||||
as count=, list=, order=, etc. in the url to adjust the feed output.
|
||||
|
||||
?action=dc will normally generate Dublin Core Metadata for the
|
||||
current page only, but placing a group=, trail=, or link= argument
|
||||
in the url causes it to generate metadata for all pages in the
|
||||
associated group, trail, or backlink.
|
||||
|
||||
There are a large number of customizations available, most of which
|
||||
are controlled by the $FeedFmt array. Elements $FeedFmt look like
|
||||
|
||||
$FeedFmt['atom']['feed']['rights'] = 'All Rights Reserved';
|
||||
|
||||
where the first index corresponds to the action (?action=atom),
|
||||
the second index indicates a per-feed or per-item element, and
|
||||
the third index is the name of the element being generated.
|
||||
The above setting would therefore generate a
|
||||
"<rights>All Rights Reserved</rights>" in the feed for
|
||||
?action=atom. If the value of an entry begins with a '<',
|
||||
then feeds.php doesn't automatically add the tag around it.
|
||||
Elements can also be callable functions which are called to
|
||||
generate the appropriate output.
|
||||
|
||||
For example, to set the RSS 2.0 <author> element to the
|
||||
value of the last author to modify a page, one can set
|
||||
(in local/config.php):
|
||||
|
||||
$FeedFmt['rss']['item']['author'] = '$LastModifiedBy';
|
||||
|
||||
To use the RSS 2.0 <description> element to contain the
|
||||
change summary of the most recent edit, set
|
||||
|
||||
$FeedFmt['rss']['item']['description'] = '$LastModifiedSummary';
|
||||
|
||||
Feeds.php can also be combined with attachments to support
|
||||
podcasting via ?action=rss. Any page such as "PageName"
|
||||
that has an mp3 attachment with the same name as the page
|
||||
("PageName.mp3") will have an appropriate <enclosure> element
|
||||
in the feed output. The set of allowed attachments can be
|
||||
extended using the $RSSEnclosureFmt array:
|
||||
|
||||
$RSSEnclosureFmt = array('{$Name}.mp3', '{$Name}.mp4');
|
||||
|
||||
References:
|
||||
http://www.atomenabled.org/developers/syndication/
|
||||
http://dublincore.org/documents/dcmes-xml/
|
||||
http://en.wikipedia.org/wiki/Podcasting
|
||||
*/
|
||||
|
||||
## Settings for ?action=atom
|
||||
SDVA($FeedFmt['atom']['feed'], array(
|
||||
'_header' => 'Content-type: text/xml; charset="$Charset"',
|
||||
'_start' => '<?xml version="1.0" encoding="$Charset"?'.'>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">'."\n",
|
||||
'_end' => "</feed>\n",
|
||||
'title' => '$WikiTitle',
|
||||
'link' => '<link rel="self" href="{$PageUrl}?action=atom" />',
|
||||
'id' => '{$PageUrl}?action=atom',
|
||||
'updated' => '$FeedISOTime',
|
||||
'author' => "<author><name>$WikiTitle</name></author>\n",
|
||||
'generator' => '$Version',
|
||||
'logo' => '$PageLogoUrl'));
|
||||
SDVA($FeedFmt['atom']['item'], array(
|
||||
'_start' => "<entry>\n",
|
||||
'id' => '{$PageUrl}',
|
||||
'title' => '{$Title}',
|
||||
'updated' => '$ItemISOTime',
|
||||
'link' => "<link rel=\"alternate\" href=\"{\$PageUrl}\" />\n",
|
||||
'author' => "<author><name>{\$LastModifiedBy}</name></author>\n",
|
||||
'summary' => '{$Description}',
|
||||
'category' => "<category term=\"\$Category\" />\n",
|
||||
'_end' => "</entry>\n"));
|
||||
|
||||
## Settings for ?action=dc
|
||||
SDVA($FeedFmt['dc']['feed'], array(
|
||||
'_header' => 'Content-type: text/xml; charset="$Charset"',
|
||||
'_start' => '<?xml version="1.0" encoding="$Charset"?'.'>
|
||||
<!DOCTYPE rdf:RDF PUBLIC "-//DUBLIN CORE//DCMES DTD 2002/07/31//EN"
|
||||
"http://dublincore.org/documents/2002/07/31/dcmes-xml/dcmes-xml-dtd.dtd">
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">'."\n",
|
||||
'_end' => "</rdf:RDF>\n"));
|
||||
SDVA($FeedFmt['dc']['item'], array(
|
||||
'_start' => "<rdf:Description rdf:about=\"{\$PageUrl}\">\n",
|
||||
'dc:title' => '{$Title}',
|
||||
'dc:identifier' => '{$PageUrl}',
|
||||
'dc:date' => '$ItemISOTime',
|
||||
'dc:type' => 'Text',
|
||||
'dc:format' => 'text/html',
|
||||
'dc:description' => '{$Description}',
|
||||
'dc:subject' => "<dc:subject>\$Category</dc:subject>\n",
|
||||
'dc:publisher' => '$WikiTitle',
|
||||
'dc:author' => '{$LastModifiedBy}',
|
||||
'_end' => "</rdf:Description>\n"));
|
||||
|
||||
## RSS 2.0 settings for ?action=rss
|
||||
SDVA($FeedFmt['rss']['feed'], array(
|
||||
'_header' => 'Content-type: text/xml; charset="$Charset"',
|
||||
'_start' => '<?xml version="1.0" encoding="$Charset"?'.'>
|
||||
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<channel>'."\n",
|
||||
'_end' => "</channel>\n</rss>\n",
|
||||
'title' => '$WikiTitle | {$Group} / {$Title}',
|
||||
'link' => '{$PageUrl}?action=rss',
|
||||
'description' => '{$Group}.{$Title}',
|
||||
'lastBuildDate' => '$FeedRSSTime'));
|
||||
SDVA($FeedFmt['rss']['item'], array(
|
||||
'_start' => "<item>\n",
|
||||
'_end' => "</item>\n",
|
||||
'title' => '{$Group} / {$Title}',
|
||||
'link' => '{$PageUrl}',
|
||||
'description' => '{$Description}',
|
||||
'dc:contributor' => '{$LastModifiedBy}',
|
||||
'dc:date' => '$ItemISOTime',
|
||||
'pubDate' => '$ItemRSSTime',
|
||||
'enclosure' => 'RSSEnclosure'));
|
||||
|
||||
## RDF 1.0, for ?action=rdf
|
||||
SDVA($FeedFmt['rdf']['feed'], array(
|
||||
'_header' => 'Content-type: text/xml; charset="$Charset"',
|
||||
'_start' => '<?xml version="1.0" encoding="$Charset"?'.'>
|
||||
<rdf:RDF xmlns="http://purl.org/rss/1.0/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<channel rdf:about="{$PageUrl}?action=rdf">'."\n",
|
||||
'title' => '$WikiTitle | {$Group} / {$Title}',
|
||||
'link' => '{$PageUrl}?action=rdf',
|
||||
'description' => '{$Group}.{$Title}',
|
||||
'dc:date' => '$FeedISOTime',
|
||||
'items' => "<items>\n<rdf:Seq>\n\$FeedRDFSeq</rdf:Seq>\n</items>\n",
|
||||
'_items' => "</channel>\n",
|
||||
'_end' => "</rdf:RDF>\n"));
|
||||
SDVA($FeedFmt['rdf']['item'], array(
|
||||
'_start' => "<item rdf:about=\"{\$PageUrl}\">\n",
|
||||
'_end' => "</item>\n",
|
||||
'title' => '$WikiTitle | {$Group} / {$Title}',
|
||||
'link' => '{$PageUrl}',
|
||||
'description' => '{$Description}',
|
||||
'dc:date' => '$ItemISOTime'));
|
||||
|
||||
foreach(array_keys($FeedFmt) as $k) {
|
||||
SDV($HandleActions[$k], 'HandleFeed');
|
||||
SDV($HandleAuth[$k], 'read');
|
||||
}
|
||||
|
||||
function HandleFeed($pagename, $auth = 'read') {
|
||||
global $FeedFmt, $action, $PCache, $FmtV, $TimeISOZFmt, $RSSTimeFmt,
|
||||
$FeedPageListOpt, $FeedCategoryOpt, $FeedTrailOpt,
|
||||
$FeedDescPatterns, $CategoryGroup, $EntitiesTable;
|
||||
SDV($RSSTimeFmt, 'D, d M Y H:i:s \G\M\T');
|
||||
SDV($FeedDescPatterns,
|
||||
array('/<[^>]*$/' => ' ', '/\\w+$/' => '', '/<[^>]+>/' => ''));
|
||||
$FeedPageListOpt = (array)@$FeedPageListOpt;
|
||||
SDVA($FeedCategoryOpt, array('link' => $pagename));
|
||||
SDVA($FeedTrailOpt, array('trail' => $pagename, 'count' => 10));
|
||||
|
||||
$f = $FeedFmt[$action];
|
||||
$page = RetrieveAuthPage($pagename, $auth, true, READPAGE_CURRENT);
|
||||
if (!$page) Abort("?cannot generate feed");
|
||||
$feedtime = $page['time'];
|
||||
|
||||
# determine list of pages to display
|
||||
if (@($_REQUEST['trail'] || $_REQUEST['group'] || $_REQUEST['link']
|
||||
|| $_REQUEST['name']))
|
||||
$opt = $FeedPageListOpt;
|
||||
else if (preg_match("/^$CategoryGroup\\./", $pagename))
|
||||
$opt = $FeedCategoryOpt;
|
||||
else if ($action != 'dc') $opt = $FeedTrailOpt;
|
||||
else {
|
||||
PCache($pagename, $page);
|
||||
$pagelist = array($pagename);
|
||||
}
|
||||
if (!@$pagelist) {
|
||||
$opt = array_merge($opt, @$_REQUEST);
|
||||
$pagelist = MakePageList($pagename, $opt, 0);
|
||||
}
|
||||
|
||||
# process list of pages in feed
|
||||
$rdfseq = '';
|
||||
$pl = array();
|
||||
foreach($pagelist as $pn) {
|
||||
if (!PageExists($pn)) continue;
|
||||
if (!isset($PCache[$pn]['time']))
|
||||
{ $page = ReadPage($pn, READPAGE_CURRENT); PCache($pn, $page); }
|
||||
$pc = & $PCache[$pn];
|
||||
$pl[] = $pn;
|
||||
$rdfseq .= FmtPageName("<rdf:li resource=\"{\$PageUrl}\" />\n", $pn);
|
||||
if ($pc['time'] > $feedtime) $feedtime = $pc['time'];
|
||||
if (@$opt['count'] && count($pl) >= $opt['count']) break;
|
||||
}
|
||||
$pagelist = $pl;
|
||||
|
||||
$FmtV['$FeedRDFSeq'] = $rdfseq;
|
||||
$FmtV['$FeedISOTime'] = gmstrftime($TimeISOZFmt, $feedtime);
|
||||
$FmtV['$FeedRSSTime'] = gmdate($RSSTimeFmt, $feedtime);
|
||||
# format start of feed
|
||||
$out = FmtPageName($f['feed']['_start'], $pagename);
|
||||
|
||||
# format feed elements
|
||||
foreach($f['feed'] as $k => $v) {
|
||||
if ($k{0} == '_' || !$v) continue;
|
||||
$x = FmtPageName($v, $pagename);
|
||||
if (!$x) continue;
|
||||
$out .= ($v{0} == '<') ? $x : "<$k>$x</$k>\n";
|
||||
}
|
||||
|
||||
# format items in feed
|
||||
if (@$f['feed']['_items'])
|
||||
$out .= FmtPageName($f['feed']['_items'], $pagename);
|
||||
foreach($pagelist as $pn) {
|
||||
$page = &$PCache[$pn];
|
||||
$FmtV['$ItemDesc'] = @$page['description'];
|
||||
$FmtV['$ItemISOTime'] = gmstrftime($TimeISOZFmt, $page['time']);
|
||||
$FmtV['$ItemRSSTime'] = gmdate($RSSTimeFmt, $page['time']);
|
||||
|
||||
$out .= FmtPageName($f['item']['_start'], $pn);
|
||||
foreach((array)@$f['item'] as $k => $v) {
|
||||
if ($k{0} == '_' || !$v) continue;
|
||||
if (is_callable($v)) { $out .= $v($pn, $page, $k); continue; }
|
||||
if (strpos($v, '$LastModifiedBy') !== false && !@$page['author'])
|
||||
continue;
|
||||
if (strpos($v, '$Category') !== false) {
|
||||
if (preg_match_all("/(?<=^|,)$CategoryGroup\\.([^,]+)/",
|
||||
@$page['targets'], $match)) {
|
||||
foreach($match[1] as $c) {
|
||||
$FmtV['$Category'] = $c;
|
||||
$out .= FmtPageName($v, $pn);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
$x = FmtPageName($v, $pn);
|
||||
if (!$x) continue;
|
||||
$out .= ($v{0} == '<') ? $x : "<$k>$x</$k>\n";
|
||||
}
|
||||
$out .= FmtPageName($f['item']['_end'], $pn);
|
||||
}
|
||||
$out .= FmtPageName($f['feed']['_end'], $pagename);
|
||||
foreach((array)@$f['feed']['_header'] as $fmt)
|
||||
header(FmtPageName($fmt, $pagename));
|
||||
print str_replace(array_keys($EntitiesTable),
|
||||
array_values($EntitiesTable), $out);
|
||||
}
|
||||
|
||||
## RSSEnclosure is called in ?action=rss to generate <enclosure>
|
||||
## tags for any pages that have an attached "PageName.mp3" file.
|
||||
## The set of attachments to enclose is given by $RSSEnclosureFmt.
|
||||
function RSSEnclosure($pagename, &$page, $k) {
|
||||
global $RSSEnclosureFmt, $UploadFileFmt, $UploadExts;
|
||||
if (!function_exists('MakeUploadName')) return '';
|
||||
SDV($RSSEnclosureFmt, array('{$Name}.mp3'));
|
||||
$encl = '';
|
||||
foreach((array)$RSSEnclosureFmt as $fmt) {
|
||||
$path = FmtPageName($fmt, $pagename);
|
||||
$upname = MakeUploadName($pagename, $path);
|
||||
$filepath = FmtPageName("$UploadFileFmt/$upname", $pagename);
|
||||
if (file_exists($filepath)) {
|
||||
$length = filesize($filepath);
|
||||
$type = @$UploadExts[preg_replace('/.*\\./', '', $filepath)];
|
||||
$url = LinkUpload($pagename, 'Attach:', $path, '', '', '$LinkUrl');
|
||||
$encl .= "<$k url='$url' length='$length' type='$type' />";
|
||||
}
|
||||
}
|
||||
return $encl;
|
||||
}
|
||||
|
||||
## Since most feeds don't understand html character entities, we
|
||||
## convert the common ones to their numeric form here.
|
||||
SDVA($EntitiesTable, array(
|
||||
# entities defined in "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent"
|
||||
' ' => ' ',
|
||||
'¡' => '¡',
|
||||
'¢' => '¢',
|
||||
'£' => '£',
|
||||
'¤' => '¤',
|
||||
'¥' => '¥',
|
||||
'¦' => '¦',
|
||||
'§' => '§',
|
||||
'¨' => '¨',
|
||||
'©' => '©',
|
||||
'ª' => 'ª',
|
||||
'«' => '«',
|
||||
'¬' => '¬',
|
||||
'­' => '­',
|
||||
'®' => '®',
|
||||
'¯' => '¯',
|
||||
'°' => '°',
|
||||
'±' => '±',
|
||||
'²' => '²',
|
||||
'³' => '³',
|
||||
'´' => '´',
|
||||
'µ' => 'µ',
|
||||
'¶' => '¶',
|
||||
'·' => '·',
|
||||
'¸' => '¸',
|
||||
'¹' => '¹',
|
||||
'º' => 'º',
|
||||
'»' => '»',
|
||||
'¼' => '¼',
|
||||
'½' => '½',
|
||||
'¾' => '¾',
|
||||
'¿' => '¿',
|
||||
'À' => 'À',
|
||||
'Á' => 'Á',
|
||||
'Â' => 'Â',
|
||||
'Ã' => 'Ã',
|
||||
'Ä' => 'Ä',
|
||||
'Å' => 'Å',
|
||||
'Æ' => 'Æ',
|
||||
'Ç' => 'Ç',
|
||||
'È' => 'È',
|
||||
'É' => 'É',
|
||||
'Ê' => 'Ê',
|
||||
'Ë' => 'Ë',
|
||||
'Ì' => 'Ì',
|
||||
'Í' => 'Í',
|
||||
'Î' => 'Î',
|
||||
'Ï' => 'Ï',
|
||||
'Ð' => 'Ð',
|
||||
'Ñ' => 'Ñ',
|
||||
'Ò' => 'Ò',
|
||||
'Ó' => 'Ó',
|
||||
'Ô' => 'Ô',
|
||||
'Õ' => 'Õ',
|
||||
'Ö' => 'Ö',
|
||||
'×' => '×',
|
||||
'Ø' => 'Ø',
|
||||
'Ù' => 'Ù',
|
||||
'Ú' => 'Ú',
|
||||
'Û' => 'Û',
|
||||
'Ü' => 'Ü',
|
||||
'Ý' => 'Ý',
|
||||
'Þ' => 'Þ',
|
||||
'ß' => 'ß',
|
||||
'à' => 'à',
|
||||
'á' => 'á',
|
||||
'â' => 'â',
|
||||
'ã' => 'ã',
|
||||
'ä' => 'ä',
|
||||
'å' => 'å',
|
||||
'æ' => 'æ',
|
||||
'ç' => 'ç',
|
||||
'è' => 'è',
|
||||
'é' => 'é',
|
||||
'ê' => 'ê',
|
||||
'ë' => 'ë',
|
||||
'ì' => 'ì',
|
||||
'í' => 'í',
|
||||
'î' => 'î',
|
||||
'ï' => 'ï',
|
||||
'ð' => 'ð',
|
||||
'ñ' => 'ñ',
|
||||
'ò' => 'ò',
|
||||
'ó' => 'ó',
|
||||
'ô' => 'ô',
|
||||
'õ' => 'õ',
|
||||
'ö' => 'ö',
|
||||
'÷' => '÷',
|
||||
'ø' => 'ø',
|
||||
'ù' => 'ù',
|
||||
'ú' => 'ú',
|
||||
'û' => 'û',
|
||||
'ü' => 'ü',
|
||||
'ý' => 'ý',
|
||||
'þ' => 'þ',
|
||||
'ÿ' => 'ÿ',
|
||||
# entities defined in "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent"
|
||||
'"' => '"',
|
||||
#'&' => '&#38;',
|
||||
#'<' => '&#60;',
|
||||
#'>' => '>',
|
||||
''' => ''',
|
||||
'Œ' => 'Œ',
|
||||
'œ' => 'œ',
|
||||
'Š' => 'Š',
|
||||
'š' => 'š',
|
||||
'Ÿ' => 'Ÿ',
|
||||
'ˆ' => 'ˆ',
|
||||
'˜' => '˜',
|
||||
' ' => ' ',
|
||||
' ' => ' ',
|
||||
' ' => ' ',
|
||||
'‌' => '‌',
|
||||
'‍' => '‍',
|
||||
'‎' => '‎',
|
||||
'‏' => '‏',
|
||||
'–' => '–',
|
||||
'—' => '—',
|
||||
'‘' => '‘',
|
||||
'’' => '’',
|
||||
'‚' => '‚',
|
||||
'“' => '“',
|
||||
'”' => '”',
|
||||
'„' => '„',
|
||||
'†' => '†',
|
||||
'‡' => '‡',
|
||||
'‰' => '‰',
|
||||
'‹' => '‹',
|
||||
'›' => '›',
|
||||
'€' => '€',
|
||||
# entities defined in "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent"
|
||||
'ƒ' => 'ƒ',
|
||||
'Α' => 'Α',
|
||||
'Β' => 'Β',
|
||||
'Γ' => 'Γ',
|
||||
'Δ' => 'Δ',
|
||||
'Ε' => 'Ε',
|
||||
'Ζ' => 'Ζ',
|
||||
'Η' => 'Η',
|
||||
'Θ' => 'Θ',
|
||||
'Ι' => 'Ι',
|
||||
'Κ' => 'Κ',
|
||||
'Λ' => 'Λ',
|
||||
'Μ' => 'Μ',
|
||||
'Ν' => 'Ν',
|
||||
'Ξ' => 'Ξ',
|
||||
'Ο' => 'Ο',
|
||||
'Π' => 'Π',
|
||||
'Ρ' => 'Ρ',
|
||||
'Σ' => 'Σ',
|
||||
'Τ' => 'Τ',
|
||||
'Υ' => 'Υ',
|
||||
'Φ' => 'Φ',
|
||||
'Χ' => 'Χ',
|
||||
'Ψ' => 'Ψ',
|
||||
'Ω' => 'Ω',
|
||||
'α' => 'α',
|
||||
'β' => 'β',
|
||||
'γ' => 'γ',
|
||||
'δ' => 'δ',
|
||||
'ε' => 'ε',
|
||||
'ζ' => 'ζ',
|
||||
'η' => 'η',
|
||||
'θ' => 'θ',
|
||||
'ι' => 'ι',
|
||||
'κ' => 'κ',
|
||||
'λ' => 'λ',
|
||||
'μ' => 'μ',
|
||||
'ν' => 'ν',
|
||||
'ξ' => 'ξ',
|
||||
'ο' => 'ο',
|
||||
'π' => 'π',
|
||||
'ρ' => 'ρ',
|
||||
'ς' => 'ς',
|
||||
'σ' => 'σ',
|
||||
'τ' => 'τ',
|
||||
'υ' => 'υ',
|
||||
'φ' => 'φ',
|
||||
'χ' => 'χ',
|
||||
'ψ' => 'ψ',
|
||||
'ω' => 'ω',
|
||||
'ϑ' => 'ϑ',
|
||||
'ϒ' => 'ϒ',
|
||||
'ϖ' => 'ϖ',
|
||||
'•' => '•',
|
||||
'…' => '…',
|
||||
'′' => '′',
|
||||
'″' => '″',
|
||||
'‾' => '‾',
|
||||
'⁄' => '⁄',
|
||||
'℘' => '℘',
|
||||
'ℑ' => 'ℑ',
|
||||
'ℜ' => 'ℜ',
|
||||
'™' => '™',
|
||||
'ℵ' => 'ℵ',
|
||||
'←' => '←',
|
||||
'↑' => '↑',
|
||||
'→' => '→',
|
||||
'↓' => '↓',
|
||||
'↔' => '↔',
|
||||
'↵' => '↵',
|
||||
'⇐' => '⇐',
|
||||
'⇑' => '⇑',
|
||||
'⇒' => '⇒',
|
||||
'⇓' => '⇓',
|
||||
'⇔' => '⇔',
|
||||
'∀' => '∀',
|
||||
'∂' => '∂',
|
||||
'∃' => '∃',
|
||||
'∅' => '∅',
|
||||
'∇' => '∇',
|
||||
'∈' => '∈',
|
||||
'∉' => '∉',
|
||||
'∋' => '∋',
|
||||
'∏' => '∏',
|
||||
'∑' => '∑',
|
||||
'−' => '−',
|
||||
'∗' => '∗',
|
||||
'√' => '√',
|
||||
'∝' => '∝',
|
||||
'∞' => '∞',
|
||||
'∠' => '∠',
|
||||
'∧' => '∧',
|
||||
'∨' => '∨',
|
||||
'∩' => '∩',
|
||||
'∪' => '∪',
|
||||
'∫' => '∫',
|
||||
'∴' => '∴',
|
||||
'∼' => '∼',
|
||||
'≅' => '≅',
|
||||
'≈' => '≈',
|
||||
'≠' => '≠',
|
||||
'≡' => '≡',
|
||||
'≤' => '≤',
|
||||
'≥' => '≥',
|
||||
'⊂' => '⊂',
|
||||
'⊃' => '⊃',
|
||||
'⊄' => '⊄',
|
||||
'⊆' => '⊆',
|
||||
'⊇' => '⊇',
|
||||
'⊕' => '⊕',
|
||||
'⊗' => '⊗',
|
||||
'⊥' => '⊥',
|
||||
'⋅' => '⋅',
|
||||
'⌈' => '⌈',
|
||||
'⌉' => '⌉',
|
||||
'⌊' => '⌊',
|
||||
'⌋' => '⌋',
|
||||
'⟨' => '〈',
|
||||
'⟩' => '〉',
|
||||
'◊' => '◊',
|
||||
'♠' => '♠',
|
||||
'♣' => '♣',
|
||||
'♥' => '♥',
|
||||
'♦' => '♦'));
|
||||
|
||||
@@ -0,0 +1,339 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2005-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
*/
|
||||
|
||||
# $InputAttrs are the attributes we allow in output tags
|
||||
SDV($InputAttrs, array('name', 'value', 'id', 'class', 'rows', 'cols',
|
||||
'size', 'maxlength', 'action', 'method', 'accesskey', 'tabindex', 'multiple',
|
||||
'checked', 'disabled', 'readonly', 'enctype', 'src', 'alt',
|
||||
'required', 'placeholder', 'autocomplete'
|
||||
));
|
||||
|
||||
# Set up formatting for text, submit, hidden, radio, etc. types
|
||||
foreach(array('text', 'submit', 'hidden', 'password', 'radio', 'checkbox',
|
||||
'reset', 'file', 'image') as $t)
|
||||
SDV($InputTags[$t][':html'], "<input type='$t' \$InputFormArgs />");
|
||||
SDV($InputTags['text']['class'], 'inputbox');
|
||||
SDV($InputTags['password']['class'], 'inputbox');
|
||||
SDV($InputTags['submit']['class'], 'inputbutton');
|
||||
SDV($InputTags['reset']['class'], 'inputbutton');
|
||||
SDV($InputTags['radio'][':checked'], 'checked');
|
||||
SDV($InputTags['checkbox'][':checked'], 'checked');
|
||||
|
||||
# (:input form:)
|
||||
SDVA($InputTags['form'], array(
|
||||
':args' => array('action', 'method'),
|
||||
':html' => "<form \$InputFormArgs>",
|
||||
'method' => 'post'));
|
||||
|
||||
# (:input end:)
|
||||
SDV($InputTags['end'][':html'], '</form>');
|
||||
|
||||
# (:input textarea:)
|
||||
SDVA($InputTags['textarea'], array(
|
||||
':content' => array('value'),
|
||||
':attr' => array_diff($InputAttrs, array('value')),
|
||||
':html' => "<textarea \$InputFormArgs>\$InputFormContent</textarea>"));
|
||||
|
||||
# (:input image:)
|
||||
SDV($InputTags['image'][':args'], array('name', 'src', 'alt'));
|
||||
|
||||
# (:input select:)
|
||||
SDVA($InputTags['select-option'], array(
|
||||
':args' => array('name', 'value', 'label'),
|
||||
':content' => array('label', 'value', 'name'),
|
||||
':attr' => array('value', 'selected'),
|
||||
':checked' => 'selected',
|
||||
':html' => "<option \$InputFormArgs>\$InputFormContent</option>"));
|
||||
SDVA($InputTags['select'], array(
|
||||
'class' => 'inputbox',
|
||||
':html' => "<select \$InputSelectArgs>\$InputSelectOptions</select>"));
|
||||
|
||||
# (:input defaults?:)
|
||||
SDVA($InputTags['default'], array(':fn' => 'InputDefault'));
|
||||
SDVA($InputTags['defaults'], array(':fn' => 'InputDefault'));
|
||||
|
||||
## (:input ...:) directives
|
||||
Markup_e('input', 'directives',
|
||||
'/\\(:input\\s+(\\w+)(.*?):\\)/i',
|
||||
"InputMarkup(\$pagename, \$m[1], \$m[2])");
|
||||
|
||||
## (:input select:) has its own markup processing
|
||||
Markup_e('input-select', '<input',
|
||||
'/\\(:input\\s+select\\s.*?:\\)(?:\\s*\\(:input\\s+select\\s.*?:\\))*/i',
|
||||
"InputSelect(\$pagename, 'select', \$m[0])");
|
||||
|
||||
## The 'input+sp' rule combines multiple (:input select ... :)
|
||||
## into a single markup line (to avoid split line effects)
|
||||
Markup('input+sp', '<split',
|
||||
'/(\\(:input\\s+select\\s(?>.*?:\\)))\\s+(?=\\(:input\\s)/', '$1');
|
||||
|
||||
SDV($InputFocusFmt,
|
||||
"<script language='javascript' type='text/javascript'><!--
|
||||
document.getElementById('\$InputFocusId').focus();//--></script>");
|
||||
|
||||
## InputToHTML performs standard processing on (:input ...:) arguments,
|
||||
## and returns the formatted HTML string.
|
||||
function InputToHTML($pagename, $type, $args, &$opt) {
|
||||
global $InputTags, $InputAttrs, $InputValues, $FmtV, $KeepToken,
|
||||
$InputFocusLevel, $InputFocusId, $InputFocusFmt, $HTMLFooterFmt;
|
||||
if (!@$InputTags[$type]) return "(:input $type $args:)";
|
||||
## get input arguments
|
||||
if (!is_array($args)) $args = ParseArgs($args, '(?>([\\w-]+)[:=])');
|
||||
## convert any positional arguments to named arguments
|
||||
$posnames = @$InputTags[$type][':args'];
|
||||
if (!$posnames) $posnames = array('name', 'value');
|
||||
while (count($posnames) > 0 && count(@$args['']) > 0) {
|
||||
$n = array_shift($posnames);
|
||||
if (!isset($args[$n])) $args[$n] = array_shift($args['']);
|
||||
}
|
||||
## merge defaults for input type with arguments
|
||||
$opt = array_merge($InputTags[$type], $args);
|
||||
## www.w3.org/TR/html4/types
|
||||
if(isset($opt['id'])) $opt['id'] = preg_replace('/[^-A-Za-z0-9:_.]+/', '_', $opt['id']);
|
||||
## convert any remaining positional args to flags
|
||||
foreach ((array)@$opt[''] as $a)
|
||||
{ $a = strtolower($a); if (!isset($opt[$a])) $opt[$a] = $a; }
|
||||
if (isset($opt['name'])) {
|
||||
$opt['name'] = preg_replace('/^\\$:/', 'ptv_', @$opt['name']);
|
||||
$opt['name'] = preg_replace('/[^-A-Za-z0-9:_.\\[\\]]+/', '_', $opt['name']);
|
||||
$name = $opt['name'];
|
||||
## set control values from $InputValues array
|
||||
## radio, checkbox, select, etc. require a flag of some sort,
|
||||
## others just set 'value'
|
||||
if (isset($InputValues[$name])) {
|
||||
$checked = @$opt[':checked'];
|
||||
if ($checked) {
|
||||
$opt[$checked] = in_array(@$opt['value'], (array)$InputValues[$name])
|
||||
? $checked : false;
|
||||
} else if (!isset($opt['value'])) $opt['value'] = $InputValues[$name];
|
||||
}
|
||||
}
|
||||
## build $InputFormContent
|
||||
$FmtV['$InputFormContent'] = '';
|
||||
foreach((array)@$opt[':content'] as $a)
|
||||
if (isset($opt[$a])) { $FmtV['$InputFormContent'] = $opt[$a]; break; }
|
||||
## hash and store any "secure" values
|
||||
if (@$opt['secure'] == '#') $opt['secure'] = rand();
|
||||
if (@$opt['secure'] > '') {
|
||||
$md5 = md5($opt['secure'] . $opt['value']);
|
||||
@session_start();
|
||||
$_SESSION['forms'][$md5] = $opt['value'];
|
||||
$opt['value'] = $md5;
|
||||
}
|
||||
## handle focus=# option
|
||||
$focus = @$opt['focus'];
|
||||
if (isset($focus)
|
||||
&& (!isset($InputFocusLevel) || $focus < $InputFocusLevel)) {
|
||||
if (!isset($opt['id'])) $opt['id'] = "wikifocus$focus";
|
||||
$InputFocusLevel = $focus;
|
||||
$InputFocusId = $opt['id'];
|
||||
$HTMLFooterFmt['inputfocus'] = $InputFocusFmt;
|
||||
}
|
||||
## build $InputFormArgs from $opt
|
||||
$attrlist = (isset($opt[':attr'])) ? $opt[':attr'] : $InputAttrs;
|
||||
$attr = array();
|
||||
foreach ($attrlist as $a) {
|
||||
if (!isset($opt[$a]) || $opt[$a]===false) continue;
|
||||
if(strpos($opt[$a], $KeepToken)!== false) # multiline textarea/hidden fields
|
||||
$opt[$a] = Keep(str_replace("'", ''', MarkupRestore($opt[$a]) ));
|
||||
$attr[] = "$a='".str_replace("'", ''', $opt[$a])."'";
|
||||
}
|
||||
$FmtV['$InputFormArgs'] = implode(' ', $attr);
|
||||
return FmtPageName($opt[':html'], $pagename);
|
||||
}
|
||||
|
||||
|
||||
## InputMarkup handles the (:input ...:) directive. It either
|
||||
## calls any function given by the :fn element of the corresponding
|
||||
## tag, or else just returns the result of InputToHTML().
|
||||
function InputMarkup($pagename, $type, $args) {
|
||||
global $InputTags;
|
||||
$fn = @$InputTags[$type][':fn'];
|
||||
if ($fn) return $fn($pagename, $type, $args);
|
||||
return Keep(InputToHTML($pagename, $type, $args, $opt));
|
||||
}
|
||||
|
||||
|
||||
## (:input default:) directive.
|
||||
function InputDefault($pagename, $type, $args) {
|
||||
global $InputValues, $PageTextVarPatterns, $PCache;
|
||||
$args = ParseArgs($args);
|
||||
$args[''] = (array)@$args[''];
|
||||
$name = (isset($args['name'])) ? $args['name'] : array_shift($args['']);
|
||||
$name = preg_replace('/^\\$:/', 'ptv_', $name);
|
||||
$value = (isset($args['value'])) ? $args['value'] : array_shift($args['']);
|
||||
if (!isset($InputValues[$name])) $InputValues[$name] = $value;
|
||||
if (@$args['request']) {
|
||||
$req = array_merge($_GET, $_POST);
|
||||
foreach($req as $k => $v)
|
||||
if (!isset($InputValues[$k]))
|
||||
$InputValues[$k] = PHSC(stripmagic($v), ENT_NOQUOTES);
|
||||
}
|
||||
$sources = @$args['source'];
|
||||
if ($sources) {
|
||||
foreach(explode(',', $sources) as $source) {
|
||||
$source = MakePageName($pagename, $source);
|
||||
if (!PageExists($source)) continue;
|
||||
$page = RetrieveAuthPage($source, 'read', false, READPAGE_CURRENT);
|
||||
if (! $page || ! isset($page['text'])) continue;
|
||||
foreach((array)$PageTextVarPatterns as $pat)
|
||||
if (preg_match_all($pat, IsEnabled($PCache[$source]['=preview'], $page['text']),
|
||||
$match, PREG_SET_ORDER))
|
||||
foreach($match as $m)
|
||||
# if (!isset($InputValues['ptv_'.$m[2]])) PITS:01337
|
||||
$InputValues['ptv_'.$m[2]] =
|
||||
PHSC(Qualify($source, $m[3]), ENT_NOQUOTES);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
## (:input select ...:) is special, because we need to process a bunch of
|
||||
## them as a single unit.
|
||||
function InputSelect($pagename, $type, $markup) {
|
||||
global $InputTags, $InputAttrs, $FmtV;
|
||||
preg_match_all('/\\(:input\\s+\\S+\\s+(.*?):\\)/', $markup, $match);
|
||||
$selectopt = (array)$InputTags[$type];
|
||||
$opt = $selectopt;
|
||||
$optionshtml = '';
|
||||
$optiontype = isset($InputTags["$type-option"])
|
||||
? "$type-option" : "select-option";
|
||||
foreach($match[1] as $args) {
|
||||
$optionshtml .= InputToHTML($pagename, $optiontype, $args, $oo);
|
||||
$opt = array_merge($opt, $oo);
|
||||
}
|
||||
$attrlist = array_diff($InputAttrs, array('value'));
|
||||
$attr = array();
|
||||
foreach($attrlist as $a) {
|
||||
if (!isset($opt[$a]) || $opt[$a]===false) continue;
|
||||
$attr[] = "$a='".str_replace("'", ''', $opt[$a])."'";
|
||||
}
|
||||
$FmtV['$InputSelectArgs'] = implode(' ', $attr);
|
||||
$FmtV['$InputSelectOptions'] = $optionshtml;
|
||||
return Keep(FmtPageName($selectopt[':html'], $pagename));
|
||||
}
|
||||
|
||||
|
||||
function InputActionForm($pagename, $type, $args) {
|
||||
global $InputAttrs;
|
||||
$args = ParseArgs($args);
|
||||
if (@$args['pagename']) $pagename = $args['pagename'];
|
||||
$opt = NULL;
|
||||
$html = InputToHTML($pagename, $type, $args, $opt);
|
||||
foreach(preg_grep('/^[\\w$]/', array_keys($args)) as $k) {
|
||||
if (is_array($args[$k]) || in_array($k, $InputAttrs)) continue;
|
||||
if ($k == 'n' || $k == 'pagename') continue;
|
||||
$html .= "<input type='hidden' name='$k' value='{$args[$k]}' />";
|
||||
}
|
||||
return Keep($html);
|
||||
}
|
||||
|
||||
|
||||
## RequestArgs is used to extract values from controls (typically
|
||||
## in $_GET and $_POST).
|
||||
function RequestArgs($req = NULL) {
|
||||
if (is_null($req)) $req = array_merge($_GET, $_POST);
|
||||
foreach ($req as $k => $v) $req[$k] = stripmagic($req[$k]);
|
||||
return $req;
|
||||
}
|
||||
|
||||
|
||||
## Form-based authorization prompts (for use with PmWikiAuth)
|
||||
SDVA($InputTags['auth_form'], array(
|
||||
':html' => "<form \$InputFormArgs>\$PostVars",
|
||||
'action' => str_replace("'", '%37', stripmagic($_SERVER['REQUEST_URI'])),
|
||||
'method' => 'post',
|
||||
'name' => 'authform'));
|
||||
SDV($AuthPromptFmt, array(&$PageStartFmt, 'page:$SiteGroup.AuthForm',
|
||||
"<script language='javascript' type='text/javascript'><!--
|
||||
try { document.authform.authid.focus(); }
|
||||
catch(e) { document.authform.authpw.focus(); } //--></script>",
|
||||
&$PageEndFmt));
|
||||
|
||||
## PITS:01188, these should exist in "browse" mode
|
||||
## NOTE: also defined in prefs.php
|
||||
XLSDV('en', array(
|
||||
'ak_save' => 's',
|
||||
'ak_saveedit' => 'u',
|
||||
'ak_preview' => 'p',
|
||||
'ak_textedit' => ',',
|
||||
'e_rows' => '23',
|
||||
'e_cols' => '60'));
|
||||
|
||||
## The section below handles specialized EditForm pages.
|
||||
## We don't bother to load it if we're not editing.
|
||||
|
||||
if ($action != 'edit') return;
|
||||
|
||||
SDV($PageEditForm, '$SiteGroup.EditForm');
|
||||
SDV($PageEditFmt, '$EditForm');
|
||||
if (@$_REQUEST['editform']) {
|
||||
$PageEditForm=$_REQUEST['editform'];
|
||||
$PageEditFmt='$EditForm';
|
||||
}
|
||||
$Conditions['e_preview'] = '(boolean)$_REQUEST["preview"]';
|
||||
|
||||
# (:e_preview:) displays the preview of formatted text.
|
||||
Markup_e('e_preview', 'directives',
|
||||
'/^\\(:e_preview:\\)/',
|
||||
"isset(\$GLOBALS['FmtV']['\$PreviewText']) ? Keep(\$GLOBALS['FmtV']['\$PreviewText']): ''");
|
||||
|
||||
# If we didn't load guiedit.php, then set (:e_guibuttons:) to
|
||||
# simply be empty.
|
||||
Markup('e_guibuttons', 'directives', '/\\(:e_guibuttons:\\)/', '');
|
||||
|
||||
# Prevent (:e_preview:) and (:e_guibuttons:) from
|
||||
# participating in text rendering step.
|
||||
SDV($SaveAttrPatterns['/\\(:e_(preview|guibuttons):\\)/'], ' ');
|
||||
|
||||
SDVA($InputTags['e_form'], array(
|
||||
':html' => "<form action='{\$PageUrl}?action=edit' method='post'
|
||||
\$InputFormArgs><input type='hidden' name='action' value='edit'
|
||||
/><input type='hidden' name='n' value='{\$FullName}'
|
||||
/><input type='hidden' name='basetime' value='\$EditBaseTime'
|
||||
/>"));
|
||||
SDVA($InputTags['e_textarea'], array(
|
||||
':html' => "<textarea \$InputFormArgs
|
||||
onkeydown='if (event.keyCode==27) event.returnValue=false;'
|
||||
>\$EditText</textarea>",
|
||||
'name' => 'text', 'id' => 'text', 'accesskey' => XL('ak_textedit'),
|
||||
'rows' => XL('e_rows'), 'cols' => XL('e_cols')));
|
||||
SDVA($InputTags['e_author'], array(
|
||||
':html' => "<input type='text' \$InputFormArgs />",
|
||||
'name' => 'author', 'value' => $Author));
|
||||
SDVA($InputTags['e_changesummary'], array(
|
||||
':html' => "<input type='text' \$InputFormArgs />",
|
||||
'name' => 'csum', 'size' => '60', 'maxlength' => '100',
|
||||
'value' => PHSC(stripmagic(@$_POST['csum']), ENT_QUOTES)));
|
||||
SDVA($InputTags['e_minorcheckbox'], array(
|
||||
':html' => "<input type='checkbox' \$InputFormArgs />",
|
||||
'name' => 'diffclass', 'value' => 'minor'));
|
||||
if (@$_POST['diffclass']=='minor')
|
||||
SDV($InputTags['e_minorcheckbox']['checked'], 'checked');
|
||||
SDVA($InputTags['e_savebutton'], array(
|
||||
':html' => "<input type='submit' \$InputFormArgs />",
|
||||
'name' => 'post', 'value' => ' '.XL('Save').' ',
|
||||
'accesskey' => XL('ak_save')));
|
||||
SDVA($InputTags['e_saveeditbutton'], array(
|
||||
':html' => "<input type='submit' \$InputFormArgs />",
|
||||
'name' => 'postedit', 'value' => ' '.XL('Save and edit').' ',
|
||||
'accesskey' => XL('ak_saveedit')));
|
||||
SDVA($InputTags['e_savedraftbutton'], array(':html' => ''));
|
||||
SDVA($InputTags['e_previewbutton'], array(
|
||||
':html' => "<input type='submit' \$InputFormArgs />",
|
||||
'name' => 'preview', 'value' => ' '.XL('Preview').' ',
|
||||
'accesskey' => XL('ak_preview')));
|
||||
SDVA($InputTags['e_cancelbutton'], array(
|
||||
':html' => "<input type='submit' \$InputFormArgs />",
|
||||
'name' => 'cancel', 'value' => ' '.XL('Cancel').' ' ));
|
||||
SDVA($InputTags['e_resetbutton'], array(
|
||||
':html' => "<input type='reset' \$InputFormArgs />",
|
||||
'value' => ' '.XL('Reset').' '));
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2013 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script adds a graphical button bar to the edit page form.
|
||||
The buttons are placed in the $GUIButtons array; each button
|
||||
is specified by an array of five values:
|
||||
- the position of the button relative to others (a number)
|
||||
- the opening markup sequence
|
||||
- the closing markup sequence
|
||||
- the default text if none was highlighted
|
||||
- the text of the button, either (a) HTML markup or (b) the
|
||||
url of a gif/jpg/png image to be used for the button
|
||||
(along with optional "title" text in quotes).
|
||||
|
||||
The buttons specified in this file are the default buttons
|
||||
for the standard markups. Some buttons (e.g., the attach/upload
|
||||
button) are specified in their respective cookbook module.
|
||||
*/
|
||||
|
||||
SDVA($HTMLHeaderFmt, array('guiedit' => "<script type='text/javascript'
|
||||
src='\$FarmPubDirUrl/guiedit/guiedit.js'></script>\n"));
|
||||
|
||||
SDV($GUIButtonDirUrlFmt,'$FarmPubDirUrl/guiedit');
|
||||
|
||||
SDVA($GUIButtons, array(
|
||||
'em' => array(100, "''", "''", '$[Emphasized]',
|
||||
'$GUIButtonDirUrlFmt/em.gif"$[Emphasized (italic)]"',
|
||||
'$[ak_em]'),
|
||||
'strong' => array(110, "'''", "'''", '$[Strong]',
|
||||
'$GUIButtonDirUrlFmt/strong.gif"$[Strong (bold)]"',
|
||||
'$[ak_strong]'),
|
||||
'pagelink' => array(200, '[[', ']]', '$[Page link]',
|
||||
'$GUIButtonDirUrlFmt/pagelink.gif"$[Link to internal page]"'),
|
||||
'extlink' => array(210, '[[', ']]', 'http:// | $[link text]',
|
||||
'$GUIButtonDirUrlFmt/extlink.gif"$[Link to external page]"'),
|
||||
'big' => array(300, "'+", "+'", '$[Big text]',
|
||||
'$GUIButtonDirUrlFmt/big.gif"$[Big text]"'),
|
||||
'small' => array(310, "'-", "-'", '$[Small text]',
|
||||
'$GUIButtonDirUrlFmt/small.gif"$[Small text]"'),
|
||||
'sup' => array(320, "'^", "^'", '$[Superscript]',
|
||||
'$GUIButtonDirUrlFmt/sup.gif"$[Superscript]"'),
|
||||
'sub' => array(330, "'_", "_'", '$[Subscript]',
|
||||
'$GUIButtonDirUrlFmt/sub.gif"$[Subscript]"'),
|
||||
'h2' => array(400, '\\n!! ', '\\n', '$[Heading]',
|
||||
'$GUIButtonDirUrlFmt/h.gif"$[Heading]"'),
|
||||
'center' => array(410, '%center%', '', '',
|
||||
'$GUIButtonDirUrlFmt/center.gif"$[Center]"')));
|
||||
|
||||
Markup_e('e_guibuttons', 'directives',
|
||||
'/\\(:e_guibuttons:\\)/',
|
||||
"Keep(FmtPageName(GUIButtonCode(\$pagename), \$pagename))");
|
||||
|
||||
function GUIButtonCode($pagename) {
|
||||
global $GUIButtons;
|
||||
$cmpfn = create_function('$a,$b', 'return $a[0]-$b[0];');
|
||||
usort($GUIButtons, $cmpfn);
|
||||
$out = "<script type='text/javascript'><!--\n";
|
||||
foreach ($GUIButtons as $k => $g) {
|
||||
if (!$g) continue;
|
||||
@list($when, $mopen, $mclose, $mtext, $tag, $mkey) = $g;
|
||||
if ($tag{0} == '<') {
|
||||
$out .= "document.write(\"$tag\");\n";
|
||||
continue;
|
||||
}
|
||||
if (preg_match('/^(.*\\.(gif|jpg|png))("([^"]+)")?$/', $tag, $m)) {
|
||||
$title = (@$m[4] > '') ? "title='{$m[4]}'" : '';
|
||||
$tag = "<img src='{$m[1]}' $title style='border:0px;' />";
|
||||
}
|
||||
$mopen = str_replace(array('\\', "'"), array('\\\\', "\\\\'"), $mopen);
|
||||
$mclose = str_replace(array('\\', "'"), array('\\\\', "\\\\'"), $mclose);
|
||||
$mtext = str_replace(array('\\', "'"), array('\\\\', "\\\\'"), $mtext);
|
||||
$out .=
|
||||
"insButton(\"$mopen\", \"$mclose\", '$mtext', \"$tag\", \"$mkey\");\n";
|
||||
}
|
||||
$out .= '//--></script>';
|
||||
return $out;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2005 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file defines an alternate authentication scheme based on the
|
||||
HTTP Basic authentication protocol (i.e., the scheme used by default
|
||||
in PmWiki 1).
|
||||
*/
|
||||
|
||||
## If the webserver has already authenticated someone, then use
|
||||
## that identifier for our authorization id. We also disable
|
||||
## the use of the browser's Basic Auth form later, since it tends
|
||||
## to confuse webservers.
|
||||
if (IsEnabled($EnableRemoteUserAuth, 1) && @$_SERVER['REMOTE_USER']) {
|
||||
SDV($EnableHTTPBasicAuth, 0);
|
||||
SDV($AuthId, $_SERVER['REMOTE_USER']);
|
||||
}
|
||||
|
||||
## If the browser supplied a password, add that password to the
|
||||
## list of passwords used for authentication
|
||||
if (@$_SERVER['PHP_AUTH_PW'])
|
||||
SessionAuth($pagename, array('authpw'=>array($_SERVER['PHP_AUTH_PW'] => 1)));
|
||||
|
||||
|
||||
## $EnableHTTPBasicAuth tells PmWikiAuth to use the browser's
|
||||
## HTTP Basic protocol prompt instead of a form-based prompt.
|
||||
if (IsEnabled($EnableHTTPBasicAuth, 1))
|
||||
SDV($AuthPromptFmt, 'function:HTTPBasicAuthPrompt');
|
||||
|
||||
## HTTPBasicAuthPrompt replaces PmWikiAuth's form-based password
|
||||
## prompt with the browser-based HTTP Basic prompt.
|
||||
function HTTPBasicAuthPrompt($pagename) {
|
||||
global $AuthRealmFmt, $AuthDeniedFmt;
|
||||
SDV($AuthRealmFmt,$GLOBALS['WikiTitle']);
|
||||
SDV($AuthDeniedFmt,'A valid password is required to access this feature.');
|
||||
$realm=FmtPageName($AuthRealmFmt,$pagename);
|
||||
header("WWW-Authenticate: Basic realm=\"$realm\"");
|
||||
header("Status: 401 Unauthorized");
|
||||
header("HTTP-Status: 401 Unauthorized");
|
||||
PrintFmt($pagename,$AuthDeniedFmt);
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
PmWiki: http://www.pmwiki.org/wiki/PmWiki/
|
||||
Cookbook: http://www.pmwiki.org/wiki/Cookbook/
|
||||
Skins: http://www.pmwiki.org/wiki/Skins/
|
||||
Wiki: http://www.c2.com/cgi/wiki?
|
||||
UseMod: http://www.usemod.com/cgi-bin/wiki.pl?
|
||||
Meatball: http://www.usemod.com/cgi-bin/mb.pl?
|
||||
Wikipedia: http://en.wikipedia.org/wiki/
|
||||
PITS: http://www.pmwiki.org/wiki/PITS/
|
||||
PmL10n: http://www.pmwiki.org/wiki/Localization/
|
||||
Path:
|
||||
@@ -0,0 +1,124 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2007-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script implements "markup expressions" -- a method to
|
||||
do simple computations and manipulations from markup. The
|
||||
generic form of a markup expression is "{(func arg1 arg2)}",
|
||||
where the named function (held in the $MarkupExpr array)
|
||||
is called with arg1 and arg2 as arguments.
|
||||
|
||||
Markup expressions can be nested. For example, to strip
|
||||
off the first five characters and convert the remainder to
|
||||
lowercase, an author can write:
|
||||
|
||||
{(tolower (substr "HELLOWORLD" 5))} # produces "world"
|
||||
|
||||
Some "built-in" expressions defined by this recipe include:
|
||||
substr - extract a portion of a string
|
||||
ftime - date/time formatting
|
||||
strlen - length of a string
|
||||
rand - generate a random number
|
||||
pagename - build a pagename from a string
|
||||
toupper - convert string to uppercase
|
||||
tolower - convert string to lowercase
|
||||
ucfirst - convert first character to uppercase
|
||||
ucwords - convert first character of each word to uppercase
|
||||
asspaced - spaceformatting of wikiwords
|
||||
|
||||
Custom expressions may be added by other recipes by adding
|
||||
entries into the $MarkupExpr array. Each entry's key is
|
||||
the name of the function, the value is the code to be evaluated
|
||||
for that function (similar to the way $FmtPV works). By default,
|
||||
any arguments for the expression are placed into the $args array:
|
||||
|
||||
## expressions like {(myfunc foo bar)}
|
||||
$MarkupExpr['myfunc'] = 'myfunc($args[0], $args[1])';
|
||||
|
||||
The expression arguments are parsed using ParseArgs(), and the
|
||||
result of this parsing is available through the $argp array:
|
||||
|
||||
## expressions like {(myfunc fmt=foo output=bar)}
|
||||
$MarkupExpr['myfunc'] = 'myfunc($argp["fmt"], $argp["output"])';
|
||||
|
||||
Finally, if the code in $MarkupExpr contains '$params', then
|
||||
it is executed directly without any preprocessing into arguments,
|
||||
and $params contains the entire argument string. Note that $params
|
||||
may contain escaped values representing quoted arguments and
|
||||
results of other expressions; these values may be un-escaped
|
||||
by using "preg_replace($rpat, $rrep, $params)".
|
||||
*/
|
||||
Markup_e('{(', '>{$var}',
|
||||
'/\\{(\\(\\w+\\b.*?\\))\\}/',
|
||||
"MarkupExpression(\$pagename, \$m[1])");
|
||||
|
||||
SDVA($MarkupExpr, array(
|
||||
'substr' => 'call_user_func_array("substr", $args)',
|
||||
'strlen' => 'strlen($args[0])',
|
||||
'ftime' => 'ME_ftime(@$args[0], @$args[1], $argp)',
|
||||
'rand' => '($args) ? rand($args[0], $args[1]) : rand()',
|
||||
'ucfirst' => 'ucfirst($args[0])',
|
||||
'ucwords' => 'ucwords($args[0])',
|
||||
'tolower' => 'strtolower($args[0])',
|
||||
'toupper' => 'strtoupper($args[0])',
|
||||
'mod' => '0 + ($args[0] % $args[1])',
|
||||
'asspaced' => '$GLOBALS["AsSpacedFunction"]($args[0])',
|
||||
'pagename' => 'MakePageName($pagename, PPRE($rpat, $rrep, $params))',
|
||||
));
|
||||
|
||||
function MarkupExpression($pagename, $expr) {
|
||||
global $KeepToken, $KPV, $MarkupExpr;
|
||||
$rpat = "/$KeepToken(\\d+P)$KeepToken/";
|
||||
$rrep = '$GLOBALS["KPV"][$m[1]]';
|
||||
$expr = PPRE('/([\'"])(.*?)\\1/', "Keep(\$m[2],'P')", $expr);
|
||||
$expr = PPRE('/\\(\\W/', "Keep(\$m[0],'P')", $expr);
|
||||
while (preg_match('/\\((\\w+)(\\s[^()]*)?\\)/', $expr, $match)) {
|
||||
list($repl, $func, $params) = $match;
|
||||
$code = @$MarkupExpr[$func];
|
||||
## if not a valid function, save this string as-is and exit
|
||||
if (!$code) break;
|
||||
## if the code uses '$params', we just evaluate directly
|
||||
if (strpos($code, '$params') !== false) {
|
||||
$out = eval("return ({$code});");
|
||||
if ($expr == $repl) { $expr = $out; break; }
|
||||
$expr = str_replace($repl, $out, $expr);
|
||||
continue;
|
||||
}
|
||||
## otherwise, we parse arguments into $args before evaluating
|
||||
$argp = ParseArgs($params);
|
||||
$x = $argp['#']; $args = array();
|
||||
while ($x) {
|
||||
list($k, $v) = array_splice($x, 0, 2);
|
||||
if ($k == '' || $k == '+' || $k == '-')
|
||||
$args[] = $k.PPRE($rpat, $rrep, $v);
|
||||
}
|
||||
## fix any quoted arguments
|
||||
foreach ($argp as $k => $v)
|
||||
if (!is_array($v)) $argp[$k] = PPRE($rpat, $rrep, $v);
|
||||
$out = eval("return ({$code});");
|
||||
if ($expr == $repl) { $expr = $out; break; }
|
||||
$expr = str_replace($repl, Keep($out, 'P'), $expr);
|
||||
}
|
||||
return PPRE($rpat, $rrep, $expr);
|
||||
}
|
||||
|
||||
## ME_ftime handles {(ftime ...)} expressions.
|
||||
##
|
||||
function ME_ftime($arg0 = '', $arg1 = '', $argp = NULL) {
|
||||
global $TimeFmt, $Now, $FTimeFmt;
|
||||
if (@$argp['fmt']) $fmt = $argp['fmt'];
|
||||
else if (strpos($arg0, '%') !== false) { $fmt = $arg0; $arg0 = $arg1; }
|
||||
else if (strpos($arg1, '%') !== false) $fmt = $arg1;
|
||||
## determine the timestamp
|
||||
if (isset($argp['when'])) list($time, $x) = DRange($argp['when']);
|
||||
else if ($arg0 > '') list($time, $x) = DRange($arg0);
|
||||
else $time = $Now;
|
||||
if (@$fmt == '') { SDV($FTimeFmt, $TimeFmt); $fmt = $FTimeFmt; }
|
||||
## make sure we have %F available for ISO dates
|
||||
$fmt = str_replace(array('%F', '%s'), array('%Y-%m-%d', $time), $fmt);
|
||||
return strftime($fmt, $time);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2006-2011 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script enables email notifications to be sent when posts
|
||||
are made. It is included by default from the stdconfig.php
|
||||
script if $EnableNotify is set to non-zero.
|
||||
|
||||
Once enabled, the addresses to receive messages are configured
|
||||
via the Site.NotifyList page. A simple line in that page
|
||||
such as
|
||||
|
||||
notify=somebody@example.com
|
||||
|
||||
will cause messages to be periodically sent to "somebody@example.com"
|
||||
listing the pages that have changed on the site since the previous
|
||||
message was sent. Multiple notify lines can be placed in the page,
|
||||
and there are options to restrict the types of notifications
|
||||
desired. For more details, see the PmWiki.Notify page in
|
||||
the documentation.
|
||||
|
||||
Several variables set defaults for this script:
|
||||
|
||||
$NotifyFrom - return email address to use in message.
|
||||
$NotifyDelay - number of seconds to wait before sending mail
|
||||
after the first post.
|
||||
$NotifySquelch - minimum number of seconds between sending email
|
||||
messages to each address. Individual "notify=" lines in
|
||||
Site.NotifyList can override this value via a custom "squelch="
|
||||
parameter.
|
||||
$NotifyFile - scratchpad file used to keep track of pending emails.
|
||||
$NotifyListPageFmt - name of the NotifyList configuration page.
|
||||
$NotifySubjectFmt - subject line for sent messages.
|
||||
$NotifyBodyFmt - body of message to be sent. The string '$NotifyItems'
|
||||
is replaced with the list of posts in the email.
|
||||
$NotifyItemFmt - the format for each post to be included in a notification.
|
||||
$NotifyTimeFmt - the format for dates and times ($PostTime)
|
||||
in notification messages.
|
||||
$NotifyHeaders - any additional message headers to be sent.
|
||||
$NotifyParameters - any additional parameters to be passed to PHP's
|
||||
mail() function.
|
||||
*/
|
||||
|
||||
SDV($NotifyDelay, 0);
|
||||
SDV($NotifySquelch, 10800);
|
||||
SDV($NotifyFile, "$WorkDir/.notifylist");
|
||||
SDV($NotifyListPageFmt, '$SiteAdminGroup.NotifyList');
|
||||
SDV($NotifySubjectFmt, '[$WikiTitle] recent notify posts');
|
||||
SDV($NotifyBodyFmt,
|
||||
"Recent \$WikiTitle posts:\n"
|
||||
. " \$ScriptUrl/$[{\$SiteGroup}/AllRecentChanges]\n\n\$NotifyItems\n");
|
||||
SDV($NotifyTimeFmt, $TimeFmt);
|
||||
SDV($NotifyItemFmt,
|
||||
' * {$FullName} . . . $PostTime by {$Author}');
|
||||
SDV($NotifyHeaders, '');
|
||||
SDV($NotifyParameters, '');
|
||||
|
||||
if (@$NotifyFrom)
|
||||
$NotifyHeaders = "From: $NotifyFrom\r\n$NotifyHeaders";
|
||||
|
||||
$EditFunctions[] = 'PostNotify';
|
||||
|
||||
## check if we need to do notifications
|
||||
if ($action != 'edit' && $action != 'postupload') NotifyCheck($pagename);
|
||||
|
||||
|
||||
function NotifyCheck($pagename) {
|
||||
global $NotifyFile, $Now, $LastModTime;
|
||||
$nfp = @fopen($NotifyFile, 'r');
|
||||
if (!$nfp) return;
|
||||
$nextevent = fgets($nfp);
|
||||
fclose($nfp);
|
||||
if ($Now < $nextevent && $LastModTime < filemtime($NotifyFile)) return;
|
||||
register_shutdown_function('NotifyUpdate', $pagename, getcwd());
|
||||
}
|
||||
|
||||
|
||||
function PostNotify($pagename, &$page, &$new) {
|
||||
global $IsPagePosted;
|
||||
if ($IsPagePosted)
|
||||
register_shutdown_function('NotifyUpdate', $pagename, getcwd());
|
||||
}
|
||||
|
||||
|
||||
function NotifyUpdate($pagename, $dir='') {
|
||||
global $NotifyList, $NotifyListPageFmt, $NotifyFile, $IsPagePosted, $IsUploadPosted,
|
||||
$FmtV, $NotifyTimeFmt, $NotifyItemFmt, $SearchPatterns,
|
||||
$NotifySquelch, $NotifyDelay, $Now, $Charset, $EnableNotifySubjectEncode,
|
||||
$NotifySubjectFmt, $NotifyBodyFmt, $NotifyHeaders, $NotifyParameters;
|
||||
|
||||
$abort = ignore_user_abort(true);
|
||||
if ($dir) { flush(); chdir($dir); }
|
||||
|
||||
$GLOBALS['EnableRedirect'] = 0;
|
||||
|
||||
## Read in the current notify configuration
|
||||
$pn = FmtPageName($NotifyListPageFmt, $pagename);
|
||||
$npage = ReadPage($pn, READPAGE_CURRENT);
|
||||
preg_match_all('/^[\s*:#->]*(notify[:=].*)/m', $npage['text'], $nlist);
|
||||
$nlist = array_merge((array)@$NotifyList, (array)@$nlist[1]);
|
||||
if (!$nlist) return;
|
||||
|
||||
## make sure other processes are locked out
|
||||
Lock(2);
|
||||
|
||||
## let's load the current .notifylist table
|
||||
$nfile = FmtPageName($NotifyFile, $pagename);
|
||||
$nfp = @fopen($nfile, 'r');
|
||||
if ($nfp) {
|
||||
## get our current squelch and delay timestamps
|
||||
clearstatcache();
|
||||
$sz = filesize($nfile);
|
||||
list($nextevent, $firstpost) = explode(' ', rtrim(fgets($nfp, $sz)));
|
||||
## restore our notify array
|
||||
$notify = unserialize(fgets($nfp, $sz));
|
||||
fclose($nfp);
|
||||
}
|
||||
if (!is_array($notify)) $notify = array();
|
||||
|
||||
## if this is for a newly posted page, get its information
|
||||
if ($IsPagePosted || $IsUploadPosted) {
|
||||
$page = ReadPage($pagename, READPAGE_CURRENT);
|
||||
$FmtV['$PostTime'] = strftime($NotifyTimeFmt, $Now);
|
||||
$item = urlencode(FmtPageName($NotifyItemFmt, $pagename));
|
||||
if ($firstpost < 1) $firstpost = $Now;
|
||||
}
|
||||
|
||||
foreach($nlist as $n) {
|
||||
$opt = ParseArgs($n);
|
||||
$mailto = preg_split('/[\s,]+/', $opt['notify']);
|
||||
if (!$mailto) continue;
|
||||
if ($opt['squelch'])
|
||||
foreach($mailto as $m) $squelch[$m] = $opt['squelch'];
|
||||
if (!$IsPagePosted) continue;
|
||||
if ($opt['link']) {
|
||||
$link = MakePageName($pagename, $opt['link']);
|
||||
if (!preg_match("/(^|,)$link(,|$)/i", $page['targets'])) continue;
|
||||
}
|
||||
$pats = @(array)$SearchPatterns[$opt['list']];
|
||||
if ($opt['group']) $pats[] = FixGlob($opt['group'], '$1$2.*');
|
||||
if ($opt['name']) $pats[] = FixGlob($opt['name'], '$1*.$2');
|
||||
if ($pats && !MatchPageNames($pagename, $pats)) continue;
|
||||
if ($opt['trail']) {
|
||||
$trail = ReadTrail($pagename, $opt['trail']);
|
||||
for ($i=0; $i<count($trail); $i++)
|
||||
if ($trail[$i]['pagename'] == $pagename) break;
|
||||
if ($i >= count($trail)) continue;
|
||||
}
|
||||
foreach($mailto as $m) { $notify[$m][] = $item; }
|
||||
}
|
||||
|
||||
$nnow = time();
|
||||
if ($nnow < $firstpost + $NotifyDelay)
|
||||
$nextevent = $firstpost + $NotifyDelay;
|
||||
else {
|
||||
$firstpost = 0;
|
||||
$nextevent = $nnow + 86400;
|
||||
$mailto = array_keys($notify);
|
||||
$subject = FmtPageName($NotifySubjectFmt, $pagename);
|
||||
if(IsEnabled($EnableNotifySubjectEncode, 0)
|
||||
&& preg_match("/[^\x20-\x7E]/", $subject))
|
||||
$subject = strtoupper("=?$Charset?B?"). base64_encode($subject)."?=";
|
||||
$body = FmtPageName($NotifyBodyFmt, $pagename);
|
||||
foreach ($mailto as $m) {
|
||||
$msquelch = @$notify[$m]['lastmail'] +
|
||||
((@$squelch[$m]) ? $squelch[$m] : $NotifySquelch);
|
||||
if ($nnow < $msquelch) {
|
||||
if ($msquelch < $nextevent && count($notify[$m])>1)
|
||||
$nextevent = $msquelch;
|
||||
continue;
|
||||
}
|
||||
unset($notify[$m]['lastmail']);
|
||||
if (!$notify[$m]) { unset($notify[$m]); continue; }
|
||||
$mbody = str_replace('$NotifyItems',
|
||||
urldecode(implode("\n", $notify[$m])), $body);
|
||||
if ($NotifyParameters && !@ini_get('safe_mode'))
|
||||
mail($m, $subject, $mbody, $NotifyHeaders, $NotifyParameters);
|
||||
else
|
||||
mail($m, $subject, $mbody, $NotifyHeaders);
|
||||
$notify[$m] = array('lastmail' => $nnow);
|
||||
}
|
||||
}
|
||||
|
||||
## save the updated notify status
|
||||
$nfp = @fopen($nfile, "w");
|
||||
if ($nfp) {
|
||||
fputs($nfp, "$nextevent $firstpost\n");
|
||||
fputs($nfp, serialize($notify) . "\n");
|
||||
fclose($nfp);
|
||||
}
|
||||
Lock(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,856 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script implements (:pagelist:) and friends -- it's one
|
||||
of the nastiest scripts you'll ever encounter. Part of the reason
|
||||
for this is that page listings are so powerful and flexible, so
|
||||
that adds complexity. They're also expensive, so we have to
|
||||
optimize them wherever we can.
|
||||
|
||||
The core function is FmtPageList(), which will generate a
|
||||
listing according to a wide variety of options. FmtPageList takes
|
||||
care of initial option processing, and then calls a "FPL"
|
||||
(format page list) function to obtain the formatted output.
|
||||
The FPL function is chosen by the 'fmt=' option to (:pagelist:).
|
||||
|
||||
Each FPL function calls MakePageList() to obtain the list
|
||||
of pages, formats the list somehow, and returns the results
|
||||
to FmtPageList. FmtPageList then returns the output to
|
||||
the caller, and calls Keep() (preserves HTML) or PRR() (re-evaluate
|
||||
as markup) as appropriate for the output being returned.
|
||||
*/
|
||||
|
||||
## $PageIndexFile is the index file for term searches and link= option
|
||||
if (IsEnabled($EnablePageIndex, 1)) {
|
||||
SDV($PageIndexFile, "$WorkDir/.pageindex");
|
||||
$EditFunctions[] = 'PostPageIndex';
|
||||
}
|
||||
|
||||
SDV($StrFoldFunction, 'strtolower');
|
||||
|
||||
## $SearchPatterns holds patterns for list= option
|
||||
SDV($SearchPatterns['all'], array());
|
||||
SDVA($SearchPatterns['normal'], array(
|
||||
'recent' => '!\.(All)?Recent(Changes|Uploads)$!',
|
||||
'group' => '!\.Group(Print)?(Header|Footer|Attributes)$!',
|
||||
'self' => str_replace('.', '\\.', "!^$pagename$!")));
|
||||
|
||||
## $FPLFormatOpt is a list of options associated with fmt=
|
||||
## values. 'default' is used for any undefined values of fmt=.
|
||||
SDVA($FPLFormatOpt, array(
|
||||
'default' => array('fn' => 'FPLTemplate', 'fmt' => '#default'),
|
||||
'bygroup' => array('fn' => 'FPLTemplate', 'template' => '#bygroup',
|
||||
'class' => 'fplbygroup'),
|
||||
'simple' => array('fn' => 'FPLTemplate', 'template' => '#simple',
|
||||
'class' => 'fplsimple'),
|
||||
'group' => array('fn' => 'FPLTemplate', 'template' => '#group',
|
||||
'class' => 'fplgroup'),
|
||||
'title' => array('fn' => 'FPLTemplate', 'template' => '#title',
|
||||
'class' => 'fpltitle', 'order' => 'title'),
|
||||
'count' => array('fn' => 'FPLCountA'),
|
||||
));
|
||||
|
||||
SDV($SearchResultsFmt, "<div class='wikisearch'>\$[SearchFor]
|
||||
<div class='vspace'></div>\$MatchList
|
||||
<div class='vspace'></div>\$[SearchFound]</div>");
|
||||
SDV($SearchQuery, str_replace('$', '$',
|
||||
PHSC(stripmagic(@$_REQUEST['q']), ENT_NOQUOTES)));
|
||||
XLSDV('en', array(
|
||||
'SearchFor' => 'Results of search for <em>$Needle</em>:',
|
||||
'SearchFound' =>
|
||||
'$MatchCount pages found out of $MatchSearched pages searched.'));
|
||||
|
||||
SDV($PageListArgPattern, '((?:\\$:?)?\\w+)[:=]');
|
||||
|
||||
Markup_e('pagelist', 'directives',
|
||||
'/\\(:pagelist(\\s+.*?)?:\\)/i',
|
||||
"FmtPageList('\$MatchList', \$pagename, array('o' => \$m[1].' '))");
|
||||
Markup_e('searchbox', 'directives',
|
||||
'/\\(:searchbox(\\s.*?)?:\\)/',
|
||||
"SearchBox(\$pagename, ParseArgs(\$m[1], '$PageListArgPattern'))");
|
||||
Markup_e('searchresults', 'directives',
|
||||
'/\\(:searchresults(\\s+.*?)?:\\)/i',
|
||||
"FmtPageList(\$GLOBALS['SearchResultsFmt'], \$pagename,
|
||||
array('req' => 1, 'request'=>1, 'o' => \$m[1]))");
|
||||
|
||||
SDV($SaveAttrPatterns['/\\(:(searchresults|pagelist)(\\s+.*?)?:\\)/i'], ' ');
|
||||
|
||||
SDV($HandleActions['search'], 'HandleSearchA');
|
||||
SDV($HandleAuth['search'], 'read');
|
||||
SDV($ActionTitleFmt['search'], '| $[Search Results]');
|
||||
|
||||
SDVA($PageListFilters, array(
|
||||
'PageListCache' => 80,
|
||||
'PageListProtect' => 90,
|
||||
'PageListSources' => 100,
|
||||
'PageListPasswords' => 120,
|
||||
'PageListIf' => 140,
|
||||
'PageListTermsTargets' => 160,
|
||||
'PageListVariables' => 180,
|
||||
'PageListSort' => 900,
|
||||
));
|
||||
|
||||
foreach(array('random', 'size', 'time', 'ctime') as $o)
|
||||
SDV($PageListSortCmp[$o], "@(\$PCache[\$x]['$o']-\$PCache[\$y]['$o'])");
|
||||
SDV($PageListSortCmp['title'],
|
||||
'@strcasecmp($PCache[$x][\'=title\'], $PCache[$y][\'=title\'])');
|
||||
|
||||
define('PAGELIST_PRE' , 1);
|
||||
define('PAGELIST_ITEM', 2);
|
||||
define('PAGELIST_POST', 4);
|
||||
|
||||
## SearchBox generates the output of the (:searchbox:) markup.
|
||||
## If $SearchBoxFmt is defined, that is used, otherwise a searchbox
|
||||
## is generated. Options include group=, size=, label=.
|
||||
function SearchBox($pagename, $opt) {
|
||||
global $SearchBoxFmt, $SearchBoxOpt, $SearchQuery, $EnablePathInfo;
|
||||
if (isset($SearchBoxFmt)) return Keep(FmtPageName($SearchBoxFmt, $pagename));
|
||||
SDVA($SearchBoxOpt, array('size' => '40',
|
||||
'label' => FmtPageName('$[Search]', $pagename),
|
||||
'value' => str_replace("'", "'", $SearchQuery)));
|
||||
$opt = array_merge((array)$SearchBoxOpt, @$_GET, (array)$opt);
|
||||
$opt['action'] = 'search';
|
||||
$target = (@$opt['target'])
|
||||
? MakePageName($pagename, $opt['target']) : $pagename;
|
||||
$opt['n'] = IsEnabled($EnablePathInfo, 0) ? '' : $target;
|
||||
$out = FmtPageName(" class='wikisearch' action='\$PageUrl' method='get'>",
|
||||
$target);
|
||||
foreach($opt as $k => $v) {
|
||||
if ($v == '' || is_array($v)) continue;
|
||||
$v = str_replace("'", "'", $v);
|
||||
$opt[$k] = $v;
|
||||
if ($k == 'q' || $k == 'label' || $k == 'value' || $k == 'size') continue;
|
||||
$k = str_replace("'", "'", $k);
|
||||
$out .= "<input type='hidden' name='$k' value='$v' />";
|
||||
}
|
||||
$out .= "<input type='text' name='q' value='{$opt['value']}'
|
||||
class='inputbox searchbox' size='{$opt['size']}' /><input type='submit'
|
||||
class='inputbutton searchbutton' value='{$opt['label']}' />";
|
||||
return '<form '.Keep($out).'</form>';
|
||||
}
|
||||
|
||||
|
||||
## FmtPageList combines options from markup, request form, and url,
|
||||
## calls the appropriate formatting function, and returns the string.
|
||||
function FmtPageList($outfmt, $pagename, $opt) {
|
||||
global $GroupPattern, $FmtV, $PageListArgPattern,
|
||||
$FPLFormatOpt, $FPLFunctions;
|
||||
# get any form or url-submitted request
|
||||
$rq = PHSC(stripmagic(@$_REQUEST['q']), ENT_NOQUOTES);
|
||||
# build the search string
|
||||
$FmtV['$Needle'] = $opt['o'] . ' ' . $rq;
|
||||
# Handle "group/" at the beginning of the form-submitted request
|
||||
if (preg_match("!^($GroupPattern(\\|$GroupPattern)*)?/!i", $rq, $match)) {
|
||||
$opt['group'] = @$match[1];
|
||||
$rq = substr($rq, strlen(@$match[1])+1);
|
||||
}
|
||||
$opt = array_merge($opt, ParseArgs($opt['o'], $PageListArgPattern));
|
||||
# merge markup options with form and url
|
||||
if (@$opt['request'] && @$_REQUEST) {
|
||||
$rkeys = preg_grep('/^=/', array_keys($_REQUEST), PREG_GREP_INVERT);
|
||||
if ($opt['request'] != '1') {
|
||||
list($incl, $excl) = GlobToPCRE($opt['request']);
|
||||
if ($excl) $rkeys = array_diff($rkeys, preg_grep("/$excl/", $rkeys));
|
||||
if ($incl) $rkeys = preg_grep("/$incl/", $rkeys);
|
||||
}
|
||||
$cleanrequest = array();
|
||||
foreach($rkeys as $k) {
|
||||
$cleanrequest[$k] = stripmagic($_REQUEST[$k]);
|
||||
}
|
||||
$opt = array_merge($opt, ParseArgs($rq, $PageListArgPattern), $cleanrequest);
|
||||
}
|
||||
|
||||
# non-posted blank search requests return nothing
|
||||
if (@($opt['req'] && !$opt['-'] && !$opt[''] && !$opt['+'] && !$opt['q']))
|
||||
return '';
|
||||
# terms and group to be included and excluded
|
||||
$GLOBALS['SearchIncl'] = array_merge((array)@$opt[''], (array)@$opt['+']);
|
||||
$GLOBALS['SearchExcl'] = (array)@$opt['-'];
|
||||
$GLOBALS['SearchGroup'] = @$opt['group'];
|
||||
$fmt = @$opt['fmt']; if (!$fmt) $fmt = 'default';
|
||||
$fmtopt = @$FPLFormatOpt[$fmt];
|
||||
if (!is_array($fmtopt)) {
|
||||
if ($fmtopt) $fmtopt = array('fn' => $fmtopt);
|
||||
elseif (@$FPLFunctions[$fmt])
|
||||
$fmtopt = array('fn' => $FPLFunctions[$fmt]);
|
||||
else $fmtopt = $FPLFormatOpt['default'];
|
||||
}
|
||||
$fmtfn = @$fmtopt['fn'];
|
||||
if (!is_callable($fmtfn)) $fmtfn = $FPLFormatOpt['default']['fn'];
|
||||
$matches = array();
|
||||
$opt = array_merge($fmtopt, $opt);
|
||||
$out = $fmtfn($pagename, $matches, $opt);
|
||||
$FmtV['$MatchCount'] = count($matches);
|
||||
if ($outfmt != '$MatchList')
|
||||
{ $FmtV['$MatchList'] = $out; $out = FmtPageName($outfmt, $pagename); }
|
||||
if ($out[0] == '<') $out = Keep($out);
|
||||
return PRR($out);
|
||||
}
|
||||
|
||||
|
||||
## MakePageList generates a list of pages using the specifications given
|
||||
## by $opt.
|
||||
function MakePageList($pagename, $opt, $retpages = 1) {
|
||||
global $MakePageListOpt, $PageListFilters, $PCache;
|
||||
|
||||
StopWatch('MakePageList pre');
|
||||
SDVA($MakePageListOpt, array('list' => 'default'));
|
||||
$opt = array_merge((array)$MakePageListOpt, (array)$opt);
|
||||
if (!@$opt['order'] && !@$opt['trail']) $opt['order'] = 'name';
|
||||
$opt['order'] = preg_replace('/[^-\\w:$]+/', ',', $opt['order']);
|
||||
|
||||
ksort($opt); $opt['=key'] = md5(serialize($opt));
|
||||
|
||||
$itemfilters = array(); $postfilters = array();
|
||||
asort($PageListFilters);
|
||||
$opt['=phase'] = PAGELIST_PRE; $list=array(); $pn=NULL; $page=NULL;
|
||||
foreach($PageListFilters as $fn => $v) {
|
||||
if ($v<0) continue;
|
||||
$ret = $fn($list, $opt, $pagename, $page);
|
||||
if ($ret & PAGELIST_ITEM) $itemfilters[] = $fn;
|
||||
if ($ret & PAGELIST_POST) $postfilters[] = $fn;
|
||||
}
|
||||
|
||||
StopWatch("MakePageList items count=".count($list).", filters=".implode(',',$itemfilters));
|
||||
$opt['=phase'] = PAGELIST_ITEM;
|
||||
$matches = array(); $opt['=readc'] = 0;
|
||||
foreach((array)$list as $pn) {
|
||||
$page = array();
|
||||
foreach((array)$itemfilters as $fn)
|
||||
if (!$fn($list, $opt, $pn, $page)) continue 2;
|
||||
$page['pagename'] = $page['name'] = $pn;
|
||||
PCache($pn, $page);
|
||||
$matches[] = $pn;
|
||||
}
|
||||
$list = $matches;
|
||||
StopWatch("MakePageList post count=".count($list).", readc={$opt['=readc']}");
|
||||
|
||||
$opt['=phase'] = PAGELIST_POST; $pn=NULL; $page=NULL;
|
||||
foreach((array)$postfilters as $fn)
|
||||
$fn($list, $opt, $pagename, $page);
|
||||
|
||||
if ($retpages)
|
||||
for($i=0; $i<count($list); $i++)
|
||||
$list[$i] = &$PCache[$list[$i]];
|
||||
StopWatch('MakePageList end');
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
||||
function PageListProtect(&$list, &$opt, $pn, &$page) {
|
||||
global $EnablePageListProtect;
|
||||
|
||||
switch ($opt['=phase']) {
|
||||
case PAGELIST_PRE:
|
||||
if (!IsEnabled($EnablePageListProtect, 1) && @$opt['readf'] < 1000)
|
||||
return 0;
|
||||
StopWatch("PageListProtect enabled");
|
||||
$opt['=protectexclude'] = array();
|
||||
$opt['=protectsafe'] = (array)@$opt['=protectsafe'];
|
||||
return PAGELIST_ITEM|PAGELIST_POST;
|
||||
|
||||
case PAGELIST_ITEM:
|
||||
if (@$opt['=protectsafe'][$pn]) return 1;
|
||||
$page = RetrieveAuthPage($pn, 'ALWAYS', false, READPAGE_CURRENT);
|
||||
$opt['=readc']++;
|
||||
if (!$page['=auth']['read']) $opt['=protectexclude'][$pn] = 1;
|
||||
if (!$page['=passwd']['read']) $opt['=protectsafe'][$pn] = 1;
|
||||
else NoCache();
|
||||
return 1;
|
||||
|
||||
case PAGELIST_POST:
|
||||
$excl = array_keys($opt['=protectexclude']);
|
||||
$safe = array_keys($opt['=protectsafe']);
|
||||
StopWatch("PageListProtect excluded=" .count($excl)
|
||||
. ", safe=" . count($safe));
|
||||
$list = array_diff($list, $excl);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function PageListSources(&$list, &$opt, $pn, &$page) {
|
||||
global $SearchPatterns;
|
||||
|
||||
StopWatch('PageListSources begin');
|
||||
## add the list= option to our list of pagename filter patterns
|
||||
$opt['=pnfilter'] = array_merge((array)@$opt['=pnfilter'],
|
||||
(array)@$SearchPatterns[$opt['list']]);
|
||||
|
||||
if (@$opt['group']) $opt['=pnfilter'][] = FixGlob($opt['group'], '$1$2.*');
|
||||
if (@$opt['name']) $opt['=pnfilter'][] = FixGlob($opt['name'], '$1*.$2');
|
||||
|
||||
if (@$opt['trail']) {
|
||||
$trail = ReadTrail($pn, $opt['trail']);
|
||||
$tlist = array();
|
||||
foreach($trail as $tstop) {
|
||||
$n = $tstop['pagename'];
|
||||
$tlist[] = $n;
|
||||
$tstop['parentnames'] = array();
|
||||
PCache($n, $tstop);
|
||||
}
|
||||
foreach($trail as $tstop)
|
||||
$PCache[$tstop['pagename']]['parentnames'][] =
|
||||
@$trail[$tstop['parent']]['pagename'];
|
||||
if (!@$opt['=cached']) $list = MatchPageNames($tlist, $opt['=pnfilter']);
|
||||
} else if (!@$opt['=cached']) $list = ListPages($opt['=pnfilter']);
|
||||
StopWatch("PageListSources end count=".count($list));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function PageListPasswords(&$list, &$opt, $pn, &$page) {
|
||||
if ($opt['=phase'] == PAGELIST_PRE)
|
||||
return (@$opt['passwd'] > '' && !@$opt['=cached']) ? PAGELIST_ITEM : 0;
|
||||
|
||||
if (!$page) { $page = ReadPage($pn, READPAGE_CURRENT); $opt['=readc']++; }
|
||||
if (!$page) return 0;
|
||||
return (boolean)preg_grep('/^passwd/', array_keys($page));
|
||||
}
|
||||
|
||||
|
||||
function PageListIf(&$list, &$opt, $pn, &$page) {
|
||||
global $Conditions, $Cursor;
|
||||
|
||||
## See if we have any "if" processing to perform
|
||||
if ($opt['=phase'] == PAGELIST_PRE)
|
||||
return (@$opt['if'] > '') ? PAGELIST_ITEM : 0;
|
||||
|
||||
$condspec = $opt['if'];
|
||||
$Cursor['='] = $pn;
|
||||
$varpat = '\\{([=*]|!?[-\\w.\\/\\x80-\\xff]*)(\\$:?\\w+)\\}';
|
||||
while (preg_match("/$varpat/", $condspec, $match)) {
|
||||
$condspec = PPRE("/$varpat/",
|
||||
"PVSE(PageVar('$pn', \$m[2], \$m[1]))", $condspec);
|
||||
}
|
||||
if (!preg_match("/^\\s*(!?)\\s*(\\S*)\\s*(.*?)\\s*$/", $condspec, $match))
|
||||
return 0;
|
||||
list($x, $not, $condname, $condparm) = $match;
|
||||
if (!isset($Conditions[$condname])) return 1;
|
||||
$tf = (int)@eval("return ({$Conditions[$condname]});");
|
||||
return (boolean)($tf xor $not);
|
||||
}
|
||||
|
||||
|
||||
function PageListTermsTargets(&$list, &$opt, $pn, &$page) {
|
||||
global $FmtV;
|
||||
static $reindex = array();
|
||||
$fold = $GLOBALS['StrFoldFunction'];
|
||||
|
||||
switch ($opt['=phase']) {
|
||||
case PAGELIST_PRE:
|
||||
$FmtV['$MatchSearched'] = count($list);
|
||||
$incl = array(); $excl = array();
|
||||
foreach((array)@$opt[''] as $i) { $incl[] = $fold($i); }
|
||||
foreach((array)@$opt['+'] as $i) { $incl[] = $fold($i); }
|
||||
foreach((array)@$opt['-'] as $i) { $excl[] = $fold($i); }
|
||||
|
||||
$indexterms = PageIndexTerms($incl);
|
||||
foreach($incl as $i) {
|
||||
$delim = (!preg_match('/[^\\w\\x80-\\xff]/', $i)) ? '$' : '/';
|
||||
$opt['=inclp'][] = $delim . preg_quote($i,$delim) . $delim . 'i';
|
||||
}
|
||||
if ($excl)
|
||||
$opt['=exclp'][] = '$'.implode('|', array_map('preg_quote',$excl)).'$i';
|
||||
|
||||
if (@$opt['link']) {
|
||||
$link = MakePageName($pn, $opt['link']);
|
||||
$opt['=linkp'] = "/(^|,)$link(,|$)/i";
|
||||
$indexterms[] = " $link ";
|
||||
}
|
||||
|
||||
if (@$opt['=cached']) return 0;
|
||||
if ($indexterms) {
|
||||
StopWatch("PageListTermsTargets begin count=".count($list));
|
||||
$xlist = PageIndexGrep($indexterms, true);
|
||||
$list = array_diff($list, $xlist);
|
||||
StopWatch("PageListTermsTargets end count=".count($list));
|
||||
}
|
||||
|
||||
if (@$opt['=inclp'] || @$opt['=exclp'] || @$opt['=linkp'])
|
||||
return PAGELIST_ITEM|PAGELIST_POST;
|
||||
return 0;
|
||||
|
||||
case PAGELIST_ITEM:
|
||||
if (!$page) { $page = ReadPage($pn, READPAGE_CURRENT); $opt['=readc']++; }
|
||||
if (!$page) return 0;
|
||||
if (@$opt['=linkp'] && !preg_match($opt['=linkp'], @$page['targets']))
|
||||
{ $reindex[] = $pn; return 0; }
|
||||
if (@$opt['=inclp'] || @$opt['=exclp']) {
|
||||
$text = $fold($pn."\n".@$page['targets']."\n".@$page['text']);
|
||||
foreach((array)@$opt['=exclp'] as $i)
|
||||
if (preg_match($i, $text)) return 0;
|
||||
foreach((array)@$opt['=inclp'] as $i)
|
||||
if (!preg_match($i, $text)) {
|
||||
if ($i{0} == '$') $reindex[] = $pn;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
case PAGELIST_POST:
|
||||
if ($reindex) PageIndexQueueUpdate($reindex);
|
||||
$reindex = array();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function PageListVariables(&$list, &$opt, $pn, &$page) {
|
||||
switch ($opt['=phase']) {
|
||||
case PAGELIST_PRE:
|
||||
$varlist = preg_grep('/^\\$/', array_keys($opt));
|
||||
if (!$varlist) return 0;
|
||||
foreach($varlist as $v) {
|
||||
list($inclp, $exclp) = GlobToPCRE($opt[$v]);
|
||||
if ($inclp) $opt['=varinclp'][$v] = "/$inclp/i";
|
||||
if ($exclp) $opt['=varexclp'][$v] = "/$exclp/i";
|
||||
}
|
||||
return PAGELIST_ITEM;
|
||||
|
||||
case PAGELIST_ITEM:
|
||||
if (@$opt['=varinclp'])
|
||||
foreach($opt['=varinclp'] as $v => $pat)
|
||||
if (!preg_match($pat, PageVar($pn, $v))) return 0;
|
||||
if (@$opt['=varexclp'])
|
||||
foreach($opt['=varexclp'] as $v => $pat)
|
||||
if (preg_match($pat, PageVar($pn, $v))) return 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function PageListSort(&$list, &$opt, $pn, &$page) {
|
||||
global $PageListSortCmp, $PCache, $PageListSortRead;
|
||||
SDVA($PageListSortRead, array('name' => 0, 'group' => 0, 'random' => 0,
|
||||
'title' => 0));
|
||||
|
||||
switch ($opt['=phase']) {
|
||||
case PAGELIST_PRE:
|
||||
$ret = 0;
|
||||
foreach(preg_split('/[^-\\w:$]+/', @$opt['order'], -1, PREG_SPLIT_NO_EMPTY)
|
||||
as $o) {
|
||||
$ret |= PAGELIST_POST;
|
||||
$r = '+';
|
||||
if ($o{0} == '-') { $r = '-'; $o = substr($o, 1); }
|
||||
$opt['=order'][$o] = $r;
|
||||
if ($o{0} != '$' &&
|
||||
(!isset($PageListSortRead[$o]) || $PageListSortRead[$o]))
|
||||
$ret |= PAGELIST_ITEM;
|
||||
}
|
||||
StopWatch(@"PageListSort pre ret=$ret order={$opt['order']}");
|
||||
return $ret;
|
||||
|
||||
case PAGELIST_ITEM:
|
||||
if (!$page) { $page = ReadPage($pn, READPAGE_CURRENT); $opt['=readc']++; }
|
||||
return 1;
|
||||
}
|
||||
|
||||
## case PAGELIST_POST
|
||||
StopWatch('PageListSort begin');
|
||||
$order = $opt['=order'];
|
||||
if (@$order['title'])
|
||||
foreach($list as $pn) $PCache[$pn]['=title'] = PageVar($pn, '$Title');
|
||||
if (@$order['group'])
|
||||
foreach($list as $pn) $PCache[$pn]['group'] = PageVar($pn, '$Group');
|
||||
if (@$order['random'])
|
||||
{ NoCache(); foreach($list as $pn) $PCache[$pn]['random'] = rand(); }
|
||||
foreach(preg_grep('/^\\$/', array_keys($order)) as $o)
|
||||
foreach($list as $pn)
|
||||
$PCache[$pn][$o] = PageVar($pn, $o);
|
||||
$code = '';
|
||||
foreach($opt['=order'] as $o => $r) {
|
||||
if (@$PageListSortCmp[$o])
|
||||
$code .= "\$c = {$PageListSortCmp[$o]}; ";
|
||||
else
|
||||
$code .= "\$c = @strcasecmp(\$PCache[\$x]['$o'],\$PCache[\$y]['$o']); ";
|
||||
$code .= "if (\$c) return $r\$c;\n";
|
||||
}
|
||||
StopWatch('PageListSort sort');
|
||||
if ($code)
|
||||
uasort($list,
|
||||
create_function('$x,$y', "global \$PCache; $code return 0;"));
|
||||
StopWatch('PageListSort end');
|
||||
}
|
||||
|
||||
|
||||
function PageListCache(&$list, &$opt, $pn, &$page) {
|
||||
global $PageListCacheDir, $LastModTime, $PageIndexFile;
|
||||
|
||||
if (@!$PageListCacheDir) return 0;
|
||||
if (isset($opt['cache']) && !$opt['cache']) return 0;
|
||||
|
||||
$key = $opt['=key'];
|
||||
$cache = "$PageListCacheDir/$key,cache";
|
||||
switch ($opt['=phase']) {
|
||||
case PAGELIST_PRE:
|
||||
if (!file_exists($cache) || filemtime($cache) <= $LastModTime)
|
||||
return PAGELIST_POST;
|
||||
StopWatch("PageListCache begin load key=$key");
|
||||
list($list, $opt['=protectsafe']) =
|
||||
unserialize(file_get_contents($cache));
|
||||
$opt['=cached'] = 1;
|
||||
StopWatch("PageListCache end load");
|
||||
return 0;
|
||||
|
||||
case PAGELIST_POST:
|
||||
StopWatch("PageListCache begin save key=$key");
|
||||
$fp = @fopen($cache, "w");
|
||||
if ($fp) {
|
||||
fputs($fp, serialize(array($list, $opt['=protectsafe'])));
|
||||
fclose($fp);
|
||||
}
|
||||
StopWatch("PageListCache end save");
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
## HandleSearchA performs ?action=search. It's basically the same
|
||||
## as ?action=browse, except it takes its contents from Site.Search.
|
||||
function HandleSearchA($pagename, $level = 'read') {
|
||||
global $PageSearchForm, $FmtV, $HandleSearchFmt,
|
||||
$PageStartFmt, $PageEndFmt;
|
||||
SDV($HandleSearchFmt,array(&$PageStartFmt, '$PageText', &$PageEndFmt));
|
||||
SDV($PageSearchForm, '$[{$SiteGroup}/Search]');
|
||||
$form = RetrieveAuthPage($pagename, $level, true, READPAGE_CURRENT);
|
||||
if (!$form) Abort("?unable to read $pagename");
|
||||
PCache($pagename, $form);
|
||||
$text = preg_replace('/\\[([=@])(.*?)\\1\\]/s', ' ', @$form['text']);
|
||||
if (!preg_match('/\\(:searchresults(\\s.*?)?:\\)/', $text))
|
||||
foreach((array)$PageSearchForm as $formfmt) {
|
||||
$form = ReadPage(FmtPageName($formfmt, $pagename), READPAGE_CURRENT);
|
||||
if ($form['text']) break;
|
||||
}
|
||||
$text = @$form['text'];
|
||||
if (!$text) $text = '(:searchresults:)';
|
||||
$FmtV['$PageText'] = MarkupToHTML($pagename,$text);
|
||||
PrintFmt($pagename, $HandleSearchFmt);
|
||||
}
|
||||
|
||||
|
||||
########################################################################
|
||||
## The functions below provide different formatting options for
|
||||
## the output list, controlled by the fmt= parameter and the
|
||||
## $FPLFormatOpt hash.
|
||||
########################################################################
|
||||
|
||||
## This helper function handles the count= parameter for extracting
|
||||
## a range of pagelist in the list.
|
||||
function CalcRange($range, $n) {
|
||||
if ($n < 1) return array(0, 0);
|
||||
if (strpos($range, '..') === false) {
|
||||
if ($range > 0) return array(1, min($range, $n));
|
||||
if ($range < 0) return array(max($n + $range + 1, 1), $n);
|
||||
return array(1, $n);
|
||||
}
|
||||
list($r0, $r1) = explode('..', $range);
|
||||
if ($r0 < 0) $r0 += $n + 1;
|
||||
if ($r1 < 0) $r1 += $n + 1;
|
||||
else if ($r1 == 0) $r1 = $n;
|
||||
if ($r0 < 1 && $r1 < 1) return array($n+1, $n+1);
|
||||
return array(max($r0, 1), max($r1, 1));
|
||||
}
|
||||
|
||||
|
||||
## FPLCountA handles fmt=count
|
||||
function FPLCountA($pagename, &$matches, $opt) {
|
||||
$matches = array_values(MakePageList($pagename, $opt, 0));
|
||||
return count($matches);
|
||||
}
|
||||
|
||||
SDVA($FPLTemplateFunctions, array(
|
||||
'FPLTemplateLoad' => 100,
|
||||
'FPLTemplateDefaults' => 200,
|
||||
'FPLTemplatePageList' => 300,
|
||||
'FPLTemplateSliceList' => 400,
|
||||
'FPLTemplateFormat' => 500
|
||||
));
|
||||
|
||||
function FPLTemplate($pagename, &$matches, $opt) {
|
||||
global $FPLTemplateFunctions;
|
||||
StopWatch("FPLTemplate: Chain begin");
|
||||
asort($FPLTemplateFunctions, SORT_NUMERIC);
|
||||
$fnlist = $FPLTemplateFunctions;
|
||||
$output = '';
|
||||
foreach($FPLTemplateFunctions as $fn=>$i) {
|
||||
if ($i<0) continue;
|
||||
StopWatch("FPLTemplate: $fn");
|
||||
$fn($pagename, $matches, $opt, $tparts, $output);
|
||||
}
|
||||
StopWatch("FPLTemplate: Chain end");
|
||||
return $output;
|
||||
}
|
||||
|
||||
## Loads a template section
|
||||
function FPLTemplateLoad($pagename, $matches, $opt, &$tparts){
|
||||
global $Cursor, $FPLTemplatePageFmt, $RASPageName, $PageListArgPattern;
|
||||
SDV($FPLTemplatePageFmt, array('{$FullName}',
|
||||
'{$SiteGroup}.LocalTemplates', '{$SiteGroup}.PageListTemplates'));
|
||||
|
||||
$template = @$opt['template'];
|
||||
if (!$template) $template = @$opt['fmt'];
|
||||
$ttext = RetrieveAuthSection($pagename, $template, $FPLTemplatePageFmt);
|
||||
$ttext = PVSE(Qualify($RASPageName, $ttext));
|
||||
|
||||
## save any escapes
|
||||
$ttext = MarkupEscape($ttext);
|
||||
## remove any anchor markups to avoid duplications
|
||||
$ttext = preg_replace('/\\[\\[#[A-Za-z][-.:\\w]*\\]\\]/', '', $ttext);
|
||||
|
||||
## extract portions of template
|
||||
$tparts = preg_split('/\\(:(template)\\s+([-!]?)\\s*(\\w+)\\s*(.*?):\\)/i',
|
||||
$ttext, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
}
|
||||
|
||||
## Merge parameters from (:template default :) with those in the (:pagelist:)
|
||||
function FPLTemplateDefaults($pagename, $matches, &$opt, &$tparts){
|
||||
global $PageListArgPattern;
|
||||
$i = 0;
|
||||
while ($i < count($tparts)) {
|
||||
if ($tparts[$i] != 'template') { $i++; continue; }
|
||||
if ($tparts[$i+2] != 'defaults' && $tparts[$i+2] != 'default') { $i+=5; continue; }
|
||||
$pvars = $GLOBALS['MarkupTable']['{$var}']; # expand {$PVars}
|
||||
$ttext = preg_replace_callback($pvars['pat'], $pvars['rep'], $tparts[$i+3]);
|
||||
$opt = array_merge(ParseArgs($ttext, $PageListArgPattern), $opt);
|
||||
array_splice($tparts, $i, 4);
|
||||
}
|
||||
SDVA($opt, array('class' => 'fpltemplate', 'wrap' => 'div'));
|
||||
}
|
||||
|
||||
## get the list of pages
|
||||
function FPLTemplatePageList($pagename, &$matches, &$opt){
|
||||
$matches = array_unique(array_merge((array)$matches, MakePageList($pagename, $opt, 0)));
|
||||
## count matches before any slicing and save value as template var {$$PageListCount}
|
||||
$opt['PageListCount'] = count($matches);
|
||||
}
|
||||
|
||||
## extract page subset according to 'count=' parameter
|
||||
function FPLTemplateSliceList($pagename, &$matches, $opt){
|
||||
if (@$opt['count']) {
|
||||
list($r0, $r1) = CalcRange($opt['count'], count($matches));
|
||||
if ($r1 < $r0)
|
||||
$matches = array_reverse(array_slice($matches, $r1-1, $r0-$r1+1));
|
||||
else
|
||||
$matches = array_slice($matches, $r0-1, $r1-$r0+1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function FPLTemplateFormat($pagename, $matches, $opt, $tparts, &$output){
|
||||
global $Cursor, $FPLTemplateMarkupFunction, $PCache;
|
||||
SDV($FPLTemplateMarkupFunction, 'MarkupToHTML');
|
||||
$savecursor = $Cursor;
|
||||
$pagecount = $groupcount = $grouppagecount = $traildepth = 0;
|
||||
$pseudovars = array('{$$PageCount}' => &$pagecount,
|
||||
'{$$GroupCount}' => &$groupcount,
|
||||
'{$$GroupPageCount}' => &$grouppagecount,
|
||||
'{$$PageTrailDepth}' => &$traildepth);
|
||||
|
||||
foreach(preg_grep('/^[\\w$]/', array_keys($opt)) as $k)
|
||||
if (!is_array($opt[$k]))
|
||||
$pseudovars["{\$\$$k}"] = PHSC($opt[$k], ENT_NOQUOTES);
|
||||
|
||||
$vk = array_keys($pseudovars);
|
||||
$vv = array_values($pseudovars);
|
||||
|
||||
$lgroup = ''; $out = '';
|
||||
if(count($matches)==0 ) {
|
||||
$t = 0;
|
||||
while($t < count($tparts)) {
|
||||
if($tparts[$t]=='template' && $tparts[$t+2]=='none') {
|
||||
$out .= MarkupRestore(FPLExpandItemVars($tparts[$t+4], $matches, 0, $pseudovars));
|
||||
$t+=4;
|
||||
}
|
||||
$t++;
|
||||
}
|
||||
} # else:
|
||||
foreach($matches as $i => $pn) {
|
||||
$traildepth = intval(@$PCache[$pn]['depth']);
|
||||
$group = PageVar($pn, '$Group');
|
||||
if ($group != $lgroup) { $groupcount++; $grouppagecount = 0; $lgroup = $group; }
|
||||
$grouppagecount++; $pagecount++;
|
||||
|
||||
$t = 0;
|
||||
while ($t < count($tparts)) {
|
||||
if ($tparts[$t] != 'template') { $item = $tparts[$t]; $t++; }
|
||||
else {
|
||||
list($neg, $when, $control, $item) = array_slice($tparts, $t+1, 4); $t+=5;
|
||||
if($when=='none') continue;
|
||||
if (!$control) {
|
||||
if ($when == 'first' && ($neg xor ($i != 0))) continue;
|
||||
if ($when == 'last' && ($neg xor ($i != count($matches) - 1))) continue;
|
||||
} else {
|
||||
if ($when == 'first' || !isset($last[$t])) {
|
||||
$curr = FPLExpandItemVars($control, $matches, $i, $pseudovars);
|
||||
if ($when == 'first' && ($neg xor (($i != 0) && ($last[$t] == $curr))))
|
||||
{ $last[$t] = $curr; continue; }
|
||||
$last[$t] = $curr;
|
||||
}
|
||||
if ($when == 'last') {
|
||||
$next = FPLExpandItemVars($control, $matches, $i+1, $pseudovars);
|
||||
if ($neg xor ($next == $last[$t] && $i != count($matches) - 1)) continue;
|
||||
$last[$t] = $next;
|
||||
}
|
||||
}
|
||||
}
|
||||
$item = FPLExpandItemVars($item, $matches, $i, $pseudovars);
|
||||
$out .= MarkupRestore($item);
|
||||
}
|
||||
}
|
||||
|
||||
$class = preg_replace('/[^-a-zA-Z0-9\\x80-\\xff]/', ' ', @$opt['class']);
|
||||
if ($class) $class = " class='$class'";
|
||||
$wrap = @$opt['wrap'];
|
||||
if ($wrap != 'inline') {
|
||||
$out = $FPLTemplateMarkupFunction($pagename, $out, array('escape' => 0, 'redirect'=>1));
|
||||
if ($wrap != 'none') $out = "<div$class>$out</div>";
|
||||
}
|
||||
$Cursor = $savecursor;
|
||||
$output .= $out;
|
||||
}
|
||||
## This function moves repeated code blocks out of FPLTemplateFormat()
|
||||
function FPLExpandItemVars($item, $matches, $idx, $psvars) {
|
||||
global $Cursor, $EnableUndefinedTemplateVars;
|
||||
$Cursor['<'] = $Cursor['<'] = (string)@$matches[$idx-1];
|
||||
$Cursor['='] = $pn = (string)@$matches[$idx];
|
||||
$Cursor['>'] = $Cursor['>'] = (string)@$matches[$idx+1];
|
||||
$item = str_replace(array_keys($psvars), array_values($psvars), $item);
|
||||
$item = PPRE('/\\{(=|&[lg]t;)(\\$:?\\w[-\\w]*)\\}/',
|
||||
"PVSE(PageVar('$pn', \$m[2], \$m[1]))", $item);
|
||||
if(! IsEnabled($EnableUndefinedTemplateVars, 0))
|
||||
$item = preg_replace("/\\{\\$\\$\\w+\\}/", '', $item);
|
||||
return $item;
|
||||
}
|
||||
|
||||
########################################################################
|
||||
## The functions below optimize searches by maintaining a file of
|
||||
## words and link cross references (the "page index").
|
||||
########################################################################
|
||||
|
||||
## PageIndexTerms($terms) takes an array of strings and returns a
|
||||
## normalized list of associated search terms. This reduces the
|
||||
## size of the index and speeds up searches.
|
||||
function PageIndexTerms($terms) {
|
||||
global $StrFoldFunction;
|
||||
$w = array();
|
||||
foreach((array)$terms as $t) {
|
||||
$w = array_merge($w, preg_split('/[^\\w\\x80-\\xff]+/',
|
||||
$StrFoldFunction($t), -1, PREG_SPLIT_NO_EMPTY));
|
||||
}
|
||||
return $w;
|
||||
}
|
||||
|
||||
## The PageIndexUpdate($pagelist) function updates the page index
|
||||
## file with terms and target links for the pages in $pagelist.
|
||||
## The optional $dir parameter allows this function to be called
|
||||
## via register_shutdown_function (which sometimes changes directories
|
||||
## on us).
|
||||
function PageIndexUpdate($pagelist = NULL, $dir = '') {
|
||||
global $EnableReadOnly, $PageIndexUpdateList, $PageIndexFile,
|
||||
$PageIndexTime, $Now;
|
||||
if (IsEnabled($EnableReadOnly, 0)) return;
|
||||
$abort = ignore_user_abort(true);
|
||||
if ($dir) { flush(); chdir($dir); }
|
||||
if (is_null($pagelist))
|
||||
{ $pagelist = (array)$PageIndexUpdateList; $PageIndexUpdateList = array(); }
|
||||
if (!$pagelist || !$PageIndexFile) return;
|
||||
SDV($PageIndexTime, 10);
|
||||
$c = count($pagelist); $updatecount = 0;
|
||||
StopWatch("PageIndexUpdate begin ($c pages to update)");
|
||||
$pagelist = (array)$pagelist;
|
||||
$timeout = time() + $PageIndexTime;
|
||||
$cmpfn = create_function('$a,$b', 'return strlen($b)-strlen($a);');
|
||||
Lock(2);
|
||||
$ofp = fopen("$PageIndexFile,new", 'w');
|
||||
foreach($pagelist as $pn) {
|
||||
if (@$updated[$pn]) continue;
|
||||
@$updated[$pn]++;
|
||||
if (time() > $timeout) continue;
|
||||
$page = ReadPage($pn, READPAGE_CURRENT);
|
||||
if ($page) {
|
||||
$targets = str_replace(',', ' ', @$page['targets']);
|
||||
$terms = PageIndexTerms(array(@$page['text'], $targets, $pn));
|
||||
usort($terms, $cmpfn);
|
||||
$x = '';
|
||||
foreach($terms as $t) { if (strpos($x, $t) === false) $x .= " $t"; }
|
||||
fputs($ofp, "$pn:$Now: $targets :$x\n");
|
||||
}
|
||||
$updatecount++;
|
||||
}
|
||||
$ifp = @fopen($PageIndexFile, 'r');
|
||||
if ($ifp) {
|
||||
while (!feof($ifp)) {
|
||||
$line = fgets($ifp, 4096);
|
||||
while (substr($line, -1, 1) != "\n" && !feof($ifp))
|
||||
$line .= fgets($ifp, 4096);
|
||||
$i = strpos($line, ':');
|
||||
if ($i === false) continue;
|
||||
$n = substr($line, 0, $i);
|
||||
if (@$updated[$n]) continue;
|
||||
fputs($ofp, $line);
|
||||
}
|
||||
fclose($ifp);
|
||||
}
|
||||
fclose($ofp);
|
||||
if (file_exists($PageIndexFile)) unlink($PageIndexFile);
|
||||
rename("$PageIndexFile,new", $PageIndexFile);
|
||||
fixperms($PageIndexFile);
|
||||
StopWatch("PageIndexUpdate end ($updatecount updated)");
|
||||
ignore_user_abort($abort);
|
||||
}
|
||||
|
||||
## PageIndexQueueUpdate specifies pages to be updated in
|
||||
## the index upon shutdown (via register_shutdown function).
|
||||
function PageIndexQueueUpdate($pagelist) {
|
||||
global $PageIndexUpdateList;
|
||||
if (!@$PageIndexUpdateList)
|
||||
register_shutdown_function('PageIndexUpdate', NULL, getcwd());
|
||||
$PageIndexUpdateList = array_merge((array)@$PageIndexUpdateList,
|
||||
(array)$pagelist);
|
||||
$c1 = count($pagelist); $c2 = count($PageIndexUpdateList);
|
||||
StopWatch("PageIndexQueueUpdate: queued $c1 pages ($c2 total)");
|
||||
}
|
||||
|
||||
## PageIndexGrep returns a list of pages that match the strings
|
||||
## provided. Note that some search terms may need to be normalized
|
||||
## in order to get the desired results (see PageIndexTerms above).
|
||||
## Also note that this just works for the index; if the index is
|
||||
## incomplete, then so are the results returned by this list.
|
||||
## (MakePageList above already knows how to deal with this.)
|
||||
function PageIndexGrep($terms, $invert = false) {
|
||||
global $PageIndexFile;
|
||||
if (!$PageIndexFile) return array();
|
||||
StopWatch('PageIndexGrep begin');
|
||||
$pagelist = array();
|
||||
$fp = @fopen($PageIndexFile, 'r');
|
||||
if ($fp) {
|
||||
$terms = (array)$terms;
|
||||
while (!feof($fp)) {
|
||||
$line = fgets($fp, 4096);
|
||||
while (substr($line, -1, 1) != "\n" && !feof($fp))
|
||||
$line .= fgets($fp, 4096);
|
||||
$i = strpos($line, ':');
|
||||
if (!$i) continue;
|
||||
$add = true;
|
||||
foreach($terms as $t)
|
||||
if (strpos($line, $t) === false) { $add = false; break; }
|
||||
if ($add xor $invert) $pagelist[] = substr($line, 0, $i);
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
StopWatch('PageIndexGrep end');
|
||||
return $pagelist;
|
||||
}
|
||||
|
||||
## PostPageIndex is inserted into $EditFunctions to update
|
||||
## the linkindex whenever a page is saved.
|
||||
function PostPageIndex($pagename, &$page, &$new) {
|
||||
global $IsPagePosted;
|
||||
if ($IsPagePosted) PageIndexQueueUpdate($pagename);
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script defines routines for displaying page revisions. It
|
||||
is included by default from the stdconfig.php script.
|
||||
*/
|
||||
|
||||
function LinkSuppress($pagename,$imap,$path,$title,$txt,$fmt=NULL)
|
||||
{ return $txt; }
|
||||
|
||||
SDV($DiffShow['minor'],(@$_REQUEST['minor']!='n')?'y':'n');
|
||||
SDV($DiffShow['source'],(@$_REQUEST['source']!='n')?'y':'n');
|
||||
SDV($DiffMinorFmt, ($DiffShow['minor']=='y') ?
|
||||
"<a href='{\$PageUrl}?action=diff&source=".$DiffShow['source']."&minor=n'>$[Hide minor edits]</a>" :
|
||||
"<a href='{\$PageUrl}?action=diff&source=".$DiffShow['source']."&minor=y'>$[Show minor edits]</a>" );
|
||||
SDV($DiffSourceFmt, ($DiffShow['source']=='y') ?
|
||||
"<a href='{\$PageUrl}?action=diff&source=n&minor=".$DiffShow['minor']."'>$[Show changes to output]</a>" :
|
||||
"<a href='{\$PageUrl}?action=diff&source=y&minor=".$DiffShow['minor']."'>$[Show changes to markup]</a>");
|
||||
SDV($PageDiffFmt,"<h2 class='wikiaction'>$[{\$FullName} History]</h2>
|
||||
<p>$DiffMinorFmt - $DiffSourceFmt</p>
|
||||
");
|
||||
SDV($DiffStartFmt,"
|
||||
<div class='diffbox'><div class='difftime'><a name='diff\$DiffGMT' href='#diff\$DiffGMT'>\$DiffTime</a>
|
||||
\$[by] <span class='diffauthor' title='\$DiffHost'>\$DiffAuthor</span> - \$DiffChangeSum</div>");
|
||||
SDV($DiffDelFmt['a'],"
|
||||
<div class='difftype'>\$[Deleted line \$DiffLines:]</div>
|
||||
<div class='diffdel'>");
|
||||
SDV($DiffDelFmt['c'],"
|
||||
<div class='difftype'>\$[Changed line \$DiffLines from:]</div>
|
||||
<div class='diffdel'>");
|
||||
SDV($DiffAddFmt['d'],"
|
||||
<div class='difftype'>\$[Added line \$DiffLines:]</div>
|
||||
<div class='diffadd'>");
|
||||
SDV($DiffAddFmt['c'],"</div>
|
||||
<div class='difftype'>$[to:]</div>
|
||||
<div class='diffadd'>");
|
||||
SDV($DiffEndDelAddFmt,"</div>");
|
||||
SDV($DiffEndFmt,"</div>");
|
||||
SDV($DiffRestoreFmt,"
|
||||
<div class='diffrestore'><a href='{\$PageUrl}?action=edit&restore=\$DiffId&preview=y'>$[Restore]</a></div>");
|
||||
|
||||
SDV($HandleActions['diff'], 'HandleDiff');
|
||||
SDV($HandleAuth['diff'], 'read');
|
||||
SDV($ActionTitleFmt['diff'], '| $[History]');
|
||||
SDV($HTMLStylesFmt['diff'], "
|
||||
.diffbox { width:570px; border-left:1px #999999 solid; margin-top:1.33em; }
|
||||
.diffauthor { font-weight:bold; }
|
||||
.diffchangesum { font-weight:bold; }
|
||||
.difftime { font-family:verdana,sans-serif; font-size:66%;
|
||||
background-color:#dddddd; }
|
||||
.difftype { clear:both; font-family:verdana,sans-serif;
|
||||
font-size:66%; font-weight:bold; }
|
||||
.diffadd { border-left:5px #99ff99 solid; padding-left:5px; }
|
||||
.diffdel { border-left:5px #ffff99 solid; padding-left:5px; }
|
||||
.diffrestore { clear:both; font-family:verdana,sans-serif;
|
||||
font-size:66%; margin:1.5em 0px; }
|
||||
.diffmarkup { font-family:monospace; }
|
||||
.diffmarkup del { background:#ffff99; text-decoration: none; }
|
||||
.diffmarkup ins { background:#99ff99; text-decoration: none; }");
|
||||
|
||||
function PrintDiff($pagename) {
|
||||
global $DiffHTMLFunction,$DiffShow,$DiffStartFmt,$TimeFmt,
|
||||
$DiffEndFmt,$DiffRestoreFmt,$FmtV, $LinkFunctions;
|
||||
$page = ReadPage($pagename);
|
||||
if (!$page) return;
|
||||
krsort($page); reset($page);
|
||||
$lf = $LinkFunctions;
|
||||
$LinkFunctions['http:'] = 'LinkSuppress';
|
||||
$LinkFunctions['https:'] = 'LinkSuppress';
|
||||
SDV($DiffHTMLFunction, 'DiffHTML');
|
||||
foreach($page as $k=>$v) {
|
||||
if (!preg_match("/^diff:(\d+):(\d+):?([^:]*)/",$k,$match)) continue;
|
||||
$diffclass = $match[3];
|
||||
if ($diffclass=='minor' && $DiffShow['minor']!='y') continue;
|
||||
$diffgmt = $FmtV['$DiffGMT'] = $match[1];
|
||||
$FmtV['$DiffTime'] = strftime($TimeFmt,$diffgmt);
|
||||
$diffauthor = @$page["author:$diffgmt"];
|
||||
if (!$diffauthor) @$diffauthor=$page["host:$diffgmt"];
|
||||
if (!$diffauthor) $diffauthor="unknown";
|
||||
$FmtV['$DiffChangeSum'] = PHSC(@$page["csum:$diffgmt"]);
|
||||
$FmtV['$DiffHost'] = @$page["host:$diffgmt"];
|
||||
$FmtV['$DiffAuthor'] = $diffauthor;
|
||||
$FmtV['$DiffId'] = $k;
|
||||
$html = $DiffHTMLFunction($pagename, $v);
|
||||
if ($html===false) continue;
|
||||
echo FmtPageName($DiffStartFmt,$pagename);
|
||||
echo $html;
|
||||
echo FmtPageName($DiffEndFmt,$pagename);
|
||||
echo FmtPageName($DiffRestoreFmt,$pagename);
|
||||
}
|
||||
$LinkFunctions = $lf;
|
||||
}
|
||||
|
||||
# This function converts a single diff entry from the wikipage file
|
||||
# into HTML, ready for display.
|
||||
function DiffHTML($pagename, $diff) {
|
||||
if (@$_REQUEST['nodiff']>'') return '';
|
||||
global $FmtV, $DiffShow, $DiffAddFmt, $DiffDelFmt, $DiffEndDelAddFmt,
|
||||
$DiffRenderSourceFunction;
|
||||
SDV($DiffRenderSourceFunction, 'DiffRenderSource');
|
||||
$difflines = explode("\n",$diff."\n");
|
||||
$in=array(); $out=array(); $dtype=''; $html = '';
|
||||
foreach($difflines as $d) {
|
||||
if ($d>'') {
|
||||
if ($d[0]=='-' || $d[0]=='\\') continue;
|
||||
if ($d[0]=='<') { $out[]=substr($d,2); continue; }
|
||||
if ($d[0]=='>') { $in[]=substr($d,2); continue; }
|
||||
}
|
||||
if (preg_match("/^(\\d+)(,(\\d+))?([adc])(\\d+)(,(\\d+))?/",
|
||||
$dtype,$match)) {
|
||||
if (@$match[7]>'') {
|
||||
$lines='lines';
|
||||
$count=$match[1].'-'.($match[1]+$match[7]-$match[5]);
|
||||
} elseif ($match[3]>'') {
|
||||
$lines='lines'; $count=$match[1].'-'.$match[3];
|
||||
} else { $lines='line'; $count=$match[1]; }
|
||||
if ($match[4]=='a' || $match[4]=='c') {
|
||||
$txt = str_replace('line',$lines,$DiffDelFmt[$match[4]]);
|
||||
$FmtV['$DiffLines'] = $count;
|
||||
$html .= FmtPageName($txt,$pagename);
|
||||
if ($DiffShow['source']=='y')
|
||||
$html .= "<div class='diffmarkup'>"
|
||||
.$DiffRenderSourceFunction($in, $out, 0)
|
||||
."</div>";
|
||||
else $html .= MarkupToHTML($pagename,
|
||||
PPRE('/\\(:.*?:\\)/',"Keep(PHSC(\$m[0]))", join("\n",$in)));
|
||||
}
|
||||
if ($match[4]=='d' || $match[4]=='c') {
|
||||
$txt = str_replace('line',$lines,$DiffAddFmt[$match[4]]);
|
||||
$FmtV['$DiffLines'] = $count;
|
||||
$html .= FmtPageName($txt,$pagename);
|
||||
if ($DiffShow['source']=='y')
|
||||
$html .= "<div class='diffmarkup'>"
|
||||
.$DiffRenderSourceFunction($in, $out, 1)
|
||||
."</div>";
|
||||
else $html .= MarkupToHTML($pagename,
|
||||
PPRE('/\\(:.*?:\\)/',"Keep(PHSC(\$m[0]))",join("\n",$out)));
|
||||
}
|
||||
$html .= FmtPageName($DiffEndDelAddFmt,$pagename);
|
||||
}
|
||||
$in=array(); $out=array(); $dtype=$d;
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
function HandleDiff($pagename, $auth='read') {
|
||||
global $HandleDiffFmt, $PageStartFmt, $PageDiffFmt, $PageEndFmt;
|
||||
$page = RetrieveAuthPage($pagename, $auth, true, READPAGE_CURRENT);
|
||||
if (!$page) { Abort("?cannot diff $pagename"); }
|
||||
PCache($pagename, $page);
|
||||
SDV($HandleDiffFmt,array(&$PageStartFmt,
|
||||
&$PageDiffFmt,"<div id='wikidiff'>", 'function:PrintDiff', '</div>',
|
||||
&$PageEndFmt));
|
||||
PrintFmt($pagename,$HandleDiffFmt);
|
||||
}
|
||||
## Functions for simple word-diff (written by Petko Yotov)
|
||||
function DiffRenderSource($in, $out, $which) {
|
||||
global $WordDiffFunction, $EnableDiffInline;
|
||||
if (!IsEnabled($EnableDiffInline, 1)) {
|
||||
$a = $which? $out : $in;
|
||||
return str_replace("\n","<br />",PHSC(join("\n",$a)));
|
||||
}
|
||||
$countdifflines = abs(count($in)-count($out));
|
||||
$lines = $cnt = $x2 = $y2 = array();
|
||||
foreach($in as $line) {
|
||||
$tmp = $countdifflines>20 ? array($line) : DiffPrepareInline($line);
|
||||
if(!$which) $cnt[] = array(count($x2), count($tmp));
|
||||
$x2 = array_merge($x2, $tmp);
|
||||
}
|
||||
foreach($out as $line) {
|
||||
$tmp = $countdifflines>20 ? array($line) : DiffPrepareInline($line);
|
||||
if($which) $cnt[] = array(count($y2), count($tmp));
|
||||
$y2 = array_merge($y2, $tmp);
|
||||
}
|
||||
$z = $WordDiffFunction(implode("\n", $x2), implode("\n", $y2));
|
||||
|
||||
$z2 = array_map('PHSC', ($which? $y2 : $x2));
|
||||
array_unshift($z2, '');
|
||||
foreach (explode("\n", $z) as $zz) {
|
||||
if (preg_match('/^(\\d+)(,(\\d+))?([adc])(\\d+)(,(\\d+))?/',$zz,$m)) {
|
||||
$a1 = $a2 = $m[1];
|
||||
if ($m[3]) $a2=$m[3];
|
||||
$b1 = $b2 = $m[5];
|
||||
if ($m[7]) $b2=$m[7];
|
||||
|
||||
if (!$which && ($m[4]=='c'||$m[4]=='d')) {
|
||||
$z2[$a1] = '<del>'. $z2[$a1];
|
||||
$z2[$a2] .= '</del>';
|
||||
}
|
||||
if ($which && ($m[4]=='c'||$m[4]=='a')) {
|
||||
$z2[$b1] = '<ins>'.$z2[$b1];
|
||||
$z2[$b2] .= '</ins>';
|
||||
}
|
||||
}
|
||||
}
|
||||
$line = array_shift($z2);
|
||||
$z2[0] = $line.$z2[0];
|
||||
foreach ($cnt as $a) $lines[] = implode('', array_slice($z2, $a[0], $a[1]));
|
||||
$ret = implode("\n", $lines);
|
||||
$ret = str_replace(array('</del> <del>', '</ins> <ins>'), ' ', $ret);
|
||||
$ret = preg_replace('/(<(ins|del)>|^) /', '$1 ', $ret);
|
||||
return str_replace(array(" ", "\n ", "\n"),array(" ", "<br /> ", "<br />"),$ret);
|
||||
}
|
||||
## Split a line into pieces before passing it through `diff`
|
||||
function DiffPrepareInline($x) {
|
||||
global $DiffSplitInlineDelims;
|
||||
SDV($DiffSplitInlineDelims, "-@!?#$%^&*()=+[]{}.'\"\\:|,<>_/;~");
|
||||
return preg_split("/([".preg_quote($DiffSplitInlineDelims, '/')."\\s])/",
|
||||
$x, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
}
|
||||
|
||||
SDV($WordDiffFunction, 'PHPDiff'); # faster than sysdiff for many calls
|
||||
if (IsEnabled($EnableDiffInline, 1) && $DiffShow['source'] == 'y'
|
||||
&& $WordDiffFunction == 'PHPDiff' && !function_exists('PHPDiff'))
|
||||
include_once("$FarmD/scripts/phpdiff.php");
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2002-2005 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script enables per-page and per-group customizations in the
|
||||
local/ subdirectory (or whatever directory is given by $LocalDir).
|
||||
For example, to create customizations for the 'Demo' group, place
|
||||
them in a file called local/Demo.php. To customize a single page,
|
||||
use the full page name (e.g., local/Demo.MyPage.php).
|
||||
Per-page/per-group customizations can be handled at any time by adding
|
||||
include_once("scripts/pgcust.php");
|
||||
to config.php. It is automatically included by scripts/stdconfig.php
|
||||
unless $EnablePGCust is set to zero in config.php.
|
||||
|
||||
A page's customization is loaded first, followed by any group
|
||||
customization. If no page or group customizations are loaded,
|
||||
then 'local/default.php' is loaded.
|
||||
|
||||
A per-page configuration file can prevent its group's config from
|
||||
loading by setting $EnablePGCust=0;. A per-page configuration file
|
||||
can force group customizations to be loaded first by using include_once
|
||||
on the group customization file.
|
||||
|
||||
*/
|
||||
|
||||
$f = 1;
|
||||
for($p=$pagename;$p;$p=preg_replace('/\\.*[^.]*$/','',$p)) {
|
||||
if (!IsEnabled($EnablePGCust,1)) return;
|
||||
if (file_exists("$LocalDir/$p.php"))
|
||||
{ include_once("$LocalDir/$p.php"); $f=0; }
|
||||
}
|
||||
|
||||
if ($f && IsEnabled($EnablePGCust,1) && file_exists("$LocalDir/default.php"))
|
||||
include_once("$LocalDir/default.php");
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/*
|
||||
Copyright 2003,2004 Nils Knappmeier (nk@knappi.org)
|
||||
Copyright 2004-2010 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file implements a diff function in native PHP. It is based
|
||||
upon the PHPDiffEngine code written by Nils Knappmeier, who in turn
|
||||
had used Daniel Unterberger's diff
|
||||
(http://www.holomind.de/phpnet/diff.php) as the basis for his code.
|
||||
|
||||
Pm's revision of Nils' code simply attempts to streamline it
|
||||
for speed (eliminate function calls and unnecessary string ops)
|
||||
and place everything into a single file.
|
||||
|
||||
*/
|
||||
|
||||
## PHPDiff returns the differences between $old and $new, formatted
|
||||
## in the standard diff(1) output format.
|
||||
function PHPDiff($old, $new)
|
||||
{
|
||||
StopWatch("PHPDiff: begin");
|
||||
# split the source text into arrays of lines
|
||||
$t1 = explode("\n", $old);
|
||||
$x = array_pop($t1);
|
||||
if ($x > '') $t1[] = "$x\n\\ No newline at end of file";
|
||||
$t2 = explode("\n", $new);
|
||||
$x = array_pop($t2);
|
||||
if ($x > '') $t2[] = "$x\n\\ No newline at end of file";
|
||||
|
||||
$t1_start = 0; $t1_end = count($t1);
|
||||
$t2_start = 0; $t2_end = count($t2);
|
||||
|
||||
# stop with a common ending
|
||||
while ($t1_start < $t1_end && $t2_start < $t2_end
|
||||
&& $t1[$t1_end-1] == $t2[$t2_end-1]) { $t1_end--; $t2_end--; }
|
||||
|
||||
# skip over any common beginning
|
||||
while ($t1_start < $t1_end && $t2_start < $t2_end
|
||||
&& $t1[$t1_start] == $t2[$t2_start]) { $t1_start++; $t2_start++; }
|
||||
|
||||
# build a reverse-index array using the line as key and line number as value
|
||||
# don't store blank lines, so they won't be targets of the shortest distance
|
||||
# search
|
||||
for($i = $t1_start; $i < $t1_end; $i++) if ($t1[$i]>'') $r1[$t1[$i]][] = $i;
|
||||
for($i = $t2_start; $i < $t2_end; $i++) if ($t2[$i]>'') $r2[$t2[$i]][] = $i;
|
||||
|
||||
$a1 = $t1_start; $a2 = $t2_start; # start at beginning of each list
|
||||
$actions = array();
|
||||
|
||||
# walk this loop until we reach the end of one of the lists
|
||||
while ($a1 < $t1_end && $a2 < $t2_end) {
|
||||
# if we have a common element, save it and go to the next
|
||||
if ($t1[$a1] == $t2[$a2]) { $actions[] = 4; $a1++; $a2++; continue; }
|
||||
|
||||
# otherwise, find the shortest move (Manhattan-distance) from the
|
||||
# current location
|
||||
$best1 = $t1_end; $best2 = $t2_end;
|
||||
$s1 = $a1; $s2 = $a2;
|
||||
while(($s1 + $s2 - $a1 - $a2) < ($best1 + $best2 - $a1 - $a2)) {
|
||||
$d = -1;
|
||||
foreach((array)@$r1[$t2[$s2]] as $n)
|
||||
if ($n >= $s1) { $d = $n; break; }
|
||||
if ($d >= $s1 && ($d + $s2 - $a1 - $a2) < ($best1 + $best2 - $a1 - $a2))
|
||||
{ $best1 = $d; $best2 = $s2; }
|
||||
$d = -1;
|
||||
foreach((array)@$r2[$t1[$s1]] as $n)
|
||||
if ($n >= $s2) { $d = $n; break; }
|
||||
if ($d >= $s2 && ($s1 + $d - $a1 - $a2) < ($best1 + $best2 - $a1 - $a2))
|
||||
{ $best1 = $s1; $best2 = $d; }
|
||||
$s1++; $s2++;
|
||||
}
|
||||
while ($a1 < $best1) { $actions[] = 1; $a1++; } # deleted elements
|
||||
while ($a2 < $best2) { $actions[] = 2; $a2++; } # added elements
|
||||
}
|
||||
|
||||
# we've reached the end of one list, now walk to the end of the other
|
||||
while($a1 < $t1_end) { $actions[] = 1; $a1++; } # deleted elements
|
||||
while($a2 < $t2_end) { $actions[] = 2; $a2++; } # added elements
|
||||
|
||||
# and this marks our ending point
|
||||
$actions[] = 8;
|
||||
|
||||
# now, let's follow the path we just took and report the added/deleted
|
||||
# elements into $out.
|
||||
$op = 0;
|
||||
$x0 = $x1 = $t1_start; $y0 = $y1 = $t2_start;
|
||||
$out = array();
|
||||
foreach($actions as $act) {
|
||||
if ($act == 1) { $op |= $act; $x1++; continue; }
|
||||
if ($act == 2) { $op |= $act; $y1++; continue; }
|
||||
if ($op > 0) {
|
||||
$xstr = ($x1 == ($x0+1)) ? $x1 : ($x0+1) . ",$x1";
|
||||
$ystr = ($y1 == ($y0+1)) ? $y1 : ($y0+1) . ",$y1";
|
||||
if ($op == 1) $out[] = "{$xstr}d{$y1}";
|
||||
elseif ($op == 3) $out[] = "{$xstr}c{$ystr}";
|
||||
while ($x0 < $x1) { $out[] = '< ' . $t1[$x0]; $x0++; } # deleted elems
|
||||
if ($op == 2) $out[] = "{$x1}a{$ystr}";
|
||||
elseif ($op == 3) $out[] = '---';
|
||||
while ($y0 < $y1) { $out[] = '> '.$t2[$y0]; $y0++; } # added elems
|
||||
}
|
||||
$x1++; $x0 = $x1;
|
||||
$y1++; $y0 = $y1;
|
||||
$op = 0;
|
||||
}
|
||||
$out[] = '';
|
||||
StopWatch("PHPDiff: end");
|
||||
return join("\n",$out);
|
||||
}
|
||||
|
||||
if (!function_exists(@$DiffFunction))
|
||||
$DiffFunction = 'PHPDiff';
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2005-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script handles per-browser preferences. Preference settings
|
||||
are stored in wiki pages as XLPage translations, and a cookie on
|
||||
the browser tells PmWiki where to find the browser's preferred
|
||||
settings.
|
||||
|
||||
This script looks for a ?setprefs= request parameter (e.g., in
|
||||
a url); when it finds one it sets a 'setprefs' cookie on the browser
|
||||
identifying the page to be used to load browser preferences,
|
||||
and loads the associated preferences.
|
||||
|
||||
If there is no ?setprefs= request, then the script uses the
|
||||
'setprefs' cookie from the browser to load the preference settings.
|
||||
*/
|
||||
|
||||
SDV($PrefsCookie, $CookiePrefix.'setprefs');
|
||||
SDV($PrefsCookieExpires, $Now + 60 * 60 * 24 * 365);
|
||||
$LogoutCookies[] = $PrefsCookie;
|
||||
|
||||
$sp = '';
|
||||
if (@$_COOKIE[$PrefsCookie]) $sp = $_COOKIE[$PrefsCookie];
|
||||
if (isset($_GET['setprefs'])) {
|
||||
$sp = MakePageName($pagename, $_GET['setprefs']);
|
||||
setcookie($PrefsCookie, $sp, $PrefsCookieExpires, '/');
|
||||
}
|
||||
if ($sp && PageExists($sp)) XLPage('prefs', $sp, true);
|
||||
|
||||
if(is_array($XL['prefs'])) {
|
||||
foreach($XL['prefs'] as $k=>$v) {
|
||||
if(! preg_match('/^(e_rows|e_cols|TimeFmt|Locale|Site\\.EditForm)$|^ak_/', $k))
|
||||
unset($XL['prefs'][$k]);
|
||||
}
|
||||
}
|
||||
|
||||
XLSDV('en', array(
|
||||
'ak_view' => '',
|
||||
'ak_edit' => 'e',
|
||||
'ak_history' => 'h',
|
||||
'ak_attach' => '',
|
||||
'ak_backlinks' => '',
|
||||
'ak_logout' => '',
|
||||
'ak_print' => '',
|
||||
'ak_recentchanges' => 'c',
|
||||
'ak_save' => 's',
|
||||
'ak_saveedit' => 'u',
|
||||
'ak_savedraft' => 'd',
|
||||
'ak_preview' => 'p',
|
||||
'ak_em' => '',
|
||||
'ak_strong' => '',
|
||||
));
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2011 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file does simple reference counting on pages in a PmWiki site.
|
||||
Simply activate this script using
|
||||
include_once('scripts/refcount.php');
|
||||
in the config.php file and then use ?action=refcount to bring up
|
||||
the reference count form. The output is a table where each row
|
||||
of the table contains a page name or link reference, the number
|
||||
of (non-RecentChanges) pages that contain links to the page,
|
||||
the number of RecentChanges pages with links to the page, and the
|
||||
total number of references in all pages.
|
||||
*/
|
||||
|
||||
SDV($PageRefCountFmt,"<h2 class='wikiaction'>Reference Count Results</h2>");
|
||||
SDV($RefCountTimeFmt," <small>%Y-%b-%d %H:%M</small>");
|
||||
SDV($HandleActions['refcount'], 'HandleRefCount');
|
||||
|
||||
function PrintRefCount($pagename) {
|
||||
global $GroupPattern,$NamePattern,$PageRefCountFmt,$RefCountTimeFmt, $ScriptUrl;
|
||||
$pagelist = ListPages();
|
||||
$grouplist = array();
|
||||
foreach($pagelist as $pname) {
|
||||
if (!preg_match("/^($GroupPattern)[\\/.]($NamePattern)$/",$pname,$m))
|
||||
continue;
|
||||
$grouplist[$m[1]]=$m[1];
|
||||
}
|
||||
asort($grouplist);
|
||||
$grouplist = array_merge(array('all' => 'all groups'),$grouplist);
|
||||
|
||||
$wlist = array('all','missing','existing','orphaned');
|
||||
$tlist = isset($_REQUEST['tlist']) ? $_REQUEST['tlist'] : array('all');
|
||||
$flist = isset($_REQUEST['flist']) ? $_REQUEST['flist'] : array('all');
|
||||
$whichrefs = @$_REQUEST['whichrefs'];
|
||||
$showrefs = (@$_REQUEST['showrefs']=='checked')? "checked='checked'" : '';
|
||||
$submit = @$_REQUEST['submit'];
|
||||
|
||||
echo FmtPageName($PageRefCountFmt,$pagename);
|
||||
echo FmtPageName("<form method='post' action='{\$PageUrl}'><input type='hidden' name='action' value='refcount'/>
|
||||
<table cellspacing='10'><tr><td valign='top'>Show
|
||||
<br/><select name='whichrefs'>",$pagename);
|
||||
foreach($wlist as $w)
|
||||
echo "<option ",($whichrefs==$w) ? 'selected="selected"' : ''," value='$w'>$w</option>\n";
|
||||
echo "</select></td><td valign='top'> page names in group<br/>
|
||||
<select name='tlist[]' multiple='multiple' size='4'>";
|
||||
foreach($grouplist as $g=>$t)
|
||||
echo "<option ",in_array($g,$tlist) ? 'selected="selected"' : ''," value='$g'>$t</option>\n";
|
||||
echo "</select></td><td valign='top'> referenced from pages in<br/>
|
||||
<select name='flist[]' multiple='multiple' size='4'>";
|
||||
foreach($grouplist as $g=>$t)
|
||||
echo "<option ",in_array($g,$flist) ? 'selected="selected"' : ''," value='$g'>$t</option>\n";
|
||||
echo "</select></td></tr></table>
|
||||
<p><input type='checkbox' name='showrefs' value='checked' $showrefs/>
|
||||
Display referencing pages
|
||||
</p><p><input type='submit' name='submit' value='Search'/></p></form><hr/>";
|
||||
|
||||
if ($submit) {
|
||||
foreach($pagelist as $pname) {
|
||||
$ref = array();
|
||||
$page = ReadPage($pname, READPAGE_CURRENT);
|
||||
if (!$page) continue;
|
||||
$tref[$pname]['time'] = $page['time'];
|
||||
if (!in_array('all',$flist) &&
|
||||
!in_array(FmtPageName('$Group',$pname),$flist)) continue;
|
||||
$rc = preg_match('/RecentChanges$/',$pname);
|
||||
foreach(explode(',',@$page['targets']) as $r) {
|
||||
if ($r=='') continue;
|
||||
if ($rc) @$tref[$r]['rc']++;
|
||||
else { @$tref[$r]['page']++; @$pref[$r][$pname]++; }
|
||||
}
|
||||
}
|
||||
uasort($tref,'RefCountCmp');
|
||||
echo "<table >
|
||||
<tr><th></th><th colspan='2'>Referring pages</th></tr>
|
||||
<tr><th>Name / Time</th><th>All</th><th>R.C.</th></tr>";
|
||||
reset($tref);
|
||||
foreach($tref as $p=>$c) {
|
||||
if (!in_array('all',$tlist) &&
|
||||
!in_array(FmtPageName('$Group',$p),$tlist)) continue;
|
||||
if ($whichrefs=='missing' && PageExists($p)) continue;
|
||||
elseif ($whichrefs=='existing' && !PageExists($p)) continue;
|
||||
elseif ($whichrefs=='orphaned' &&
|
||||
(@$tref[$p]['page']>0 || !PageExists($p))) continue;
|
||||
echo "<tr><td valign='top'>",LinkPage($pagename, '', $p, '', $p);
|
||||
if (@$tref[$p]['time']) echo strftime($RefCountTimeFmt,$tref[$p]['time']);
|
||||
if ($showrefs && is_array(@$pref[$p])) {
|
||||
foreach($pref[$p] as $pr=>$pc)
|
||||
echo "<dd>", LinkPage($pagename, '', $pr, '', $pr);
|
||||
}
|
||||
echo "</td>";
|
||||
echo "<td align='center' valign='top'>",@$tref[$p]['page']+0,"</td>";
|
||||
echo "<td align='center' valign='top'>",@$tref[$p]['rc']+0,"</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
echo "</table>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function RefCountCmp($ua,$ub) {
|
||||
if (@($ua['page']!=$ub['page'])) return @($ub['page']-$ua['page']);
|
||||
if (@($ua['rc']!=$ub['rc'])) return @($ub['rc']-$ua['rc']);
|
||||
return @($ub['time']-$ua['time']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function HandleRefCount($pagename, $auth='read') {
|
||||
global $HandleRefCountFmt,$PageStartFmt,$PageEndFmt;
|
||||
$page = RetrieveAuthPage($pagename, $auth, true, READPAGE_CURRENT);
|
||||
if (!$page) Abort('?unauthorized');
|
||||
PCache($pagename, $page);
|
||||
SDV($HandleRefCountFmt,array(&$PageStartFmt,
|
||||
'function:PrintRefCount',&$PageEndFmt));
|
||||
PrintFmt($pagename,$HandleRefCountFmt);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2005-2006 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file provides various features to allow PmWiki to control
|
||||
what web crawlers (robots) see when they visit the site. Of course
|
||||
it's still possible to control robots at the webserver level
|
||||
and via robots.txt, but this page provides some finer level
|
||||
of control.
|
||||
|
||||
The $MetaRobots variable controls generation of the
|
||||
<meta name='robots' ... /> tag in the head of the HTML document.
|
||||
By default $MetaRobots is set so that robots do not index pages in
|
||||
the Site, SiteAdmin, and PmWiki groups.
|
||||
|
||||
The $RobotPattern variable is used to determine if the user agent
|
||||
accessing the site is a robot, and $IsRobotAgent is set accordingly.
|
||||
By default this pattern identifies Googlebot, Yahoo! Slurp, msnbot,
|
||||
BecomeBot, and HTTrack as robots.
|
||||
|
||||
If the agent is deemed a robot, then the $RobotActions array is
|
||||
checked to see if robots are allowed to perform the given action,
|
||||
and if not the robot is immediately sent an HTTP 403 Forbidden
|
||||
response.
|
||||
|
||||
If $EnableRobotCloakActions is set, then a pattern is added to
|
||||
$FmtP to hide any "?action=" url parameters in page urls
|
||||
generated by PmWiki for actions that robots aren't allowed to
|
||||
access. This can greatly reduce the load on the server by
|
||||
not providing the robot with links to pages that it will be
|
||||
forbidden to index anyway.
|
||||
*/
|
||||
|
||||
## $MetaRobots provides the value for the <meta name='robots' ...> tag.
|
||||
SDV($MetaRobots,
|
||||
($action!='browse' || !PageExists($pagename)
|
||||
|| preg_match('#^PmWiki[./](?!PmWiki$)|^Site(Admin)?[./]#', $pagename))
|
||||
? 'noindex,nofollow' : 'index,follow');
|
||||
if ($MetaRobots)
|
||||
$HTMLHeaderFmt['robots'] =
|
||||
" <meta name='robots' content='\$MetaRobots' />\n";
|
||||
|
||||
## $RobotPattern is used to identify robots.
|
||||
SDV($RobotPattern,'Googlebot|Slurp|msnbot|Teoma|ia_archiver|BecomeBot|HTTrack|MJ12bot|XML Sitemaps|Yandex');
|
||||
SDV($IsRobotAgent,
|
||||
$RobotPattern && preg_match("!$RobotPattern!", @$_SERVER['HTTP_USER_AGENT']));
|
||||
if (!$IsRobotAgent) return;
|
||||
|
||||
## $RobotActions indicates which actions a robot is allowed to perform.
|
||||
SDVA($RobotActions, array('browse' => 1, 'rss' => 1, 'dc' => 1));
|
||||
if (!@$RobotActions[$action]) {
|
||||
$pagename = ResolvePageName($pagename);
|
||||
if (!PageExists($pagename)) {
|
||||
header("HTTP/1.1 404 Not Found");
|
||||
print("<h1>Not Found</h1>");
|
||||
exit();
|
||||
}
|
||||
header("HTTP/1.1 403 Forbidden");
|
||||
print("<h1>Forbidden</h1>");
|
||||
exit();
|
||||
}
|
||||
|
||||
## The following removes any ?action= parameters that robots aren't
|
||||
## allowed to access.
|
||||
if (IsEnabled($EnableRobotCloakActions, 0)) {
|
||||
$p = create_function('$a', 'return (boolean)$a;');
|
||||
$p = join('|', array_keys(array_filter($RobotActions, $p)));
|
||||
$FmtPV['$PageUrl'] =
|
||||
'PUE(($EnablePathInfo)
|
||||
? "\\$ScriptUrl/$group/$name"
|
||||
: "\\$ScriptUrl?n=$group.$name")';
|
||||
$FmtP["/(\\\$ScriptUrl[^#\"'\\s<>]+)\\?action=(?!$p)\\w+/"] = '$1';
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file enables merging of concurrent edits, using the "diff3"
|
||||
program available on most Unix systems to merge the edits. If
|
||||
diff3 is not available or you'd like to use a different command,
|
||||
then set $SysMergeCmd accordingly.
|
||||
*/
|
||||
|
||||
array_unshift($EditFunctions,'MergeSimulEdits');
|
||||
$HTMLStylesFmt['simuledit'] = ".editconflict { color:green;
|
||||
font-style:italic; margin-top:1.33em; margin-bottom:1.33em; }\n";
|
||||
|
||||
function Merge($newtext,$oldtext,$pagetext) {
|
||||
global $WorkDir,$SysMergeCmd, $SysMergePassthru;
|
||||
SDV($SysMergeCmd,"/usr/bin/diff3 -L '' -L '' -L '' -m -E");
|
||||
if (substr($newtext,-1,1)!="\n") $newtext.="\n";
|
||||
if (substr($oldtext,-1,1)!="\n") $oldtext.="\n";
|
||||
if (substr($pagetext,-1,1)!="\n") $pagetext.="\n";
|
||||
$tempnew = tempnam($WorkDir,"new");
|
||||
$tempold = tempnam($WorkDir,"old");
|
||||
$temppag = tempnam($WorkDir,"page");
|
||||
if ($newfp=fopen($tempnew,'w')) { fputs($newfp,$newtext); fclose($newfp); }
|
||||
if ($oldfp=fopen($tempold,'w')) { fputs($oldfp,$oldtext); fclose($oldfp); }
|
||||
if ($pagfp=fopen($temppag,'w')) { fputs($pagfp,$pagetext); fclose($pagfp); }
|
||||
$mergetext = '';
|
||||
if (IsEnabled($SysMergePassthru, 0)) {
|
||||
ob_start();
|
||||
passthru("$SysMergeCmd $tempnew $tempold $temppag");
|
||||
$mergetext = ob_get_clean();
|
||||
}
|
||||
else {
|
||||
$merge_handle = popen("$SysMergeCmd $tempnew $tempold $temppag",'r');
|
||||
if ($merge_handle) {
|
||||
while (!feof($merge_handle)) $mergetext .= fread($merge_handle,4096);
|
||||
pclose($merge_handle);
|
||||
}
|
||||
}
|
||||
@unlink($tempnew); @unlink($tempold); @unlink($temppag);
|
||||
return $mergetext;
|
||||
}
|
||||
|
||||
function MergeSimulEdits($pagename,&$page,&$new) {
|
||||
global $Now, $EnablePost, $MessagesFmt, $WorkDir;
|
||||
if (@!$_POST['basetime'] || !PageExists($pagename)
|
||||
|| $page['time'] >= $Now
|
||||
|| $_POST['basetime']>=$page['time']
|
||||
|| $page['text'] == $new['text']) return;
|
||||
$EnablePost = 0;
|
||||
$old = array();
|
||||
RestorePage($pagename,$page,$old,"diff:{$_POST['basetime']}");
|
||||
$text = Merge($new['text'],$old['text'],$page['text']);
|
||||
if ($text > '') { $new['text'] = $text; $ec = '$[EditConflict]'; }
|
||||
else $ec = '$[EditWarning]';
|
||||
XLSDV('en', array(
|
||||
'EditConflict' => "The page you are
|
||||
editing has been modified since you started editing it.
|
||||
The modifications have been merged into the text below,
|
||||
you may want to verify the results of the merge before
|
||||
pressing save. Conflicts the system couldn't resolve are
|
||||
bracketed by <<<<<<< and
|
||||
>>>>>>>.",
|
||||
'EditWarning' => "The page you are editing has been modified
|
||||
since you started editing it. If you continue, your
|
||||
changes will overwrite any changes that others have made."));
|
||||
$MessagesFmt[] = "<p class='editconflict'>$ec
|
||||
(<a target='_blank' href='\$PageUrl?action=diff'>$[View changes]</a>)
|
||||
</p>\n";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2007 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file implements the skin selection code for PmWiki. Skin
|
||||
selection is controlled by the $Skin variable, which can also
|
||||
be an array (in which case the first skin found is loaded).
|
||||
|
||||
In addition, $ActionSkin[$action] specifies other skins to be
|
||||
searched based on the current action.
|
||||
|
||||
*/
|
||||
|
||||
SDV($Skin, 'pmwiki');
|
||||
SDV($ActionSkin['print'], 'print');
|
||||
SDV($FarmPubDirUrl, $PubDirUrl);
|
||||
SDV($PageLogoUrl, "$FarmPubDirUrl/skins/pmwiki/pmwiki-32.gif");
|
||||
SDVA($TmplDisplay, array('PageEditFmt' => 0));
|
||||
|
||||
# $PageTemplateFmt is deprecated
|
||||
if (isset($PageTemplateFmt)) LoadPageTemplate($pagename,$PageTemplateFmt);
|
||||
else {
|
||||
$x = array_merge((array)@$ActionSkin[$action], (array)$Skin);
|
||||
SetSkin($pagename, $x);
|
||||
}
|
||||
|
||||
SDV($PageCSSListFmt,array(
|
||||
'pub/css/local.css' => '$PubDirUrl/css/local.css',
|
||||
'pub/css/{$Group}.css' => '$PubDirUrl/css/{$Group}.css',
|
||||
'pub/css/{$FullName}.css' => '$PubDirUrl/css/{$FullName}.css'));
|
||||
|
||||
foreach((array)$PageCSSListFmt as $k=>$v)
|
||||
if (file_exists(FmtPageName($k,$pagename)))
|
||||
$HTMLHeaderFmt[] = "<link rel='stylesheet' type='text/css' href='$v' />\n";
|
||||
|
||||
# SetSkin changes the current skin to the first available skin from
|
||||
# the $skin array.
|
||||
function SetSkin($pagename, $skin) {
|
||||
global $Skin, $SkinLibDirs, $SkinDir, $SkinDirUrl,
|
||||
$IsTemplateLoaded, $PubDirUrl, $FarmPubDirUrl, $FarmD, $GCount;
|
||||
SDV($SkinLibDirs, array(
|
||||
"./pub/skins/\$Skin" => "$PubDirUrl/skins/\$Skin",
|
||||
"$FarmD/pub/skins/\$Skin" => "$FarmPubDirUrl/skins/\$Skin"));
|
||||
foreach((array)$skin as $sfmt) {
|
||||
$Skin = FmtPageName($sfmt, $pagename); $GCount = 0;
|
||||
foreach($SkinLibDirs as $dirfmt => $urlfmt) {
|
||||
$SkinDir = FmtPageName($dirfmt, $pagename);
|
||||
if (is_dir($SkinDir))
|
||||
{ $SkinDirUrl = FmtPageName($urlfmt, $pagename); break 2; }
|
||||
}
|
||||
}
|
||||
if (!is_dir($SkinDir)) {
|
||||
unset($Skin);
|
||||
Abort("?unable to find skin from list ".implode(' ',(array)$skin));
|
||||
}
|
||||
$IsTemplateLoaded = 0;
|
||||
if (file_exists("$SkinDir/$Skin.php"))
|
||||
include_once("$SkinDir/$Skin.php");
|
||||
else if (file_exists("$SkinDir/skin.php"))
|
||||
include_once("$SkinDir/skin.php");
|
||||
if ($IsTemplateLoaded) return;
|
||||
if (file_exists("$SkinDir/$Skin.tmpl"))
|
||||
LoadPageTemplate($pagename, "$SkinDir/$Skin.tmpl");
|
||||
else if (file_exists("$SkinDir/skin.tmpl"))
|
||||
LoadPageTemplate($pagename, "$SkinDir/skin.tmpl");
|
||||
else if (($dh = opendir($SkinDir))) {
|
||||
while (($fname = readdir($dh)) !== false) {
|
||||
if ($fname[0] == '.') continue;
|
||||
if (substr($fname, -5) != '.tmpl') continue;
|
||||
if ($IsTemplateLoaded)
|
||||
Abort("?unable to find unique template in $SkinDir");
|
||||
LoadPageTemplate($pagename, "$SkinDir/$fname");
|
||||
}
|
||||
closedir($dh);
|
||||
}
|
||||
if (!$IsTemplateLoaded) Abort("Unable to load $Skin template", 'skin');
|
||||
}
|
||||
|
||||
|
||||
# LoadPageTemplate loads a template into $TmplFmt
|
||||
function LoadPageTemplate($pagename,$tfilefmt) {
|
||||
global $PageStartFmt, $PageEndFmt,
|
||||
$EnableSkinDiag, $HTMLHeaderFmt, $HTMLFooterFmt,
|
||||
$IsTemplateLoaded, $TmplFmt, $TmplDisplay,
|
||||
$PageTextStartFmt, $PageTextEndFmt, $SkinDirectivesPattern;
|
||||
|
||||
SDV($PageTextStartFmt, "\n<div id='wikitext'>\n");
|
||||
SDV($PageTextEndFmt, "</div>\n");
|
||||
SDV($SkinDirectivesPattern,
|
||||
"[[<]!--((?:wiki|file|function|markup):.*?)--[]>]");
|
||||
|
||||
$sddef = array('PageEditFmt' => 0);
|
||||
$k = implode('', file(FmtPageName($tfilefmt, $pagename)));
|
||||
|
||||
if (IsEnabled($EnableSkinDiag, 0)) {
|
||||
if (!preg_match('/<!--((No)?(HT|X)MLHeader|HeaderText)-->/i', $k))
|
||||
Abort("Skin template missing <!--HTMLHeader-->", 'htmlheader');
|
||||
if (!preg_match('/<!--(No)?(HT|X)MLFooter-->/i', $k))
|
||||
Abort("Skin template missing <!--HTMLFooter-->", 'htmlheader');
|
||||
}
|
||||
|
||||
$sect = preg_split(
|
||||
'#[[<]!--(/?(?:Page[A-Za-z]+Fmt|(?:HT|X)ML(?:Head|Foot)er|HeaderText|PageText).*?)--[]>]#',
|
||||
$k, 0, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$TmplFmt['Start'] = array_merge(array('headers:'),
|
||||
preg_split("/$SkinDirectivesPattern/s",
|
||||
array_shift($sect),0,PREG_SPLIT_DELIM_CAPTURE));
|
||||
$TmplFmt['End'] = array($PageTextEndFmt);
|
||||
$ps = 'Start';
|
||||
while (count($sect)>0) {
|
||||
$k = array_shift($sect);
|
||||
$v = preg_split("/$SkinDirectivesPattern/s",
|
||||
array_shift($sect),0,PREG_SPLIT_DELIM_CAPTURE);
|
||||
$TmplFmt[$ps][] = "<!--$k-->";
|
||||
if ($k{0} == '/')
|
||||
{ $TmplFmt[$ps][] = (count($v) > 1) ? $v : $v[0]; continue; }
|
||||
@list($var, $sd) = explode(' ', $k, 2);
|
||||
$GLOBALS[$var] = (count($v) > 1) ? $v : $v[0];
|
||||
if ($sd > '') $sddef[$var] = $sd;
|
||||
if ($var == 'PageText') { $ps = 'End'; }
|
||||
if ($var == 'HTMLHeader' || $var == 'XMLHeader')
|
||||
$TmplFmt[$ps][] = &$HTMLHeaderFmt;
|
||||
if ($var == 'HTMLFooter' || $var == 'XMLFooter')
|
||||
$TmplFmt[$ps][] = &$HTMLFooterFmt;
|
||||
## <!--HeaderText--> deprecated, 2.1.16
|
||||
if ($var == 'HeaderText') { $TmplFmt[$ps][] = &$HTMLHeaderFmt; }
|
||||
$TmplFmt[$ps][$var] =& $GLOBALS[$var];
|
||||
}
|
||||
array_push($TmplFmt['Start'], $PageTextStartFmt);
|
||||
$PageStartFmt = 'function:PrintSkin Start';
|
||||
$PageEndFmt = 'function:PrintSkin End';
|
||||
$IsTemplateLoaded = 1;
|
||||
SDVA($TmplDisplay, $sddef);
|
||||
}
|
||||
|
||||
# This function is called to print a portion of the skin template
|
||||
# according to the settings in $TmplDisplay.
|
||||
function PrintSkin($pagename, $arg) {
|
||||
global $TmplFmt, $TmplDisplay;
|
||||
foreach ($TmplFmt[$arg] as $k => $v)
|
||||
if (!isset($TmplDisplay[$k]) || $TmplDisplay[$k])
|
||||
PrintFmt($pagename, $v);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2002-2007 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This file allows features to be easily enabled/disabled in config.php.
|
||||
Simply set variables for the features to be enabled/disabled in config.php
|
||||
before including this file. For example:
|
||||
$EnableQAMarkup=0; #disable Q: and A: tags
|
||||
$EnableWikiStyles=1; #include default wikistyles
|
||||
Each feature has a default setting, if the corresponding $Enable
|
||||
variable is not set then you get the default.
|
||||
|
||||
To avoid processing any of the features of this file, set
|
||||
$EnableStdConfig = 0;
|
||||
in config.php.
|
||||
*/
|
||||
|
||||
$pagename = ResolvePageName($pagename);
|
||||
|
||||
if (!IsEnabled($EnableStdConfig,1)) return;
|
||||
|
||||
|
||||
if (!function_exists('session_start') && IsEnabled($EnableRequireSession, 1))
|
||||
Abort('PHP is lacking session support', 'session');
|
||||
|
||||
if (IsEnabled($EnablePGCust,1))
|
||||
include_once("$FarmD/scripts/pgcust.php");
|
||||
|
||||
if (isset($PostConfig) && is_array($PostConfig)) {
|
||||
asort($PostConfig, SORT_NUMERIC);
|
||||
foreach ($PostConfig as $k=>$v) {
|
||||
if (!$k || !$v || $v<0 || $v>=50) continue;
|
||||
if (function_exists($k)) $k($pagename);
|
||||
elseif (file_exists($k)) include_once($k);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsEnabled($EnableRobotControl,1))
|
||||
include_once("$FarmD/scripts/robots.php");
|
||||
|
||||
if (IsEnabled($EnableCaches, 1))
|
||||
include_once("$FarmD/scripts/caches.php");
|
||||
|
||||
## Scripts that are part of a standard PmWiki distribution.
|
||||
if (IsEnabled($EnableAuthorTracking,1))
|
||||
include_once("$FarmD/scripts/author.php");
|
||||
if (IsEnabled($EnablePrefs, 1))
|
||||
include_once("$FarmD/scripts/prefs.php");
|
||||
if (IsEnabled($EnableSimulEdit, 1))
|
||||
include_once("$FarmD/scripts/simuledit.php");
|
||||
if (IsEnabled($EnableDrafts, 0))
|
||||
include_once("$FarmD/scripts/draft.php"); # after simuledit + prefs
|
||||
if (IsEnabled($EnableSkinLayout,1))
|
||||
include_once("$FarmD/scripts/skins.php"); # must come after prefs
|
||||
if (@$Transition || IsEnabled($EnableTransitions, 0))
|
||||
include_once("$FarmD/scripts/transition.php"); # must come after skins
|
||||
if (@$LinkWikiWords || IsEnabled($EnableWikiWords, 0))
|
||||
include_once("$FarmD/scripts/wikiwords.php"); # must come before stdmarkup
|
||||
if (IsEnabled($EnableStdMarkup,1))
|
||||
include_once("$FarmD/scripts/stdmarkup.php"); # must come after transition
|
||||
if ($action=='diff' && @!$HandleActions['diff'])
|
||||
include_once("$FarmD/scripts/pagerev.php");
|
||||
if (IsEnabled($EnableWikiTrails,1))
|
||||
include_once("$FarmD/scripts/trails.php");
|
||||
if (IsEnabled($EnableWikiStyles,1))
|
||||
include_once("$FarmD/scripts/wikistyles.php");
|
||||
if (IsEnabled($EnableMarkupExpressions, 1)
|
||||
&& !function_exists('MarkupExpression'))
|
||||
include_once("$FarmD/scripts/markupexpr.php");
|
||||
if (IsEnabled($EnablePageList,1))
|
||||
include_once("$FarmD/scripts/pagelist.php");
|
||||
if (IsEnabled($EnableVarMarkup,1))
|
||||
include_once("$FarmD/scripts/vardoc.php");
|
||||
if (!function_exists(@$DiffFunction))
|
||||
include_once("$FarmD/scripts/phpdiff.php");
|
||||
if ($action=='crypt')
|
||||
include_once("$FarmD/scripts/crypt.php");
|
||||
if ($action=='edit' && IsEnabled($EnableGUIButtons,0))
|
||||
include_once("$FarmD/scripts/guiedit.php");
|
||||
if (IsEnabled($EnableForms,1))
|
||||
include_once("$FarmD/scripts/forms.php"); # must come after prefs
|
||||
if (IsEnabled($EnableUpload,0))
|
||||
include_once("$FarmD/scripts/upload.php"); # must come after forms
|
||||
if (IsEnabled($EnableBlocklist, 0))
|
||||
include_once("$FarmD/scripts/blocklist.php");
|
||||
if (IsEnabled($EnableNotify,0))
|
||||
include_once("$FarmD/scripts/notify.php");
|
||||
if (IsEnabled($EnableDiag,0))
|
||||
include_once("$FarmD/scripts/diag.php");
|
||||
|
||||
if (IsEnabled($EnableUpgradeCheck,1)) {
|
||||
SDV($StatusPageName, "$SiteAdminGroup.Status");
|
||||
$page = ReadPage($StatusPageName, READPAGE_CURRENT);
|
||||
if (@$page['updatedto'] != $VersionNum)
|
||||
{ $action = 'upgrade'; include_once("$FarmD/scripts/upgrades.php"); }
|
||||
}
|
||||
@@ -0,0 +1,504 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2015 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script defines PmWiki's standard markup. It is automatically
|
||||
included from stdconfig.php unless $EnableStdMarkup==0.
|
||||
|
||||
Each call to Markup() below adds a new rule to PmWiki's translation
|
||||
engine (unless a rule with the same name has already been defined).
|
||||
The form of the call is Markup($id,$where,$pat,$rep);
|
||||
$id is a unique name for the rule, $where is the position of the rule
|
||||
relative to another rule, $pat is the pattern to look for, and
|
||||
$rep is the string to replace it with.
|
||||
*/
|
||||
|
||||
## first we preserve text in [=...=] and [@...@]
|
||||
function PreserveText($sigil, $text, $lead) {
|
||||
if ($sigil=='=') return $lead.Keep($text);
|
||||
if (strpos($text, "\n")===false)
|
||||
return "$lead<code class='escaped'>".Keep($text)."</code>";
|
||||
$text = preg_replace("/\n[^\\S\n]+$/", "\n", $text);
|
||||
if ($lead == "" || $lead == "\n")
|
||||
return "$lead<pre class='escaped'>".Keep($text)."</pre>";
|
||||
return "$lead<:pre,1>".Keep($text);
|
||||
}
|
||||
|
||||
Markup_e('[=','_begin',"/(\n[^\\S\n]*)?\\[([=@])(.*?)\\2\\]/s",
|
||||
"PreserveText(\$m[2], \$m[3], \$m[1])");
|
||||
Markup_e('restore','<_end',"/$KeepToken(\\d.*?)$KeepToken/",
|
||||
'$GLOBALS[\'KPV\'][$m[1]]');
|
||||
Markup('<:', '>restore',
|
||||
'/<:[^>]*>/', '');
|
||||
Markup('<vspace>', '<restore',
|
||||
'/<vspace>/',
|
||||
"<div class='vspace'></div>");
|
||||
Markup('<vspace><p>', '<<vspace>',
|
||||
"/<vspace><p\\b(([^>]*)(\\s)class=(['\"])([^>]*?)\\4)?/",
|
||||
"<p$2 class='vspace$3$5'");
|
||||
|
||||
## remove carriage returns before preserving text
|
||||
Markup('\\r','<[=','/\\r/','');
|
||||
|
||||
# $[phrase] substitutions
|
||||
Markup_e('$[phrase]', '>[=',
|
||||
'/\\$\\[(?>([^\\]]+))\\]/', "NoCache(XL(\$m[1]))");
|
||||
|
||||
# {$var} substitutions
|
||||
Markup_e('{$var}', '>$[phrase]',
|
||||
'/\\{(\\*|!?[-\\w.\\/\\x80-\\xff]*)(\\$:?\\w[-\\w]*)\\}/',
|
||||
"PRR(PVSE(PageVar(\$pagename, \$m[2], \$m[1])))");
|
||||
|
||||
# invisible (:textvar:...:) definition
|
||||
Markup('textvar:', '<split',
|
||||
'/\\(: *\\w[-\\w]* *:(?!\\)).*?:\\)/s', '');
|
||||
|
||||
## handle relative text vars in includes
|
||||
if (IsEnabled($EnableRelativePageVars, 1))
|
||||
SDV($QualifyPatterns["/\\{([-\\w\\x80-\\xfe]*)(\\$:?\\w+\\})/"],
|
||||
PCCF("'{' . (\$m[1] ? MakePageName(\$pagename, \$m[1]) : \$pagename) . \$m[2]", 'qualify'));
|
||||
|
||||
|
||||
## character entities
|
||||
Markup('&','<if','/&(?>([A-Za-z0-9]+|#\\d+|#[xX][A-Fa-f0-9]+));/',
|
||||
'&$1;');
|
||||
Markup('&amp;', '<&', '/&amp;/', Keep('&'));
|
||||
|
||||
|
||||
## (:if:)/(:elseif:)/(:else:)
|
||||
SDV($CondTextPattern,
|
||||
"/ \\(:if (\d*) (?:end)? \\b[^\n]*?:\\)
|
||||
.*?
|
||||
(?: \\(: (?:if\\1|if\\1end) \\s* :\\)
|
||||
| (?=\\(:(?:if\\1|if\\1end)\\b[^\n]*?:\\) | $)
|
||||
)
|
||||
/six");
|
||||
SDV($CondTextReplacement, "CondText2(\$pagename, \$m[0], \$m[1])");
|
||||
Markup_e('if', 'fulltext', $CondTextPattern, $CondTextReplacement);
|
||||
|
||||
function CondText2($pagename, $text, $code = '') {
|
||||
global $Conditions, $CondTextPattern, $CondTextReplacement;
|
||||
$if = "if$code";
|
||||
$repl = str_replace('$pagename', "'$pagename'", $CondTextReplacement);
|
||||
|
||||
$parts = preg_split("/\\(:(?:{$if}end|$if|else *$if|else$code)\\b\\s*(.*?)\\s*:\\)/",
|
||||
$text, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$x = array_shift($parts);
|
||||
while ($parts) {
|
||||
list($condspec, $condtext) = array_splice($parts, 0, 2);
|
||||
if (!preg_match("/^\\s*(!?)\\s*(\\S*)\\s*(.*?)\\s*$/", $condspec, $match)) continue;
|
||||
list($x, $not, $condname, $condparm) = $match;
|
||||
|
||||
if (!isset($Conditions[$condname]))
|
||||
return PPRE($CondTextPattern, $repl, $condtext);
|
||||
$tf = @eval("return ({$Conditions[$condname]});");
|
||||
if ($tf xor $not)
|
||||
return PPRE($CondTextPattern, $repl, $condtext);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
## (:include:)
|
||||
Markup_e('include', '>if',
|
||||
'/\\(:include\\s+(\\S.*?):\\)/i',
|
||||
"PRR(IncludeText(\$pagename, \$m[1]))");
|
||||
|
||||
## (:redirect:)
|
||||
Markup_e('redirect', '<include',
|
||||
'/\\(:redirect\\s+(\\S.*?):\\)/i',
|
||||
"RedirectMarkup(\$pagename, \$m[1])");
|
||||
|
||||
$SaveAttrPatterns['/\\(:(if\\d*|include|redirect)(\\s.*?)?:\\)/i'] = ' ';
|
||||
|
||||
## GroupHeader/GroupFooter handling
|
||||
Markup_e('nogroupheader', '>include',
|
||||
'/\\(:nogroupheader:\\)/i',
|
||||
"PZZ(\$GLOBALS['GroupHeaderFmt']='')");
|
||||
Markup_e('nogroupfooter', '>include',
|
||||
'/\\(:nogroupfooter:\\)/i',
|
||||
"PZZ(\$GLOBALS['GroupFooterFmt']='')");
|
||||
Markup_e('groupheader', '>nogroupheader',
|
||||
'/\\(:groupheader:\\)/i',
|
||||
"PRR(FmtPageName(\$GLOBALS['GroupHeaderFmt'],\$pagename))");
|
||||
Markup_e('groupfooter','>nogroupfooter',
|
||||
'/\\(:groupfooter:\\)/i',
|
||||
"PRR(FmtPageName(\$GLOBALS['GroupFooterFmt'],\$pagename))");
|
||||
|
||||
## (:nl:)
|
||||
Markup('nl0','<split',"/([^\n])(?>(?:\\(:nl:\\))+)([^\n])/i","$1\n$2");
|
||||
Markup('nl1','>nl0',"/\\(:nl:\\)/i",'');
|
||||
|
||||
## \\$ (end of line joins)
|
||||
Markup_e('\\$','>nl1',"/\\\\(?>(\\\\*))\n/",
|
||||
"str_repeat('<br />',strlen(\$m[1]))");
|
||||
|
||||
## Remove one <:vspace> after !headings
|
||||
Markup('!vspace', '>\\$', "/^(!(?>[^\n]+)\n)<:vspace>/m", '$1');
|
||||
|
||||
## (:noheader:),(:nofooter:),(:notitle:)...
|
||||
Markup_e('noheader', 'directives',
|
||||
'/\\(:noheader:\\)/i',
|
||||
"SetTmplDisplay('PageHeaderFmt',0)");
|
||||
Markup_e('nofooter', 'directives',
|
||||
'/\\(:nofooter:\\)/i',
|
||||
"SetTmplDisplay('PageFooterFmt',0)");
|
||||
Markup_e('notitle', 'directives',
|
||||
'/\\(:notitle:\\)/i',
|
||||
"SetTmplDisplay('PageTitleFmt',0)");
|
||||
Markup_e('noleft', 'directives',
|
||||
'/\\(:noleft:\\)/i',
|
||||
"SetTmplDisplay('PageLeftFmt',0)");
|
||||
Markup_e('noright', 'directives',
|
||||
'/\\(:noright:\\)/i',
|
||||
"SetTmplDisplay('PageRightFmt',0)");
|
||||
Markup_e('noaction', 'directives',
|
||||
'/\\(:noaction:\\)/i',
|
||||
"SetTmplDisplay('PageActionFmt',0)");
|
||||
|
||||
## (:spacewikiwords:)
|
||||
Markup_e('spacewikiwords', 'directives',
|
||||
'/\\(:(no)?spacewikiwords:\\)/i',
|
||||
"PZZ(\$GLOBALS['SpaceWikiWords']=(\$m[1]!='no'))");
|
||||
|
||||
## (:linkwikiwords:)
|
||||
Markup_e('linkwikiwords', 'directives',
|
||||
'/\\(:(no)?linkwikiwords:\\)/i',
|
||||
"PZZ(\$GLOBALS['LinkWikiWords']=(\$m[1]!='no'))");
|
||||
|
||||
## (:linebreaks:)
|
||||
Markup_e('linebreaks', 'directives',
|
||||
'/\\(:(no)?linebreaks:\\)/i',
|
||||
"PZZ(\$GLOBALS['HTMLPNewline'] = (\$m[1]!='no') ? '<br />' : '')");
|
||||
|
||||
## (:messages:)
|
||||
Markup_e('messages', 'directives',
|
||||
'/^\\(:messages:\\)/i',
|
||||
"'<:block>'.Keep(
|
||||
FmtPageName(implode('',(array)\$GLOBALS['MessagesFmt']), \$pagename))");
|
||||
|
||||
## (:comment:)
|
||||
Markup('comment', 'directives', '/\\(:comment .*?:\\)/i', '');
|
||||
|
||||
## (:title:) +fix for PITS:00266, 00779
|
||||
$tmpwhen = IsEnabled($EnablePageTitlePriority, 0) ? '<include' : 'directives';
|
||||
$tmpkeep = IsEnabled($EnablePageTitlePriority, 0) ? '1' : 'NULL';
|
||||
Markup_e('title', $tmpwhen,
|
||||
'/\\(:title\\s(.*?):\\)/i',
|
||||
"PZZ(PCache(\$pagename,
|
||||
\$zz=array('title' => SetProperty(\$pagename, 'title', \$m[1], NULL, $tmpkeep))))");
|
||||
unset($tmpwhen, $tmpkeep);
|
||||
|
||||
## (:keywords:), (:description:)
|
||||
Markup_e('keywords', 'directives',
|
||||
"/\\(:keywords?\\s+(.+?):\\)/i",
|
||||
"PZZ(SetProperty(\$pagename, 'keywords', \$m[1], ', '))");
|
||||
Markup_e('description', 'directives',
|
||||
"/\\(:description\\s+(.+?):\\)/i",
|
||||
"PZZ(SetProperty(\$pagename, 'description', \$m[1], '\n'))");
|
||||
$HTMLHeaderFmt['meta'] = 'function:PrintMetaTags';
|
||||
function PrintMetaTags($pagename, $args) {
|
||||
global $PCache;
|
||||
foreach(array('keywords', 'description') as $n) {
|
||||
foreach((array)@$PCache[$pagename]["=p_$n"] as $v) {
|
||||
$v = str_replace("'", ''', $v);
|
||||
print "<meta name='$n' content='$v' />\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#### inline markups ####
|
||||
## ''emphasis''
|
||||
Markup("''",'inline',"/''(.*?)''/",'<em>$1</em>');
|
||||
|
||||
## '''strong'''
|
||||
Markup("'''","<''","/'''(.*?)'''/",'<strong>$1</strong>');
|
||||
|
||||
## '''''strong emphasis'''''
|
||||
Markup("'''''","<'''","/'''''(.*?)'''''/",'<strong><em>$1</em></strong>');
|
||||
|
||||
## @@code@@
|
||||
Markup('@@','inline','/@@(.*?)@@/','<code>$1</code>');
|
||||
|
||||
## '+big+', '-small-'
|
||||
Markup("'+","<'''''","/'\\+(.*?)\\+'/",'<big>$1</big>');
|
||||
Markup("'-","<'''''","/'\\-(.*?)\\-'/",'<small>$1</small>');
|
||||
|
||||
## '^superscript^', '_subscript_'
|
||||
Markup("'^","<'''''","/'\\^(.*?)\\^'/",'<sup>$1</sup>');
|
||||
Markup("'_","<'''''","/'_(.*?)_'/",'<sub>$1</sub>');
|
||||
|
||||
## [+big+], [-small-]
|
||||
Markup_e('[+','inline','/\\[(([-+])+)(.*?)\\1\\]/',
|
||||
"'<span style=\'font-size:'.(round(pow(6/5,(\$m[2]=='-'? -1:1)*strlen(\$m[1]))*100,0)).'%\'>'.
|
||||
\$m[3].'</span>'");
|
||||
|
||||
## {+ins+}, {-del-}
|
||||
Markup('{+','inline','/\\{\\+(.*?)\\+\\}/','<ins>$1</ins>');
|
||||
Markup('{-','inline','/\\{-(.*?)-\\}/','<del>$1</del>');
|
||||
|
||||
## [[<<]] (break)
|
||||
Markup('[[<<]]','inline','/\\[\\[<<\\]\\]/',"<br clear='all' />");
|
||||
|
||||
###### Links ######
|
||||
## [[free links]]
|
||||
Markup_e('[[','links',"/(?>\\[\\[\\s*(.*?)\\]\\])($SuffixPattern)/",
|
||||
"Keep(MakeLink(\$pagename,\$m[1],NULL,\$m[2]),'L')");
|
||||
|
||||
## [[!Category]]
|
||||
SDV($CategoryGroup,'Category');
|
||||
SDV($LinkCategoryFmt,"<a class='categorylink' href='\$LinkUrl'>\$LinkText</a>");
|
||||
Markup_e('[[!','<[[','/\\[\\[!(.*?)\\]\\]/',
|
||||
"Keep(MakeLink(\$pagename,'$CategoryGroup/'.\$m[1],NULL,'',\$GLOBALS['LinkCategoryFmt']),'L')");
|
||||
# This is a temporary workaround for blank category pages.
|
||||
# It may be removed in a future release (Pm, 2006-01-24)
|
||||
if (preg_match("/^$CategoryGroup\\./", $pagename)) {
|
||||
SDV($DefaultPageTextFmt, '');
|
||||
SDV($PageNotFoundHeaderFmt, 'HTTP/1.1 200 Ok');
|
||||
}
|
||||
|
||||
## [[target | text]]
|
||||
Markup_e('[[|','<[[',
|
||||
"/(?>\\[\\[([^|\\]]*)\\|\\s*)(.*?)\\s*\\]\\]($SuffixPattern)/",
|
||||
"Keep(MakeLink(\$pagename,\$m[1],\$m[2],\$m[3]),'L')");
|
||||
|
||||
## [[text -> target ]]
|
||||
Markup_e('[[->','>[[|',
|
||||
"/(?>\\[\\[([^\\]]+?)\\s*-+>\\s*)(.*?)\\]\\]($SuffixPattern)/",
|
||||
"Keep(MakeLink(\$pagename,\$m[2],\$m[1],\$m[3]),'L')");
|
||||
|
||||
if (IsEnabled($EnableRelativePageLinks, 1))
|
||||
SDV($QualifyPatterns['/(\\[\\[(?>[^\\]]+?->)?\\s*)([-\\w\\x80-\\xfe\\s\'()]+([|#?].*?)?\\]\\])/'],
|
||||
PCCF("\$m[1].\$group.'/'.\$m[2]", 'qualify'));
|
||||
|
||||
## [[#anchor]]
|
||||
Markup_e('[[#','<[[','/(?>\\[\\[#([A-Za-z][-.:\\w]*))\\]\\]/',
|
||||
"Keep(TrackAnchors(\$m[1]) ? '' : \"<a name='{\$m[1]}' id='{\$m[1]}'></a>\", 'L')");
|
||||
function TrackAnchors($x) { global $SeenAnchor; return @$SeenAnchor[$x]++; }
|
||||
|
||||
## [[target |#]] reference links
|
||||
Markup_e('[[|#', '<[[|',
|
||||
"/(?>\\[\\[([^|\\]]+))\\|\\s*#\\s*\\]\\]/",
|
||||
"Keep(MakeLink(\$pagename,\$m[1],'['.++\$GLOBALS['MarkupFrame'][0]['ref'].']'),'L')");
|
||||
|
||||
## [[target |+]] title links moved inside LinkPage()
|
||||
|
||||
## bare urllinks
|
||||
Markup_e('urllink','>[[',
|
||||
"/\\b(?>(\\L))[^\\s$UrlExcludeChars]*[^\\s.,?!$UrlExcludeChars]/",
|
||||
"Keep(MakeLink(\$pagename,\$m[0],\$m[0]),'L')");
|
||||
|
||||
## mailto: links
|
||||
Markup_e('mailto','<urllink',
|
||||
"/\\bmailto:([^\\s$UrlExcludeChars]*[^\\s.,?!$UrlExcludeChars])/",
|
||||
"Keep(MakeLink(\$pagename,\$m[0],\$m[1]),'L')");
|
||||
|
||||
## inline images
|
||||
Markup_e('img','<urllink',
|
||||
"/\\b(?>(\\L))([^\\s$UrlExcludeChars]+$ImgExtPattern)(\"([^\"]*)\")?/",
|
||||
"Keep(\$GLOBALS['LinkFunctions'][\$m[1]](\$pagename,\$m[1],\$m[2],\$m[4],\$m[1].\$m[2],
|
||||
\$GLOBALS['ImgTagFmt']),'L')");
|
||||
|
||||
## bare wikilinks
|
||||
## v2.2: markup rule moved to scripts/wikiwords.php)
|
||||
Markup('wikilink', '>urllink');
|
||||
|
||||
## escaped `WikiWords
|
||||
## v2.2: rule kept here for markup compatibility with 2.1 and earlier
|
||||
Markup_e('`wikiword', '<wikilink',
|
||||
"/`(($GroupPattern([\\/.]))?($WikiWordPattern))/",
|
||||
"Keep(\$m[1])");
|
||||
|
||||
#### Block markups ####
|
||||
## Completely blank lines don't do anything.
|
||||
Markup('blank', '<block', '/^\\s+$/', '');
|
||||
|
||||
## process any <:...> markup (after all other block markups)
|
||||
Markup_e('^<:','>block','/^(?=\\s*\\S)(<:([^>]+)>)?/',"Block(\$m[2])");
|
||||
|
||||
## unblocked lines w/block markup become anonymous <:block>
|
||||
Markup('^!<:', '<^<:',
|
||||
"/^(?!<:)(?=.*(<\\/?($BlockPattern)\\b)|$KeepToken\\d+B$KeepToken)/",
|
||||
'<:block>');
|
||||
|
||||
## Lines that begin with displayed images receive their own block. A
|
||||
## pipe following the image indicates a "caption" (generates a linebreak).
|
||||
Markup_e('^img', 'block',
|
||||
"/^((?>(\\s+|%%|%[A-Za-z][-,=:#\\w\\s'\".]*%)*)$KeepToken(\\d+L)$KeepToken)(\\s*\\|\\s?)?(.*)$/",
|
||||
"(strpos(\$GLOBALS['KPV'][\$m[3]],'<img')===false) ? \$m[0] :
|
||||
'<:block,1><div>'.\$m[1] . (\$m[4] ? '<br />' : '') .\$m[5].'</div>'");
|
||||
|
||||
|
||||
## Whitespace at the beginning of lines can be used to maintain the
|
||||
## indent level of a previous list item, or a preformatted text block.
|
||||
Markup_e('^ws', '<^img', '/^\\s+ #1/x', "WSIndent(\$m[0])");
|
||||
function WSIndent($i) {
|
||||
global $MarkupFrame;
|
||||
$icol = strlen($i);
|
||||
for($depth = count(@$MarkupFrame[0]['cs']); $depth > 0; $depth--)
|
||||
if (@$MarkupFrame[0]['is'][$depth] == $icol) {
|
||||
$MarkupFrame[0]['idep'] = $depth;
|
||||
$MarkupFrame[0]['icol'] = $icol;
|
||||
return '';
|
||||
}
|
||||
return $i;
|
||||
}
|
||||
|
||||
## The $EnableWSPre setting uses leading spaces on markup lines to indicate
|
||||
## blocks of preformatted text.
|
||||
SDV($EnableWSPre, 1);
|
||||
Markup_e('^ ', 'block',
|
||||
'/^\\s+ #2/x',
|
||||
"(\$GLOBALS['EnableWSPre'] > 0 && strlen(\$m[0]) >= \$GLOBALS['EnableWSPre'])
|
||||
? '<:pre,1>'.\$m[0] : \$m[0]");
|
||||
|
||||
## bullet lists
|
||||
Markup('^*','block','/^(\\*+)\\s?(\\s*)/','<:ul,$1,$0>$2');
|
||||
|
||||
## numbered lists
|
||||
Markup('^#','block','/^(#+)\\s?(\\s*)/','<:ol,$1,$0>$2');
|
||||
|
||||
## indented (->) /hanging indent (-<) text
|
||||
Markup('^->','block','/^(?>(-+))>\\s?(\\s*)/','<:indent,$1,$1 $2>$2');
|
||||
Markup('^-<','block','/^(?>(-+))<\\s?(\\s*)/','<:outdent,$1,$1 $2>$2');
|
||||
|
||||
## definition lists
|
||||
Markup('^::','block','/^(:+)(\s*)([^:]+):/','<:dl,$1,$1$2><dt>$2$3</dt><dd>');
|
||||
|
||||
## Q: and A:
|
||||
Markup('^Q:', 'block', '/^Q:(.*)$/', "<:block,1><p class='question'>$1</p>");
|
||||
Markup('^A:', 'block', '/^A:/', Keep(''));
|
||||
|
||||
## tables
|
||||
## ||cell||, ||!header cell||, ||!caption!||
|
||||
Markup_e('^||||', 'block',
|
||||
'/^\\|\\|.*\\|\\|.*$/',
|
||||
"FormatTableRow(\$m[0])");
|
||||
## ||table attributes
|
||||
Markup_e('^||','>^||||','/^\\|\\|(.*)$/',
|
||||
"PZZ(\$GLOBALS['BlockMarkups']['table'][0] = '<table '.PQA(\$m[1]).'>')
|
||||
.'<:block,1>'");
|
||||
|
||||
## headings
|
||||
Markup_e('^!', 'block',
|
||||
'/^(!{1,6})\\s?(.*)$/',
|
||||
"'<:block,1><h'.strlen(\$m[1]).'>'.\$m[2].'</h'.strlen(\$m[1]).'>'");
|
||||
|
||||
## horiz rule
|
||||
Markup('^----','>^->','/^----+/','<:block,1><hr />');
|
||||
|
||||
#### (:table:) markup (AdvancedTables)
|
||||
function Cells($name,$attr) {
|
||||
global $MarkupFrame, $EnableTableAutoValignTop;
|
||||
$attr = PQA($attr);
|
||||
$tattr = @$MarkupFrame[0]['tattr'];
|
||||
$name = strtolower($name);
|
||||
$key = preg_replace('/end$/', '', $name);
|
||||
if (preg_match("/^(?:head|cell)(nr)?$/", $name)) $key = 'cell';
|
||||
$out = '<:block>'.MarkupClose($key);
|
||||
if (substr($name, -3) == 'end') return $out;
|
||||
$cf = & $MarkupFrame[0]['closeall'];
|
||||
if ($name == 'table') $MarkupFrame[0]['tattr'] = $attr;
|
||||
else if ($key == 'cell') {
|
||||
if (IsEnabled($EnableTableAutoValignTop, 1) && strpos($attr, "valign=")===false)
|
||||
$attr .= " valign='top'";
|
||||
$t = (strpos($name, 'head')===0 ) ? 'th' : 'td';
|
||||
if (!@$cf['table']) {
|
||||
$tattr = @$MarkupFrame[0]['tattr'];
|
||||
$out .= "<table $tattr><tr><$t $attr>";
|
||||
$cf['table'] = '</tr></table>';
|
||||
} else if ( preg_match("/nr$/", $name)) $out .= "</tr><tr><$t $attr>";
|
||||
else $out .= "<$t $attr>";
|
||||
$cf['cell'] = "</$t>";
|
||||
} else {
|
||||
$tag = preg_replace('/\\d+$/', '', $key);
|
||||
$out .= "<$tag $attr>";
|
||||
$cf[$key] = "</$tag>";
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
Markup_e('table', '<block',
|
||||
'/^\\(:(table|cell|cellnr|head|headnr|tableend|(?:div\\d*|section\\d*|article\\d*|header|footer|nav|address|aside)(?:end)?)(\\s.*?)?:\\)/i',
|
||||
"Cells(\$m[1],\$m[2])");
|
||||
Markup('^>>', '<table',
|
||||
'/^>>(.+?)<<(.*)$/',
|
||||
'(:div:)%div $1 apply=div%$2 ');
|
||||
Markup('^>><<', '<^>>',
|
||||
'/^>><</',
|
||||
'(:divend:)');
|
||||
|
||||
#### special stuff ####
|
||||
## (:markup:) for displaying markup examples
|
||||
function MarkupMarkup($pagename, $text, $opt = '') {
|
||||
global $MarkupWordwrapFunction, $MarkupWrapTag;
|
||||
SDV($MarkupWordwrapFunction,
|
||||
PCCF('return str_replace(" ", " ", nl2br($m));'));
|
||||
SDV($MarkupWrapTag, 'code');
|
||||
$MarkupMarkupOpt = array('class' => 'vert');
|
||||
$opt = array_merge($MarkupMarkupOpt, ParseArgs($opt));
|
||||
$html = MarkupToHTML($pagename, $text, array('escape' => 0));
|
||||
if (@$opt['caption'])
|
||||
$caption = str_replace("'", ''',
|
||||
"<caption>{$opt['caption']}</caption>");
|
||||
$class = preg_replace('/[^-\\s\\w]+/', ' ', @$opt['class']);
|
||||
if (strpos($class, 'horiz') !== false)
|
||||
{ $sep = ''; $pretext = $MarkupWordwrapFunction($text, 40); }
|
||||
else
|
||||
{ $sep = '</tr><tr>'; $pretext = $MarkupWordwrapFunction($text, 75); }
|
||||
return Keep(@"<table class='markup $class' align='center'>$caption
|
||||
<tr><td class='markup1' valign='top'><$MarkupWrapTag>$pretext</$MarkupWrapTag></td>$sep<td
|
||||
class='markup2' valign='top'>$html</td></tr></table>");
|
||||
}
|
||||
|
||||
Markup_e('markup', '<[=',
|
||||
"/\\(:markup(\\s+([^\n]*?))?:\\)[^\\S\n]*\\[([=@])(.*?)\\3\\]/si",
|
||||
"MarkupMarkup(\$pagename, \$m[4], \$m[2])");
|
||||
Markup_e('markupend', '>markup',
|
||||
"/\\(:markup(\\s+([^\n]*?))?:\\)[^\\S\n]*\n(.*?)\\(:markupend:\\)/si",
|
||||
"MarkupMarkup(\$pagename, \$m[3], \$m[1])");
|
||||
|
||||
SDV($HTMLStylesFmt['markup'], "
|
||||
table.markup { border:2px dotted #ccf; width:90%; }
|
||||
td.markup1, td.markup2 { padding-left:10px; padding-right:10px; }
|
||||
table.vert td.markup1 { border-bottom:1px solid #ccf; }
|
||||
table.horiz td.markup1 { width:23em; border-right:1px solid #ccf; }
|
||||
table.markup caption { text-align:left; }
|
||||
div.faq p, div.faq pre { margin-left:2em; }
|
||||
div.faq p.question { margin:1em 0 0.75em 0; font-weight:bold; }
|
||||
div.faqtoc div.faq * { display:none; }
|
||||
div.faqtoc div.faq p.question
|
||||
{ display:block; font-weight:normal; margin:0.5em 0 0.5em 20px; line-height:normal; }
|
||||
div.faqtoc div.faq p.question * { display:inline; }
|
||||
");
|
||||
|
||||
#### Special conditions ####
|
||||
## The code below adds (:if date:) conditions to the markup.
|
||||
$Conditions['date'] = "CondDate(\$condparm)";
|
||||
|
||||
function CondDate($condparm) {
|
||||
global $Now;
|
||||
if (!preg_match('/^(\\S*?)(\\.\\.(\\S*))?(\\s+\\S.*)?$/',
|
||||
trim($condparm), $match))
|
||||
return false;
|
||||
if ($match[4] == '') { $x0 = $Now; NoCache(); }
|
||||
else { list($x0, $x1) = DRange($match[4]); }
|
||||
if ($match[1] > '') {
|
||||
list($t0, $t1) = DRange($match[1]);
|
||||
if ($x0 < $t0) return false;
|
||||
if ($match[2] == '' && $x0 >= $t1) return false;
|
||||
}
|
||||
if ($match[3] > '') {
|
||||
list($t0, $t1) = DRange($match[3]);
|
||||
if ($x0 >= $t1) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
# This pattern enables the (:encrypt <phrase>:) markup/replace-on-save
|
||||
# pattern.
|
||||
SDV($ROSPatterns['/\\(:encrypt\\s+([^\\s:=]+).*?:\\)/'], PCCF("return pmcrypt(\$m[1]);"));
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2002-2013 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script enables markup of the form <<|TrailPage|>> to be
|
||||
used to build "trails" through wiki documents.
|
||||
|
||||
This feature is automatically included from stdconfig.php unless
|
||||
disabled by $EnableWikiTrails = 0; . To explicitly include this feature,
|
||||
execute
|
||||
include_once("scripts/trails.php");
|
||||
from config.php somewhere.
|
||||
|
||||
Once enabled, the <<|TrailPage|>> markup is replaced with
|
||||
<< PrevPage | TrailPage | NextPage >> on output. TrailPage should
|
||||
contain either a bullet or number list defining the sequence of pages
|
||||
in the "trail".
|
||||
|
||||
The ^|TrailPage|^ markup uses the depth of the bullets to display
|
||||
the ancestry of the TrailPage to the current one. The <|TrailPage|>
|
||||
markup is like <<|TrailPage|>> except that "< PrevPage |" and
|
||||
"| NextPage >" are omitted if at the beginning or end of the
|
||||
trail respectively. Thanks to John Rankin for contributing these
|
||||
markups and the original suggestion for WikiTrails.
|
||||
*/
|
||||
|
||||
Markup_e('<<|','<links','/<<\\|([^|]+|\\[\\[(.+?)\\]\\])\\|>>/',
|
||||
"PRR(MakeTrailStop(\$pagename,\$m[1]))");
|
||||
Markup_e('<|','><<|','/<\\|([^|]+|\\[\\[(.+?)\\]\\])\\|>/',
|
||||
"PRR(MakeTrailStopB(\$pagename,\$m[1]))");
|
||||
Markup_e('^|','<links','/\\^\\|([^|]+|\\[\\[(.+?)\\]\\])\\|\\^/',
|
||||
"PRR(MakeTrailPath(\$pagename,\$m[1]))");
|
||||
|
||||
SDVA($SaveAttrPatterns, array(
|
||||
'/<<\\|([^|]+|\\[\\[(.+?)\\]\\])\\|>>/' => '$1',
|
||||
'/<\\|([^|]+|\\[\\[(.+?)\\]\\])\\|>/' => '$1',
|
||||
'/\\^\\|([^|]+|\\[\\[(.+?)\\]\\])\\|\\^/' => '$1'));
|
||||
|
||||
$Conditions['ontrail'] = 'CondOnTrail($pagename, $condparm)';
|
||||
|
||||
function CondOnTrail($pagename, $condparm) {
|
||||
@list($trailname, $pn) = preg_split('/\\s+/', $condparm, 2);
|
||||
$trail = ReadTrail($pagename, $trailname);
|
||||
if (!$trail) return false;
|
||||
$pn = ($pn > '') ? MakePageName($pagename, $pn) : $pagename;
|
||||
foreach($trail as $t)
|
||||
if ($t['pagename'] == $pn) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function ReadTrail($pagename, $trailname) {
|
||||
global $RASPageName, $SuffixPattern, $GroupPattern, $WikiWordPattern,
|
||||
$LinkWikiWords;
|
||||
if (preg_match('/^\\[\\[(.+?)(->|\\|)(.+?)\\]\\]$/', $trailname, $m))
|
||||
$trailname = ($m[2] == '|') ? $m[1] : $m[3];
|
||||
$trailtext = RetrieveAuthSection($pagename, $trailname);
|
||||
$trailname = $RASPageName;
|
||||
$trailtext = Qualify($trailname, $trailtext);
|
||||
$t = array();
|
||||
$n = 0;
|
||||
foreach(explode("\n", PHSC(@$trailtext, ENT_NOQUOTES))
|
||||
as $x) {
|
||||
$x = preg_replace("/\\[\\[([^\\]]*)->([^\\]]*)\\]\\]/",'[[$2|$1]]',$x);
|
||||
if (!preg_match("/^([#*:]+) \\s*
|
||||
(\\[\\[([^:#!|][^|:]*?)(?:\".*?\")?(\\|.*?)?\\]\\]($SuffixPattern)
|
||||
| (($GroupPattern([\\/.]))?$WikiWordPattern)) (.*)/x",$x,$match))
|
||||
continue;
|
||||
if (@$match[6]) {
|
||||
if (!$LinkWikiWords) continue;
|
||||
$tgt = MakePageName($trailname, $match[6]);
|
||||
} else $tgt = MakePageName($trailname, $match[3]);
|
||||
$t[$n]['depth'] = $depth = strlen($match[1]);
|
||||
$t[$n]['pagename'] = $tgt;
|
||||
$t[$n]['markup'] = $match[2];
|
||||
$t[$n]['detail'] = $match[9];
|
||||
for($i=$depth;$i<10;$i++) $d[$i]=$n;
|
||||
if ($depth>1) $t[$n]['parent']=@$d[$depth-1];
|
||||
$n++;
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
|
||||
function MakeTrailStop($pagename,$trailname) {
|
||||
$t = ReadTrail($pagename,$trailname);
|
||||
$prev=''; $next='';
|
||||
for($i=0;$i<count($t);$i++) {
|
||||
if ($t[$i]['pagename']==$pagename) {
|
||||
if ($i>0) $prev = $t[$i-1]['markup'];
|
||||
if ($i+1<count($t)) $next = $t[$i+1]['markup'];
|
||||
}
|
||||
}
|
||||
return "<span class='wikitrail'><< $prev | $trailname | $next >></span>";
|
||||
}
|
||||
|
||||
function MakeTrailStopB($pagename,$trailname) {
|
||||
$t = ReadTrail($pagename,$trailname);
|
||||
$prev = ''; $next = '';
|
||||
for($i=0;$i<count($t);$i++) {
|
||||
if ($t[$i]['pagename']==$pagename) {
|
||||
if ($i>0) $prev = '< '.$t[$i-1]['markup'].' | ';
|
||||
if ($i+1<count($t)) $next = ' | '.$t[$i+1]['markup'].' >';
|
||||
}
|
||||
}
|
||||
return "<span class='wikitrail'>$prev$trailname$next</span>";
|
||||
}
|
||||
|
||||
function MakeTrailPath($pagename,$trailname) {
|
||||
global $TrailPathSep;
|
||||
SDV($TrailPathSep,' | ');
|
||||
$t = ReadTrail($pagename,$trailname);
|
||||
$crumbs = '';
|
||||
for($i=0;$i<count($t);$i++) {
|
||||
if ($t[$i]['pagename']==$pagename) {
|
||||
while (@$t[$i]['depth']>0) {
|
||||
$crumbs = $TrailPathSep.$t[$i]['markup'].$crumbs;
|
||||
$i = @$t[$i]['parent'];
|
||||
}
|
||||
return "<span class='wikitrail'>$trailname$crumbs</span>";
|
||||
}
|
||||
}
|
||||
return "<span class='wikitrail'>$trailname</span>";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,277 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2005-2014 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script handles various "fixup transitions" that might need to
|
||||
occur to help existing sites smoothly upgrade to newer releases of
|
||||
PmWiki. Rather than put the workarounds in the main code files, we
|
||||
try to centralize them here so we can see what's deprecated and a
|
||||
simple switch (?trans=0 in the url) can tell the admin if his site
|
||||
is relying on an outdated feature or way of doing things.
|
||||
|
||||
Transitions defined in this script:
|
||||
|
||||
$Transition['nosessionencode'] - turn off session encoding
|
||||
|
||||
$Transition['version'] < 2001967 - all transitions listed above
|
||||
|
||||
$Transition['wspre'] - leading spaces are pre text
|
||||
|
||||
$Transition['version'] < 2001941 - all transitions listed above
|
||||
|
||||
$Transition['wikiwords'] - 2.1-style WikiWord processing
|
||||
|
||||
$Transition['version'] < 2001924 - all transitions listed above
|
||||
|
||||
$Transition['abslinks'] - absolute links/page vars
|
||||
|
||||
$Transition['version'] < 2001901 - all transitions listed above
|
||||
|
||||
$Transition['vspace'] - restore <p class='vspace'></p>
|
||||
|
||||
$Transition['version'] < 2001006 - all transitions listed above
|
||||
|
||||
$Transition['fplbygroup'] - restore FPLByGroup function
|
||||
|
||||
$Transition['version'] < 2000915 - all transitions listed above
|
||||
|
||||
$Transition['mainrc'] - keep using Main.AllRecentChanges
|
||||
$Transition['mainapprovedurls'] - keep using Main.ApprovedUrls
|
||||
$Transition['pageeditfmt'] - default $PageEditFmt value
|
||||
$Transition['mainpages'] - other default pages in Main
|
||||
|
||||
$Transition['version'] < 1999944 - all transitions listed above
|
||||
|
||||
To get all of the transitions for compatibility with a previous
|
||||
version of PmWiki, simply set $Transition['version'] in a local
|
||||
configuration file to the version number you want compatibility
|
||||
with. All of the transitions associated with that version will
|
||||
then be enabled. Example:
|
||||
|
||||
# Keep compatibility with PmWiki version 2.0.13
|
||||
$Transition['version'] = 2000013;
|
||||
|
||||
To explicitly enable or disable specific transitions, set
|
||||
the corresponding $Transition[] element to 1 or 0. This will
|
||||
override the $Transition['version'] item listed above. For
|
||||
example, to enable just the 'pageeditfmt' transition, use
|
||||
|
||||
$Transition['pageeditfmt'] = 1;
|
||||
|
||||
*/
|
||||
|
||||
## if ?trans=0 is specified, then we don't do any fixups.
|
||||
if (@$_REQUEST['trans']==='0') return;
|
||||
|
||||
## set a default Transition version if we don't have one
|
||||
SDV($Transition['version'], $VersionNum);
|
||||
|
||||
## Transitions from 2.2.0-beta67
|
||||
if (@$Transition['version'] < 2001967)
|
||||
SDVA($Transition, array('nosessionencode' => 1));
|
||||
|
||||
if (@$Transition['nosessionencode']) {
|
||||
$SessionEncode = NULL;
|
||||
$SessionDecode = NULL;
|
||||
}
|
||||
|
||||
## Transitions from 2.2.0-beta41
|
||||
if (@$Transition['version'] < 2001941)
|
||||
SDVA($Transition, array('wspre' => 1));
|
||||
|
||||
if (@$Transition['wspre']) SDV($EnableWSPre, 1);
|
||||
|
||||
## Transitions from 2.2.0-beta24
|
||||
if (@$Transition['version'] < 2001924)
|
||||
SDVA($Transition, array('wikiwords' => 1));
|
||||
|
||||
## wikiwords:
|
||||
## This restores the PmWiki 2.1 behavior for WikiWord processing.
|
||||
## WikiWords aren't linked by default, but appear with
|
||||
## <span class='wikiword'>...</span> tags around them.
|
||||
if (@$Transition['wikiwords']) {
|
||||
SDV($EnableWikiWords, 1);
|
||||
SDV($LinkWikiWords, 0);
|
||||
}
|
||||
|
||||
## Transitions from 2.2.0-beta1
|
||||
if (@$Transition['version'] < 2001901)
|
||||
SDVA($Transition, array('abslinks' => 1));
|
||||
|
||||
## abslinks:
|
||||
## This restores settings so that PmWiki treats all links
|
||||
## as absolute (following the 2.1.x and earlier interpretation).
|
||||
if (@$Transition['abslinks']) {
|
||||
SDV($EnableRelativePageLinks, 0);
|
||||
SDV($EnableRelativePageVars, 0);
|
||||
}
|
||||
|
||||
## Transitions from 2.1.12
|
||||
|
||||
if (@$Transition['version'] < 2001012)
|
||||
SDVA($Transition, array('nodivnest' => 1));
|
||||
|
||||
## nodivnest:
|
||||
## This restores the PmWiki 2.1.11 behavior that doesn't
|
||||
## allow nesting of divs and tables.
|
||||
if (@$Transition['nodivnest']) {
|
||||
function TCells($name,$attr) {
|
||||
global $MarkupFrame;
|
||||
$attr = preg_replace('/([a-zA-Z]=)([^\'"]\\S*)/',"\$1'\$2'",$attr);
|
||||
$tattr = @$MarkupFrame[0]['tattr'];
|
||||
$name = strtolower($name);
|
||||
$out = '<:block>';
|
||||
if (strncmp($name, 'cell', 4) != 0 || @$MarkupFrame[0]['closeall']['div']) {
|
||||
$out .= @$MarkupFrame[0]['closeall']['div'];
|
||||
unset($MarkupFrame[0]['closeall']['div']);
|
||||
$out .= @$MarkupFrame[0]['closeall']['table'];
|
||||
unset($MarkupFrame[0]['closeall']['table']);
|
||||
}
|
||||
if ($name == 'div') {
|
||||
$MarkupFrame[0]['closeall']['div'] = "</div>";
|
||||
$out .= "<div $attr>";
|
||||
}
|
||||
if ($name == 'table') $MarkupFrame[0]['tattr'] = $attr;
|
||||
if (strncmp($name, 'cell', 4) == 0) {
|
||||
if (strpos($attr, "valign=")===false) $attr .= " valign='top'";
|
||||
if (!@$MarkupFrame[0]['closeall']['table']) {
|
||||
$MarkupFrame[0]['closeall']['table'] = "</td></tr></table>";
|
||||
$out .= "<table $tattr><tr><td $attr>";
|
||||
} else if ($name == 'cellnr') $out .= "</td></tr><tr><td $attr>";
|
||||
else $out .= "</td><td $attr>";
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
Markup_e('table', '<block',
|
||||
'/^\\(:(table|cell|cellnr|tableend|div|divend)(\\s.*?)?:\\)/i',
|
||||
"TCells(\$m[1],\$m[2])");
|
||||
}
|
||||
|
||||
|
||||
## Transitions from 2.1.7
|
||||
|
||||
if (@$Transition['version'] < 2001007)
|
||||
SDVA($Transition, array('vspace' => 1));
|
||||
|
||||
## vspace:
|
||||
## This restores PmWiki's use of <p class='vspace'></p> to mark
|
||||
## vertical space in the output.
|
||||
if (@$Transition['vspace']) $HTMLVSpace = "<p class='vspace'></p>";
|
||||
|
||||
|
||||
## Transitions from 2.1.beta15
|
||||
|
||||
if (@$Transition['version'] < 2000915)
|
||||
SDVA($Transition, array('fplbygroup' => 1));
|
||||
|
||||
## fplbygroup:
|
||||
## The FPLByGroup function was removed in 2.1.beta15, this restores it.
|
||||
if (@$Transition['fplbygroup'] && !function_exists('FPLByGroup')) {
|
||||
SDV($FPLFormatOpt['bygroup'], array('fn' => 'FPLByGroup'));
|
||||
function FPLByGroup($pagename, &$matches, $opt) {
|
||||
global $FPLByGroupStartFmt, $FPLByGroupEndFmt, $FPLByGroupGFmt,
|
||||
$FPLByGroupIFmt, $FPLByGroupOpt;
|
||||
SDV($FPLByGroupStartFmt,"<dl class='fplbygroup'>");
|
||||
SDV($FPLByGroupEndFmt,'</dl>');
|
||||
SDV($FPLByGroupGFmt,"<dt><a href='\$ScriptUrl/\$Group'>\$Group</a> /</dt>\n");
|
||||
SDV($FPLByGroupIFmt,"<dd><a href='\$PageUrl'>\$Name</a></dd>\n");
|
||||
SDVA($FPLByGroupOpt, array('readf' => 0, 'order' => 'name'));
|
||||
$matches = MakePageList($pagename,
|
||||
array_merge((array)$FPLByGroupOpt, $opt), 0);
|
||||
if (@$opt['count']) array_splice($matches, $opt['count']);
|
||||
if (count($matches)<1) return '';
|
||||
$out = '';
|
||||
foreach($matches as $pn) {
|
||||
$pgroup = FmtPageName($FPLByGroupGFmt, $pn);
|
||||
if ($pgroup != @$lgroup) { $out .= $pgroup; $lgroup = $pgroup; }
|
||||
$out .= FmtPageName($FPLByGroupIFmt, $pn);
|
||||
}
|
||||
return FmtPageName($FPLByGroupStartFmt, $pagename) . $out .
|
||||
FmtPageName($FPLByGroupEndFmt, $pagename);
|
||||
}
|
||||
}
|
||||
|
||||
## Transitions from 2.0.beta44
|
||||
|
||||
if (@$Transition['version'] < 1999944)
|
||||
SDVA($Transition, array('mainrc' => 1, 'mainapprovedurls' => 1,
|
||||
'pageeditfmt' => 1, 'mainpages' => 1));
|
||||
|
||||
## mainrc:
|
||||
## 2.0.beta44 switched Main.AllRecentChanges to be
|
||||
## $SiteGroup.AllRecentChanges. This setting keeps Main.AllRecentChanges
|
||||
## if it exists.
|
||||
if (@$Transition['mainrc'] && PageExists('Main.AllRecentChanges')) {
|
||||
SDV($RecentChangesFmt['Main.AllRecentChanges'],
|
||||
'* [[$Group.$Name]] . . . $CurrentTime $[by] $AuthorLink');
|
||||
}
|
||||
|
||||
## siteapprovedurls:
|
||||
## 2.0.beta44 switched Main.ApprovedUrls to be $SiteGroup.ApprovedUrls .
|
||||
## This setting keeps using Main.ApprovedUrls if it exists.
|
||||
if (@$Transition['mainapprovedurls'] && PageExists('Main.ApprovedUrls')) {
|
||||
$ApprovedUrlPagesFmt = (array)$ApprovedUrlPagesFmt;
|
||||
if (PageExists(FmtPageName($ApprovedUrlPagesFmt[0], $pagename)))
|
||||
$ApprovedUrlPagesFmt[] = 'Main.ApprovedUrls';
|
||||
else array_unshift($ApprovedUrlPagesFmt, 'Main.ApprovedUrls');
|
||||
}
|
||||
|
||||
## pageeditfmt:
|
||||
## 2.0.beta44 switched to using wiki markup forms for page editing.
|
||||
## However, some sites and skins have customized values of $PageEdit.
|
||||
## This setting restores the default values.
|
||||
if (@$Transition['pageeditfmt']) {
|
||||
SDV($PageEditFmt, "<div id='wikiedit'>
|
||||
<a id='top' name='top'></a>
|
||||
<h1 class='wikiaction'>$[Editing \$FullName]</h1>
|
||||
<form method='post' action='\$PageUrl?action=edit'>
|
||||
<input type='hidden' name='action' value='edit' />
|
||||
<input type='hidden' name='n' value='\$FullName' />
|
||||
<input type='hidden' name='basetime' value='\$EditBaseTime' />
|
||||
\$EditMessageFmt
|
||||
<textarea id='text' name='text' rows='25' cols='60'
|
||||
onkeydown='if (event.keyCode==27) event.returnValue=false;'
|
||||
>\$EditText</textarea><br />
|
||||
$[Author]: <input type='text' name='author' value='\$Author' />
|
||||
<input type='checkbox' name='diffclass' value='minor' \$DiffClassMinor />
|
||||
$[This is a minor edit]<br />
|
||||
<input type='submit' name='post' value=' $[Save] ' />
|
||||
<input type='submit' name='preview' value=' $[Preview] ' />
|
||||
<input type='reset' value=' $[Reset] ' /></form></div>");
|
||||
if (@$_POST['preview'])
|
||||
SDV($PagePreviewFmt, "<div id='wikipreview'>
|
||||
<h2 class='wikiaction'>$[Preview \$FullName]</h2>
|
||||
<p><b>$[Page is unsaved]</b></p>
|
||||
\$PreviewText
|
||||
<hr /><p><b>$[End of preview -- remember to save]</b><br />
|
||||
<a href='#top'>$[Top]</a></p></div>");
|
||||
SDV($HandleEditFmt, array(&$PageStartFmt,
|
||||
&$PageEditFmt, 'wiki:$[PmWiki.EditQuickReference]', &$PagePreviewFmt,
|
||||
&$PageEndFmt));
|
||||
$EditMessageFmt = implode('', $MessagesFmt) . $EditMessageFmt;
|
||||
if ($action=='edit' && IsEnabled($EnableGUIButtons, 0))
|
||||
array_push($EditFunctions, 'GUIEdit');
|
||||
} else $MessagesFmt[] = @$EditMessageFmt;
|
||||
|
||||
|
||||
function GUIEdit($pagename, &$page, &$new) {
|
||||
global $EditMessageFmt;
|
||||
$EditMessageFmt .= GUIButtonCode($pagename);
|
||||
}
|
||||
|
||||
## mainpages:
|
||||
## In 2.0.beta44 several utility pages change location to the new Site
|
||||
## group. These settings cause some skins (that use translations)
|
||||
## to know to link to the new locations.
|
||||
if (@$Transition['mainpages']) {
|
||||
XLSDV('en', array(
|
||||
'Main/SearchWiki' => XL('Site/Search'),
|
||||
'PmWiki.EditQuickReference' => XL('Site/EditQuickReference'),
|
||||
'PmWiki.UploadQuickReference' => XL('Site/UploadQuickReference'),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2007-2011 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
*/
|
||||
global $HandleActions, $HandleAuth;
|
||||
|
||||
$HandleActions['upgrade'] = 'HandleUpgrade';
|
||||
$HandleAuth['upgrade'] = 'read';
|
||||
|
||||
function HandleUpgrade($pagename, $auth = 'ALWAYS') {
|
||||
global $SiteGroup, $SiteAdminGroup, $StatusPageName, $ScriptUrl,
|
||||
$AuthUserPageFmt, $VersionNum, $Version;
|
||||
StopWatch('HandleUpgrade: begin');
|
||||
|
||||
$message = '';
|
||||
$done = '';
|
||||
## check for Site.* --> SiteAdmin.*
|
||||
foreach(array('AuthUser', 'NotifyList', 'Blocklist', 'ApprovedUrls') as $n) {
|
||||
$n0 = "$SiteGroup.$n"; $n1 = "$SiteAdminGroup.$n";
|
||||
StopWatch("HandleUpgrade: checking $n0 -> $n1");
|
||||
## checking AuthUser is special, because Site.AuthUser comes with the
|
||||
## distribution.
|
||||
if ($n == 'AuthUser') {
|
||||
## if we already have a user-modified SiteAdmin.AuthUser, we can skip
|
||||
SDV($AuthUserPageFmt, '$SiteAdminGroup.AuthUser');
|
||||
$n1 = FmtPageName($AuthUserPageFmt, $pagename);
|
||||
$page = ReadPage($n1, READPAGE_CURRENT);
|
||||
if (@$page['time'] > 1000000000) continue;
|
||||
## if there's not a user-modified Site.AuthUser, we can skip
|
||||
$page = ReadPage($n0, READPAGE_CURRENT);
|
||||
if (@$page['time'] == 1000000000) continue;
|
||||
} else if (!PageExists($n0) || PageExists($n1)) continue;
|
||||
|
||||
if (@$_REQUEST['migrate'] == 'yes') {
|
||||
## if the admin wants PmWiki to migrate, do it.
|
||||
$page = RetrieveAuthPage($n0, 'admin', true);
|
||||
StopWatch("HandleUpgrade: copying $n0 -> $n1");
|
||||
if ($page) {
|
||||
WritePage($n1, $page);
|
||||
$done .= "<li>Copied $n0 to $n1</li>";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$message .= "<li>$n0 -> $n1</li>";
|
||||
}
|
||||
|
||||
if ($message) {
|
||||
$migrateurl = "$ScriptUrl?action=upgrade&migrate=yes";
|
||||
$infourl = 'http://www.pmwiki.org/wiki/PmWiki/UpgradeToSiteAdmin';
|
||||
$message =
|
||||
"<h2>Upgrade notice -- SiteAdmin group</h2>
|
||||
<p>This version of PmWiki expects several administrative pages
|
||||
from the <em>Site</em> group to be found in a new <em>SiteAdmin</em> group.
|
||||
On this site, the following pages appear to need to be relocated:</p>
|
||||
<ul>$message</ul>
|
||||
|
||||
<p>For more information about this change, including the various
|
||||
options for proceeding, see</p>
|
||||
<blockquote><a target='_blank' href='$infourl'>$infourl</a></blockquote>
|
||||
|
||||
<form action='$ScriptUrl' method='post'>
|
||||
<p>If you would like PmWiki to attempt to automatically copy
|
||||
these pages into their new <br /> locations for you, try
|
||||
<input type='hidden' name='action' value='upgrade' />
|
||||
<input type='hidden' name='migrate' value='yes' />
|
||||
<input type='submit' value='Relocate pages listed above' />
|
||||
(admin password required) </p>
|
||||
</form>
|
||||
|
||||
<p>If you want to configure PmWiki so that it continues to
|
||||
look for the above pages in <em>$SiteGroup</em>, add the
|
||||
following line near the top of <em>local/config.php</em>:</p>
|
||||
|
||||
<blockquote><pre>\$SiteAdminGroup = \$SiteGroup;</pre></blockquote>
|
||||
|
||||
$Version
|
||||
";
|
||||
print $message;
|
||||
exit;
|
||||
}
|
||||
|
||||
StopWatch("UpgradeCheck: writing $StatusPageName");
|
||||
Lock(2);
|
||||
SDV($StatusPageName, "$SiteAdminGroup.Status");
|
||||
$page = ReadPage($StatusPageName);
|
||||
$page['updatedto'] = $VersionNum;
|
||||
WritePage($StatusPageName, $page);
|
||||
|
||||
if ($done) {
|
||||
$done .= "<li>Updated $StatusPageName</li>";
|
||||
echo "<h2>Upgrade to $Version ... ok</h2><ul>$done</ul>";
|
||||
$GLOBALS['EnableRedirect'] = 0;
|
||||
}
|
||||
Redirect($pagename);
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2015 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script adds upload capabilities to PmWiki. Uploads can be
|
||||
enabled by setting
|
||||
$EnableUpload = 1;
|
||||
in config.php. In addition, an upload password must be set, as
|
||||
the default is to lock uploads. In some configurations it may also
|
||||
be necessary to set values for $UploadDir and $UploadUrlFmt,
|
||||
especially if any form of URL rewriting is being performed.
|
||||
See the PmWiki.UploadsAdmin page for more information.
|
||||
*/
|
||||
|
||||
## $EnableUploadOverwrite determines if we allow previously uploaded
|
||||
## files to be overwritten.
|
||||
SDV($EnableUploadOverwrite,1);
|
||||
|
||||
## $UploadExts contains the list of file extensions we're willing to
|
||||
## accept, along with the Content-Type: value appropriate for each.
|
||||
SDVA($UploadExts,array(
|
||||
'gif' => 'image/gif', 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg',
|
||||
'png' => 'image/png', 'bmp' => 'image/bmp', 'ico' => 'image/x-icon',
|
||||
'wbmp'=> 'image/vnd.wap.wbmp', 'svg' => 'image/svg+xml', 'xcf' => 'image/x-xcf',
|
||||
'mp3' => 'audio/mpeg', 'au' => 'audio/basic', 'wav' => 'audio/x-wav',
|
||||
'ogg' => 'audio/ogg', 'flac' => 'audio/x-flac',
|
||||
'ogv' => 'video/ogg', 'mp4' => 'video/mp4', 'webm' => 'video/webm',
|
||||
'mpg' => 'video/mpeg', 'mpeg' => 'video/mpeg',
|
||||
'mov' => 'video/quicktime', 'qt' => 'video/quicktime',
|
||||
'wmf' => 'text/plain', 'avi' => 'video/x-msvideo',
|
||||
'zip' => 'application/zip', '7z' => 'application/x-7z-compressed',
|
||||
'gz' => 'application/x-gzip', 'tgz' => 'application/x-gzip',
|
||||
'rpm' => 'application/x-rpm',
|
||||
'hqx' => 'application/mac-binhex40', 'sit' => 'application/x-stuffit',
|
||||
'doc' => 'application/msword', 'ppt' => 'application/vnd.ms-powerpoint',
|
||||
'xls' => 'application/vnd.ms-excel', 'mdb' => 'text/plain',
|
||||
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'exe' => 'application/octet-stream',
|
||||
'pdf' => 'application/pdf', 'psd' => 'text/plain',
|
||||
'ps' => 'application/postscript', 'ai' => 'application/postscript',
|
||||
'eps' => 'application/postscript',
|
||||
'htm' => 'text/html', 'html' => 'text/html', 'css' => 'text/css',
|
||||
'fla' => 'application/x-shockwave-flash',
|
||||
'swf' => 'application/x-shockwave-flash',
|
||||
'txt' => 'text/plain', 'rtf' => 'application/rtf',
|
||||
'tex' => 'application/x-tex', 'dvi' => 'application/x-dvi',
|
||||
'odt' => 'application/vnd.oasis.opendocument.text',
|
||||
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
|
||||
'odp' => 'application/vnd.oasis.opendocument.presentation',
|
||||
'odg' => 'application/vnd.oasis.opendocument.graphics',
|
||||
'epub'=> 'application/epub+zip',
|
||||
'kml' => 'application/vnd.google-earth.kml+xml',
|
||||
'kmz' => 'application/vnd.google-earth.kmz',
|
||||
'' => 'text/plain'));
|
||||
|
||||
# Array containing forbidden strings in a filename, array('.php', '.cgi')
|
||||
SDV($UploadBlacklist, array());
|
||||
|
||||
SDV($UploadMaxSize,50000);
|
||||
SDV($UploadPrefixQuota,0);
|
||||
SDV($UploadDirQuota,0);
|
||||
foreach($UploadExts as $k=>$v)
|
||||
if (!isset($UploadExtSize[$k])) $UploadExtSize[$k]=$UploadMaxSize;
|
||||
|
||||
SDV($UploadDir,'uploads');
|
||||
SDV($UploadPermAdd,0444);
|
||||
SDV($UploadPermSet,0);
|
||||
SDV($UploadPrefixFmt,'/$Group');
|
||||
SDV($UploadFileFmt,"$UploadDir$UploadPrefixFmt");
|
||||
$v = preg_replace('#^/(.*/)#', '', $UploadDir);
|
||||
SDV($UploadUrlFmt,preg_replace('#/[^/]*$#', "/$v", $PubDirUrl, 1));
|
||||
SDV($LinkUploadCreateFmt, "<a rel='nofollow' class='createlinktext' href='\$LinkUpload'>\$LinkText</a><a rel='nofollow' class='createlink' href='\$LinkUpload'> Δ</a>");
|
||||
SDVA($ActionTitleFmt, array('upload' => '| $[Attach]'));
|
||||
|
||||
SDV($PageUploadFmt,array("
|
||||
<div id='wikiupload'>
|
||||
<h2 class='wikiaction'>$[Attachments for] {\$FullName}</h2>
|
||||
<h3>\$UploadResult</h3>
|
||||
<form enctype='multipart/form-data' action='{\$PageUrl}' method='post'>
|
||||
<input type='hidden' name='n' value='{\$FullName}' />
|
||||
<input type='hidden' name='action' value='postupload' />
|
||||
<table border='0'>
|
||||
<tr><td align='right'>$[File to upload:]</td><td><input
|
||||
name='uploadfile' type='file' /></td></tr>
|
||||
<tr><td align='right'>$[Name attachment as:]</td>
|
||||
<td><input type='text' name='upname' value='\$UploadName' /><input
|
||||
type='submit' value=' $[Upload] ' /><br />
|
||||
</td></tr></table></form></div>",
|
||||
'wiki:$[{$SiteGroup}/UploadQuickReference]'));
|
||||
XLSDV('en',array(
|
||||
'ULsuccess' => 'successfully uploaded',
|
||||
'ULbadname' => 'invalid attachment name',
|
||||
'ULbadtype' => '\'$upext\' is not an allowed file extension',
|
||||
'ULtoobig' => 'file is larger than maximum allowed by webserver',
|
||||
'ULtoobigext' => 'file is larger than allowed maximum of $upmax
|
||||
bytes for \'$upext\' files',
|
||||
'ULpartial' => 'incomplete file received',
|
||||
'ULnofile' => 'no file uploaded',
|
||||
'ULexists' => 'file with that name already exists',
|
||||
'ULpquota' => 'group quota exceeded',
|
||||
'ULtquota' => 'upload quota exceeded'));
|
||||
SDV($PageAttributes['passwdupload'],'$[Set new upload password:]');
|
||||
SDV($DefaultPasswords['upload'],'*');
|
||||
SDV($AuthCascade['upload'], 'read');
|
||||
SDV($FmtPV['$PasswdUpload'], 'PasswdVar($pn, "upload")');
|
||||
|
||||
Markup_e('attachlist', 'directives',
|
||||
'/\\(:attachlist\\s*(.*?):\\)/i',
|
||||
"Keep('<ul>'.FmtUploadList('$pagename',\$m[1]).'</ul>')");
|
||||
SDV($GUIButtons['attach'], array(220, 'Attach:', '', '$[file.ext]',
|
||||
'$GUIButtonDirUrlFmt/attach.gif"$[Attach file]"'));
|
||||
SDV($LinkFunctions['Attach:'], 'LinkUpload');
|
||||
SDV($IMap['Attach:'], '$1');
|
||||
SDVA($HandleActions, array('upload' => 'HandleUpload',
|
||||
'postupload' => 'HandlePostUpload',
|
||||
'download' => 'HandleDownload'));
|
||||
SDVA($HandleAuth, array('upload' => 'upload',
|
||||
'download' => 'read'));
|
||||
SDV($HandleAuth['postupload'], $HandleAuth['upload']);
|
||||
SDV($UploadVerifyFunction, 'UploadVerifyBasic');
|
||||
|
||||
function MakeUploadName($pagename,$x) {
|
||||
global $UploadNameChars, $MakeUploadNamePatterns;
|
||||
SDV($UploadNameChars, "-\\w. ");
|
||||
SDV($MakeUploadNamePatterns, array(
|
||||
"/[^$UploadNameChars]/" => '',
|
||||
'/\\.[^.]*$/' => PCCF('return strtolower($m[0]);'),
|
||||
'/^[^[:alnum:]_]+/' => '',
|
||||
'/[^[:alnum:]_]+$/' => ''));
|
||||
return PPRA($MakeUploadNamePatterns, $x);
|
||||
}
|
||||
|
||||
function LinkUpload($pagename, $imap, $path, $alt, $txt, $fmt=NULL) {
|
||||
global $FmtV, $UploadFileFmt, $LinkUploadCreateFmt,
|
||||
$UploadUrlFmt, $UploadPrefixFmt, $EnableDirectDownload;
|
||||
if (preg_match('!^(.*)/([^/]+)$!', $path, $match)) {
|
||||
$pagename = MakePageName($pagename, $match[1]);
|
||||
$path = $match[2];
|
||||
}
|
||||
$upname = MakeUploadName($pagename, $path);
|
||||
$encname = rawurlencode($upname);
|
||||
$filepath = FmtPageName("$UploadFileFmt/$upname", $pagename);
|
||||
$FmtV['$LinkUpload'] =
|
||||
FmtPageName("\$PageUrl?action=upload&upname=$encname", $pagename);
|
||||
$FmtV['$LinkText'] = $txt;
|
||||
if (!file_exists($filepath))
|
||||
return FmtPageName($LinkUploadCreateFmt, $pagename);
|
||||
$path = PUE(FmtPageName(IsEnabled($EnableDirectDownload, 1)
|
||||
? "$UploadUrlFmt$UploadPrefixFmt/$encname"
|
||||
: "{\$PageUrl}?action=download&upname=$encname",
|
||||
$pagename));
|
||||
return LinkIMap($pagename, $imap, $path, $alt, $txt, $fmt);
|
||||
}
|
||||
|
||||
# Authenticate group downloads with the group password
|
||||
function UploadAuth($pagename, $auth, $cache=0){
|
||||
global $GroupAttributesFmt, $EnableUploadGroupAuth;
|
||||
if (IsEnabled($EnableUploadGroupAuth,0)){
|
||||
SDV($GroupAttributesFmt,'$Group/GroupAttributes');
|
||||
$pn_upload = FmtPageName($GroupAttributesFmt, $pagename);
|
||||
} else $pn_upload = $pagename;
|
||||
$page = RetrieveAuthPage($pn_upload, $auth, true, READPAGE_CURRENT);
|
||||
if(!$page) Abort("?No '$auth' permissions for $pagename");
|
||||
if($cache) PCache($pn_upload,$page);
|
||||
return true;
|
||||
}
|
||||
|
||||
function HandleUpload($pagename, $auth = 'upload') {
|
||||
global $FmtV,$UploadExtMax, $EnableReadOnly,
|
||||
$HandleUploadFmt,$PageStartFmt,$PageEndFmt,$PageUploadFmt;
|
||||
UploadAuth($pagename, $auth, 1);
|
||||
$FmtV['$UploadName'] = MakeUploadName($pagename,@$_REQUEST['upname']);
|
||||
$upresult = PHSC(@$_REQUEST['upresult']);
|
||||
$uprname = PHSC(@$_REQUEST['uprname']);
|
||||
$FmtV['$upext'] = PHSC(@$_REQUEST['upext']);
|
||||
$FmtV['$upmax'] = PHSC(@$_REQUEST['upmax']);
|
||||
$FmtV['$UploadResult'] = ($upresult) ?
|
||||
FmtPageName("<i>$uprname</i>: $[UL$upresult]",$pagename) :
|
||||
(@$EnableReadOnly ? XL('Cannot modify site -- $EnableReadOnly is set'): '');
|
||||
SDV($HandleUploadFmt,array(&$PageStartFmt,&$PageUploadFmt,&$PageEndFmt));
|
||||
PrintFmt($pagename,$HandleUploadFmt);
|
||||
}
|
||||
|
||||
function HandleDownload($pagename, $auth = 'read') {
|
||||
global $UploadFileFmt, $UploadExts, $DownloadDisposition, $EnableIMSCaching;
|
||||
SDV($DownloadDisposition, "inline");
|
||||
UploadAuth($pagename, $auth);
|
||||
$upname = MakeUploadName($pagename, @$_REQUEST['upname']);
|
||||
$filepath = FmtPageName("$UploadFileFmt/$upname", $pagename);
|
||||
if (!$upname || !file_exists($filepath)) {
|
||||
header("HTTP/1.0 404 Not Found");
|
||||
Abort("?requested file not found");
|
||||
exit();
|
||||
}
|
||||
if (IsEnabled($EnableIMSCaching, 0)) {
|
||||
header('Cache-Control: private');
|
||||
header('Expires: ');
|
||||
$filelastmod = gmdate('D, d M Y H:i:s \G\M\T', filemtime($filepath));
|
||||
if (@$_SERVER['HTTP_IF_MODIFIED_SINCE'] == $filelastmod)
|
||||
{ header("HTTP/1.0 304 Not Modified"); exit(); }
|
||||
header("Last-Modified: $filelastmod");
|
||||
}
|
||||
preg_match('/\\.([^.]+)$/',$filepath,$match);
|
||||
if ($UploadExts[@$match[1]])
|
||||
header("Content-Type: {$UploadExts[@$match[1]]}");
|
||||
header("Content-Length: ".filesize($filepath));
|
||||
header("Content-disposition: $DownloadDisposition; filename=\"$upname\"");
|
||||
$fp = fopen($filepath, "rb");
|
||||
if ($fp) {
|
||||
while (!feof($fp)) echo fread($fp, 4096);
|
||||
flush();
|
||||
fclose($fp);
|
||||
}
|
||||
exit();
|
||||
}
|
||||
|
||||
function HandlePostUpload($pagename, $auth = 'upload') {
|
||||
global $UploadVerifyFunction, $UploadFileFmt, $LastModFile,
|
||||
$EnableUploadVersions, $Now, $RecentUploadsFmt, $FmtV,
|
||||
$NotifyItemUploadFmt, $NotifyItemFmt, $IsUploadPosted,
|
||||
$UploadRedirectFunction, $UploadPermAdd, $UploadPermSet,
|
||||
$EnableReadOnly;
|
||||
|
||||
if(IsEnabled($EnableReadOnly, 0))
|
||||
Abort('Cannot modify site -- $EnableReadOnly is set', 'readonly');
|
||||
|
||||
UploadAuth($pagename, $auth);
|
||||
$uploadfile = $_FILES['uploadfile'];
|
||||
$upname = $_REQUEST['upname'];
|
||||
if ($upname=='') $upname=$uploadfile['name'];
|
||||
$upname = MakeUploadName($pagename,$upname);
|
||||
if (!function_exists($UploadVerifyFunction))
|
||||
Abort('?no UploadVerifyFunction available');
|
||||
$filepath = FmtPageName("$UploadFileFmt/$upname",$pagename);
|
||||
$result = $UploadVerifyFunction($pagename,$uploadfile,$filepath);
|
||||
if ($result=='') {
|
||||
$filedir = preg_replace('#/[^/]*$#','',$filepath);
|
||||
mkdirp($filedir);
|
||||
if (IsEnabled($EnableUploadVersions, 0))
|
||||
@rename($filepath, "$filepath,$Now");
|
||||
if (!move_uploaded_file($uploadfile['tmp_name'],$filepath))
|
||||
{ Abort("?cannot move uploaded file to $filepath"); return; }
|
||||
fixperms($filepath, $UploadPermAdd, $UploadPermSet);
|
||||
if ($LastModFile) { touch($LastModFile); fixperms($LastModFile); }
|
||||
$result = "upresult=success";
|
||||
$FmtV['$upname'] = $upname;
|
||||
$FmtV['$upsize'] = $uploadfile['size'];
|
||||
if (IsEnabled($RecentUploadsFmt, 0)) {
|
||||
PostRecentChanges($pagename, '', '', $RecentUploadsFmt);
|
||||
}
|
||||
if (IsEnabled($NotifyItemUploadFmt, 0) && function_exists('NotifyUpdate')) {
|
||||
$NotifyItemFmt = $NotifyItemUploadFmt;
|
||||
$IsUploadPosted = 1;
|
||||
register_shutdown_function('NotifyUpdate', $pagename, getcwd());
|
||||
}
|
||||
}
|
||||
SDV($UploadRedirectFunction, 'Redirect');
|
||||
$UploadRedirectFunction($pagename,"{\$PageUrl}?action=upload&uprname=$upname&$result");
|
||||
}
|
||||
|
||||
function UploadVerifyBasic($pagename,$uploadfile,$filepath) {
|
||||
global $EnableUploadOverwrite,$UploadExtSize,$UploadPrefixQuota,
|
||||
$UploadDirQuota,$UploadDir, $UploadBlacklist;
|
||||
if (count($UploadBlacklist)) {
|
||||
$tmp = explode("/", $filepath);
|
||||
$upname = strtolower(end($tmp));
|
||||
foreach($UploadBlacklist as $needle) {
|
||||
if (strpos($upname, $needle)!==false) return 'upresult=badname';
|
||||
}
|
||||
}
|
||||
if (!$EnableUploadOverwrite && file_exists($filepath))
|
||||
return 'upresult=exists';
|
||||
preg_match('/\\.([^.\\/]+)$/',$filepath,$match); $ext=@$match[1];
|
||||
$maxsize = $UploadExtSize[$ext];
|
||||
if ($maxsize<=0) return "upresult=badtype&upext=$ext";
|
||||
if ($uploadfile['size']>$maxsize)
|
||||
return "upresult=toobigext&upext=$ext&upmax=$maxsize";
|
||||
switch (@$uploadfile['error']) {
|
||||
case 1: return 'upresult=toobig';
|
||||
case 2: return 'upresult=toobig';
|
||||
case 3: return 'upresult=partial';
|
||||
case 4: return 'upresult=nofile';
|
||||
}
|
||||
if (!is_uploaded_file($uploadfile['tmp_name'])) return 'upresult=nofile';
|
||||
$filedir = preg_replace('#/[^/]*$#','',$filepath);
|
||||
if ($UploadPrefixQuota &&
|
||||
(dirsize($filedir)-@filesize($filepath)+$uploadfile['size']) >
|
||||
$UploadPrefixQuota) return 'upresult=pquota';
|
||||
if ($UploadDirQuota &&
|
||||
(dirsize($UploadDir)-@filesize($filepath)+$uploadfile['size']) >
|
||||
$UploadDirQuota) return 'upresult=tquota';
|
||||
return '';
|
||||
}
|
||||
|
||||
function dirsize($dir) {
|
||||
$size = 0;
|
||||
$dirp = @opendir($dir);
|
||||
if (!$dirp) return 0;
|
||||
while (($file=readdir($dirp)) !== false) {
|
||||
if ($file[0]=='.') continue;
|
||||
if (is_dir("$dir/$file")) $size+=dirsize("$dir/$file");
|
||||
else $size+=filesize("$dir/$file");
|
||||
}
|
||||
closedir($dirp);
|
||||
return $size;
|
||||
}
|
||||
|
||||
function FmtUploadList($pagename, $args) {
|
||||
global $UploadDir, $UploadPrefixFmt, $UploadUrlFmt, $EnableUploadOverwrite,
|
||||
$TimeFmt, $EnableDirectDownload, $IMapLinkFmt, $UrlLinkFmt, $FmtV;
|
||||
|
||||
$opt = ParseArgs($args);
|
||||
if (@$opt[''][0]) $pagename = MakePageName($pagename, $opt[''][0]);
|
||||
if (@$opt['ext'])
|
||||
$matchext = '/\\.('
|
||||
. implode('|', preg_split('/\\W+/', $opt['ext'], -1, PREG_SPLIT_NO_EMPTY))
|
||||
. ')$/i';
|
||||
|
||||
$uploaddir = FmtPageName("$UploadDir$UploadPrefixFmt", $pagename);
|
||||
$uploadurl = FmtPageName(IsEnabled($EnableDirectDownload, 1)
|
||||
? "$UploadUrlFmt$UploadPrefixFmt/"
|
||||
: "\$PageUrl?action=download&upname=",
|
||||
$pagename);
|
||||
|
||||
$dirp = @opendir($uploaddir);
|
||||
if (!$dirp) return '';
|
||||
$filelist = array();
|
||||
while (($file=readdir($dirp)) !== false) {
|
||||
if ($file{0} == '.') continue;
|
||||
if (@$matchext && !preg_match(@$matchext, $file)) continue;
|
||||
$filelist[$file] = rawurlencode($file);
|
||||
}
|
||||
closedir($dirp);
|
||||
$out = array();
|
||||
natcasesort($filelist);
|
||||
$overwrite = '';
|
||||
$fmt = IsEnabled($IMapLinkFmt['Attach:'], $UrlLinkFmt);
|
||||
foreach($filelist as $file=>$encfile) {
|
||||
$FmtV['$LinkUrl'] = PUE("$uploadurl$encfile");
|
||||
$FmtV['$LinkText'] = $file;
|
||||
$FmtV['$LinkUpload'] =
|
||||
FmtPageName("\$PageUrl?action=upload&upname=$encfile", $pagename);
|
||||
$stat = stat("$uploaddir/$file");
|
||||
if ($EnableUploadOverwrite)
|
||||
$overwrite = FmtPageName("<a rel='nofollow' class='createlink'
|
||||
href='\$LinkUpload'> Δ</a>",
|
||||
$pagename);
|
||||
$lnk = FmtPageName($fmt, $pagename);
|
||||
$out[] = "<li> $lnk$overwrite ... ".
|
||||
number_format($stat['size']) . " bytes ... " .
|
||||
strftime($TimeFmt, $stat['mtime']) . "</li>";
|
||||
}
|
||||
return implode("\n",$out);
|
||||
}
|
||||
|
||||
# this adds (:if [!]attachments:) to the markup
|
||||
$Conditions['attachments'] = "AttachExist(\$pagename)";
|
||||
function AttachExist($pagename) {
|
||||
global $UploadDir, $UploadPrefixFmt;
|
||||
$uploaddir = FmtPageName("$UploadDir$UploadPrefixFmt", $pagename);
|
||||
$count = 0;
|
||||
$dirp = @opendir($uploaddir);
|
||||
if ($dirp) {
|
||||
while (($file = readdir($dirp)) !== false)
|
||||
if ($file{0} != '.') $count++;
|
||||
closedir($dirp);
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2013 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script provides a URL-approval capability. To enable this
|
||||
script, add the following line to a configuration file:
|
||||
|
||||
include_once('scripts/urlapprove.php');
|
||||
|
||||
The URL prefixes to be allowed are stored as patterns in
|
||||
$WhiteUrlPatterns. This array can be loaded from config.php, or
|
||||
from the wiki pages given by the $ApprovedUrlPagesFmt[] array.
|
||||
Any http: or https: URL that isn't in $WhiteUrlPatterns is rendered
|
||||
using $UnapprovedLinkFmt.
|
||||
|
||||
The script also provides ?action=approveurls and ?action=approvesites,
|
||||
which scan the current page for any new URLs to be automatically added
|
||||
the first page of $UrlApprovalPagesFmt.
|
||||
|
||||
Finally, the script will block any post containing more than
|
||||
$UnapprovedLinkCountMax unapproved urls in it. By default this
|
||||
is set to a very large number, leaving the posting of unapproved
|
||||
urls wide open, but by setting $UnapprovedLinkCountMax to a smaller
|
||||
number you can limit the number of unapproved urls that make it into
|
||||
a page. (Wikispammers seem to like to post long lists of urls, while
|
||||
more "normal" authors tend to only post a few.)
|
||||
*/
|
||||
|
||||
$LinkFunctions['http:'] = 'LinkHTTP';
|
||||
$LinkFunctions['https:'] = 'LinkHTTP';
|
||||
SDV($ApprovedUrlPagesFmt, array('$SiteAdminGroup.ApprovedUrls'));
|
||||
SDV($UnapprovedLinkFmt,
|
||||
"\$LinkText<a class='apprlink' href='{\$PageUrl}?action=approvesites'>$[(approve sites)]</a>");
|
||||
$HTMLStylesFmt['urlapprove'] = '.apprlink { font-size:smaller; }';
|
||||
SDV($ApproveUrlPattern,
|
||||
"\\bhttps?:[^\\s$UrlExcludeChars]*[^\\s.,?!$UrlExcludeChars]");
|
||||
$WhiteUrlPatterns = (array)$WhiteUrlPatterns;
|
||||
SDV($HandleActions['approveurls'], 'HandleApprove');
|
||||
SDV($HandleAuth['approveurls'], 'edit');
|
||||
SDV($HandleActions['approvesites'], 'HandleApprove');
|
||||
SDV($HandleAuth['approvesites'], 'edit');
|
||||
SDV($UnapprovedLinkCountMax, 1000000);
|
||||
array_splice($EditFunctions, array_search('PostPage', $EditFunctions),
|
||||
0, 'BlockUnapprovedPosts');
|
||||
|
||||
function LinkHTTP($pagename,$imap,$path,$alt,$txt,$fmt=NULL) {
|
||||
global $EnableUrlApprovalRequired, $IMap, $WhiteUrlPatterns, $FmtV,
|
||||
$UnapprovedLink, $UnapprovedLinkCount, $UnapprovedLinkFmt;
|
||||
if (!IsEnabled($EnableUrlApprovalRequired,1))
|
||||
return LinkIMap($pagename,$imap,$path,$alt,$txt,$fmt);
|
||||
static $havereadpages;
|
||||
if (!$havereadpages) { ReadApprovedUrls($pagename); $havereadpages=true; }
|
||||
$p = str_replace(' ','%20',$path);
|
||||
$url = str_replace('$1',$p,$IMap[$imap]);
|
||||
if (!isset($UnapprovedLink)) $UnapprovedLink = array();
|
||||
foreach((array)$WhiteUrlPatterns as $pat) {
|
||||
if (preg_match("!^$pat(/|$)!i",$url))
|
||||
return LinkIMap($pagename,$imap,$path,$alt,$txt,$fmt);
|
||||
}
|
||||
$FmtV['$LinkUrl'] = PUE(str_replace('$1',$path,$IMap[$imap]));
|
||||
$FmtV['$LinkText'] = $txt;
|
||||
$FmtV['$LinkAlt'] = str_replace(array('"',"'"),array('"','''),$alt);
|
||||
$UnapprovedLink[] = $url;
|
||||
@$UnapprovedLinkCount++;
|
||||
return FmtPageName($UnapprovedLinkFmt,$pagename);
|
||||
}
|
||||
|
||||
function ReadApprovedUrls($pagename) {
|
||||
global $ApprovedUrlPagesFmt,$ApproveUrlPattern,$WhiteUrlPatterns;
|
||||
foreach((array)$ApprovedUrlPagesFmt as $p) {
|
||||
$pn = FmtPageName($p, $pagename);
|
||||
StopWatch("ReadApprovedUrls $pn begin");
|
||||
$apage = ReadPage($pn, READPAGE_CURRENT);
|
||||
preg_match_all("/$ApproveUrlPattern/",@$apage['text'],$match);
|
||||
foreach($match[0] as $a)
|
||||
$WhiteUrlPatterns[] = preg_quote($a,'!');
|
||||
StopWatch("ReadApprovedUrls $pn end");
|
||||
}
|
||||
}
|
||||
|
||||
function HandleApprove($pagename, $auth='edit') {
|
||||
global $ApproveUrlPattern,$WhiteUrlPatterns,$ApprovedUrlPagesFmt,$action;
|
||||
Lock(2);
|
||||
$page = ReadPage($pagename);
|
||||
$text = preg_replace('/[()]/','',$page['text']);
|
||||
preg_match_all("/$ApproveUrlPattern/",$text,$match);
|
||||
ReadApprovedUrls($pagename);
|
||||
$addpat = array();
|
||||
foreach($match[0] as $a) {
|
||||
if ($action=='approvesites')
|
||||
$a=preg_replace("!^([^:]+://[^/]+).*$!",'$1',$a);
|
||||
$addpat[] = $a;
|
||||
}
|
||||
if (count($addpat)>0) {
|
||||
$aname = FmtPageName($ApprovedUrlPagesFmt[0],$pagename);
|
||||
$apage = RetrieveAuthPage($aname, $auth);
|
||||
if (!$apage) Abort("?cannot edit $aname");
|
||||
$new = $apage;
|
||||
if (substr($new['text'],-1,1)!="\n") $new['text'].="\n";
|
||||
foreach($addpat as $a) {
|
||||
foreach((array)$WhiteUrlPatterns as $pat)
|
||||
if (preg_match("!^$pat(/|$)!i",$a)) continue 2;
|
||||
$urlp = preg_quote($a,'!');
|
||||
$WhiteUrlPatterns[] = $urlp;
|
||||
$new['text'].=" $a\n";
|
||||
}
|
||||
$_POST['post'] = 'y';
|
||||
PostPage($aname,$apage,$new);
|
||||
}
|
||||
Redirect($pagename);
|
||||
}
|
||||
|
||||
function BlockUnapprovedPosts($pagename, &$page, &$new) {
|
||||
global $EnableUrlApprovalRequired, $UnapprovedLinkCount,
|
||||
$UnapprovedLinkCountMax, $EnablePost, $MessagesFmt, $BlockMessageFmt;
|
||||
if (!IsEnabled($EnableUrlApprovalRequired, 1)) return;
|
||||
if ($UnapprovedLinkCount <= $UnapprovedLinkCountMax) return;
|
||||
if ($page['=auth']['admin']) return;
|
||||
$EnablePost = 0;
|
||||
$MessagesFmt[] = $BlockMessageFmt;
|
||||
$MessagesFmt[] = XL('Too many unapproved external links.');
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2002-2013 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script provides special handling for WikiWords that are
|
||||
preceded by a $, treating them as PmWiki variables to be looked up
|
||||
in the variable documentation pages if such documentation exists.
|
||||
The $VarPagesFmt variable contains a list of pages to be searched
|
||||
to build an index of the variable documentation. This index is
|
||||
generated only once per browse request, and then only when needed.
|
||||
*/
|
||||
|
||||
SDV($VarPagesFmt,array('$[PmWiki.Variables]'));
|
||||
Markup_e('varlink','<wikilink',"/\\$($WikiWordPattern)\\b/",
|
||||
"Keep(VarLink(\$pagename,\$m[1],'$'.\$m[1]))");
|
||||
Markup('vardef','<links',"/^:\\$($WikiWordPattern):/",
|
||||
':[[#$1]]$$1:');
|
||||
Markup_e('varindex', 'directives',
|
||||
'/\\(:varindex:\\)/i',
|
||||
"Keep(VarIndexList(\$pagename))");
|
||||
|
||||
$HTMLStylesFmt['vardoc'] = "a.varlink { text-decoration:none; }\n";
|
||||
|
||||
function VarLink($pagename,$tgt,$txt) {
|
||||
global $VarIndex,$FmtV,$VarLinkMissingFmt,$VarLinkExistsFmt;
|
||||
SDV($VarLinkMissingFmt,'$LinkText');
|
||||
SDV($VarLinkExistsFmt,"<a class='varlink' href='\$LinkUrl'><code class='varlink'>\$LinkText</code></a>");
|
||||
VarIndexLoad($pagename);
|
||||
$FmtV['$LinkText'] = str_replace('$', '$', $txt);
|
||||
$FmtV['$LinkUrl'] = @$VarIndex[$tgt]['url'];
|
||||
if (@!$VarIndex[$tgt]['url'])
|
||||
return FmtPageName($VarLinkMissingFmt,$pagename);
|
||||
return FmtPageName($VarLinkExistsFmt,$pagename);
|
||||
}
|
||||
|
||||
function VarIndexLoad($pagename) {
|
||||
global $VarPagesFmt,$VarIndex,$WikiWordPattern;
|
||||
static $loaded;
|
||||
$VarIndex = (array)@$VarIndex;
|
||||
if ($loaded) return;
|
||||
foreach($VarPagesFmt as $vf) {
|
||||
$v = FmtPageName($vf, $pagename);
|
||||
if (@$loaded[$v]) continue;
|
||||
$vlist = array($v);
|
||||
$t = ReadTrail($pagename,$v);
|
||||
if ($t)
|
||||
for($i=0;$i<count($t);$i++)
|
||||
if (@!$loaded[$t[$i]['pagename']]) $vlist[]=$t[$i]['pagename'];
|
||||
foreach($vlist as $vname) {
|
||||
$vpage = ReadPage($vname, READPAGE_CURRENT); @$loaded[$vname]++;
|
||||
if (!$vpage) continue;
|
||||
if (!preg_match_all("/\n:\\$([[:upper:]]\\w+):/",@$vpage['text'],$match))
|
||||
continue;
|
||||
foreach($match[1] as $n) {
|
||||
$VarIndex[$n]['pagename'] = $vname;
|
||||
$VarIndex[$n]['url'] = FmtPageName("{\$PageUrl}#$n",$vname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# VarIndexList() generates a table of all indexed variables.
|
||||
function VarIndexList($pagename) {
|
||||
global $VarIndex;
|
||||
if (!isset($VarIndex)) VarIndexLoad($pagename);
|
||||
ksort($VarIndex);
|
||||
$out = "<table><tr><th>Variable</th><th>Documented in</th></tr>\n";
|
||||
foreach($VarIndex as $v=>$a)
|
||||
$out .= FmtPageName("<tr><td><a class='varlink'
|
||||
href='{$a['url']}'><code>$$v</code></a></td><td><a
|
||||
href='{\$PageUrl}'>{\$Name}</a></td></tr>\n",$a['pagename']);
|
||||
$out .= "</table>";
|
||||
return $out;
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<?php $Version="pmwiki-2.2.75"; $VersionNum=2002075;
|
||||
@@ -0,0 +1,193 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2004-2015 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
*/
|
||||
|
||||
SDV($WikiStylePattern,'%%|%[A-Za-z][-,=:#\\w\\s\'"().]*%');
|
||||
|
||||
## %% markup
|
||||
Markup('%%','style','%','return ApplyStyles($x);');
|
||||
|
||||
## %define=...% markup on a line by itself
|
||||
Markup_e('%define=', '>split',
|
||||
"/^(?=%define=)((?:$WikiStylePattern)\\s*)+$/",
|
||||
"PZZ(ApplyStyles(\$m[0]))");
|
||||
|
||||
## restore links before applying styles
|
||||
Markup_e('restorelinks','<%%',"/$KeepToken(\\d+L)$KeepToken/",
|
||||
'$GLOBALS[\'KPV\'][$m[1]]');
|
||||
|
||||
# define PmWiki's standard/default wikistyles
|
||||
if (IsEnabled($EnableStdWikiStyles,1)) {
|
||||
## standard colors
|
||||
foreach(array('black','white','red','yellow','blue','gray',
|
||||
'silver','maroon','green','navy','purple') as $c)
|
||||
SDV($WikiStyle[$c]['color'],$c);
|
||||
## %newwin% style opens links in a new window
|
||||
SDV($WikiStyle['newwin']['target'],'_blank');
|
||||
## %comment% style turns markup into a comment via display:none css
|
||||
SDV($WikiStyle['comment']['display'],'none');
|
||||
## display, margin, padding, and border css properties
|
||||
$WikiStyleCSS[] =
|
||||
'float|clear|display|(margin|padding|border)(-(left|right|top|bottom))?';
|
||||
$WikiStyleCSS[] = 'white-space';
|
||||
$WikiStyleCSS[] = '((min|max)-)?(width|height)';
|
||||
## list-styles
|
||||
$WikiStyleCSS[] = 'list-style';
|
||||
foreach(array('decimal'=>'decimal', 'roman'=>'lower-roman',
|
||||
'ROMAN'=>'upper-roman', 'alpha'=>'lower-alpha', 'ALPHA'=>'upper-alpha')
|
||||
as $k=>$v)
|
||||
SDV($WikiStyle[$k],array('apply'=>'list','list-style'=>$v));
|
||||
## apply ranges
|
||||
SDVA($WikiStyleApply,array(
|
||||
'item' => 'li|dt',
|
||||
'list' => 'ul|ol|dl',
|
||||
'div' => 'div',
|
||||
'article' => 'article',
|
||||
'section' => 'section',
|
||||
'nav' => 'nav',
|
||||
'aside' => 'aside',
|
||||
'header' => 'header',
|
||||
'footer' => 'footer',
|
||||
'address' => 'address',
|
||||
'pre' => 'pre',
|
||||
'img' => 'img',
|
||||
'block' => 'p(?!\\s+class=)|div|ul|ol|dl|li|dt|pre|h[1-6]|article|section|nav|aside|address|header|footer',
|
||||
'p' => 'p(?!\\s+class=)'));
|
||||
foreach(array('item', 'list', 'block', 'p', 'div') as $c)
|
||||
SDV($WikiStyle[$c],array('apply'=>$c));
|
||||
## block justifications
|
||||
foreach(array('left','right','center','justify') as $c)
|
||||
SDV($WikiStyle[$c],array('apply'=>'block','text-align'=>$c));
|
||||
## frames, floating frames, and floats
|
||||
SDV($HTMLStylesFmt['wikistyles'], "
|
||||
.frame
|
||||
{ border:1px solid #cccccc; padding:4px; background-color:#f9f9f9; }
|
||||
.lfloat { float:left; margin-right:0.5em; }
|
||||
.rfloat { float:right; margin-left:0.5em; }\n");
|
||||
SDV($WikiStyle['thumb'], array('width' => '100px'));
|
||||
SDV($WikiStyle['frame'], array('class' => 'frame'));
|
||||
SDV($WikiStyle['lframe'], array('class' => 'frame lfloat'));
|
||||
SDV($WikiStyle['rframe'], array('class' => 'frame rfloat'));
|
||||
SDV($WikiStyle['cframe'], array(
|
||||
'class' => 'frame', 'margin-left' => 'auto', 'margin-right' => 'auto',
|
||||
'width' => '200px', 'apply' => 'block', 'text-align' => 'center'));
|
||||
## preformatted text sections
|
||||
SDV($WikiStyle['pre'], array('apply' => 'block', 'white-space' => 'pre'));
|
||||
SDV($WikiStyle['sidehead'], array('apply' => 'block', 'class' => 'sidehead'));
|
||||
}
|
||||
|
||||
SDVA($WikiStyleAttr,array(
|
||||
'vspace' => 'img',
|
||||
'hspace' => 'img',
|
||||
'align' => 'img',
|
||||
'value' => 'li',
|
||||
'target' => 'a',
|
||||
'accesskey' => 'a',
|
||||
'rel' => 'a'));
|
||||
|
||||
SDVA($WikiStyleRepl,array(
|
||||
'/^%(.*)%$/' => '$1',
|
||||
'/\\bbgcolor([:=])/' => 'background-color$1',
|
||||
'/\\b(\d+)pct\\b/' => '$1%',
|
||||
));
|
||||
|
||||
$WikiStyleCSS[] = 'color|background-color';
|
||||
$WikiStyleCSS[] = 'text-align|text-decoration';
|
||||
$WikiStyleCSS[] = 'font-size|font-family|font-weight|font-style';
|
||||
|
||||
SDV($imgTag, '(?:img|object|embed)'); SDV($aTag, 'a'); SDV($spanTag, 'span');
|
||||
|
||||
function ApplyStyles($x) {
|
||||
global $UrlExcludeChars, $WikiStylePattern, $WikiStyleRepl, $WikiStyle,
|
||||
$WikiStyleAttr, $WikiStyleCSS, $WikiStyleApply, $BlockPattern,
|
||||
$WikiStyleTag, $imgTag, $aTag, $spanTag, $WikiStyleAttrPrefix;
|
||||
$wt = @$WikiStyleTag; $ns = $WikiStyleAttrPrefix; $ws = '';
|
||||
$x = PPRE("/\\b(href|src)=(['\"]?)[^$UrlExcludeChars]+\\2/",
|
||||
"Keep(\$m[0])", $x);
|
||||
$x = PPRE("/\\bhttps?:[^$UrlExcludeChars]+/", "Keep(\$m[0])", $x);
|
||||
$parts = preg_split("/($WikiStylePattern)/",$x,-1,PREG_SPLIT_DELIM_CAPTURE);
|
||||
$parts[] = NULL;
|
||||
$out = '';
|
||||
$style = array();
|
||||
$wikicsspat = '/^('.implode('|',(array)$WikiStyleCSS).')$/';
|
||||
while ($parts) {
|
||||
$p = array_shift($parts);
|
||||
if (preg_match("/^$WikiStylePattern\$/",$p)) {
|
||||
$WikiStyle['curr']=$style; $style=array();
|
||||
foreach((array)$WikiStyleRepl as $pat=>$rep)
|
||||
$p=preg_replace($pat,$rep,$p);
|
||||
preg_match_all(
|
||||
'/\\b([a-zA-Z][-\\w]*)([:=]([-#,\\w.()%]+|([\'"]).*?\\4))?/',
|
||||
$p, $match, PREG_SET_ORDER);
|
||||
while ($match) {
|
||||
$m = array_shift($match);
|
||||
if (@$m[2]) $style[$m[1]]=preg_replace('/^([\'"])(.*?)\\1$/','$2',$m[3]);
|
||||
else if (!isset($WikiStyle[$m[1]])) @$style['class'] .= ' ' . $m[1];
|
||||
else {
|
||||
$c = @$style['class'];
|
||||
$style=array_merge($style,(array)$WikiStyle[$m[1]]);
|
||||
if ($c && !preg_match("/(^| )$c( |$)/", $style['class']) )
|
||||
$style['class'] = $c . ' ' . $style['class'];
|
||||
}
|
||||
}
|
||||
if (@$style['define']) {
|
||||
$d = $style['define']; unset($style['define']);
|
||||
$WikiStyle[$d] = $style;
|
||||
}
|
||||
if (@$WikiStyleApply[$style['apply']]) {
|
||||
$apply[$style['apply']] =
|
||||
array_merge((array)@$apply[$style['apply']],$style);
|
||||
$style=array();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (is_null($p))
|
||||
{ $alist=@$apply; unset($alist['']); $p=$out; $out=''; }
|
||||
elseif ($p=='') continue;
|
||||
else { $alist=array(''=>$style); }
|
||||
foreach((array)$alist as $a=>$s) {
|
||||
$spanattr = ''; $stylev = array(); $id = '';
|
||||
foreach((array)$s as $k=>$v) {
|
||||
$v = trim($v);
|
||||
if ($wt) $ws = str_replace('$1', "$ns$k='$v'", $wt);
|
||||
if ($k == 'class' && $v) $spanattr = "{$ns}class='$v'";
|
||||
elseif ($k=='id') $id = preg_replace('/[^-A-Za-z0-9:_.]+/', '_', $v);
|
||||
elseif (($k=='width' || $k=='height') && !@$WikiStyleApply[$a]
|
||||
&& preg_match("/\\s*<$imgTag\\b/", $p))
|
||||
$p = preg_replace("/<($imgTag)\\b(?![^>]*\\s$k=)/",
|
||||
"$ws<$1 $ns$k='$v'", $p);
|
||||
elseif (@$WikiStyleAttr[$k])
|
||||
$p = preg_replace(
|
||||
"/<({$WikiStyleAttr[$k]}(?![^>]*\\s(?:$ns)?$k=))([^>]*)>/s",
|
||||
"$ws<$1 $ns$k='$v' $2>", $p);
|
||||
elseif (preg_match($wikicsspat,$k)) $stylev[]="$k: $v;";
|
||||
}
|
||||
if ($stylev) $spanattr .= " {$ns}style='".implode(' ',$stylev)."'";
|
||||
if ($id) $spanattr .= " {$ns}id='$id'";
|
||||
if ($spanattr) {
|
||||
if ($wt) $ws = str_replace('$1', $spanattr, $wt);
|
||||
if (!@$WikiStyleApply[$a]) {
|
||||
$p = preg_replace("!^(.*?)($|</?($BlockPattern))!s",
|
||||
"$ws<$spanTag $spanattr>$1</$spanTag>$2", $p, 1);
|
||||
}
|
||||
elseif (!preg_match('/^(\\s*<[^>]+>)*$/s',$p) ||
|
||||
preg_match("/<$imgTag\\b/", $p)) {
|
||||
$p = preg_replace("/<({$WikiStyleApply[$a]})\\b/",
|
||||
"$ws<$1 $spanattr", $p);
|
||||
}
|
||||
}
|
||||
if (@$s['color']) {
|
||||
$colorattr = "{$ns}style='color: {$s['color']}'";
|
||||
if ($wt) $ws = str_replace('$1', $colorattr, $wt);
|
||||
$p = preg_replace("/<$aTag\\b/", "$ws<$aTag $colorattr", $p);
|
||||
}
|
||||
}
|
||||
$out .= $p;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2001-2013 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
|
||||
This script adds WikiWord (CamelCase) processing to PmWiki.
|
||||
Originally WikiWords were part of the default configuration,
|
||||
but their usage has died out over time and so it's now optional.
|
||||
|
||||
To enable WikiWord links, simply add the following to
|
||||
a local customization file:
|
||||
|
||||
$EnableWikiWords = 1;
|
||||
|
||||
To have PmWiki recognize and process WikiWords but not link
|
||||
them (i.e., the default behavior in PmWiki 2.1), also add
|
||||
|
||||
$LinkWikiWords = 0;
|
||||
|
||||
If you want only the first occurrence of a WikiWord to be converted
|
||||
to a link, set $WikiWordCountMax=1.
|
||||
|
||||
$WikiWordCountMax = 1; # converts only first WikiWord
|
||||
$WikiWordCountMax = 0; # another way to disable WikiWord links
|
||||
|
||||
The $WikiWordCount array can be used to control the number of times
|
||||
a WikiWord is converted to a link. This is useful for disabling
|
||||
or limiting specific WikiWords.
|
||||
|
||||
$WikiWordCount['PhD'] = 0; # disables 'PhD'
|
||||
$WikiWordCount['PmWiki'] = 1; # convert only first 'PmWiki'
|
||||
$WikiWordCount['WikiWord'] = -1; # ignore $SpaceWikiWord setting
|
||||
|
||||
By default, PmWiki is configured such that only the first occurrence
|
||||
of 'PmWiki' in a page is treated as a WikiWord. If you want to
|
||||
restore 'PmWiki' to be treated like other WikiWords, uncomment the
|
||||
line below.
|
||||
unset($WikiWordCount['PmWiki']);
|
||||
|
||||
If you want to disable WikiWords matching a pattern, you can use
|
||||
something like the following. Note that the first argument has to
|
||||
be different for each call to Markup(). The example below disables
|
||||
WikiWord links like COM1, COM2, COM1234, etc.
|
||||
Markup('COM\d+', '<wikilink', '/\\bCOM\\d+/', "Keep('$0')");
|
||||
*/
|
||||
|
||||
SDV($LinkWikiWords, 1);
|
||||
|
||||
## bare wikilinks
|
||||
Markup_e('wikilink', '>urllink',
|
||||
"/\\b(?<![#&])($GroupPattern([\\/.]))?($WikiWordPattern)/",
|
||||
"Keep('<span class=\\'wikiword\\'>'.WikiLink(\$pagename,\$m[0]).'</span>',
|
||||
'L')");
|
||||
|
||||
function WikiLink($pagename, $word) {
|
||||
global $LinkWikiWords, $WikiWordCount, $SpaceWikiWords, $AsSpacedFunction,
|
||||
$MarkupFrame, $WikiWordCountMax;
|
||||
if (!$LinkWikiWords || ($WikiWordCount[$word] < 0)) return $word;
|
||||
$text = ($SpaceWikiWords) ? $AsSpacedFunction($word) : $word;
|
||||
$text = preg_replace('!.*/!', '', $text);
|
||||
if (!isset($MarkupFrame[0]['wwcount'][$word]))
|
||||
$MarkupFrame[0]['wwcount'][$word] = $WikiWordCountMax;
|
||||
if ($MarkupFrame[0]['wwcount'][$word]-- < 1) return $text;
|
||||
return MakeLink($pagename, $word, $text);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php if (!defined('PmWiki')) exit();
|
||||
/* Copyright 2005-2011 Patrick R. Michaud (pmichaud@pobox.com)
|
||||
This file is part of PmWiki; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version. See pmwiki.php for full details.
|
||||
*/
|
||||
|
||||
global $HTTPHeaders, $Charset, $DefaultPageCharset;
|
||||
|
||||
$HTTPHeaders[] = "Content-type: text/html; charset=iso-8859-13;";
|
||||
$Charset = "ISO-8859-13";
|
||||
SDVA($DefaultPageCharset, array('ISO-8859-1'=>$Charset));
|
||||