aboutsummaryrefslogtreecommitdiff
path: root/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu
diff options
context:
space:
mode:
Diffstat (limited to 'mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu')
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/COPYING340
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/CREDITS58
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/VERSION.txt1
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/action.php169
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/admin.php453
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/ajax.php196
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/changelog207
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/conf/default.php19
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/conf/metadata.php18
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/edit-full.js152
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/edit.js1
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/close.gifbin0 -> 64 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/base.gifbin0 -> 578 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/empty.gifbin0 -> 62 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/folder.gifbin0 -> 352 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/folderh.gifbin0 -> 572 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/folderhopen.gifbin0 -> 577 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/folderopen.gifbin0 -> 354 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/info.txt2
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/join.gifbin0 -> 69 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/joinbottom.gifbin0 -> 66 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/line.gifbin0 -> 66 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/minus.gifbin0 -> 86 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/minusbottom.gifbin0 -> 85 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/nolines_minus.gifbin0 -> 861 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/nolines_plus.gifbin0 -> 870 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/page.gifbin0 -> 565 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/plus.gifbin0 -> 89 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/plusbottom.gifbin0 -> 88 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/empty.gifbin0 -> 275 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/indexmenu_toolbar.pngbin0 -> 726 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/larrow.gifbin0 -> 1829 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/msort.gifbin0 -> 420 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/rarrow.gifbin0 -> 81 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/toc_bullet.gifbin0 -> 74 bytes
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/inc/pclzip.lib.php5748
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/inc/repo.class.php51
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/indexmenu-full.js640
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/indexmenu.js18
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/jsmenu/admmenu.js71
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/jsmenu/menu.js56
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/jsmenu/usrmenu.js69
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/lang/de/lang.php27
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/lang/en/lang.php28
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/lang/es/lang.php28
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/lang/it/lang.php29
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/nojsindex-full.js101
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/nojsindex.js1
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/script.js152
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/style.css190
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/syntax/indexmenu.php720
-rw-r--r--mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/syntax/tag.php70
52 files changed, 9615 insertions, 0 deletions
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/COPYING b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/COPYING
new file mode 100644
index 000000000..d60c31a97
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/COPYING
@@ -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.
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/CREDITS b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/CREDITS
new file mode 100644
index 000000000..cb03c247d
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/CREDITS
@@ -0,0 +1,58 @@
+Thanks to:
+
+Geir Landro:
+ Dtree Javascript code.
+
+Roland Hellebart:
+ The Dtree idea.
+
+Chris Beetle:
+ The root namespace index.
+
+Gleb:
+ The nons e headpage option suggestion.
+
+Malyfred:
+ Resolved incorrect namespaces levels bug.
+
+Raymond Elferink:
+ Resolved incorrect ACLs bug.
+
+Ilya Lebedev:
+ Skip index option.
+
+Franck Baron:
+ Js id option.
+
+Jon B:
+ Skip file option.
+
+Neosky:
+ Javascript toolbar bug.
+
+Paul Grove:
+ Css dynamic properties and suggestion of js theme with differents image formats
+
+Anja Vag:
+ Great help in testing and finding bugs.
+
+Blaz:
+ Current page highliting suggestion.
+
+Adrien CLERC:
+ Start page bug.
+
+Ryan Jake and Fullindex plugin:
+ Sort by metada suggestion.
+
+Herman Huitema:
+ Context menu search function and great help in testing patches.
+
+Thomas Binder:
+ Fixed a bug with msort/nsort that did not manage empty arrays.
+
+Fabian Pfannes:
+ German language
+
+Urban:
+ Context menu patch and other suggestions
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/VERSION.txt b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/VERSION.txt
new file mode 100644
index 000000000..db43bc514
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/VERSION.txt
@@ -0,0 +1 @@
+2009-08-29
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/action.php b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/action.php
new file mode 100644
index 000000000..ee09a980d
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/action.php
@@ -0,0 +1,169 @@
+<?php
+/**
+ * Indexmenu Action Plugin: Indexmenu Component.
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+
+if(!defined('DOKU_INC')) die();
+if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
+require_once(DOKU_PLUGIN.'action.php');
+
+class action_plugin_indexmenu extends DokuWiki_Action_Plugin {
+
+ /**
+ * return some info
+ */
+ function getInfo(){
+ return array(
+ 'author' => 'Samuele Tognini',
+ 'email' => 'samuele@netsons.org',
+ 'date' => rtrim(io_readFile(DOKU_PLUGIN.'indexmenu/VERSION.txt')),
+ 'name' => 'Indexmenu (action plugin component)',
+ 'desc' => 'Indexmenu action functions.',
+ 'url' => 'http://wiki.splitbrain.org/plugin:indexmenu',
+ );
+ }
+
+ /*
+ * plugin should use this method to register its handlers with the dokuwiki's event controller
+ */
+ function register(&$controller) {
+ if ($this->getConf('only_admins')) $controller->register_hook('IO_WIKIPAGE_WRITE', 'BEFORE', $this, '_checkperm');
+ if ($this->getConf('page_index') != '') $controller->register_hook('TPL_ACT_RENDER', 'BEFORE', $this, '_loadindex');
+ $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, '_hookjs');
+ $controller->register_hook('PARSER_CACHE_USE', 'BEFORE', $this, '_purgecache');
+ if ($this->getConf('show_sort')) $controller->register_hook('TPL_CONTENT_DISPLAY', 'BEFORE', $this, '_showsort');
+ }
+
+ /**
+ * Check if user has permission to insert indexmenu
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _checkperm(&$event, $param) {
+ if ($this->_notadmin()) {
+ $event->data[0][1]= preg_replace("/{{indexmenu(|_n)>.+?}}/","",$event->data[0][1]);
+ }
+ }
+
+ /**
+ * Hook js script into page headers.
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _hookjs(&$event, $param) {
+ global $ID;
+ global $INFO;
+ $jsmenu=DOKU_BASE."lib/plugins/indexmenu/jsmenu/";
+
+ if ($INFO['userinfo']['grps']) {
+ $jsmenu .= ($this->_notadmin()) ? "usrmenu.js" : "admmenu.js";
+ } else {
+ $jsmenu .= "menu.js";
+ }
+
+ $event->data["script"][] = array ( "type" => "text/javascript",
+ "charset" => "utf-8",
+ "_data" => "",
+ "src" => $jsmenu
+ );
+
+ $event->data["script"][] = array ( "type" => "text/javascript",
+ "charset" => "utf-8",
+ "_data" => "",
+ "src" => DOKU_BASE."lib/plugins/indexmenu/indexmenu.js"
+ );
+
+ $event->data["script"][] = array ( "type" => "text/javascript",
+ "charset" => "utf-8",
+ "_data" => "var indexmenu_ID='".idfilter($ID)."'"
+ );
+ }
+
+ /**
+ * Check for pages changes and eventually purge cache.
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _purgecache(&$event, $param) {
+ global $ID;
+ global $conf;
+ $cache = &$event->data;
+
+ if (!isset($cache->page)) return;
+ //purge only xhtml cache
+ if ($cache->mode != "xhtml") return;
+ //Check if it is an indexmenu page
+ if (!p_get_metadata($ID,'indexmenu')) return;
+ $aclcache=$this->getConf('aclcache');
+ if ($conf['useacl']) {
+ $newkey=false;
+ if ($aclcache == 'user') {
+ //Cache per user
+ if ($_SERVER['REMOTE_USER']) $newkey=$_SERVER['REMOTE_USER'];
+ } else if ($aclcache == 'groups') {
+ //Cache per groups
+ global $INFO;
+ if ($INFO['userinfo']['grps']) $newkey=implode('#',$INFO['userinfo']['grps']);
+ }
+ if ($newkey) {
+ $cache->key .= "#".$newkey;
+ $cache->cache = getCacheName($cache->key, $cache->ext);
+ }
+ }
+ //Check if a page is more recent than purgefile.
+ if (@filemtime($cache->cache) < @filemtime($conf['cachedir'].'/purgefile')) {
+ $event->preventDefault();
+ $event->stopPropagation();
+ $event->result = false;
+ }
+ }
+
+ /**
+ * Render a defined page as index.
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _loadindex(&$event, $param) {
+ if ('index' != $event->data) return;
+ if (!file_exists(wikiFN($this->getConf('page_index')))) return;
+ global $lang;
+ print '<h1><a id="index" name="index">'.$lang['btn_index']."</a></h1>\n";
+ print p_wiki_xhtml($this->getConf('page_index'));
+ $event->preventDefault();
+ $event->stopPropagation();
+
+ }
+
+ /**
+ * Display the indexmenu sort number.
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _showsort(&$event, $param) {
+ global $ID,$ACT;
+ if ($ACT != 'show' || $this->_notadmin()) return;
+ if ($n=p_get_metadata($ID,'indexmenu_n')) {
+ ptln('<div class="info">');
+ ptln($this->getLang('showsort').$n);
+ ptln('</div>');
+ }
+ }
+
+ /**
+ * Check if user is administrator..
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _notadmin() {
+ global $conf;
+ global $INFO;
+
+ if ($conf['useacl'] && $INFO['perm'] < AUTH_ADMIN) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/admin.php b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/admin.php
new file mode 100644
index 000000000..99b6e12a2
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/admin.php
@@ -0,0 +1,453 @@
+<?php
+/**
+ * Indexmenu Admin Plugin: Indexmenu Component.
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+
+if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
+if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
+require_once(DOKU_PLUGIN.'admin.php');
+require_once (DOKU_INC.'inc/HTTPClient.php');
+require_once(DOKU_PLUGIN."indexmenu/inc/pclzip.lib.php");
+if(!defined('INDEXMENU_IMG_ABSDIR')) define('INDEXMENU_IMG_ABSDIR',DOKU_PLUGIN."indexmenu/images");
+define('INDEXMENU_ICOS','base,folder,folderopen,folderh,folderhopen,page,plus,minus,nolines_plus,nolines_minus,minusbottom,plusbottom,join,joinbottom,line,empty');
+
+class admin_plugin_indexmenu extends DokuWiki_Admin_Plugin {
+ var $req = 'fetch';
+ var $repos = array (
+ "url" => array(DOKU_URL),
+ "status" => array(""),
+ );
+
+ var $selected=-1;
+
+ /**
+ * return some info
+ */
+ function getInfo(){
+ return array(
+ 'author' => 'Samuele Tognini',
+ 'email' => 'samuele@netsons.org',
+ 'date' => rtrim(io_readFile(DOKU_PLUGIN.'indexmenu/VERSION.txt')),
+ 'name' => 'Indexmenu (admin plugin component)',
+ 'desc' => 'Indexmenu admin functions.',
+ 'url' => 'http://wiki.splitbrain.org/plugin:indexmenu',
+ );
+ }
+
+ /**
+ * return sort order for position in admin menu
+ */
+ function getMenuSort() {
+ return 999;
+ }
+
+ /**
+ * handle user request
+ */
+ function handle() {
+ $url=$this->getConf('themes_url');
+ if (empty($url)) {
+ $this->repos['url'][]=$this->getLang('no_repos');
+ $this->repos['status'][]="disabled";
+ $this->repos['install'][]=-1;
+ } else {
+ $this->repos['url']= array_merge($this->repos['url'],explode(',',$url));
+ }
+
+ if (!isset($_REQUEST['req'])) return; // first time - nothing to do
+ $this->req=$_REQUEST['req'];
+
+ if (is_numeric($_REQUEST['repo'])) $this->selected=$_REQUEST['repo'];
+ }
+
+ /**
+ * output appropriate html
+ */
+ function html() {
+ global $conf;
+ ptln('<div id="config__manager">');
+ ptln(' <h1>'.$this->getLang('menu').'</h1>');
+ ptln($this->_donate());
+ ptln(' <fieldset>');
+ ptln(' <legend>'.$this->getLang('checkupdates').'</legend>');
+ $this->_form_open("checkupdates");
+ $this->_form_close('check');
+ if ($this->req=='checkupdates') {
+ $this->_checkupdates();
+ }
+ ptln(' </fieldset>');
+ ptln(' <fieldset>');
+ ptln(' <legend>Themes</legend>');
+ ptln(' <table class="inline">');
+ ptln(' <tr class="default"><td class="label" colspan="2">');
+ ptln(' <span class="outkey">'.$this->getLang('infos').'</span>');
+ ptln(' </td></tr>');
+ $n=0;
+ //cycles thru repositories urls
+ foreach ($this->repos['url'] as $url) {
+ ptln(' <tr class="search_hit"><td>');
+ $legend=($n == 0) ? $conf['title'] : $this->repos['url'][$n];
+ ptln(' <span><label><strong>'.$legend.'</strong></label></span>');
+ ptln(' </td>');
+ ptln(' <td class="value">');
+ $this->_form_open("fetch",$n);
+ $this->_form_close("fetch");
+ ptln(' </td></tr>');
+ //list requested theme
+ if ($n==$this->selected) {
+ ptln(' <tr class="default"><td colspan="2">');
+ if ($this->req=='install') $this->install($this->selected,$_REQUEST['name']);
+ if ($this->req=='upload' && $_REQUEST['name']) {
+ $info="";
+ if (isset($_REQUEST['author_info'])) {
+ $obfuscate = array('@' => ' [at] ', '.' => ' [dot] ', '-' => ' [dash] ');
+ $info .= "author=".strtr($_REQUEST['author_info'], $obfuscate)."\n";
+ }
+ if (isset($_REQUEST['url_info'])) $info .= "url=".$_REQUEST['url_info']."\n";
+ if (isset($_REQUEST['author_info'])) $info .= "description=".$_REQUEST['author_info'];
+ if (!$this->upload($_REQUEST['name'],$info)) msg($this->getLang('install_no'),-1);
+ }
+ if ($this->req=='delete' && $_REQUEST['name']) $this->_delete($_REQUEST['name']);
+ ptln(' </td></tr><tr><td colspan="2">');
+ $this->dolist($n);
+ ptln(' </td></tr>');
+ }
+ $n++;
+ }
+ ptln(' </table>');
+ ptln(' </fieldset>');
+ ptln('</div>');
+ }
+
+ /**
+ * Connect to theme repository and list themes
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function dolist($n) {
+ global $INFO;
+ if ($n === false) return;
+ //info.txt keys to parse
+ $keys=array('author','url','description');
+ $icos=explode(',',INDEXMENU_ICOS);
+ $turl="";
+ $info="";
+ //get list
+ $data=$this->_remotequery($this->repos['url'][$n]."/lib/plugins/indexmenu/ajax.php?req=local");
+ $data=explode(",",$data);
+ //print themes
+ for ($i=3;$i<count($data);$i++) {
+ $theme=$data[$i];
+ $turl=$data[1].$data[2]."/".$theme;
+ ptln(' <em>'.$theme.'</em>');
+ ptln(' <div class="indexmenu_list_themes">');
+ ptln(' <div>');
+ //print images
+ foreach (array_slice($icos,0,8) as $ico) {
+ $ext = explode(".", $theme);
+ $ext=array_pop($ext);
+ $ext=($ext == $theme) ? '.gif' : ".$ext";
+ ptln(' <img src="'.$turl."/".$ico.$ext.'" title="'.$ico.'" alt="'.$ico.'" />');
+ }
+ ptln(' </div>');
+ //get theme info.txt
+ if ($info=$this->_remotequery($turl."/info.txt",false)) {
+ foreach ($keys as $key) {
+ if (!preg_match('/'.$key.'=(.*)/',$info,$out)) continue;
+ ptln(" <div>");
+ ptln(" <strong>".hsc($key).": </strong>".hsc($out[1]));
+ ptln(" </div>");
+ }
+ }
+ if ($n == 0) {
+ $act="upload";
+ if ($theme != "default" ) {
+ $this->_form_open("delete",$n);
+ ptln(' <input type="hidden" name="name" value="'.$theme.'" />');
+ $this->_form_close("delete");
+ }
+ } else {
+ $act="install";
+ ptln(' <a href="'.$this->repos['url'][$n]."$repo/lib/plugins/indexmenu/ajax.php?req=send&amp;t=".$theme.'">Download</a>');
+ }
+ $this->_form_open($act,$n);
+ if ($n==0 && !is_file(INDEXMENU_IMG_ABSDIR."/".$theme."/info.txt")) {
+ ptln(' <div><strong>author:</strong><input type="text" name="author_info" value="'.$INFO["userinfo"]["name"].hsc(" <".$INFO["userinfo"]["mail"].">").'" size="50" maxlength="100" /><br />');
+ ptln(' <strong>url:</strong><input type="text" name="url_info" value="'.$this->repos['url'][$n].'" size="50" maxlength="200" /><br />');
+ ptln(' <strong>description:</strong><input type="text" name="description_info" value="" size="50" maxlength="200" /></div>');
+ }
+ ptln(' <input type="hidden" name="name" value="'.$theme.'" />');
+ $this->_form_close($act);
+ ptln(' <br /><br /></div>');
+ }
+ }
+
+ /**
+ * Download and install themes
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function install ($n,$name) {
+ $repo=$this->repos['url'][$n];
+ if (!isset($name)) return false;
+ $return=true;
+ if (!$absdir=$this->checktmpsubdir()) return;
+ $tmp=$absdir."/tmp";
+
+ //send theme list request
+ if (!$zipfile=io_download($repo."/lib/plugins/indexmenu/ajax.php?req=send&t=".$name,"$tmp/",true)) {
+ msg($this->getLang('down_err').": $name",-1);
+ $return=false;
+ } else {
+ //create zip
+ $zip=new PclZip("$tmp/$zipfile");
+ $regexp="/^".$name."\/(info.txt)|(style.css)|(".str_replace(",","|",INDEXMENU_ICOS).")\.(gif|png|jpg)$/i";
+ $status=$zip->extract(PCLZIP_OPT_PATH,$absdir."/",PCLZIP_OPT_BY_PREG,$regexp);
+ //error
+ if ($status == 0) {
+ msg($this->getLang('zip_err')." $tmp/$zipfile: ".$zip->errorName(true),-1);
+ $return=false;
+ } else {
+ msg("<strong>$name</strong> ".$this->getLang('install_ok'),1);
+ }
+ }
+ //clean tmp
+ $this->_rm_dir($tmp);
+ return $return;
+ }
+
+
+ /**
+ * Remove a directory
+ *
+ */
+ function _rm_dir($path) {
+ if (!is_string($path) || $path == "") return false;
+
+ if (is_dir($path)) {
+ if (!$dh = @opendir($path)) return false;
+
+ while ($f = readdir($dh)) {
+ if ($f == '..' || $f == '.') continue;
+ $this->_rm_dir("$path/$f");
+ }
+
+ closedir($dh);
+ return @rmdir($path);
+ } else {
+ return @unlink($path);
+ }
+
+ return false;
+ }
+
+ /**
+ * Retrive and create themes tmp directory
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function checktmpsubdir () {
+ $tmp=INDEXMENU_IMG_ABSDIR."/tmp";
+ if (!io_mkdir_p($tmp)) {
+ msg($this->getLang('dir_err').": $tmp",-1);
+ return false;
+ }
+ return INDEXMENU_IMG_ABSDIR;
+ }
+
+
+ /**
+ * Upload a theme into my site
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function upload($theme,$info) {
+ $return=true;
+ $host='samuele.netsons.org';
+ $path='/dokuwiki/lib/plugins/indexmenu/upload/index.php';
+ //TODO: merge zip creation with that in ajax.php (create a class?)
+ if (!$absdir=$this->checktmpsubdir()) return false;
+ $tmp=$absdir."/tmp";
+ $zipfile="$theme.zip";
+ $filelist="$absdir/$theme";
+ //create info
+ if (!empty($info)) {
+ io_savefile("$tmp/$theme/info.txt",$info);
+ $filelist .= ",$tmp/$theme";
+ }
+ //create zip
+ $zip=new PclZip("$tmp/$zipfile");
+ $status=$zip->create($filelist,PCLZIP_OPT_REMOVE_ALL_PATH);
+ if ($status == 0) {
+ //error
+ msg($this->getLang('zip_err').": ".$zip->errorName(true),-1);
+ $return=false;
+ } else {
+ //prepare POST headers.
+ $boundary = "---------------------------".uniqid("");
+ $data=join("", file("$tmp/$zipfile"));
+ $header="POST $path HTTP/1.0\r\n";
+ $header.= "Host: $host\r\n";
+ $header.= "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061024 Iceweasel/2.0 (Debian-2.0+dfsg-1)\r\n";
+ $header.= "Content-type: multipart/form-data, boundary=$boundary\r\n";
+ $body="--".$boundary."\r\n";
+ $body.= "Content-Disposition: form-data; name=\"userfile\"; filename=\"$zipfile\"\r\n";
+ $body.= "Content-Type: application/x-zip-compressed\r\n\r\n";
+ $body.=$data."\r\n";
+ $body.= "--".$boundary."\r\n";
+ $body.= "Content-Disposition: form-data; name=\"upload\"\r\n\r\n";
+ $body.= "Upload\r\n";
+ $body.="--".$boundary."--\r\n";
+ $header.= "Content-Length: ".strlen($body)."\r\n\r\n";
+
+ //connect and send zip
+ if ($fp = fsockopen($host, 80)) {
+ fwrite($fp,$header.$body);
+ //reply
+ $buf="";
+ while (!feof($fp)) {
+ $buf .= fgets($fp,3200);
+ }
+ fclose($fp);
+ //parse resply
+ if (preg_match("/<!--indexmenu-->(.*)<!--\/indexmenu-->/s",$buf,$match)) {
+ $str=substr($match[1],4,7);
+ switch ($str) {
+ case "ERROR ":
+ $mesg_type=-1;
+ break;
+ case "SUCCESS":
+ $mesg_type=1;
+ break;
+ default:
+ $mesg_type=2;
+ }
+ msg($match[1],$mesg_type);
+ } else {
+ $return=false;
+ }
+ } else {
+ $return=false;
+ }
+ }
+
+ $this->_rm_dir($tmp);
+ return $return;
+ }
+
+ /**
+ * Check for new messages from upstream
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _checkupdates() {
+ require_once (DOKU_INC.'inc/HTTPClient.php');
+ global $conf;
+ global $INFO;
+ $w=-1;
+ $date=$this->getInfo('date');
+ $date=$date['date'];
+ $data=$this->_remotequery("http://samuele.netsons.org/dokuwiki/lib/plugins/indexmenu/remote.php?check=$date");
+ if ($data==="") {
+ msg($this->getLang('noupdates'),1);
+ $data .= @preg_replace('/\n\n.*$/s','',@io_readFile(DOKU_PLUGIN.'indexmenu/changelog'))."\n%\n";
+ $w=1;
+ } else {
+ $data=preg_replace('/\<br(\s*)?\/?\>/i',"", $data);
+ $data=preg_replace('/\t/'," ", $data);
+ }
+ $data=preg_replace('/\[\[(?!(http|https))(.:)(.*?)\]\]/s',"[[plugin:$3]]", $data);
+ $data=preg_replace('/\[\[(?!(http|https))(.*?)\]\]/s',"[[http://www.dokuwiki.org/$2]]", $data);
+ $msgs = explode("\n%\n",$data);
+ foreach($msgs as $msg){
+ if($msg) {
+ $msg= p_render('xhtml',p_get_instructions($msg),$info);
+ msg($msg,$w);
+ }
+ }
+ }
+
+
+ /**
+ * Get url response and check it
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _remotequery($url,$tag=true) {
+ require_once (DOKU_INC.'inc/HTTPClient.php');
+ $http = new DokuHTTPClient();
+ $http->timeout = 8;
+ $data = $http->get($url);
+ if ($tag) {
+ if ($data===false) {
+ msg($this->getLang('conn_err'),-1);
+ } else {
+ (substr($data,0,9)==="indexmenu") ? $data=substr($data,9): $data="";
+ }
+ }
+ return $data;
+ }
+
+
+ /**
+ * Open an html form
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _form_open($act,$n=-1) {
+ ptln(' <form action="'.wl($ID).'" method="post">');
+ ptln(' <input type="hidden" name="do" value="admin" />');
+ ptln(' <input type="hidden" name="page" value="'.$this->getPluginName().'" />');
+ ptln(' <input type="hidden" name="req" value="'.$act.'" />');
+ ptln(' <input type="hidden" name="repo" value="'.$n.'" />');
+ }
+
+ /**
+ * Close the html form
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _form_close($act) {
+ ptln(' <input type="submit" name="btn" '.$this->repos['status'][$n].' value="'.$this->getLang($act).'" />');
+ ptln(' </form>');
+ }
+
+ /**
+ * Remove an installed theme
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _delete($theme) {
+ if ($theme=="default") return;
+ if ($this->_rm_dir(INDEXMENU_IMG_ABSDIR."/".utf8_encodeFN(basename($theme)))) {
+ msg($this->getLang('delete_ok').": $theme.",1);
+ } else {
+ msg($this->getLang('delete_no').": $theme.",-1);
+ }
+ }
+
+ /**
+ * Print the donate button.
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _donate() {
+ $out = "<fieldset>\n";
+ $out .= '<p>'.$this->getLang('donation_text').'</p>';
+ $out .= '<form action="https://www.paypal.com/cgi-bin/webscr" method="post">'."\n";
+ $out .= '<input type="hidden" name="cmd" value="_s-xclick" />'."\n";
+ $out .= '<input type="hidden" name="hosted_button_id" value="102873" />'."\n";
+ $out .= '<input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" name="submit" alt="" />'."\n";
+ $out .= '<img alt="" src="https://www.paypal.com/it_IT/i/scr/pixel.gif" width="1" height="1" />'."\n";
+ $out .= "</form></fieldset>\n";
+ return $out;
+ }
+
+}
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/ajax.php b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/ajax.php
new file mode 100644
index 000000000..93b3d5f07
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/ajax.php
@@ -0,0 +1,196 @@
+<?php
+/**
+ * AJAX Backend for indexmenu
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ */
+
+//fix for Opera XMLHttpRequests
+if(!count($_POST) && @$HTTP_RAW_POST_DATA){
+ parse_str($HTTP_RAW_POST_DATA, $_POST);
+}
+
+if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../../').'/');
+if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
+require_once(DOKU_INC.'inc/init.php');
+require_once(DOKU_INC.'inc/auth.php');
+if(!defined('INDEXMENU_IMG_ABSDIR')) define('INDEXMENU_IMG_ABSDIR',DOKU_PLUGIN."indexmenu/images");
+//close session
+session_write_close();
+
+$ajax_indexmenu=new ajax_indexmenu_plugin;
+$ajax_indexmenu->render();
+
+class ajax_indexmenu_plugin {
+ /**
+ * Output
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+
+ function render () {
+ $req=$_REQUEST['req'];
+ $succ=false;
+ //send the zip
+ if ($req == 'send' and isset($_REQUEST['t'])) {
+ include(DOKU_PLUGIN.'indexmenu/inc/repo.class.php');
+ $repo=new repo_indexmenu_plugin;
+ $succ=$repo->send_theme($_REQUEST['t']);
+ }
+ if ($succ) return true;
+
+ header('Content-Type: text/html; charset=utf-8');
+ header('Cache-Control: public, max-age=3600');
+ header('Pragma: public');
+ switch ($req) {
+ case 'local':
+ //list themes
+ print $this->local_themes();
+ break;
+ case 'toc':
+ //print toc preview
+ if (isset($_REQUEST['id'])) print $this->print_toc($_REQUEST['id']);
+ break;
+ case 'index':
+ //print index
+ if (isset($_REQUEST['idx'])) print $this->print_index($_REQUEST['idx']);
+ break;
+ }
+ }
+
+ /**
+ * Print a list of local themes
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+
+ function local_themes() {
+ $list='indexmenu,'.DOKU_URL.",lib/plugins/indexmenu/images,";
+ $data=array();
+ $handle=@opendir(INDEXMENU_IMG_ABSDIR);
+ while (false !== ($file = readdir($handle))) {
+ if ( is_dir (INDEXMENU_IMG_ABSDIR.'/'.$file)
+ && $file != "."
+ && $file != ".."
+ && $file != "repository"
+ && $file != "tmp"
+ ) {
+ $data[]=$file;
+ }
+ }
+ closedir($handle);
+ sort($data);
+ $list .= implode(",",$data);
+ return $list;
+ }
+
+ /**
+ * Print a toc preview
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+ function print_toc($id) {
+ require_once(DOKU_INC.'inc/parser/xhtml.php');
+ $id=cleanID($id);
+ if (auth_quickaclcheck($id) < AUTH_READ) return;
+ $meta = p_get_metadata($id);
+ $toc = $meta['description']['tableofcontents'];
+ $out .= '<div class="tocheader toctoggle">'.DOKU_LF;
+ if (count($toc)>1) {
+ $out .= $this->render_toc($toc);
+ } else {
+ $out .= '<a href="'.wl($id).'">';
+ $out .= ($meta['title']) ? htmlspecialchars($meta['title']) : htmlspecialchars(noNS($id));
+ $out .= '</a>'.DOKU_LF;
+ if ($meta['description']['abstract']) {
+ $out .= '</div>'.DOKU_LF;
+ $out .= '<div class="indexmenu_toc_inside">'.DOKU_LF;
+ $out .= p_render('xhtml',p_get_instructions($meta['description']['abstract']),$info);
+ $out .= '</div>'.DOKU_LF;
+ }
+ }
+ $out .= '</div>'.DOKU_LF;
+ return $out;
+ }
+
+ /**
+ * Return the TOC rendered to XHTML
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+ function render_toc($toc){
+ global $lang;
+ $r = new Doku_Renderer_xhtml;
+ $r->toc = $toc;
+ $out .= $lang['toc'];
+ $out .= '</div>'.DOKU_LF;
+ $out .= '<div class="indexmenu_toc_inside">'.DOKU_LF;
+ $out .= html_buildlist($r->toc,'toc',array($this,'_tocitem'));
+ $out .= '</div>'.DOKU_LF;
+ return $out;
+ }
+
+ /**
+ * Callback for html_buildlist
+ */
+ function _tocitem($item){
+ $id=cleanID($_POST['id']);
+ return '<span class="li"><a href="'.wl($id,'#'.$item['hid'],false,'').'" class="toc">'.
+ htmlspecialchars($item['title']).'</a></span>';
+ }
+
+ /**
+ * Print index nodes
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+ function print_index($ns) {
+ require_once(DOKU_PLUGIN.'indexmenu/syntax/indexmenu.php');
+ global $conf;
+ $idxm=new syntax_plugin_indexmenu_indexmenu();
+ $ns=$idxm->_parse_ns($ns);
+ $level=-1;
+ $max=0;
+ $data = array();
+ if ($_REQUEST['max'] > 0) {
+ $max=$_REQUEST['max'];
+ $level=$max;
+ }
+ $nss= ($_REQUEST['nss']) ? cleanID($_REQUEST['nss']) : '';
+ $idxm->sort=$_REQUEST['sort'];
+ $idxm->msort=$_REQUEST['msort'];
+ $idxm->rsort=$_REQUEST['rsort'];
+ $idxm->nsort=$_REQUEST['nsort'];
+ $fsdir="/".utf8_encodeFN(str_replace(':','/',$ns));
+ $opts= array('level' => $level,
+ 'nons' => $_REQUEST['nons'],
+ 'nss' => array(array($nss,1)),
+ 'max' => $max,
+ 'js' => false,
+ 'nopg' => $_REQUEST['nopg'],
+ 'skip_index' => $idxm->getConf('skip_index'),
+ 'skip_file' => $idxm->getConf('skip_file'),
+ 'headpage' => $idxm->getConf('headpage'),
+ 'hide_headpage' => $idxm->getConf('hide_headpage')
+ );
+ if ($idxm->sort||$idxm->msort||$idxm->rsort) {
+ $idxm->_search($data,$conf['datadir'],array($idxm,'_search_index'),$opts,$fsdir);
+ } else {
+ search($data,$conf['datadir'],array($idxm,'_search_index'),$opts,$fsdir);
+ }
+ if ($_REQUEST['nojs']) {
+ require_once(DOKU_INC.'inc/html.php');
+ $out_tmp=html_buildlist($data,'idx',array($idxm,"_html_list_index"),"html_li_index");
+ $out.=preg_replace('/<ul class="idx">(.*)<\/ul>/s',"$1",$out_tmp);
+ } else {
+ $nodes=$idxm->_jsnodes($data,'',0);
+ $out="ajxnodes = [";
+ $out.=rtrim($nodes[0],",");
+ $out.="];";
+ }
+ return $out;
+ }
+}
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/changelog b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/changelog
new file mode 100644
index 000000000..ec78c7c38
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/changelog
@@ -0,0 +1,207 @@
+ * **2009-08-29 Version 4.6**:
+ * //New Feature//: Namespace declaration complies with dokuwiki [[:namespaces#creating namespaces|namespaces]]. :!: **Important before upgrading from previuos versions**: according to the new dokuwiki syntax, a simple //main namespace// without relative declaration prefix (i.e: "playground") doesn't refer anymore to the subnamespace in the root namespace but in the **current** namespace. To refer to the root namespace, you need to prepend the ":" declaration to it. :!:
+ * //New Feature//: Added the //context// option. It resolves relative requested namespaces starting from the current user location instead of the page containing the indexmenu syntax.
+ * //New Feature//: Changed skip_file and skip_index syntax to use dokuwiki id instead of system paths. Thanks to Dmitry Katsubo.
+ * //New Feature//: Metatada titles are not rendered when recursively bulding the indexmenu tree. This will speed up the page loading when cache expires, but could not display the heading title for nodes without metadata infos.
+ * //New Feature//: Added the nojs button in the edit toolbar and toolbar CSS classes.
+ * //New Feature//: The right JS context menu is closed by any document click. Thanks to Urban.
+ * //Bug//: Fixed a bug which prevents page caching when it contains only indexmenu syntax.
+ * //Bug//: Disable JS indexmenu cookies in preview mode.
+ * //Bug//: Fixed an acl issue.
+ * //Bug//: Fixed UTF8 toc preview bug.
+
+ * **2009-01-04 Version 4.5**:
+ * //Bug//: Fixed a stupid bug with toolbar.
+
+ * **2008-12-02 Version 4.4**:
+ * //New Feature//: Added ajax for the nojs index view.
+ * //New Feature//: Added navbar support also in nojs mode, but unlike js mode, its page does not use cache.
+ * //New Feature//: Added nopg option. Thanks to Sebastian E.
+ * //New Feature//: Toc preview displays rendered instructions instead of raw text when toc is empty.
+ * //New Feature//: German translation by Fabian Pfannes.
+ * //Bug//: Fixed acl bugs that prevents js mode to work correctly.
+ * //Bug//: Fixed a bug with [[plugin:indexmenu#only_admins|Only Admins]] option.
+ * //Bug//: Fixed a bug that prevents to disable the context menu.
+ * //Bug & Features//: id for navbar trees is now random by default + Minor bug fixes and improvements.
+ * //Others//: [[http://samuele.netsons.org/dokuwiki/doku.php?id=dokuwiki:plugins:indexmenu#donation|Donation]] button added.
+
+ * **2008-04-12 Version 4.3**:
+ * New Feature: Different js [[plugin:indexmenu#the_context_menu|context menus]] for anonymous, authenticated and admin user.
+ * Bug: Dokuwiki RC2008-04-11 compatible.
+ * Bug: Context menu should now support all userewrite and useslash DW config options.
+ * Bug: Fixed msort to work with nsort when in non-js mode.
+
+ * **2008-03-10 Version 4.2**:
+ * Bug: Fixed loop with nsort option. Thanks to Thomas Binder.
+ * Bug: Do not display empty namespace icon for empty headpages.
+ * Bug: Fixed navbar not working with max option and a main namespace different from root.
+ * Bug: Context menu "New page here" item creates the right page for headpages.
+
+ * **2008-02-16 Version 4.1**:
+ * New Feature: Indexmenu tree behaviour depends on the [[wiki:config#sneaky_index]] option. More info in the [[.:indexmenu#about ACLs]] section. Please read carefully the note about dokuwiki versions that do not support it.
+ * New Feature: Fixed some issues with Acls and empty namespaces. More info in the section [[.:indexmenu#about empty namespaces]].
+ * New Feature: Added the "Search in this namespace" option in the contextmenu. Thanks to Herman Huitema.
+ * Bug: Fixed broken js tree with dokuwiki search engine when node contains an highlighted word.
+ * Bugs: Fixed broken toolbar element when the dokuwiki js compact option is on.
+ * Bug: Single quote in dokuwiki config [[wiki:config#title]] breaks js tree when [[.:indexmenu#Namespaces title and link|headpage]] option is not configured.
+ * Changes: Minor contextmenu styling changes.
+
+ * **2007-10-26 Version 4.0**:
+ * New Feature: Added a customizable context menu (right click) for pages/namespaces common actions.
+ * New Feature: Added nsort option in order to sorts namespaces according to tsort/dsort/msort options.
+ * Bugs: Fixed a xhtml compatibility bug with msort and max option.
+ * Changes: Automatically scroll navbar menu to fit the current page.
+
+ * **2007-08-30 Version 3.9**:
+ * New Feature: Added options to sort by title, date and by custom metadata. Infos in the [[.:indexmenu#syntax]] section. Metadata sorting idea was "stolen" from [[.:fullindex]] plugin so thanks to the its author.
+ * New Feature: Added the %%{{indexmenu_n>N}}%% syntax to set a custom number used by metadata sorting. Infos in the [[.:indexmenu#syntax]] section.
+ * New Feature: Support for custom css styles based on theme. Infos in the [[.:indexmenu#css style]] section. An example is in the thread theme on the indexmenu repository.
+ * Changes: Added more options to the indexmenu toolbar in edit mode.
+ * Changes: Changed the scrolling tree style and usability. It does not anymore scroll automatically when node gets focus.
+
+ * **2007-07-11 Version 3.8**:
+ * Bug: Solved bugs when using url rewriting.
+ * Bug: Solved a bug in the css width property of toc preview div.
+
+ * **2007-07-07 Version 3.7**:
+ * Bug: Navbar did not work in ie6/7 with max option on.
+ * Bug: The js tree was wrong with headpages off.
+
+ * **2007-07-05 Version 3.6**:
+ * New Feature: Added max option to load nodes from ajax. This will significantly speed up the index in sites with an high amount of pages.
+ * Changes: Old max option renamed to maxjs.
+
+ * **2007-06-10 Version 3.5**:
+ * Bug: tsort option did not sort namespaces.
+
+ * **2007-06-08 Version 3.4**:
+ * New Feature: Added option "tsort" to sort nodes by title.
+ * Security Fix: Fixed ajax security with toc preview.
+
+ * **2007-06-04 Version 3.3**:
+ * :!: You could need to purge browser cache after installing it.
+ * New Feature: Added a Toc preview for javascript tree. You can disable it with "notoc" option.
+ * New Feature: The tree is always automatically updated with every requested namespace. You don't need anymore any ~~NOCACHE~~ or &purge options.
+ * New Feature: Acls work correctly with every requested namespace. Be sure to set correctly the [[.:indexmenu#acl cache]] option.
+ * New Feature: Added a global option to replace the dokuwiki index with an indexmenu page.
+ * New Feature: Added the global "Acl cache" option in order to optimize the acl caching mechanism. Please, read info at [[.:indexmenu#acl cache]].
+ * Changes: The size of the scrolling arrow image adjusts itself dynamically.
+ * Changes: Added the uncompressed javascript file for development purpose.
+ * Bug: The "Deny indexmenu to no-admins" now works correctly.
+
+ * **2007-05-10 Version 3.2**:
+ * Bug: Solved acl bug. It works only for root requested namespace.
+ * Bug: Solved start page bug. Patch by Adrien CLERC, thanks.
+
+ * **2007-03-14 Version 3.1**:
+ * :!: You could need to purge browser cache after installing it.
+ * New Feature: Themes deleting option in admin panel.
+ * Bug-New Feature: No-tree message now works and it supports wiki instructions.
+ * Bug: Js tree does not scroll anymore when nodes are visibles.
+ * Bug: Solved a bug with utf8 that prevented hidepages to work with no ASCII characters.
+ * Changes: Removed the automatic checking for updates option, because it slows down a bit the pages loading. Now it's manual and it's in admin panel.
+
+ * **2007-01-25 Version 3.0**:
+ * New Feature: Quick initial tree render thanks to the max option.
+ * New Feature: Max option to set how many js tree levels initially render. By default is set to 1 to speed up initial page loading.
+ * New feature: Scrolling js tree when nodes length do not fit its container.
+ * New Feature: Js tree highligts the current page.
+ * New Feature: Added js tooltips.
+ * Change: Removed the theme images directory setting to avoid problems. A symlink do the same work and in a simplest way.
+ * Change: Nojs tree is displayed when javascript is disabled or fails.
+ * Bug: The heading titles option for pages now works only if the global useheading setting is on.
+ * Bug: Pages that does not contain anymore indexmenu instructions are nomore cache purged by indexmenu itself.
+ * Bug: Indexmenu is xhtml compatible.
+ * Others: Code improvements and cleaning. A big thanks to Anja Wagenbret for testing and helping.
+
+ * **2006-12-19 Version 2.9**:
+ * New feature: The tree is automatically updated when the specified namespaces is the site root (..).
+ You don't need anymore to use the NOCACHE istruction.
+ * New feature: Indexmenu theme management in admin panel. You can download and share js themes.
+ * New feature: "navbar" option: the tree opens automatically itself at the current page namespace.
+ Good as navigation sidebar.
+ * Changed: Disabled custom css style for nojs menu when headpage is off.
+ * Bug: Firefox sometimes corrupt cached dokuwiki javascript.
+ This is an attempt to solve this bug, i hope it works (any feedback is welcome).
+ * Bug: Displayed incorrect titles when headpages are disable.
+
+ * **2006-11-09 Version 2.8**:
+ * New Feature: Option to deny the indexmenu use to no-admins.
+ * New Feature: Option to check for indexmenu updates when in admin mode ((need web connection to my site)).
+ * New Feature: Css style for namespaces and headpages links in nojs status as suggested by Mathiasm.
+ * New Feature: Support for png and jpg images formats for the js theme.
+ * Bug: Solved the Call-time pass-by-reference php5 bug.
+ * Changed: Changed some static css property into dynamic.
+
+ * **2006-10-23 Version 2.7**:
+ * :!: The default release is Compatible with Dokuwiki RC and it's configurable throught [[plugin:config|Configuration Manager]]. 2006-09-03 Dokuwiki users should read the [[.:indexmenu#How to install]] infos.
+ * Changes: Optional namespaces now works as you expect.
+ * Bug Fixed: Indexmenu button toolbar not showed when page is readonly. Thanks to [[neospams@vodafone.de|Neosky]].
+ * Bug Fixed: Escape of html in titles.
+ * Changes: Better displaying of default theme icons on dark background. Thanks to Paul Grove.
+ * Cosmetic code changes.
+ * **2006-10-7 Version 2.6**:
+ * New feature: Optional namespaces option.
+ * New feature: ".:ns" now specifies the "ns" namespace inside current namespace.
+ * Changes: "Cookie" option substituted by "nocookie" option. Now cookies are enabled by default.
+ * New feature: Custom headpages icon and css style in js mode.
+ * New feature: Added a Dtree option that should speed up the tree rendering.
+ * New feature: If scripts are disabled by the browser, standard tree will be showed in place of js one.
+ * New feature: Skip files option. Coded by Jon B (thanks).
+ * New feature: Customizable js theme directory path.
+ * New feature: Indexmenu toolbar in "edit page" mode.
+
+ * **2006-09-10 Version 2.5**:
+ * New feature: More customizable headpage option ((old "true" value is automatically translated into the :inside: option)).
+ * New feature: Js cookie option.
+ * New feature: Js id option. Many thanks to [[frbaron@gmail.com|Franck Baron]].
+ * New feature: Skip index option. Many thanks to [[ilya@lebedev.net|Ilya Lebedev AKA WingedFox]].
+ * Fixed bug: Incorrect ACL namespace. Many thanks to [[raymond@raycom.com|Raymond Elferink]].
+
+ * **2006-07-10 Version 2.4**:
+ * Fixed bug: Strange behaviours when using [[wiki:config#userewrite]] and [[wiki:config#useslash]].
+ * Fixed bug: No namespace title when the "." namespace is requested.
+ * Fixed bug: When title of the page contains %%'%% symbol, indexmenu fails.
+
+ * **2006-06-25 Version 2.3**:
+ * Fixed bug: incorrect namespaces levels. Many thanks to [[http://fredfred.net/skriker|malyfred]].
+ * Fixed bug: empty namespace title if headpage has no title.
+ * Fixed bug: nons doesn't work with js option.
+ * Fixed bug: parameters check.
+ * Fixed bug: start page is not hidden with js option.
+ * Fixed bug: acl denied namespaces are displayed. info [[.:indexmenu#about_acl|here]].
+
+ * **2006-06-13 Version 2.2**:
+is for the [[http://www.destroydrop.com/javascripts/tree/|dTree]] menu. Thanks to the [[.:tree]] plugin for the idea.
+ * Custom themes and style for javascript menu.
+
+ * **2006-06-12 Version 2.1**:
+ * Changed the way ''headpage'' option works.
+ * Added ''hide_headpage'' option to hide headpages.
+
+ * **2006-06-12 Version 2.0**:
+ * Added the ''headpage'' global configuration option to customize namespaces title and link. Thanks to [[bru@inbox.ru|Gleb]] for this nice idea.
+ *Javascript level bug fixed.
+ *Changed the base icon in default js theme.
+
+ * **2006-04-05 Version 1.9**:
+ * Added the javascript tree method. Thanks to Geir Landr
+
+ * **2006-04-05 Version 1.4**:
+ * Replaced the ''closed'' argument with a more powerful level number option. I guess it is the last modification on this argument.
+ * Small code fix.
+
+ * **2006-04-04 Version 1.3**:
+ * New ''nons'' option for excluding namespace items from index as suggested by //[[bru@inbox.ru|Gleb]]//.
+ * Some cosmetic changes (changed the argument name for closed index).
+
+ * **2006-04-01 Version 1.2**:
+ * Root namespace index. Thanks to [[cbeetle@physics.fau.edu|Chris Beetle]].
+
+ * **2006-03-29 Version 1.1**:
+ * Recursive tree index of all pages and namespaces beneath the specified namespace.
+ * Lexical option for disabling the tree index and only showing the first level.
+
+ * **2006-03-24 Version 1.0**:
+ * Released.
+ * Fixed bug in namespaces title visualization.
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/conf/default.php b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/conf/default.php
new file mode 100644
index 000000000..7c0f46228
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/conf/default.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Default configuration for indexmenu plugin
+ *
+ * @license: GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author: Samuele Tognini <samuele@netsons.org>
+ */
+$conf['only_admins'] = 0;
+$conf['aclcache'] = 'groups';
+$conf['headpage'] = ':start:,:same:,:inside:';
+$conf['hide_headpage'] = 1;
+$conf['page_index'] = '';
+$conf['empty_msg'] = '';
+$conf['skip_index'] = '';
+$conf['skip_file'] = 'sidebar';
+$conf['show_sort'] = true;
+$conf['themes_url'] = 'http://samuele.netsons.org/dokuwiki';
+$conf['be_repo'] = false;
+$conf['sneaky_index'] = (isset($GLOBALS['conf']['sneaky_index'])) ? $GLOBALS['conf']['sneaky_index'] : true;
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/conf/metadata.php b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/conf/metadata.php
new file mode 100644
index 000000000..cd45f163a
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/conf/metadata.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * Configuration-manager metadata for indexmenu plugin
+ *
+ * @license: GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author: Samuele Tognini <samuele@netsons.org>
+ */
+$meta['only_admins'] = array('onoff');
+$meta['aclcache'] = array('multichoice', '_choices' => array('none', 'user' ,'groups'));
+$meta['headpage'] = array('multicheckbox', '_choices' => array(':start:', ':same:' ,':inside:'));
+$meta['hide_headpage'] = array('onoff');
+$meta['page_index'] = array('string', '_pattern' => '#^[a-z:]*#');
+$meta['empty_msg'] = array('string');
+$meta['skip_index'] = array('string','_pattern' => '/^($|\/.*\/.*$)/');
+$meta['skip_file'] = array('string','_pattern' => '/^($|\/.*\/.*$)/');
+$meta['show_sort'] = array('onoff');
+//$meta['themes_url'] = array('string','_pattern' => '/^($|http:\/\/\S+$)/i');
+//$meta['be_repo'] = array('onoff');
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/edit-full.js b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/edit-full.js
new file mode 100644
index 000000000..9ab87c8a8
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/edit-full.js
@@ -0,0 +1,152 @@
+function indexmenu_toolbar_additions() {
+ var edbtn,cmenu,indx_btn,toolbar = DOKUid('tool__bar');
+ if(!toolbar) return;
+ edbtn = DOKUid('edbtn__save');
+ if(!edbtn) return;
+ var indx_list = indexmenu_createPicker('picker_plugin_indexmenu');
+ indx_btn = indexmenu_createToolbar();
+ toolbar.appendChild(indx_btn);
+ indx_btn.onclick = function(){indexmenu_ajaxmenu('req=local',indx_list,this,false,indexmenu_createThemes);return false;};
+ cmenu=window.indexmenu_contextmenu;
+ if(cmenu[1]) {
+ window.indexmenu_contextmenu[0]=cmenu[1].concat(cmenu[0]);
+ }
+}
+
+function indexmenu_createThemes(data,indx_list) {
+ if (data.substring(0,9) != 'indexmenu') {
+ indx_list.innerHTML="Retrieving error";
+ return;
+ }
+ var checkboxes=[['<p><strong><em>Navigation</em></strong></p>',0],
+ ['navbar','The tree opens at the current namespace'],
+ ['context','Display the tree of the current wiki namespace context'],
+ ['nocookie','Don\t remember open/closed nodes during user navigation'],
+ ['noscroll','Prevent to scrolling the tree when it does not fit its container width'],
+ ['notoc','Disable the toc preview feature'],
+ ['<p><strong><em>Sort</em></strong></p>',0],
+ ['nsort','Sort also namespaces'],
+ ['tsort','By title'],
+ ['dsort','By date'],
+ ['msort','By meta tag'],
+ ['<p><strong><em>Performance</em></strong></p>',0],
+ ['max#2','How many levels to render with ajax when a node is opened'],
+ ['maxjs#2','How many levels to render in the client browser when a node is opened'],
+ ['<p><strong><em>Filters</em></strong></p>',0],
+ ['nons','Show only pages'],
+ ['nopg','Show only namespaces']];
+
+ var btn,key,theme_url,adata,f,f2,l,fo;
+ adata=data.split(',');
+ theme_url = DOKU_MEDIA + 'lib/plugins/indexmenu/images/';
+ f=indexmenu_toolFrame(indx_list,'Indexmenu');
+ l = document.createElement('div');
+ l.className = 'no indexmenu_nojstoolbar';
+ f.appendChild(l);
+ btn = createToolButton(DOKU_MEDIA + 'lib/tpl/default/images/open.gif','nojs index');
+ btn.innerHTML += 'Nojs';
+ btn.className = 'pickerbutton';
+ eval('btn.onclick = function(){indexmenu_opts("");}');
+ l.appendChild(btn);
+
+ l = document.createElement('div');
+ l.className = 'no indexmenu_jstoolbar';
+ f.appendChild(l);
+ if (adata[0] != 'indexmenu') {
+ l.innerHTML += 'No themes';
+ adata=[];
+ } else {
+ adata.splice(0,3);
+ }
+ for (key in adata) {
+ btn = createToolButton(theme_url + adata[key]+'/base.'+indexmenu_findExt(adata[key]),adata[key]);
+ btn.className = 'pickerbutton';
+ eval('btn.onclick = function(){indexmenu_opts("js#'+adata[key]+'");}');
+ l.appendChild(btn);
+ }
+ f2=indexmenu_toolFrame(indx_list,'Options');
+ fo=document.createElement('form');
+ fo.id='indexmenu_optfrm';
+ fo.className='indexmenu_opts';
+ f2.appendChild(fo);
+ for (key in checkboxes) {
+ lc = document.createElement('label');
+ lc.innerHTML=checkboxes[key][0]+' ';
+ if (checkboxes[key][1]) {
+ lc.title= checkboxes[key][1];
+ btn=document.createElement('input');
+ btn.type = 'checkbox';
+ btn.name = 'check';
+ btn.title = checkboxes[key][1];
+ btn.value = checkboxes[key][0];
+ fo.appendChild(btn);
+ }
+ fo.appendChild(lc);
+ }
+
+ l = document.createElement('div');
+ l.className = 'indexmenu_extratoolbar';
+ l.innerHTML='<p><strong><em>Extra</em></strong></p>';
+ f.appendChild(l);
+ btn = createToolButton(theme_url+'/msort.gif','Insert the sort meta-number');
+ btn.className = 'pickerbutton';
+ btn.onclick = function(){insertTags(
+ 'wiki__text',
+ '{{indexmenu_n>',
+ '}}',
+ '1'
+ );
+ DOKUid('picker_plugin_indexmenu').style.display='none';
+ return false;
+ };
+ l.appendChild(btn);
+}
+
+function indexmenu_createToolbar (){
+ var indx_ico = document.createElement('img');
+ indx_ico.src = DOKU_MEDIA + 'lib/plugins/indexmenu/images/indexmenu_toolbar.png';
+ var indx_btn = document.createElement('button');
+ indx_btn.id = 'syntax_plugin_indexmenu';
+ indx_btn.className = 'toolbutton';
+ indx_btn.title = 'Insert the Indexmenu tree';
+ indx_btn.appendChild(indx_ico);
+ return indx_btn;
+}
+
+function indexmenu_opts(m) {
+ var i,v = '';
+ var f=DOKUid('indexmenu_optfrm');
+ for (i=0; i < f.length; i++) {
+ if (f[i].checked) {
+ v = v + ' ' + f[i].value;
+ }
+ }
+ insertTags(
+ 'wiki__text',
+ '{{indexmenu>',
+ ((m||v)?'|':'')+m.replace(/#default$/,'')+v+'}}',
+ '#1'
+ );
+ DOKUid('picker_plugin_indexmenu').style.display='none';
+ return false;
+}
+
+function indexmenu_insertTags(lnk,sep) {
+ var r,l=lnk;
+ if (sep) {
+ r=new RegExp (sep,"g");
+ l=lnk.replace(r,':');
+ }
+ insertTags('wiki__text','[[',']]',l);
+}
+
+function indexmenu_toolFrame(parent,txt) {
+ f=document.createElement('fieldset');
+ l=document.createElement('legend');
+ l.innerHTML='<strong>'+txt+'</strong>';
+ f.appendChild(l);
+ parent.appendChild(f);
+ return f;
+}
+
+indexmenu_toolbar_additions();
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/edit.js b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/edit.js
new file mode 100644
index 000000000..7deb5a596
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/edit.js
@@ -0,0 +1 @@
+function indexmenu_toolbar_additions(){var e,d,c,b=DOKUid("tool__bar");if(!b){return;}e=DOKUid("edbtn__save");if(!e){return;}var a=indexmenu_createPicker("picker_plugin_indexmenu");c=indexmenu_createToolbar();b.appendChild(c);c.onclick=(function(){indexmenu_ajaxmenu("req=local",a,this,false,indexmenu_createThemes);return false;});d=window.indexmenu_contextmenu;if(d[1]){window.indexmenu_contextmenu[0]=d[1].concat(d[0]);}}function indexmenu_createThemes(k,j){if(k.substring(0,9)!="indexmenu"){j.innerHTML="Retrieving error";return;}var i=[["<p><strong><em>Navigation</em></strong></p>",0],["navbar","The tree opens at the current namespace"],["context","Display the tree of the current wiki namespace context"],["nocookie","Don\t remember open/closed nodes during user navigation"],["noscroll","Prevent to scrolling the tree when it does not fit its container width"],["notoc","Disable the toc preview feature"],["<p><strong><em>Sort</em></strong></p>",0],["nsort","Sort also namespaces"],["tsort","By title"],["dsort","By date"],["msort","By meta tag"],["<p><strong><em>Performance</em></strong></p>",0],["max#2","How many levels to render with ajax when a node is opened"],["maxjs#2","How many levels to render in the client browser when a node is opened"],["<p><strong><em>Filters</em></strong></p>",0],["nons","Show only pages"],["nopg","Show only namespaces"]];var h,g,f,e,d,c,b,a;e=k.split(",");f=DOKU_MEDIA+"lib/plugins/indexmenu/images/";d=indexmenu_toolFrame(j,"Indexmenu");b=document.createElement("div");b.className="no indexmenu_nojstoolbar";d.appendChild(b);h=createToolButton(DOKU_MEDIA+"lib/tpl/default/images/open.gif","nojs index");h.innerHTML+="Nojs";h.className="pickerbutton";eval("b.onclick = function(){indexmenu_opts(\"\");}");b.appendChild(h);b=document.createElement("div");b.className="no indexmenu_jstoolbar";d.appendChild(b);if(e[0]!="indexmenu"){b.innerHTML+="No themes";e=[];}else{e.splice(0,3);}for(g in e){h=createToolButton(f+e[g]+"/base."+indexmenu_findExt(e[g]),e[g]);h.className="pickerbutton";eval("h.onclick = function(){indexmenu_opts(\"js#"+e[g]+"\");}");b.appendChild(h);}c=indexmenu_toolFrame(j,"Options");a=document.createElement("form");a.id="indexmenu_optfrm";a.className="indexmenu_opts";c.appendChild(a);for(g in i){lc=document.createElement("label");lc.innerHTML=i[g][0]+" ";if(i[g][1]){lc.title=i[g][1];h=document.createElement("input");h.type="checkbox";h.name="check";h.title=i[g][1];h.value=i[g][0];a.appendChild(h);}a.appendChild(lc);}b=document.createElement("div");b.className="indexmenu_extratoolbar";b.innerHTML="<p><strong><em>Extra</em></strong></p>";d.appendChild(b);h=createToolButton(f+"/msort.gif","Insert the sort meta-number");h.className="pickerbutton";h.onclick=(function(){insertTags("wiki__text","{{indexmenu_n>","}}","1");DOKUid("picker_plugin_indexmenu").style.display="none";return false;});b.appendChild(h);}function indexmenu_createToolbar(){var b=document.createElement("img");b.src=DOKU_MEDIA+"lib/plugins/indexmenu/images/indexmenu_toolbar.png";var a=document.createElement("button");a.id="syntax_plugin_indexmenu";a.className="toolbutton";a.title="Insert the Indexmenu tree";a.appendChild(b);return a;}function indexmenu_opts(d){var c,b="";var a=DOKUid("indexmenu_optfrm");for(c=0;c<a.length;c++){if(a[c].checked){b=b+" "+a[c].value;}}insertTags("wiki__text","{{indexmenu>",((d||b)?"|":"")+d.replace(/#default$/,"")+b+"}}","#1");DOKUid("picker_plugin_indexmenu").style.display="none";return false;}function indexmenu_insertTags(d,c){var b,a=d;if(c){b=new RegExp(c,"g");a=d.replace(b,":");}insertTags("wiki__text","[[","]]",a);}function indexmenu_toolFrame(b,a){f=document.createElement("fieldset");l=document.createElement("legend");l.innerHTML="<strong>"+a+"</strong>";f.appendChild(l);b.appendChild(f);return f;}indexmenu_toolbar_additions();
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/close.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/close.gif
new file mode 100644
index 000000000..8c07da8ad
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/close.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/base.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/base.gif
new file mode 100644
index 000000000..ced7f0879
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/base.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/empty.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/empty.gif
new file mode 100644
index 000000000..b5cf52378
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/empty.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/folder.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/folder.gif
new file mode 100644
index 000000000..0d7d6431b
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/folder.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/folderh.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/folderh.gif
new file mode 100644
index 000000000..c7c9f7ed6
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/folderh.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/folderhopen.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/folderhopen.gif
new file mode 100644
index 000000000..20fe6ace1
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/folderhopen.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/folderopen.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/folderopen.gif
new file mode 100644
index 000000000..a9c466a5b
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/folderopen.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/info.txt b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/info.txt
new file mode 100644
index 000000000..1b1d8cde3
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/info.txt
@@ -0,0 +1,2 @@
+author=Samuele Tognini
+url=http://samuele.netsons.org/dokuwiki
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/join.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/join.gif
new file mode 100644
index 000000000..34dd47610
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/join.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/joinbottom.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/joinbottom.gif
new file mode 100644
index 000000000..48b81c80a
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/joinbottom.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/line.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/line.gif
new file mode 100644
index 000000000..1a259eea0
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/line.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/minus.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/minus.gif
new file mode 100644
index 000000000..3d212a97a
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/minus.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/minusbottom.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/minusbottom.gif
new file mode 100644
index 000000000..dc3198be2
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/minusbottom.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/nolines_minus.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/nolines_minus.gif
new file mode 100644
index 000000000..2592ac20f
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/nolines_minus.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/nolines_plus.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/nolines_plus.gif
new file mode 100644
index 000000000..f258ce211
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/nolines_plus.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/page.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/page.gif
new file mode 100644
index 000000000..5d120fa99
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/page.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/plus.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/plus.gif
new file mode 100644
index 000000000..b2c997233
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/plus.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/plusbottom.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/plusbottom.gif
new file mode 100644
index 000000000..b5671d891
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/default/plusbottom.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/empty.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/empty.gif
new file mode 100644
index 000000000..afbe6429d
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/empty.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/indexmenu_toolbar.png b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/indexmenu_toolbar.png
new file mode 100644
index 000000000..460e0f981
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/indexmenu_toolbar.png
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/larrow.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/larrow.gif
new file mode 100644
index 000000000..a0f09e9d1
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/larrow.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/msort.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/msort.gif
new file mode 100644
index 000000000..5dae8131d
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/msort.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/rarrow.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/rarrow.gif
new file mode 100644
index 000000000..58a4158f5
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/rarrow.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/toc_bullet.gif b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/toc_bullet.gif
new file mode 100644
index 000000000..a90924ce8
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/images/toc_bullet.gif
Binary files differ
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/inc/pclzip.lib.php b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/inc/pclzip.lib.php
new file mode 100644
index 000000000..19f20b9da
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/inc/pclzip.lib.php
@@ -0,0 +1,5748 @@
+<?php
+// --------------------------------------------------------------------------------
+// PhpConcept Library - Zip Module 2.5
+// --------------------------------------------------------------------------------
+// License GNU/LGPL - Vincent Blavet - March 2006
+// http://www.phpconcept.net
+// --------------------------------------------------------------------------------
+//
+// Presentation :
+// PclZip is a PHP library that manage ZIP archives.
+// So far tests show that archives generated by PclZip are readable by
+// WinZip application and other tools.
+//
+// Description :
+// See readme.txt and http://www.phpconcept.net
+//
+// Warning :
+// This library and the associated files are non commercial, non professional
+// work.
+// It should not have unexpected results. However if any damage is caused by
+// this software the author can not be responsible.
+// The use of this software is at the risk of the user.
+//
+// --------------------------------------------------------------------------------
+// $Id: pclzip.lib.php,v 1.44 2006/03/08 21:23:59 vblavet Exp $
+// --------------------------------------------------------------------------------
+
+ // ----- Constants
+ define( 'PCLZIP_READ_BLOCK_SIZE', 2048 );
+
+ // ----- File list separator
+ // In version 1.x of PclZip, the separator for file list is a space
+ // (which is not a very smart choice, specifically for windows paths !).
+ // A better separator should be a comma (,). This constant gives you the
+ // abilty to change that.
+ // However notice that changing this value, may have impact on existing
+ // scripts, using space separated filenames.
+ // Recommanded values for compatibility with older versions :
+ //define( 'PCLZIP_SEPARATOR', ' ' );
+ // Recommanded values for smart separation of filenames.
+ define( 'PCLZIP_SEPARATOR', ',' );
+
+ // ----- Error configuration
+ // 0 : PclZip Class integrated error handling
+ // 1 : PclError external library error handling. By enabling this
+ // you must ensure that you have included PclError library.
+ // [2,...] : reserved for futur use
+ define( 'PCLZIP_ERROR_EXTERNAL', 0 );
+
+ // ----- Optional static temporary directory
+ // By default temporary files are generated in the script current
+ // path.
+ // If defined :
+ // - MUST BE terminated by a '/'.
+ // - MUST be a valid, already created directory
+ // Samples :
+ // define( 'PCLZIP_TEMPORARY_DIR', '/temp/' );
+ // define( 'PCLZIP_TEMPORARY_DIR', 'C:/Temp/' );
+ define( 'PCLZIP_TEMPORARY_DIR', '' );
+
+// --------------------------------------------------------------------------------
+// ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
+// --------------------------------------------------------------------------------
+
+ // ----- Global variables
+ $g_pclzip_version = "2.5";
+
+ // ----- Error codes
+ // -1 : Unable to open file in binary write mode
+ // -2 : Unable to open file in binary read mode
+ // -3 : Invalid parameters
+ // -4 : File does not exist
+ // -5 : Filename is too long (max. 255)
+ // -6 : Not a valid zip file
+ // -7 : Invalid extracted file size
+ // -8 : Unable to create directory
+ // -9 : Invalid archive extension
+ // -10 : Invalid archive format
+ // -11 : Unable to delete file (unlink)
+ // -12 : Unable to rename file (rename)
+ // -13 : Invalid header checksum
+ // -14 : Invalid archive size
+ define( 'PCLZIP_ERR_USER_ABORTED', 2 );
+ define( 'PCLZIP_ERR_NO_ERROR', 0 );
+ define( 'PCLZIP_ERR_WRITE_OPEN_FAIL', -1 );
+ define( 'PCLZIP_ERR_READ_OPEN_FAIL', -2 );
+ define( 'PCLZIP_ERR_INVALID_PARAMETER', -3 );
+ define( 'PCLZIP_ERR_MISSING_FILE', -4 );
+ define( 'PCLZIP_ERR_FILENAME_TOO_LONG', -5 );
+ define( 'PCLZIP_ERR_INVALID_ZIP', -6 );
+ define( 'PCLZIP_ERR_BAD_EXTRACTED_FILE', -7 );
+ define( 'PCLZIP_ERR_DIR_CREATE_FAIL', -8 );
+ define( 'PCLZIP_ERR_BAD_EXTENSION', -9 );
+ define( 'PCLZIP_ERR_BAD_FORMAT', -10 );
+ define( 'PCLZIP_ERR_DELETE_FILE_FAIL', -11 );
+ define( 'PCLZIP_ERR_RENAME_FILE_FAIL', -12 );
+ define( 'PCLZIP_ERR_BAD_CHECKSUM', -13 );
+ define( 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', -14 );
+ define( 'PCLZIP_ERR_MISSING_OPTION_VALUE', -15 );
+ define( 'PCLZIP_ERR_INVALID_OPTION_VALUE', -16 );
+ define( 'PCLZIP_ERR_ALREADY_A_DIRECTORY', -17 );
+ define( 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', -18 );
+ define( 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION', -19 );
+ define( 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE', -20 );
+ define( 'PCLZIP_ERR_DIRECTORY_RESTRICTION', -21 );
+
+ // ----- Options values
+ define( 'PCLZIP_OPT_PATH', 77001 );
+ define( 'PCLZIP_OPT_ADD_PATH', 77002 );
+ define( 'PCLZIP_OPT_REMOVE_PATH', 77003 );
+ define( 'PCLZIP_OPT_REMOVE_ALL_PATH', 77004 );
+ define( 'PCLZIP_OPT_SET_CHMOD', 77005 );
+ define( 'PCLZIP_OPT_EXTRACT_AS_STRING', 77006 );
+ define( 'PCLZIP_OPT_NO_COMPRESSION', 77007 );
+ define( 'PCLZIP_OPT_BY_NAME', 77008 );
+ define( 'PCLZIP_OPT_BY_INDEX', 77009 );
+ define( 'PCLZIP_OPT_BY_EREG', 77010 );
+ define( 'PCLZIP_OPT_BY_PREG', 77011 );
+ define( 'PCLZIP_OPT_COMMENT', 77012 );
+ define( 'PCLZIP_OPT_ADD_COMMENT', 77013 );
+ define( 'PCLZIP_OPT_PREPEND_COMMENT', 77014 );
+ define( 'PCLZIP_OPT_EXTRACT_IN_OUTPUT', 77015 );
+ define( 'PCLZIP_OPT_REPLACE_NEWER', 77016 );
+ define( 'PCLZIP_OPT_STOP_ON_ERROR', 77017 );
+ // Having big trouble with crypt. Need to multiply 2 long int
+ // which is not correctly supported by PHP ...
+ //define( 'PCLZIP_OPT_CRYPT', 77018 );
+ define( 'PCLZIP_OPT_EXTRACT_DIR_RESTRICTION', 77019 );
+
+ // ----- File description attributes
+ define( 'PCLZIP_ATT_FILE_NAME', 79001 );
+ define( 'PCLZIP_ATT_FILE_NEW_SHORT_NAME', 79002 );
+ define( 'PCLZIP_ATT_FILE_NEW_FULL_NAME', 79003 );
+
+ // ----- Call backs values
+ define( 'PCLZIP_CB_PRE_EXTRACT', 78001 );
+ define( 'PCLZIP_CB_POST_EXTRACT', 78002 );
+ define( 'PCLZIP_CB_PRE_ADD', 78003 );
+ define( 'PCLZIP_CB_POST_ADD', 78004 );
+ /* For futur use
+ define( 'PCLZIP_CB_PRE_LIST', 78005 );
+ define( 'PCLZIP_CB_POST_LIST', 78006 );
+ define( 'PCLZIP_CB_PRE_DELETE', 78007 );
+ define( 'PCLZIP_CB_POST_DELETE', 78008 );
+ */
+
+ // --------------------------------------------------------------------------------
+ // Class : PclZip
+ // Description :
+ // PclZip is the class that represent a Zip archive.
+ // The public methods allow the manipulation of the archive.
+ // Attributes :
+ // Attributes must not be accessed directly.
+ // Methods :
+ // PclZip() : Object creator
+ // create() : Creates the Zip archive
+ // listContent() : List the content of the Zip archive
+ // extract() : Extract the content of the archive
+ // properties() : List the properties of the archive
+ // --------------------------------------------------------------------------------
+ class PclZip
+ {
+ // ----- Filename of the zip file
+ var $zipname = '';
+
+ // ----- File descriptor of the zip file
+ var $zip_fd = 0;
+
+ // ----- Internal error handling
+ var $error_code = 1;
+ var $error_string = '';
+
+ // ----- Current status of the magic_quotes_runtime
+ // This value store the php configuration for magic_quotes
+ // The class can then disable the magic_quotes and reset it after
+ var $magic_quotes_status;
+
+ // --------------------------------------------------------------------------------
+ // Function : PclZip()
+ // Description :
+ // Creates a PclZip object and set the name of the associated Zip archive
+ // filename.
+ // Note that no real action is taken, if the archive does not exist it is not
+ // created. Use create() for that.
+ // --------------------------------------------------------------------------------
+ function PclZip($p_zipname)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::PclZip', "zipname=$p_zipname");
+
+ // ----- Tests the zlib
+ if (!function_exists('gzopen'))
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 1, "zlib extension seems to be missing");
+ die('Abort '.basename(__FILE__).' : Missing zlib extensions');
+ }
+
+ // ----- Set the attributes
+ $this->zipname = $p_zipname;
+ $this->zip_fd = 0;
+ $this->magic_quotes_status = -1;
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 1);
+ return;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function :
+ // create($p_filelist, $p_add_dir="", $p_remove_dir="")
+ // create($p_filelist, $p_option, $p_option_value, ...)
+ // Description :
+ // This method supports two different synopsis. The first one is historical.
+ // This method creates a Zip Archive. The Zip file is created in the
+ // filesystem. The files and directories indicated in $p_filelist
+ // are added in the archive. See the parameters description for the
+ // supported format of $p_filelist.
+ // When a directory is in the list, the directory and its content is added
+ // in the archive.
+ // In this synopsis, the function takes an optional variable list of
+ // options. See bellow the supported options.
+ // Parameters :
+ // $p_filelist : An array containing file or directory names, or
+ // a string containing one filename or one directory name, or
+ // a string containing a list of filenames and/or directory
+ // names separated by spaces.
+ // $p_add_dir : A path to add before the real path of the archived file,
+ // in order to have it memorized in the archive.
+ // $p_remove_dir : A path to remove from the real path of the file to archive,
+ // in order to have a shorter path memorized in the archive.
+ // When $p_add_dir and $p_remove_dir are set, $p_remove_dir
+ // is removed first, before $p_add_dir is added.
+ // Options :
+ // PCLZIP_OPT_ADD_PATH :
+ // PCLZIP_OPT_REMOVE_PATH :
+ // PCLZIP_OPT_REMOVE_ALL_PATH :
+ // PCLZIP_OPT_COMMENT :
+ // PCLZIP_CB_PRE_ADD :
+ // PCLZIP_CB_POST_ADD :
+ // Return Values :
+ // 0 on failure,
+ // The list of the added files, with a status of the add action.
+ // (see PclZip::listContent() for list entry format)
+ // --------------------------------------------------------------------------------
+ function create($p_filelist)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::create', "filelist='$p_filelist', ...");
+ $v_result=1;
+
+ // ----- Reset the error handler
+ $this->privErrorReset();
+
+ // ----- Set default values
+ $v_options = array();
+ $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
+
+ // ----- Look for variable options arguments
+ $v_size = func_num_args();
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
+
+ // ----- Look for arguments
+ if ($v_size > 1) {
+ // ----- Get the arguments
+ $v_arg_list = func_get_args();
+
+ // ----- Remove from the options list the first argument
+ array_shift($v_arg_list);
+ $v_size--;
+
+ // ----- Look for first arg
+ if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options detected");
+
+ // ----- Parse the options
+ $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
+ array (PCLZIP_OPT_REMOVE_PATH => 'optional',
+ PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
+ PCLZIP_OPT_ADD_PATH => 'optional',
+ PCLZIP_CB_PRE_ADD => 'optional',
+ PCLZIP_CB_POST_ADD => 'optional',
+ PCLZIP_OPT_NO_COMPRESSION => 'optional',
+ PCLZIP_OPT_COMMENT => 'optional'
+ //, PCLZIP_OPT_CRYPT => 'optional'
+ ));
+ if ($v_result != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return 0;
+ }
+ }
+
+ // ----- Look for 2 args
+ // Here we need to support the first historic synopsis of the
+ // method.
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
+
+ // ----- Get the first argument
+ $v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0];
+
+ // ----- Look for the optional second argument
+ if ($v_size == 2) {
+ $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
+ }
+ else if ($v_size > 2) {
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
+ "Invalid number / type of arguments");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return 0;
+ }
+ }
+ }
+
+ // ----- Init
+ $v_string_list = array();
+ $v_att_list = array();
+ $v_filedescr_list = array();
+ $p_result_list = array();
+
+ // ----- Look if the $p_filelist is really an array
+ if (is_array($p_filelist)) {
+
+ // ----- Look if the first element is also an array
+ // This will mean that this is a file description entry
+ if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
+ $v_att_list = $p_filelist;
+ }
+
+ // ----- The list is a list of string names
+ else {
+ $v_string_list = $p_filelist;
+ }
+ }
+
+ // ----- Look if the $p_filelist is a string
+ else if (is_string($p_filelist)) {
+ // ----- Create a list from the string
+ $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
+ }
+
+ // ----- Invalid variable type for $p_filelist
+ else {
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return 0;
+ }
+
+ // ----- Reformat the string list
+ if (sizeof($v_string_list) != 0) {
+ foreach ($v_string_list as $v_string) {
+ if ($v_string != '') {
+ $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
+ }
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Ignore an empty filename");
+ }
+ }
+ }
+
+ // ----- For each file in the list check the attributes
+ $v_supported_attributes
+ = array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
+ ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
+ ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
+ );
+ foreach ($v_att_list as $v_entry) {
+ $v_result = $this->privFileDescrParseAtt($v_entry,
+ $v_filedescr_list[],
+ $v_options,
+ $v_supported_attributes);
+ if ($v_result != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return 0;
+ }
+ }
+
+ // ----- Expand the filelist (expand directories)
+ $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
+ if ($v_result != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return 0;
+ }
+
+ // ----- Call the create fct
+ $v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options);
+ if ($v_result != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return 0;
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_result_list);
+ return $p_result_list;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function :
+ // add($p_filelist, $p_add_dir="", $p_remove_dir="")
+ // add($p_filelist, $p_option, $p_option_value, ...)
+ // Description :
+ // This method supports two synopsis. The first one is historical.
+ // This methods add the list of files in an existing archive.
+ // If a file with the same name already exists, it is added at the end of the
+ // archive, the first one is still present.
+ // If the archive does not exist, it is created.
+ // Parameters :
+ // $p_filelist : An array containing file or directory names, or
+ // a string containing one filename or one directory name, or
+ // a string containing a list of filenames and/or directory
+ // names separated by spaces.
+ // $p_add_dir : A path to add before the real path of the archived file,
+ // in order to have it memorized in the archive.
+ // $p_remove_dir : A path to remove from the real path of the file to archive,
+ // in order to have a shorter path memorized in the archive.
+ // When $p_add_dir and $p_remove_dir are set, $p_remove_dir
+ // is removed first, before $p_add_dir is added.
+ // Options :
+ // PCLZIP_OPT_ADD_PATH :
+ // PCLZIP_OPT_REMOVE_PATH :
+ // PCLZIP_OPT_REMOVE_ALL_PATH :
+ // PCLZIP_OPT_COMMENT :
+ // PCLZIP_OPT_ADD_COMMENT :
+ // PCLZIP_OPT_PREPEND_COMMENT :
+ // PCLZIP_CB_PRE_ADD :
+ // PCLZIP_CB_POST_ADD :
+ // Return Values :
+ // 0 on failure,
+ // The list of the added files, with a status of the add action.
+ // (see PclZip::listContent() for list entry format)
+ // --------------------------------------------------------------------------------
+ function add($p_filelist)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::add', "filelist='$p_filelist', ...");
+ $v_result=1;
+
+ // ----- Reset the error handler
+ $this->privErrorReset();
+
+ // ----- Set default values
+ $v_options = array();
+ $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
+
+ // ----- Look for variable options arguments
+ $v_size = func_num_args();
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
+
+ // ----- Look for arguments
+ if ($v_size > 1) {
+ // ----- Get the arguments
+ $v_arg_list = func_get_args();
+
+ // ----- Remove form the options list the first argument
+ array_shift($v_arg_list);
+ $v_size--;
+
+ // ----- Look for first arg
+ if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options detected");
+
+ // ----- Parse the options
+ $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
+ array (PCLZIP_OPT_REMOVE_PATH => 'optional',
+ PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
+ PCLZIP_OPT_ADD_PATH => 'optional',
+ PCLZIP_CB_PRE_ADD => 'optional',
+ PCLZIP_CB_POST_ADD => 'optional',
+ PCLZIP_OPT_NO_COMPRESSION => 'optional',
+ PCLZIP_OPT_COMMENT => 'optional',
+ PCLZIP_OPT_ADD_COMMENT => 'optional',
+ PCLZIP_OPT_PREPEND_COMMENT => 'optional'
+ //, PCLZIP_OPT_CRYPT => 'optional'
+ ));
+ if ($v_result != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return 0;
+ }
+ }
+
+ // ----- Look for 2 args
+ // Here we need to support the first historic synopsis of the
+ // method.
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
+
+ // ----- Get the first argument
+ $v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0];
+
+ // ----- Look for the optional second argument
+ if ($v_size == 2) {
+ $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
+ }
+ else if ($v_size > 2) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return 0;
+ }
+ }
+ }
+
+ // ----- Init
+ $v_string_list = array();
+ $v_att_list = array();
+ $v_filedescr_list = array();
+ $p_result_list = array();
+
+ // ----- Look if the $p_filelist is really an array
+ if (is_array($p_filelist)) {
+
+ // ----- Look if the first element is also an array
+ // This will mean that this is a file description entry
+ if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
+ $v_att_list = $p_filelist;
+ }
+
+ // ----- The list is a list of string names
+ else {
+ $v_string_list = $p_filelist;
+ }
+ }
+
+ // ----- Look if the $p_filelist is a string
+ else if (is_string($p_filelist)) {
+ // ----- Create a list from the string
+ $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
+ }
+
+ // ----- Invalid variable type for $p_filelist
+ else {
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return 0;
+ }
+
+ // ----- Reformat the string list
+ if (sizeof($v_string_list) != 0) {
+ foreach ($v_string_list as $v_string) {
+ $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
+ }
+ }
+
+ // ----- For each file in the list check the attributes
+ $v_supported_attributes
+ = array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
+ ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
+ ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
+ );
+ foreach ($v_att_list as $v_entry) {
+ $v_result = $this->privFileDescrParseAtt($v_entry,
+ $v_filedescr_list[],
+ $v_options,
+ $v_supported_attributes);
+ if ($v_result != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return 0;
+ }
+ }
+
+ // ----- Expand the filelist (expand directories)
+ $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
+ if ($v_result != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return 0;
+ }
+
+ // ----- Call the create fct
+ $v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options);
+ if ($v_result != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return 0;
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_result_list);
+ return $p_result_list;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : listContent()
+ // Description :
+ // This public method, gives the list of the files and directories, with their
+ // properties.
+ // The properties of each entries in the list are (used also in other functions) :
+ // filename : Name of the file. For a create or add action it is the filename
+ // given by the user. For an extract function it is the filename
+ // of the extracted file.
+ // stored_filename : Name of the file / directory stored in the archive.
+ // size : Size of the stored file.
+ // compressed_size : Size of the file's data compressed in the archive
+ // (without the headers overhead)
+ // mtime : Last known modification date of the file (UNIX timestamp)
+ // comment : Comment associated with the file
+ // folder : true | false
+ // index : index of the file in the archive
+ // status : status of the action (depending of the action) :
+ // Values are :
+ // ok : OK !
+ // filtered : the file / dir is not extracted (filtered by user)
+ // already_a_directory : the file can not be extracted because a
+ // directory with the same name already exists
+ // write_protected : the file can not be extracted because a file
+ // with the same name already exists and is
+ // write protected
+ // newer_exist : the file was not extracted because a newer file exists
+ // path_creation_fail : the file is not extracted because the folder
+ // does not exists and can not be created
+ // write_error : the file was not extracted because there was a
+ // error while writing the file
+ // read_error : the file was not extracted because there was a error
+ // while reading the file
+ // invalid_header : the file was not extracted because of an archive
+ // format error (bad file header)
+ // Note that each time a method can continue operating when there
+ // is an action error on a file, the error is only logged in the file status.
+ // Return Values :
+ // 0 on an unrecoverable failure,
+ // The list of the files in the archive.
+ // --------------------------------------------------------------------------------
+ function listContent()
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::listContent', "");
+ $v_result=1;
+
+ // ----- Reset the error handler
+ $this->privErrorReset();
+
+ // ----- Check archive
+ if (!$this->privCheckFormat()) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return(0);
+ }
+
+ // ----- Call the extracting fct
+ $p_list = array();
+ if (($v_result = $this->privList($p_list)) != 1)
+ {
+ unset($p_list);
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
+ return(0);
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
+ return $p_list;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function :
+ // extract($p_path="./", $p_remove_path="")
+ // extract([$p_option, $p_option_value, ...])
+ // Description :
+ // This method supports two synopsis. The first one is historical.
+ // This method extract all the files / directories from the archive to the
+ // folder indicated in $p_path.
+ // If you want to ignore the 'root' part of path of the memorized files
+ // you can indicate this in the optional $p_remove_path parameter.
+ // By default, if a newer file with the same name already exists, the
+ // file is not extracted.
+ //
+ // If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions
+ // are used, the path indicated in PCLZIP_OPT_ADD_PATH is append
+ // at the end of the path value of PCLZIP_OPT_PATH.
+ // Parameters :
+ // $p_path : Path where the files and directories are to be extracted
+ // $p_remove_path : First part ('root' part) of the memorized path
+ // (if any similar) to remove while extracting.
+ // Options :
+ // PCLZIP_OPT_PATH :
+ // PCLZIP_OPT_ADD_PATH :
+ // PCLZIP_OPT_REMOVE_PATH :
+ // PCLZIP_OPT_REMOVE_ALL_PATH :
+ // PCLZIP_CB_PRE_EXTRACT :
+ // PCLZIP_CB_POST_EXTRACT :
+ // Return Values :
+ // 0 or a negative value on failure,
+ // The list of the extracted files, with a status of the action.
+ // (see PclZip::listContent() for list entry format)
+ // --------------------------------------------------------------------------------
+ function extract()
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::extract", "");
+ $v_result=1;
+
+ // ----- Reset the error handler
+ $this->privErrorReset();
+
+ // ----- Check archive
+ if (!$this->privCheckFormat()) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return(0);
+ }
+
+ // ----- Set default values
+ $v_options = array();
+// $v_path = "./";
+ $v_path = '';
+ $v_remove_path = "";
+ $v_remove_all_path = false;
+
+ // ----- Look for variable options arguments
+ $v_size = func_num_args();
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
+
+ // ----- Default values for option
+ $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
+
+ // ----- Look for arguments
+ if ($v_size > 0) {
+ // ----- Get the arguments
+ $v_arg_list = func_get_args();
+
+ // ----- Look for first arg
+ if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options");
+
+ // ----- Parse the options
+ $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
+ array (PCLZIP_OPT_PATH => 'optional',
+ PCLZIP_OPT_REMOVE_PATH => 'optional',
+ PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
+ PCLZIP_OPT_ADD_PATH => 'optional',
+ PCLZIP_CB_PRE_EXTRACT => 'optional',
+ PCLZIP_CB_POST_EXTRACT => 'optional',
+ PCLZIP_OPT_SET_CHMOD => 'optional',
+ PCLZIP_OPT_BY_NAME => 'optional',
+ PCLZIP_OPT_BY_EREG => 'optional',
+ PCLZIP_OPT_BY_PREG => 'optional',
+ PCLZIP_OPT_BY_INDEX => 'optional',
+ PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
+ PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional',
+ PCLZIP_OPT_REPLACE_NEWER => 'optional'
+ ,PCLZIP_OPT_STOP_ON_ERROR => 'optional'
+ ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional'
+ ));
+ if ($v_result != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return 0;
+ }
+
+ // ----- Set the arguments
+ if (isset($v_options[PCLZIP_OPT_PATH])) {
+ $v_path = $v_options[PCLZIP_OPT_PATH];
+ }
+ if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
+ $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
+ }
+ if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
+ $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
+ }
+ if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
+ // ----- Check for '/' in last path char
+ if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
+ $v_path .= '/';
+ }
+ $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
+ }
+ }
+
+ // ----- Look for 2 args
+ // Here we need to support the first historic synopsis of the
+ // method.
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
+
+ // ----- Get the first argument
+ $v_path = $v_arg_list[0];
+
+ // ----- Look for the optional second argument
+ if ($v_size == 2) {
+ $v_remove_path = $v_arg_list[1];
+ }
+ else if ($v_size > 2) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
+ return 0;
+ }
+ }
+ }
+
+ // ----- Trace
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "path='$v_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_path?'true':'false')."'");
+
+ // ----- Call the extracting fct
+ $p_list = array();
+ $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path,
+ $v_remove_all_path, $v_options);
+ if ($v_result < 1) {
+ unset($p_list);
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
+ return(0);
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
+ return $p_list;
+ }
+ // --------------------------------------------------------------------------------
+
+
+ // --------------------------------------------------------------------------------
+ // Function :
+ // extractByIndex($p_index, $p_path="./", $p_remove_path="")
+ // extractByIndex($p_index, [$p_option, $p_option_value, ...])
+ // Description :
+ // This method supports two synopsis. The first one is historical.
+ // This method is doing a partial extract of the archive.
+ // The extracted files or folders are identified by their index in the
+ // archive (from 0 to n).
+ // Note that if the index identify a folder, only the folder entry is
+ // extracted, not all the files included in the archive.
+ // Parameters :
+ // $p_index : A single index (integer) or a string of indexes of files to
+ // extract. The form of the string is "0,4-6,8-12" with only numbers
+ // and '-' for range or ',' to separate ranges. No spaces or ';'
+ // are allowed.
+ // $p_path : Path where the files and directories are to be extracted
+ // $p_remove_path : First part ('root' part) of the memorized path
+ // (if any similar) to remove while extracting.
+ // Options :
+ // PCLZIP_OPT_PATH :
+ // PCLZIP_OPT_ADD_PATH :
+ // PCLZIP_OPT_REMOVE_PATH :
+ // PCLZIP_OPT_REMOVE_ALL_PATH :
+ // PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and
+ // not as files.
+ // The resulting content is in a new field 'content' in the file
+ // structure.
+ // This option must be used alone (any other options are ignored).
+ // PCLZIP_CB_PRE_EXTRACT :
+ // PCLZIP_CB_POST_EXTRACT :
+ // Return Values :
+ // 0 on failure,
+ // The list of the extracted files, with a status of the action.
+ // (see PclZip::listContent() for list entry format)
+ // --------------------------------------------------------------------------------
+ //function extractByIndex($p_index, options...)
+ function extractByIndex($p_index)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::extractByIndex", "index='$p_index', ...");
+ $v_result=1;
+
+ // ----- Reset the error handler
+ $this->privErrorReset();
+
+ // ----- Check archive
+ if (!$this->privCheckFormat()) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return(0);
+ }
+
+ // ----- Set default values
+ $v_options = array();
+// $v_path = "./";
+ $v_path = '';
+ $v_remove_path = "";
+ $v_remove_all_path = false;
+
+ // ----- Look for variable options arguments
+ $v_size = func_num_args();
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
+
+ // ----- Default values for option
+ $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
+
+ // ----- Look for arguments
+ if ($v_size > 1) {
+ // ----- Get the arguments
+ $v_arg_list = func_get_args();
+
+ // ----- Remove form the options list the first argument
+ array_shift($v_arg_list);
+ $v_size--;
+
+ // ----- Look for first arg
+ if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options");
+
+ // ----- Parse the options
+ $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
+ array (PCLZIP_OPT_PATH => 'optional',
+ PCLZIP_OPT_REMOVE_PATH => 'optional',
+ PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
+ PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
+ PCLZIP_OPT_ADD_PATH => 'optional',
+ PCLZIP_CB_PRE_EXTRACT => 'optional',
+ PCLZIP_CB_POST_EXTRACT => 'optional',
+ PCLZIP_OPT_SET_CHMOD => 'optional',
+ PCLZIP_OPT_REPLACE_NEWER => 'optional'
+ ,PCLZIP_OPT_STOP_ON_ERROR => 'optional'
+ ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional'
+ ));
+ if ($v_result != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return 0;
+ }
+
+ // ----- Set the arguments
+ if (isset($v_options[PCLZIP_OPT_PATH])) {
+ $v_path = $v_options[PCLZIP_OPT_PATH];
+ }
+ if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
+ $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
+ }
+ if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
+ $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
+ }
+ if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
+ // ----- Check for '/' in last path char
+ if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
+ $v_path .= '/';
+ }
+ $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
+ }
+ if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) {
+ $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Option PCLZIP_OPT_EXTRACT_AS_STRING not set.");
+ }
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Option PCLZIP_OPT_EXTRACT_AS_STRING set.");
+ }
+ }
+
+ // ----- Look for 2 args
+ // Here we need to support the first historic synopsis of the
+ // method.
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
+
+ // ----- Get the first argument
+ $v_path = $v_arg_list[0];
+
+ // ----- Look for the optional second argument
+ if ($v_size == 2) {
+ $v_remove_path = $v_arg_list[1];
+ }
+ else if ($v_size > 2) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return 0;
+ }
+ }
+ }
+
+ // ----- Trace
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "index='$p_index', path='$v_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_path?'true':'false')."'");
+
+ // ----- Trick
+ // Here I want to reuse extractByRule(), so I need to parse the $p_index
+ // with privParseOptions()
+ $v_arg_trick = array (PCLZIP_OPT_BY_INDEX, $p_index);
+ $v_options_trick = array();
+ $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick,
+ array (PCLZIP_OPT_BY_INDEX => 'optional' ));
+ if ($v_result != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return 0;
+ }
+ $v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX];
+
+ // ----- Call the extracting fct
+ if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
+ return(0);
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
+ return $p_list;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function :
+ // delete([$p_option, $p_option_value, ...])
+ // Description :
+ // This method removes files from the archive.
+ // If no parameters are given, then all the archive is emptied.
+ // Parameters :
+ // None or optional arguments.
+ // Options :
+ // PCLZIP_OPT_BY_INDEX :
+ // PCLZIP_OPT_BY_NAME :
+ // PCLZIP_OPT_BY_EREG :
+ // PCLZIP_OPT_BY_PREG :
+ // Return Values :
+ // 0 on failure,
+ // The list of the files which are still present in the archive.
+ // (see PclZip::listContent() for list entry format)
+ // --------------------------------------------------------------------------------
+ function delete()
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::delete", "");
+ $v_result=1;
+
+ // ----- Reset the error handler
+ $this->privErrorReset();
+
+ // ----- Check archive
+ if (!$this->privCheckFormat()) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return(0);
+ }
+
+ // ----- Set default values
+ $v_options = array();
+
+ // ----- Look for variable options arguments
+ $v_size = func_num_args();
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
+
+ // ----- Look for arguments
+ if ($v_size > 0) {
+ // ----- Get the arguments
+ $v_arg_list = func_get_args();
+
+ // ----- Parse the options
+ $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
+ array (PCLZIP_OPT_BY_NAME => 'optional',
+ PCLZIP_OPT_BY_EREG => 'optional',
+ PCLZIP_OPT_BY_PREG => 'optional',
+ PCLZIP_OPT_BY_INDEX => 'optional' ));
+ if ($v_result != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return 0;
+ }
+ }
+
+ // ----- Magic quotes trick
+ $this->privDisableMagicQuotes();
+
+ // ----- Call the delete fct
+ $v_list = array();
+ if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) {
+ $this->privSwapBackMagicQuotes();
+ unset($v_list);
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
+ return(0);
+ }
+
+ // ----- Magic quotes trick
+ $this->privSwapBackMagicQuotes();
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_list);
+ return $v_list;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : deleteByIndex()
+ // Description :
+ // ***** Deprecated *****
+ // delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered.
+ // --------------------------------------------------------------------------------
+ function deleteByIndex($p_index)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::deleteByIndex", "index='$p_index'");
+
+ $p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index);
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
+ return $p_list;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : properties()
+ // Description :
+ // This method gives the properties of the archive.
+ // The properties are :
+ // nb : Number of files in the archive
+ // comment : Comment associated with the archive file
+ // status : not_exist, ok
+ // Parameters :
+ // None
+ // Return Values :
+ // 0 on failure,
+ // An array with the archive properties.
+ // --------------------------------------------------------------------------------
+ function properties()
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::properties", "");
+
+ // ----- Reset the error handler
+ $this->privErrorReset();
+
+ // ----- Magic quotes trick
+ $this->privDisableMagicQuotes();
+
+ // ----- Check archive
+ if (!$this->privCheckFormat()) {
+ $this->privSwapBackMagicQuotes();
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return(0);
+ }
+
+ // ----- Default properties
+ $v_prop = array();
+ $v_prop['comment'] = '';
+ $v_prop['nb'] = 0;
+ $v_prop['status'] = 'not_exist';
+
+ // ----- Look if file exists
+ if (@is_file($this->zipname))
+ {
+ // ----- Open the zip file
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+ if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
+ {
+ $this->privSwapBackMagicQuotes();
+
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), 0);
+ return 0;
+ }
+
+ // ----- Read the central directory informations
+ $v_central_dir = array();
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
+ {
+ $this->privSwapBackMagicQuotes();
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return 0;
+ }
+
+ // ----- Close the zip file
+ $this->privCloseFd();
+
+ // ----- Set the user attributes
+ $v_prop['comment'] = $v_central_dir['comment'];
+ $v_prop['nb'] = $v_central_dir['entries'];
+ $v_prop['status'] = 'ok';
+ }
+
+ // ----- Magic quotes trick
+ $this->privSwapBackMagicQuotes();
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_prop);
+ return $v_prop;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : duplicate()
+ // Description :
+ // This method creates an archive by copying the content of an other one. If
+ // the archive already exist, it is replaced by the new one without any warning.
+ // Parameters :
+ // $p_archive : The filename of a valid archive, or
+ // a valid PclZip object.
+ // Return Values :
+ // 1 on success.
+ // 0 or a negative value on error (error code).
+ // --------------------------------------------------------------------------------
+ function duplicate($p_archive)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::duplicate", "");
+ $v_result = 1;
+
+ // ----- Reset the error handler
+ $this->privErrorReset();
+
+ // ----- Look if the $p_archive is a PclZip object
+ if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip'))
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The parameter is valid PclZip object '".$p_archive->zipname."'");
+
+ // ----- Duplicate the archive
+ $v_result = $this->privDuplicate($p_archive->zipname);
+ }
+
+ // ----- Look if the $p_archive is a string (so a filename)
+ else if (is_string($p_archive))
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The parameter is a filename '$p_archive'");
+
+ // ----- Check that $p_archive is a valid zip file
+ // TBC : Should also check the archive format
+ if (!is_file($p_archive)) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'");
+ $v_result = PCLZIP_ERR_MISSING_FILE;
+ }
+ else {
+ // ----- Duplicate the archive
+ $v_result = $this->privDuplicate($p_archive);
+ }
+ }
+
+ // ----- Invalid variable
+ else
+ {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
+ $v_result = PCLZIP_ERR_INVALID_PARAMETER;
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : merge()
+ // Description :
+ // This method merge the $p_archive_to_add archive at the end of the current
+ // one ($this).
+ // If the archive ($this) does not exist, the merge becomes a duplicate.
+ // If the $p_archive_to_add archive does not exist, the merge is a success.
+ // Parameters :
+ // $p_archive_to_add : It can be directly the filename of a valid zip archive,
+ // or a PclZip object archive.
+ // Return Values :
+ // 1 on success,
+ // 0 or negative values on error (see below).
+ // --------------------------------------------------------------------------------
+ function merge($p_archive_to_add)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::merge", "");
+ $v_result = 1;
+
+ // ----- Reset the error handler
+ $this->privErrorReset();
+
+ // ----- Check archive
+ if (!$this->privCheckFormat()) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
+ return(0);
+ }
+
+ // ----- Look if the $p_archive_to_add is a PclZip object
+ if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip'))
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The parameter is valid PclZip object");
+
+ // ----- Merge the archive
+ $v_result = $this->privMerge($p_archive_to_add);
+ }
+
+ // ----- Look if the $p_archive_to_add is a string (so a filename)
+ else if (is_string($p_archive_to_add))
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The parameter is a filename");
+
+ // ----- Create a temporary archive
+ $v_object_archive = new PclZip($p_archive_to_add);
+
+ // ----- Merge the archive
+ $v_result = $this->privMerge($v_object_archive);
+ }
+
+ // ----- Invalid variable
+ else
+ {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
+ $v_result = PCLZIP_ERR_INVALID_PARAMETER;
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+
+
+ // --------------------------------------------------------------------------------
+ // Function : errorCode()
+ // Description :
+ // Parameters :
+ // --------------------------------------------------------------------------------
+ function errorCode()
+ {
+ if (PCLZIP_ERROR_EXTERNAL == 1) {
+ return(PclErrorCode());
+ }
+ else {
+ return($this->error_code);
+ }
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : errorName()
+ // Description :
+ // Parameters :
+ // --------------------------------------------------------------------------------
+ function errorName($p_with_code=false)
+ {
+ $v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR',
+ PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL',
+ PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL',
+ PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER',
+ PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE',
+ PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG',
+ PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP',
+ PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE',
+ PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL',
+ PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION',
+ PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT',
+ PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL',
+ PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL',
+ PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM',
+ PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP',
+ PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE',
+ PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE',
+ PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION',
+ PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION'
+ ,PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE'
+ ,PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION'
+ );
+
+ if (isset($v_name[$this->error_code])) {
+ $v_value = $v_name[$this->error_code];
+ }
+ else {
+ $v_value = 'NoName';
+ }
+
+ if ($p_with_code) {
+ return($v_value.' ('.$this->error_code.')');
+ }
+ else {
+ return($v_value);
+ }
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : errorInfo()
+ // Description :
+ // Parameters :
+ // --------------------------------------------------------------------------------
+ function errorInfo($p_full=false)
+ {
+ if (PCLZIP_ERROR_EXTERNAL == 1) {
+ return(PclErrorString());
+ }
+ else {
+ if ($p_full) {
+ return($this->errorName(true)." : ".$this->error_string);
+ }
+ else {
+ return($this->error_string." [code ".$this->error_code."]");
+ }
+ }
+ }
+ // --------------------------------------------------------------------------------
+
+
+// --------------------------------------------------------------------------------
+// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
+// ***** *****
+// ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY *****
+// --------------------------------------------------------------------------------
+
+
+
+ // --------------------------------------------------------------------------------
+ // Function : privCheckFormat()
+ // Description :
+ // This method check that the archive exists and is a valid zip archive.
+ // Several level of check exists. (futur)
+ // Parameters :
+ // $p_level : Level of check. Default 0.
+ // 0 : Check the first bytes (magic codes) (default value))
+ // 1 : 0 + Check the central directory (futur)
+ // 2 : 1 + Check each file header (futur)
+ // Return Values :
+ // true on success,
+ // false on error, the error code is set.
+ // --------------------------------------------------------------------------------
+ function privCheckFormat($p_level=0)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCheckFormat", "");
+ $v_result = true;
+
+ // ----- Reset the file system cache
+ clearstatcache();
+
+ // ----- Reset the error handler
+ $this->privErrorReset();
+
+ // ----- Look if the file exits
+ if (!is_file($this->zipname)) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, false, PclZip::errorInfo());
+ return(false);
+ }
+
+ // ----- Check that the file is readeable
+ if (!is_readable($this->zipname)) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, false, PclZip::errorInfo());
+ return(false);
+ }
+
+ // ----- Check the magic code
+ // TBC
+
+ // ----- Check the central header
+ // TBC
+
+ // ----- Check each file header
+ // TBC
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privParseOptions()
+ // Description :
+ // This internal methods reads the variable list of arguments ($p_options_list,
+ // $p_size) and generate an array with the options and values ($v_result_list).
+ // $v_requested_options contains the options that can be present and those that
+ // must be present.
+ // $v_requested_options is an array, with the option value as key, and 'optional',
+ // or 'mandatory' as value.
+ // Parameters :
+ // See above.
+ // Return Values :
+ // 1 on success.
+ // 0 on failure.
+ // --------------------------------------------------------------------------------
+ function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privParseOptions", "");
+ $v_result=1;
+
+ // ----- Read the options
+ $i=0;
+ while ($i<$p_size) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Looking for table index $i, option = '".PclZipUtilOptionText($p_options_list[$i])."(".$p_options_list[$i].")'");
+
+ // ----- Check if the option is supported
+ if (!isset($v_requested_options[$p_options_list[$i]])) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Look for next option
+ switch ($p_options_list[$i]) {
+ // ----- Look for options that request a path value
+ case PCLZIP_OPT_PATH :
+ case PCLZIP_OPT_REMOVE_PATH :
+ case PCLZIP_OPT_ADD_PATH :
+ // ----- Check the number of parameters
+ if (($i+1) >= $p_size) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Get the value
+ $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], false);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
+ $i++;
+ break;
+
+ case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION :
+ // ----- Check the number of parameters
+ if (($i+1) >= $p_size) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Get the value
+ if ( is_string($p_options_list[$i+1])
+ && ($p_options_list[$i+1] != '')) {
+ $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], false);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
+ $i++;
+ }
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." set with an empty value is ignored.");
+ }
+ break;
+
+ // ----- Look for options that request an array of string for value
+ case PCLZIP_OPT_BY_NAME :
+ // ----- Check the number of parameters
+ if (($i+1) >= $p_size) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Get the value
+ if (is_string($p_options_list[$i+1])) {
+ $v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1];
+ }
+ else if (is_array($p_options_list[$i+1])) {
+ $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
+ }
+ else {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
+ $i++;
+ break;
+
+ // ----- Look for options that request an EREG or PREG expression
+ case PCLZIP_OPT_BY_EREG :
+ case PCLZIP_OPT_BY_PREG :
+ //case PCLZIP_OPT_CRYPT :
+ // ----- Check the number of parameters
+ if (($i+1) >= $p_size) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Get the value
+ if (is_string($p_options_list[$i+1])) {
+ $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
+ }
+ else {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
+ $i++;
+ break;
+
+ // ----- Look for options that takes a string
+ case PCLZIP_OPT_COMMENT :
+ case PCLZIP_OPT_ADD_COMMENT :
+ case PCLZIP_OPT_PREPEND_COMMENT :
+ // ----- Check the number of parameters
+ if (($i+1) >= $p_size) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
+ "Missing parameter value for option '"
+ .PclZipUtilOptionText($p_options_list[$i])
+ ."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Get the value
+ if (is_string($p_options_list[$i+1])) {
+ $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
+ }
+ else {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
+ "Wrong parameter value for option '"
+ .PclZipUtilOptionText($p_options_list[$i])
+ ."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
+ $i++;
+ break;
+
+ // ----- Look for options that request an array of index
+ case PCLZIP_OPT_BY_INDEX :
+ // ----- Check the number of parameters
+ if (($i+1) >= $p_size) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Get the value
+ $v_work_list = array();
+ if (is_string($p_options_list[$i+1])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is a string '".$p_options_list[$i+1]."'");
+
+ // ----- Remove spaces
+ $p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', '');
+
+ // ----- Parse items
+ $v_work_list = explode(",", $p_options_list[$i+1]);
+ }
+ else if (is_integer($p_options_list[$i+1])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is an integer '".$p_options_list[$i+1]."'");
+ $v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1];
+ }
+ else if (is_array($p_options_list[$i+1])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is an array");
+ $v_work_list = $p_options_list[$i+1];
+ }
+ else {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Reduce the index list
+ // each index item in the list must be a couple with a start and
+ // an end value : [0,3], [5-5], [8-10], ...
+ // ----- Check the format of each item
+ $v_sort_flag=false;
+ $v_sort_value=0;
+ for ($j=0; $j<sizeof($v_work_list); $j++) {
+ // ----- Explode the item
+ $v_item_list = explode("-", $v_work_list[$j]);
+ $v_size_item_list = sizeof($v_item_list);
+
+ // ----- TBC : Here we might check that each item is a
+ // real integer ...
+
+ // ----- Look for single value
+ if ($v_size_item_list == 1) {
+ // ----- Set the option value
+ $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
+ $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[0];
+ }
+ elseif ($v_size_item_list == 2) {
+ // ----- Set the option value
+ $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
+ $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[1];
+ }
+ else {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Too many values in index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extracted index item = [".$v_result_list[$p_options_list[$i]][$j]['start'].",".$v_result_list[$p_options_list[$i]][$j]['end']."]");
+
+ // ----- Look for list sort
+ if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The list should be sorted ...");
+ $v_sort_flag=true;
+
+ // ----- TBC : An automatic sort should be writen ...
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Invalid order of index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ $v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start'];
+ }
+
+ // ----- Sort the items
+ if ($v_sort_flag) {
+ // TBC : To Be Completed
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "List sorting is not yet write ...");
+ }
+
+ // ----- Next option
+ $i++;
+ break;
+
+ // ----- Look for options that request no value
+ case PCLZIP_OPT_REMOVE_ALL_PATH :
+ case PCLZIP_OPT_EXTRACT_AS_STRING :
+ case PCLZIP_OPT_NO_COMPRESSION :
+ case PCLZIP_OPT_EXTRACT_IN_OUTPUT :
+ case PCLZIP_OPT_REPLACE_NEWER :
+ case PCLZIP_OPT_STOP_ON_ERROR :
+ $v_result_list[$p_options_list[$i]] = true;
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
+ break;
+
+ // ----- Look for options that request an octal value
+ case PCLZIP_OPT_SET_CHMOD :
+ // ----- Check the number of parameters
+ if (($i+1) >= $p_size) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Get the value
+ $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
+ $i++;
+ break;
+
+ // ----- Look for options that request a call-back
+ case PCLZIP_CB_PRE_EXTRACT :
+ case PCLZIP_CB_POST_EXTRACT :
+ case PCLZIP_CB_PRE_ADD :
+ case PCLZIP_CB_POST_ADD :
+ /* for futur use
+ case PCLZIP_CB_PRE_DELETE :
+ case PCLZIP_CB_POST_DELETE :
+ case PCLZIP_CB_PRE_LIST :
+ case PCLZIP_CB_POST_LIST :
+ */
+ // ----- Check the number of parameters
+ if (($i+1) >= $p_size) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Get the value
+ $v_function_name = $p_options_list[$i+1];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "call-back ".PclZipUtilOptionText($p_options_list[$i])." = '".$v_function_name."'");
+
+ // ----- Check that the value is a valid existing function
+ if (!function_exists($v_function_name)) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Set the attribute
+ $v_result_list[$p_options_list[$i]] = $v_function_name;
+ $i++;
+ break;
+
+ default :
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
+ "Unknown parameter '"
+ .$p_options_list[$i]."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Next options
+ $i++;
+ }
+
+ // ----- Look for mandatory options
+ if ($v_requested_options !== false) {
+ for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
+ // ----- Look for mandatory option
+ if ($v_requested_options[$key] == 'mandatory') {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Detect a mandatory option : ".PclZipUtilOptionText($key)."(".$key.")");
+ // ----- Look if present
+ if (!isset($v_result_list[$key])) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ }
+ }
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privFileDescrParseAtt()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // 1 on success.
+ // 0 on failure.
+ // --------------------------------------------------------------------------------
+ function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privFileDescrParseAtt", "");
+ $v_result=1;
+
+ // ----- For each file in the list check the attributes
+ foreach ($p_file_list as $v_key => $v_value) {
+
+ // ----- Check if the option is supported
+ if (!isset($v_requested_options[$v_key])) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Look for attribute
+ switch ($v_key) {
+ case PCLZIP_ATT_FILE_NAME :
+ if (!is_string($v_value)) {
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ $p_filedescr['filename'] = PclZipUtilPathReduction($v_value);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
+
+ if ($p_filedescr['filename'] == '') {
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".PclZipUtilOptionText($v_key)."'");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ break;
+
+ case PCLZIP_ATT_FILE_NEW_SHORT_NAME :
+ if (!is_string($v_value)) {
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ $p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
+
+ if ($p_filedescr['new_short_name'] == '') {
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '".PclZipUtilOptionText($v_key)."'");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ break;
+
+ case PCLZIP_ATT_FILE_NEW_FULL_NAME :
+ if (!is_string($v_value)) {
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ $p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
+
+ if ($p_filedescr['new_full_name'] == '') {
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '".PclZipUtilOptionText($v_key)."'");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ break;
+
+ default :
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
+ "Unknown parameter '".$v_key."'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Look for mandatory options
+ if ($v_requested_options !== false) {
+ for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
+ // ----- Look for mandatory option
+ if ($v_requested_options[$key] == 'mandatory') {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Detect a mandatory option : ".PclZipUtilOptionText($key)."(".$key.")");
+ // ----- Look if present
+ if (!isset($p_file_list[$key])) {
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ }
+ }
+ }
+
+ // end foreach
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privFileDescrExpand()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // 1 on success.
+ // 0 on failure.
+ // --------------------------------------------------------------------------------
+ function privFileDescrExpand(&$p_filedescr_list, &$p_options)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privFileDescrExpand", "");
+ $v_result=1;
+
+ // ----- Create a result list
+ $v_result_list = array();
+
+ // ----- Look each entry
+ for ($i=0; $i<sizeof($p_filedescr_list); $i++) {
+ // ----- Get filedescr
+ $v_descr = $p_filedescr_list[$i];
+
+ // ----- Reduce the filename
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filedescr before reduction :'".$v_descr['filename']."'");
+ $v_descr['filename'] = PclZipUtilTranslateWinPath($v_descr['filename']);
+ $v_descr['filename'] = PclZipUtilPathReduction($v_descr['filename']);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filedescr after reduction :'".$v_descr['filename']."'");
+
+ // ----- Get type of descr
+ if (!file_exists($v_descr['filename'])) {
+ // ----- Error log
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_descr['filename']."' does not exists");
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$v_descr['filename']."' does not exists");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ if (@is_file($v_descr['filename'])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "This is a file");
+ $v_descr['type'] = 'file';
+ }
+ else if (@is_dir($v_descr['filename'])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "This is a folder");
+ $v_descr['type'] = 'folder';
+ }
+ else if (@is_link($v_descr['filename'])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Unsupported file type : link");
+ // skip
+ continue;
+ }
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Unsupported file type : unknown type");
+ // skip
+ continue;
+ }
+
+ // ----- Calculate the stored filename
+ $this->privCalculateStoredFilename($v_descr, $p_options);
+
+ // ----- Add the descriptor in result list
+ $v_result_list[sizeof($v_result_list)] = $v_descr;
+
+ // ----- Look for folder
+ if ($v_descr['type'] == 'folder') {
+ // ----- List of items in folder
+ $v_dirlist_descr = array();
+ $v_dirlist_nb = 0;
+ if ($v_folder_handler = @opendir($v_descr['filename'])) {
+ while (($v_item_handler = @readdir($v_folder_handler)) !== false) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Looking for '".$v_item_handler."' in the directory");
+
+ // ----- Skip '.' and '..'
+ if (($v_item_handler == '.') || ($v_item_handler == '..')) {
+ continue;
+ }
+
+ // ----- Compose the full filename
+ $v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler;
+
+ // ----- Look for different stored filename
+ // Because the name of the folder was changed, the name of the
+ // files/sub-folders also change
+ if ($v_descr['stored_filename'] != $v_descr['filename']) {
+ $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler;
+ }
+
+ $v_dirlist_nb++;
+ }
+ }
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to open dir '".$v_descr['filename']."' in read mode. Skipped.");
+ // TBC : unable to open folder in read mode
+ }
+
+ // ----- Expand each element of the list
+ if ($v_dirlist_nb != 0) {
+ // ----- Expand
+ if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Concat the resulting list
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Merging result list (size '".sizeof($v_result_list)."') with dirlist (size '".sizeof($v_dirlist_descr)."')");
+ $v_result_list = array_merge($v_result_list, $v_dirlist_descr);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "merged result list is size '".sizeof($v_result_list)."'");
+ }
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Nothing in this folder to expand.");
+ }
+
+ // ----- Free local array
+ unset($v_dirlist_descr);
+ }
+ }
+
+ // ----- Get the result list
+ $p_filedescr_list = $v_result_list;
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privCreate()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privCreate($p_filedescr_list, &$p_result_list, &$p_options)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCreate", "list");
+ $v_result=1;
+ $v_list_detail = array();
+
+ // ----- Magic quotes trick
+ $this->privDisableMagicQuotes();
+
+ // ----- Open the file in write mode
+ if (($v_result = $this->privOpenFd('wb')) != 1)
+ {
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Add the list of files
+ $v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options);
+
+ // ----- Close
+ $this->privCloseFd();
+
+ // ----- Magic quotes trick
+ $this->privSwapBackMagicQuotes();
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privAdd()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privAdd($p_filedescr_list, &$p_result_list, &$p_options)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAdd", "list");
+ $v_result=1;
+ $v_list_detail = array();
+
+ // ----- Look if the archive exists or is empty
+ if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0))
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive does not exist, or is empty, create it.");
+
+ // ----- Do a create
+ $v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options);
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // ----- Magic quotes trick
+ $this->privDisableMagicQuotes();
+
+ // ----- Open the zip file
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+ if (($v_result=$this->privOpenFd('rb')) != 1)
+ {
+ // ----- Magic quotes trick
+ $this->privSwapBackMagicQuotes();
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Read the central directory informations
+ $v_central_dir = array();
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
+ {
+ $this->privCloseFd();
+ $this->privSwapBackMagicQuotes();
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Go to beginning of File
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
+ @rewind($this->zip_fd);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
+
+ // ----- Creates a temporay file
+ $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
+
+ // ----- Open the temporary file in write mode
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+ if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
+ {
+ $this->privCloseFd();
+ $this->privSwapBackMagicQuotes();
+
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Copy the files from the archive to the temporary file
+ // TBC : Here I should better append the file and go back to erase the central dir
+ $v_size = $v_central_dir['offset'];
+ while ($v_size != 0)
+ {
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+ $v_buffer = fread($this->zip_fd, $v_read_size);
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
+ $v_size -= $v_read_size;
+ }
+
+ // ----- Swap the file descriptor
+ // Here is a trick : I swap the temporary fd with the zip fd, in order to use
+ // the following methods on the temporary fil and not the real archive
+ $v_swap = $this->zip_fd;
+ $this->zip_fd = $v_zip_temp_fd;
+ $v_zip_temp_fd = $v_swap;
+
+ // ----- Add the files
+ $v_header_list = array();
+ if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
+ {
+ fclose($v_zip_temp_fd);
+ $this->privCloseFd();
+ @unlink($v_zip_temp_name);
+ $this->privSwapBackMagicQuotes();
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Store the offset of the central dir
+ $v_offset = @ftell($this->zip_fd);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset");
+
+ // ----- Copy the block of file headers from the old archive
+ $v_size = $v_central_dir['size'];
+ while ($v_size != 0)
+ {
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+ $v_buffer = @fread($v_zip_temp_fd, $v_read_size);
+ @fwrite($this->zip_fd, $v_buffer, $v_read_size);
+ $v_size -= $v_read_size;
+ }
+
+ // ----- Create the Central Dir files header
+ for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++)
+ {
+ // ----- Create the file header
+ if ($v_header_list[$i]['status'] == 'ok') {
+ if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
+ fclose($v_zip_temp_fd);
+ $this->privCloseFd();
+ @unlink($v_zip_temp_name);
+ $this->privSwapBackMagicQuotes();
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ $v_count++;
+ }
+
+ // ----- Transform the header to a 'usable' info
+ $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
+ }
+
+ // ----- Zip file comment
+ $v_comment = $v_central_dir['comment'];
+ if (isset($p_options[PCLZIP_OPT_COMMENT])) {
+ $v_comment = $p_options[PCLZIP_OPT_COMMENT];
+ }
+ if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) {
+ $v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT];
+ }
+ if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) {
+ $v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment;
+ }
+
+ // ----- Calculate the size of the central header
+ $v_size = @ftell($this->zip_fd)-$v_offset;
+
+ // ----- Create the central dir footer
+ if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1)
+ {
+ // ----- Reset the file list
+ unset($v_header_list);
+ $this->privSwapBackMagicQuotes();
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Swap back the file descriptor
+ $v_swap = $this->zip_fd;
+ $this->zip_fd = $v_zip_temp_fd;
+ $v_zip_temp_fd = $v_swap;
+
+ // ----- Close
+ $this->privCloseFd();
+
+ // ----- Close the temporary file
+ @fclose($v_zip_temp_fd);
+
+ // ----- Magic quotes trick
+ $this->privSwapBackMagicQuotes();
+
+ // ----- Delete the zip file
+ // TBC : I should test the result ...
+ @unlink($this->zipname);
+
+ // ----- Rename the temporary file
+ // TBC : I should test the result ...
+ //@rename($v_zip_temp_name, $this->zipname);
+ PclZipUtilRename($v_zip_temp_name, $this->zipname);
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privOpenFd()
+ // Description :
+ // Parameters :
+ // --------------------------------------------------------------------------------
+ function privOpenFd($p_mode)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privOpenFd", 'mode='.$p_mode);
+ $v_result=1;
+
+ // ----- Look if already open
+ if ($this->zip_fd != 0)
+ {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Open the zip file
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Open file in '.$p_mode.' mode');
+ if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0)
+ {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privCloseFd()
+ // Description :
+ // Parameters :
+ // --------------------------------------------------------------------------------
+ function privCloseFd()
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCloseFd", "");
+ $v_result=1;
+
+ if ($this->zip_fd != 0)
+ @fclose($this->zip_fd);
+ $this->zip_fd = 0;
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privAddList()
+ // Description :
+ // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
+ // different from the real path of the file. This is usefull if you want to have PclTar
+ // running in any directory, and memorize relative path from an other directory.
+ // Parameters :
+ // $p_list : An array containing the file or directory names to add in the tar
+ // $p_result_list : list of added files with their properties (specially the status field)
+ // $p_add_dir : Path to add in the filename path archived
+ // $p_remove_dir : Path to remove in the filename path archived
+ // Return Values :
+ // --------------------------------------------------------------------------------
+// function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
+ function privAddList($p_filedescr_list, &$p_result_list, &$p_options)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddList", "list");
+ $v_result=1;
+
+ // ----- Add the files
+ $v_header_list = array();
+ if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
+ {
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Store the offset of the central dir
+ $v_offset = @ftell($this->zip_fd);
+
+ // ----- Create the Central Dir files header
+ for ($i=0,$v_count=0; $i<sizeof($v_header_list); $i++)
+ {
+ // ----- Create the file header
+ if ($v_header_list[$i]['status'] == 'ok') {
+ if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ $v_count++;
+ }
+
+ // ----- Transform the header to a 'usable' info
+ $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
+ }
+
+ // ----- Zip file comment
+ $v_comment = '';
+ if (isset($p_options[PCLZIP_OPT_COMMENT])) {
+ $v_comment = $p_options[PCLZIP_OPT_COMMENT];
+ }
+
+ // ----- Calculate the size of the central header
+ $v_size = @ftell($this->zip_fd)-$v_offset;
+
+ // ----- Create the central dir footer
+ if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1)
+ {
+ // ----- Reset the file list
+ unset($v_header_list);
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privAddFileList()
+ // Description :
+ // Parameters :
+ // $p_filedescr_list : An array containing the file description
+ // or directory names to add in the zip
+ // $p_result_list : list of added files with their properties (specially the status field)
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFileList", "filedescr_list");
+ $v_result=1;
+ $v_header = array();
+
+ // ----- Recuperate the current number of elt in list
+ $v_nb = sizeof($p_result_list);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Before add, list have ".$v_nb." elements");
+
+ // ----- Loop on the files
+ for ($j=0; ($j<sizeof($p_filedescr_list)) && ($v_result==1); $j++) {
+ // ----- Format the filename
+ $p_filedescr_list[$j]['filename']
+ = PclZipUtilTranslateWinPath($p_filedescr_list[$j]['filename'], false);
+
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Looking for file '".$p_filedescr_list[$j]['filename']."'");
+
+ // ----- Skip empty file names
+ // TBC : Can this be possible ? not checked in DescrParseAtt ?
+ if ($p_filedescr_list[$j]['filename'] == "") {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Skip empty filename");
+ continue;
+ }
+
+ // ----- Check the filename
+ if (!file_exists($p_filedescr_list[$j]['filename'])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$p_filedescr_list[$j]['filename']."' does not exists");
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$p_filedescr_list[$j]['filename']."' does not exists");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Look if it is a file or a dir with no all path remove option
+ if ( (is_file($p_filedescr_list[$j]['filename']))
+ || ( is_dir($p_filedescr_list[$j]['filename'])
+ && ( !isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])
+ || !$p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))) {
+
+ // ----- Add the file
+ $v_result = $this->privAddFile($p_filedescr_list[$j], $v_header,
+ $p_options);
+ if ($v_result != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Store the file infos
+ $p_result_list[$v_nb++] = $v_header;
+ }
+ }
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "After add, list have ".$v_nb." elements");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privAddFile()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privAddFile($p_filedescr, &$p_header, &$p_options)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFile", "filename='".$p_filedescr['filename']."'");
+ $v_result=1;
+
+ // ----- Working variable
+ $p_filename = $p_filedescr['filename'];
+
+ // TBC : Already done in the fileAtt check ... ?
+ if ($p_filename == "") {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Look for a stored different filename
+ if (isset($p_filedescr['stored_filename'])) {
+ $v_stored_filename = $p_filedescr['stored_filename'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, 'Stored filename is NOT the same "'.$v_stored_filename.'"');
+ }
+ else {
+ $v_stored_filename = $p_filedescr['stored_filename'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, 'Stored filename is the same');
+ }
+
+ // ----- Set the file properties
+ clearstatcache();
+ $p_header['version'] = 20;
+ $p_header['version_extracted'] = 10;
+ $p_header['flag'] = 0;
+ $p_header['compression'] = 0;
+ $p_header['mtime'] = filemtime($p_filename);
+ $p_header['crc'] = 0;
+ $p_header['compressed_size'] = 0;
+ $p_header['size'] = filesize($p_filename);
+ $p_header['filename_len'] = strlen($p_filename);
+ $p_header['extra_len'] = 0;
+ $p_header['comment_len'] = 0;
+ $p_header['disk'] = 0;
+ $p_header['internal'] = 0;
+// $p_header['external'] = (is_file($p_filename)?0xFE49FFE0:0x41FF0010);
+ $p_header['external'] = (is_file($p_filename)?0x00000000:0x00000010);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header external extension '".sprintf("0x%X",$p_header['external'])."'");
+ $p_header['offset'] = 0;
+ $p_header['filename'] = $p_filename;
+ $p_header['stored_filename'] = $v_stored_filename;
+ $p_header['extra'] = '';
+ $p_header['comment'] = '';
+ $p_header['status'] = 'ok';
+ $p_header['index'] = -1;
+
+ // ----- Look for pre-add callback
+ if (isset($p_options[PCLZIP_CB_PRE_ADD])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_ADD]."()') is defined for the extraction");
+
+ // ----- Generate a local information
+ $v_local_header = array();
+ $this->privConvertHeader2FileInfo($p_header, $v_local_header);
+
+ // ----- Call the callback
+ // Here I do not use call_user_func() because I need to send a reference to the
+ // header.
+ eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);');
+ if ($v_result == 0) {
+ // ----- Change the file status
+ $p_header['status'] = "skipped";
+ $v_result = 1;
+ }
+
+ // ----- Update the informations
+ // Only some fields can be modified
+ if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
+ $p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New stored filename is '".$p_header['stored_filename']."'");
+ }
+ }
+
+ // ----- Look for empty stored filename
+ if ($p_header['stored_filename'] == "") {
+ $p_header['status'] = "filtered";
+ }
+
+ // ----- Check the path length
+ if (strlen($p_header['stored_filename']) > 0xFF) {
+ $p_header['status'] = 'filename_too_long';
+ }
+
+ // ----- Look if no error, or file not skipped
+ if ($p_header['status'] == 'ok') {
+
+ // ----- Look for a file
+ if (is_file($p_filename))
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "'".$p_filename."' is a file");
+ // ----- Open the source file
+ if (($v_file = @fopen($p_filename, "rb")) == 0) {
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will not be compressed");
+ // ----- Read the file content
+ $v_content_compressed = @fread($v_file, $p_header['size']);
+
+ // ----- Calculate the CRC
+ $p_header['crc'] = @crc32($v_content_compressed);
+
+ // ----- Set header parameters
+ $p_header['compressed_size'] = $p_header['size'];
+ $p_header['compression'] = 0;
+ }
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will be compressed");
+ // ----- Read the file content
+ $v_content = @fread($v_file, $p_header['size']);
+
+ // ----- Calculate the CRC
+ $p_header['crc'] = @crc32($v_content);
+
+ // ----- Compress the file
+ $v_content_compressed = @gzdeflate($v_content);
+
+ // ----- Set header parameters
+ $p_header['compressed_size'] = strlen($v_content_compressed);
+ $p_header['compression'] = 8;
+ }
+
+ // ----- Look for encryption
+ /*
+ if ((isset($p_options[PCLZIP_OPT_CRYPT]))
+ && ($p_options[PCLZIP_OPT_CRYPT] != "")) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File need to be crypted ....");
+
+ // Should be a random header
+ $v_header = 'xxxxxxxxxxxx';
+ $v_content_compressed = PclZipUtilZipEncrypt($v_content_compressed,
+ $p_header['compressed_size'],
+ $v_header,
+ $p_header['crc'],
+ "test");
+
+ $p_header['compressed_size'] += 12;
+ $p_header['flag'] = 1;
+
+ // ----- Add the header to the data
+ $v_content_compressed = $v_header.$v_content_compressed;
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Size after header : ".strlen($v_content_compressed)."");
+ }
+ */
+
+ // ----- Call the header generation
+ if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
+ @fclose($v_file);
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Write the compressed (or not) content
+ @fwrite($this->zip_fd,
+ $v_content_compressed, $p_header['compressed_size']);
+
+ // ----- Close the file
+ @fclose($v_file);
+ }
+
+ // ----- Look for a directory
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "'".$p_filename."' is a folder");
+ // ----- Look for directory last '/'
+ if (@substr($p_header['stored_filename'], -1) != '/') {
+ $p_header['stored_filename'] .= '/';
+ }
+
+ // ----- Set the file properties
+ $p_header['size'] = 0;
+ //$p_header['external'] = 0x41FF0010; // Value for a folder : to be checked
+ $p_header['external'] = 0x00000010; // Value for a folder : to be checked
+
+ // ----- Call the header generation
+ if (($v_result = $this->privWriteFileHeader($p_header)) != 1)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ }
+ }
+
+ // ----- Look for post-add callback
+ if (isset($p_options[PCLZIP_CB_POST_ADD])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_ADD]."()') is defined for the extraction");
+
+ // ----- Generate a local information
+ $v_local_header = array();
+ $this->privConvertHeader2FileInfo($p_header, $v_local_header);
+
+ // ----- Call the callback
+ // Here I do not use call_user_func() because I need to send a reference to the
+ // header.
+ eval('$v_result = '.$p_options[PCLZIP_CB_POST_ADD].'(PCLZIP_CB_POST_ADD, $v_local_header);');
+ if ($v_result == 0) {
+ // ----- Ignored
+ $v_result = 1;
+ }
+
+ // ----- Update the informations
+ // Nothing can be modified
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privCalculateStoredFilename()
+ // Description :
+ // Based on file descriptor properties and global options, this method
+ // calculate the filename that will be stored in the archive.
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privCalculateStoredFilename(&$p_filedescr, &$p_options)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCalculateStoredFilename", "filename='".$p_filedescr['filename']."'");
+ $v_result=1;
+
+ // ----- Working variables
+ $p_filename = $p_filedescr['filename'];
+ if (isset($p_options[PCLZIP_OPT_ADD_PATH])) {
+ $p_add_dir = $p_options[PCLZIP_OPT_ADD_PATH];
+ }
+ else {
+ $p_add_dir = '';
+ }
+ if (isset($p_options[PCLZIP_OPT_REMOVE_PATH])) {
+ $p_remove_dir = $p_options[PCLZIP_OPT_REMOVE_PATH];
+ }
+ else {
+ $p_remove_dir = '';
+ }
+ if (isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
+ $p_remove_all_dir = $p_options[PCLZIP_OPT_REMOVE_ALL_PATH];
+ }
+ else {
+ $p_remove_all_dir = 0;
+ }
+
+ // ----- Look for full name change
+ if (isset($p_filedescr['new_full_name'])) {
+ $v_stored_filename = $p_filedescr['new_full_name'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Changing full name of '".$p_filename."' for '".$v_stored_filename."'");
+ }
+
+ // ----- Look for path and/or short name change
+ else {
+
+ // ----- Look for short name change
+ if (isset($p_filedescr['new_short_name'])) {
+ $v_path_info = pathinfo($p_filename);
+ $v_dir = '';
+ if ($v_path_info['dirname'] != '') {
+ $v_dir = $v_path_info['dirname'].'/';
+ }
+ $v_stored_filename = $v_dir.$p_filedescr['new_short_name'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Changing short name of '".$p_filename."' for '".$v_stored_filename."'");
+ }
+ else {
+ // ----- Calculate the stored filename
+ $v_stored_filename = $p_filename;
+ }
+
+ // ----- Look for all path to remove
+ if ($p_remove_all_dir) {
+ $v_stored_filename = basename($p_filename);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Remove all path selected change '".$p_filename."' for '".$v_stored_filename."'");
+ }
+ // ----- Look for partial path remove
+ else if ($p_remove_dir != "") {
+ if (substr($p_remove_dir, -1) != '/')
+ $p_remove_dir .= "/";
+
+ if ( (substr($p_filename, 0, 2) == "./")
+ || (substr($p_remove_dir, 0, 2) == "./")) {
+
+ if ( (substr($p_filename, 0, 2) == "./")
+ && (substr($p_remove_dir, 0, 2) != "./")) {
+ $p_remove_dir = "./".$p_remove_dir;
+ }
+ if ( (substr($p_filename, 0, 2) != "./")
+ && (substr($p_remove_dir, 0, 2) == "./")) {
+ $p_remove_dir = substr($p_remove_dir, 2);
+ }
+ }
+
+ $v_compare = PclZipUtilPathInclusion($p_remove_dir,
+ $v_stored_filename);
+ if ($v_compare > 0) {
+ if ($v_compare == 2) {
+ $v_stored_filename = "";
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Path to remove is the current folder");
+ }
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Remove path '$p_remove_dir' in file '$v_stored_filename'");
+ $v_stored_filename = substr($v_stored_filename,
+ strlen($p_remove_dir));
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Result is '$v_stored_filename'");
+ }
+ }
+ }
+ // ----- Look for path to add
+ if ($p_add_dir != "") {
+ if (substr($p_add_dir, -1) == "/")
+ $v_stored_filename = $p_add_dir.$v_stored_filename;
+ else
+ $v_stored_filename = $p_add_dir."/".$v_stored_filename;
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Add path '$p_add_dir' in file '$p_filename' = '$v_stored_filename'");
+ }
+ }
+
+ // ----- Filename (reduce the path of stored name)
+ $v_stored_filename = PclZipUtilPathReduction($v_stored_filename);
+ $p_filedescr['stored_filename'] = $v_stored_filename;
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Stored filename will be '".$p_filedescr['stored_filename']."', strlen ".strlen($p_filedescr['stored_filename']));
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privWriteFileHeader()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privWriteFileHeader(&$p_header)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteFileHeader", 'file="'.$p_header['filename'].'", stored as "'.$p_header['stored_filename'].'"');
+ $v_result=1;
+
+ // ----- Store the offset position of the file
+ $p_header['offset'] = ftell($this->zip_fd);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, 'File offset of the header :'.$p_header['offset']);
+
+ // ----- Transform UNIX mtime to DOS format mdate/mtime
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
+ $v_date = getdate($p_header['mtime']);
+ $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
+ $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
+
+ // ----- Packed data
+ $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50,
+ $p_header['version_extracted'], $p_header['flag'],
+ $p_header['compression'], $v_mtime, $v_mdate,
+ $p_header['crc'], $p_header['compressed_size'],
+ $p_header['size'],
+ strlen($p_header['stored_filename']),
+ $p_header['extra_len']);
+
+ // ----- Write the first 148 bytes of the header in the archive
+ fputs($this->zip_fd, $v_binary_data, 30);
+
+ // ----- Write the variable fields
+ if (strlen($p_header['stored_filename']) != 0)
+ {
+ fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
+ }
+ if ($p_header['extra_len'] != 0)
+ {
+ fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privWriteCentralFileHeader()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privWriteCentralFileHeader(&$p_header)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteCentralFileHeader", 'file="'.$p_header['filename'].'", stored as "'.$p_header['stored_filename'].'"');
+ $v_result=1;
+
+ // TBC
+ //for(reset($p_header); $key = key($p_header); next($p_header)) {
+ // //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "header[$key] = ".$p_header[$key]);
+ //}
+
+ // ----- Transform UNIX mtime to DOS format mdate/mtime
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
+ $v_date = getdate($p_header['mtime']);
+ $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
+ $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
+
+ // ----- Packed data
+ $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50,
+ $p_header['version'], $p_header['version_extracted'],
+ $p_header['flag'], $p_header['compression'],
+ $v_mtime, $v_mdate, $p_header['crc'],
+ $p_header['compressed_size'], $p_header['size'],
+ strlen($p_header['stored_filename']),
+ $p_header['extra_len'], $p_header['comment_len'],
+ $p_header['disk'], $p_header['internal'],
+ $p_header['external'], $p_header['offset']);
+
+ // ----- Write the 42 bytes of the header in the zip file
+ fputs($this->zip_fd, $v_binary_data, 46);
+
+ // ----- Write the variable fields
+ if (strlen($p_header['stored_filename']) != 0)
+ {
+ fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
+ }
+ if ($p_header['extra_len'] != 0)
+ {
+ fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
+ }
+ if ($p_header['comment_len'] != 0)
+ {
+ fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']);
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privWriteCentralHeader()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteCentralHeader", 'nb_entries='.$p_nb_entries.', size='.$p_size.', offset='.$p_offset.', comment="'.$p_comment.'"');
+ $v_result=1;
+
+ // ----- Packed data
+ $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries,
+ $p_nb_entries, $p_size,
+ $p_offset, strlen($p_comment));
+
+ // ----- Write the 22 bytes of the header in the zip file
+ fputs($this->zip_fd, $v_binary_data, 22);
+
+ // ----- Write the variable fields
+ if (strlen($p_comment) != 0)
+ {
+ fputs($this->zip_fd, $p_comment, strlen($p_comment));
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privList()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privList(&$p_list)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privList", "list");
+ $v_result=1;
+
+ // ----- Magic quotes trick
+ $this->privDisableMagicQuotes();
+
+ // ----- Open the zip file
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+ if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
+ {
+ // ----- Magic quotes trick
+ $this->privSwapBackMagicQuotes();
+
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Read the central directory informations
+ $v_central_dir = array();
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
+ {
+ $this->privSwapBackMagicQuotes();
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Go to beginning of Central Dir
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Offset : ".$v_central_dir['offset']."'");
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
+ @rewind($this->zip_fd);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
+ if (@fseek($this->zip_fd, $v_central_dir['offset']))
+ {
+ $this->privSwapBackMagicQuotes();
+
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
+
+ // ----- Read each entry
+ for ($i=0; $i<$v_central_dir['entries']; $i++)
+ {
+ // ----- Read the file header
+ if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
+ {
+ $this->privSwapBackMagicQuotes();
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ $v_header['index'] = $i;
+
+ // ----- Get the only interesting attributes
+ $this->privConvertHeader2FileInfo($v_header, $p_list[$i]);
+ unset($v_header);
+ }
+
+ // ----- Close the zip file
+ $this->privCloseFd();
+
+ // ----- Magic quotes trick
+ $this->privSwapBackMagicQuotes();
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privConvertHeader2FileInfo()
+ // Description :
+ // This function takes the file informations from the central directory
+ // entries and extract the interesting parameters that will be given back.
+ // The resulting file infos are set in the array $p_info
+ // $p_info['filename'] : Filename with full path. Given by user (add),
+ // extracted in the filesystem (extract).
+ // $p_info['stored_filename'] : Stored filename in the archive.
+ // $p_info['size'] = Size of the file.
+ // $p_info['compressed_size'] = Compressed size of the file.
+ // $p_info['mtime'] = Last modification date of the file.
+ // $p_info['comment'] = Comment associated with the file.
+ // $p_info['folder'] = true/false : indicates if the entry is a folder or not.
+ // $p_info['status'] = status of the action on the file.
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privConvertHeader2FileInfo($p_header, &$p_info)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privConvertHeader2FileInfo", "Filename='".$p_header['filename']."'");
+ $v_result=1;
+
+ // ----- Get the interesting attributes
+ $p_info['filename'] = $p_header['filename'];
+ $p_info['stored_filename'] = $p_header['stored_filename'];
+ $p_info['size'] = $p_header['size'];
+ $p_info['compressed_size'] = $p_header['compressed_size'];
+ $p_info['mtime'] = $p_header['mtime'];
+ $p_info['comment'] = $p_header['comment'];
+ $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010);
+ $p_info['index'] = $p_header['index'];
+ $p_info['status'] = $p_header['status'];
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privExtractByRule()
+ // Description :
+ // Extract a file or directory depending of rules (by index, by name, ...)
+ // Parameters :
+ // $p_file_list : An array where will be placed the properties of each
+ // extracted file
+ // $p_path : Path to add while writing the extracted files
+ // $p_remove_path : Path to remove (from the file memorized path) while writing the
+ // extracted files. If the path does not match the file path,
+ // the file is extracted with its memorized path.
+ // $p_remove_path does not apply to 'list' mode.
+ // $p_path and $p_remove_path are commulative.
+ // Return Values :
+ // 1 on success,0 or less on error (see error code list)
+ // --------------------------------------------------------------------------------
+ function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privExtractByRule", "path='$p_path', remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'");
+ $v_result=1;
+
+ // ----- Magic quotes trick
+ $this->privDisableMagicQuotes();
+
+ // ----- Check the path
+ if ( ($p_path == "")
+ || ( (substr($p_path, 0, 1) != "/")
+ && (substr($p_path, 0, 3) != "../")
+ && (substr($p_path,1,2)!=":/")))
+ $p_path = "./".$p_path;
+
+ // ----- Reduce the path last (and duplicated) '/'
+ if (($p_path != "./") && ($p_path != "/"))
+ {
+ // ----- Look for the path end '/'
+ while (substr($p_path, -1) == "/")
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Destination path [$p_path] ends by '/'");
+ $p_path = substr($p_path, 0, strlen($p_path)-1);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Modified to [$p_path]");
+ }
+ }
+
+ // ----- Look for path to remove format (should end by /)
+ if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/'))
+ {
+ $p_remove_path .= '/';
+ }
+ $p_remove_path_size = strlen($p_remove_path);
+
+ // ----- Open the zip file
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+ if (($v_result = $this->privOpenFd('rb')) != 1)
+ {
+ $this->privSwapBackMagicQuotes();
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Read the central directory informations
+ $v_central_dir = array();
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
+ {
+ // ----- Close the zip file
+ $this->privCloseFd();
+ $this->privSwapBackMagicQuotes();
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Start at beginning of Central Dir
+ $v_pos_entry = $v_central_dir['offset'];
+
+ // ----- Read each entry
+ $j_start = 0;
+ for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file header entry : '$i'");
+
+ // ----- Read next Central dir entry
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Position before rewind : ".ftell($this->zip_fd)."'");
+ @rewind($this->zip_fd);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Position after rewind : ".ftell($this->zip_fd)."'");
+ if (@fseek($this->zip_fd, $v_pos_entry))
+ {
+ // ----- Close the zip file
+ $this->privCloseFd();
+ $this->privSwapBackMagicQuotes();
+
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after fseek : ".ftell($this->zip_fd)."'");
+
+ // ----- Read the file header
+ $v_header = array();
+ if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
+ {
+ // ----- Close the zip file
+ $this->privCloseFd();
+ $this->privSwapBackMagicQuotes();
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Store the index
+ $v_header['index'] = $i;
+
+ // ----- Store the file position
+ $v_pos_entry = ftell($this->zip_fd);
+
+ // ----- Look for the specific extract rules
+ $v_extract = false;
+
+ // ----- Look for extract by name rule
+ if ( (isset($p_options[PCLZIP_OPT_BY_NAME]))
+ && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByName'");
+
+ // ----- Look if the filename is in the list
+ for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_extract); $j++) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Compare with file '".$p_options[PCLZIP_OPT_BY_NAME][$j]."'");
+
+ // ----- Look for a directory
+ if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The searched item is a directory");
+
+ // ----- Look if the directory is in the filename path
+ if ( (strlen($v_header['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
+ && (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The directory is in the file path");
+ $v_extract = true;
+ }
+ }
+ // ----- Look for a filename
+ elseif ($v_header['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The file is the right one.");
+ $v_extract = true;
+ }
+ }
+ }
+
+ // ----- Look for extract by ereg rule
+ else if ( (isset($p_options[PCLZIP_OPT_BY_EREG]))
+ && ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract by ereg '".$p_options[PCLZIP_OPT_BY_EREG]."'");
+
+ if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
+ $v_extract = true;
+ }
+ }
+
+ // ----- Look for extract by preg rule
+ else if ( (isset($p_options[PCLZIP_OPT_BY_PREG]))
+ && ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByEreg'");
+
+ if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
+ $v_extract = true;
+ }
+ }
+
+ // ----- Look for extract by index rule
+ else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX]))
+ && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByIndex'");
+
+ // ----- Look if the index is in the list
+ for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_extract); $j++) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Look if index '$i' is in [".$p_options[PCLZIP_OPT_BY_INDEX][$j]['start'].",".$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']."]");
+
+ if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as part of an index range");
+ $v_extract = true;
+ }
+ if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Do not look this index range for next loop");
+ $j_start = $j+1;
+ }
+
+ if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Index range is greater than index, stop loop");
+ break;
+ }
+ }
+ }
+
+ // ----- Look for no rule, which means extract all the archive
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with no rule (extract all)");
+ $v_extract = true;
+ }
+
+ // ----- Check compression method
+ if ( ($v_extract)
+ && ( ($v_header['compression'] != 8)
+ && ($v_header['compression'] != 0))) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unsupported compression method (".$v_header['compression'].")");
+ $v_header['status'] = 'unsupported_compression';
+
+ // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
+ if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
+ && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
+
+ $this->privSwapBackMagicQuotes();
+
+ PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION,
+ "Filename '".$v_header['stored_filename']."' is "
+ ."compressed by an unsupported compression "
+ ."method (".$v_header['compression'].") ");
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ }
+
+ // ----- Check encrypted files
+ if (($v_extract) && (($v_header['flag'] & 1) == 1)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unsupported file encryption");
+ $v_header['status'] = 'unsupported_encryption';
+
+ // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
+ if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
+ && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
+
+ $this->privSwapBackMagicQuotes();
+
+ PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION,
+ "Unsupported encryption for "
+ ." filename '".$v_header['stored_filename']
+ ."'");
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ }
+
+ // ----- Look for real extraction
+ if (($v_extract) && ($v_header['status'] != 'ok')) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "No need for extract");
+ $v_result = $this->privConvertHeader2FileInfo($v_header,
+ $p_file_list[$v_nb_extracted++]);
+ if ($v_result != 1) {
+ $this->privCloseFd();
+ $this->privSwapBackMagicQuotes();
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ $v_extract = false;
+ }
+
+ // ----- Look for real extraction
+ if ($v_extract)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file '".$v_header['filename']."', index '$i'");
+
+ // ----- Go to the file position
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
+ @rewind($this->zip_fd);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
+ if (@fseek($this->zip_fd, $v_header['offset']))
+ {
+ // ----- Close the zip file
+ $this->privCloseFd();
+
+ $this->privSwapBackMagicQuotes();
+
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
+
+ // ----- Look for extraction as string
+ if ($p_options[PCLZIP_OPT_EXTRACT_AS_STRING]) {
+
+ // ----- Extracting the file
+ $v_result1 = $this->privExtractFileAsString($v_header, $v_string);
+ if ($v_result1 < 1) {
+ $this->privCloseFd();
+ $this->privSwapBackMagicQuotes();
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
+ return $v_result1;
+ }
+
+ // ----- Get the only interesting attributes
+ if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1)
+ {
+ // ----- Close the zip file
+ $this->privCloseFd();
+ $this->privSwapBackMagicQuotes();
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Set the file content
+ $p_file_list[$v_nb_extracted]['content'] = $v_string;
+
+ // ----- Next extracted file
+ $v_nb_extracted++;
+
+ // ----- Look for user callback abort
+ if ($v_result1 == 2) {
+ break;
+ }
+ }
+ // ----- Look for extraction in standard output
+ elseif ( (isset($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT]))
+ && ($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) {
+ // ----- Extracting the file in standard output
+ $v_result1 = $this->privExtractFileInOutput($v_header, $p_options);
+ if ($v_result1 < 1) {
+ $this->privCloseFd();
+ $this->privSwapBackMagicQuotes();
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
+ return $v_result1;
+ }
+
+ // ----- Get the only interesting attributes
+ if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) {
+ $this->privCloseFd();
+ $this->privSwapBackMagicQuotes();
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Look for user callback abort
+ if ($v_result1 == 2) {
+ break;
+ }
+ }
+ // ----- Look for normal extraction
+ else {
+ // ----- Extracting the file
+ $v_result1 = $this->privExtractFile($v_header,
+ $p_path, $p_remove_path,
+ $p_remove_all_path,
+ $p_options);
+ if ($v_result1 < 1) {
+ $this->privCloseFd();
+ $this->privSwapBackMagicQuotes();
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
+ return $v_result1;
+ }
+
+ // ----- Get the only interesting attributes
+ if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1)
+ {
+ // ----- Close the zip file
+ $this->privCloseFd();
+ $this->privSwapBackMagicQuotes();
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Look for user callback abort
+ if ($v_result1 == 2) {
+ break;
+ }
+ }
+ }
+ }
+
+ // ----- Close the zip file
+ $this->privCloseFd();
+ $this->privSwapBackMagicQuotes();
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privExtractFile()
+ // Description :
+ // Parameters :
+ // Return Values :
+ //
+ // 1 : ... ?
+ // PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback
+ // --------------------------------------------------------------------------------
+ function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFile', "path='$p_path', remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'");
+ $v_result=1;
+
+ // ----- Read the file header
+ if (($v_result = $this->privReadFileHeader($v_header)) != 1)
+ {
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'");
+
+ // ----- Check that the file header is coherent with $p_entry info
+ if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
+ // TBC
+ }
+
+ // ----- Look for all path to remove
+ if ($p_remove_all_path == true) {
+ // ----- Look for folder entry that not need to be extracted
+ if (($p_entry['external']&0x00000010)==0x00000010) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The entry is a folder : need to be filtered");
+
+ $p_entry['status'] = "filtered";
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "All path is removed");
+ // ----- Get the basename of the path
+ $p_entry['filename'] = basename($p_entry['filename']);
+ }
+
+ // ----- Look for path to remove
+ else if ($p_remove_path != "")
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Look for some path to remove");
+ if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The folder is the same as the removed path '".$p_entry['filename']."'");
+
+ // ----- Change the file status
+ $p_entry['status'] = "filtered";
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ $p_remove_path_size = strlen($p_remove_path);
+ if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found path '$p_remove_path' to remove in file '".$p_entry['filename']."'");
+
+ // ----- Remove the path
+ $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
+
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Resulting file is '".$p_entry['filename']."'");
+ }
+ }
+
+ // ----- Add the path
+ if ($p_path != '') {
+ $p_entry['filename'] = $p_path."/".$p_entry['filename'];
+ }
+
+ // ----- Check a base_dir_restriction
+ if (isset($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Check the extract directory restriction");
+ $v_inclusion
+ = PclZipUtilPathInclusion($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION],
+ $p_entry['filename']);
+ if ($v_inclusion == 0) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_EXTRACT_DIR_RESTRICTION is selected, file is outside restriction");
+
+ PclZip::privErrorLog(PCLZIP_ERR_DIRECTORY_RESTRICTION,
+ "Filename '".$p_entry['filename']."' is "
+ ."outside PCLZIP_OPT_EXTRACT_DIR_RESTRICTION");
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ }
+
+ // ----- Look for pre-extract callback
+ if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_EXTRACT]."()') is defined for the extraction");
+
+ // ----- Generate a local information
+ $v_local_header = array();
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
+
+ // ----- Call the callback
+ // Here I do not use call_user_func() because I need to send a reference to the
+ // header.
+ eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
+ if ($v_result == 0) {
+ // ----- Change the file status
+ $p_entry['status'] = "skipped";
+ $v_result = 1;
+ }
+
+ // ----- Look for abort result
+ if ($v_result == 2) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
+ // ----- This status is internal and will be changed in 'skipped'
+ $p_entry['status'] = "aborted";
+ $v_result = PCLZIP_ERR_USER_ABORTED;
+ }
+
+ // ----- Update the informations
+ // Only some fields can be modified
+ $p_entry['filename'] = $v_local_header['filename'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New filename is '".$p_entry['filename']."'");
+ }
+
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file (with path) '".$p_entry['filename']."', size '$v_header[size]'");
+
+ // ----- Look if extraction should be done
+ if ($p_entry['status'] == 'ok') {
+
+ // ----- Look for specific actions while the file exist
+ if (file_exists($p_entry['filename']))
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$p_entry['filename']."' already exists");
+
+ // ----- Look if file is a directory
+ if (is_dir($p_entry['filename']))
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is a directory");
+
+ // ----- Change the file status
+ $p_entry['status'] = "already_a_directory";
+
+ // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
+ // For historical reason first PclZip implementation does not stop
+ // when this kind of error occurs.
+ if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
+ && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
+
+ PclZip::privErrorLog(PCLZIP_ERR_ALREADY_A_DIRECTORY,
+ "Filename '".$p_entry['filename']."' is "
+ ."already used by an existing directory");
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ }
+ // ----- Look if file is write protected
+ else if (!is_writeable($p_entry['filename']))
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is write protected");
+
+ // ----- Change the file status
+ $p_entry['status'] = "write_protected";
+
+ // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
+ // For historical reason first PclZip implementation does not stop
+ // when this kind of error occurs.
+ if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
+ && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
+
+ PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
+ "Filename '".$p_entry['filename']."' exists "
+ ."and is write protected");
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ }
+
+ // ----- Look if the extracted file is older
+ else if (filemtime($p_entry['filename']) > $p_entry['mtime'])
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is newer (".date("l dS of F Y h:i:s A", filemtime($p_entry['filename'])).") than the extracted file (".date("l dS of F Y h:i:s A", $p_entry['mtime']).")");
+ // ----- Change the file status
+ if ( (isset($p_options[PCLZIP_OPT_REPLACE_NEWER]))
+ && ($p_options[PCLZIP_OPT_REPLACE_NEWER]===true)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_REPLACE_NEWER is selected, file will be replaced");
+ }
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will not be replaced");
+ $p_entry['status'] = "newer_exist";
+
+ // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
+ // For historical reason first PclZip implementation does not stop
+ // when this kind of error occurs.
+ if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
+ && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
+
+ PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
+ "Newer version of '".$p_entry['filename']."' exists "
+ ."and option PCLZIP_OPT_REPLACE_NEWER is not selected");
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ }
+ }
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is older than the extrated one - will be replaced by the extracted one (".date("l dS of F Y h:i:s A", filemtime($p_entry['filename'])).") than the extracted file (".date("l dS of F Y h:i:s A", $p_entry['mtime']).")");
+ }
+ }
+
+ // ----- Check the directory availability and create it if necessary
+ else {
+ if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/'))
+ $v_dir_to_check = $p_entry['filename'];
+ else if (!strstr($p_entry['filename'], "/"))
+ $v_dir_to_check = "";
+ else
+ $v_dir_to_check = dirname($p_entry['filename']);
+
+ if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to create path for '".$p_entry['filename']."'");
+
+ // ----- Change the file status
+ $p_entry['status'] = "path_creation_fail";
+
+ // ----- Return
+ ////--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ //return $v_result;
+ $v_result = 1;
+ }
+ }
+ }
+
+ // ----- Look if extraction should be done
+ if ($p_entry['status'] == 'ok') {
+
+ // ----- Do the extraction (if not a folder)
+ if (!(($p_entry['external']&0x00000010)==0x00000010))
+ {
+ // ----- Look for not compressed file
+ if ($p_entry['compression'] == 0) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
+
+ // ----- Opening destination file
+ if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode");
+
+ // ----- Change the file status
+ $p_entry['status'] = "write_error";
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read '".$p_entry['size']."' bytes");
+
+ // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
+ $v_size = $p_entry['compressed_size'];
+ while ($v_size != 0)
+ {
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read $v_read_size bytes");
+ $v_buffer = @fread($this->zip_fd, $v_read_size);
+ /* Try to speed up the code
+ $v_binary_data = pack('a'.$v_read_size, $v_buffer);
+ @fwrite($v_dest_file, $v_binary_data, $v_read_size);
+ */
+ @fwrite($v_dest_file, $v_buffer, $v_read_size);
+ $v_size -= $v_read_size;
+ }
+
+ // ----- Closing the destination file
+ fclose($v_dest_file);
+
+ // ----- Change the file mtime
+ touch($p_entry['filename'], $p_entry['mtime']);
+
+
+ }
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file (Compression method ".$p_entry['compression'].")");
+ // ----- TBC
+ // Need to be finished
+ if (($p_entry['flag'] & 1) == 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File is encrypted");
+ /*
+ // ----- Read the encryption header
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read 12 encryption header bytes");
+ $v_encryption_header = @fread($this->zip_fd, 12);
+
+ // ----- Read the encrypted & compressed file in a buffer
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read '".($p_entry['compressed_size']-12)."' compressed & encrypted bytes");
+ $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']-12);
+
+ // ----- Decrypt the buffer
+ $this->privDecrypt($v_encryption_header, $v_buffer,
+ $p_entry['compressed_size']-12, $p_entry['crc']);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Buffer is '".$v_buffer."'");
+ */
+ }
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read '".$p_entry['compressed_size']."' compressed bytes");
+ // ----- Read the compressed file in a buffer (one shot)
+ $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
+ }
+
+ // ----- Decompress the file
+ $v_file_content = @gzinflate($v_buffer);
+ unset($v_buffer);
+ if ($v_file_content === FALSE) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to inflate compressed file");
+
+ // ----- Change the file status
+ // TBC
+ $p_entry['status'] = "error";
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Opening destination file
+ if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode");
+
+ // ----- Change the file status
+ $p_entry['status'] = "write_error";
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Write the uncompressed data
+ @fwrite($v_dest_file, $v_file_content, $p_entry['size']);
+ unset($v_file_content);
+
+ // ----- Closing the destination file
+ @fclose($v_dest_file);
+
+ // ----- Change the file mtime
+ @touch($p_entry['filename'], $p_entry['mtime']);
+ }
+
+ // ----- Look for chmod option
+ if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "chmod option activated '".$p_options[PCLZIP_OPT_SET_CHMOD]."'");
+
+ // ----- Change the mode of the file
+ @chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]);
+ }
+
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
+ }
+ }
+
+ // ----- Change abort status
+ if ($p_entry['status'] == "aborted") {
+ $p_entry['status'] = "skipped";
+ }
+
+ // ----- Look for post-extract callback
+ elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_EXTRACT]."()') is defined for the extraction");
+
+ // ----- Generate a local information
+ $v_local_header = array();
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
+
+ // ----- Call the callback
+ // Here I do not use call_user_func() because I need to send a reference to the
+ // header.
+ eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
+
+ // ----- Look for abort result
+ if ($v_result == 2) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
+ $v_result = PCLZIP_ERR_USER_ABORTED;
+ }
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privExtractFileInOutput()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privExtractFileInOutput(&$p_entry, &$p_options)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFileInOutput', "");
+ $v_result=1;
+
+ // ----- Read the file header
+ if (($v_result = $this->privReadFileHeader($v_header)) != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'");
+
+ // ----- Check that the file header is coherent with $p_entry info
+ if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
+ // TBC
+ }
+
+ // ----- Look for pre-extract callback
+ if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_EXTRACT]."()') is defined for the extraction");
+
+ // ----- Generate a local information
+ $v_local_header = array();
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
+
+ // ----- Call the callback
+ // Here I do not use call_user_func() because I need to send a reference to the
+ // header.
+ eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
+ if ($v_result == 0) {
+ // ----- Change the file status
+ $p_entry['status'] = "skipped";
+ $v_result = 1;
+ }
+
+ // ----- Look for abort result
+ if ($v_result == 2) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
+ // ----- This status is internal and will be changed in 'skipped'
+ $p_entry['status'] = "aborted";
+ $v_result = PCLZIP_ERR_USER_ABORTED;
+ }
+
+ // ----- Update the informations
+ // Only some fields can be modified
+ $p_entry['filename'] = $v_local_header['filename'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New filename is '".$p_entry['filename']."'");
+ }
+
+ // ----- Trace
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file (with path) '".$p_entry['filename']."', size '$v_header[size]'");
+
+ // ----- Look if extraction should be done
+ if ($p_entry['status'] == 'ok') {
+
+ // ----- Do the extraction (if not a folder)
+ if (!(($p_entry['external']&0x00000010)==0x00000010)) {
+ // ----- Look for not compressed file
+ if ($p_entry['compressed_size'] == $p_entry['size']) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes");
+
+ // ----- Read the file in a buffer (one shot)
+ $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
+
+ // ----- Send the file to the output
+ echo $v_buffer;
+ unset($v_buffer);
+ }
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file");
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Reading '".$p_entry['size']."' bytes");
+
+ // ----- Read the compressed file in a buffer (one shot)
+ $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
+
+ // ----- Decompress the file
+ $v_file_content = gzinflate($v_buffer);
+ unset($v_buffer);
+
+ // ----- Send the file to the output
+ echo $v_file_content;
+ unset($v_file_content);
+ }
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
+ }
+ }
+
+ // ----- Change abort status
+ if ($p_entry['status'] == "aborted") {
+ $p_entry['status'] = "skipped";
+ }
+
+ // ----- Look for post-extract callback
+ elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_EXTRACT]."()') is defined for the extraction");
+
+ // ----- Generate a local information
+ $v_local_header = array();
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
+
+ // ----- Call the callback
+ // Here I do not use call_user_func() because I need to send a reference to the
+ // header.
+ eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
+
+ // ----- Look for abort result
+ if ($v_result == 2) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
+ $v_result = PCLZIP_ERR_USER_ABORTED;
+ }
+ }
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privExtractFileAsString()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privExtractFileAsString(&$p_entry, &$p_string)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFileAsString', "p_entry['filename']='".$p_entry['filename']."'");
+ $v_result=1;
+
+ // ----- Read the file header
+ $v_header = array();
+ if (($v_result = $this->privReadFileHeader($v_header)) != 1)
+ {
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'");
+
+ // ----- Check that the file header is coherent with $p_entry info
+ if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
+ // TBC
+ }
+
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file in string (with path) '".$p_entry['filename']."', size '$v_header[size]'");
+
+ // ----- Do the extraction (if not a folder)
+ if (!(($p_entry['external']&0x00000010)==0x00000010))
+ {
+ // ----- Look for not compressed file
+// if ($p_entry['compressed_size'] == $p_entry['size'])
+ if ($p_entry['compression'] == 0) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes");
+
+ // ----- Reading the file
+ $p_string = @fread($this->zip_fd, $p_entry['compressed_size']);
+ }
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file (compression method '".$p_entry['compression']."')");
+
+ // ----- Reading the file
+ $v_data = @fread($this->zip_fd, $p_entry['compressed_size']);
+
+ // ----- Decompress the file
+ if (($p_string = @gzinflate($v_data)) === FALSE) {
+ // TBC
+ }
+ }
+
+ // ----- Trace
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
+ }
+ else {
+ // TBC : error : can not extract a folder in a string
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privReadFileHeader()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privReadFileHeader(&$p_header)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadFileHeader", "");
+ $v_result=1;
+
+ // ----- Read the 4 bytes signature
+ $v_binary_data = @fread($this->zip_fd, 4);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
+ $v_data = unpack('Vid', $v_binary_data);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
+
+ // ----- Check signature
+ if ($v_data['id'] != 0x04034b50)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid File header");
+
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Read the first 42 bytes of the header
+ $v_binary_data = fread($this->zip_fd, 26);
+
+ // ----- Look for invalid block size
+ if (strlen($v_binary_data) != 26)
+ {
+ $p_header['filename'] = "";
+ $p_header['status'] = "invalid_header";
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid block size : ".strlen($v_binary_data));
+
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Extract the values
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Header : '".$v_binary_data."'");
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Header (Hex) : '".bin2hex($v_binary_data)."'");
+ $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
+
+ // ----- Get filename
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "File name length : ".$v_data['filename_len']);
+ $p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Filename : \''.$p_header['filename'].'\'');
+
+ // ----- Get extra_fields
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extra field length : ".$v_data['extra_len']);
+ if ($v_data['extra_len'] != 0) {
+ $p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']);
+ }
+ else {
+ $p_header['extra'] = '';
+ }
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Extra field : \''.bin2hex($p_header['extra']).'\'');
+
+ // ----- Extract properties
+ $p_header['version_extracted'] = $v_data['version'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version need to extract : ('.$p_header['version_extracted'].') \''.($p_header['version_extracted']/10).'.'.($p_header['version_extracted']%10).'\'');
+ $p_header['compression'] = $v_data['compression'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compression method : \''.$p_header['compression'].'\'');
+ $p_header['size'] = $v_data['size'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size : \''.$p_header['size'].'\'');
+ $p_header['compressed_size'] = $v_data['compressed_size'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compressed Size : \''.$p_header['compressed_size'].'\'');
+ $p_header['crc'] = $v_data['crc'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'CRC : \''.sprintf("0x%X", $p_header['crc']).'\'');
+ $p_header['flag'] = $v_data['flag'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Flag : \''.$p_header['flag'].'\'');
+ $p_header['filename_len'] = $v_data['filename_len'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Filename_len : \''.$p_header['filename_len'].'\'');
+
+ // ----- Recuperate date in UNIX format
+ $p_header['mdate'] = $v_data['mdate'];
+ $p_header['mtime'] = $v_data['mtime'];
+ if ($p_header['mdate'] && $p_header['mtime'])
+ {
+ // ----- Extract time
+ $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
+ $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
+ $v_seconde = ($p_header['mtime'] & 0x001F)*2;
+
+ // ----- Extract date
+ $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
+ $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
+ $v_day = $p_header['mdate'] & 0x001F;
+
+ // ----- Get UNIX date format
+ $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
+
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
+ }
+ else
+ {
+ $p_header['mtime'] = time();
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date is actual : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
+ }
+
+ // TBC
+ //for(reset($v_data); $key = key($v_data); next($v_data)) {
+ // //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Attribut[$key] = ".$v_data[$key]);
+ //}
+
+ // ----- Set the stored filename
+ $p_header['stored_filename'] = $p_header['filename'];
+
+ // ----- Set the status field
+ $p_header['status'] = "ok";
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privReadCentralFileHeader()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privReadCentralFileHeader(&$p_header)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadCentralFileHeader", "");
+ $v_result=1;
+
+ // ----- Read the 4 bytes signature
+ $v_binary_data = @fread($this->zip_fd, 4);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
+ $v_data = unpack('Vid', $v_binary_data);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
+
+ // ----- Check signature
+ if ($v_data['id'] != 0x02014b50)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid Central Dir File signature");
+
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Read the first 42 bytes of the header
+ $v_binary_data = fread($this->zip_fd, 42);
+
+ // ----- Look for invalid block size
+ if (strlen($v_binary_data) != 42)
+ {
+ $p_header['filename'] = "";
+ $p_header['status'] = "invalid_header";
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid block size : ".strlen($v_binary_data));
+
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Extract the values
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header : '".$v_binary_data."'");
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header (Hex) : '".bin2hex($v_binary_data)."'");
+ $p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data);
+
+ // ----- Get filename
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "File name length : ".$p_header['filename_len']);
+ if ($p_header['filename_len'] != 0)
+ $p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']);
+ else
+ $p_header['filename'] = '';
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Filename : \''.$p_header['filename'].'\'');
+
+ // ----- Get extra
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Extra length : ".$p_header['extra_len']);
+ if ($p_header['extra_len'] != 0)
+ $p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']);
+ else
+ $p_header['extra'] = '';
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Extra : \''.$p_header['extra'].'\'');
+
+ // ----- Get comment
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Comment length : ".$p_header['comment_len']);
+ if ($p_header['comment_len'] != 0)
+ $p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']);
+ else
+ $p_header['comment'] = '';
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Comment : \''.$p_header['comment'].'\'');
+
+ // ----- Extract properties
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version : \''.($p_header['version']/10).'.'.($p_header['version']%10).'\'');
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version need to extract : \''.($p_header['version_extracted']/10).'.'.($p_header['version_extracted']%10).'\'');
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Size : \''.$p_header['size'].'\'');
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Compressed Size : \''.$p_header['compressed_size'].'\'');
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'CRC : \''.sprintf("0x%X", $p_header['crc']).'\'');
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Flag : \''.$p_header['flag'].'\'');
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Offset : \''.$p_header['offset'].'\'');
+
+ // ----- Recuperate date in UNIX format
+ if ($p_header['mdate'] && $p_header['mtime'])
+ {
+ // ----- Extract time
+ $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
+ $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
+ $v_seconde = ($p_header['mtime'] & 0x001F)*2;
+
+ // ----- Extract date
+ $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
+ $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
+ $v_day = $p_header['mdate'] & 0x001F;
+
+ // ----- Get UNIX date format
+ $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
+
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
+ }
+ else
+ {
+ $p_header['mtime'] = time();
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Date is actual : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
+ }
+
+ // ----- Set the stored filename
+ $p_header['stored_filename'] = $p_header['filename'];
+
+ // ----- Set default status to ok
+ $p_header['status'] = 'ok';
+
+ // ----- Look if it is a directory
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Internal (Hex) : '".sprintf("Ox%04X", $p_header['internal'])."'");
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "External (Hex) : '".sprintf("Ox%04X", $p_header['external'])."' (".(($p_header['external']&0x00000010)==0x00000010?'is a folder':'is a file').')');
+ if (substr($p_header['filename'], -1) == '/') {
+ //$p_header['external'] = 0x41FF0010;
+ $p_header['external'] = 0x00000010;
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Force folder external : \''.sprintf("Ox%04X", $p_header['external']).'\'');
+ }
+
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Header of filename : \''.$p_header['filename'].'\'');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privCheckFileHeaders()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // 1 on success,
+ // 0 on error;
+ // --------------------------------------------------------------------------------
+ function privCheckFileHeaders(&$p_local_header, &$p_central_header)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCheckFileHeaders", "");
+ $v_result=1;
+
+ // ----- Check the static values
+ // TBC
+ if ($p_local_header['filename'] != $p_central_header['filename']) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "filename" : TBC To Be Completed');
+ }
+ if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "version_extracted" : TBC To Be Completed');
+ }
+ if ($p_local_header['flag'] != $p_central_header['flag']) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "flag" : TBC To Be Completed');
+ }
+ if ($p_local_header['compression'] != $p_central_header['compression']) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "compression" : TBC To Be Completed');
+ }
+ if ($p_local_header['mtime'] != $p_central_header['mtime']) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "mtime" : TBC To Be Completed');
+ }
+ if ($p_local_header['filename_len'] != $p_central_header['filename_len']) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "filename_len" : TBC To Be Completed');
+ }
+
+ // ----- Look for flag bit 3
+ if (($p_local_header['flag'] & 8) == 8) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Purpose bit flag bit 3 set !');
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'File size, compression size and crc found in central header');
+ $p_local_header['size'] = $p_central_header['size'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size : \''.$p_local_header['size'].'\'');
+ $p_local_header['compressed_size'] = $p_central_header['compressed_size'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compressed Size : \''.$p_local_header['compressed_size'].'\'');
+ $p_local_header['crc'] = $p_central_header['crc'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'CRC : \''.sprintf("0x%X", $p_local_header['crc']).'\'');
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privReadEndCentralDir()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privReadEndCentralDir(&$p_central_dir)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadEndCentralDir", "");
+ $v_result=1;
+
+ // ----- Go to the end of the zip file
+ $v_size = filesize($this->zipname);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Size of the file :$v_size");
+ @fseek($this->zip_fd, $v_size);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position at end of zip file : \''.ftell($this->zip_fd).'\'');
+ if (@ftell($this->zip_fd) != $v_size)
+ {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\'');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- First try : look if this is an archive with no commentaries (most of the time)
+ // in this case the end of central dir is at 22 bytes of the file end
+ $v_found = 0;
+ if ($v_size > 26) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Look for central dir with no comment');
+ @fseek($this->zip_fd, $v_size-22);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after min central position : \''.ftell($this->zip_fd).'\'');
+ if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22))
+ {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Read for bytes
+ $v_binary_data = @fread($this->zip_fd, 4);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
+ $v_data = @unpack('Vid', $v_binary_data);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
+
+ // ----- Check signature
+ if ($v_data['id'] == 0x06054b50) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found central dir at the default position.");
+ $v_found = 1;
+ }
+
+ $v_pos = ftell($this->zip_fd);
+ }
+
+ // ----- Go back to the maximum possible size of the Central Dir End Record
+ if (!$v_found) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Start extended search of end central dir');
+ $v_maximum_size = 65557; // 0xFFFF + 22;
+ if ($v_maximum_size > $v_size)
+ $v_maximum_size = $v_size;
+ @fseek($this->zip_fd, $v_size-$v_maximum_size);
+ if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size))
+ {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after max central position : \''.ftell($this->zip_fd).'\'');
+
+ // ----- Read byte per byte in order to find the signature
+ $v_pos = ftell($this->zip_fd);
+ $v_bytes = 0x00000000;
+ while ($v_pos < $v_size)
+ {
+ // ----- Read a byte
+ $v_byte = @fread($this->zip_fd, 1);
+
+ // ----- Add the byte
+ $v_bytes = ($v_bytes << 8) | Ord($v_byte);
+
+ // ----- Compare the bytes
+ if ($v_bytes == 0x504b0506)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Found End Central Dir signature at position : \''.ftell($this->zip_fd).'\'');
+ $v_pos++;
+ break;
+ }
+
+ $v_pos++;
+ }
+
+ // ----- Look if not found end of central dir
+ if ($v_pos == $v_size)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to find End of Central Dir Record signature");
+
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ }
+
+ // ----- Read the first 18 bytes of the header
+ $v_binary_data = fread($this->zip_fd, 18);
+
+ // ----- Look for invalid block size
+ if (strlen($v_binary_data) != 18)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
+
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Extract the values
+ ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Central Dir Record : '".$v_binary_data."'");
+ ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Central Dir Record (Hex) : '".bin2hex($v_binary_data)."'");
+ $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
+
+ // ----- Check the global size
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Comment length : ".$v_data['comment_size']);
+ if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The central dir is not at the end of the archive. Some trailing bytes exists after the archive.");
+
+ // ----- Removed in release 2.2 see readme file
+ // The check of the file size is a little too strict.
+ // Some bugs where found when a zip is encrypted/decrypted with 'crypt'.
+ // While decrypted, zip has training 0 bytes
+ if (0) {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT,
+ 'The central dir is not at the end of the archive.'
+ .' Some trailing bytes exists after the archive.');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ }
+
+ // ----- Get comment
+ if ($v_data['comment_size'] != 0)
+ $p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']);
+ else
+ $p_central_dir['comment'] = '';
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment : \''.$p_central_dir['comment'].'\'');
+
+ $p_central_dir['entries'] = $v_data['entries'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Nb of entries : \''.$p_central_dir['entries'].'\'');
+ $p_central_dir['disk_entries'] = $v_data['disk_entries'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Nb of entries for this disk : \''.$p_central_dir['disk_entries'].'\'');
+ $p_central_dir['offset'] = $v_data['offset'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Offset of Central Dir : \''.$p_central_dir['offset'].'\'');
+ $p_central_dir['size'] = $v_data['size'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size of Central Dir : \''.$p_central_dir['size'].'\'');
+ $p_central_dir['disk'] = $v_data['disk'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Disk number : \''.$p_central_dir['disk'].'\'');
+ $p_central_dir['disk_start'] = $v_data['disk_start'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Start disk number : \''.$p_central_dir['disk_start'].'\'');
+
+ // TBC
+ //for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) {
+ // //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "central_dir[$key] = ".$p_central_dir[$key]);
+ //}
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privDeleteByRule()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privDeleteByRule(&$p_result_list, &$p_options)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDeleteByRule", "");
+ $v_result=1;
+ $v_list_detail = array();
+
+ // ----- Open the zip file
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+ if (($v_result=$this->privOpenFd('rb')) != 1)
+ {
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Read the central directory informations
+ $v_central_dir = array();
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
+ {
+ $this->privCloseFd();
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Go to beginning of File
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
+ @rewind($this->zip_fd);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
+
+ // ----- Scan all the files
+ // ----- Start at beginning of Central Dir
+ $v_pos_entry = $v_central_dir['offset'];
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
+ @rewind($this->zip_fd);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
+ if (@fseek($this->zip_fd, $v_pos_entry))
+ {
+ // ----- Close the zip file
+ $this->privCloseFd();
+
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
+
+ // ----- Read each entry
+ $v_header_list = array();
+ $j_start = 0;
+ for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file header entry (index '$i')");
+
+ // ----- Read the file header
+ $v_header_list[$v_nb_extracted] = array();
+ if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1)
+ {
+ // ----- Close the zip file
+ $this->privCloseFd();
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename (index '$i') : '".$v_header_list[$v_nb_extracted]['stored_filename']."'");
+
+ // ----- Store the index
+ $v_header_list[$v_nb_extracted]['index'] = $i;
+
+ // ----- Look for the specific extract rules
+ $v_found = false;
+
+ // ----- Look for extract by name rule
+ if ( (isset($p_options[PCLZIP_OPT_BY_NAME]))
+ && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByName'");
+
+ // ----- Look if the filename is in the list
+ for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_found); $j++) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Compare with file '".$p_options[PCLZIP_OPT_BY_NAME][$j]."'");
+
+ // ----- Look for a directory
+ if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The searched item is a directory");
+
+ // ----- Look if the directory is in the filename path
+ if ( (strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
+ && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The directory is in the file path");
+ $v_found = true;
+ }
+ elseif ( (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */
+ && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The entry is the searched directory");
+ $v_found = true;
+ }
+ }
+ // ----- Look for a filename
+ elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The file is the right one.");
+ $v_found = true;
+ }
+ }
+ }
+
+ // ----- Look for extract by ereg rule
+ else if ( (isset($p_options[PCLZIP_OPT_BY_EREG]))
+ && ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract by ereg '".$p_options[PCLZIP_OPT_BY_EREG]."'");
+
+ if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
+ $v_found = true;
+ }
+ }
+
+ // ----- Look for extract by preg rule
+ else if ( (isset($p_options[PCLZIP_OPT_BY_PREG]))
+ && ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByEreg'");
+
+ if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
+ $v_found = true;
+ }
+ }
+
+ // ----- Look for extract by index rule
+ else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX]))
+ && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByIndex'");
+
+ // ----- Look if the index is in the list
+ for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_found); $j++) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Look if index '$i' is in [".$p_options[PCLZIP_OPT_BY_INDEX][$j]['start'].",".$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']."]");
+
+ if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as part of an index range");
+ $v_found = true;
+ }
+ if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Do not look this index range for next loop");
+ $j_start = $j+1;
+ }
+
+ if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Index range is greater than index, stop loop");
+ break;
+ }
+ }
+ }
+ else {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "No argument mean remove all file");
+ $v_found = true;
+ }
+
+ // ----- Look for deletion
+ if ($v_found)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_header_list[$v_nb_extracted]['stored_filename']."', index '$i' need to be deleted");
+ unset($v_header_list[$v_nb_extracted]);
+ }
+ else
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_header_list[$v_nb_extracted]['stored_filename']."', index '$i' will not be deleted");
+ $v_nb_extracted++;
+ }
+ }
+
+ // ----- Look if something need to be deleted
+ if ($v_nb_extracted > 0) {
+
+ // ----- Creates a temporay file
+ $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
+
+ // ----- Creates a temporary zip archive
+ $v_temp_zip = new PclZip($v_zip_temp_name);
+
+ // ----- Open the temporary zip file in write mode
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary write mode");
+ if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) {
+ $this->privCloseFd();
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Look which file need to be kept
+ for ($i=0; $i<sizeof($v_header_list); $i++) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Keep entry index '$i' : '".$v_header_list[$i]['filename']."'");
+
+ // ----- Calculate the position of the header
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset='". $v_header_list[$i]['offset']."'");
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
+ @rewind($this->zip_fd);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
+ if (@fseek($this->zip_fd, $v_header_list[$i]['offset'])) {
+ // ----- Close the zip file
+ $this->privCloseFd();
+ $v_temp_zip->privCloseFd();
+ @unlink($v_zip_temp_name);
+
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
+
+ // ----- Read the file header
+ $v_local_header = array();
+ if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) {
+ // ----- Close the zip file
+ $this->privCloseFd();
+ $v_temp_zip->privCloseFd();
+ @unlink($v_zip_temp_name);
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Check that local file header is same as central file header
+ if ($this->privCheckFileHeaders($v_local_header,
+ $v_header_list[$i]) != 1) {
+ // TBC
+ }
+ unset($v_local_header);
+
+ // ----- Write the file header
+ if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) {
+ // ----- Close the zip file
+ $this->privCloseFd();
+ $v_temp_zip->privCloseFd();
+ @unlink($v_zip_temp_name);
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset for this file is '".$v_header_list[$i]['offset']."'");
+
+ // ----- Read/write the data block
+ if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) {
+ // ----- Close the zip file
+ $this->privCloseFd();
+ $v_temp_zip->privCloseFd();
+ @unlink($v_zip_temp_name);
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ }
+
+ // ----- Store the offset of the central dir
+ $v_offset = @ftell($v_temp_zip->zip_fd);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "New offset of central dir : $v_offset");
+
+ // ----- Re-Create the Central Dir files header
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Creates the new central directory");
+ for ($i=0; $i<sizeof($v_header_list); $i++) {
+ // ----- Create the file header
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset of file : ".$v_header_list[$i]['offset']);
+ if (($v_result = $v_temp_zip->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
+ $v_temp_zip->privCloseFd();
+ $this->privCloseFd();
+ @unlink($v_zip_temp_name);
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Transform the header to a 'usable' info
+ $v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
+ }
+
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Creates the central directory footer");
+
+ // ----- Zip file comment
+ $v_comment = '';
+ if (isset($p_options[PCLZIP_OPT_COMMENT])) {
+ $v_comment = $p_options[PCLZIP_OPT_COMMENT];
+ }
+
+ // ----- Calculate the size of the central header
+ $v_size = @ftell($v_temp_zip->zip_fd)-$v_offset;
+
+ // ----- Create the central dir footer
+ if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) {
+ // ----- Reset the file list
+ unset($v_header_list);
+ $v_temp_zip->privCloseFd();
+ $this->privCloseFd();
+ @unlink($v_zip_temp_name);
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Close
+ $v_temp_zip->privCloseFd();
+ $this->privCloseFd();
+
+ // ----- Delete the zip file
+ // TBC : I should test the result ...
+ @unlink($this->zipname);
+
+ // ----- Rename the temporary file
+ // TBC : I should test the result ...
+ //@rename($v_zip_temp_name, $this->zipname);
+ PclZipUtilRename($v_zip_temp_name, $this->zipname);
+
+ // ----- Destroy the temporary archive
+ unset($v_temp_zip);
+ }
+
+ // ----- Remove every files : reset the file
+ else if ($v_central_dir['entries'] != 0) {
+ $this->privCloseFd();
+
+ if (($v_result = $this->privOpenFd('wb')) != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ $this->privCloseFd();
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privDirCheck()
+ // Description :
+ // Check if a directory exists, if not it creates it and all the parents directory
+ // which may be useful.
+ // Parameters :
+ // $p_dir : Directory path to check.
+ // Return Values :
+ // 1 : OK
+ // -1 : Unable to create directory
+ // --------------------------------------------------------------------------------
+ function privDirCheck($p_dir, $p_is_dir=false)
+ {
+ $v_result = 1;
+
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDirCheck", "entry='$p_dir', is_dir='".($p_is_dir?"true":"false")."'");
+
+ // ----- Remove the final '/'
+ if (($p_is_dir) && (substr($p_dir, -1)=='/'))
+ {
+ $p_dir = substr($p_dir, 0, strlen($p_dir)-1);
+ }
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Looking for entry '$p_dir'");
+
+ // ----- Check the directory availability
+ if ((is_dir($p_dir)) || ($p_dir == ""))
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, "'$p_dir' is a directory");
+ return 1;
+ }
+
+ // ----- Extract parent directory
+ $p_parent_dir = dirname($p_dir);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Parent directory is '$p_parent_dir'");
+
+ // ----- Just a check
+ if ($p_parent_dir != $p_dir)
+ {
+ // ----- Look for parent directory
+ if ($p_parent_dir != "")
+ {
+ if (($v_result = $this->privDirCheck($p_parent_dir)) != 1)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ }
+ }
+
+ // ----- Create the directory
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Create directory '$p_dir'");
+ if (!@mkdir($p_dir, 0777))
+ {
+ // ----- Error log
+ PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'");
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result, "Directory '$p_dir' created");
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privMerge()
+ // Description :
+ // If $p_archive_to_add does not exist, the function exit with a success result.
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privMerge(&$p_archive_to_add)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privMerge", "archive='".$p_archive_to_add->zipname."'");
+ $v_result=1;
+
+ // ----- Look if the archive_to_add exists
+ if (!is_file($p_archive_to_add->zipname))
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive to add does not exist. End of merge.");
+
+ // ----- Nothing to merge, so merge is a success
+ $v_result = 1;
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Look if the archive exists
+ if (!is_file($this->zipname))
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive does not exist, duplicate the archive_to_add.");
+
+ // ----- Do a duplicate
+ $v_result = $this->privDuplicate($p_archive_to_add->zipname);
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Open the zip file
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+ if (($v_result=$this->privOpenFd('rb')) != 1)
+ {
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Read the central directory informations
+ $v_central_dir = array();
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
+ {
+ $this->privCloseFd();
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Go to beginning of File
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in zip : ".ftell($this->zip_fd)."'");
+ @rewind($this->zip_fd);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in zip : ".ftell($this->zip_fd)."'");
+
+ // ----- Open the archive_to_add file
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open archive_to_add in binary read mode");
+ if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1)
+ {
+ $this->privCloseFd();
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Read the central directory informations
+ $v_central_dir_to_add = array();
+ if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1)
+ {
+ $this->privCloseFd();
+ $p_archive_to_add->privCloseFd();
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Go to beginning of File
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in archive_to_add : ".ftell($p_archive_to_add->zip_fd)."'");
+ @rewind($p_archive_to_add->zip_fd);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in archive_to_add : ".ftell($p_archive_to_add->zip_fd)."'");
+
+ // ----- Creates a temporay file
+ $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
+
+ // ----- Open the temporary file in write mode
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+ if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
+ {
+ $this->privCloseFd();
+ $p_archive_to_add->privCloseFd();
+
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Copy the files from the archive to the temporary file
+ // TBC : Here I should better append the file and go back to erase the central dir
+ $v_size = $v_central_dir['offset'];
+ while ($v_size != 0)
+ {
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+ $v_buffer = fread($this->zip_fd, $v_read_size);
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
+ $v_size -= $v_read_size;
+ }
+
+ // ----- Copy the files from the archive_to_add into the temporary file
+ $v_size = $v_central_dir_to_add['offset'];
+ while ($v_size != 0)
+ {
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+ $v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size);
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
+ $v_size -= $v_read_size;
+ }
+
+ // ----- Store the offset of the central dir
+ $v_offset = @ftell($v_zip_temp_fd);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset");
+
+ // ----- Copy the block of file headers from the old archive
+ $v_size = $v_central_dir['size'];
+ while ($v_size != 0)
+ {
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+ $v_buffer = @fread($this->zip_fd, $v_read_size);
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
+ $v_size -= $v_read_size;
+ }
+
+ // ----- Copy the block of file headers from the archive_to_add
+ $v_size = $v_central_dir_to_add['size'];
+ while ($v_size != 0)
+ {
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+ $v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size);
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
+ $v_size -= $v_read_size;
+ }
+
+ // ----- Merge the file comments
+ $v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment'];
+
+ // ----- Calculate the size of the (new) central header
+ $v_size = @ftell($v_zip_temp_fd)-$v_offset;
+
+ // ----- Swap the file descriptor
+ // Here is a trick : I swap the temporary fd with the zip fd, in order to use
+ // the following methods on the temporary fil and not the real archive fd
+ $v_swap = $this->zip_fd;
+ $this->zip_fd = $v_zip_temp_fd;
+ $v_zip_temp_fd = $v_swap;
+
+ // ----- Create the central dir footer
+ if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1)
+ {
+ $this->privCloseFd();
+ $p_archive_to_add->privCloseFd();
+ @fclose($v_zip_temp_fd);
+ $this->zip_fd = null;
+
+ // ----- Reset the file list
+ unset($v_header_list);
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Swap back the file descriptor
+ $v_swap = $this->zip_fd;
+ $this->zip_fd = $v_zip_temp_fd;
+ $v_zip_temp_fd = $v_swap;
+
+ // ----- Close
+ $this->privCloseFd();
+ $p_archive_to_add->privCloseFd();
+
+ // ----- Close the temporary file
+ @fclose($v_zip_temp_fd);
+
+ // ----- Delete the zip file
+ // TBC : I should test the result ...
+ @unlink($this->zipname);
+
+ // ----- Rename the temporary file
+ // TBC : I should test the result ...
+ //@rename($v_zip_temp_name, $this->zipname);
+ PclZipUtilRename($v_zip_temp_name, $this->zipname);
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privDuplicate()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privDuplicate($p_archive_filename)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDuplicate", "archive_filename='$p_archive_filename'");
+ $v_result=1;
+
+ // ----- Look if the $p_archive_filename exists
+ if (!is_file($p_archive_filename))
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive to duplicate does not exist. End of duplicate.");
+
+ // ----- Nothing to duplicate, so duplicate is a success.
+ $v_result = 1;
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Open the zip file
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+ if (($v_result=$this->privOpenFd('wb')) != 1)
+ {
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Open the temporary file in write mode
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
+ if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0)
+ {
+ $this->privCloseFd();
+
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode');
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
+ return PclZip::errorCode();
+ }
+
+ // ----- Copy the files from the archive to the temporary file
+ // TBC : Here I should better append the file and go back to erase the central dir
+ $v_size = filesize($p_archive_filename);
+ while ($v_size != 0)
+ {
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read $v_read_size bytes");
+ $v_buffer = fread($v_zip_temp_fd, $v_read_size);
+ @fwrite($this->zip_fd, $v_buffer, $v_read_size);
+ $v_size -= $v_read_size;
+ }
+
+ // ----- Close
+ $this->privCloseFd();
+
+ // ----- Close the temporary file
+ @fclose($v_zip_temp_fd);
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privErrorLog()
+ // Description :
+ // Parameters :
+ // --------------------------------------------------------------------------------
+ function privErrorLog($p_error_code=0, $p_error_string='')
+ {
+ if (PCLZIP_ERROR_EXTERNAL == 1) {
+ PclError($p_error_code, $p_error_string);
+ }
+ else {
+ $this->error_code = $p_error_code;
+ $this->error_string = $p_error_string;
+ }
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privErrorReset()
+ // Description :
+ // Parameters :
+ // --------------------------------------------------------------------------------
+ function privErrorReset()
+ {
+ if (PCLZIP_ERROR_EXTERNAL == 1) {
+ PclErrorReset();
+ }
+ else {
+ $this->error_code = 0;
+ $this->error_string = '';
+ }
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privDecrypt()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privDecrypt($p_encryption_header, &$p_buffer, $p_size, $p_crc)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privDecrypt', "size=".$p_size."");
+ $v_result=1;
+
+ // ----- To Be Modified ;-)
+ $v_pwd = "test";
+
+ $p_buffer = PclZipUtilZipDecrypt($p_buffer, $p_size, $p_encryption_header,
+ $p_crc, $v_pwd);
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privDisableMagicQuotes()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privDisableMagicQuotes()
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privDisableMagicQuotes', "");
+ $v_result=1;
+
+ // ----- Look if function exists
+ if ( (!function_exists("get_magic_quotes_runtime"))
+ || (!function_exists("set_magic_quotes_runtime"))) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Functions *et_magic_quotes_runtime are not supported");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Look if already done
+ if ($this->magic_quotes_status != -1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "magic_quote already disabled");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Get and memorize the magic_quote value
+ $this->magic_quotes_status = @get_magic_quotes_runtime();
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Current magic_quotes_runtime status is '".($this->magic_quotes_status==0?'disable':'enable')."'");
+
+ // ----- Disable magic_quotes
+ if ($this->magic_quotes_status == 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Disable magic_quotes");
+ @set_magic_quotes_runtime(0);
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : privSwapBackMagicQuotes()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function privSwapBackMagicQuotes()
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privSwapBackMagicQuotes', "");
+ $v_result=1;
+
+ // ----- Look if function exists
+ if ( (!function_exists("get_magic_quotes_runtime"))
+ || (!function_exists("set_magic_quotes_runtime"))) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Functions *et_magic_quotes_runtime are not supported");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Look if something to do
+ if ($this->magic_quotes_status != -1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "magic_quote not modified");
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+
+ // ----- Swap back magic_quotes
+ if ($this->magic_quotes_status == 1) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Enable back magic_quotes");
+ @set_magic_quotes_runtime($this->magic_quotes_status);
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ }
+ // End of class
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : PclZipUtilPathReduction()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function PclZipUtilPathReduction($p_dir)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilPathReduction", "dir='$p_dir'");
+ $v_result = "";
+
+ // ----- Look for not empty path
+ if ($p_dir != "") {
+ // ----- Explode path by directory names
+ $v_list = explode("/", $p_dir);
+
+ // ----- Study directories from last to first
+ $v_skip = 0;
+ for ($i=sizeof($v_list)-1; $i>=0; $i--) {
+ // ----- Look for current path
+ if ($v_list[$i] == ".") {
+ // ----- Ignore this directory
+ // Should be the first $i=0, but no check is done
+ }
+ else if ($v_list[$i] == "..") {
+ $v_skip++;
+ }
+ else if ($v_list[$i] == "") {
+ // ----- First '/' i.e. root slash
+ if ($i == 0) {
+ $v_result = "/".$v_result;
+ if ($v_skip > 0) {
+ // ----- It is an invalid path, so the path is not modified
+ // TBC
+ $v_result = $p_dir;
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid path is unchanged");
+ $v_skip = 0;
+ }
+ }
+ // ----- Last '/' i.e. indicates a directory
+ else if ($i == (sizeof($v_list)-1)) {
+ $v_result = $v_list[$i];
+ }
+ // ----- Double '/' inside the path
+ else {
+ // ----- Ignore only the double '//' in path,
+ // but not the first and last '/'
+ }
+ }
+ else {
+ // ----- Look for item to skip
+ if ($v_skip > 0) {
+ $v_skip--;
+ }
+ else {
+ $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:"");
+ }
+ }
+ }
+
+ // ----- Look for skip
+ if ($v_skip > 0) {
+ while ($v_skip > 0) {
+ $v_result = '../'.$v_result;
+ $v_skip--;
+ }
+ }
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : PclZipUtilPathInclusion()
+ // Description :
+ // This function indicates if the path $p_path is under the $p_dir tree. Or,
+ // said in an other way, if the file or sub-dir $p_path is inside the dir
+ // $p_dir.
+ // The function indicates also if the path is exactly the same as the dir.
+ // This function supports path with duplicated '/' like '//', but does not
+ // support '.' or '..' statements.
+ // Parameters :
+ // Return Values :
+ // 0 if $p_path is not inside directory $p_dir
+ // 1 if $p_path is inside directory $p_dir
+ // 2 if $p_path is exactly the same as $p_dir
+ // --------------------------------------------------------------------------------
+ function PclZipUtilPathInclusion($p_dir, $p_path)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilPathInclusion", "dir='$p_dir', path='$p_path'");
+ $v_result = 1;
+
+ // ----- Look for path beginning by ./
+ if ( ($p_dir == '.')
+ || ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) {
+ $p_dir = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_dir, 1);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Replacing ./ by full path in p_dir '".$p_dir."'");
+ }
+ if ( ($p_path == '.')
+ || ((strlen($p_path) >=2) && (substr($p_path, 0, 2) == './'))) {
+ $p_path = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_path, 1);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Replacing ./ by full path in p_path '".$p_path."'");
+ }
+
+ // ----- Explode dir and path by directory separator
+ $v_list_dir = explode("/", $p_dir);
+ $v_list_dir_size = sizeof($v_list_dir);
+ $v_list_path = explode("/", $p_path);
+ $v_list_path_size = sizeof($v_list_path);
+
+ // ----- Study directories paths
+ $i = 0;
+ $j = 0;
+ while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Working on dir($i)='".$v_list_dir[$i]."' and path($j)='".$v_list_path[$j]."'");
+
+ // ----- Look for empty dir (path reduction)
+ if ($v_list_dir[$i] == '') {
+ $i++;
+ continue;
+ }
+ if ($v_list_path[$j] == '') {
+ $j++;
+ continue;
+ }
+
+ // ----- Compare the items
+ if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Items ($i,$j) are different");
+ $v_result = 0;
+ }
+
+ // ----- Next items
+ $i++;
+ $j++;
+ }
+
+ // ----- Look if everything seems to be the same
+ if ($v_result) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Look for tie break");
+ // ----- Skip all the empty items
+ while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++;
+ while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++;
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Looking on dir($i)='".($i < $v_list_dir_size?$v_list_dir[$i]:'')."' and path($j)='".($j < $v_list_path_size?$v_list_path[$j]:'')."'");
+
+ if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
+ // ----- There are exactly the same
+ $v_result = 2;
+ }
+ else if ($i < $v_list_dir_size) {
+ // ----- The path is shorter than the dir
+ $v_result = 0;
+ }
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : PclZipUtilCopyBlock()
+ // Description :
+ // Parameters :
+ // $p_mode : read/write compression mode
+ // 0 : src & dest normal
+ // 1 : src gzip, dest normal
+ // 2 : src normal, dest gzip
+ // 3 : src & dest gzip
+ // Return Values :
+ // --------------------------------------------------------------------------------
+ function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilCopyBlock", "size=$p_size, mode=$p_mode");
+ $v_result = 1;
+
+ if ($p_mode==0)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Src offset before read :".(@ftell($p_src)));
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Dest offset before write :".(@ftell($p_dest)));
+ while ($p_size != 0)
+ {
+ $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+ $v_buffer = @fread($p_src, $v_read_size);
+ @fwrite($p_dest, $v_buffer, $v_read_size);
+ $p_size -= $v_read_size;
+ }
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Src offset after read :".(@ftell($p_src)));
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Dest offset after write :".(@ftell($p_dest)));
+ }
+ else if ($p_mode==1)
+ {
+ while ($p_size != 0)
+ {
+ $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+ $v_buffer = @gzread($p_src, $v_read_size);
+ @fwrite($p_dest, $v_buffer, $v_read_size);
+ $p_size -= $v_read_size;
+ }
+ }
+ else if ($p_mode==2)
+ {
+ while ($p_size != 0)
+ {
+ $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+ $v_buffer = @fread($p_src, $v_read_size);
+ @gzwrite($p_dest, $v_buffer, $v_read_size);
+ $p_size -= $v_read_size;
+ }
+ }
+ else if ($p_mode==3)
+ {
+ while ($p_size != 0)
+ {
+ $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
+ $v_buffer = @gzread($p_src, $v_read_size);
+ @gzwrite($p_dest, $v_buffer, $v_read_size);
+ $p_size -= $v_read_size;
+ }
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : PclZipUtilRename()
+ // Description :
+ // This function tries to do a simple rename() function. If it fails, it
+ // tries to copy the $p_src file in a new $p_dest file and then unlink the
+ // first one.
+ // Parameters :
+ // $p_src : Old filename
+ // $p_dest : New filename
+ // Return Values :
+ // 1 on success, 0 on failure.
+ // --------------------------------------------------------------------------------
+ function PclZipUtilRename($p_src, $p_dest)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilRename", "source=$p_src, destination=$p_dest");
+ $v_result = 1;
+
+ // ----- Try to rename the files
+ if (!@rename($p_src, $p_dest)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to rename file, try copy+unlink");
+
+ // ----- Try to copy & unlink the src
+ if (!@copy($p_src, $p_dest)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to copy file");
+ $v_result = 0;
+ }
+ else if (!@unlink($p_src)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to unlink old filename");
+ $v_result = 0;
+ }
+ }
+
+ // ----- Return
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : PclZipUtilOptionText()
+ // Description :
+ // Translate option value in text. Mainly for debug purpose.
+ // Parameters :
+ // $p_option : the option value.
+ // Return Values :
+ // The option text value.
+ // --------------------------------------------------------------------------------
+ function PclZipUtilOptionText($p_option)
+ {
+ //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilOptionText", "option='".$p_option."'");
+
+ $v_list = get_defined_constants();
+ for (reset($v_list); $v_key = key($v_list); next($v_list)) {
+ $v_prefix = substr($v_key, 0, 10);
+ if (( ($v_prefix == 'PCLZIP_OPT')
+ || ($v_prefix == 'PCLZIP_CB_')
+ || ($v_prefix == 'PCLZIP_ATT'))
+ && ($v_list[$v_key] == $p_option)) {
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_key);
+ return $v_key;
+ }
+ }
+
+ $v_result = 'Unknown';
+
+ //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+ return $v_result;
+ }
+ // --------------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------------
+ // Function : PclZipUtilTranslateWinPath()
+ // Description :
+ // Translate windows path by replacing '\' by '/' and optionally removing
+ // drive letter.
+ // Parameters :
+ // $p_path : path to translate.
+ // $p_remove_disk_letter : true | false
+ // Return Values :
+ // The path translated.
+ // --------------------------------------------------------------------------------
+ function PclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter=true)
+ {
+ if (stristr(php_uname(), 'windows')) {
+ // ----- Look for potential disk letter
+ if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) {
+ $p_path = substr($p_path, $v_position+1);
+ }
+ // ----- Change potential windows directory separator
+ if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
+ $p_path = strtr($p_path, '\\', '/');
+ }
+ }
+ return $p_path;
+ }
+ // --------------------------------------------------------------------------------
+
+
+?>
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/inc/repo.class.php b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/inc/repo.class.php
new file mode 100644
index 000000000..04dc75675
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/inc/repo.class.php
@@ -0,0 +1,51 @@
+<?php
+class repo_indexmenu_plugin {
+ /**
+ * Send a zipped theme
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+
+ function send_theme ($file) {
+ require_once(DOKU_PLUGIN.'indexmenu/syntax/indexmenu.php');
+ $idxm=new syntax_plugin_indexmenu_indexmenu();
+ //clean the file name
+ $file=cleanID($file);
+ //check config
+ if(!$idxm->getConf('be_repo') || empty($file)) return false;
+ $repodir=INDEXMENU_IMG_ABSDIR."/repository";
+ $zipfile=$repodir."/$file.zip";
+ $localtheme=INDEXMENU_IMG_ABSDIR."/$file/";
+ //theme does not exists
+ if (!file_exists($localtheme)) return false;
+ if (!io_mkdir_p($repodir)) return false;
+ $lm=@filemtime($zipfile);
+ //no cached zip or older than 1 day
+ if ($lm < time()-(60*60*24)) {
+ //create the zip
+ require_once(DOKU_PLUGIN."indexmenu/inc/pclzip.lib.php");
+ @unlink($zipfile);
+ $zip=new PclZip($zipfile);
+ $status=$zip->add($localtheme,PCLZIP_OPT_REMOVE_ALL_PATH);
+ //error
+ if ($status == 0) return false;
+ }
+ $len = (int) filesize($zipfile);
+ //don't send large zips
+ if ($len > 2*1024*1024) return false;
+ //headers
+ header('Cache-Control: must-revalidate, no-transform, post-check=0, pre-check=0');
+ header('Pragma: public');
+ header('Content-Type: application/zip');
+ header('Content-Disposition: attachment; filename="'.basename($zipfile).'";');
+ header("Content-Transfer-Encoding: binary");
+ //send zip
+ $fp=@fopen($zipfile, 'rb');
+ if ($fp) {
+ $ct=@fread($fp, $len);
+ print $ct;
+ }
+ @fclose($fp);
+ return true;
+ }
+}
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/indexmenu-full.js b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/indexmenu-full.js
new file mode 100644
index 000000000..7c60ceffe
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/indexmenu-full.js
@@ -0,0 +1,640 @@
+/*----------------------------------------------------|
+ | dTree 2.05 | www.destroydrop.com/javascript/tree/ |
+ |---------------------------------------------------|
+ | Copyright (c) 2002-2003 Geir Landro |
+ | |
+ | This script can be used freely as long as all |
+ | copyright messages are intact. |
+ | |
+ | Updated: 17.04.2003 |
+ |---------------------------------------------------|
+ | Modified for Dokuwiki by |
+ | Samuele Tognini <samuele@netsons.org> |
+ | under GPL 2 license |
+ | (http://www.gnu.org/licenses/gpl.html) |
+ | Updated: 29.08.2009 |
+ |---------------------------------------------------|
+ | indexmenu | wiki.splitbrain.org/plugin:indexmenu |
+ |--------------------------------------------------*/
+
+// Node object
+function Node(dokuid, id, pid, name, hns, isdir, ajax) {
+ this.dokuid = dokuid;
+ this.id = id;
+ this.pid = pid;
+ this.name = name;
+ this.hns = hns;
+ this.isdir = isdir;
+ this.ajax = ajax;
+ this._io = 0;
+ this._is = false;
+ this._ls = false;
+ this._hc = ajax;
+ this._ai = 0;
+ this._p = false;
+ this._lv = 0;
+ this._ok = false;
+ this._cp=false;
+}
+// Tree object
+function dTree(objName,theme) {
+ var objExt = indexmenu_findExt(theme);
+ this.config = {
+ urlbase:DOKU_BASE+'doku.php?id=',
+ plugbase:DOKU_BASE+'lib/plugins/indexmenu',
+ useCookies: true,
+ scroll:true,
+ toc:true,
+ maxjs:1,
+ jsajax:'',
+ sepchar:':',
+ theme:theme
+ };
+ var objImg=this.config.plugbase+'/images/'+theme+'/';
+ this.icon = {
+ root: objImg + 'base.'+objExt,
+ folder: objImg + 'folder.'+objExt,
+ folderH: objImg + 'folderh.'+objExt,
+ folderOpen: objImg + 'folderopen.'+objExt,
+ folderHOpen: objImg + 'folderhopen.'+objExt,
+ node: objImg + 'page.'+objExt,
+ empty: objImg + 'empty.'+objExt,
+ line: objImg + 'line.'+objExt,
+ join: objImg + 'join.'+objExt,
+ joinBottom: objImg + 'joinbottom.'+objExt,
+ plus: objImg + 'plus.'+objExt,
+ plusBottom: objImg + 'plusbottom.'+objExt,
+ minus: objImg + 'minus.'+objExt,
+ minusBottom: objImg + 'minusbottom.'+objExt,
+ nlPlus: objImg + 'nolines_plus.'+objExt,
+ nlMinus: objImg + 'nolines_minus.'+objExt
+ };
+ this.obj = objName;
+ this.aNodes = [];
+ this.aIndent = [];
+ this.root = new Node(false,-1);
+ this.selectedNode = null;
+ this.selectedFound = false;
+ this.completed = false;
+ this.scrllTmr=0;
+ this.pageid=window.indexmenu_ID||'';
+ this.fajax=false;
+}
+
+// Adds a new node to the node array
+dTree.prototype.add = function(dokuid, id, pid, name, hns, isdir, ajax) {
+ this.aNodes[this.aNodes.length] = new Node(dokuid, id, pid, name, hns, isdir, ajax);
+};
+
+// Open/close all nodes
+dTree.prototype.openAll = function() {
+ if (!this.getCookie('co' + this.obj)) {
+ this.oAll(true);
+ }
+};
+
+// Outputs the tree to the page
+dTree.prototype.toString = function() {
+ var str='';
+ if (this.config.scroll) {str += '<div id="cdtree_'+this.obj+'" class="dtree" style="position:relative;overflow:hidden;width:100%;">';}
+ str += '<div id="dtree_'+this.obj+'" class="dtree '+this.config.theme+'" style="overflow:';
+ if (this.config.scroll) { str += 'visible;position:relative;width:100%"';} else {str += 'hidden;"';}
+ str += '>';
+ if (DOKUid('dtree_'+this.obj)) {str += '<div class="error">Indexmenu id conflict</div>';}
+ if (this.config.toc) {
+ str += '<div id="t' + this.obj + '" class="indexmenu_tocbullet '+this.config.theme+'" style="display:none;" title="Table of contents"></div>';
+ str += '<div id="toc_' + this.obj + '" style="display:none;"></div>';
+ }
+ if (this.config.useCookies) { this.selectedNode = this.getSelected(); }
+ str += this.addNode(this.root)+'</div>';
+ if (this.config.scroll) {
+ str += '<div id="z' + this.obj + '" class="indexmenu_rarrow"></div>';
+ str += '<div id="left_'+this.obj+'" class="indexmenu_larrow" style="display:none;" title="Click to scroll back" onmousedown="javascript:'+this.obj+'.scroll(\'r\',1);" onmouseup="javascript:'+this.obj+'.stopscroll();"></div>';
+ str += '</div>';
+ }
+ this.completed = true;
+ this.divdisplay('nojs_',0);
+ return str;
+};
+
+// Creates the tree structure
+dTree.prototype.addNode = function(pNode) {
+ var str = '',cn,n=pNode._ai,l=pNode._lv+1;
+ for (n; n<this.aNodes.length; n++) {
+ if (this.aNodes[n].pid == pNode.id) {
+ cn = this.aNodes[n];
+ cn._p = pNode;
+ cn._ai = n;
+ cn._lv=l;
+ this.setCS(cn);
+ if (cn._hc && !cn._io && this.config.useCookies) {cn._io = this.isOpen(cn.id);}
+ if (this.pageid == (!cn.hns && cn.dokuid || cn.hns)) {
+ cn._cp=true;
+ } else if (cn.id == this.selectedNode && !this.selectedFound) {
+ cn._is = true;
+ this.selectedNode = n;
+ this.selectedFound = true;
+ }
+ if (!cn._hc && cn.isdir && !cn.ajax && !cn.hns) {
+ if (cn._ls) {str += this.noderr(cn, n);}
+ } else {
+ str += this.node(cn, n);
+ }
+ if (cn._ls) {break;}
+ }
+ }
+ return str;
+};
+
+dTree.prototype.noderr = function(node, nodeId) {
+ var str = '<div class="dTreeNode">' + this.indent(node, nodeId);
+ str += '<div class="emptynode" title="Empty"></div></div>';
+ return str;
+};
+
+// Creates the node icon, url and text
+dTree.prototype.node = function(node, nodeId) {
+ var h=1,jsfnc,str;
+ jsfnc='onmouseover="'+this.obj+'.show_feat(\''+nodeId+'\');" onmousedown="return indexmenu_checkcontextm(\''+nodeId+'\','+this.obj+',event);" oncontextmenu="return indexmenu_stopevt(event)"';
+ if (node._lv > this.config.maxjs) {h=0;} else {node._ok=true;}
+ str = '<div class="dTreeNode">' + this.indent(node, nodeId);
+ node.icon = (this.root.id == node.pid) ? this.icon.root : ((node.hns) ? this.icon.folderH : ((node._hc) ? this.icon.folder : this.icon.node));
+ node.iconOpen = (node._hc) ? ((node.hns) ? this.icon.folderHOpen : this.icon.folderOpen) : this.icon.node;
+ if (this.root.id == node.pid) {
+ node.icon = this.icon.root;
+ node.iconOpen = this.icon.root;
+ }
+ str += '<img id="i' + this.obj + nodeId + '" src="' + ((node._io) ? node.iconOpen : node.icon) + '" alt="" />';
+ if (!node._hc || node.hns) {
+ str += '<a id="s' + this.obj + nodeId + '" class="' + ((node._cp) ? 'navSel' : ((node._is) ? 'nodeSel' : (node._hc) ? 'nodeFdUrl' : 'nodeUrl')) ;
+ str += '" href="' + this.config.urlbase;
+ (node.hns) ? str +=node.hns : str += node.dokuid;
+ str += '"' + ' title="' + node.name + '"' +jsfnc;
+ str += ' onclick="javascript: ' + this.obj + '.s(' + nodeId + ');"';
+ str += '>'+node.name+'</a>';
+ }
+ else if (node.pid != this.root.id) {
+ str += '<a id="s' + this.obj + nodeId + '" href="javascript: ' + this.obj + '.o(' + nodeId + '); " class="node"' + jsfnc + '>'+node.name+'</a>';
+ } else {
+ str += node.name;
+ }
+ str += '</div>';
+ if (node._hc) {
+ str += '<div id="d' + this.obj + nodeId + '" class="clip" style="display:' + ((this.root.id == node.pid || node._io) ? 'block' : 'none') + ';">';
+ if (h) {str += this.addNode(node);}
+ str += '</div>';
+ }
+ this.aIndent.pop();
+ return str;
+};
+
+// Adds the empty and line icons
+dTree.prototype.indent = function(node, nodeId) {
+ var n,str = '';
+ if (this.root.id != node.pid) {
+ for (n=0; n<this.aIndent.length; n++) {
+ str += '<img src="' + ( (this.aIndent[n] == 1) ? this.icon.line : this.icon.empty ) + '" alt="" />';
+ }
+ if (node._ls) {
+ this.aIndent.push(0);
+ } else {
+ this.aIndent.push(1);
+ }
+ if (node._hc) {
+ str += '<a href="javascript: ' + this.obj + '.o(' + nodeId+');"><img id="j' + this.obj + nodeId + '" src="';
+ str += ( (node._io) ? ((node._ls) ? this.icon.minusBottom : this.icon.minus) : ((node._ls) ? this.icon.plusBottom : this.icon.plus ) );
+ str += '" alt="" /></a>';
+ } else {str += '<img src="' + ((node._ls) ? this.icon.joinBottom : this.icon.join) + '" alt="" />';}
+ }
+ return str;
+};
+
+// Checks if a node has any children and if it is the last sibling
+dTree.prototype.setCS = function(node) {
+ var lastId,n;
+ for (n=0; n<this.aNodes.length; n++) {
+ if (this.aNodes[n].pid == node.id) {node._hc = true;}
+ if (this.aNodes[n].pid == node.pid) {lastId = this.aNodes[n].id;}
+ }
+ if (lastId==node.id) {node._ls = true;}
+};
+
+// Returns the selected node
+dTree.prototype.getSelected = function() {
+ var sn = this.getCookie('cs' + this.obj);
+ return (sn) ? sn : null;
+};
+
+// Highlights the selected node
+dTree.prototype.s = function(id) {
+ var eOld,eNew,cn = this.aNodes[id];
+ if (this.selectedNode != id) {
+ eNew = DOKUid("s" + this.obj + id);
+ if (!eNew ) {return;}
+ if (this.selectedNode || this.selectedNode===0) {
+ eOld = DOKUid("s" + this.obj + this.selectedNode);
+ eOld.className = "node";
+ }
+ eNew.className = "nodeSel";
+ this.selectedNode = id;
+ if (this.config.useCookies) {this.setCookie('cs' + this.obj, cn.id);}
+ }
+};
+
+// Toggle Open or close
+dTree.prototype.o = function(id) {
+ var cn = this.aNodes[id];
+ this.nodeStatus(!cn._io, id, cn._ls);
+ cn._io = !cn._io;
+ if (this.config.useCookies) {this.updateCookie();}
+ this.divdisplay('z',0);
+ this.resizescroll("block");
+};
+
+// Open or close all nodes
+dTree.prototype.oAll = function(status) {
+ for (var n=0; n<this.aNodes.length; n++) {
+ if (this.aNodes[n]._hc && this.aNodes[n].pid != this.root.id) {
+ this.nodeStatus(status, n, this.aNodes[n]._ls);
+ this.aNodes[n]._io = status;
+ }
+ }
+ if (this.config.useCookies) {this.updateCookie();}
+};
+
+// Opens the tree to a specific node
+dTree.prototype.openTo = function(nId, bSelect, bFirst) {
+ var n,cn;
+ if (!bFirst) {
+ for (n=0; n<this.aNodes.length; n++) {
+ if (this.aNodes[n].id == nId) {
+ nId=n;
+ break;
+ }
+ }
+ }
+ this.fill(this.aNodes[nId].pid);
+ cn=this.aNodes[nId];
+ if (cn.pid==this.root.id || !cn._p) {return;}
+ cn._io = 1;
+ if (this.completed && cn._hc) {this.nodeStatus(true, cn._ai, cn._ls);}
+ if (cn._is) {
+ (this.completed) ? this.s(cn._ai) : this._sn=cn._ai;
+ }
+ this.openTo(cn._p._ai, false, true);
+};
+
+dTree.prototype.getOpenTo = function(nodes) {
+ if (nodes === '') {
+ this.openAll();
+ } else if (!this.config.useCookies ||!this.getCookie('co' + this.obj)) {
+ for (var n=0; n<nodes.length; n++) {
+ this.openTo(nodes[n],false,true);
+ }
+ }
+};
+
+// Change the status of a node(open or closed)
+dTree.prototype.nodeStatus = function(status, id, bottom) {
+ if (status && !this.fill(id)) {return;}
+ var eJoin,eIcon;
+ eJoin= DOKUid('j' + this.obj + id);
+ eIcon= DOKUid('i' + this.obj + id);
+ eIcon.src = (status) ? this.aNodes[id].iconOpen : this.aNodes[id].icon;
+ eJoin.src = ((status)?((bottom)?this.icon.minusBottom:this.icon.minus):((bottom)?this.icon.plusBottom:this.icon.plus));
+ DOKUid('d' + this.obj + id).style.display = (status) ? 'block': 'none';
+};
+
+// [Cookie] Clears a cookie
+dTree.prototype.clearCookie = function() {
+ var now,yday;
+ now = new Date();
+ yday = new Date(now.getTime() - 1000 * 60 * 60 * 24);
+ this.setCookie('co'+this.obj, 'cookieValue', yday);
+ this.setCookie('cs'+this.obj, 'cookieValue', yday);
+};
+
+// [Cookie] Sets value in a cookie
+dTree.prototype.setCookie = function(cookieName, cookieValue, expires, path, domain, secure) {
+ document.cookie =
+ escape(cookieName) + '=' + escape(cookieValue) +
+ (expires ? '; expires=' + expires.toGMTString() : '') +
+ ';path=/' +
+ (domain ? '; domain=' + domain : '') +
+ (secure ? '; secure' : '');
+};
+
+// [Cookie] Gets a value from a cookie
+dTree.prototype.getCookie = function(cookieName) {
+ var cookieValue = '',pN,posValue,endPos;
+ pN = document.cookie.indexOf(escape(cookieName) + '=');
+ if (pN != -1) {
+ posValue = pN + (escape(cookieName) + '=').length;
+ endPos = document.cookie.indexOf(';', posValue);
+ if (endPos != -1) {cookieValue = unescape(document.cookie.substring(posValue, endPos));}
+ else {cookieValue = unescape(document.cookie.substring(posValue));}
+ }
+ return (cookieValue);
+};
+
+// [Cookie] Returns ids of open nodes as a string
+dTree.prototype.updateCookie = function() {
+ var str = '',n;
+ for (n=0; n<this.aNodes.length; n++) {
+ if (this.aNodes[n]._io && this.aNodes[n].pid != this.root.id) {
+ if (str) {str += '.';}
+ str += this.aNodes[n].id;
+ }
+ }
+ this.setCookie('co' + this.obj, str);
+};
+
+// [Cookie] Checks if a node id is in a cookie
+dTree.prototype.isOpen = function(id) {
+ var n,aOpen = this.getCookie('co' + this.obj).split('.');
+ for (n=0; n<aOpen.length; n++){
+ if (aOpen[n] == id) {return true;}
+ }
+ return false;
+};
+
+dTree.prototype.openCurNS = function (max){
+ var r,cn,match,t,i,n,cnsa,cna,cns=this.pageid;
+ r=new RegExp ("\\b"+this.config.sepchar+"\\b","g");
+ match=cns.match(r)||-1;
+ if (max>0 && match.length >= max) {
+ t = cns.split(this.config.sepchar);
+ n = (this.aNodes[0].dokuid == '') ? 0 :this.aNodes[0].dokuid.split(this.config.sepchar).length;
+ t.splice(max + n,t.length);
+ cnsa=t.join(this.config.sepchar);
+ }
+ for (i=0; i<this.aNodes.length; i++){
+ cn=this.aNodes[i];
+ if (cns == cn.dokuid || cns == cn.hns) {
+ this.openTo(cn.id,false,true);
+ this.fajax=false;
+ if (cn.pid >= 0) {
+ addInitEvent(this.scroll("l",4,cn.pid,1));
+ }
+ break;
+ }
+ if (cnsa == cn.dokuid || cnsa == cn.hns) {
+ cna=cn;
+ this.fajax=true;
+ }
+ }
+ if (cna) {this.openTo(cna.id,false,true);}
+};
+
+dTree.prototype.fill = function(id) {
+ if (id == -1 || this.aNodes[id]._ok ) {return true;}
+ var n=id,eLoad,node,a,rd,ln,eDiv;
+ if (this.aNodes[n].ajax) {
+ eLoad=DOKUid('l' + this.obj);
+ node=DOKUid('s'+this.obj+n);
+ if (!eLoad) {eLoad=indexmenu_createPicker('l' + this.obj);}
+ eLoad.innerHTML='Loading ...';
+ DOKUid('s'+this.obj+n).parentNode.appendChild(eLoad);
+ eLoad.style.width='auto';
+ eLoad.style.display='inline';
+ this.getAjax(n);
+ return true;
+ }
+ rd = [];
+ while (!this.aNodes[n]._ok) {
+ rd[rd.length]=n;
+ n=this.aNodes[n].pid;
+ }
+ for (ln=rd.length-1; ln>=0; ln--) {
+ id=rd[ln];
+ a=this.aNodes[id];
+ eDiv=DOKUid('d' + this.obj + id);
+ if (!eDiv) {return false;}
+ this.aIndent = [];
+ n=a;
+ while (n.pid>=0) {
+ if (n._ls) {
+ this.aIndent.unshift(0);
+ } else {
+ this.aIndent.unshift(1);
+ }
+ n=n._p;
+ }
+ eDiv.innerHTML=this.addNode(a);
+ a._ok=true;
+ }
+ return true;
+};
+
+dTree.prototype.openCookies = function() {
+ var n,cn,aOpen = this.getCookie('co' + this.obj).split('.');
+ for (n=0; n<aOpen.length; n++){
+ if (aOpen[n] === "") {break;}
+ cn = this.aNodes[aOpen[n]];
+ if (!cn._ok) {this.nodeStatus(true, aOpen[n], cn._ls);cn._io = 1;}
+ }
+};
+
+dTree.prototype.scroll = function (where,s,n,i){
+ if (!this.config.scroll) {return false;}
+ var w,dtree,dtreel,nodeId;
+ dtree=DOKUid('dtree_'+this.obj);
+ dtreel=parseInt(dtree.offsetLeft,0);
+ if (where=="r") {
+ DOKUid('left_'+this.obj).style.border="thin inset";
+ this.scrollRight(dtreel,s);
+ } else {
+ nodeId=DOKUid('s'+this.obj+n);
+ w = parseInt(dtree.parentNode.offsetWidth - nodeId.offsetWidth - nodeId.offsetLeft,0);
+ if (this.config.toc) {w=w-11;}
+ if (dtreel <= w) {return;}
+ this.resizescroll("none");
+ this.stopscroll();
+ this.scrollLeft(dtreel,s,w-3,i);
+ }
+};
+
+dTree.prototype.scrollLeft = function (lft,s,w,i){
+ if(lft < w - i -10) {
+ this.divdisplay('z',0);
+ this.scrllTmr=0;
+ return;
+ }
+ var self=this;
+ DOKUid('dtree_'+self.obj).style.left = lft + "px";
+ this.scrllTmr=setTimeout(function (){self.scrollLeft(lft - s,s+i,w,i);},20);
+};
+
+//Scroll Back
+dTree.prototype.scrollRight = function (lft,s){
+ if(lft >= s) {
+ this.divdisplay('left_',0);
+ this.stopscroll();
+ return;
+ }
+ var self=this;
+ DOKUid('dtree_'+self.obj).style.left = lft + "px";
+ if (lft>-15) {s=1;}
+ this.scrllTmr=setTimeout(function (){self.scrollRight(lft+s,s+1);},20);
+};
+
+dTree.prototype.stopscroll = function (){
+ DOKUid('left_'+this.obj).style.border="none";
+ clearTimeout(this.scrllTmr);
+ this.scrllTmr=0;
+};
+
+dTree.prototype.show_feat = function (n){
+ var w,div,id,dtree,dtreel,self,node=DOKUid('s'+this.obj+n);
+ self=this;
+ if (this.config.toc && node.className != "node") {
+ div=DOKUid('t'+this.obj);
+ id =(this.aNodes[n].hns) ? this.aNodes[n].hns : this.aNodes[n].dokuid;
+ div.onmousedown=function (){indexmenu_createTocMenu('req=toc&id='+decodeURIComponent(id),'picker_'+self.obj,'t'+self.obj);};
+ node.parentNode.appendChild(div);
+ if (div.style.display=="none") {div.style.display="inline";}
+ }
+ if (this.config.scroll) {
+ div=DOKUid('z'+this.obj);
+ div.onmouseover=function(){div.style.border="none";self.scroll("l",1,n,0);};
+ div.onmousedown=function(){div.style.border="thin inset";self.scroll("l",4,n,1);};
+ div.onmouseout=function(){div.style.border="none";self.stopscroll();};
+ div.onmouseup=div.onmouseover;
+ dtree=DOKUid('dtree_'+this.obj);
+ dtreel=parseInt(dtree.offsetLeft,0);
+ w = parseInt(dtree.parentNode.offsetWidth - node.offsetWidth - node.offsetLeft + 1,0);
+ if (dtreel > w) {
+ div.style.display="none";
+ div.style.top = node.offsetTop+"px";
+ div.style.left = parseInt(node.offsetLeft + node.offsetWidth + w - 12,0)+"px";
+ div.style.display="block";
+ }
+ }
+};
+
+dTree.prototype.resizescroll = function (status){
+ var dtree,w,h,left=DOKUid('left_'+this.obj);
+ if (!left) {return;}
+ if (left.style.display==status) {
+ dtree=DOKUid('dtree_'+this.obj);
+ w=parseInt(dtree.offsetHeight/3,0);
+ h= parseInt(w/50,0)*50;
+ if (h < 50) {h=50;}
+ left.style.height=h+"px";
+ left.style.top = w+"px";
+ if (status=="none") {left.style.display="block";}
+ }
+};
+
+// Toggle Open or close
+dTree.prototype.getAjax = function(n) {
+ var node,req,curns,selft=this;
+ node=selft.aNodes[n];
+ // We use SACK to do the AJAX requests
+ var Ajax = new sack(DOKU_BASE+'lib/plugins/indexmenu/ajax.php');
+ req='req=index&idx='+node.dokuid+decodeURIComponent(this.config.jsajax);
+ curns=this.pageid.substring(0,this.pageid.lastIndexOf(this.config.sepchar));
+ Ajax.encodeURIString=false;
+ Ajax.onCompletion = function(){
+ var i,ajxnodes,ajxnode,plus;
+ plus=selft.aNodes.length -1;
+ eval(this.response);
+ if (!isArray(ajxnodes) || ajxnodes.length < 1) {
+ ajxnodes=[['', 1, 0, '', 0, 1, 0]];
+ }
+ node.ajax=false;
+ for(i=0;i<ajxnodes.length;i++){
+ ajxnode=ajxnodes[i];
+ ajxnode[2]=(ajxnode[2]==0) ? node.id : ajxnode[2] + plus;
+ ajxnode[1] += plus;
+ selft.add(ajxnode[0],ajxnode[1],ajxnode[2],ajxnode[3],ajxnode[4],ajxnode[5],ajxnode[6]);
+ }
+ if (selft.fajax) {
+ selft.fajax=false;
+ selft.openCurNS(0);
+ } else {
+ selft.openTo(node.id,false,true);
+ }
+ DOKUid('l'+selft.obj).style.display='none';
+ };
+ if (this.fajax) {
+ req +='&nss='+curns+'&max=1';
+ }
+ Ajax.encodeURIString = false;
+ Ajax.runAJAX(encodeURI(req));
+};
+
+//Load custom css
+dTree.prototype.loadCss = function() {
+ var oLink = document.createElement("link");
+ oLink.href = this.config.plugbase+'/images/'+this.config.theme+'/style.css';
+ oLink.rel = "stylesheet";
+ oLink.type = "text/css";
+ document.getElementsByTagName('head')[0].appendChild(oLink);
+};
+
+//Right click
+dTree.prototype.contextmenu = function(n,e) {
+ var li,id,html,type,node,self,cmenu,cdtree,rmenu,X=0,Y=0,i;
+ cdtree= DOKUid("cdtree_" + this.obj);
+ rmenu=DOKUid('r' + this.obj);
+ if(!rmenu) { return true; }
+ indexmenu_mouseposition(rmenu,e);
+ cmenu=window.indexmenu_contextmenu[0];
+ node =this.aNodes[n];
+ self=this;
+ rmenu.innerHTML='<div class="indexmenu_rmenuhead" title="'+node.name+'">'+node.name+"</div>";
+ for (i=0; i<cmenu.length; i++,i++,i++,i++) {
+ if (((!node._hc || node.hns) && !cmenu[i+2])||(node._hc && !node.hns && !cmenu[i+3])) {continue;}
+ html=cmenu[i];
+ if (cmenu[i+1]) {
+ type='li';
+ id =(node.hns) ? node.hns : node.dokuid;
+ html='<a title="'+cmenu[i]+'" href="'+eval(cmenu[i+1])+'">'+html+'</a>';
+ } else {
+ type='span';
+ rmenu.appendChild(document.createElement('ul'));
+ }
+ li=document.createElement(type);
+ li.innerHTML=html;
+ rmenu.lastChild.appendChild(li);
+ }
+ rmenu.style.display='inline';
+ return false;
+};
+
+dTree.prototype.divdisplay = function(obj,v) {
+ var o=DOKUid(obj+this.obj);
+ if (!o) {return false;}
+ (v) ? o.style.display='inline': o.style.display='none' ;
+};
+
+dTree.prototype.init = function(s,c,n,nav,max) {
+ if (s) {this.loadCss();}
+ if (!c) {this.openCookies();}
+ if (n) {this.getOpenTo(n.split(" "));}
+ if (nav) {this.openCurNS(max);}
+ if (window.indexmenu_contextmenu) {
+ var self = this;
+ indexmenu_createPicker('r'+ this.obj,'indexmenu_rmenu '+this.config.theme);
+ DOKUid('r'+ this.obj).oncontextmenu=indexmenu_stopevt;
+ addEvent(document, 'click', function() {self.divdisplay('r',0);});
+ }
+};
+
+// If Push and pop is not implemented by the browser
+if (!Array.prototype.push) {
+ Array.prototype.push = function array_push() {
+ for(var i=0;i<arguments.length;i++){
+ this[this.length]=arguments[i];
+ }
+ return this.length;
+ };
+}
+if (!Array.prototype.pop) {
+ Array.prototype.pop = function array_pop() {
+ var lstEl = this[this.length-1];
+ this.length = Math.max(this.length-1,0);
+ return lstEl;
+ };
+}
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/indexmenu.js b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/indexmenu.js
new file mode 100644
index 000000000..ce5937c3d
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/indexmenu.js
@@ -0,0 +1,18 @@
+/*----------------------------------------------------|
+ | dTree 2.05 | www.destroydrop.com/javascript/tree/ |
+ |---------------------------------------------------|
+ | Copyright (c) 2002-2003 Geir Landro |
+ | |
+ | This script can be used freely as long as all |
+ | copyright messages are intact. |
+ | |
+ | Updated: 17.04.2003 |
+ |---------------------------------------------------|
+ | Modified for Dokuwiki by |
+ | Samuele Tognini <samuele@netsons.org> |
+ | under GPL 2 license |
+ | (http://www.gnu.org/licenses/gpl.html) |
+ | Updated: 29.08.2009 |
+ |---------------------------------------------------|
+ | indexmenu | wiki.splitbrain.org/plugin:indexmenu |
+ |--------------------------------------------------*/ function Node(g,f,e,d,c,b,a){this.dokuid=g;this.id=f;this.pid=e;this.name=d;this.hns=c;this.isdir=b;this.ajax=a;this._io=0;this._is=false;this._ls=false;this._hc=a;this._ai=0;this._p=false;this._lv=0;this._ok=false;this._cp=false;}function dTree(d,c){var b=indexmenu_findExt(c);this.config={urlbase:DOKU_BASE+"doku.php?id=",plugbase:DOKU_MEDIA+"lib/plugins/indexmenu",useCookies:true,scroll:true,toc:true,maxjs:1,jsajax:"",sepchar:":",theme:c};var a=this.config.plugbase+"/images/"+c+"/";this.icon={root:a+"base."+b,folder:a+"folder."+b,folderH:a+"folderh."+b,folderOpen:a+"folderopen."+b,folderHOpen:a+"folderhopen."+b,node:a+"page."+b,empty:a+"empty."+b,line:a+"line."+b,join:a+"join."+b,joinBottom:a+"joinbottom."+b,plus:a+"plus."+b,plusBottom:a+"plusbottom."+b,minus:a+"minus."+b,minusBottom:a+"minusbottom."+b,nlPlus:a+"nolines_plus."+b,nlMinus:a+"nolines_minus."+b};this.obj=d;this.aNodes=[];this.aIndent=[];this.root=new Node(false,-1);this.selectedNode=null;this.selectedFound=false;this.completed=false;this.scrllTmr=0;this.pageid=window.indexmenu_ID||"";this.fajax=false;}dTree.prototype.add=(function(g,f,e,d,c,b,a){this.aNodes[this.aNodes.length]=new Node(g,f,e,d,c,b,a);});dTree.prototype.openAll=(function(){if(!this.getCookie("co"+this.obj)){this.oAll(true);}});dTree.prototype.toString=(function(){var str="";if(this.config.scroll){str+="<div id=\"cdtree_"+this.obj+"\" class=\"dtree\" style=\"position:relative;overflow:hidden;width:100%;\">";}str+="<div id=\"dtree_"+this.obj+"\" class=\"dtree "+this.config.theme+"\" style=\"overflow:";if(this.config.scroll){str+="visible;position:relative;width:100%\"";}else{str+="hidden;\"";}str+=">";if(DOKUid("dtree_"+this.obj)){str+="<div class=\"error\">Indexmenu id conflict</div>";}if(this.config.toc){str+="<div id=\"t"+this.obj+"\" class=\"indexmenu_tocbullet "+this.config.theme+"\" style=\"display:none;\" title=\"Table of contents\"></div>";str+="<div id=\"toc_"+this.obj+"\" style=\"display:none;\"></div>";}if(this.config.useCookies){this.selectedNode=this.getSelected();}str+=this.addNode(this.root)+"</div>";if(this.config.scroll){str+="<div id=\"z"+this.obj+"\" class=\"indexmenu_rarrow\"></div>";str+="<div id=\"left_"+this.obj+"\" class=\"indexmenu_larrow\" style=\"display:none;\" title=\"Click to scroll back\" onmousedown=\"javascript:"+this.obj+".scroll('r',1);\" onmouseup=\"javascript:"+this.obj+".stopscroll();\"></div>";str+="</div>";}this.completed=true;this.divdisplay("nojs_",0);return str;});dTree.prototype.addNode=(function(pNode){var str="",cn,n=pNode._ai,l=pNode._lv+1;for(n;n<this.aNodes.length;n++){if(this.aNodes[n].pid==pNode.id){cn=this.aNodes[n];cn._p=pNode;cn._ai=n;cn._lv=l;this.setCS(cn);if(cn._hc&&!cn._io&&this.config.useCookies){cn._io=this.isOpen(cn.id);}if(this.pageid==(!cn.hns&&cn.dokuid||cn.hns)){cn._cp=true;}else{if(cn.id==this.selectedNode&&!this.selectedFound){cn._is=true;this.selectedNode=n;this.selectedFound=true;}}if(!cn._hc&&cn.isdir&&!cn.ajax&&!cn.hns){if(cn._ls){str+=this.noderr(cn,n);}}else{str+=this.node(cn,n);}if(cn._ls){break;}}}return str;});dTree.prototype.noderr=(function(node,nodeId){var str="<div class=\"dTreeNode\">"+this.indent(node,nodeId);str+="<div class=\"emptynode\" title=\"Empty\"></div></div>";return str;});dTree.prototype.node=(function(node,nodeId){var h=1,jsfnc,str;jsfnc="onmouseover=\""+this.obj+".show_feat('"+nodeId+"');\" onmousedown=\"return indexmenu_checkcontextm('"+nodeId+"',"+this.obj+",event);\" oncontextmenu=\"return indexmenu_stopevt(event)\"";if(node._lv>this.config.maxjs){h=0;}else{node._ok=true;}str="<div class=\"dTreeNode\">"+this.indent(node,nodeId);node.icon=(this.root.id==node.pid)?this.icon.root:((node.hns)?this.icon.folderH:((node._hc)?this.icon.folder:this.icon.node));node.iconOpen=(node._hc)?((node.hns)?this.icon.folderHOpen:this.icon.folderOpen):this.icon.node;if(this.root.id==node.pid){node.icon=this.icon.root;node.iconOpen=this.icon.root;}str+="<img id=\"i"+this.obj+nodeId+"\" src=\""+((node._io)?node.iconOpen:node.icon)+"\" alt=\"\" />";if(!node._hc||node.hns){str+="<a id=\"s"+this.obj+nodeId+"\" class=\""+((node._cp)?"navSel":((node._is)?"nodeSel":(node._hc)?"nodeFdUrl":"nodeUrl"));str+="\" href=\""+this.config.urlbase;(node.hns)?str+=node.hns:str+=node.dokuid;str+="\" title=\""+node.name+"\""+jsfnc;str+=" onclick=\"javascript: "+this.obj+".s("+nodeId+");\"";str+=">"+node.name+"</a>";}else{if(node.pid!=this.root.id){str+="<a id=\"s"+this.obj+nodeId+"\" href=\"javascript: "+this.obj+".o("+nodeId+"); \" class=\"node\""+jsfnc+">"+node.name+"</a>";}else{str+=node.name;}}str+="</div>";if(node._hc){str+="<div id=\"d"+this.obj+nodeId+"\" class=\"clip\" style=\"display:"+((this.root.id==node.pid||node._io)?"block":"none")+";\">";if(h){str+=this.addNode(node);}str+="</div>";}this.aIndent.pop();return str;});dTree.prototype.indent=(function(node,nodeId){var n,str="";if(this.root.id!=node.pid){for(n=0;n<this.aIndent.length;n++){str+="<img src=\""+((this.aIndent[n]==1)?this.icon.line:this.icon.empty)+"\" alt=\"\" />";}if(node._ls){this.aIndent.push(0);}else{this.aIndent.push(1);}if(node._hc){str+="<a href=\"javascript: "+this.obj+".o("+nodeId+");\"><img id=\"j"+this.obj+nodeId+"\" src=\"";str+=((node._io)?((node._ls)?this.icon.minusBottom:this.icon.minus):((node._ls)?this.icon.plusBottom:this.icon.plus));str+="\" alt=\"\" /></a>";}else{str+="<img src=\""+((node._ls)?this.icon.joinBottom:this.icon.join)+"\" alt=\"\" />";}}return str;});dTree.prototype.setCS=(function(node){var lastId,n;for(n=0;n<this.aNodes.length;n++){if(this.aNodes[n].pid==node.id){node._hc=true;}if(this.aNodes[n].pid==node.pid){lastId=this.aNodes[n].id;}}if(lastId==node.id){node._ls=true;}});dTree.prototype.getSelected=(function(){var sn=this.getCookie("cs"+this.obj);return(sn)?sn:null;});dTree.prototype.s=(function(id){var eOld,eNew,cn=this.aNodes[id];if(this.selectedNode!=id){eNew=DOKUid("s"+this.obj+id);if(!eNew){return;}if(this.selectedNode||this.selectedNode===0){eOld=DOKUid("s"+this.obj+this.selectedNode);eOld.className="node";}eNew.className="nodeSel";this.selectedNode=id;if(this.config.useCookies){this.setCookie("cs"+this.obj,cn.id);}}});dTree.prototype.o=(function(id){var cn=this.aNodes[id];this.nodeStatus(!cn._io,id,cn._ls);cn._io=!cn._io;if(this.config.useCookies){this.updateCookie();}this.divdisplay("z",0);this.resizescroll("block");});dTree.prototype.oAll=(function(status){for(var n=0;n<this.aNodes.length;n++){if(this.aNodes[n]._hc&&this.aNodes[n].pid!=this.root.id){this.nodeStatus(status,n,this.aNodes[n]._ls);this.aNodes[n]._io=status;}}if(this.config.useCookies){this.updateCookie();}});dTree.prototype.openTo=(function(nId,bSelect,bFirst){var n,cn;if(!bFirst){for(n=0;n<this.aNodes.length;n++){if(this.aNodes[n].id==nId){nId=n;break;}}}this.fill(this.aNodes[nId].pid);cn=this.aNodes[nId];if(cn.pid==this.root.id||!cn._p){return;}cn._io=1;if(this.completed&&cn._hc){this.nodeStatus(true,cn._ai,cn._ls);}if(cn._is){(this.completed)?this.s(cn._ai):this._sn=cn._ai;}this.openTo(cn._p._ai,false,true);});dTree.prototype.getOpenTo=(function(nodes){if(nodes===""){this.openAll();}else{if(!this.config.useCookies||!this.getCookie("co"+this.obj)){for(var n=0;n<nodes.length;n++){this.openTo(nodes[n],false,true);}}}});dTree.prototype.nodeStatus=(function(status,id,bottom){if(status&&!this.fill(id)){return;}var eJoin,eIcon;eJoin=DOKUid("j"+this.obj+id);eIcon=DOKUid("i"+this.obj+id);eIcon.src=(status)?this.aNodes[id].iconOpen:this.aNodes[id].icon;eJoin.src=((status)?((bottom)?this.icon.minusBottom:this.icon.minus):((bottom)?this.icon.plusBottom:this.icon.plus));DOKUid("d"+this.obj+id).style.display=(status)?"block":"none";});dTree.prototype.clearCookie=(function(){var now,yday;now=new Date();yday=new Date(now.getTime()-86400000);this.setCookie("co"+this.obj,"cookieValue",yday);this.setCookie("cs"+this.obj,"cookieValue",yday);});dTree.prototype.setCookie=(function(cookieName,cookieValue,expires,path,domain,secure){document.cookie=escape(cookieName)+"="+escape(cookieValue)+(expires?"; expires="+expires.toGMTString():"")+";path=/"+(domain?"; domain="+domain:"")+(secure?"; secure":"");});dTree.prototype.getCookie=(function(cookieName){var cookieValue="",pN,posValue,endPos;pN=document.cookie.indexOf(escape(cookieName)+"=");if(pN!=-1){posValue=pN+(escape(cookieName)+"=").length;endPos=document.cookie.indexOf(";",posValue);if(endPos!=-1){cookieValue=unescape(document.cookie.substring(posValue,endPos));}else{cookieValue=unescape(document.cookie.substring(posValue));}}return(cookieValue);});dTree.prototype.updateCookie=(function(){var str="",n;for(n=0;n<this.aNodes.length;n++){if(this.aNodes[n]._io&&this.aNodes[n].pid!=this.root.id){if(str){str+=".";}str+=this.aNodes[n].id;}}this.setCookie("co"+this.obj,str);});dTree.prototype.isOpen=(function(id){var n,aOpen=this.getCookie("co"+this.obj).split(".");for(n=0;n<aOpen.length;n++){if(aOpen[n]==id){return true;}}return false;});dTree.prototype.openCurNS=(function(max){var r,cn,match,t,i,n,cnsa,cna,cns=this.pageid;r=new RegExp("\\b"+this.config.sepchar+"\\b","g");match=cns.match(r)||-1;if(max>0&&match.length>=max){t=cns.split(this.config.sepchar);n=(this.aNodes[0].dokuid=="")?0:this.aNodes[0].dokuid.split(this.config.sepchar).length;t.splice(max+n,t.length);cnsa=t.join(this.config.sepchar);}for(i=0;i<this.aNodes.length;i++){cn=this.aNodes[i];if(cns==cn.dokuid||cns==cn.hns){this.openTo(cn.id,false,true);this.fajax=false;if(cn.pid>=0){addInitEvent(this.scroll("l",4,cn.pid,1));}break;}if(cnsa==cn.dokuid||cnsa==cn.hns){cna=cn;this.fajax=true;}}if(cna){this.openTo(cna.id,false,true);}});dTree.prototype.fill=(function(id){if(id==-1||this.aNodes[id]._ok){return true;}var n=id,eLoad,node,a,rd,ln,eDiv;if(this.aNodes[n].ajax){eLoad=DOKUid("l"+this.obj);node=DOKUid("s"+this.obj+n);if(!eLoad){eLoad=indexmenu_createPicker("l"+this.obj);}eLoad.innerHTML="Loading ...";DOKUid("s"+this.obj+n).parentNode.appendChild(eLoad);eLoad.style.width="auto";eLoad.style.display="inline";this.getAjax(n);return true;}rd=[];while(!this.aNodes[n]._ok){rd[rd.length]=n;n=this.aNodes[n].pid;}for(ln=rd.length-1;ln>=0;ln--){id=rd[ln];a=this.aNodes[id];eDiv=DOKUid("d"+this.obj+id);if(!eDiv){return false;}this.aIndent=[];n=a;while(n.pid>=0){if(n._ls){this.aIndent.unshift(0);}else{this.aIndent.unshift(1);}n=n._p;}eDiv.innerHTML=this.addNode(a);a._ok=true;}return true;});dTree.prototype.openCookies=(function(){var n,cn,aOpen=this.getCookie("co"+this.obj).split(".");for(n=0;n<aOpen.length;n++){if(aOpen[n]===""){break;}cn=this.aNodes[aOpen[n]];if(!cn._ok){this.nodeStatus(true,aOpen[n],cn._ls);cn._io=1;}}});dTree.prototype.scroll=(function(where,s,n,i){if(!this.config.scroll){return false;}var w,dtree,dtreel,nodeId;dtree=DOKUid("dtree_"+this.obj);dtreel=parseInt(dtree.offsetLeft,0);if(where=="r"){DOKUid("left_"+this.obj).style.border="thin inset";this.scrollRight(dtreel,s);}else{nodeId=DOKUid("s"+this.obj+n);w=parseInt(dtree.parentNode.offsetWidth-nodeId.offsetWidth-nodeId.offsetLeft,0);if(this.config.toc){w=w-11;}if(dtreel<=w){return;}this.resizescroll("none");this.stopscroll();this.scrollLeft(dtreel,s,w-3,i);}});dTree.prototype.scrollLeft=(function(lft,s,w,i){if(lft<w-i-10){this.divdisplay("z",0);this.scrllTmr=0;return;}var self=this;DOKUid("dtree_"+self.obj).style.left=lft+"px";this.scrllTmr=setTimeout((function(){self.scrollLeft(lft-s,s+i,w,i);}),20);});dTree.prototype.scrollRight=(function(lft,s){if(lft>=s){this.divdisplay("left_",0);this.stopscroll();return;}var self=this;DOKUid("dtree_"+self.obj).style.left=lft+"px";if(lft>-15){s=1;}this.scrllTmr=setTimeout((function(){self.scrollRight(lft+s,s+1);}),20);});dTree.prototype.stopscroll=(function(){DOKUid("left_"+this.obj).style.border="none";clearTimeout(this.scrllTmr);this.scrllTmr=0;});dTree.prototype.show_feat=(function(n){var w,div,id,dtree,dtreel,self,node=DOKUid("s"+this.obj+n);self=this;if(this.config.toc&&node.className!="node"){div=DOKUid("t"+this.obj);id=(this.aNodes[n].hns)?this.aNodes[n].hns:this.aNodes[n].dokuid;div.onmousedown=(function(){indexmenu_createTocMenu("req=toc&id="+decodeURIComponent(id),"picker_"+self.obj,"t"+self.obj);});node.parentNode.appendChild(div);if(div.style.display=="none"){div.style.display="inline";}}if(this.config.scroll){div=DOKUid("z"+this.obj);div.onmouseover=(function(){div.style.border="none";self.scroll("l",1,n,0);});div.onmousedown=(function(){div.style.border="thin inset";self.scroll("l",4,n,1);});div.onmouseout=(function(){div.style.border="none";self.stopscroll();});div.onmouseup=div.onmouseover;dtree=DOKUid("dtree_"+this.obj);dtreel=parseInt(dtree.offsetLeft,0);w=parseInt(dtree.parentNode.offsetWidth-node.offsetWidth-node.offsetLeft+1,0);if(dtreel>w){div.style.display="none";div.style.top=node.offsetTop+"px";div.style.left=parseInt(node.offsetLeft+node.offsetWidth+w-12,0)+"px";div.style.display="block";}}});dTree.prototype.resizescroll=(function(status){var dtree,w,h,left=DOKUid("left_"+this.obj);if(!left){return;}if(left.style.display==status){dtree=DOKUid("dtree_"+this.obj);w=parseInt(dtree.offsetHeight/3,0);h=parseInt(w/50,0)*50;if(h<50){h=50;}left.style.height=h+"px";left.style.top=w+"px";if(status=="none"){left.style.display="block";}}});dTree.prototype.getAjax=(function(n){var node,req,curns,selft=this;node=selft.aNodes[n];var Ajax=new sack(DOKU_BASE+"lib/plugins/indexmenu/ajax.php");req="req=index&idx="+node.dokuid+decodeURIComponent(this.config.jsajax);curns=this.pageid.substring(0,this.pageid.lastIndexOf(this.config.sepchar));Ajax.encodeURIString=false;Ajax.onCompletion=(function(){var i,ajxnodes,ajxnode,plus;plus=selft.aNodes.length-1;eval(this.response);if(!isArray(ajxnodes)||ajxnodes.length<1){ajxnodes=[["",1,0,"",0,1,0]];}node.ajax=false;for(i=0;i<ajxnodes.length;i++){ajxnode=ajxnodes[i];ajxnode[2]=(ajxnode[2]==0)?node.id:ajxnode[2]+plus;ajxnode[1]+=plus;selft.add(ajxnode[0],ajxnode[1],ajxnode[2],ajxnode[3],ajxnode[4],ajxnode[5],ajxnode[6]);}if(selft.fajax){selft.fajax=false;selft.openCurNS(0);}else{selft.openTo(node.id,false,true);}DOKUid("l"+selft.obj).style.display="none";});if(this.fajax){req+="&nss="+curns+"&max=1";}Ajax.encodeURIString=false;Ajax.runAJAX(encodeURI(req));});dTree.prototype.loadCss=(function(){var oLink=document.createElement("link");oLink.href=this.config.plugbase+"/images/"+this.config.theme+"/style.css";oLink.rel="stylesheet";oLink.type="text/css";document.getElementsByTagName("head")[0].appendChild(oLink);});dTree.prototype.contextmenu=(function(n,e){var li,id,html,type,node,self,cmenu,cdtree,rmenu,X=0,Y=0,i;cdtree=DOKUid("cdtree_"+this.obj);rmenu=DOKUid("r"+this.obj);if(!rmenu){return true;}indexmenu_mouseposition(rmenu,e);cmenu=window.indexmenu_contextmenu[0];node=this.aNodes[n];self=this;rmenu.innerHTML="<div class=\"indexmenu_rmenuhead\" title=\""+node.name+"\">"+node.name+"</div>";for(i=0;i<cmenu.length;i++,i++,i++,i++){if(((!node._hc||node.hns)&&!cmenu[i+2])||(node._hc&&!node.hns&&!cmenu[i+3])){continue;}html=cmenu[i];if(cmenu[i+1]){type="li";id=(node.hns)?node.hns:node.dokuid;html="<a title=\""+cmenu[i]+"\" href=\""+eval(cmenu[i+1])+"\">"+html+"</a>";}else{type="span";rmenu.appendChild(document.createElement("ul"));}li=document.createElement(type);li.innerHTML=html;rmenu.lastChild.appendChild(li);}rmenu.style.display="inline";return false;});dTree.prototype.divdisplay=(function(obj,v){var o=DOKUid(obj+this.obj);if(!o){return false;}(v)?o.style.display="inline":o.style.display="none";});dTree.prototype.init=(function(s,c,n,nav,max){if(s){this.loadCss();}if(!c){this.openCookies();}if(n){this.getOpenTo(n.split(" "));}if(nav){this.openCurNS(max);}if(window.indexmenu_contextmenu){var self=this;indexmenu_createPicker("r"+this.obj,"indexmenu_rmenu "+this.config.theme);DOKUid("r"+this.obj).oncontextmenu=indexmenu_stopevt;addEvent(document,"click",(function(){self.divdisplay("r",0);}));}});if(!Array.prototype.push){Array.prototype.push=(function array_push(){for(var i=0;i<arguments.length;i++){this[this.length]=arguments[i];}return this.length;});}if(!Array.prototype.pop){Array.prototype.pop=(function array_pop(){var lstEl=this[this.length-1];this.length=Math.max(this.length-1,0);return lstEl;});}
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/jsmenu/admmenu.js b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/jsmenu/admmenu.js
new file mode 100644
index 000000000..2ea6e32f2
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/jsmenu/admmenu.js
@@ -0,0 +1,71 @@
+/* Right Context Menu configuration for admin users:
+ Menu is built from four array items: title, link, show if page or headpage, show if namespace.
+ Link is not created if it's 0, otherwise it's evaluated.
+ Second array is displayed only in edit mode.
+
+ Some usefull variables:
+ node.hns = headpage id;
+ node.isdir = node is namespace;
+ node.dokuid = the DW id (namespace parent in case of headpage);
+ id = the DW id of the selected node (headpage id in case of headpage);
+ this.config.urlbase = Url Base;
+ this.config.sepchar = Url separator;
+*/
+
+var indexmenu_contextmenu=new Array(
+ //Standard right menu
+ new Array(
+ '<b><em>Page action:</em></b>',0,1,0,
+ '<b><em>Namespace action:</em></b>',0,0,1,
+ 'New page here','"javascript: indexmenu_reqpage(\'"+this.config.urlbase+"\',\'"+this.config.sepchar+"\',\'"+node.dokuid+"\');"',1,1,
+ 'Headpage here','"javascript: indexmenu_reqpage(\'"+this.config.urlbase+"\',\'"+this.config.sepchar+"\',\'"+node.dokuid+"\',\'"+node.name+"\');"',0,1,
+ 'Edit','indexmenu_getid(this.config.urlbase,id)+"do=edit"',1,0,
+ 'Search','"javascript: indexmenu_srchpage(\'"+this.config.urlbase+"\',\'"+this.config.sepchar+"\',\'"+node.isdir+"\',\'"+node.dokuid+"\');"',1,1,
+ 'Toc preview','"javascript: indexmenu_createTocMenu(\'req=toc&id="+id+"\',\'picker_"+this.obj+"\',\'s"+this.obj+node.id+"\');"',1,0,
+ 'Revisions','indexmenu_getid(this.config.urlbase,id)+"do=revisions"',1,0,
+ 'Purge cache','indexmenu_getid(this.config.urlbase,id)+"purge=true"',1,0,
+ 'Acls','indexmenu_getid(this.config.urlbase,id)+"do=admin&dokupage=acl"',1,1
+ ),
+
+ //Right menu in edit mode.
+ new Array(
+ '<b><em>Edit action:</em></b>',0,1,0,
+ 'Insert as DWlink','"javascript: indexmenu_insertTags(\'"+id+"\',\'"+this.config.sepchar+"\');"+this.obj+".divdisplay(\'r\',0);"',1,0
+ )
+ );
+
+/*Custom User Functions
+Insert your custom functions here.
+*/
+function indexmenu_reqpage(b,s,id,n) {
+ var r,u=b;
+ if (n) {
+ r = id + s + n;
+ } else {
+ r = prompt("Insert the pagename to create","");
+ if (!r) {return;}
+ r = id + s + r;
+ }
+ if (r) window.location.href = indexmenu_getid(u,r);
+}
+
+function indexmenu_srchpage(u,s,isdir,nid) {
+ var r = prompt("Insert keyword(s) to search for within this namespace","");
+ if (r)
+ {
+ var fnid = nid;
+ if (isdir == "0") {
+ fnid = fnid.substring(0,nid.lastIndexOf(s));
+ }
+ var b=u,re = new RegExp(s, 'g');
+ fnid = fnid.replace(re, ":");
+ b += (u.indexOf("?id=") < 0) ? '?id=': '';
+ window.location.href = indexmenu_getid(b,r+" @"+fnid)+"do=search";
+ }
+}
+
+function indexmenu_getid(u,id) {
+ var url=(u||'')+encodeURI(id||'');
+ url += (u.indexOf("?") < 0) ? '?': '&';
+ return url;
+}
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/jsmenu/menu.js b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/jsmenu/menu.js
new file mode 100644
index 000000000..d92956141
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/jsmenu/menu.js
@@ -0,0 +1,56 @@
+/* Right Context Menu configuration for anonymous users:
+ Menu is built from four array items: title, link, show if page or headpage, show if namespace.
+ Link is not created if it's 0, otherwise it's evaluated.
+ Second array is displayed only in edit mode.
+
+ Some usefull variables:
+ node.hns = headpage id;
+ node.isdir = node is namespace;
+ node.dokuid = the DW id (namespace parent in case of headpage);
+ id = the DW id of the selected node (headpage id in case of headpage);
+ this.config.urlbase = Url Base;
+ this.config.sepchar = Url separator;
+*/
+
+var indexmenu_contextmenu=new Array(
+ //Standard right menu
+ new Array(
+ '<b><em>Page action:</em></b>',0,1,0,
+ '<b><em>Namespace action:</em></b>',0,0,1,
+ 'Search','"javascript: indexmenu_srchpage(\'"+this.config.urlbase+"\',\'"+this.config.sepchar+"\',\'"+node.isdir+"\',\'"+node.dokuid+"\');"',1,1,
+ 'Toc preview','"javascript: indexmenu_createTocMenu(\'req=toc&id="+id+"\',\'picker_"+this.obj+"\',\'s"+this.obj+node.id+"\');"',1,0,
+ 'Revisions','indexmenu_getid(this.config.urlbase,id)+"do=revisions"',1,0
+ ),
+
+ //Right menu in edit mode.
+ new Array(
+ '<b><em>Edit action:</em></b>',0,1,0,
+ 'Insert as DWlink','"javascript: indexmenu_insertTags(\'"+id+"\',\'"+this.config.sepchar+"\');"+this.obj+".divdisplay(\'r\',0);"',1,0,
+ 'Edit','indexmenu_getid(this.config.urlbase,id)+"do=edit"',1,0
+ )
+ );
+
+/*Custom User Functions
+Insert your custom functions here.
+*/
+
+function indexmenu_srchpage(u,s,isdir,nid) {
+ var r = prompt("Insert keyword(s) to search for within this namespace","");
+ if (r)
+ {
+ var fnid = nid;
+ if (isdir == "0") {
+ fnid = fnid.substring(0,nid.lastIndexOf(s));
+ }
+ var b=u,re = new RegExp(s, 'g');
+ fnid = fnid.replace(re, ":");
+ b += (u.indexOf("?id=") < 0) ? '?id=': '';
+ window.location.href = indexmenu_getid(b,r+" @"+fnid)+"do=search";
+ }
+}
+
+function indexmenu_getid(u,id) {
+ var url=(u||'')+encodeURI(id||'');
+ url += (u.indexOf("?") < 0) ? '?': '&';
+ return url;
+}
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/jsmenu/usrmenu.js b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/jsmenu/usrmenu.js
new file mode 100644
index 000000000..d58ae3802
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/jsmenu/usrmenu.js
@@ -0,0 +1,69 @@
+/* Right Context Menu configuration for authenticated users:
+ Menu is built from four array items: title, link, show if page or headpage, show if namespace.
+ Link is not created if it's 0, otherwise it's evaluated.
+ Second array is displayed only in edit mode.
+
+ Some usefull variables:
+ node.hns = headpage id;
+ node.isdir = node is namespace;
+ node.dokuid = the DW id (namespace parent in case of headpage);
+ id = the DW id of the selected node (headpage id in case of headpage);
+ this.config.urlbase = Url Base;
+ this.config.sepchar = Url separator;
+*/
+
+var indexmenu_contextmenu=new Array(
+ //Standard right menu
+ new Array(
+ '<b><em>Page action:</em></b>',0,1,0,
+ '<b><em>Namespace action:</em></b>',0,0,1,
+ 'New page here','"javascript: indexmenu_reqpage(\'"+this.config.urlbase+"\',\'"+this.config.sepchar+"\',\'"+node.dokuid+"\');"',1,1,
+ 'Headpage here','"javascript: indexmenu_reqpage(\'"+this.config.urlbase+"\',\'"+this.config.sepchar+"\',\'"+node.dokuid+"\',\'"+node.name+"\');"',0,1,
+ 'Edit','indexmenu_getid(this.config.urlbase,id)+"do=edit"',1,0,
+ 'Search','"javascript: indexmenu_srchpage(\'"+this.config.urlbase+"\',\'"+this.config.sepchar+"\',\'"+node.isdir+"\',\'"+node.dokuid+"\');"',1,1,
+ 'Toc preview','"javascript: indexmenu_createTocMenu(\'req=toc&id="+id+"\',\'picker_"+this.obj+"\',\'s"+this.obj+node.id+"\');"',1,0,
+ 'Revisions','indexmenu_getid(this.config.urlbase,id)+"do=revisions"',1,0
+ ),
+
+ //Right menu in edit mode.
+ new Array(
+ '<b><em>Edit action:</em></b>',0,1,0,
+ 'Insert as DWlink','"javascript: indexmenu_insertTags(\'"+id+"\',\'"+this.config.sepchar+"\');"+this.obj+".divdisplay(\'r\',0);"',1,0
+ )
+ );
+
+/*Custom User Functions
+Insert your custom functions here.
+*/
+function indexmenu_reqpage(b,s,id,n) {
+ var r,u=b;
+ if (n) {
+ r = id + s + n;
+ } else {
+ r = prompt("Insert the pagename to create","");
+ if (!r) {return;}
+ r = id + s + r;
+ }
+ if (r) window.location.href = indexmenu_getid(u,r);
+}
+
+function indexmenu_srchpage(u,s,isdir,nid) {
+ var r = prompt("Insert keyword(s) to search for within this namespace","");
+ if (r)
+ {
+ var fnid = nid;
+ if (isdir == "0") {
+ fnid = fnid.substring(0,nid.lastIndexOf(s));
+ }
+ var b=u,re = new RegExp(s, 'g');
+ fnid = fnid.replace(re, ":");
+ b += (u.indexOf("?id=") < 0) ? '?id=': '';
+ window.location.href = indexmenu_getid(b,r+" @"+fnid)+"do=search";
+ }
+}
+
+function indexmenu_getid(u,id) {
+ var url=(u||'')+encodeURI(id||'');
+ url += (u.indexOf("?") < 0) ? '?': '&';
+ return url;
+}
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/lang/de/lang.php b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/lang/de/lang.php
new file mode 100644
index 000000000..29d939aa5
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/lang/de/lang.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * German language for indexmenu plugin
+ *
+ * @license: GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author: Fabian Pfannes <fpfannes@web.de>
+ */
+$lang['menu'] = 'Indexmenu Werkzeuge';
+$lang['fetch'] = 'Anzeigen';
+$lang['install'] = 'Installieren';
+$lang['delete'] = 'L&ouml;schen';
+$lang['check'] = '&Uuml;berpr&uuml;fen';
+$lang['no_repos'] = 'Keine URL f&uuml;r ein Template Repository vorhanden.';
+$lang['disabled'] = 'Deaktiviert';
+$lang['conn_err'] = 'Verbindung fehlgeschlagen';
+$lang['dir_err'] = 'Fehler bei der Erzeugung eines Verzeichnises. Designvorlage konnte nicht gespeichert werden';
+$lang['down_err'] = 'Fehler beim Herunterladen der Designvorlage';
+$lang['zip_err'] = 'Fehler beim Erstellen oder Entpacken der Zip-Datei';
+$lang['install_ok'] = 'Designvorlage wurde erfolgreich erstellt. Die neue Designvorlage ist in der Werkzeugleiste der Konfigurationsseite oder &uuml;ber die js#theme_name Option verf&uuml;gbar.';
+$lang['install_no'] = 'Verbindungsfehler. Sie k&ouml;nnen aber versuchen die Designvorlage <a href="http://samuele.netsons.org/dokuwiki/lib/plugins/indexmenu/upload/">hier</a> hochzuladen.';
+$lang['delete_ok'] = 'Designvorlage wurde erfolgreich gel&ouml;scht.';
+$lang['delete_no'] = 'Beim L&ouml;schen ist ein Fehler aufgetreten';
+$lang['upload'] = 'Hochladen';
+$lang['checkupdates'] = 'Plugin updaten';
+$lang['noupdates'] = "Indexmenu muss nicht upgedated werden. Sie haben bereits die aktuellste Version:";
+$lang['infos'] = 'Sie k&ouml;nnen eine neue Designvorlage erstellen. Beachten Sie die Anleitung im <a href="http://wiki.splitbrain.org/plugin:indexmenu#theme_tutorial">Designvorlagen Tutorial</a. <br />Wenn Sie den "Hochladen" Button unter der Desingvorlage dr&uuml;cken k&ouml;nnen Sie viele Leute gl&uuml;cklich machen :-) dadurch, dass Sie sie im &ouml;ffentliche Indexmenu Repository bereitstellen.';
+$lang['showsort']="Indexmenu Sortierungsnummer: ";
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/lang/en/lang.php b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/lang/en/lang.php
new file mode 100644
index 000000000..e298caa44
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/lang/en/lang.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * English language for indexmenu plugin
+ *
+ * @license: GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author: Samuele Tognini <samuele@netsons.org>
+ */
+$lang['menu'] = 'Indexmenu Utilities';
+$lang['fetch'] = 'Show';
+$lang['install'] = 'Install';
+$lang['delete'] = 'Delete';
+$lang['check'] = 'Check';
+$lang['no_repos'] = 'No theme repository url configured.';
+$lang['disabled'] = 'Disabled';
+$lang['conn_err'] = 'Connection error';
+$lang['dir_err'] = 'Unable to create temporary folder to receive theme';
+$lang['down_err'] = 'Unable to receive theme';
+$lang['zip_err'] = 'Zip creation or extraction error';
+$lang['install_ok'] = 'theme installed successfully. The new theme is avaiable in the toolbar of the edit page or with the js#theme_name option.';
+$lang['install_no'] = 'Connection error. However you can try to upload manually your theme from <a href="http://samuele.netsons.org/dokuwiki/lib/plugins/indexmenu/upload/">here</a>.';
+$lang['delete_ok'] = 'Theme is successfully deleted.';
+$lang['delete_no'] = 'An error occurred during theme deleting';
+$lang['upload'] = 'Share';
+$lang['checkupdates'] = 'Plugin updates';
+$lang['noupdates'] = "Indexmenu does not need to be update. You have already the last release:";
+$lang['infos'] = 'You can create your theme following the instructions at the <a href="http://wiki.splitbrain.org/plugin:indexmenu#theme_tutorial">Theme Tutorial</a> page. <br />Then you could make more people happy :-) sending it to the public indexmenu repository, with the "share" button under that theme.';
+$lang['showsort']="Indexmenu sort number: ";
+$lang['donation_text'] = 'The indexmenu plugin is not sponsored by anyone but i develop and support it for free during my spare time. If you gain something thanks to it or you want to support its development, you can consider to make a donation.';
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/lang/es/lang.php b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/lang/es/lang.php
new file mode 100644
index 000000000..114237f32
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/lang/es/lang.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * spanish language file
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Digna González Otero <digna.gonzalezotero [at] gmail [dot] com>
+ */
+
+$lang['menu'] = 'Utilidades de Indexmenu';
+$lang['fetch'] = 'Mostrar';
+$lang['install'] = 'Instalar';
+$lang['delete'] = 'Eliminar';
+$lang['check'] = 'Seleccionar';
+$lang['no_repos'] = 'Url de repositorio de temas no configurado.';
+$lang['disabled'] = 'Desactivado';
+$lang['conn_err'] = 'Error de conexión';
+$lang['dir_err'] = 'Imposible crear directorio temporar para almacenar el tema';
+$lang['down_err'] = 'Imposible recibir el tema';
+$lang['zip_err'] = 'Error de creación o extracción de Zip';
+$lang['install_ok'] = 'Tema instalado satisfactoriamente. El nuevo tema está disponible en la barra de herramientas de la página a editar o con el comando js#nombre_del_tema opción.';
+$lang['install_no'] = 'Error de conexión. Puedes intentar subir tu tema manualmente desde <a href="http://samuele.netsons.org/dokuwiki/lib/plugins/indexmenu/upload/">here</a>.';
+$lang['delete_ok'] = 'Tema eliminado correctamente.';
+$lang['delete_no'] = 'Ocurrió un error durante la eliminación del tema';
+$lang['upload'] = 'Compartir';
+$lang['checkupdates'] = 'Actualizaciones de plugin';
+$lang['noupdates'] = "No es necesario actualizar Indexmenu. Ya tienes la última versión:";
+$lang['infos'] = 'Puedes crear tu tema siguiendo las instrucciones de la página <a href="http://wiki.splitbrain.org/plugin:indexmenu#theme_tutorial">Theme Tutorial</a>. <br />Después puedes hacer feliz a más gente:-) enviándolo al repositorio público de indexmenu, con el botón de "compartir" bajo ese tema.';
+$lang['showsort']="Número de posición de Indexmenu: ";
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/lang/it/lang.php b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/lang/it/lang.php
new file mode 100644
index 000000000..4f6bbcd54
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/lang/it/lang.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Italian language for indexmenu plugin
+ *
+ * @license: GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author: Samuele Tognini <samuele@netsons.org>
+ */
+$lang['menu'] = "Utility di Indexmenu";
+$lang['fetch'] = 'Mostra';
+$lang['install'] = 'Installa';
+$lang['delete'] = 'Elimina';
+$lang['check'] = 'Controlla';
+$lang['no_repos'] = 'Non &egrave stato configurato nessun indirizzo web per il repository dei temi.';
+$lang['disabled'] = 'Disabilitato';
+$lang['conn_err'] = 'Errore di connessione';
+$lang['local_themes'] = 'Temi installati';
+$lang['dir_err'] = 'Impossibile creare la directory temporanea per scaricare il tema';
+$lang['down_err'] = 'Impossibile scaricare il tema';
+$lang['zip_err'] = 'Errore durante la creazione o scompattazione dell\' archivio';
+$lang['install_ok'] = "tema installato correttamente. Il nuovo tema &egrave accessibile dalla toolbar degli strumenti quando crei una pagina oppure tramite l' opzione js#nome_tema di indexmenu.";
+$lang['install_no'] = 'Errore durante l\' upload. Puoi comunque provare ad inviarmi manualmente il tema da <a href="http://samuele.netsons.org/dokuwiki/lib/plugins/indexmenu/upload/">qui</a>.';
+$lang['delete_ok'] = 'Rimozione del tema avvenuta con successo';
+$lang['delete_no'] = "Errore durante la rimozione del tema";
+$lang['upload'] = 'Condividi';
+$lang['checkupdates'] = 'Aggiornamenti plugin';
+$lang['noupdates'] = "Indexmenu non ha bisogno di essere aggiornato. Hai gi&agrave l'ultima release:";
+$lang['infos'] = 'Puoi creare il tuo tema seguendo le istruzioni nella pagina del <a href="http://wiki.splitbrain.org/plugin:indexmenu#theme_tutorial">Tutorial dei temi</a>.<br /> Poi potreste rendere felice pi&ugrave gente :-) inviandolo nel repository pubblico di indexemnu tramite il pulsante "condividi" sotto il tema della lista.';
+$lang['showsort']="Ordinamento in indexmenu: ";
+$lang['donation_text'] = 'Il plugin indexmenu non &egrave sponsorizzato da nessuno, ma lo sviluppo e supporto gratuitamente nel mio tempo libero. Se guadagni qualcosa grazie a questo plugin o vuoi supportarne lo sviluppo, puoi farlo con una donazione.';
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/nojsindex-full.js b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/nojsindex-full.js
new file mode 100644
index 000000000..34c8266cc
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/nojsindex-full.js
@@ -0,0 +1,101 @@
+/**
+ * Javascript for index view
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+
+indexmenu_nojs = {
+ /**
+ * Delay in ms before showing the throbber.
+ * Used to skip the throbber for fast AJAX calls.
+ */
+ throbber_delay: 500,
+
+ /**
+ * Attach event handlers to all "folders" below the given element
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+ treeattach: function(iobj){
+ var obj=DOKUid('nojs_'+iobj[0]);
+ if (!obj) return;
+
+ var items = getElementsByClass('indexmenu_idx',obj,'a');
+ for(var i=0; i<items.length; i++){
+ var elem = items[i];
+
+ // attach action to make the link clickable by AJAX
+ addEvent(elem,'click',function(e){ return indexmenu_nojs.toggle(e,this,iobj[1]); });
+ }
+ },
+
+ /**
+ * Open or close a subtree using AJAX
+ * The contents of subtrees are "cached" untill the page is reloaded.
+ * A "loading" indicator is shown only when the AJAX call is slow.
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ * Modified by Samuele Tognini <samuele@netsons.org> for the indexmenu plugin
+ */
+ toggle: function(e,clicky,jsajax){
+ var listitem = clicky.parentNode.parentNode;
+
+ // if already open, close by removing the sublist
+ var sublists = listitem.getElementsByTagName('ul');
+ if(sublists.length && listitem.className=='open'){
+ sublists[0].style.display='none';
+ listitem.className='closed';
+ e.preventDefault();
+ return false;
+ }
+
+ // just show if already loaded
+ if(sublists.length && listitem.className=='closed'){
+ sublists[0].style.display='';
+ listitem.className='open';
+ e.preventDefault();
+ return false;
+ }
+
+ // prepare an AJAX call to fetch the subtree
+ var ajax = new sack(DOKU_BASE+'lib/plugins/indexmenu/ajax.php');
+ ajax.AjaxFailedAlert = '';
+ ajax.encodeURIString = false;
+ if(ajax.failed) return true;
+
+ //prepare the new ul
+ var ul = document.createElement('ul');
+ ul.className = 'idx';
+ timeout = window.setTimeout(function(){
+ // show the throbber as needed
+ ul.innerHTML = '<li><img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="loading..." title="loading..." /></li>';
+ listitem.appendChild(ul);
+ listitem.className='open';
+ }, this.throbber_delay);
+ ajax.elementObj = ul;
+ ajax.afterCompletion = function(){
+ window.clearTimeout(timeout);
+ indexmenu_nojs.treeattach(ul);
+ if (listitem.className!='open') {
+ listitem.appendChild(ul);
+ listitem.className='open';
+ }
+ };
+ ajax.runAJAX(encodeURI('req=index&nojs=1&'+clicky.search.substr(1)+'&max=1'+decodeURIComponent(jsajax)));
+ e.preventDefault();
+ return false;
+ },
+
+ /* Find all nojs indexmenu objects */
+ treefind: function () {
+ var aobj=indexmenu_nojsqueue;
+ if (!aobj) return;
+
+ for (var i in aobj) {
+ indexmenu_nojs.treeattach(aobj[i]);
+ }
+ }
+};
+
+indexmenu_nojs.treefind();
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/nojsindex.js b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/nojsindex.js
new file mode 100644
index 000000000..ac437321e
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/nojsindex.js
@@ -0,0 +1 @@
+indexmenu_nojs={throbber_delay:500,treeattach:(function(iobj){var obj=DOKUid("nojs_"+iobj[0]);if(!obj){return;}var items=getElementsByClass("indexmenu_idx",obj,"a");for(var i=0;i<items.length;i++){var elem=items[i];addEvent(elem,"click",(function(e){return indexmenu_nojs.toggle(e,this,iobj[1]);}));}}),toggle:(function(e,clicky,jsajax){var listitem=clicky.parentNode.parentNode;var sublists=listitem.getElementsByTagName("ul");if(sublists.length&&listitem.className=="open"){sublists[0].style.display="none";listitem.className="closed";e.preventDefault();return false;}if(sublists.length&&listitem.className=="closed"){sublists[0].style.display="";listitem.className="open";e.preventDefault();return false;}var ajax=new sack(DOKU_BASE+"lib/plugins/indexmenu/ajax.php");ajax.AjaxFailedAlert="";ajax.encodeURIString=false;if(ajax.failed){return true;}var ul=document.createElement("ul");ul.className="idx";timeout=window.setTimeout((function(){ul.innerHTML="<li><img src=\""+DOKU_BASE+"lib/images/throbber.gif\" alt=\"loading...\" title=\"loading...\" /></li>";listitem.appendChild(ul);listitem.className="open";}),this.throbber_delay);ajax.elementObj=ul;ajax.afterCompletion=(function(){window.clearTimeout(timeout);indexmenu_nojs.treeattach(ul);if(listitem.className!="open"){listitem.appendChild(ul);listitem.className="open";}});ajax.runAJAX(encodeURI("req=index&nojs=1&"+clicky.search.substr(1)+"&max=1"+decodeURIComponent(jsajax)));e.preventDefault();return false;}),treefind:(function(){var aobj=indexmenu_nojsqueue;if(!aobj){return;}for(var i in aobj){indexmenu_nojs.treeattach(aobj[i]);}})};indexmenu_nojs.treefind();
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/script.js b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/script.js
new file mode 100644
index 000000000..411f0fde5
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/script.js
@@ -0,0 +1,152 @@
+/* Queue of loaded script files */
+var indexmenu_jsqueue = [];
+/* Queue of loaded css files */
+var indexmenu_cssqueue = [];
+/* Queue of nojs trees */
+var indexmenu_nojsqueue = [];
+
+function indexmenu_findExt(path){
+ var ext = "gif";
+ var cext = path.lastIndexOf(".");
+ if ( cext > -1){
+ cext++;
+ cext = path.substring(cext, path.length).toLowerCase();
+ if ((cext == "png") || (cext == "jpg")) {ext = cext;}
+ }
+ return ext;
+}
+
+function indexmenu_createTocMenu(get,picker,btn) {
+ var toc_picker = DOKUid(picker);
+ if (!toc_picker) {
+ toc_picker=indexmenu_createPicker(picker);
+ toc_picker.className='dokuwiki indexmenu_toc';
+ toc_picker.innerHTML='<a href="#"><img src="'+DOKU_BASE+'lib/plugins/indexmenu/images/close.gif" class="indexmenu_close" /></a><div />';
+ addEvent(toc_picker.firstChild, 'click',function (event) {event.stopPropagation();return indexmenu_showPicker(picker)});
+ } else {
+ toc_picker.style.display = 'none';
+ }
+ indexmenu_ajaxmenu(get,toc_picker,DOKUid(btn),toc_picker.childNodes[1]);
+}
+
+function indexmenu_ajaxmenu(get,picker,btn,container,oncomplete) {
+ var indx_list;
+ if (container) {
+ indx_list = container;
+ } else {
+ indx_list = picker;
+ }
+ if (!indexmenu_showPicker(picker,btn)) return;
+ // We use SACK to do the AJAX requests
+ var ajax = new sack(DOKU_BASE+'lib/plugins/indexmenu/ajax.php');
+ ajax.encodeURIString=false;
+ ajax.onLoading = function () {
+ indx_list.innerHTML='<div class="tocheader">Loading .....</div>';
+ };
+
+ // define callback
+ ajax.onCompletion = function(){
+ var data = this.response;
+ indx_list.innerHTML="";
+ if (isFunction(oncomplete)) {
+ oncomplete(data,indx_list);
+ } else {
+ indx_list.innerHTML=data;
+ }
+ };
+
+ ajax.runAJAX(encodeURI(get));
+}
+
+function indexmenu_createPicker(id,cl) {
+ var indx_list = document.createElement('div');
+ indx_list.className = cl || 'picker';
+ indx_list.id=id;
+ indx_list.style.position = 'absolute';
+ indx_list.style.display = 'none';
+ var body = document.getElementsByTagName('body')[0];
+ body.appendChild(indx_list);
+ return indx_list;
+}
+
+function indexmenu_showPicker(pickerid,btn){
+ var x = 3, y = 3, picker = DOKUid(pickerid);
+ if(picker.style.display == 'none'){
+ x += findPosX(btn);
+ y += findPosY(btn);
+ if (picker.id != 'picker_plugin_indexmenu') {
+ x += btn.offsetWidth-3;
+ } else {
+ y += btn.offsetHeight;
+ }
+ picker.style.display = 'block';
+ picker.style.left = x+'px';
+ picker.style.top = y+'px';
+ return true;
+ }else{
+ picker.style.display = 'none';
+ return false;
+ }
+}
+
+function indexmenu_loadtoolbar(){
+ var toolbar = DOKUid('tool__bar');
+ if(!toolbar) return;
+ indexmenu_loadJs(DOKU_BASE+'lib/plugins/indexmenu/edit.js');
+}
+
+function indexmenu_loadJs(f){
+ var basef = f.replace(/^.*[\/\\]/g, '');
+ if (indexmenu_notinarray(indexmenu_jsqueue,basef)) {
+ var oLink = document.createElement("script");
+ oLink.src = f;
+ oLink.type = "text/javascript";
+ oLink.charset="utf-8";
+ indexmenu_jsqueue.push(basef);
+ document.getElementsByTagName("head")[0].appendChild(oLink);
+ }
+}
+
+function indexmenu_checkcontextm(n,obj,e){
+ var k=0;
+ e=e||event;
+ if ((e.which == 3 || e.button == 2) || (window.opera && e.which == 1 && e.ctrlKey)) {
+ obj.contextmenu (n,e);
+ indexmenu_stopevt(e);
+ }
+}
+
+function indexmenu_stopevt(e) {
+ if (!window.indexmenu_contextmenu) {
+ return true;
+ }
+ e=e||event;
+ e.preventdefault? e.preventdefault() : e.returnValue = false;
+ return false;
+}
+
+function indexmenu_notinarray(array,val) {
+ for (var i = 0; i < array.length; i++) {
+ if (array[i] == val) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function indexmenu_mouseposition(obj,e) {
+/*http://www.quirksmode.org/js/events_properties.html*/
+ if (!e) e = window.event;
+ if (e.pageX || e.pageY) {
+ X = e.pageX;
+ Y = e.pageY;
+ }
+ else if (e.clientX || e.clientY) {
+ X = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
+ Y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
+ }
+ obj.style.left=X-5+'px';
+ obj.style.top=Y-5+'px';
+}
+
+addInitEvent(indexmenu_loadtoolbar);
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/style.css b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/style.css
new file mode 100644
index 000000000..a70cbebfe
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/style.css
@@ -0,0 +1,190 @@
+/*--------------------------------------------------|
+| dTree 2.05 | www.destroydrop.com/javascript/tree/ |
+|---------------------------------------------------|
+| Copyright (c) 2002-2003 Geir Landro |
+|--------------------------------------------------*/
+/*
+ a.nodeFdUrl Namespace with url link (headpage) js
+ a.node Namespace without url link js
+ a.nodeUrl Page js
+ a.nodeSel Last visited page js
+ a.navSel Current page js
+ a.indexmenu_idx_head link style of a namespace with url (headpage) nojs
+ a.indexmenu_idx link style of a namespace without url nojs
+ */
+
+/* dtree properties. No need to change*/
+
+.dtree {
+ font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ color: __text__;
+ white-space: nowrap;
+ line-height: normal;
+}
+
+.dtree img {
+ border: 0px;
+ vertical-align: top;
+}
+
+/*Properties that can be edit*/
+
+/*Link properties*/
+.dtree a {
+ color: __existing__;
+ text-decoration: none;
+}
+
+/*Link properties*/
+.dtree a.node, .dtree a.nodeSel a.navSel {
+ white-space: nowrap;
+ padding: 1px 2px 1px 2px;
+}
+/* Last visited page highlighting*/
+.dtree a.nodeSel {
+ background-color: __background_alt__;
+}
+/* Current page highlighting*/
+.dtree a.navSel {
+ background-color: __highlight__;
+}
+
+/*
+.dtree .clip {
+}
+*/
+
+/*nojs tree div*/
+.indexmenu_nojs {
+ display: block;
+}
+
+/*Namespace without page link in nojs mode. !important has to be used*/
+div.li a.indexmenu_idx {
+ color: __missing__ !important;
+ text-decoration: none !important;
+ font-weight: bold;
+}
+
+/*Namespace with page link (headpage) in nojs mode. !important has to be used*/
+
+div.li a.indexmenu_idx_head {
+ font-weight: bold;
+}
+
+
+/*Style for admin panel interface*/
+div.dokuwiki div.indexmenu_list_themes {
+ clear: both;
+ border-top: 2px solid __border__;
+ padding-left: 1em;
+}
+
+/*Mouseover property*/
+.dtree a.nodeFdUrl:hover, .dtree a.nodeSel:hover, a.navSel:hover, .dtree a.nodeUrl:hover {
+ color: __existing__;
+ text-decoration: underline;
+ background-color: __background_alt__;
+}
+/*Mouseover property*/
+.dtree a.node:hover {
+ text-decoration: none;
+}
+
+/*tocbullet property*/
+.dtree .indexmenu_tocbullet {
+ position:absolute;
+ background: transparent url(images/toc_bullet.gif) no-repeat scroll;
+ vertical-align: middle;
+ width: 11px;
+ height: 11px;
+}
+
+/*scrolling arrow property*/
+.dtree .indexmenu_larrow {
+ position:absolute;
+ filter:alpha(opacity=60);-moz-opacity:.60;opacity:.60;
+ background:transparent url(images/larrow.gif) repeat-y scroll;
+ padding-left:22px;
+ z-index:100;
+}
+
+/*toc property*/
+.indexmenu_toc {
+ font-size: 80%;
+ line-height: 1.2em;
+ white-space: normal;
+ overflow: hidden;
+ width: 200px !important;
+ z-index:100 !important;
+ word-wrap: break-word;
+}
+
+.indexmenu_toc .indexmenu_toc_inside {
+ border: 1px solid __border__;
+ background-color: __background__;
+ text-align: left;
+ padding: 0.5em 0 0.7em 0;
+ max-height: 300px;
+ height: expression( this.scrollHeight > 300 ? "300px" : "auto" );
+ overflow: auto;
+}
+
+.dtree .indexmenu_rarrow {
+ position:absolute;
+ background:white url(images/rarrow.gif) no-repeat scroll;
+ width:11px;
+ height:15px;
+}
+
+.indexmenu_rmenu {
+ position: absolute;
+ z-index: 100;
+ background-color: #fff;
+ border: 1px solid black;
+ font-size: 80%;
+ line-height: 100%;
+ padding-bottom: 5px;
+}
+
+.indexmenu_rmenuhead {
+ background-color: #CCFFCC;
+ border-bottom: 1px solid __text__;
+ color: __text__;
+ font-size: 90%;
+ margin: 0pt;
+ text-align: center;
+ padding: 1px 5px;
+ vertical-align: middle;
+ overflow: hidden;
+ width: 80px;
+}
+
+.indexmenu_rmenu ul,.indexmenu_rmenu li {
+ list-style-type: none !important;
+ list-style-image: none !important;
+ color: #000 !important;
+ margin: 2px !important;
+ text-align: center;
+}
+
+.indexmenu_rmenu a:hover {
+ background-color: #000 !important;
+ color: #fff !important;
+}
+
+.indexmenu_opts {
+ font-size: 80%;
+}
+
+.dtree .emptynode {
+ background: transparent url(images/empty.gif) no-repeat scroll;
+ display: inline;
+ padding: 1px 8px;
+ width: 16px;
+ height: 16px;
+ vertical-align: top;
+ /* needed by ie7 */
+ zoom: 1;
+}
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/syntax/indexmenu.php b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/syntax/indexmenu.php
new file mode 100644
index 000000000..a1653437d
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/syntax/indexmenu.php
@@ -0,0 +1,720 @@
+<?php
+/**
+ * Info Indexmenu: Displays the index of a specified namespace.
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Samuele Tognini <samuele@netsons.org>
+ *
+ */
+
+if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
+if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
+if(!defined('INDEXMENU_IMG_ABSDIR')) define('INDEXMENU_IMG_ABSDIR',DOKU_PLUGIN."indexmenu/images");
+require_once(DOKU_PLUGIN.'syntax.php');
+require_once(DOKU_INC.'inc/search.php');
+
+/**
+ * All DokuWiki plugins to extend the parser/rendering mechanism
+ * need to inherit from this class
+ */
+class syntax_plugin_indexmenu_indexmenu extends DokuWiki_Syntax_Plugin {
+
+ var $sort=false;
+ var $msort=false;
+ var $rsort=false;
+ var $nsort=false;
+
+ /**
+ * return some info
+ */
+ function getInfo(){
+ return array(
+ 'author' => 'Samuele Tognini',
+ 'email' => 'samuele@netsons.org',
+ 'date' => rtrim(io_readFile(DOKU_PLUGIN.'indexmenu/VERSION.txt')),
+ 'name' => 'Indexmenu',
+ 'desc' => 'Insert the index of a specified namespace.',
+ 'url' => 'http://wiki.splitbrain.org/plugin:indexmenu'
+ );
+ }
+
+ /**
+ * What kind of syntax are we?
+ */
+ function getType(){
+ return 'substition';
+ }
+
+ function getPType(){
+ return 'block';
+ }
+
+ /**
+ * Where to sort in?
+ */
+ function getSort(){
+ return 138;
+ }
+
+ /**
+ * Connect pattern to lexer
+ */
+ function connectTo($mode) {
+ $this->Lexer->addSpecialPattern('{{indexmenu>.+?}}',$mode,'plugin_indexmenu_indexmenu');
+ }
+
+ /**
+ * Handle the match
+ */
+ function handle($match, $state, $pos, &$handler){
+ $theme="default";
+ $ns=".";
+ $level = -1;
+ $nons = true;
+ $gen_id='random';
+ $maxjs=0;
+ $max=0;
+ $jsajax='';
+ $nss=array();
+ $match = substr($match,12,-2);
+ //split namespace,level,theme
+ $match = preg_split('/\|/u', $match, 2);
+ //split options
+ $opts=preg_split('/ /u',$match[1]);
+ //Context option
+ $context = in_array('context',$opts);
+ //split optional namespaces
+ $nss_temp=preg_split("/ /u",$match[0],-1,PREG_SPLIT_NO_EMPTY);
+ //Array optional namespace => level
+ for ($i = 1; $i < count($nss_temp); $i++) {
+ $nsss=preg_split("/#/u",$nss_temp[$i]);
+ if (!$context) {
+ $nsss[0] = $this->_parse_ns($nsss[0]);
+ }
+ $nss[]=array($nsss[0],(is_numeric($nsss[1])) ? $nsss[1] : $level);
+ }
+ //split main requested namespace
+ if (preg_match('/(.*)#(\S*)/u',$nss_temp[0],$ns_opt)) {
+ //split level
+ $ns = $ns_opt[1];
+ if (is_numeric($ns_opt[2])) $level=$ns_opt[2];
+ } else {
+ $ns = $nss_temp[0];
+ }
+ if (!$context) {
+ $ns = $this->_parse_ns($ns);
+ }
+ //nocookie option (disable for uncached pages)
+ $nocookie=$context||in_array('nocookie',$opts);
+ //noscroll option
+ $noscroll=in_array('noscroll',$opts);
+ //Open at current namespace option
+ $navbar=in_array('navbar',$opts);
+ //no namespaces options
+ $nons = in_array('nons',$opts);
+ //no pages option
+ $nopg = in_array('nopg',$opts);
+ //disable toc preview
+ $notoc = in_array('notoc',$opts);
+ //Main sort method
+ if (in_array('tsort',$opts)) {
+ $sort='t';
+ } elseif (in_array('dsort',$opts)) {
+ $sort='d';
+ } else $sort=0;
+ //Directory sort
+ $nsort=in_array('nsort',$opts);
+ //Metadata sort method
+ if ($msort = in_array('msort',$opts)) {
+ $msort='indexmenu_n';
+ } elseif (preg_match('/msort#(\S+)/u',$match[1],$msort_tmp) >0) $msort=str_replace(':',' ',$msort_tmp[1]);
+ //reverse sort
+ $rsort=in_array('rsort',$opts);
+ //javascript option
+ if (!$js= in_array('js',$opts)) {
+ //split theme
+ if (preg_match('/js#(\S*)/u',$match[1],$tmp_theme) > 0) {
+ if (is_dir(INDEXMENU_IMG_ABSDIR."/".$tmp_theme[1])) {
+ $theme=$tmp_theme[1];
+ }
+ $js=true;
+ }
+ }
+ //id generation method
+ if (preg_match('/id#(\S+)/u',$match[1],$id) >0) $gen_id=$id[1];
+ //max option
+ if (preg_match('/max#(\d+)($|\s+|#(\d+))/u',$match[1],$maxtmp) >0) {
+ $max=$maxtmp[1];
+ if ($maxtmp[3]) $jsajax = "&max=".$maxtmp[3];
+ //disable cookie to avoid javascript errors
+ $nocookie=true;
+ }
+ if ($sort) $jsajax .= "&sort=".$sort;
+ if ($msort) $jsajax .= "&msort=".$msort;
+ if ($rsort) $jsajax .= "&rsort=1";
+ if ($nsort) $jsajax .= "&nsort=1";
+ if ($nopg) $jsajax .= "&nopg=1";
+ //max js option
+ if (preg_match('/maxjs#(\d+)/u',$match[1],$maxtmp) >0) $maxjs=$maxtmp[1];
+ //js options
+ $js_opts=compact('theme','gen_id','nocookie','navbar','noscroll','maxjs','notoc','jsajax','context');
+ return array($ns,
+ $js_opts,
+ $sort,
+ $msort,
+ $rsort,
+ $nsort,
+ array('level' => $level,
+ 'nons' => $nons,
+ 'nopg' => $nopg,
+ 'nss' => $nss,
+ 'max' => $max,
+ 'js' => $js,
+ 'skip_index' => $this->getConf('skip_index'),
+ 'skip_file' => $this->getConf('skip_file'),
+ 'headpage' => $this->getConf('headpage'),
+ 'hide_headpage' => $this->getConf('hide_headpage')
+ )
+ );
+ }
+
+ /**
+ * Render output
+ */
+ function render($mode, &$renderer, $data) {
+ global $ACT;
+ global $conf;
+ global $INFO;
+ if($mode == 'xhtml'){
+ if ($ACT == 'preview') {
+ //Check user permission to display indexmenu in a preview page
+ if( $this->getConf('only_admins') &&
+ $conf['useacl'] &&
+ $INFO['perm'] < AUTH_ADMIN)
+ return false;
+ //disable cookies
+ $data[1]['nocookie']=true;
+ }
+ //Navbar with nojs
+ if ($data[1]['navbar'] && !$data[6]['js']) {
+ if (!isset($data[0])) $data[0]='..';
+ $data[6]['nss'][]=array(getNS($INFO['id']));
+ $renderer->info['cache'] = FALSE;
+ }
+
+ if ($data[1]['context']) {
+ //resolve current id relative namespaces
+ $data[0]=$this->_parse_ns($data[0],$INFO['id']);
+ foreach ($data[6]['nss'] as $key=>$value) {
+ $data[6]['nss'][$key][0] = $this->_parse_ns($value[0],$INFO['id']);
+ }
+ $renderer->info['cache'] = FALSE;
+ }
+ $n = $this->_indexmenu($data);
+ if (!@$n) {
+ $n = $this->getConf('empty_msg');
+ $n = str_replace('{{ns}}',cleanID($data[0]),$n);
+ $n = p_render('xhtml',p_get_instructions($n),$info);
+ }
+ $renderer->doc .= $n;
+ return true;
+ } else if ($mode == 'metadata') {
+ if (!($data[1]['navbar'] && !$data[6]['js']) && !$data[1]['context']) {
+ //this is an indexmenu page that needs the PARSER_CACHE_USE event trigger;
+ $renderer->meta['indexmenu'] = TRUE;
+ }
+ $renderer->doc .= ((empty($data[0])) ? $conf['title'] : nons($data[0])) ." index\n\n";
+ unset($renderer->persistent['indexmenu']);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Return the index
+ * @author Samuele Tognini <samuele@netsons.org>
+ *
+ * This function is a simple hack of Dokuwiki html_index($ns)
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+ function _indexmenu($myns) {
+ global $conf;
+ $ns = $myns[0];
+ $js_opts=$myns[1];
+ $this->sort = $myns[2];
+ $this->msort = $myns[3];
+ $this->rsort = $myns[4];
+ $this->nsort = $myns[5];
+ $opts = $myns[6];
+ $output=false;
+ $data = array();
+ $js_name="indexmenu_";
+ $fsdir="/".utf8_encodeFN(str_replace(':','/',$ns));
+ if ($this->sort || $this->msort || $this->rsort) {
+ $custsrch=$this->_search($data,$conf['datadir'],array($this,'_search_index'),$opts,$fsdir);
+ } else {
+ search($data,$conf['datadir'],array($this,'_search_index'),$opts,$fsdir);
+ }
+ if (!$data) return false;
+
+ // Id generation method
+ if (is_numeric($js_opts['gen_id'])) {
+ $js_name .= $js_opts['gen_id'];
+ } elseif ($js_opts['gen_id'] == 'ns') {
+ $js_name .= sprintf("%u",crc32($ns));
+ } else {
+ $js_name .= uniqid(rand());
+ }
+
+ //javascript index
+ if ($opts['js']) {
+ $ns = str_replace('/',':',$ns);
+ $output_tmp=$this->_jstree($data,$ns,$js_opts,$js_name,$opts['max']);
+ //remove unwanted nodes from standard index
+ $this->_clean_data($data);
+ } else {
+ $output .= "<script type='text/javascript' charset='utf-8'>\n";
+ $output .= "<!--//--><![CDATA[//><!--\n";
+ $output .= "indexmenu_nojsqueue.push(new Array('".$js_name."','".utf8_encodeFN($js_opts['jsajax'])."'));\n";
+ $output .= "addInitEvent(function(){indexmenu_loadJs(DOKU_BASE+'lib/plugins/indexmenu/nojsindex.js');});\n";
+ $output .= "//--><!]]>\n";
+ $output .= "</script>\n";
+ }
+ //Nojs dokuwiki index
+ $output.="\n".'<div id="nojs_'.$js_name.'" class="indexmenu_nojs"';
+ $output.=">\n";
+ $output.=html_buildlist($data,'idx',array($this,"_html_list_index"),"html_li_index");
+ $output.="</div>\n";
+ $output.=$output_tmp;
+ return $output;
+ }
+
+ /**
+ * Build the browsable index of pages using javascript
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _jstree($data,$ns,$js_opts,$js_name,$max) {
+ global $conf;
+ $hns=false;
+ if (empty($data)) return false;
+ //Render requested ns as root
+ $headpage=$this->getConf('headpage');
+ if (empty($ns) && !empty($headpage)) $headpage.=','.$conf['start'];
+ $title=$this->_getTitle($ns,$headpage,$hns);
+ if (empty($title)) {
+ (empty($ns)) ? $title = htmlspecialchars($conf['title'],ENT_QUOTES) : $title=$ns;
+ }
+ $out = "<script type='text/javascript' charset='utf-8'>\n";
+ $out .= "<!--//--><![CDATA[//><!--\n";
+ $out .= "var $js_name = new dTree('".$js_name."','".$js_opts['theme']."');\n";
+ $sepchar = idfilter(':');
+ $out .= "$js_name.config.urlbase='".substr(wl(":"), 0, -1)."';\n";
+ $out .= "$js_name.config.sepchar='".$sepchar."';\n";
+ if ($js_opts['notoc']) $out .="$js_name.config.toc=false;\n";
+ if ($js_opts['nocookie']) $out .="$js_name.config.useCookies=false;\n";
+ if ($js_opts['noscroll']) $out .="$js_name.config.scroll=false;\n";
+ if ($js_opts['maxjs'] > 0) $out .= "$js_name.config.maxjs=".$js_opts['maxjs'].";\n";
+ if (!empty($js_opts['jsajax'])) $out .= "$js_name.config.jsajax='".utf8_encodeFN($js_opts['jsajax'])."';\n";
+ $out .= $js_name.".add('".idfilter(cleanID($ns))."',0,-1,'".$title."'";
+ if ($hns) $out .= ",'".idfilter(cleanID($hns))."'";
+ $out .= ");\n";
+ $anodes = $this->_jsnodes($data,$js_name);
+ $out .= $anodes[0];
+ $out .= "document.write(".$js_name.");\n";
+ $out .= "addInitEvent(function(){".$js_name.".init(";
+ $out .= (int) is_file(INDEXMENU_IMG_ABSDIR.'/'.$js_opts['theme'].'/style.css').",";
+ $out .= (int) $js_opts['nocookie'].",";
+ $out .= '"'.$anodes[1].'",';
+ $out .= (int) $js_opts['navbar'].",$max";
+ $out .= ");});\n";
+ $out .= "//--><!]]>\n";
+ $out .= "</script>\n";
+ return $out;
+ }
+
+ /**
+ * Return array of javascript nodes and nodes to open.
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _jsnodes($data,$js_name,$noajax=1) {
+ if (empty($data)) return false;
+ //Array of nodes to check
+ $q=array('0');
+ //Current open node
+ $node=0;
+ $out='';
+ $extra='';
+ if ($noajax) {
+ $jscmd=$js_name.".add";
+ $com=";\n";
+ } else {
+ $jscmd="new Array ";
+ $com=",";
+ }
+ foreach ($data as $i=>$item){
+ $i++;
+ //Remove already processed nodes (greater level = lower level)
+ while ($item['level'] <= $data[end($q)-1]['level']) {
+ array_pop($q);
+ }
+
+ //till i found its father node
+ if ($item['level']==1) {
+ //root node
+ $father='0';
+ } else {
+ //Father node
+ $father=end($q);
+ }
+ //add node and its options
+ if ($item['type'] == 'd' ) {
+ //Search the lowest open node of a tree branch in order to open it.
+ if ($item['open']) ($item['level'] < $data[$node]['level']) ? $node=$i : $extra .= "$i ";
+ //insert node in last position
+ array_push($q,$i);
+ }
+ $out .= $jscmd."('".idfilter($item['id'])."',$i,".$father.",'".$item['title']."'";
+ //hns
+ ($item['hns']) ? $out .= ",'".idfilter($item['hns'])."'" : $out .= ",0";
+ ($item['type'] == 'd' || $item['type']=='l') ? $out .= ",1" : $out .= ",0";
+ //MAX option
+ ($item['type']=='l') ? $out .= ",1" : $out .= ",0";
+ $out .= ")".$com;
+ }
+ $extra=rtrim($extra,' ');
+ return array($out,$extra);
+ }
+ /**
+ * Get page title, checking for headpages
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _getTitle ($ns,$headpage,&$hns) {
+ global $conf;
+ $hns=false;
+ $title=noNS($ns);
+ if (empty($headpage)) return $title;
+ $ahp=explode(",",$headpage);
+ foreach ($ahp as $hp) {
+ switch ($hp) {
+ case ":inside:":
+ $page=$ns.":".noNS($ns);
+ break;
+ case ":same:":
+ $page=$ns;
+ break;
+ //it's an inside start
+ case ":start:":
+ $page=ltrim($ns.":".$conf['start'],":");
+ break;
+ //inside pages
+ default:
+ $page=$ns.":".$hp;
+ }
+ //check headpage
+ if (@file_exists(wikiFN($page)) && auth_quickaclcheck($page) >= AUTH_READ) {
+ if ($conf['useheading'] && $title_tmp=p_get_first_heading($page,FALSE)) $title=$title_tmp;
+ $title=htmlspecialchars($title,ENT_QUOTES);
+ $hns=$page;
+ //headpage found, exit for
+ break;
+ }
+ }
+ return $title;
+ }
+
+ /**
+ * Parse namespace request
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _parse_ns ($ns,$id=FALSE) {
+ if (!$id) {
+ global $ID;
+ $id = $ID;
+ }
+ //Just for old reelases compatibility
+ if (empty($ns) || $ns == '..') $ns=":..";
+ return resolve_id(getNS($id),$ns);
+ }
+
+ /**
+ * Clean index data from unwanted nodes in nojs mode.
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _clean_data(&$data) {
+ foreach ($data as $i=>$item) {
+ //closed node
+ if ($item['type'] == "d" && !$item['open']) {
+ $a=$i+1;
+ $level=$data[$i]['level'];
+ //search and remove every lower and closed nodes
+ while ($data[$a]['level'] > $level && !$data[$a]['open']) {
+ unset($data[$a]);
+ $a++;
+ }
+ }
+ $i++;
+ }
+ }
+
+ /**
+ * Build the browsable index of pages
+ *
+ * $opts['ns'] is the current namespace
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * modified by Samuele Tognini <samuele@netsons.org>
+ */
+ function _search_index(&$data,$base,$file,$type,$lvl,$opts){
+ global $conf;
+ $hns=false;
+ $return=false;
+ $isopen=false;
+ $skip_index=$opts['skip_index'];
+ $skip_file=$opts['skip_file'];
+ $headpage=$opts['headpage'];
+ $id = pathID($file);
+ if($type == 'd'){
+ // Skip folders in plugin conf
+ if (!empty($skip_index) &&
+ preg_match($skip_index, $id))
+ return false;
+ //check ACL (for sneaky_index namespaces too).
+ if ($this->getConf('sneaky_index') && auth_quickaclcheck($id.':') < AUTH_READ) return false;
+ //Open requested level
+ if ($opts['level'] > $lvl || $opts['level'] == -1) $isopen=true;
+ //Search optional namespaces
+ if (!empty($opts['nss'])){
+ $nss=$opts['nss'];
+ for ($a=0; $a<count($nss);$a++) {
+ if (preg_match("/^".$id."($|:.+)/i",$nss[$a][0],$match)) {
+ //It contains an optional namespace
+ $isopen=true;
+ } elseif (preg_match("/^".$nss[$a][0]."(:.*)/i",$id,$match)) {
+ //It's inside an optional namespace
+ if ($nss[$a][1] == -1 || substr_count($match[1],":") < $nss[$a][1]) {
+ $isopen=true;
+ } else {
+ $isopen=false;
+ }
+ }
+ }
+ }
+ if ($opts['nons']) {
+ return $isopen;
+ } elseif ($opts['max'] >0 && !$isopen && $lvl >= $opts['max']) {
+ $isopen=false;
+ //Stop recursive searching
+ $return=false;
+ //change type
+ $type="l";
+ } elseif ($opts['js']) {
+ $return=true;
+ } else {
+ $return=$isopen;
+ }
+ //Set title and headpage
+ $title=$this->_getTitle($id,$headpage,$hns);
+ if (!$hns && $opts['nopg']) $hns=$id.":".$conf['start'];
+ } else {
+ //Nopg.Dont show pages
+ if ($opts['nopg']) return false;
+ $return=true;
+ //Nons.Set all pages at first level
+ if ($opts['nons']) $lvl=1;
+ //don't add
+ if (substr($file,-4) != '.txt') return false;
+ //check hiddens and acl
+ if (isHiddenPage($id) || auth_quickaclcheck($id) < AUTH_READ) return false;
+ //Skip files in plugin conf
+ if (!empty($skip_file) &&
+ preg_match($skip_file, $id))
+ return false;
+ //Skip headpages to hide
+ if (!$opts['nons'] &&
+ !empty($headpage) &&
+ $opts['hide_headpage']) {
+ if ($id==$conf['start']) return false;
+ $ahp=explode(",",$headpage);
+ foreach ($ahp as $hp) {
+ switch ($hp) {
+ case ":inside:":
+ if (noNS($id)==noNS(getNS($id))) return false;
+ break;
+ case ":same:":
+ if (@is_dir(dirname(wikiFN($id))."/".utf8_encodeFN(noNS($id)))) return false;
+ break;
+ //it' s an inside start
+ case ":start:":
+ if (noNS($id)==$conf['start']) return false;
+ break;
+ default:
+ if (noNS($id)==cleanID($hp)) return false;
+ }
+ }
+ }
+ //Set title
+ if (!$conf['useheading'] || !$title=p_get_first_heading($id,FALSE)) $title=noNS($id);
+ $title=htmlspecialchars($title,ENT_QUOTES);
+ }
+
+ $item = array( 'id' => $id,
+ 'type' => $type,
+ 'level' => $lvl,
+ 'open' => $isopen,
+ 'title' => $title,
+ 'hns' => $hns,
+ 'file' => $file,
+ 'return' => $return
+ );
+ $item['sort'] = $this->_setorder($item);
+ $data[] = $item;
+ return $return;
+ }
+
+
+ /**
+ * Index item formatter
+ *
+ * User function for html_buildlist()
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * modified by Samuele Tognini <samuele@netsons.org>
+ */
+ function _html_list_index($item){
+ $ret = '';
+ //namespace
+ if($item['type']=='d' || $item['type']=='l'){
+ $link=$item['id'];
+ $more='idx='.$item['id'];
+ //namespace link
+ if ($item['hns']) {
+ $link=$item['hns'];
+ $tagid="indexmenu_idx_head";
+ $more='';
+ } else {
+ //namespace with headpage
+ $tagid="indexmenu_idx";
+ if ($item['open']) $tagid.=' open';
+ }
+ $ret .= '<a href="'.wl($link,$more).'" class="'.$tagid.'">';
+ $ret .= $item['title'];
+ $ret .= '</a>';
+ }else{
+ //page link
+ $ret .= html_wikilink(':'.$item['id']);
+ }
+ return $ret;
+ }
+
+
+ /**
+ * recurse direcory
+ *
+ * This function recurses into a given base directory
+ * and calls the supplied function for each file and directory
+ *
+ * @param array ref $data The results of the search are stored here
+ * @param string $base Where to start the search
+ * @param callback $func Callback (function name or arayy with object,method)
+ * @param string $dir Current directory beyond $base
+ * @param int $lvl Recursion Level
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * modified by Samuele Tognini <samuele@netsons.org>
+ */
+ function _search(&$data,$base,$func,$opts,$dir='',$lvl=1){
+ $dirs = array();
+ $files = array();
+ $files_tmp=array();
+ $dirs_tmp=array();
+
+ //read in directories and files
+ $dh = @opendir($base.'/'.$dir);
+ if(!$dh) return;
+ while(($file = readdir($dh)) !== false){
+ //skip hidden files and upper dirs
+ if(preg_match('/^[\._]/',$file)) continue;
+ if(is_dir($base.'/'.$dir.'/'.$file)){
+ $dirs[] = $dir.'/'.$file;
+ continue;
+ }
+ $files[] = $dir.'/'.$file;
+ }
+ closedir($dh);
+ //Sort dirs
+ if ($this->nsort) {
+ foreach($dirs as $dir){
+ search_callback($func,$dirs_tmp,$base,$dir,'d',$lvl,$opts);
+ }
+ usort($dirs_tmp,array($this,"_cmp"));
+ foreach ($dirs_tmp as $dir) {
+ $data[]=$dir;
+ if ($dir['return']) $this->_search($data,$base,$func,$opts,$dir['file'],$lvl+1);
+ }
+ } else {
+ sort($dirs);
+ foreach($dirs as $dir){
+ if (search_callback($func,$data,$base,$dir,'d',$lvl,$opts)) $this->_search($data,$base,$func,$opts,$dir,$lvl+1);
+ }
+ }
+ //Sort files
+ foreach($files as $file){
+ search_callback($func,$files_tmp,$base,$file,'f',$lvl,$opts);
+ }
+ usort($files_tmp,array($this,"_cmp"));
+ if (empty($dirs) && empty($files_tmp)) {
+ $v=end($data);
+ if (!$v['hns']) array_pop($data);
+ } else {
+ $data=array_merge($data,$files_tmp);
+ }
+ return true;
+ }
+
+ /**
+ * Sort nodes
+ *
+ */
+ function _cmp($a, $b) {
+ if ($this->rsort) {
+ return strnatcasecmp($b['sort'], $a['sort']);
+ } else {
+ return strnatcasecmp($a['sort'], $b['sort']);
+ }
+ }
+
+
+ /**
+ * Add sort information to item.
+ *
+ * @author Samuele Tognini <samuele@netsons.org>
+ */
+ function _setorder($item) {
+ $sort=false;
+ if ($item['type']=='d') {
+ //Fake order info when nsort is not requested
+ ($this->nsort) ? $page=$item['hns'] : $sort=0;
+ }
+ if ($item['type']=='f') $page=$item['id'];
+ if ($page) {
+ if ($this->msort) $sort=p_get_metadata($page,$this->msort);
+ if (!$sort && $this->sort) {
+ switch ($this->sort) {
+ case 't':
+ $sort=$item['title'];
+ break;
+ case 'd':
+ $sort=@filectime(wikiFN($page));
+ break;
+ }
+ }
+ }
+ if ($sort===false) $sort=noNS($item['id']);
+ return $sort;
+ }
+} //Indexmenu class end
diff --git a/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/syntax/tag.php b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/syntax/tag.php
new file mode 100644
index 000000000..962f7efca
--- /dev/null
+++ b/mod/dokuwiki/vendors/dokuwiki/lib/plugins/indexmenu/syntax/tag.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * Info Indexmenu tag: Tag a page with a sort number.
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Samuele Tognini <samuele@netsons.org>
+ *
+ */
+
+if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
+if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
+require_once(DOKU_PLUGIN.'syntax.php');
+
+/**
+ * All DokuWiki plugins to extend the parser/rendering mechanism
+ * need to inherit from this class
+ */
+class syntax_plugin_indexmenu_tag extends DokuWiki_Syntax_Plugin {
+
+ /**
+ * return some info
+ */
+ function getInfo(){
+ return array(
+ 'author' => 'Samuele Tognini',
+ 'email' => 'samuele@netsons.org',
+ 'date' => rtrim(io_readFile(DOKU_PLUGIN.'indexmenu/VERSION.txt')),
+ 'name' => 'Indexmenu tag',
+ 'desc' => 'Indexmenu tag plugin.',
+ 'url' => 'http://wiki.splitbrain.org/plugin:indexmenu'
+ );
+ }
+
+ /**
+ * What kind of syntax are we?
+ */
+ function getType(){
+ return 'substition';
+ }
+
+ /**
+ * Where to sort in?
+ */
+ function getSort(){
+ return 139;
+ }
+
+ /**
+ * Connect pattern to lexer
+ */
+ function connectTo($mode) {
+ $this->Lexer->addSpecialPattern('{{indexmenu_n>.+?}}',$mode,'plugin_indexmenu_tag');
+ }
+
+ /**
+ * Handle the match
+ */
+ function handle($match, $state, $pos, &$handler){
+ $match = substr($match,14,-2);
+ return array($match);
+ }
+
+ /**
+ * Render output
+ */
+ function render($mode, &$renderer, $data) {
+ if (is_numeric($data[0])) $renderer->meta['indexmenu_n'] = $data[0];;
+ }
+} \ No newline at end of file