import PHPTAL NoPEAR 0.7.0 - files
authorJens Frank <jeluf@users.mediawiki.org>
Tue, 23 Mar 2004 22:22:16 +0000 (22:22 +0000)
committerJens Frank <jeluf@users.mediawiki.org>
Tue, 23 Mar 2004 22:22:16 +0000 (22:22 +0000)
50 files changed:
PHPTAL-NP-0.7.0/COPYING [new file with mode: 0644]
PHPTAL-NP-0.7.0/README [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/Algo/Map.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/GetText.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PEAR.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Attributes.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Name.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Translate.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Define_macro.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Define_slot.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Fill_slot.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Use_macro.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/PHPTAL/Include.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/PHPTAL/Src_include.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Attributes.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Comment.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Condition.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Content.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Define.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Omit_tag.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/On_error.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Repeat.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Replace.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Cache.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Context.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Expression.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/ExpressionFunctions.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Filter.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Generator.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/I18N.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/LoopControler.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Macro.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/OutputControl.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Parser.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/SourceLocator.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/SourceResolver.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Tag.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/Template.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/PHPTAL/XML_Parser.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/Types.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/Types/Code.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/Types/Errors.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/Types/Iterator.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/Types/OArray.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/Types/ODate.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/Types/OHash.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/Types/OString.php [new file with mode: 0644]
PHPTAL-NP-0.7.0/libs/Types/Ref.php [new file with mode: 0644]

diff --git a/PHPTAL-NP-0.7.0/COPYING b/PHPTAL-NP-0.7.0/COPYING
new file mode 100644 (file)
index 0000000..d3a38e5
--- /dev/null
@@ -0,0 +1,504 @@
+                 GNU LESSER GENERAL PUBLIC LICENSE
+                      Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 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.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+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 and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+                 GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, 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 library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete 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 distribute a copy of this License along with the
+Library.
+
+  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 Library or any portion
+of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+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 Library, 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 Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you 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.
+
+  If distribution of 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 satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be 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.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library 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.
+
+  9. 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 Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+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 with
+this License.
+\f
+  11. 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 Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library 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 Library.
+
+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.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library 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.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser 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 Library
+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 Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. 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 LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  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 library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; 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.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/PHPTAL-NP-0.7.0/README b/PHPTAL-NP-0.7.0/README
new file mode 100644 (file)
index 0000000..e910c2e
--- /dev/null
@@ -0,0 +1,12 @@
+PHPTAL for non PEAR users
+
+This package contains PHPTAL and its dependencies.
+
+It also contains the PEAR.php file, used for Error handling in PHPTAL 
+and its dependencies.
+
+Installation:
+
+copy the content of libs in one of your php include path.
+
+
diff --git a/PHPTAL-NP-0.7.0/libs/Algo/Map.php b/PHPTAL-NP-0.7.0/libs/Algo/Map.php
new file mode 100644 (file)
index 0000000..eb431b6
--- /dev/null
@@ -0,0 +1,206 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+// $id$
+
+define('ALGO_MAP_VERSION', '0.1.1');
+       
+/**
+ * Applies a callback(or code) to the elements of given arrays.
+ * 
+ * This function acts much like the perl 'map' keyword, it pass through all 
+ * array parameters and apply a callback function to each elements of 
+ * these arrays.
+ *
+ * See examples below to an overview of Algo_map() usage.
+ *
+ * *IMPORTANT*
+ *
+ * Please note that the callback function needs to return something, when you
+ * don't want your function to return an element or an hashtable, just return
+ * an empty array().
+ *
+ * 
+ * example 1 : Simple use, this example compose an hashtable with an array.
+ * 
+ * <?php
+ * function myfunc($a)
+ * {
+ *      return array($a=>1);
+ * }
+ *
+ * $a_pam = array("apple", "pie", "cherry");
+ *
+ * $result = Algo_map('myfunc', $a_pam);
+ *
+ * // $result ==> array("apple"=>1, "pie"=>1, "cherry"=>1);
+ * ?>
+ *
+ * You can pass more than one array as parameters. The number of elements of
+ * each array should be at least equal to the number of elements of the first
+ * array.
+ *
+ * If count($a1) > count($a2), elements of $a2 that doesn't exists
+ * will be replaced by a false value.
+ *
+ * 
+ * example 2 : Using more than one array with Algo_map()
+ * 
+ * <?php
+ * function myfunc($a, $b)
+ * {
+ *      return array($a * $b);
+ * }
+ *
+ * $a_nbr = array(1,2,3,4);
+ * $b_nbr = array(1,2,4,8,16);
+ *
+ * $result = Algo_map('myfunc', $a_nbr, $b_nbr);
+ *
+ * // $result ==> array(1, 4, 12, 32);
+ * ?>
+ * 
+ *
+ * example 3 : Problem of array size
+ * 
+ * <?php
+ * function myfunc($a, $b)
+ * {
+ *      return array($a * $b);
+ * }
+ * 
+ * $a_nbr = array(1,2,3,4,16);
+ * $b_nbr = array(1,2,4,8);
+ *
+ * $result = Algo_map('myfunc', $a_nbr, $b_nbr);
+ *
+ * // $result ==> array(1, 4, 12, 32, 0);
+ * // the fifth element is equal to 0 because the fifth element of $b_nbr
+ * // doesn't exists and is replaced by false(ie:0) in the callback
+ * // function.
+ * ?>
+ * 
+ * 
+ * example 4 : Defining the function code inside the Algo_map() call
+ * 
+ * <?php
+ * $a_t = array("a","b","c","d");
+ * $b_t = array("z","b","e","d");
+ * 
+ * $result = Algo_map(
+ *      // first element match the function arguments two vars $a and $b 
+ *      // which will be filled with $a_t[x] and $b_t[x] for x=0 to len(a)
+ *      '$a,$b',
+ *      // the second parameter is the callback function code
+ *      // map always return an array (or an hashtable)
+ *      'return($a==$b ? $a : array());',
+ *      $a_t,
+ *      $b_t
+ *     );
+ * 
+ * // $result ==> array("b","d");
+ * ?>
+ * 
+ *
+ * example 5 : Object method callback
+ * 
+ * <?php
+ * class Foo {
+ *     function myCallback($a){
+ *         return "-$a-";
+ *     }
+ * };
+ *
+ * $foo = new Foo();
+ * $array = array('a','b','c');
+ * $result = Algo_map($foo, 'myCallback', $array);
+ *
+ * // $result = array('-a-', '-b-', '-c-');
+ * ?>
+ * 
+ * 
+ * @param  mixed ... See examples
+ * @return array
+ * @author Laurent Bedubourg <codebringer@free.fr>
+ * @date   2001-09-20
+ */
+function Algo_map()
+{
+    // we retrieve the list of map arguments
+    $argv = func_get_args();
+    // the first argument is the function name
+    $func = array_shift($argv);
+
+    if (is_object($func)) {
+        // if first argument is an object, this map
+        // has a callback to some method
+        $obj  = $func;
+        $func = array_shift($argv);     
+    } else if (!function_exists($func)) {
+        // if the function isn't defined,
+        // we'll try to create the function
+        // the first argument was the string
+        // of function arguments(ie:'$a,$b,$c')
+
+        // The code is the second argument
+        $code = array_shift($argv);
+
+        // We create the new function
+        // it will be a lambda style function
+        $func = create_function($func, $code);
+    }
+
+    // prepare the result array
+    $result = array();
+
+    // we'll apply the new function to
+    // each element of arrays passed as
+    // parameters
+    while (count($argv[0]) > 0) {
+        // prepare the array of arguments
+        $fargs = array();
+        
+        for($i = 0; $i < count($argv); $i++) {
+            // for each array to map
+            // we add the next element of the
+            // array to the argument array
+            $fargs[] = array_shift($argv[$i]);
+        }
+
+        if (isset($obj)) {
+            $result = array_merge($result,
+                                  call_user_func_array(array($obj,$func),
+                                                       $fargs));
+        } else {
+            // we merge the result of the function
+            // with allready found results
+            $result = array_merge($result,
+                                  // call the function with the array
+                                  // of arguments
+                                  call_user_func_array($func, $fargs));
+        }
+    }
+
+    // let's return the result array
+    return $result;
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/GetText.php b/PHPTAL-NP-0.7.0/libs/GetText.php
new file mode 100644 (file)
index 0000000..029d51b
--- /dev/null
@@ -0,0 +1,616 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+require_once "PEAR.php";
+
+define('GETTEXT_NATIVE', 1);
+define('GETTEXT_PHP', 2);
+
+/**
+ * Generic gettext static class.
+ *
+ * This class allows gettext usage with php even if the gettext support is 
+ * not compiled in php.
+ *
+ * The developper can choose between the GETTEXT_NATIVE support and the
+ * GETTEXT_PHP support on initialisation. If native is not supported, the
+ * system will fall back to PHP support.
+ *
+ * On both systems, this package add a variable interpolation system so you can
+ * translate entire dynamic sentences in stead of peace of sentences.
+ *
+ * Small example without pear error lookup :
+ * 
+ * <?php
+ * require_once "GetText.php";
+ *
+ * GetText::init();
+ * GetText::setLanguage('fr_Fr');      // may throw GetText_Error
+ * GetText::addDomain('myAppDomain');  // may throw GetText_Error
+ * GetText::setVar('login', $login);   
+ * GetText::setVar('name', $name);
+ * 
+ * // may throw GetText_Error
+ * echo GetText::gettext('Welcome ${name}, you\'re connected with login ${login}');
+ * 
+ * // should echo something like :
+ * //
+ * // "Bienvenue Jean-Claude, vous Ãªtes connecté en tant qu'utilisateur jcaccount"
+ * // 
+ * // or if fr_FR translation does not exists
+ * //
+ * // "Welcome Jean-Claude, you're connected with login jcaccount"
+ * 
+ * ?>
+ *
+ * A gettext mini-howto should be provided with this package, if you're new 
+ * to gettext usage, please read it to learn how to build a gettext 
+ * translation directory (locale).
+ * 
+ * @todo    Tools to manage gettext files in php.
+ * 
+ *          - non traducted domains / keys
+ *          - modification of keys
+ *          - domain creation, preparation, delete, ...
+ *          - tool to extract required messages from TOF templates
+ *
+ * @version 0.5
+ * @author  Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class GetText
+{
+    /**
+     * This method returns current gettext support class.
+     *
+     * @return GetText_Support
+     * @static 1
+     * @access private
+     */
+    function &_support($set=false)
+    { 
+        static $supportObject;
+        if ($set !== false) { 
+            $supportObject = $set; 
+        } elseif (!isset($supportObject)) {
+            trigger_error("GetText not initialized !". endl.
+                          "Please call GetText::init() before calling ".
+                          "any GetText function !".endl
+                          , E_USER_ERROR);
+        }
+        return $supportObject;
+    }
+    
+    /**
+     * Initialize gettext package.
+     *
+     * This method instantiate the gettext support depending on managerType
+     * value. 
+     *
+     * GETTEXT_NATIVE try to use gettext php support and fail back to PHP
+     * support if not installed.
+     *
+     * GETTEXT_PHP explicitely request the usage of PHP support.
+     *
+     * @param  int $managerType
+     *         Gettext support type.
+     *         
+     * @access public
+     * @static 1
+     */
+    function init($managerType = GETTEXT_NATIVE)
+    {
+        if ($managerType == GETTEXT_NATIVE) {
+            if (function_exists('gettext')) {
+                return GetText::_support(new GetText_NativeSupport());
+            }
+        }
+        // fail back to php support 
+        return GetText::_support(new GetText_PHPSupport());
+    }
+    
+    /**
+     * Set the language to use for traduction.
+     *
+     * @param string $langCode
+     *        The language code usually defined as ll_CC, ll is the two letter
+     *        language code and CC is the two letter country code.
+     *
+     * @throws GetText_Error if language is not supported by your system.
+     */
+    function setLanguage($langCode)
+    {
+        $support =& GetText::_support();
+        return $support->setLanguage($langCode);
+    }
+    
+    /**
+     * Add a translation domain.
+     *
+     * The domain name is usually the name of the .po file you wish to use. 
+     * For example, if you created a file 'locale/ll_CC/LC_MESSAGES/myapp.po',
+     * you'll use 'myapp' as the domain name.
+     *
+     * @param string $domain
+     *        The domain name.
+     *
+     * @param string $path optional
+     *        The path to the locale directory (ie: /path/to/locale/) which
+     *        contains ll_CC directories.
+     */
+    function addDomain($domain, $path=false)
+    {
+        $support =& GetText::_support();
+        return $support->addDomain($domain, $path);
+    }
+    
+    /**
+     * Retrieve the translation for specified key.
+     *
+     * @param string $key
+     *        String to translate using gettext support.
+     */
+    function gettext($key)
+    { 
+        $support =& GetText::_support();
+        return $support->gettext($key);
+    }
+   
+    /**
+     * Add a variable to gettext interpolation system.
+     *
+     * @param string $key
+     *        The variable name.
+     *
+     * @param string $value
+     *        The variable value.
+     */
+    function setVar($key, $value)
+    {
+        $support =& GetText::_support();
+        return $support->setVar($key, $value);
+    }
+
+    /**
+     * Add an hashtable of variables.
+     *
+     * @param hashtable $hash 
+     *        PHP associative array of variables.
+     */
+    function setVars($hash)
+    {
+        $support =& GetText::_support();
+        return $support->setVars($hash);
+    }
+
+    /**
+     * Reset interpolation variables.
+     */
+    function reset()
+    {
+        $support =& GetText::_support();
+        return $support->reset();
+    }
+}
+
+
+/**
+ * Interface to gettext native support.
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ * @access private
+ */
+class GetText_NativeSupport 
+{
+    var $_interpolationVars = array();
+
+    /**
+     * Set gettext language code.
+     * @throws GetText_Error
+     */
+    function setLanguage($langCode)
+    {
+        putenv("LANG=$langCode");
+        putenv("LC_ALL=$langCode");
+        putenv("LANGUAGE=$langCode");
+        $set = setlocale(LC_ALL, "$langCode");
+        if ($set === false) {
+            $str = sprintf('Language code "%s" not supported by your system',
+                           $langCode);
+            $err = new GetText_Error($str);
+            return PEAR::raiseError($err);
+        }
+    }
+    
+    /**
+     * Add a translation domain.
+     */
+    function addDomain($domain, $path=false)
+    {
+        if ($path === false) {
+            bindtextdomain($domain, "./locale/");
+        } else { 
+            bindtextdomain($domain, $path);
+        }
+        textdomain($domain);
+    }
+    
+    /**
+     * Retrieve translation for specified key.
+     *
+     * @access private
+     */
+    function _getTranslation($key)
+    {
+        return gettext($key);
+    }
+    
+
+    /**
+     * Reset interpolation variables.
+     */
+    function reset()
+    {
+        $this->_interpolationVars = array();
+    }
+    
+    /**
+     * Set an interpolation variable.
+     */
+    function setVar($key, $value)
+    {
+        $this->_interpolationVars[$key] = $value;
+    }
+
+    /**
+     * Set an associative array of interpolation variables.
+     */
+    function setVars($hash)
+    {
+        $this->_interpolationVars = array_merge($this->_interpolationVars,
+                                                $hash);
+    }
+    
+    /**
+     * Retrieve translation for specified key.
+     *
+     * @param  string $key  -- gettext msgid
+     * @throws GetText_Error
+     */
+    function gettext($key)
+    {
+        $value = $this->_getTranslation($key);
+        if ($value === false) {
+            $str = sprintf('Unable to locate gettext key "%s"', $key);
+            $err = new GetText_Error($str);
+            return PEAR::raiseError($err);
+        }
+        
+        while (preg_match('/\$\{(.*?)\}/sm', $value, $m)) {
+            list($src, $var) = $m;
+
+            // retrieve variable to interpolate in context, throw an exception
+            // if not found.
+            $varValue = $this->_getVar($var);
+            if ($varValue === false) {
+                $str = sprintf('Interpolation error, var "%s" not set', $var);
+                $err = new GetText_Error($str);
+                return PEAR::raiseError($err);
+            }
+            $value = str_replace($src, $varValue, $value);
+        }
+        return $value;
+    }
+
+    /**
+     * Retrieve an interpolation variable value.
+     * 
+     * @return mixed
+     * @access private
+     */
+    function _getVar($name)
+    {
+        if (!array_key_exists($name, $this->_interpolationVars)) {
+            return false;
+        }
+        return $this->_interpolationVars[$name];
+    }
+}
+
+
+/**
+ * Implementation of GetText support for PHP.
+ *
+ * This implementation is abble to cache .po files into php files returning the
+ * domain translation hashtable.
+ *
+ * @access private
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class GetText_PHPSupport extends GetText_NativeSupport
+{
+    var $_path     = 'locale/';
+    var $_langCode = false;
+    var $_domains  = array();
+    var $_end      = -1;
+    var $_jobs     = array();
+
+    /**
+     * Set the translation domain.
+     *
+     * @param  string $langCode -- language code
+     * @throws GetText_Error
+     */
+    function setLanguage($langCode)
+    {
+        // if language already set, try to reload domains
+        if ($this->_langCode !== false and $this->_langCode != $langCode) {
+            foreach ($this->_domains as $domain) {
+                $this->_jobs[] = array($domain->name, $domain->path);
+            }
+            $this->_domains = array();
+            $this->_end = -1;
+        }
+        
+        $this->_langCode = $langCode;
+
+        // this allow us to set the language code after 
+        // domain list.
+        while (count($this->_jobs) > 0) {
+            list($domain, $path) = array_shift($this->_jobs);
+            $err = $this->addDomain($domain, $path);
+            // error raised, break jobs
+            if (PEAR::isError($err)) {
+                return $err;
+            }
+        }
+    }
+    
+    /**
+     * Add a translation domain.
+     *
+     * @param string $domain        -- Domain name
+     * @param string $path optional -- Repository path
+     * @throws GetText_Error
+     */
+    function addDomain($domain, $path = "./locale/")
+    {   
+        if (array_key_exists($domain, $this->_domains)) { 
+            return; 
+        }
+        
+        if (!$this->_langCode) { 
+            $this->_jobs[] = array($domain, $path); 
+            return;
+        }
+
+        $err = $this->_loadDomain($domain, $path);
+        if (PEAR::isError($err)) {
+            return $err;
+        }
+
+        $this->_end++;
+    }
+
+    /**
+     * Load a translation domain file.
+     *
+     * This method cache the translation hash into a php file unless
+     * GETTEXT_NO_CACHE is defined.
+     * 
+     * @param  string $domain        -- Domain name
+     * @param  string $path optional -- Repository
+     * @throws GetText_Error
+     * @access private
+     */
+    function _loadDomain($domain, $path = "./locale")
+    {
+        $srcDomain = $path . "/$this->_langCode/LC_MESSAGES/$domain.po";
+        $phpDomain = $path . "/$this->_langCode/LC_MESSAGES/$domain.php";
+        
+        if (!file_exists($srcDomain)) {
+            $str = sprintf('Domain file "%s" not found.', $srcDomain);
+            $err = new GetText_Error($str);
+            return PEAR::raiseError($err);
+        }
+        
+        $d = new GetText_Domain();
+        $d->name = $domain;
+        $d->path = $path;
+        
+        if (!file_exists($phpDomain) 
+            || (filemtime($phpDomain) < filemtime($srcDomain))) {
+            
+            // parse and compile translation table
+            $parser = new GetText_PHPSupport_Parser();
+            $hash   = $parser->parse($srcDomain);
+            if (!defined('GETTEXT_NO_CACHE')) {
+                $comp = new GetText_PHPSupport_Compiler();
+                $err  = $comp->compile($hash, $srcDomain);
+                if (PEAR::isError($err)) { 
+                    return $err; 
+                }
+            }
+            $d->_keys = $hash;
+        } else {
+            $d->_keys = include $phpDomain;
+        }
+        $this->_domains[] =& $d;
+    }
+    
+    /**
+     * Implementation of gettext message retrieval.
+     */
+    function _getTranslation($key)
+    {
+        for ($i = $this->_end; $i >= 0; $i--) {
+            if ($this->_domains[$i]->hasKey($key)) {
+                return $this->_domains[$i]->get($key);
+            }
+        }
+        return $key;
+    }
+}
+
+/**
+ * Class representing a domain file for a specified language.
+ *
+ * @access private
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class GetText_Domain
+{
+    var $name;
+    var $path;
+
+    var $_keys = array();
+
+    function hasKey($key)
+    {
+        return array_key_exists($key, $this->_keys);
+    }
+
+    function get($key)
+    {
+        return $this->_keys[$key];
+    }
+}
+
+/**
+ * This class is used to parse gettext '.po' files into php associative arrays.
+ *
+ * @access private
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class GetText_PHPSupport_Parser 
+{
+    var $_hash = array();
+    var $_currentKey;
+    var $_currentValue;
+    
+    /**
+     * Parse specified .po file.
+     *
+     * @return hashtable
+     * @throws GetText_Error
+     */
+    function parse($file)
+    {
+        $this->_hash = array();
+        $this->_currentKey = false;
+        $this->_currentValue = "";
+        
+        if (!file_exists($file)) {
+            $str = sprintf('Unable to locate file "%s"', $file);
+            $err = new GetText_Error($str);
+            return PEAR::raiseError($err);
+        }
+        $i=0;
+        $lines = file($file);
+        foreach ($lines as $line) {
+            $this->_parseLine($line, ++$i);
+        }
+        $this->_storeKey();
+
+        return $this->_hash;
+    }
+
+    /**
+     * Parse one po line.
+     *
+     * @access private
+     */
+    function _parseLine($line, $nbr)
+    {
+        if (preg_match('/^\s*?#/', $line)) { return; }
+        if (preg_match('/^\s*?msgid \"(.*?)(?!<\\\)\"/', $line, $m)) {
+            $this->_storeKey();
+            $this->_currentKey = $m[1];
+            return;
+        }
+        if (preg_match('/^\s*?msgstr \"(.*?)(?!<\\\)\"/', $line, $m)) {
+            $this->_currentValue .= $m[1];
+            return;
+        }
+        if (preg_match('/^\s*?\"(.*?)(?!<\\\)\"/', $line, $m)) {
+            $this->_currentValue .= $m[1];
+            return;
+        }
+    }
+
+    /**
+     * Store last key/value pair into building hashtable.
+     *
+     * @access private
+     */
+    function _storeKey()
+    {
+        if ($this->_currentKey === false) return;
+        $this->_currentValue = str_replace('\\n', "\n", $this->_currentValue);
+        $this->_hash[$this->_currentKey] = $this->_currentValue;
+        $this->_currentKey = false;
+        $this->_currentValue = "";
+    }
+}
+
+
+/**
+ * This class write a php file from a gettext hashtable.
+ *
+ * The produced file return the translation hashtable on include.
+ * 
+ * @throws GetText_Error
+ * @access private
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class GetText_PHPSupport_Compiler 
+{
+    /**
+     * Write hash in an includable php file.
+     */
+    function compile(&$hash, $sourcePath)
+    {
+        $destPath = preg_replace('/\.po$/', '.php', $sourcePath);
+        $fp = @fopen($destPath, "w");
+        if (!$fp) {
+            $str = sprintf('Unable to open "%s" in write mode.', $destPath);
+            $err = new GetText_Error($str);
+            return PEAR::raiseError($err);
+        }
+        fwrite($fp, '<?php' . "\n");
+        fwrite($fp, 'return array(' . "\n");
+        foreach ($hash as $key => $value) {
+            $key   = str_replace("'", "\\'", $key);
+            $value = str_replace("'", "\\'", $value);
+            fwrite($fp, '    \'' . $key . '\' => \'' . $value . "',\n");
+        }
+        fwrite($fp, ');' . "\n");
+        fwrite($fp, '?>');
+        fclose($fp);
+    }
+}
+
+/**
+ * GetText related error.
+ */
+class GetText_Error extends PEAR_Error {}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PEAR.php b/PHPTAL-NP-0.7.0/libs/PEAR.php
new file mode 100644 (file)
index 0000000..7f034b7
--- /dev/null
@@ -0,0 +1,945 @@
+<?php
+//
+// +----------------------------------------------------------------------+
+// | PHP Version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Sterling Hughes <sterling@php.net>                          |
+// |          Stig Bakken <ssb@fast.no>                                   |
+// |          Tomas V.V.Cox <cox@idecnet.com>                             |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+//
+
+define('PEAR_ERROR_RETURN',   1);
+define('PEAR_ERROR_PRINT',    2);
+define('PEAR_ERROR_TRIGGER',  4);
+define('PEAR_ERROR_DIE',      8);
+define('PEAR_ERROR_CALLBACK', 16);
+define('PEAR_ZE2', (function_exists('version_compare') &&
+                    version_compare(zend_version(), "2-dev", "ge")));
+
+if (substr(PHP_OS, 0, 3) == 'WIN') {
+    define('OS_WINDOWS', true);
+    define('OS_UNIX',    false);
+    define('PEAR_OS',    'Windows');
+} else {
+    define('OS_WINDOWS', false);
+    define('OS_UNIX',    true);
+    define('PEAR_OS',    'Unix'); // blatant assumption
+}
+
+$GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
+$GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
+$GLOBALS['_PEAR_destructor_object_list'] = array();
+$GLOBALS['_PEAR_shutdown_funcs']         = array();
+$GLOBALS['_PEAR_error_handler_stack']    = array();
+
+ini_set('track_errors', true);
+
+/**
+ * Base class for other PEAR classes.  Provides rudimentary
+ * emulation of destructors.
+ *
+ * If you want a destructor in your class, inherit PEAR and make a
+ * destructor method called _yourclassname (same name as the
+ * constructor, but with a "_" prefix).  Also, in your constructor you
+ * have to call the PEAR constructor: $this->PEAR();.
+ * The destructor method will be called without parameters.  Note that
+ * at in some SAPI implementations (such as Apache), any output during
+ * the request shutdown (in which destructors are called) seems to be
+ * discarded.  If you need to get any debug information from your
+ * destructor, use error_log(), syslog() or something similar.
+ *
+ * IMPORTANT! To use the emulated destructors you need to create the
+ * objects by reference, ej: $obj =& new PEAR_child;
+ *
+ * @since PHP 4.0.2
+ * @author Stig Bakken <ssb@fast.no>
+ * @see http://pear.php.net/manual/
+ */
+class PEAR
+{
+    // {{{ properties
+
+    /**
+     * Whether to enable internal debug messages.
+     *
+     * @var     bool
+     * @access  private
+     */
+    var $_debug = false;
+
+    /**
+     * Default error mode for this object.
+     *
+     * @var     int
+     * @access  private
+     */
+    var $_default_error_mode = null;
+
+    /**
+     * Default error options used for this object when error mode
+     * is PEAR_ERROR_TRIGGER.
+     *
+     * @var     int
+     * @access  private
+     */
+    var $_default_error_options = null;
+
+    /**
+     * Default error handler (callback) for this object, if error mode is
+     * PEAR_ERROR_CALLBACK.
+     *
+     * @var     string
+     * @access  private
+     */
+    var $_default_error_handler = '';
+
+    /**
+     * Which class to use for error objects.
+     *
+     * @var     string
+     * @access  private
+     */
+    var $_error_class = 'PEAR_Error';
+
+    /**
+     * An array of expected errors.
+     *
+     * @var     array
+     * @access  private
+     */
+    var $_expected_errors = array();
+
+    // }}}
+
+    // {{{ constructor
+
+    /**
+     * Constructor.  Registers this object in
+     * $_PEAR_destructor_object_list for destructor emulation if a
+     * destructor object exists.
+     *
+     * @param string $error_class  (optional) which class to use for
+     *        error objects, defaults to PEAR_Error.
+     * @access public
+     * @return void
+     */
+    function PEAR($error_class = null)
+    {
+        $classname = get_class($this);
+        if ($this->_debug) {
+            print "PEAR constructor called, class=$classname\n";
+        }
+        if ($error_class !== null) {
+            $this->_error_class = $error_class;
+        }
+        while ($classname) {
+            $destructor = "_$classname";
+            if (method_exists($this, $destructor)) {
+                global $_PEAR_destructor_object_list;
+                $_PEAR_destructor_object_list[] = &$this;
+                break;
+            } else {
+                $classname = get_parent_class($classname);
+            }
+        }
+    }
+
+    // }}}
+    // {{{ destructor
+
+    /**
+     * Destructor (the emulated type of...).  Does nothing right now,
+     * but is included for forward compatibility, so subclass
+     * destructors should always call it.
+     *
+     * See the note in the class desciption about output from
+     * destructors.
+     *
+     * @access public
+     * @return void
+     */
+    function _PEAR() {
+        if ($this->_debug) {
+            printf("PEAR destructor called, class=%s\n", get_class($this));
+        }
+    }
+
+    // }}}
+    // {{{ getStaticProperty()
+
+    /**
+    * If you have a class that's mostly/entirely static, and you need static
+    * properties, you can use this method to simulate them. Eg. in your method(s)
+    * do this: $myVar = &PEAR::getStaticProperty('myVar');
+    * You MUST use a reference, or they will not persist!
+    *
+    * @access public
+    * @param  string $class  The calling classname, to prevent clashes
+    * @param  string $var    The variable to retrieve.
+    * @return mixed   A reference to the variable. If not set it will be
+    *                 auto initialised to NULL.
+    */
+    function &getStaticProperty($class, $var)
+    {
+        static $properties;
+        return $properties[$class][$var];
+    }
+
+    // }}}
+    // {{{ registerShutdownFunc()
+
+    /**
+    * Use this function to register a shutdown method for static
+    * classes.
+    *
+    * @access public
+    * @param  mixed $func  The function name (or array of class/method) to call
+    * @param  mixed $args  The arguments to pass to the function
+    * @return void
+    */
+    function registerShutdownFunc($func, $args = array())
+    {
+        $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
+    }
+
+    // }}}
+    // {{{ isError()
+
+    /**
+     * Tell whether a value is a PEAR error.
+     *
+     * @param   mixed $data   the value to test
+     * @access  public
+     * @return  bool    true if parameter is an error
+     */
+    function isError($data) {
+        return (bool)(is_object($data) &&
+                      (get_class($data) == 'pear_error' ||
+                      is_subclass_of($data, 'pear_error')));
+    }
+
+    // }}}
+    // {{{ setErrorHandling()
+
+    /**
+     * Sets how errors generated by this DB object should be handled.
+     * Can be invoked both in objects and statically.  If called
+     * statically, setErrorHandling sets the default behaviour for all
+     * PEAR objects.  If called in an object, setErrorHandling sets
+     * the default behaviour for that object.
+     *
+     * @param int $mode
+     *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
+     *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE or
+     *        PEAR_ERROR_CALLBACK.
+     *
+     * @param mixed $options
+     *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
+     *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
+     *
+     *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
+     *        to be the callback function or method.  A callback
+     *        function is a string with the name of the function, a
+     *        callback method is an array of two elements: the element
+     *        at index 0 is the object, and the element at index 1 is
+     *        the name of the method to call in the object.
+     *
+     *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
+     *        a printf format string used when printing the error
+     *        message.
+     *
+     * @access public
+     * @return void
+     * @see PEAR_ERROR_RETURN
+     * @see PEAR_ERROR_PRINT
+     * @see PEAR_ERROR_TRIGGER
+     * @see PEAR_ERROR_DIE
+     * @see PEAR_ERROR_CALLBACK
+     *
+     * @since PHP 4.0.5
+     */
+
+    function setErrorHandling($mode = null, $options = null)
+    {
+        if (isset($this)) {
+            $setmode     = &$this->_default_error_mode;
+            $setoptions  = &$this->_default_error_options;
+        } else {
+            $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
+            $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
+        }
+
+        switch ($mode) {
+            case PEAR_ERROR_RETURN:
+            case PEAR_ERROR_PRINT:
+            case PEAR_ERROR_TRIGGER:
+            case PEAR_ERROR_DIE:
+            case null:
+                $setmode = $mode;
+                $setoptions = $options;
+                break;
+
+            case PEAR_ERROR_CALLBACK:
+                $setmode = $mode;
+                if ((is_string($options) && function_exists($options)) ||
+                    (is_array($options) && method_exists(@$options[0], @$options[1])))
+                {
+                    $setoptions = $options;
+                } else {
+                    trigger_error("invalid error callback", E_USER_WARNING);
+                }
+                break;
+
+            default:
+                trigger_error("invalid error mode", E_USER_WARNING);
+                break;
+        }
+    }
+
+    // }}}
+    // {{{ expectError()
+
+    /**
+     * This method is used to tell which errors you expect to get.
+     * Expected errors are always returned with error mode
+     * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
+     * and this method pushes a new element onto it.  The list of
+     * expected errors are in effect until they are popped off the
+     * stack with the popExpect() method.
+     *
+     * Note that this method can not be called statically
+     *
+     * @param mixed $code a single error code or an array of error codes to expect
+     *
+     * @return int     the new depth of the "expected errors" stack
+     * @access public
+     */
+    function expectError($code = '*')
+    {
+        if (is_array($code)) {
+            array_push($this->_expected_errors, $code);
+        } else {
+            array_push($this->_expected_errors, array($code));
+        }
+        return sizeof($this->_expected_errors);
+    }
+
+    // }}}
+    // {{{ popExpect()
+
+    /**
+     * This method pops one element off the expected error codes
+     * stack.
+     *
+     * @return array   the list of error codes that were popped
+     */
+    function popExpect()
+    {
+        return array_pop($this->_expected_errors);
+    }
+
+    // }}}
+    // {{{ _checkDelExpect()
+
+    /**
+     * This method checks unsets an error code if available
+     *
+     * @param mixed error code
+     * @return bool true if the error code was unset, false otherwise
+     * @access private
+     * @since PHP 4.3.0
+     */
+    function _checkDelExpect($error_code)
+    {
+        $deleted = false;
+
+        foreach ($this->_expected_errors AS $key => $error_array) {
+            if (in_array($error_code, $error_array)) {
+                unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
+                $deleted = true;
+            }
+
+            // clean up empty arrays
+            if (0 == count($this->_expected_errors[$key])) {
+                unset($this->_expected_errors[$key]);
+            }
+        }
+        return $deleted;
+    }
+
+    // }}}
+    // {{{ delExpect()
+
+    /**
+     * This method deletes all occurences of the specified element from
+     * the expected error codes stack.
+     *
+     * @param  mixed $error_code error code that should be deleted
+     * @return mixed list of error codes that were deleted or error
+     * @access public
+     * @since PHP 4.3.0
+     */
+    function delExpect($error_code)
+    {
+        $deleted = false;
+
+        if ((is_array($error_code) && (0 != count($error_code)))) {
+            // $error_code is a non-empty array here;
+            // we walk through it trying to unset all
+            // values
+            foreach($error_code AS $key => $error) {
+                if ($this->_checkDelExpect($error)) {
+                    $deleted =  true;
+                } else {
+                    $deleted = false;
+                }
+            }
+            return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
+        } elseif (!empty($error_code)) {
+            // $error_code comes alone, trying to unset it
+            if ($this->_checkDelExpect($error_code)) {
+                return true;
+            } else {
+                return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
+            }
+        } else {
+            // $error_code is empty
+            return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
+        }
+    }
+
+    // }}}
+    // {{{ raiseError()
+
+    /**
+     * This method is a wrapper that returns an instance of the
+     * configured error class with this object's default error
+     * handling applied.  If the $mode and $options parameters are not
+     * specified, the object's defaults are used.
+     *
+     * @param mixed $message a text error message or a PEAR error object
+     *
+     * @param int $code      a numeric error code (it is up to your class
+     *                  to define these if you want to use codes)
+     *
+     * @param int $mode      One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
+     *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE or
+     *                  PEAR_ERROR_CALLBACK.
+     *
+     * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
+     *                  specifies the PHP-internal error level (one of
+     *                  E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
+     *                  If $mode is PEAR_ERROR_CALLBACK, this
+     *                  parameter specifies the callback function or
+     *                  method.  In other error modes this parameter
+     *                  is ignored.
+     *
+     * @param string $userinfo If you need to pass along for example debug
+     *                  information, this parameter is meant for that.
+     *
+     * @param string $error_class The returned error object will be
+     *                  instantiated from this class, if specified.
+     *
+     * @param bool $skipmsg If true, raiseError will only pass error codes,
+     *                  the error message parameter will be dropped.
+     *
+     * @access public
+     * @return object   a PEAR error object
+     * @see PEAR::setErrorHandling
+     * @since PHP 4.0.5
+     */
+    function &raiseError($message = null,
+                         $code = null,
+                         $mode = null,
+                         $options = null,
+                         $userinfo = null,
+                         $error_class = null,
+                         $skipmsg = false)
+    {
+        // The error is yet a PEAR error object
+        if (is_object($message)) {
+            $code        = $message->getCode();
+            $userinfo    = $message->getUserInfo();
+            $error_class = $message->getType();
+            $message     = $message->getMessage();
+        }
+
+        if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) {
+            if ($exp[0] == "*" ||
+                (is_int(reset($exp)) && in_array($code, $exp)) ||
+                (is_string(reset($exp)) && in_array($message, $exp))) {
+                $mode = PEAR_ERROR_RETURN;
+            }
+        }
+        // No mode given, try global ones
+        if ($mode === null) {
+            // Class error handler
+            if (isset($this) && isset($this->_default_error_mode)) {
+                $mode    = $this->_default_error_mode;
+                $options = $this->_default_error_options;
+            // Global error handler
+            } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
+                $mode    = $GLOBALS['_PEAR_default_error_mode'];
+                $options = $GLOBALS['_PEAR_default_error_options'];
+            }
+        }
+
+        if ($error_class !== null) {
+            $ec = $error_class;
+        } elseif (isset($this) && isset($this->_error_class)) {
+            $ec = $this->_error_class;
+        } else {
+            $ec = 'PEAR_Error';
+        }
+        if ($skipmsg) {
+            return new $ec($code, $mode, $options, $userinfo);
+        } else {
+            return new $ec($message, $code, $mode, $options, $userinfo);
+        }
+    }
+
+    // }}}
+    // {{{ throwError()
+
+    /**
+     * Simpler form of raiseError with fewer options.  In most cases
+     * message, code and userinfo are enough.
+     *
+     * @param string $message
+     *
+     */
+    function &throwError($message = null,
+                         $code = null,
+                         $userinfo = null)
+    {
+        if (isset($this)) {
+            return $this->raiseError($message, $code, null, null, $userinfo);
+        } else {
+            return PEAR::raiseError($message, $code, null, null, $userinfo);
+        }
+    }
+
+    // }}}
+    // {{{ pushErrorHandling()
+
+    /**
+     * Push a new error handler on top of the error handler options stack. With this
+     * you can easily override the actual error handler for some code and restore
+     * it later with popErrorHandling.
+     *
+     * @param mixed $mode (same as setErrorHandling)
+     * @param mixed $options (same as setErrorHandling)
+     *
+     * @return bool Always true
+     *
+     * @see PEAR::setErrorHandling
+     */
+    function pushErrorHandling($mode, $options = null)
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        if (isset($this)) {
+            $def_mode    = &$this->_default_error_mode;
+            $def_options = &$this->_default_error_options;
+        } else {
+            $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
+            $def_options = &$GLOBALS['_PEAR_default_error_options'];
+        }
+        $stack[] = array($def_mode, $def_options);
+
+        if (isset($this)) {
+            $this->setErrorHandling($mode, $options);
+        } else {
+            PEAR::setErrorHandling($mode, $options);
+        }
+        $stack[] = array($mode, $options);
+        return true;
+    }
+
+    // }}}
+    // {{{ popErrorHandling()
+
+    /**
+    * Pop the last error handler used
+    *
+    * @return bool Always true
+    *
+    * @see PEAR::pushErrorHandling
+    */
+    function popErrorHandling()
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        array_pop($stack);
+        list($mode, $options) = $stack[sizeof($stack) - 1];
+        array_pop($stack);
+        if (isset($this)) {
+            $this->setErrorHandling($mode, $options);
+        } else {
+            PEAR::setErrorHandling($mode, $options);
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ loadExtension()
+
+    /**
+    * OS independant PHP extension load. Remember to take care
+    * on the correct extension name for case sensitive OSes.
+    *
+    * @param string $ext The extension name
+    * @return bool Success or not on the dl() call
+    */
+    function loadExtension($ext)
+    {
+        if (!extension_loaded($ext)) {
+            if (OS_WINDOWS) {
+                $suffix = '.dll';
+            } elseif (PHP_OS == 'HP-UX') {
+                $suffix = '.sl';
+            } elseif (PHP_OS == 'AIX') {
+                $suffix = '.a';
+            } elseif (PHP_OS == 'OSX') {
+                $suffix = '.bundle';
+            } else {
+                $suffix = '.so';
+            }
+            return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
+        }
+        return true;
+    }
+
+    // }}}
+}
+
+// {{{ _PEAR_call_destructors()
+
+function _PEAR_call_destructors()
+{
+    global $_PEAR_destructor_object_list;
+    if (is_array($_PEAR_destructor_object_list) &&
+        sizeof($_PEAR_destructor_object_list))
+    {
+        reset($_PEAR_destructor_object_list);
+        while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
+            $classname = get_class($objref);
+            while ($classname) {
+                $destructor = "_$classname";
+                if (method_exists($objref, $destructor)) {
+                    $objref->$destructor();
+                    break;
+                } else {
+                    $classname = get_parent_class($classname);
+                }
+            }
+        }
+        // Empty the object list to ensure that destructors are
+        // not called more than once.
+        $_PEAR_destructor_object_list = array();
+    }
+
+    // Now call the shutdown functions
+    if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
+        foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
+            call_user_func_array($value[0], $value[1]);
+        }
+    }
+}
+
+// }}}
+
+class PEAR_Error
+{
+    // {{{ properties
+
+    var $error_message_prefix = '';
+    var $mode                 = PEAR_ERROR_RETURN;
+    var $level                = E_USER_NOTICE;
+    var $code                 = -1;
+    var $message              = '';
+    var $userinfo             = '';
+    var $backtrace            = null;
+
+    // }}}
+    // {{{ constructor
+
+    /**
+     * PEAR_Error constructor
+     *
+     * @param string $message  message
+     *
+     * @param int $code     (optional) error code
+     *
+     * @param int $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
+     * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER or
+     * PEAR_ERROR_CALLBACK
+     *
+     * @param mixed $options   (optional) error level, _OR_ in the case of
+     * PEAR_ERROR_CALLBACK, the callback function or object/method
+     * tuple.
+     *
+     * @param string $userinfo (optional) additional user/debug info
+     *
+     * @access public
+     *
+     */
+    function PEAR_Error($message = 'unknown error', $code = null,
+                        $mode = null, $options = null, $userinfo = null)
+    {
+        if ($mode === null) {
+            $mode = PEAR_ERROR_RETURN;
+        }
+        $this->message   = $message;
+        $this->code      = $code;
+        $this->mode      = $mode;
+        $this->userinfo  = $userinfo;
+        if (function_exists("debug_backtrace")) {
+            $this->backtrace = debug_backtrace();
+        }
+        if ($mode & PEAR_ERROR_CALLBACK) {
+            $this->level = E_USER_NOTICE;
+            $this->callback = $options;
+        } else {
+            if ($options === null) {
+                $options = E_USER_NOTICE;
+            }
+            $this->level = $options;
+            $this->callback = null;
+        }
+        if ($this->mode & PEAR_ERROR_PRINT) {
+            if (is_null($options) || is_int($options)) {
+                $format = "%s";
+            } else {
+                $format = $options;
+            }
+            printf($format, $this->getMessage());
+        }
+        if ($this->mode & PEAR_ERROR_TRIGGER) {
+            trigger_error($this->getMessage(), $this->level);
+        }
+        if ($this->mode & PEAR_ERROR_DIE) {
+            $msg = $this->getMessage();
+            if (is_null($options) || is_int($options)) {
+                $format = "%s";
+                if (substr($msg, -1) != "\n") {
+                    $msg .= "\n";
+                }
+            } else {
+                $format = $options;
+            }
+            die(sprintf($format, $msg));
+        }
+        if ($this->mode & PEAR_ERROR_CALLBACK) {
+            if (is_string($this->callback) && strlen($this->callback)) {
+                call_user_func($this->callback, $this);
+            } elseif (is_array($this->callback) &&
+                      sizeof($this->callback) == 2 &&
+                      is_object($this->callback[0]) &&
+                      is_string($this->callback[1]) &&
+                      strlen($this->callback[1])) {
+                      @call_user_func($this->callback, $this);
+            }
+        }
+    }
+
+    // }}}
+    // {{{ getMode()
+
+    /**
+     * Get the error mode from an error object.
+     *
+     * @return int error mode
+     * @access public
+     */
+    function getMode() {
+        return $this->mode;
+    }
+
+    // }}}
+    // {{{ getCallback()
+
+    /**
+     * Get the callback function/method from an error object.
+     *
+     * @return mixed callback function or object/method array
+     * @access public
+     */
+    function getCallback() {
+        return $this->callback;
+    }
+
+    // }}}
+    // {{{ getMessage()
+
+
+    /**
+     * Get the error message from an error object.
+     *
+     * @return  string  full error message
+     * @access public
+     */
+    function getMessage()
+    {
+        return ($this->error_message_prefix . $this->message);
+    }
+
+
+    // }}}
+    // {{{ getCode()
+
+    /**
+     * Get error code from an error object
+     *
+     * @return int error code
+     * @access public
+     */
+     function getCode()
+     {
+        return $this->code;
+     }
+
+    // }}}
+    // {{{ getType()
+
+    /**
+     * Get the name of this error/exception.
+     *
+     * @return string error/exception name (type)
+     * @access public
+     */
+    function getType()
+    {
+        return get_class($this);
+    }
+
+    // }}}
+    // {{{ getUserInfo()
+
+    /**
+     * Get additional user-supplied information.
+     *
+     * @return string user-supplied information
+     * @access public
+     */
+    function getUserInfo()
+    {
+        return $this->userinfo;
+    }
+
+    // }}}
+    // {{{ getDebugInfo()
+
+    /**
+     * Get additional debug information supplied by the application.
+     *
+     * @return string debug information
+     * @access public
+     */
+    function getDebugInfo()
+    {
+        return $this->getUserInfo();
+    }
+
+    // }}}
+    // {{{ getBacktrace()
+
+    /**
+     * Get the call backtrace from where the error was generated.
+     * Supported with PHP 4.3.0 or newer.
+     *
+     * @param int $frame (optional) what frame to fetch
+     * @return array Backtrace, or NULL if not available.
+     * @access public
+     */
+    function getBacktrace($frame = null)
+    {
+        if ($frame === null) {
+            return $this->backtrace;
+        }
+        return $this->backtrace[$frame];
+    }
+
+    // }}}
+    // {{{ addUserInfo()
+
+    function addUserInfo($info)
+    {
+        if (empty($this->userinfo)) {
+            $this->userinfo = $info;
+        } else {
+            $this->userinfo .= " ** $info";
+        }
+    }
+
+    // }}}
+    // {{{ toString()
+
+    /**
+     * Make a string representation of this object.
+     *
+     * @return string a string with an object summary
+     * @access public
+     */
+    function toString() {
+        $modes = array();
+        $levels = array(E_USER_NOTICE  => 'notice',
+                        E_USER_WARNING => 'warning',
+                        E_USER_ERROR   => 'error');
+        if ($this->mode & PEAR_ERROR_CALLBACK) {
+            if (is_array($this->callback)) {
+                $callback = get_class($this->callback[0]) . '::' .
+                    $this->callback[1];
+            } else {
+                $callback = $this->callback;
+            }
+            return sprintf('[%s: message="%s" code=%d mode=callback '.
+                           'callback=%s prefix="%s" info="%s"]',
+                           get_class($this), $this->message, $this->code,
+                           $callback, $this->error_message_prefix,
+                           $this->userinfo);
+        }
+        if ($this->mode & PEAR_ERROR_PRINT) {
+            $modes[] = 'print';
+        }
+        if ($this->mode & PEAR_ERROR_TRIGGER) {
+            $modes[] = 'trigger';
+        }
+        if ($this->mode & PEAR_ERROR_DIE) {
+            $modes[] = 'die';
+        }
+        if ($this->mode & PEAR_ERROR_RETURN) {
+            $modes[] = 'return';
+        }
+        return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
+                       'prefix="%s" info="%s"]',
+                       get_class($this), $this->message, $this->code,
+                       implode("|", $modes), $levels[$this->level],
+                       $this->error_message_prefix,
+                       $this->userinfo);
+    }
+
+    // }}}
+}
+
+register_shutdown_function("_PEAR_call_destructors");
+
+/*
+ * Local Variables:
+ * mode: php
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL.php b/PHPTAL-NP-0.7.0/libs/PHPTAL.php
new file mode 100644 (file)
index 0000000..e05e583
--- /dev/null
@@ -0,0 +1,288 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+/*
+ * This file:
+ * 
+ * - Include PHPTAL dependencies 
+ * - Define PHPTAL attributes
+ * - Define PHPTAL aliases
+ * - Define PHPTAL rules
+ * 
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+
+$__d = dirname(__FILE__);
+require_once "PEAR.php";
+
+if (OS_WINDOWS) {
+    define('PHPTAL_PATH_SEP', '\\');
+} else {
+    define('PHPTAL_PATH_SEP', '/');
+}
+
+function _phptal_os_path_join()
+{
+    $args = func_get_args();
+    return join(PHPTAL_PATH_SEP, $args);
+}
+
+require_once 'Types/Errors.php';
+require_once 'Types/OString.php';
+
+require_once _phptal_os_path_join($__d, 'PHPTAL', 'Cache.php');
+require_once _phptal_os_path_join($__d, 'PHPTAL', 'Context.php');
+require_once _phptal_os_path_join($__d, 'PHPTAL', 'Filter.php');
+require_once _phptal_os_path_join($__d, 'PHPTAL', 'LoopControler.php');
+require_once _phptal_os_path_join($__d, 'PHPTAL', 'OutputControl.php');
+require_once _phptal_os_path_join($__d, 'PHPTAL', 'Template.php');
+require_once _phptal_os_path_join($__d, 'PHPTAL', 'Macro.php');
+require_once _phptal_os_path_join($__d, 'PHPTAL', 'I18N.php');
+
+require_once _phptal_os_path_join($__d, 'PHPTAL', 'SourceResolver.php');
+require_once _phptal_os_path_join($__d, 'PHPTAL', 'SourceLocator.php');
+
+
+define('PHPTAL_VERSION', '0.7.0');
+define('PHPTAL_MARK', str_replace('.', '_', PHPTAL_VERSION) . '_');
+define('PHPTAL_DEFAULT_CACHE_DIR', '/tmp/');
+
+/**
+ * This define is used to select the templates output format.
+ *
+ * There's few differences between XHTML and XML but they these differences can
+ * break some browsers output.
+ *
+ * Default PHPTAL output mode is XHTML.
+ */
+define('PHPTAL_XHTML', 1);
+
+/**
+ * This define is used to select the templates output format.
+ *
+ * The XML mode does not worry about XHTML specificity and echo every entity
+ * in a <entity></entity> format.
+ */
+define('PHPTAL_XML', 2);
+
+/**
+ * @var _phptal_namespaces
+ * @type array
+ *
+ * This array contains the list of all known attribute namespaces, if an
+ * attribute belonging to one of this namespaces is not recognized by PHPTAL,
+ * an exception will be raised.
+ * 
+ * These namespaces will be drop from resulting xml/xhtml unless the parser 
+ * is told to keep them.
+ *
+ * @access private
+ * @static 1
+ */
+global $_phptal_namespaces;
+$_phptal_namespaces = array('TAL', 'METAL', 'I18N', 'PHPTAL');
+
+
+define('_PHPTAL_SURROUND', 1);
+define('_PHPTAL_REPLACE', 2);
+define('_PHPTAL_CONTENT', 3);
+
+/**
+ * @var   _phptal_dictionary
+ * @type  hashtable
+ * 
+ * This dictionary contains ALL known PHPTAL attributes. Unknown attributes 
+ * will be echoed in result as xhtml/xml ones.
+ * 
+ * The value define how and when the attribute handler will be called during
+ * code generation.
+ * 
+ * @access private 
+ * @static 1
+ */ 
+global $_phptal_dictionary;
+$_phptal_dictionary = array(
+    'TAL:DEFINE'         => _PHPTAL_REPLACE,  // set a context variable
+    'TAL:CONDITION'      => _PHPTAL_SURROUND, // print tag content only when condition true
+    'TAL:REPEAT'         => _PHPTAL_SURROUND, // repeat over an iterable
+    'TAL:CONTENT'        => _PHPTAL_CONTENT,  // replace tag content
+    'TAL:REPLACE'        => _PHPTAL_REPLACE,  // replace entire tag
+    'TAL:ATTRIBUTES'     => _PHPTAL_REPLACE,  // dynamically set tag attributes
+    'TAL:OMIT-TAG'       => _PHPTAL_SURROUND, // omit to print tag but not its content
+    'TAL:COMMENT'        => _PHPTAL_SURROUND, // do nothing
+    'TAL:ON-ERROR'       => _PHPTAL_SURROUND, // replace content with this if error occurs
+    
+    'METAL:DEFINE-MACRO' => _PHPTAL_SURROUND, // define a template macro
+    'METAL:USE-MACRO'    => _PHPTAL_REPLACE,  // use a template macro
+    'METAL:DEFINE-SLOT'  => _PHPTAL_SURROUND, // define a macro slot
+    'METAL:FILL-SLOT'    => _PHPTAL_SURROUND, // fill a macro slot 
+    
+    'PHPTAL:INCLUDE'     => _PHPTAL_REPLACE,  // include an external template 
+    'PHPTAL:SRC-INCLUDE' => _PHPTAL_CONTENT,  // include external file without parsing
+
+    'I18N:TRANSLATE'     => _PHPTAL_CONTENT,  // translate some data using GetText package
+    'I18N:NAME'          => _PHPTAL_SURROUND, // prepare a translation name
+    'I18N:ATTRIBUTES'    => _PHPTAL_REPLACE,  // translate tag attributes values
+);
+
+/**
+ * @var   _phptal_aliases
+ * @type  hashtable
+ *
+ * Create aliases for attributes. If an alias is found during parsing, the
+ * matching phptal attribute will be used.
+ *
+ * @access private
+ * @static 1
+ */
+global $_phptal_aliases;
+$_phptal_aliases = array(    
+    'TAL:INCLUDE'    => 'PHPTAL:INCLUDE',
+    'TAL:SRC-INCLUDE'=> 'PHPTAL:SRC-INCLUDE',  
+);
+
+/**
+ * @var   _phptal_rules_order
+ * @type  hashtable
+ * 
+ * This rule associative array represents both ordering and exclusion 
+ * mecanism for template attributes.
+ *
+ * All known attributes must appear here and must be associated with 
+ * an occurence priority.
+ *
+ * When more than one phptal attribute appear in the same tag, they 
+ * will execute in following order.
+ * 
+ * @access private
+ * @static 1
+ */ 
+global $_phptal_rules_order;
+$_phptal_rules_order = array(
+    'TAL:OMIT-TAG'       => 0,    // surround -> $tag->disableHeadFootPrint()
+
+    'TAL:ON-ERROR'       => 1,    // surround
+
+    'METAL:DEFINE-MACRO' => 3,    // surround
+    'TAL:DEFINE'         => 3,    // replace
+    'I18N:NAME'          => 3,    // replace
+    'I18N:TRANSLATE'     => 3,    // content
+
+    'TAL:CONDITION'      => 4,    // surround
+
+    'TAL:REPEAT'         => 5,    // surround
+
+    'I18N:ATTRIBUTES'    => 6,    // replace
+    'TAL:ATTRIBUTES'     => 6,    // replace
+    'TAL:REPLACE'        => 6,    // replace
+    'METAL:USE-MACRO'    => 6,    // replace
+    'PHPTAL:SRC-INCLUDE' => 6,    // replace
+    'PHPTAL:INCLUDE'     => 6,    // replace
+    'METAL:DEFINE-SLOT'  => 6,    // replace
+    'METAL:FILL-SLOT'    => 6,    // replace
+    
+    'TAL:CONTENT'        => 7,    // content
+
+    'TAL:COMMENT'        => 8,    // surround
+);
+
+/**
+ * @var _phptal_xhtml_content_free_tags
+ * @type array
+ *
+ * This array contains XHTML tags that must be echoed in a &lt;tag/&gt; form
+ * instead of the &lt;tag&gt;&lt;/tag&gt; form.
+ *
+ * In fact, some browsers does not support the later form so PHPTAL 
+ * ensure these tags are correctly echoed.
+ */
+global $_phptal_xhtml_empty_tags;
+$_phptal_xhtml_empty_tags = array(
+    'AREA',
+    'BASE',
+    'BASEFONT',
+    'BR',
+    'COL',
+    'FRAME',
+    'HR',
+    'IMG',
+    'INPUT',
+    'ISINDEX',
+    'LINK',
+    'META',
+    'PARAM',
+);
+
+/**
+ * @var _phptal_xhtml_boolean_attributes
+ * @type array
+ *
+ * This array contains XHTML attributes that must be echoed in a minimized
+ * form. Some browsers (non HTML4 compliants are unable to interpret those
+ * attributes.
+ *
+ * The output will definitively not be an xml document !!
+ * PreFilters should be set to modify xhtml input containing these attributes.
+ */
+global $_phptal_xhtml_boolean_attributes;
+$_phptal_xhtml_boolean_attributes = array(
+    'compact',
+    'nowrap',
+    'ismap',
+    'declare',
+    'noshade',
+    'checked',
+    'disabled',
+    'readonly',
+    'multiple',
+    'selected',
+    'noresize',
+    'defer'
+);
+
+/**
+ * Shortcut to PHPTAL_Template for lazzy ones (me first).
+ */
+class PHPTAL extends PHPTAL_Template {}
+
+/**
+ * PEAR compliant class name.
+ */
+class HTML_Template_PHPTAL extends PHPTAL_Template {}
+
+/**
+ * PEAR compliant class name.
+ */
+class HTML_Template_PHPTAL_Filter extends PHPTAL_Filter {}
+
+/**
+ * PEAR compliant class name.
+ */
+class HTML_Template_PHPTAL_SourceLocator extends PHPTAL_SourceLocator {}
+
+/**
+ * PEAR compliant class name.
+ */
+class HTML_Template_PHPTAL_SourceResolver extends PHPTAL_SourceResolver {}
+
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute.php
new file mode 100644 (file)
index 0000000..c948eda
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+/**
+ * Base class for every kind of PHPTAL attribute.
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class PHPTAL_Attribute
+{
+    var $expression;
+
+    function PHPTAL_Attribute($exp)
+    {
+        $this->expression = $exp;
+    }
+
+    function activate(&$g, &$tag){}
+    function start(&$g, &$tag){}
+    function end(&$g, &$tag){}
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Attributes.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Attributes.php
new file mode 100644 (file)
index 0000000..4c12f5e
--- /dev/null
@@ -0,0 +1,142 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_Attribute_I18N_Attributes extends PHPTAL_Attribute
+{
+    var $_overwritten = array();
+    
+    function activate(&$g, &$tag)
+    {
+        global $_phptal_xhtml_boolean_attributes;
+        $g->requireGettext();
+
+        $g->doPrintString('<', $tag->name());
+
+        $attributes = $tag->attributes();
+        
+        // prepare expressions for attributes to translate
+        $exp = new PHPTAL_Expression($g, $tag, $this->expression);
+        $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_TEMP);
+        $err = $exp->prepare();
+        if (PEAR::isError($err)) { return $err; }
+
+        // more than one attribute to translate
+        if ($exp->countSubs() > 0) {
+            foreach ($exp->subs() as $subExpression) {
+                $err = $this->_attributeExpression($g, $tag, $subExpression);
+                if (PEAR::isError($err)) { return $err; }
+            }
+        } else {
+            $err = $this->_attributeExpression($g, $tag, $exp);
+            if (PEAR::isError($err)) { return $err; }
+        }
+    
+        // echo non overwritten attributes
+        foreach ($attributes as $key=>$value) {
+            $test_key = strtolower($key);
+            if (!in_array($test_key, $this->_overwritten)) {
+                // beware of xhtml boolean attributes
+                if ($tag->_parser->_outputMode() == PHPTAL_XHTML
+                    && in_array($test_key, $_phptal_xhtml_boolean_attributes)) {
+                    $g->doPrintString(' '.$key);
+                } else {
+                    $g->doPrintString(' '.$key.'="');
+                    $g->doPrintString($value);
+                    $g->doPrintString('"');
+                }
+            }
+        }
+
+        if ($tag->_isXHTMLEmptyElement()) { 
+            $g->doPrintString(' />'); 
+            return; 
+        }
+        
+        if ($tag->hasContent()) {
+            $g->doPrintString('>');
+        } else {
+            $g->doPrintString('/>');
+        }
+
+        $err = $tag->generateContent($g);
+        if (PEAR::isError($err)) { return $err; }
+
+        if ($tag->hasContent()) {
+            $g->doPrintString('</', $tag->name(), '>');
+        }
+    }
+
+    function _attributeExpression(&$g, &$tag, &$subExpression)
+    {
+        $attributes = $tag->attributes();
+        $default    = false;
+        $name       = strtolower($subExpression->getReceiver());
+
+        // set default attribute value in $default variable
+        if (preg_match('/\bdefault\b/sm', $subExpression->_src)) {
+            if (!array_key_exists($name, $attributes)) {
+                $g->doAffectResult('$__default__', 'false');
+            } else {
+                $value = $attributes[$name];
+                $value = str_replace('\'', '\\\'', $value);
+                $g->doAffectResult('$__default__', '\''. $value . '\'');
+            }
+            $default = true;
+        }
+
+        $real = str_replace('__phptales_dd__', ':', $name);
+        $this->_overwritten[] = $real;
+        $err  = $subExpression->generate();
+        if (PEAR::isError($err)) { return $err; }
+
+        $this->_printAttribute($g, $tag, $real, $name, $default);
+    }
+
+    function _printAttribute(&$g, &$tag, $realName, $varName, $default=false)
+    {
+        global $_phptal_xhtml_boolean_attributes;
+        
+        // watch boolean attributes on XHTML mode
+        if ($tag->_parser->_outputMode() == PHPTAL_XHTML 
+            && in_array($realName, $_phptal_xhtml_boolean_attributes)) {
+            $g->doIf('!PEAR::isError($'.$varName.') && $'.$varName);
+            $g->doPrintString(' '.$realName);
+            $g->endBlock();
+        } elseif ($default) {
+            $g->doIf('!PEAR::isError($'.$varName.') && false !== $'.$varName.' && null !== $'.$varName);
+            $g->doPrintString(' '. $realName . '="');
+            $code = sprintf('$__tpl__->_translate(trim($%s))', $varName);
+            $g->doPrintRes($code, true);
+            // $g->doPrintVar($varName);
+            $g->doPrintString('"');
+            $g->endBlock();
+        } else {
+            $g->doPrintString(' '. $realName . '="');
+            $code = sprintf('$__tpl__->_translate(trim($%s))', $varName);
+            $g->doPrintRes($code, true);
+            // $g->doPrintVar($varName);
+            $g->doPrintString('"');
+        }
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Name.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Name.php
new file mode 100644 (file)
index 0000000..58970c2
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_Attribute_I18N_Name extends PHPTAL_Attribute
+{
+    function start(&$g, &$tag)
+    {
+        $g->requireGettext();
+        $g->doOBStart();
+    }
+    
+    function end(&$g, &$tag)
+    {
+        $temp = $g->newTemporaryVar();
+        $g->doOBEnd($temp);
+        $code = sprintf('$__tpl__->_setTranslateVar(\'%s\', %s)', 
+                        $this->expression, 
+                        $temp);
+        $g->execute($code);
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Translate.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Translate.php
new file mode 100644 (file)
index 0000000..42c1e80
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_Attribute_I18N_Translate extends PHPTAL_Attribute
+{
+    function activate(&$g, &$tag)
+    {
+        $g->requireGettext();
+
+        if (strlen($this->expression) == 0) {
+            $key = "'". $this->_preparseGetTextKey($tag) ."'";
+        } else {
+            $exp = new PHPTAL_Expression($g, $tag, $this->expression);
+            $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_TEMP);
+            $key = $g->newTemporaryVar();
+            $exp->setReceiver($key);
+            $err = $exp->generate();
+            if (PEAR::isError($err)) { return $err; }
+        }
+        
+        // children may contains i18n:name attributes,
+        // we ignore output but parse content before calling translation.
+        $g->doOBStart();
+        foreach ($tag->_children as $child) {
+            $child->generateCode($g);
+        }
+        $g->doOBClean();
+        // $code = sprintf('$__tpl__->_translate(\'%s\')', $key);
+        $code = sprintf('$__tpl__->_translate(%s)', $key);
+        $g->doPrintRes($code, true);
+    }
+
+    function _preparseGetTextKey(&$tag)
+    {
+        $key = "";
+        foreach ($tag->_children as $child) {
+            if ($child->isData()) {
+                $str = preg_replace('/\s+/sm', ' ', $child->_content);
+                $key .= trim($str) . ' ';
+            } else {
+                $is_i18n_name = false;
+                // look for i18n:name
+                foreach ($child->_surround_attributes as $att) {
+                    if (get_class($att) == strtolower("PHPTAL_Attribute_I18N_Name")) {
+                        $key .= '${' . $att->expression . '}';
+                        $is_i18n_name = true;
+                    }
+                }
+                // recursive call to preparse key for non i18n:name tags
+                if (!$is_i18n_name) {
+                    $key .= PHPTAL_Attribute_I18N_Translate::_preparseGetTextKey($child) . ' ';
+                }
+            }
+        }
+
+        // remove every thing that has more than 1 space
+        $key = preg_replace('/\s+/sm', ' ', $key);
+        $key = trim($key);
+        return $key;
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Define_macro.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Define_macro.php
new file mode 100644 (file)
index 0000000..fc06ebc
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_Attribute_METAL_Define_Macro extends PHPTAL_Attribute
+{
+    function start(&$g, &$tag)
+    {
+        $g->doMacroDeclare($this->expression);
+    }
+
+    function end(&$g, &$tag)
+    {
+        $g->doMacroEnd();
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Define_slot.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Define_slot.php
new file mode 100644 (file)
index 0000000..811cd63
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_Attribute_METAL_Define_slot extends PHPTAL_Attribute
+{
+    function start(&$g, &$tag)
+    {
+        $slotName = $this->expression;
+        $cond = sprintf('$__ctx__->has(\'slots/%s\')', $slotName);
+        $g->doIf($cond);
+        $g->doPrintContext('slots/'.$slotName, true);
+        $g->doElse();
+    }
+
+    function end(&$g, &$tag)
+    {
+        $g->endBlock();
+    }
+};
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Fill_slot.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Fill_slot.php
new file mode 100644 (file)
index 0000000..b71926c
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_Attribute_METAL_Fill_slot extends PHPTAL_Attribute
+{
+    function start(&$g, &$tag)
+    {
+        $g->doOBStart();
+    }
+
+    function end(&$g, &$tag)
+    {
+        $g->doOBEndInContext('slots/'.$this->expression);
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Use_macro.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Use_macro.php
new file mode 100644 (file)
index 0000000..17b4e88
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_Attribute_METAL_Use_Macro extends PHPTAL_Attribute
+{
+    function activate(&$g, &$tag)
+    {
+        $g->doOBStart();
+        $err = $tag->generateContent($g);
+        if (PEAR::isError($err)) { return $err; }
+        $g->doOBClean();
+        
+        $path = $g->newTemporaryVar();
+        
+        $g->doAffectResult($path, "'". PHPTAL_ES_path_in_string($this->expression,"'") . "'");
+        
+        $temp = $g->newTemporaryVar();
+        
+        // push error
+        $g->execute('$__old_error = $__ctx__->_errorRaised');
+        $g->execute('$__ctx__->_errorRaised = false');
+        
+        $g->doAffectResult($temp, 'new PHPTAL_Macro($__tpl__, '. $path .')');
+        $g->doAffectResult($temp, $temp.'->execute($__tpl__)');
+        
+        $g->doIf('PEAR::isError('.$temp.')');
+        $g->execute('$__ctx__->_errorRaised = '.$temp );
+        $g->endBlock();
+        
+        $g->doPrintVar($temp, true);
+
+        // restore error
+        $g->doIf('!$__ctx__->_errorRaised');
+        $g->execute('$__ctx__->_errorRaised = $__old_error');
+        $g->endBlock();
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/PHPTAL/Include.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/PHPTAL/Include.php
new file mode 100644 (file)
index 0000000..6a2927b
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_Attribute_PHPTAL_Include extends PHPTAL_Attribute
+{
+    function activate(&$g, &$tag)
+    {
+        $exp = new PHPTAL_Expression($g, $tag, $this->expression);
+        $temp = $g->newTemporaryVar();
+        $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_TEMP);
+        $exp->setReceiver($temp);
+        $err = $exp->generate();
+        if (PEAR::isError($err)) { return $err; }
+        
+        $tpl  = $g->newTemporaryVar();
+        $g->doAffectResult($tpl, 'new PHPTAL_Template('.$temp.', $__tpl__->_repository, $__tpl__->_cacheDir)');
+        $g->execute($tpl.'->setParent($__tpl__)');
+        $g->execute($tpl.'->setContext($__ctx__)');
+        $g->doPrintRes($tpl.'->execute()', true);
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/PHPTAL/Src_include.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/PHPTAL/Src_include.php
new file mode 100644 (file)
index 0000000..8d367ed
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_Attribute_PHPTAL_Src_include extends PHPTAL_Attribute
+{
+    function activate(&$g, &$tag)
+    {
+        $temp = $g->newTemporaryVar();
+        
+        $exp = new PHPTAL_Expression($g, $tag, $this->expression);
+        $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_TEMP);
+        $exp->setReceiver($temp);
+        $err = $exp->generate();
+        if (PEAR::isError($err)) { return $err; }
+
+        $g->doAffectResult($temp, '$__tpl__->realpath('.$temp.')');
+        $g->doIf('PEAR::isError('.$temp.')');
+        $g->execute('$__ctx__->_errorRaised = true');
+        $g->doPrintVar($temp);
+        $g->doElse();
+        $g->doPrintRes('join("", file('.$temp.'))', true);
+        $g->endBlock();
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Attributes.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Attributes.php
new file mode 100644 (file)
index 0000000..42420f8
--- /dev/null
@@ -0,0 +1,173 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+/**
+ * tal:attributes attribute handler.
+ *
+ * This template attribute defines xhtml entity attributes.
+ *
+ * Assuming link variable :
+ *
+ * $link->href  = "http://www.google.fr";
+ * $link->title = "google search engine";
+ * $link->text  = "google";
+ *
+ * The template code :
+ *
+ * <a href="http://www.example.com"
+ *    title="sample title"
+ *    class="cssLink"
+ *
+ *    tal:attributes="href link/href; title link/title"
+ *    tal:content="href link/text"
+ *
+ * >sample text</a>
+ *
+ * Will produce :
+ *
+ * <a class="cssLink"
+ *    href="http://www.google.com"
+ *    title="google search engine"
+ * >google</a>
+ *
+ * As shown above, non overwritten attributes are keep in result xhtml.
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class PHPTAL_Attribute_TAL_Attributes extends PHPTAL_Attribute
+{
+    var $_overwritten = array();
+    
+    function activate(&$g, &$tag)
+    {
+        global $_phptal_xhtml_boolean_attributes;
+
+        $g->doPrintString('<', $tag->name());
+        
+        $atts = $tag->attributes();
+        
+        $exp = new PHPTAL_Expression($g, $tag, $this->expression);
+        $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_TEMP);
+        $err = $exp->prepare();
+        if (PEAR::isError($err)) { return $err; }
+        
+        if ($exp->countSubs() > 0) {
+            foreach ($exp->subs() as $sub) {
+                $err = $this->_attributeExpression($g, $tag, $sub);
+                if (PEAR::isError($err)) { return $err; }
+            }
+        } else {
+            $err = $this->_attributeExpression($g, $tag, $exp);
+            if (PEAR::isError($err)) { return $err; }
+        }
+        
+        // echo non overwritten xhtml attributes
+        
+        foreach ($atts as $key=>$value) {
+            $test_key = strtolower($key);
+            if (!in_array($test_key, $this->_overwritten)) {
+                // boolean attributes
+                if ($tag->_parser->_outputMode() == PHPTAL_XHTML 
+                    && in_array($test_key, $_phptal_xhtml_boolean_attributes)) {
+                    $g->doPrintString(' '.$key);
+                } else {
+                    $g->doPrintString(' '.$key .'="');
+                    $g->doPrintString($value);
+                    $g->doPrintString('"');
+                }
+            }
+        }
+
+        if ($tag->_isXHTMLEmptyElement()) {
+            $g->doPrintString(' />');
+            return;
+        }
+        
+        // continue tag show
+        if ($tag->hasContent()) {
+            $g->doPrintString('>');
+        } else {
+            $g->doPrintString('/>');
+        }
+
+        $err = $tag->generateContent($g);
+        if (PEAR::isError($err)) { return $err; }
+       
+        if ($tag->hasContent()) {
+            $g->doPrintString('</', $tag->name(), '>');
+        }
+    }
+
+    function _printAttribute(&$g, &$tag, &$realName, &$varName, $default=false)
+    {
+        global $_phptal_xhtml_boolean_attributes;
+        // watch boolean attributes on XHTML mode
+        if ($tag->_parser->_outputMode() == PHPTAL_XHTML 
+            && in_array($realName, $_phptal_xhtml_boolean_attributes)) {
+            $g->doIf('!PEAR::isError($'.$varName.') && $'.$varName);
+            $g->doPrintString(' '.$realName);
+            $g->endBlock();
+        } elseif ($default) {
+            $g->doIf('!PEAR::isError($'.$varName.') && false !== $'.$varName.' && null !== $'.$varName);
+            $g->doPrintString(' '. $realName . '="');
+            $g->doPrintVar($varName);
+            $g->doPrintString('"');
+            $g->endBlock();
+        } else {
+            $g->doPrintString(' '. $realName . '="');
+            $g->doPrintVar($varName);
+            $g->doPrintString('"');
+        }
+    }
+
+    function _attributeExpression(&$g, &$tag, &$sub) 
+    {
+        $atts = $tag->attributes();
+        $default = false;
+        $name = strtolower($sub->getReceiver());
+
+        // default in tal:attributes use default tag attributes
+        // if (preg_match('/\|\s*?\bdefault\b/sm', $sub->_src)) {
+        if (preg_match('/\bdefault\b/sm', $sub->_src)) {
+            // ensure the attribute as a default value set in source
+            // template
+            $attrs = $tag->attributes();
+            if (!array_key_exists($name, $atts)){
+                $g->doAffectResult('$__default__', 'false');
+            } else {
+                // store the default value in __default__ variable
+                $g->doAffectResult('$__default__', 
+                                   '\''. str_replace('\'', '\\\'', $atts[$name]) . '\'' );
+            }
+            $default = true;
+        }
+                
+        $real = str_replace('__phptales_dd__', ':', $name);
+        $this->_overwritten[] = $real;
+        $err = $sub->generate();
+        if (PEAR::isError($err)) { return $err; }
+        
+        $this->_printAttribute($g, $tag, $real, $name, $default);
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Comment.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Comment.php
new file mode 100644 (file)
index 0000000..e739e78
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_Attribute_TAL_Comment extends PHPTAL_Attribute
+{
+    function start(&$g, &$tag)
+    {
+        $g->doComment($this->expression);
+    }
+    
+    function end(&$g, &$tag)
+    {}
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Condition.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Condition.php
new file mode 100644 (file)
index 0000000..be02e50
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+
+class PHPTAL_Attribute_TAL_Condition extends PHPTAL_Attribute
+{
+    function start(&$g, &$tag)
+    {
+        $exp = new PHPTAL_Expression($g, $tag, $this->expression);
+        $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_TEMP);
+        $test_var = $g->newTemporaryVar();
+        $exp->setReceiver($test_var);
+        $err = $exp->generate();
+        if (PEAR::isError($err)) { return $err; }
+        $g->doIf("!PEAR::isError($test_var) && $test_var");
+    }
+
+    function end(&$g, &$tag)
+    {
+        $g->endBlock();
+    }
+};
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Content.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Content.php
new file mode 100644 (file)
index 0000000..3dfa826
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+/**
+ * Handle tal:content attributes
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class PHPTAL_Attribute_TAL_Content extends PHPTAL_Attribute 
+{
+    function activate(&$g, &$tag)
+    {
+        if (preg_match('/\|\s*?\bdefault\b/sm', $this->expression)) {
+            $g->doOBStart();
+            foreach ($tag->_children as $child) {
+                $err = $child->generateCode($g);
+                if (PEAR::isError($err)) { return $err; }
+            }
+            $g->doOBEnd('$__default__');
+            $default = true;
+        }
+        
+        $g->setSource($tag->name(), $tag->line);
+        $exp = new PHPTAL_Expression($g, $tag, $this->expression);
+        $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_OUTPUT);
+        $err = $exp->generate();
+        if (PEAR::isError($err)) { return $err; }
+
+        if (isset($default)) { $g->execute('unset($__default__)'); }
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Define.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Define.php
new file mode 100644 (file)
index 0000000..fdc6121
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_Attribute_TAL_Define extends PHPTAL_Attribute
+{
+    function activate(&$g, &$tag)
+    {
+        if (preg_match('/\|\s*?\bdefault\b/sm', $this->expression)) {
+            $g->doOBStart();
+            $err = $tag->generateContent($g);
+            if (PEAR::isError($err)) { return $err; }
+            $g->doOBEnd('$__default__');
+            $default = true;
+        }
+        
+        // use node content to set variable
+        if (preg_match('/^[a-z0-9_]+$/i', $this->expression)) {
+            $g->doOBStart();
+            $err = $tag->generateContent($g);
+            if (PEAR::isError($err)) { return $err; }
+            $g->doOBEndInContext($this->expression);
+        } else {
+            $exp = new PHPTAL_Expression($g, $tag, $this->expression);
+            $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_CONTEXT);
+            $err = $exp->generate();
+            if (PEAR::isError($err)) { return $err; }
+        }
+        if (isset($default)) { $g->execute('unset($__default__)'); }
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Omit_tag.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Omit_tag.php
new file mode 100644 (file)
index 0000000..71a403a
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_Attribute_TAL_Omit_tag extends PHPTAL_Attribute
+{
+    function start(&$g, &$tag)
+    {
+        $tag->disableHeadFoot();
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/On_error.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/On_error.php
new file mode 100644 (file)
index 0000000..397388e
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_Attribute_TAL_On_Error extends PHPTAL_Attribute
+{
+    function start(&$g, &$tag)
+    {
+        $g->doComment("OnError handling");
+        $g->execute('$__ctx__->cleanError()');
+        $g->doOBStart();
+    }
+
+    function end(&$g, &$tag)
+    {
+        $exp = new PHPTAL_Expression($g, $tag, $this->expression);
+        $g->doIf("\$__ctx__->errorRaised()");
+        $g->doOBClean();
+        $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_OUTPUT);
+        $err = $exp->generate();
+        if (PEAR::isError($err)) { return $err; }
+        $g->doElse();
+        $g->doOBPrint();
+        $g->endBlock();
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Repeat.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Repeat.php
new file mode 100644 (file)
index 0000000..f45548c
--- /dev/null
@@ -0,0 +1,64 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_Attribute_TAL_Repeat extends PHPTAL_Attribute
+{
+    var $in = "__in__";
+    var $out = "__out__";
+    
+    function start(&$g, &$tag)
+    {
+        $g->setSource($tag->name(), $tag->line);
+        
+        $g->doComment('new loop');
+        $exp = new PHPTAL_Expression($g, $tag, $this->expression);
+        $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_TEMP);
+        $err = $exp->prepare();
+        if (PEAR::isError($err)) { return $err; }
+        
+        $this->out = $exp->getReceiver();
+        $temp = $g->newTemporaryVar();
+        $exp->setReceiver($temp);
+        $err = $exp->generate();   // now $temp points to the loop data
+        if (PEAR::isError($err)) { return $err; }
+
+        $loop = $g->newTemporaryVar();
+        $this->loop = $loop;
+        $g->doAffectResult($loop, 
+                           '& new PHPTAL_LoopControler($__ctx__, "'. $this->out . '", '
+                                                  . $temp .');');
+        $g->doIf('PEAR::isError('.$loop.'->_error)');
+        $g->doPrintVar($loop.'->_error');
+        $g->doElse();
+        // $g->execute($loop.'->prepare()');
+        $g->doWhile($loop.'->isValid()');
+        
+    }
+
+    function end(&$g, &$tag)
+    {
+        $g->execute($this->loop.'->next()');
+        $g->endBlock();
+        $g->endBlock();
+        $g->doComment('end loop');
+    }
+}
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Replace.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Replace.php
new file mode 100644 (file)
index 0000000..3944622
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_Attribute_TAL_Replace extends PHPTAL_Attribute
+{
+    function activate(&$g, &$tag)
+    {
+        if (preg_match('/\|\s*?\bdefault\b/sm', $this->expression)) {
+            $g->doOBStart();
+            foreach ($tag->_children as $child) {
+                $err = $child->generateCode($g);
+                if (PEAR::isError($err)) { return $err; }
+            }
+            $g->doOBEnd('$__default__');
+            $default = true;
+        }
+        $g->setSource($tag->name(), $tag->line);
+        $exp = new PHPTAL_Expression($g, $tag, $this->expression);
+        $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_OUTPUT);
+        $err = $exp->generate();
+        if (PEAR::isError($err)) { return $err; }
+        
+        if (isset($default)) { $g->execute('unset($__default__)'); }
+    }
+};
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Cache.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Cache.php
new file mode 100644 (file)
index 0000000..6821789
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+/**
+ * Interface to PHPTAL cache system.
+ *
+ * Implement this interface and use PHPTAL_Template::setCacheManager() method
+ * to intercept macro and template execution with your own cache system.
+ *
+ * The aim of this system is to fine grain the caching of PHPTAL results
+ * allowing the php coder to use whatever cache system he prefers with a 
+ * good granularity as he can cache result of specific templates execution, 
+ * and specific macros calls.
+ *
+ * @see         Documentation.txt 
+ * @author      Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class PHPTAL_Cache
+{
+    /**
+     * Called each time a template has to be executed.
+     *
+     * This method must return the cache value or the template execution 
+     * return.
+     *
+     * function template(&$tpl, $path, &$context)
+     * {
+     *     // return cache if exists
+     *     // else realy process template
+     *     $res = $tpl->_process();
+     *     // cache the result if needed
+     *     // and return it
+     *     return $res;
+     * }
+     *
+     * @param PHPTAL_Template     -- the template that must be cached/executed
+     * @param string $path        -- the template path
+     * @param PHPTAL_Context $ctx -- the execution context
+     * 
+     * @return string
+     */
+    function template(&$tpl, $path, &$context)
+    {
+        return $tpl->_process();
+    }
+    
+
+    /**
+     * Called each time a macro needs to be executed.
+     *
+     * This method allow cache on macro result. It must return the cache value
+     * or at least the macro execution result.
+     *
+     * function macro(&$macro, $file, $name, &$context)
+     * {
+     *     // return cache if exists
+     *     // else really process macro
+     *     $res = $macro->_process();
+     *     // cache the result if needed
+     *     // and return it
+     *     return $res
+     * }
+     * 
+     *
+     * @param PHPTAL_Macro -- the macro to executed
+     * @param string $file -- the macro source file
+     * @param string $name -- the macro name
+     * @param PHPTAL_Context $context -- the current execution context
+     *
+     * @return string
+     */
+    function macro(&$macro, $file, $name, &$context)
+    {
+        return $macro->_process();
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Context.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Context.php
new file mode 100644 (file)
index 0000000..b41201f
--- /dev/null
@@ -0,0 +1,349 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+
+// What are Context and Resolvers
+// ==============================
+//
+// In phptal, variables and methods are referenced by path without distinction,
+// also, arrays and hashtable elements are accessed using a path like
+// myarray/10 to reach the 11's element of myarray or myhash/mykey to
+// reach the value of mykey in myhash.
+//
+// This allow things like 'myobject/mymethod/10/othermethod' which is usefull
+// in templates.
+// 
+// The Context is an array containing all template variables.
+// When asked to reach a path, it look for the variable type of the first path
+// element and generate a resolver matching the variable type.
+// Then this resolver is asked to resolve the rest of the path, etc... up to 
+// the final path element.
+//
+// Resolver knows how to handle a given path relatively to the object they
+// handle.
+//
+// For instance, an array resolver can handle access to its array elements
+// given a key (string) or the element id (int).
+//
+// The array resolver also bring an array method : count which return the
+// number of elements in the array.
+//
+// Note
+// ----
+// 
+// If a name conflict occurs between an object's variable and one of its
+// methods, the variable is return in stead of the method.
+// 
+
+/**
+ * Template context handler.
+ *
+ * This object produce a translation between variables passed to the template
+ * and regular template pathes.
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class PHPTAL_Context
+{
+    var $_array = array();
+    var $_errorRaised = false;
+
+    /**
+     * Context constructor.
+     *
+     * @param hashtable $hash (opt)
+     */
+    function PHPTAL_Context($hash=array())
+    {
+        $this->_array = $hash;
+    }
+    
+    /**
+     * Set a value by reference.
+     *
+     * @param string $path  -- Variable path
+     * @param mixed  $value -- Reference to variable.
+     */
+    function setRef($path, &$value)
+    { 
+        $this->remove($path);
+        $this->_array[$path] =& $value;
+    }
+
+    /**
+     * Set a context variable.
+     *
+     * @param string $path  -- Variable path
+     * @param mixed  $value -- Value
+     */
+    function set($path, $value)
+    {
+        $this->remove($path);
+        $this->_array[$path] = $value;
+    }
+
+    /**
+     * Remove a context variable.
+     *
+     * @param string $path -- Context path 
+     */
+    function remove($path)
+    {
+        if (array_key_exists($path, $this->_array)) {
+            unset($this->_array[$path]); 
+        }
+    }
+
+    /**
+     * Test if the context can resolve specified path.
+     *
+     * @param string $path 
+     *        Path to a context resource.
+     *
+     * @return boolean
+     */
+    function has($path)
+    {
+        if (array_key_exists($path, $this->_array)) {
+            return true;
+        }
+        $resp =& PHPTAL_ArrayResolver::get($this->_array, $path);
+        if (PEAR::isError($resp)) {
+            return false;
+        } else if ($resp === null) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Return the context associative object.
+     */
+    function &getHash()
+    {
+        return $this->_array;
+    }
+
+    /**
+     * Retrieve specified context resource.
+     *
+     * @param string $path
+     *        Path to a context resource.
+     *        
+     * @return mixed
+     * @throws NameError
+     */
+    function &get($path)
+    {
+        if (array_key_exists($path, $this->_array)) {
+            return $this->_array[$path];
+        }
+        $resp =& PHPTAL_ArrayResolver::get($this->_array, $path);
+        if (PEAR::isError($resp)) {
+            $this->_errorRaised = $resp; 
+        } else if ($resp === null) {
+            $this->_errorRaised = true;
+        }
+        return $resp;
+    }
+
+    /**
+     * Retrieve specified context resouce as a string object
+     *
+     * @param string $path
+     *        Path to a context resource.
+     *
+     * @return string
+     */
+    function &getToString($path)
+    {
+        $o = $this->get($path);
+        if (is_object($o) && method_exists($o, "toString")) {
+            return $o->toString();
+        }
+        if (is_object($o) || is_array($o)) {
+            ob_start();
+            print_r($o); // var_dump($o);
+            $res = ob_get_contents();
+            ob_end_clean();
+            return $res;
+        }
+        return $o;
+    }
+    
+    /**
+     * Tells if an error was raised by this context accessing an unknown path.
+     *
+     * @return boolean
+     */
+    function errorRaised()
+    {
+        $r = $this->_errorRaised;
+        $this->_errorRaised = false;
+        return $r;
+    }
+
+    /**
+     * Clean error handler.
+     */
+    function cleanError()
+    {
+        $this->_errorRaised = false;
+    }
+}
+
+/**
+ * Object resolver.
+ *
+ * Resolver pathes relatives to object.
+ *
+ * @access private
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class PHPTAL_ObjectResolver
+{
+    function &get(&$obj, $subpath)
+    {       
+        list($first, $next) = PHPTAL_path_explode($subpath);
+        
+        if (method_exists($obj, $first)) { 
+            // reference to a variable of the handled object
+            $value =& $obj->$first(); 
+        } elseif (array_key_exists($first, $obj)) {
+            // reference to an object variable
+            $value =& $obj->$first;
+        } elseif (is_a($obj, 'OHash') && $obj->containsKey($first)) {
+            return $obj->get($first);
+        } elseif (is_a($obj, 'OArray') && preg_match('/^[0-9]+$/', $first)) {
+            return $obj->get((int)$first);
+        } else {
+            $err = new NameError($subpath . " not found");
+            return $err;
+        }
+        // more to resolve in value
+        if ($next) {
+            return PHPTAL_resolve($next, $value, $obj);
+        }
+        return $value;        
+    }
+}
+
+
+/**
+ * Array resolver.
+ *
+ * Resolve pathes relative to arrays and hashtables.
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class PHPTAL_ArrayResolver
+{
+    function &get(&$array, $subpath)
+    {
+        list($first, $next) = PHPTAL_path_explode($subpath);
+
+        if ($first == "length" && !$next && !array_key_exists("length", $array)) {
+            return count($array);
+        }
+        
+        if ($next === false) {
+            if ($first == 'count') { return count($array); }
+            if ($first == 'keys')  { return array_keys($array); }
+            if ($first == 'values'){ return array_values($array); }
+            if (!array_key_exists($first, $array)) {
+                $err = new NameError("(ArrayResolver) Context does not contains key '$first'");
+                return $err;
+            }
+            return $array[$first];
+        }
+
+        if (!array_key_exists($first, $array)) {
+            $err = new NameError("(ArrayResolver) Context does not contains key '$first'");
+            return $err;
+        }
+        $temp =& $array[$first];
+        if ($temp) {
+            return PHPTAL_resolve($next, $temp, $array);
+        }
+    }
+}
+
+
+/**
+ * String resolver.
+ *
+ * Add method to string type.
+ */
+class PHPTAL_StringResolver
+{
+    function get(&$str, $subpath)
+    {
+        list($first, $next) = PHPTAL_path_explode($subpath);
+        if ($next) {
+            $err = new TypeError("string methods have no sub path (string.$subpath)");
+            return $err;
+        }
+        if ($first == "len") {
+            return strlen($str);
+        }
+        $err = new NameError("string type has no method named '$first'");
+        return $err;
+    }
+};
+
+/**
+ * Retrieve a resolver given a value and a parent.
+ */
+function &PHPTAL_resolve($path, &$value, &$parent)
+{
+    if (is_array($value))  return PHPTAL_ArrayResolver::get($value, $path);
+    if (is_object($value)) return PHPTAL_ObjectResolver::get($value, $path);
+    if (is_string($value)) return PHPTAL_StringResolver::get($value, $path);
+    $err = new TypeError("unable to find adequate resolver for '".gettype($value)."' remaining path is '$path'");
+    return $err;
+}
+
+/**
+ * Shift the first elemetn of a phptal path.
+ *
+ * Returns an array containing the first element of the path and the rest of
+ * the path.
+ */
+function PHPTAL_path_explode($path)
+{
+    if (preg_match('|^(.*?)\/(.*?)$|', $path, $match)) {
+        array_shift($match);
+        return $match;
+    } else {
+        return array($path, false);
+    }
+
+    $pos = strpos($path,".");
+    if ($pos !== false) { 
+        $first = substr($path, 0, $pos);
+        $next  = substr($path, $pos+1);
+        return array($first, $next);
+    }
+    return array($path, false);
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Expression.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Expression.php
new file mode 100644 (file)
index 0000000..5e4a63d
--- /dev/null
@@ -0,0 +1,369 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+define('_PHPTAL_ES_RECEIVER_IS_CONTEXT', 1);
+define('_PHPTAL_ES_RECEIVER_IS_NONE', 2);
+define('_PHPTAL_ES_RECEIVER_IS_TEMP', 4);
+define('_PHPTAL_ES_RECEIVER_IS_OUTPUT', 8);
+
+
+// Important note:
+//
+// The PHPTALES system works quite well but it's not yet fully optimized, it 
+// should be refactored at some points of my TODO list.
+//
+
+
+class PHPTAL_Expression
+{
+    var $_tag;
+    var $_gen;
+    var $_src;
+    var $_subs = array();
+    var $_policy;
+    var $_receiver = false;
+    var $_prepared = false;
+    var $_structure = false;
+
+    function PHPTAL_Expression(&$generator, &$tag, $str)
+    {
+        $this->_tag =& $tag;
+        $this->_gen =& $generator;
+        $this->_src = $str;
+    }
+
+    function setPolicy($policy)
+    {
+        $this->_policy = $policy;
+    }
+
+    /**
+     * Prepare the expression.
+     *
+     * This method explode the expression into sub expression and prepare each 
+     * expression for parsing.
+     *
+     * @throws PHPTAL_ExpressionError 
+     *         If receiver policy fail.
+     */
+    function prepare()
+    {
+        if ($this->_prepared) { return; }
+        $test = $this->_src;
+
+        // some sub expression detected
+        while (preg_match('/^(.*?)(?<!;);(?!;)/sm', $test, $m)) {
+            list($src, $exp) = $m;
+
+            $x = new PHPTAL_Expression($this->_gen, $this->_tag, $exp);
+            $x->setPolicy($this->_policy);
+            $x->setReceiver($this->getReceiver());
+            $err = $x->prepare();
+            if (PEAR::isError($err)) { 
+                return $err; 
+            }
+            $this->_subs[] = $x;
+
+            $test = substr($test, strlen($src));
+        }
+        // if subs, insert last one
+        if ($this->countSubs() > 0 && strlen(trim($test)) > 0) {
+            $exp = $test;
+            $x = new PHPTAL_Expression($this->_gen, $this->_tag, $exp);
+            $x->setPolicy($this->_policy);
+            $x->setReceiver($this->getReceiver());
+            $err = $x->prepare();
+            if (PEAR::isError($err)) { 
+                return $err; 
+            }
+            $this->_subs[] = $x;
+        } else {        
+            // otherwise, just remove expression delimiters from source
+            // and apply the receiver policy
+            $exp = $test;
+            $exp = str_replace(';;', ';', $exp);
+            $this->_src = $exp;
+            if (strlen($exp) == 0) return;
+
+            $err = $this->_extractReceiver();
+            if (PEAR::isError($err)){ 
+                return $err; 
+            }
+
+            if (!$this->_receiver 
+                && ($this->_policy & _PHPTAL_ES_RECEIVER_IS_CONTEXT 
+                    || $this->_policy & _PHPTAL_ES_RECEIVER_IS_TEMP)) {
+                $str = sprintf('Receiver required in expression \'%s\' from %s:%d',
+                               $this->_src, 
+                               $this->_tag->_parser->_file, 
+                               $this->_tag->line);
+                $err = new PHPTAL_ExpressionError($str);
+                return PEAR::raiseError($err);
+            }
+
+            if ($this->_policy & _PHPTAL_ES_RECEIVER_IS_NONE && $this->_receiver) {
+                $str = sprintf('Unexpected receiver \'%s\' in  expression \'%s\' from %s:%d', 
+                               $this->_receiver, 
+                               $this->_src,
+                               $this->_tag->_parser->_file, 
+                               $this->_tag->line);
+                $err = new PHPTAL_ExpressionError($str);
+                return PEAR::raiseError($err);
+            }
+        }
+
+        $this->_prepared = true;
+    }
+
+    function _extractReceiver()
+    {
+        global $_phptal_es_namespaces;
+        
+        $this->_src = preg_replace('/^\s+/sm', '', $this->_src); 
+        if (preg_match('/^([a-z:A-Z_0-9]+)\s+([^\|].*?)$/sm', $this->_src, $m)) {
+            // the receiver looks like xxxx:aaaa
+            //
+            // we must ensure that it's not a known phptales namespaces
+            if (preg_match('/^([a-zA-Z_0-9]+):/', $m[1], $sub)) {
+                $ns = $sub[1];
+                // known namespace, just break
+                if (function_exists('phptal_es_'.$ns)) {
+                    // in_array(strtolower($ns), $_phptal_es_namespaces)) {
+                    return;
+                }
+            }
+            
+            if ($this->_receiver) {
+                $str = sprintf('Receiver already set to \'%s\' in \'%s\'', 
+                               $this->_receiver, 
+                               $this->_src);
+                $err = new PHPTAL_ExpressionError($str);
+                return PEAR::raiseError($err);
+            }
+            
+            $this->_receiver = $m[1];
+            // 
+            // that the way to replace : in setters (usually this this should
+            // only be used under tal:attributes tag !!!!
+            // 
+            $this->_receiver = str_replace(':', '__phptales_dd__', $this->_receiver);
+            $this->_src      = $m[2];
+            if ($this->_receiver == "structure") {
+                $this->_structure = true;
+                $this->_receiver  = false;
+                $this->_extractReceiver();
+            }
+        }
+    }
+
+    /** 
+     * Retrieve the number of sub expressions.
+     */
+    function countSubs()
+    {
+        return count($this->_subs);
+    }
+
+    function &subs()
+    {
+        return $this->_subs;
+    }
+
+    /**
+     * Returns true if a receiver is set for this expression.
+     */
+    function hasReceiver()
+    {
+        return $this->_receiver != false;
+    }
+
+    /**
+     * Retrieve receiver's name.
+     */
+    function getReceiver()
+    {
+        return $this->_receiver;
+    }
+
+    /**
+     * Set expression receiver.
+     */
+    function setReceiver($name)
+    {
+        $this->_receiver = $name;
+    }
+
+    /**
+     * Generate php code for this expression.
+     */
+    function generate()
+    {
+        $err = $this->prepare();
+        if (PEAR::isError($err)) {
+            return $err;
+        }
+
+        if ($this->countSubs() > 0) {
+            foreach ($this->_subs as $sub) {
+                $err = $sub->generate();
+                if (PEAR::isError($err)) {
+                    return $err;
+                }
+            }
+        } else {
+            $exp = $this->_src;
+            if (strlen($exp) == 0) return;
+
+            // expression may be composed of alternatives | list of expression
+            // they are evaluated with a specific policy : _PHPTAL_ES_SEQUENCE
+            //
+            // 'string:' break the sequence as no alternative exists after a
+            // string which is always true.
+            if (preg_match('/\s*?\|\s*?string:/sm', $exp, $m)) {
+                $search = $m[0];
+                $str = strpos($exp, $search);
+                // $str = strpos($exp, ' | string:');
+                // if ($str !== false) {
+                $seq  = preg_split('/(\s*?\|\s*?)/sm', substr($exp, 0, $str));
+                $seq[]= substr($exp, $str + 2);
+            } else {
+                $seq = preg_split('/(\s*?\|\s*?)/sm', $exp);
+            }
+
+            // not a sequence
+            if (count($seq) == 1) {
+                $code = PHPTAL_Expression::_GetCode($this, $exp);
+                if (PEAR::isError($code)) { return $code; }
+                
+                $temp = $this->_gen->newTemporaryVar();
+                $this->_gen->doAffectResult($temp, $code);
+                return $this->_useResult($temp);
+            } else {
+                return $this->_evaluateSequence($seq);
+            }
+        }
+    }
+
+
+    function _evaluateSequence($seq)
+    {
+        $temp = $this->_gen->newTemporaryVar();
+        $this->_gen->doIf('!$__ctx__->_errorRaised');
+        $this->_gen->doDo();
+        foreach ($seq as $s) {
+            // skip empty parts
+            if (strlen(trim($s)) > 0) {
+                $code = PHPTAL_Expression::_GetCode($this, $s);
+                if (PEAR::isError($code)) { return $code; }
+
+                $this->_gen->doUnset($temp);
+                $this->_gen->doAffectResult($temp, $code);
+                $this->_gen->doIf('!PEAR::isError(' . $temp . ') && ' . 
+                                  // $temp .' != false && '.
+                                  $temp . ' !== null');
+                $this->_gen->execute('$__ctx__->_errorRaised = false');
+                $this->_gen->execute('break');
+                $this->_gen->endBlock();
+            }
+        }
+        $this->_gen->doEndDoWhile('0');
+        // test errorRaised
+        $this->_gen->doElse();
+        
+        // $this->_gen->doAffectResult($temp, '""'); // $__ctx__->_errorRaised');
+        $this->_gen->doAffectResult($temp, '$__ctx__->_errorRaised');
+        $this->_gen->execute('$__ctx__->_errorRaised = false');
+        $this->_gen->endBlock();
+        // ----------------
+
+        $err = $this->_useResult($temp);
+                                    
+        // $this->_gen->endBlock();
+        return $err;
+    }
+    
+    function _useResult($temp)
+    {
+        if ($this->_policy & _PHPTAL_ES_RECEIVER_IS_TEMP) {
+            $this->_gen->doReference($this->_receiver, $temp);
+        } else if ($this->_policy & _PHPTAL_ES_RECEIVER_IS_OUTPUT) {
+            $this->_gen->doPrintVar($temp, $this->_structure);
+        } else if ($this->_policy & _PHPTAL_ES_RECEIVER_IS_CONTEXT) {
+            $this->_gen->doContextSet($this->_receiver, $temp);
+        } else {
+            $err = new PHPTAL_ExpressionError("Expression '$this->_src' Don't know what to do with result.");
+            return PEAR::raiseError($err);
+        }
+    }
+
+    /**
+     * Retrieve a function namespace for given string and the associated
+     * expression.
+     *
+     * Examples:
+     *
+     * The function namespace of 'php:XXXX' is 'php'
+     * The function namespace of 'XXXX' is 'path'
+     * The function namespace of 'foo:bar::baz' is 'foo'
+     * 
+     * @param string $str 
+     *        Expression string without receiver
+     *        
+     * @return array
+     *        An array composed as follow : array('ns', 'exp'),
+     *        Where 'ns' is the function namespace and 'exp', is the 
+     *        source string without the 'ns:' part.
+     */
+    function _FindFunctionNamespace($str)
+    {
+        $str = preg_replace('/^\s/sm', '', $str);
+        if (preg_match('/^([a-z0-9\-]+):(?!>:)(.*?)$/ism', $str, $m)) {
+            list($ns, $path) = array_slice($m, 1);
+            $ns = str_replace('-', '_', $ns);
+            return array($ns, $path);
+        }
+        return array('path', $str);
+    }
+
+    /**
+     * Get the code for a ns:args string.
+     */
+    function _GetCode(&$exp, $str)
+    {
+        list($ns, $args) = PHPTAL_Expression::_FindFunctionNamespace($str);
+        $func = "PHPTAL_ES_$ns";
+        if (!function_exists($func)) {
+            $err = new PHPTAL_ExpressionError("Unknown function $func in '$str'");
+            return PEAR::raiseError($err);
+        }
+        return $func($exp, $args);
+    }
+}
+
+/**
+ * Thrown on expression parsing error.
+ */
+class PHPTAL_ExpressionError extends PEAR_Error 
+{
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/ExpressionFunctions.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/ExpressionFunctions.php
new file mode 100644 (file)
index 0000000..238a15d
--- /dev/null
@@ -0,0 +1,384 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+/**
+ * @var $_phptal_es_namespaces
+ * @type array
+ *
+ * This array contains phptales namespaces, it means php:, string:, exists:,
+ * not: and path: at this time.
+ */
+global $_phptal_es_namespaces;
+$_phptal_es_namespaces = array('not', 'php', 'string', 'exists', 'path', 'not-exists');
+
+/**
+ * @var $_phptal_es_keywords
+ * @type array
+ *
+ * List of reserved phptales keywords.
+ */
+global $_phptal_es_keywords;
+$_phptal_es_keywords = array('nothing', 'default', 'structure');
+
+global $_phptal_es_php_types;
+$_phptal_es_php_types = array('true', 'false', 'null');
+
+/**
+ * string: expression type
+ */
+function PHPTAL_ES_string(&$exp, $value)
+{
+    $value = PHPTAL_ES_path_in_string($value);
+    // $value = str_replace('$$', '\$\$', $value);
+    $value = '"' . $value . '"';
+    $value = preg_replace('/^\" ?\"\. /', '', $value);
+    $value = preg_replace('/\.\"\"$/', '', $value);
+    return $value;
+}
+
+/**
+ * not: expression type
+ */
+function PHPTAL_ES_not(&$exp, $value)
+{
+    return "! " . PHPTAL_ES_path($exp, $value);
+}
+
+/**
+ * not-exists: expression type
+ */
+function PHPTAL_ES_not_exists(&$exp, $value) 
+{
+    return "! " . PHPTAL_ES_exists($exp, $value);
+}
+
+/**
+ * path: expression type
+ *
+ * @todo default  -- existing text inside tag
+ *       options  -- ?? keyword arguments passed to template ??
+ *       repeat   -- repeat variables
+ *       attrs    -- initial values of tag attributes
+ *       CONTEXTS -- list of standard names (above list) in case one of these
+ *                   names was hidden by a local variable.
+ */
+function PHPTAL_ES_path(&$exp, $value)
+{
+    $value = trim($value);
+    // special case : 'string' authorized
+    if ($value[0] == "'") { return PHPTAL_ES_path_in_string($value,"'");  }
+    // number case
+    if (preg_match('/^[0-9\.]*$/', $value)) { return $value; }
+    // php constants are accessed though @ keyword
+    if (preg_match('/^@[_a-z][0-9a-z_]*$/i', $value)) { return substr($value, 1); }
+    if ($value == "nothing") { return 'null'; }
+    if ($value == "default") { return '$__default__'; }
+    $value = PHPTAL_ES_path_in_string($value);
+    return '$__ctx__->get("'. $value .'")';
+}
+
+
+function PHPTAL_ES_path_toString(&$exp, $value)
+{
+    $value = trim($value);
+    if ($value == "nothing") { return 'null'; }
+    if ($value == "default") { return '$__default__'; }
+    if (preg_match('/^@[_a-z][0-9a-z_]*$/i', $value)) { return substr($value, 1); }
+    return '$__ctx__->getToString("'. $value .'")';
+}
+
+
+/**
+ * exists: expression type
+ */
+function PHPTAL_ES_exists(&$exp, $value)
+{
+    return '$__ctx__->has("'. trim($value). '")';
+}
+
+/**
+ * php: expression type
+ */
+function PHPTAL_ES_php(&$exp, $str)
+{
+    $parser = new PHPTAL_ES_PHP_Parser($exp, $str);
+    return $parser->evaluate();
+}
+
+
+//
+// utility functions (internal)
+//
+
+function PHPTAL_ES_path_in_string($arg, $c='"')
+{
+    list($match,$repl) = _PHPTAL_context_accessed($arg);
+    for ($i=0; $i<count($match); $i++) {
+        $null = "";
+        $repl[$i] = $c . ". " . PHPTAL_ES_path_toString($null, $repl[$i]) . " ." . $c;
+        $pos = strpos($arg, $match[$i]);
+        $arg = substr($arg, 0, $pos)
+            .  $repl[$i]
+            .  substr($arg, $pos + strlen($match[$i]));
+    }
+    if ($c == '"') {
+        $arg = str_replace('$$','\$', $arg);
+    } else {
+        $arg = str_replace('$$', '$', $arg);
+    }
+    return $arg;
+}
+
+function _PHPTAL_context_accessed($str)
+{
+    if (preg_match_all('/((?<!\$)\$\{?([@_a-zA-z0-9.\/\-]+)\}?)/', $str, $match)) {
+        return array_slice($match, 1);
+    }
+    return array(array(),array());
+}
+
+//
+// php: expression parser
+//
+
+class PHPTAL_ES_PHP_Parser
+{
+    var $_exp;
+    var $_gen;
+    var $_str;
+    var $_aliases = array();
+    var $_code    = "";
+    var $_last_was_array = false;
+
+    function PHPTAL_ES_PHP_Parser(&$expression, $str)
+    {
+        $this->_exp =& $expression;
+        $this->_gen =& $expression->_gen;
+        $this->_str =  $str;
+    }
+
+    function evaluate()
+    {
+        $value   = $this->_str;
+        $strings = array();
+
+        // extract strings and replace context calls
+        if (preg_match_all('/(\'.*?(?<!\\\)\')/sm', $value, $m)) {
+            list(,$m) = $m;
+            foreach ($m as $str) {
+                $s_rplc = PHPTAL_ES_path_in_string($str, "'");
+                $s_rplc = preg_replace('/^\' ?\'\. /', '', $s_rplc);
+                $s_rplc = preg_replace('/\.\'\'$/', '', $s_rplc);
+                $value = str_replace($str, '#_STRING_'. count($strings) . '_#', $value);
+                $strings[] = $s_rplc;
+            }
+        }
+
+        list($match, $replc) = _PHPTAL_context_accessed($value);
+        $contexts = array();
+        foreach ($match as $m) {
+            $i = count($contexts);
+            $contexts[] = $replc[$i];
+            $value = str_replace($m, '#_CONTEXT_'. $i . '_#', $value);
+        }
+
+        // replace or, and, lt, gt, etc...
+        $value = $this->_php_test_modifiers($value);
+        $value = $this->_php_vars($value);
+
+        // restore strings
+        $i = 0;
+        foreach ($strings as $str) {
+            $value = str_replace('#_STRING_'. $i . '_#', $str, $value);
+            $i++;
+        }
+
+        $i = 0;
+        foreach ($contexts as $c) {
+            $value = str_replace('#_CONTEXT_' . $i . '_#', PHPTAL_ES_path($this->_exp, $c), $value);
+            $i++;
+        }
+
+        // experimental, compile php: content
+
+        require_once "Types/Code.php";
+        
+        $code = new Code();
+        $code->setCode($value .";");
+        $err = $code->compile();
+        if (PEAR::isError($err)) {
+            return $this->_raiseCompileError($value, $err);
+        }
+        
+        return $value;
+    }
+
+    function _php_test_modifiers($exp)
+    {
+        $exp = preg_replace('/\bnot\b/i', ' !', $exp);
+        $exp = preg_replace('/\bne\b/i', ' != ', $exp);
+        $exp = preg_replace('/\band\b/i', ' && ', $exp);
+        $exp = preg_replace('/\bor\b/i', ' || ', $exp);
+        $exp = preg_replace('/\blt\b/i', ' < ', $exp);
+        $exp = preg_replace('/\bgt\b/i', ' > ', $exp);
+        $exp = preg_replace('/\bge\b/i', ' >= ', $exp);
+        $exp = preg_replace('/\ble\b/i', ' <= ', $exp);
+        $exp = preg_replace('/\beq\b/i', ' == ', $exp);
+        return $exp;
+    }
+
+    function _php_vars($arg)
+    {
+        $arg = preg_replace('/\s*\/\s*/',' / ', $arg);
+        $arg = preg_replace("/\s*\(\s*/","(", $arg );
+        $arg = preg_replace('/\s*\)\s*/',') ', $arg );
+        $arg = preg_replace('/\s*\[\s*/','[', $arg );
+        $arg = preg_replace('/\s*\]\s*/',']', $arg );
+        $arg = preg_replace('/\s*,\s*/',' , ', $arg );
+
+        $result = "";
+        $path = false;
+        $last_path = false;
+        $last_was_array = false;
+
+        $i = 0;
+        while ($i < strlen($arg)) {
+            $c = $arg[$i];
+            if (preg_match('/[a-z_]/i', $c)) {
+                $path .= $c;
+            } else if (preg_match('/[0-9]/', $c) && $path) {
+                $path .= $c;
+            } else if (preg_match('/[\/\.]/', $c) && $path) {
+                $last_path = $path;
+                $path .= $c;
+            } else if (preg_match('/[\/\.]/', $c) && $this->_last_was_array) {
+                $result .= '->';
+            } else if ($c == '(') {
+                if ($last_path) {
+                    $result .= $this->pathRequest($last_path);
+                    $result .= '->';
+                    $path    = substr($path, strlen($last_path) +1);
+                    $last_path = false;
+                }
+                $result .= $path . '(';
+                $this->_last_was_array = false;
+                $path = false;
+            } else if ($c == '#') {
+                if ($path) {
+                    $result .= $this->pathRequest($path);
+                    $path    = false;
+                    $last_path = false;
+                }
+                $next = strpos($arg, '#', $i+1);
+                $result .= substr($arg, $i, $next - $i +1);
+                $i = $next;
+            } else if ($c == ':') {
+                if ($arg[$i+1] != ':') { // error
+                }
+                $i++;
+                $result .= $path;
+                $result .= '::';
+                $path = false;
+                $last_path = false;
+                
+            } else if ($c == '@') {
+                // access to defined variable, append to result
+                // up to non word character
+                $i++;   // skip @ character
+                do {
+                    $c = $arg[$i];
+                    $result .= $c;
+                    $i++;
+                } while ($i < strlen($arg) && preg_match('/[a-z_0-9]/i', $arg[$i]));
+                $i--;   // reset last character
+                
+            } else {
+                if ($path) {
+                    $result .= $this->pathRequest($path);
+                    $path    = false;
+                }
+                $result .= $c;
+                if ($c == ']') {
+                    $last_path = false;
+                    $path = false;
+                    $this->_last_was_array = true;
+                } else {
+                    $this->_last_was_array = false;
+                }
+            }
+            $i++;
+        }
+        
+        // don't forget the last bit
+        if (isset($path) && $path) {
+            $result .= $this->pathRequest($path);
+        }
+
+        return $result;
+    }
+
+    function pathRequest($path)
+    {
+        global $_phptal_es_php_types;
+
+        if (!preg_match('/[a-z]/i', $path)){ 
+            return $path; 
+        }
+        if ($this->_last_was_array) { 
+            return str_replace('.', '->', $path); 
+        }
+        if (in_array($path, $_phptal_es_php_types)) {
+            return $path;
+        }
+
+        $concatenate = false;
+        $path = str_replace('.','/', $path);
+        if (substr($path,-1) == '/') { 
+            $path = substr($path, 0, -1);
+            $concatenate = true;
+        }
+
+        if (array_key_exists($path, $this->_aliases)) {
+            $res = $this->_aliases[$path];
+        } else {
+            $res = $this->_gen->newTemporaryVar();
+            $this->_aliases[$path] = $res;
+            $this->_gen->doContextGet($res, $path);
+        }
+
+        if ($concatenate) { 
+            $res .= ' .'; 
+        }
+        return $res;
+    }
+
+    function _raiseCompileError($code, $err) 
+    {
+        $str = sprintf("Expression 'php:' compilation error in %s:%d".endl,
+                       $this->_exp->_tag->_parser->_file,
+                       $this->_exp->_tag->line);
+        return PEAR::raiseError($str);
+    }
+}
+
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Filter.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Filter.php
new file mode 100644 (file)
index 0000000..00c983d
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+
+define('PHPTAL_PRE_FILTER', 1);
+define('PHPTAL_POST_FILTER', 2);
+
+/**
+ * Interface for source filter.
+ *
+ * This interface may be used to implement input / output filters.
+ *
+ * If the template intermediate php code is up to date, pre filters won't be
+ * used on it.
+ *
+ * Output filters are only called on main template result.
+ * 
+ *
+ * <?
+ * class MyFilter extends PHPTAL_Filter
+ * {
+ *     function filter(&$tpl, $data, $mode) 
+ *     {
+ *         // just to present $mode usage for input/output filters
+ *         if ($mode == PHPTAL_POST_FILTER) {
+ *             return PEAR::raiseError("MyFilter mustn't be used as a pre-filter');
+ *         }
+ *         
+ *         // remove html comments from template source
+ *         return preg_replace('/(<\!--.*?-->)/sm', '', $data);
+ *     }
+ * }
+ *
+ * $tpl = PHPTAL('mytemplate.html');
+ * $tpl->addInputFilter( new MyFilter() );
+ * echo $tpl->execute();
+ * 
+ * ?>
+ *
+ * @author    Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class PHPTAL_Filter
+{
+    /**
+     * Filter some template source string.
+     *
+     * @param PHPTAL_Template $tpl 
+     *        The template which invoked this filter.
+     *        
+     * @param string $data         
+     *        Data to filter.
+     *
+     * @param int $mode
+     *        PHPTAL_PRE_FILTER | PHPTAL_POST_FILTER depending if this filter
+     *        is registered as a pre-filter or as a post-filter.
+     *        
+     */
+    function filter(&$tpl, $data, $mode)
+    {
+        return $data;
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Generator.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Generator.php
new file mode 100644 (file)
index 0000000..e0c90e9
--- /dev/null
@@ -0,0 +1,362 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_Generator
+{
+    var $_temp_id   = 0;
+    var $_str_buffer = "";
+    var $_tab = "";
+    var $_tab_save = "";
+    var $_code = "";
+    var $_closed = false;
+    var $_fname;
+    var $_funcName;
+
+    var $_macros = array();
+    var $_stacks = array();
+    var $_current_macro = false;
+
+    var $_gettext_required = false;
+
+    var $_headers          = false;
+
+    function PHPTAL_Generator($fname, $func_name)
+    {
+        $this->_fname = $fname;
+        $this->_funcName = $func_name;
+        $this->appendln('<?php');
+        $this->doComment(str_pad("", 78, "-"));
+        $this->doComment("This code was generate by PHPTAL based on the template source file :");
+        $this->doComment("$fname");
+        $this->doComment(str_pad("", 78, "-"));
+        $this->appendln();
+        $this->appendln('function ', $func_name, '(&$__tpl__)');
+        $this->appendln('{');
+        $this->tabInc();
+        $this->appendln('$__ctx__ =& $__tpl__->getContext();');
+        $this->appendln('$__out__ = new PHPTAL_OutputControl($__ctx__, $__tpl__->getEncoding());');
+        $this->appendln('$__ctx__->set("repeat", array());');
+    }
+
+    function setHeaders($h)
+    {
+        $this->_headers = $h;
+        if ($this->_headers) {
+            $this->doHeadersPrint();
+        }
+    }
+
+    function requireGettext()
+    {
+        $this->_gettext_required = true;
+    }
+    
+    function getCode()
+    {
+        if (!$this->_closed) {
+            $this->_flushOutput();
+            $this->appendln('return $__out__->toString();');
+            $this->endBlock();
+
+            foreach ($this->_macros as $name=>$code) {
+                $this->_code .= $code;
+            }
+            if ($this->_gettext_required) {
+                $this->_code = preg_replace('/^<\?php/sm', 
+                                            '<?php require_once "GetText.php";', 
+                                           $this->_code, 
+                                           1);
+            }
+            $this->append('?>');
+            $this->_closed = true;
+        }
+        return $this->_code;
+    }
+    
+    function execute($code)
+    {
+        $this->_flushOutput();
+        $this->appendln(trim($code), ";");
+    }
+
+    function doComment($str)
+    {
+        $this->_flushOutput();
+        $this->appendln('// ',$str);
+    }
+
+    function setSource($tagName, $line)
+    {
+        $this->doComment('TAG ' . $tagName . ' AT LINE ' . $line);
+        $this->appendln('$_src_tag = "'. $tagName. '"; ', '$_src_line = '. $line. ';');
+    }
+    
+    // loop
+    function doDo()
+    {
+        $this->_flushOutput();
+        $this->appendln("do {");
+        $this->tabInc();        
+    }
+    
+    function doEndDoWhile($condition)
+    {
+        $this->tabDec();
+        $this->appendln("} while($condition);");
+    }
+
+    function doWhile($condition)
+    {
+        $this->_flushOutput();
+        $this->appendln("while ($condition) {");
+        $this->tabInc();
+    }
+
+    // conditionals
+    function doIf($condition)
+    {
+        $this->_flushOutput();
+        $this->appendln("if ($condition) {");
+        $this->tabInc();
+    }
+    
+    function doElseIf($condition)
+    {
+        $this->_str_buffer = "";
+        $this->endBlock();
+        $this->appendln("else if ($condition) {");
+        $this->tabInc();
+    }
+    
+    function doElse()
+    {
+        $this->endBlock();
+        $this->appendln("else {");
+        $this->tabInc();
+    }
+
+    // 
+    function doMacroDeclare($name)
+    {
+        $this->_flushOutput();
+        $this->_stacks[] = $this->_code;
+        $this->_code = "";
+        $this->_current_macro = $name;
+        $this->_tab_save = $this->_tab;
+        $this->_tab = "";
+        $this->appendln('function ', $this->_funcName,'_',$name, '(&$__tpl__)');
+        $this->appendln('{');
+        $this->tabInc();
+        $this->appendln('$__ctx__ =& $__tpl__->getContext();');
+        $this->appendln('$__out__ = new PHPTAL_OutputControl($__ctx__, $__tpl__->getEncoding());');
+        if ($this->_headers) {
+            $this->doHeadersPrint();
+        }
+    }
+
+    function doHeadersPrint()
+    {
+        $this->_flushOutput();
+        $this->doIf('! $__tpl__->_headers');
+        $str = str_replace("'", "\\'", $this->_headers);
+        $str = "'" . $str . "'";
+        $str = PHPTAL_ES_path_in_string($str, "'");
+        $this->appendln('$__tpl__->_headers = ' . $str .';');
+        $this->endBlock();
+    }
+    
+    function doMacroEnd()
+    {
+        $this->_flushOutput();
+        $this->appendln('return $__out__->toString();');
+        $this->endBlock();
+        $this->_macros[$this->_current_macro] = $this->_code;
+        $this->_code = array_pop($this->_stacks);
+        $this->_current_macro = false;
+        $this->_tab = $this->_tab_save;
+    }
+
+    function doAffectResult($dest, $code)
+    {
+        if ($dest[0] != '$') { $dest = '$'.$dest; }
+        // test &
+        $this->appendln("$dest = $code;");
+    }
+    
+    //
+    function doPrintString()
+    {
+        $args = func_get_args();
+        $this->_str_buffer .= join("", $args);
+        // $this->appendln('$__out__->write(', $str, ');');
+    }
+    
+    function doPrintVar($var, $structure=false)
+    {
+        $this->_flushOutput();
+        if ($var[0] != '$') { 
+            $var = '$' . $var; 
+        }
+        if ($structure) {
+            $this->appendln('$__out__->writeStructure(', $var, ');');
+        } else {
+            $this->appendln('$__out__->write(', $var, ');');
+        }
+    }
+    
+    function doPrintRes($code, $structure=false)
+    {
+        $this->_flushOutput();
+        if ($structure) {
+            $this->appendln('$__out__->writeStructure(', $code, ');');
+        } else {
+            $this->appendln('$__out__->write(', $code, ');');
+        }
+    }
+
+    function doPrintContext($path, $structure=false)
+    {
+        $code = sprintf('$__ctx__->get(\'%s\')', $path);
+        $this->doPrintRes($code, $structure);
+    }
+
+    // output buffering control
+    function doOBStart()
+    {
+        $this->_flushOutput();
+        $this->appendln('$__out__->pushBuffer();');
+    }
+    
+    function doOBEnd($dest)
+    {
+        $this->_flushOutput();
+        // test &
+        $this->appendln($dest, ' =& $__out__->popBuffer();');
+    }
+
+    function doOBClean()
+    {
+        $this->_flushOutput();
+        $this->appendln('$__out__->popBuffer();');
+    }
+
+    function doOBPrint()
+    {
+        $this->_flushOutput();
+        $this->appendln('$__out__->writeStructure($__out__->popBuffer());');
+    }
+
+    function doOBEndInContext($dest)
+    {
+        $this->doContextSet($dest, '$__out__->popBuffer()');
+    }
+
+    // 
+    function doReference($dest, $source)
+    {
+        $this->_flushOutput();
+        if ($dest[0] != '$') { $dest = '$'.$dest; }
+        if ($source[0] != '$') { $source = '$'.$source; }
+        // test &
+        $this->appendln("$dest =& $source;");
+    }
+    
+    function doUnset($var)
+    {
+        $this->appendln("unset($var);");
+    }
+    
+    // create a new temporary variable (non context) and return its name
+    function newTemporaryVar()
+    {
+        return '$temp_' . $this->_temp_id++;
+    }
+    
+    function releaseTemporaryVar($name)
+    {
+        $this->doUnset($name);
+    }
+
+    // context methods
+    
+    function doContextSet($out, $code)
+    {
+        $this->_flushOutput();
+        if ($out[0] != '$') 
+        { $out = '"'.$out.'"'; }
+        // test & (Ref)
+        $this->appendln("\$__ctx__->setRef($out, $code);");
+    }
+    
+    function doContextGet($out, $path)
+    {
+        $this->_flushOutput();
+        if ($out[0] != '$') 
+        { $out = '$' . $out; }
+        // test &
+        $this->appendln("$out =& \$__ctx__->get(\"$path\");");
+    }
+    
+    function endBlock()
+    {
+        $this->tabDec();
+        $this->appendln('}');
+    }
+
+    function tabInc()
+    {
+        $this->_flushOutput();
+        $this->_tab .= "    ";
+    }
+    
+    function tabDec()
+    {
+        $this->_flushOutput();
+        $this->_tab = substr($this->_tab, 4);
+    }
+    
+    function appendln()
+    {
+        $args = func_get_args();
+        $str  = join("", $args);
+        $this->_code .= $this->_tab . $str . "\n";
+    }
+
+    function append()
+    {
+        $args = func_get_args();
+        $str  = join("", $args);
+        $this->_code .= $this->_tab . $str;
+    }
+    
+    function _flushOutput()
+    {
+        if ($this->_str_buffer == "") return;
+        $this->_str_buffer = str_replace("'", "\\'", $this->_str_buffer);
+        $this->_str_buffer = "'" . $this->_str_buffer . "'";
+        $this->_str_buffer = PHPTAL_ES_path_in_string($this->_str_buffer, "'");
+        $this->appendln('$__out__->writeStructure(', $this->_str_buffer, ');');
+        $this->_str_buffer = "";
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/I18N.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/I18N.php
new file mode 100644 (file)
index 0000000..cf03650
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+
+class PHPTAL_I18N 
+{
+    function set($varName, $value)
+    {
+        return GetText::setVar($varName, $value);
+    }
+
+    function translate($key)
+    {
+        return GetText::gettext($key);
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/LoopControler.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/LoopControler.php
new file mode 100644 (file)
index 0000000..fdb8d7a
--- /dev/null
@@ -0,0 +1,364 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+require_once "Types/OArray.php";
+require_once "Types/OHash.php";
+require_once "Types/Iterator.php";
+
+/**
+ * Template loop execution controler.
+ *
+ * This object is instantiated by the template on each loop. 
+ *
+ * LoopControlers accept different types of loop target.
+ * 
+ * - array
+ * - objects having an getNewIterator() method returning an Iterator object.
+ * - Iterator objects which produce isValid(), next(), key() and index() 
+ *   methods.
+ *   please note that key() return index() for non associative data.
+ *
+ * Other types are rejected by the loop controler on runtime producing
+ * a TypeError exception.
+ *
+ * The loop controler install its iterator under the path "repeat/item"
+ * where "item" is the name of the output var (defined in the template).
+ *
+ * Thus, the template can access differents methods of the iterator:
+ *    repeat/someitem/key
+ *    repeat/someitem/index
+ *    repeat/someitem/next
+ *    repeat/someitem/last
+ *
+ * If not all of these methods are implemented in iterators, ask 
+ * iterator maintainers.
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ * 
+ */
+class PHPTAL_LoopControler
+{
+    var $_context;
+    var $_data;
+    var $_data_name;
+    var $_iterator;
+    var $_error;
+    
+    /**
+     * Controler constructor.
+     *
+     * @param PHPTAL_Context $context
+     *        The template context.
+     * @param string $data_name
+     *        The item data name.
+     * @param mixed  $data
+     *        Loop resource.
+     */
+    function PHPTAL_LoopControler(&$context, $data_name, $data)
+    {
+        $this->_context   =& $context;
+        $this->_data      =& $data;
+        $this->_data_name =  $data_name;
+        
+        // ensure that data is not an error
+        if (PEAR::isError($data)) {
+            $this->_error =& $data;
+            return $data;
+        }
+        
+        // accepted objects
+        // 
+        // - iteratable implementing getNewIterator() method
+        // - iterator implementing next(), isValid() and index() methods
+        // - db_result produced by PEAR::DB package
+        // 
+        if (is_object($data)) {
+            if (method_exists($data, "getNewIterator")) {
+                
+                $this->_iterator =& $data->getNewIterator();
+                
+            } elseif (is_a("iterator", $data)
+                      || (method_exists($data, 'next')
+                          && method_exists($data, 'isValid')
+                          && method_exists($data, 'index'))) {
+                
+                $this->_iterator =& $data;
+                
+            } elseif (get_class($data) == 'db_result') {
+                
+                $this->_iterator = new PHPTAL_DBResultIterator($data);
+                
+            } else {
+                
+                $err = new TypeError("PHPTAL loop controler received a non Iterable object ("
+                                     . get_class($data) . ")");
+                $this->_error =& $err;
+                return PEAR::raiseError($err);
+            }
+        } elseif (is_array($data)) {
+            // 
+            // array are accepted thanks to OArrayIterator
+            // 
+            reset($data);
+            if (count($data) > 0 && array_key_exists(0, $data)) {
+                // echo "OArray::iterator", RxObject::ClassName($data), endl;
+                $this->_data = new OArray($data);
+                $this->_iterator =& $this->_data->getNewIterator();
+            } else {
+                // echo "OHash::iterator", RxObject::ClassName($data), endl;
+                $this->_data = new OHash($data);
+                $this->_iterator =& $this->_data->getNewIterator();
+            }
+        } else {
+            $err = new TypeError("phptal loop controler received a non Iterable value ("
+                                 . gettype($data) . ")");
+            $this->_error =& $err;
+            return PEAR::raiseError($err);
+        }
+
+        // 
+        // install loop in repeat context array
+        // 
+        $repeat =& $this->_context->get("repeat");
+        if (array_key_exists($this->_data_name, $repeat)) {
+            unset($repeat[$this->_data_name]);
+        }
+        $repeat[$this->_data_name] =& $this;        
+
+        // $this->_context->setRef($this->_data_name, $temp);
+        $temp =& $this->_iterator->value();
+        $this->_context->set($this->_data_name, $temp);
+        return $temp;
+    }
+
+    /**
+     * Return current item index.
+     * 
+     * @return int
+     */
+    function index()
+    {
+        return $this->_iterator->index();
+    }
+
+    /**
+     * Return current item key or index for non associative iterators.
+     *
+     * @return mixed
+     */
+    function key()
+    {
+        if (method_exists($this->_iterator, "key")) {
+            return $this->_iterator->key();
+        } else {
+            return $this->_iterator->index();
+        }
+    }
+
+    /**
+     * Index is in range(0, length-1), the number in in range(1, length).
+     *
+     * @return int
+     */
+    function number()
+    {
+        return $this->index() + 1;
+    }
+
+    /**
+     * Return true if index is even.
+     *
+     * @return boolean
+     */
+    function even()
+    {
+        return !$this->odd();
+    }
+
+    /**
+     * Return true if index is odd.
+     *
+     * @return boolean
+     */
+    function odd()
+    {
+        return ($this->index() % 2);
+    }
+
+    /**
+     * Return true if at the begining of the loop.
+     *
+     * @return boolean
+     */
+    function start()
+    {
+        return ($this->index() == 0);
+    }
+
+    /**
+     * Return true if at the end of the loop (no more item).
+     *
+     * @return boolean
+     */
+    function end()
+    {
+        return ($this->length() == $this->number());
+    }
+
+    function isValid()
+    {
+        return $this->_iterator->isValid();
+    }
+
+    /**
+     * Return the length of the data (total number of iterations). 
+     *
+     * @return int
+     */
+    function length()
+    {
+        return $this->_data->size();
+    }
+   
+    /**
+     * Retrieve next iterator value.
+     *
+     * @return mixed
+     */
+    function &next()
+    {
+        $temp =& $this->_iterator->next();
+        if (!$this->_iterator->isValid()) {
+            return false;
+        }
+        
+        // $this->_context->setRef($this->_data_name, $temp);
+        $this->_context->set($this->_data_name, $temp);
+        return $temp;
+    }
+};
+
+
+/**
+ * Iterator for DB_Result PEAR object.
+ *
+ * This class is an implementation of the Iterator Interface
+ * for DB_Result objects produced by the usage of PEAR::DB package.
+ * 
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class PHPTAL_DBResultIterator extends Iterator
+{
+    var $_src;
+    var $_index = -1;
+    var $_end   = false;
+    var $_value;
+    
+    /**
+     * Iterator constructor.
+     *
+     * @param DB_Result $result
+     *        The query result.
+     */
+    function PHPTAL_DBResultIterator(&$result)
+    {
+        $this->_src =& $result;
+        $this->reset();
+    }
+
+    function reset()
+    {
+        if ($this->size() == 0) {
+            $this->_end = true;
+            return;
+        }
+
+        $this->_index = 0;        
+        $this->_end = false;
+        unset($this->_value);
+        $this->_value = $this->_src->fetchRow();        
+    }
+    
+    /**
+     * Return the number of rows in this result.
+     *
+     * @return int
+     */
+    function size()
+    {
+        if (!isset($this->_size)) {
+            $this->_size = $this->_src->numRows();
+        }
+        return $this->_size;
+    }
+
+    /**
+     * Returns true if end of iterator has not been reached yet.
+     */
+    function isValid()
+    {
+        return !$this->_end;
+    }
+
+    /**
+     * Return the next row in this result.
+     *
+     * This method calls fetchRow() on the DB_Result, the return type depends
+     * of the DB_result->fetchmod. Please specify it before executing the 
+     * template.
+     *
+     * @return mixed
+     */
+    function &next()
+    {
+        if ($this->_end || ++ $this->_index >= $this->size()) {
+            $this->_end = true;
+            return false;
+        }
+
+        unset($this->_value);
+        $this->_value = $this->_src->fetchRow();
+        return $this->_value;
+    }
+    
+    /**
+     * Return current row.
+     *
+     * @return mixed
+     */
+    function &value()
+    {
+        return $this->_value;
+    }
+
+    /**
+     * Return current row index in resultset.
+     *
+     * @return int
+     */
+    function index()
+    {
+        return $this->_index;
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Macro.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Macro.php
new file mode 100644 (file)
index 0000000..facdd03
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+/*
+ * Macro invoker.
+ */
+class PHPTAL_Macro extends PHPTAL_Template
+{
+    var $_path = false;
+    var $_name;
+    
+    /**
+     * Macro constructor.
+     *
+     * @param PHPTAL_Template $caller 
+     *        The macro caller may be a template or a macro.
+     * @param string $path 
+     *        The macro path/name
+     */
+    function PHPTAL_Macro(&$caller, $path)
+    {
+        $this->_name = $path;
+        
+        // extract macro path part, if none found, we'll assume macro is 
+        // in the caller template.
+
+        if (preg_match('/(.*?)\/([a-zA-Z0-9_]*?)$/', $this->_name, $match)) {
+            list(, $this->_path, $this->_name) = $match;
+        } else {
+            $this->_sourceFile = $caller->_sourceFile;
+        }
+
+        // call parent constructor
+        $this->PHPTAL_Template($this->_path, 
+                               $caller->_repository, 
+                               $caller->_cacheDir);
+        
+        $this->setParent($caller);
+        $this->setEncoding($caller->getEncoding());
+    }
+    
+    /**
+     * Execute macro with caller context.
+     *
+     * @return string
+     */
+    function execute()
+    {
+        if ($this->_path !== false) {
+            $err = $this->_prepare();
+            if (PEAR::isError($err)) {
+                return $err;
+            }
+        }
+        return $this->_cacheManager->macro($this,
+                                            $this->_sourceFile,
+                                            $this->_name,
+                                            $this->_parent->getContext());
+    }
+
+    /**
+     * Really process macro parsing/invocation.
+     *
+     * @return string
+     */
+    function _process()
+    {
+        if ($this->_path !== false) {
+            $err = $this->_load();
+            if (PEAR::isError($err)) {
+                return $err;
+            }
+        } else {
+            $this->_funcName = $this->_parent->_funcName;
+        }            
+        
+        $func = $this->_funcName . '_' . $this->_name;
+        
+        if (!function_exists($func)) {
+            $err = "Unknown macro '$this->_name'";
+            return PEAR::raiseError($err);
+        }
+        
+        return $func($this->_parent);
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/OutputControl.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/OutputControl.php
new file mode 100644 (file)
index 0000000..ce3c340
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+class PHPTAL_OutputControl
+{
+    var $_buffer = "";
+    var $_buffers = array();
+    var $_quoteStyle = ENT_COMPAT;
+    var $_encoding   = 'UTF-8';
+    var $_context;
+    
+    function PHPTAL_OutputControl(&$context, $encoding='UTF-8')
+    {
+        $this->_context = $context;
+        $this->_encoding = $encoding;
+    }
+
+    function pushBuffer()
+    {
+        $this->_buffers[] = $this->_buffer;
+        $this->_buffer = "";
+    }
+    
+    function popBuffer()
+    {
+        $res = $this->_buffer;
+        $this->_buffer = array_pop($this->_buffers);
+        return $res;
+    }
+    
+    function write(&$str)
+    {
+        if (is_object($str)) {
+            if (PEAR::isError($str)) {
+                $str = "[". get_class($str) . ": " . $str->message . "]";
+                // $this->_context->cleanError();
+            } else {
+                $str = Types::toString($str);
+            }
+        }
+
+        if (defined("PHPTAL_DIRECT_OUTPUT") && count($this->_buffers) == 0) {
+            // echo htmlentities($str);
+            // support for cyrillic strings thanks to Igor E. Poteryaev
+            echo htmlentities($str, $this->_quoteStyle, $this->_encoding);
+        } else {
+            // $this->_buffer .= htmlentities($str);
+            // support for cyrillic strings thanks to Igor E. Poteryaev
+            $this->_buffer .= htmlentities($str, $this->_quoteStyle, $this->_encoding);
+        }
+    }
+
+    function writeStructure($str)
+    {
+        if (is_object($str)) {
+            if (PEAR::isError($str)) {
+                $str = "[" . $str->message . "]";
+                // $this->_context->cleanError();
+            } else {
+                $str = Types::toString($str);
+            }
+        }
+        
+        if (defined("PHPTAL_DIRECT_OUTPUT") && count($this->_buffers) == 0) {
+            echo $str;
+        } else {
+            $this->_buffer .= $str;
+        }
+    }
+
+    function &toString()
+    {
+        return $this->_buffer;
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Parser.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Parser.php
new file mode 100644 (file)
index 0000000..f113c5d
--- /dev/null
@@ -0,0 +1,515 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+$__d = dirname(__FILE__);
+require_once _phptal_os_path_join($__d, 'XML_Parser.php');
+require_once _phptal_os_path_join($__d, 'Attribute.php');
+require_once _phptal_os_path_join($__d, 'Expression.php');
+require_once _phptal_os_path_join($__d, 'ExpressionFunctions.php');
+require_once _phptal_os_path_join($__d, 'Generator.php');
+require_once _phptal_os_path_join($__d, 'Tag.php');
+
+$_t = _phptal_os_path_join($__d, 'Attribute', 'TAL');
+require_once _phptal_os_path_join($_t, 'Attributes.php');
+require_once _phptal_os_path_join($_t, 'Comment.php');
+require_once _phptal_os_path_join($_t, 'Content.php');
+require_once _phptal_os_path_join($_t, 'Condition.php');
+require_once _phptal_os_path_join($_t, 'Define.php');
+require_once _phptal_os_path_join($_t, 'Omit_tag.php');
+require_once _phptal_os_path_join($_t, 'Replace.php');
+require_once _phptal_os_path_join($_t, 'On_error.php');
+require_once _phptal_os_path_join($_t, 'Repeat.php');
+
+$_t = _phptal_os_path_join($__d, 'Attribute', 'PHPTAL');
+require_once _phptal_os_path_join($_t, 'Include.php');
+require_once _phptal_os_path_join($_t, 'Src_include.php');
+
+$_t = _phptal_os_path_join($__d, 'Attribute', 'METAL');
+require_once _phptal_os_path_join($_t, 'Define_macro.php');
+require_once _phptal_os_path_join($_t, 'Use_macro.php');
+require_once _phptal_os_path_join($_t, 'Define_slot.php');
+require_once _phptal_os_path_join($_t, 'Fill_slot.php');
+
+$_t = _phptal_os_path_join($__d, 'Attribute', 'I18N');
+require_once _phptal_os_path_join($_t, 'Translate.php');
+require_once _phptal_os_path_join($_t, 'Name.php');
+require_once _phptal_os_path_join($_t, 'Attributes.php');
+
+
+/**
+ * PHPTAL template parser.
+ * 
+ * This object implements PHPTAL_XML_Parser interface and will accept only 
+ * well formed xml templates.
+ * 
+ * 
+ * Parser object has two aims :
+ *
+ * - generate the template structure tree
+ * - generate the php source code this structure represents
+ *
+ * Once this job is accomplished, the parser object should be destroyed and
+ * MUST NOT be used to parse another template. It's a one time and drop 
+ * object.
+ * 
+ *
+ * Note about code generation :
+ *
+ * The final source code is ready to write into a php file.
+ * 
+ * The code generation process requires a function name which should represent
+ * the template unique id (Template class makes an md5 over the source file
+ * path to create this id).
+ * 
+ * @version 0.1
+ * @author  Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class PHPTAL_Parser extends PHPTAL_XML_Parser
+{
+    // root gat
+    var $_root;
+    // document headers (string)
+    var $_headers = false;
+    var $_started = false;
+
+    var $_docType;
+    var $_inDocType;
+
+    // current tag
+    var $_current;
+
+    // source file name
+    var $_file;
+
+    // activate xhtml empty tags lookup 
+    var $_outputFormat = PHPTAL_XHTML;
+
+    // keep xmlns:* attributes ?
+    var $_keepXMLNS = false;
+
+    /**
+     * Parse a template string.
+     * 
+     * @param string $file
+     *        The template source file.
+     * @param string $src
+     *        The template source.
+     *
+     * @throws PHPTAL_ParseError
+     */
+    function parse($file, $src)
+    {
+        $this->_file  = $file;
+        $this->_initRoot();
+        return $this->parseString($src, true);
+    }
+
+    /**
+     * Generate php code.
+     * 
+     * After template parsing, this method must be called to generate php code
+     * from the template tree.
+     * 
+     * @param  string func_name 
+     *         The template function name
+     *         
+     * @access private
+     * @return string
+     */
+    function generateCode($func_name)
+    {
+        $gen = new PHPTAL_Generator($this->_file, $func_name);
+        $gen->setHeaders($this->_headers);
+        $err = $this->_root->generateCode($gen);
+        if (PEAR::isError($err)) {
+            return $err;
+        }
+        return $gen->getCode();
+    }
+
+    /**
+     * Return a string representation of the underlying xhtml tree.
+     *
+     * This method is for debug purpose.
+     *
+     * @access private
+     * @return string
+     */
+    function toString()
+    {
+        $buf = new StringBuffer();
+        $buf->appendln('Template tree [\'', $this->_file, '\']');
+        $buf->append($this->_root->toString());
+        return $buf->toString();
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Private methods
+    // ----------------------------------------------------------------------
+    
+    /**
+     * Initialize root node.
+     *
+     * @access private
+     */
+    function _initRoot()
+    {
+        $this->_headers = "";
+        $this->_started = false;
+        $this->_root    =  new PHPTAL_Tag($this, "#root", array());
+        $this->_current =& $this->_root;
+    }
+
+    /**
+     * Push a node as the current one.
+     *
+     * @param  PHPTAL_Node tag
+     * @access private
+     */
+    function _push(&$tag)
+    {
+        $this->_current->addChild($tag);
+        unset($this->_current);
+        $this->_current =& $tag;
+    }
+
+    /**
+     * Push a node into the current one.
+     *
+     * @param  PHPTAL_Node tag
+     * @access private
+     */
+    function _pushChild(&$tag)
+    {
+        $this->_current->addChild($tag);
+    }
+    
+    /**
+     * Pop the last node (go up a level in tree).
+     *
+     * @access private
+     */
+    function _pop()
+    {
+        $temp =& $this->_current;
+        unset($this->_current);
+        if ($temp != $this->_root) {
+            $this->_current =& $temp->getParent();
+        } else {
+            $this->_current =& $this->_root;
+        }
+    }
+
+    /*
+     * getter/setter for the output mode.
+     *
+     * @param int $mode optional
+     *        PHPTAL_XML or PHPTAL_XHTML
+     */
+    function _outputMode($mode=false)
+    {
+        if ($mode !== false) {
+            $this->_outputFormat = $mode;
+        }
+        return $this->_outputFormat;
+    }
+
+    // ----------------------------------------------------------------------
+    // XML callbacks methods
+    // ----------------------------------------------------------------------
+    
+    /**
+     * xml callback
+     * 
+     * @access private
+     */
+    function onElementStart($name, $attributes)
+    {
+        global $_phptal_namespaces;
+
+        $this->_started = true;
+
+        if (strpos($name, ':') !== false) {
+            list($domain, $extend) = split(':', strtoupper($name));
+            if (($extend == 'BLOCK') && (in_array($domain, $_phptal_namespaces))) {
+                $attributes = PHPTAL_Parser::extendZptBlockAttributes($domain, $attributes);
+                $attributes['tal:omit-tag'] = '';
+            }
+        }
+
+        // separate phptal attributes from xhtml ones
+        // if an attribute is not found, an error is raised.
+        $split = PHPTAL_Parser::TemplateAttributes($attributes);
+        if (PEAR::isError($split)) {
+            return $split;
+        }
+        
+        // no error, the returned value is a tuple 
+        list($phptal, $attributes) = $split;
+        
+        // sort phptal attributes
+        $phptal = PHPTAL_Parser::OrderTemplateAttributes($phptal);
+        if (PEAR::isError($phptal)) {
+            return $phptal;
+        }
+        
+        // create the tag and add its template attributes
+        $tag = new PHPTAL_Tag($this, $name, $attributes);
+        foreach ($phptal as $t) { 
+            $tag->appendTemplateAttribute($t); 
+            unset($t); // $t is appended by reference 
+        }
+        
+        $tag->line = $this->getLineNumber();
+        $this->_push($tag);
+    }
+
+    /**
+     * Extends ZPT attributes withing a *:block element so these attributes can
+     * be used by phptal parser.
+     *
+     * @access private
+     */
+    function extendZptBlockAttributes($domain, $attributes)
+    {
+        global $_phptal_dictionary;
+        $result = array();
+        foreach ($attributes as $key => $value) {
+            $expected = strtoupper("$domain:$key");
+            if (array_key_exists($expected, $_phptal_dictionary)) {
+                $result[$expected] = $value;
+            }
+        }
+        return $result;
+    }
+
+    /**
+     * xml callback
+     * 
+     * @access private
+     */
+    function onElementData($data)
+    {
+        // ${xxxx} variables are evaluated during code
+        // generation whithin the CodeGenerator under the 
+        // printString() method.
+        $tag = new PHPTAL_Tag($this, "#cdata", array());
+        $tag->setContent($data);
+        $this->_pushChild($tag);
+    }
+
+    /**
+     * xml callback
+     * 
+     * @access private
+     */
+    function onSpecific($data)
+    {
+        // fix xml parser '&' => '&amp;' automatic conversion
+           $data = str_replace('&amp;', '&', $data);
+
+        if ($this->_current->name() == "#root" && !$this->_started) { 
+            $this->_headers .= $data;
+            return;
+        }
+        $tag = new PHPTAL_Tag($this, "#cdata", array());
+        $tag->setContent($data);
+        $this->_pushChild($tag);
+    }
+
+    /**
+     * xml callback
+     * 
+     * @access private
+     */
+    function onElementClose($name)
+    {
+        if ($this->_current == null) {
+            return $this->_raiseNoTagExpected($name);
+        }
+        if ($this->_current->name() != $name) {
+            return $this->_raiseUnexpectedTagClosure($name);
+        }
+        $this->_pop();
+    }
+
+    // ----------------------------------------------------------------------
+    // Static methods
+    // ----------------------------------------------------------------------
+
+    /**
+     * Lookup template attributes in given hashtable.
+     *
+     * This method separate xml attributes from template attributes
+     * and return an array composed of the array of formers and the array of
+     * laters.
+     * 
+     * @access private 
+     * @static 1
+     * 
+     * @param   hashtable attrs 
+     *          Attributes hash
+     *          
+     * @return  array
+     */
+    function TemplateAttributes($attrs)
+    {
+        global $_phptal_dictionary, $_phptal_aliases, $_phptal_namespaces;
+        $phptal = array();
+        $att = array();
+        
+        foreach ($attrs as $key=>$exp) {
+            
+            $test_key = strtoupper($key);
+            $ns = preg_replace('/(:.*?)$/', '', $test_key);
+            $sns = preg_replace('/^(.*?:)/', '', $test_key);
+            // dictionary lookup
+            if (array_key_exists($test_key, $_phptal_dictionary)) {
+                $phptal[$test_key] = $exp;
+            }
+            // alias lookup
+            elseif (array_key_exists($test_key, $_phptal_aliases)) {
+                $phptal[ $_phptal_aliases[$test_key] ] = $exp;
+            }
+            // the namespace is known but the the attribute is not
+            elseif (in_array($ns, $_phptal_namespaces)) {
+                return $this->_raiseUnknownAttribute($test_key);
+            }
+            // regular xml/xhtml attribute (skip namespaces declaration)
+            elseif ($ns !== 'XMLNS' || $this->_keepXMLNS 
+                    || !in_array($sns, $_phptal_namespaces)) {
+                $att[$key] = $exp;
+            }
+        }
+        return array($phptal, $att);
+    }
+
+    /**
+     * Order phptal attributes array using $_phptal_rules_order array.
+     * 
+     * @static  1
+     * @access  private
+     * 
+     * @param   array phptal 
+     *          Array of phptal attributes (will be modified)
+     */
+    function OrderTemplateAttributes(&$phptal)
+    {
+        global $_phptal_rules_order, $_phptal_dictionary;
+        
+        // order elements by their name using the rule table       
+        $result = array();
+        foreach ($phptal as $akey=>$exp) {
+            
+            // retrieve attribute handler class
+            $class = "PHPTAL_ATTRIBUTE_" . str_replace(":", "_", $akey);
+            $class = str_replace("-", "_", $class);
+            if (!class_exists($class)) {
+                return $this->_raiseAttributeNotFound($akey, $class);
+            }
+
+            $hdl = new $class($exp);
+            $hdl->name = $akey;
+            $hdl->_phptal_type = $_phptal_dictionary[$akey];
+
+            // resolve attributes conflict
+            $pos = $_phptal_rules_order[$akey];
+            if (array_key_exists($pos, $result)) {
+                return $this->_raiseAttConflict($akey, $result[$pos]->name);
+            }
+            
+            // order elements by their order rule
+            $result[$_phptal_rules_order[$akey]] = $hdl;
+            unset($hdl);
+        }
+        return $result;
+    }
+
+    // ----------------------------------------------------------------------
+    // Errors raising methods
+    // ----------------------------------------------------------------------
+
+    function _raiseAttributeNotFound($att, $class)
+    {
+        $str = sprintf("Attribute '%s' exists in dictionary but class '%s' ".
+                       "was not found",
+                       $att, $class);
+        $err = new PHPTAL_ParseError($str);
+        return PEAR::raiseError($err);
+    }
+    
+    function _raiseUnknownAttribute($att)
+    {
+        $str = sprintf("Unknown PHPTAL attribute '%s' in %s at line %d",
+                       $att, $this->_file, $this->getLineNumber());
+        $err = new PHPTAL_UnknownAttribute($str);
+        return PEAR::raiseError($err);
+    }
+
+    function _raiseUnexpectedTagClosure($name)
+    {
+        $str = sprintf("Non matching tag '%s' error in xml file '%s' at line %d" 
+                       . endl . "waiting for end of tag '%s' declared at line %d.",
+                       $name, $this->_file, $this->getLineNumber(), 
+                       $this->_current->name(), $this->_current->line);
+        $err = new PHPTAL_ParseError($str);
+        return PEAR::raiseError($err);
+    }
+
+    function _raiseNoTagExpected($name)
+    {
+        $str = sprintf("Bad xml error in xml file '%s' at line %d". endl
+                       ."Found closing tag '%s' while no current tag is waited.",
+                       $this->_file, $this->getLineNumber(), $name);
+        $err = new PHPTAL_ParseError($str);
+        return PEAR::raiseError($err);
+    }
+
+    function _raiseAttConflict($a2, $a1)
+    {
+        $str = sprintf('Template Attribute conflict in \'%s\' at line %d'. endl
+                       . ' %s must not be used in the same tag as %s', 
+                       $this->_file, $this->getLineNumber(), $a1, $a2);
+        $err = new PHPTAL_AttributeConflict($str);
+        return PEAR::raiseError($err);
+    }
+};
+
+/**
+ * Error raised at parse time when some bad xml is found or when some tag
+ * is unknown or is badly used.
+ */
+class PHPTAL_ParseError extends PEAR_Error {}
+
+/**
+ * Error raised when an unknown PHPTAL tag is requested by the template.
+ */
+class PHPTAL_UnknownAttribute extends PHPTAL_ParseError {}
+
+/**
+ * Error raised when a template attribute conflicts with another one.
+ */
+class PHPTAL_AttributeConflict extends PHPTAL_ParseError {}
+
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/SourceLocator.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/SourceLocator.php
new file mode 100644 (file)
index 0000000..e281479
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * Interface for template source locators.
+ *
+ * A locator is a way to retrieve a PHPTAL template source otherwhere than in
+ * the file system.
+ *
+ * The default behavour of this class is to act like a file system locator.
+ *
+ * @author    Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class PHPTAL_SourceLocator
+{
+    var $path;
+    
+    function PHPTAL_SourceLocator($path)
+    {
+        $this->path = $path;
+    }
+    
+    /**
+     * Returns an absolute path to this resource.
+     * 
+     * The result of this method is used to generate some unique
+     * md5 value which represent the template php function name
+     * and the intermediate php file name.
+     *
+     * @return string
+     */
+    function realPath()
+    {
+        return $this->path;
+    }
+
+    /**
+     * Return source last modified date in a filemtime format.
+     *
+     * The result is compared to php intermediate mtime to decide
+     * weither or not to re-parse the template source.
+     *
+     * @return int
+     */
+    function lastModified()
+    {
+        return filemtime($this->path);
+    }
+
+    /**
+     * Return the template source.
+     *
+     * This method is invoqued if the template has to be parsed.
+     *
+     * @return string
+     */
+    function data()
+    {
+        return join('', file($this->path));
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/SourceResolver.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/SourceResolver.php
new file mode 100644 (file)
index 0000000..735a161
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * This class is used to resolve template source path outside the file system.
+ *
+ * Given a path, a template repository and a template caller path, one resolver
+ * must decide whether or not it can retrieve the template source.
+ *
+ * @author    Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class PHPTAL_SourceResolver
+{
+    /**
+     * Resolve a template source path.
+     *
+     * This method is invoked each time a template source has to be
+     * located.
+     *
+     * This method must returns a PHPTAL_SourceLocator object which
+     * 'point' to the template source and is able to retrieve it.
+     *
+     * If the resolver does not handle this kind of path, it must return
+     * 'false' so PHPTAL will ask other resolvers.
+     *
+     * @param string $path       -- path to resolve
+     *
+     * @param string $repository -- templates repository if specified on
+     *                              on template creation. 
+     *
+     * @param string $callerPath -- caller realpath when a template look
+     *                              for an external template or macro,
+     *                              this should be usefull for relative urls
+     *
+     * @return PHPTAL_SourceLocator | false 
+     */
+    function resolve($path, $repository=false, $callerPath=false)
+    {
+        // first look at an absolute path
+        $pathes = array($path);
+        // search in the caller directory
+        if ($callerPath) {
+            $pathes[] = dirname($callerPath) . PHPTAL_PATH_SEP . $path;
+        }
+        // search in the template repository
+        if ($repository) {
+            $pathes[] = $repository . PHPTAL_PATH_SEP . $path;
+        }
+        // search in the defined repository
+        if (defined('PHPTAL_REPOSITORY')) {
+            $pathes[] = PHPTAL_REPOSITORY . PHPTAL_PATH_SEP . $path;
+        }
+        foreach ($pathes as $ftest) {
+            if (file_exists($ftest)) {
+                $realpath = realpath($ftest);
+                $locator  = new PHPTAL_SourceLocator($realpath);
+                return $locator;
+            }
+        }
+        return false;
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Tag.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Tag.php
new file mode 100644 (file)
index 0000000..253c739
--- /dev/null
@@ -0,0 +1,296 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+/**
+ * Represents an xhtml entity.
+ *
+ * To obtain a fine granularity of code generation the Tag code generation 
+ * process is divided into logical sub sequences.
+ * 
+ * surround head                // call surround attributes
+ *    replace                   // call replace and skip head -> foo sequence
+ *    || head                   // echo tag start (see disableHeadFoot())
+ *            content           // call content replace and skip cdata seq
+ *            || cdata && child // echo tag content and generate children code
+ *       foot                   // echo tag end   (see disableHeadFoot())
+ * surround foot                // call surround attributes
+ *  
+ *
+ * Some attributes like 'omit' requires to disable the head / foot sequences 
+ * whithout touching content sequences, the disableHeadFoot() method must be
+ * used in that aim.
+ * 
+ * @version 0.1
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class PHPTAL_Tag 
+{
+    /**
+     * @var int $line The template line which produced this tag.
+     */
+    var $line = 0;
+    
+    // tree properties
+    
+    var $_name = "#cdata";
+    var $_attrs = array();
+    var $_children = array();
+    var $_content = "";
+    var $_parent = null;
+
+    // template system properties
+    
+    var $_parser;
+    var $_replace_attributes = array();
+    var $_content_attributes = array();
+    var $_surround_attributes = array();
+    var $_head_foot_disabled = false;
+
+
+    /**
+     * Tag constructor.
+     *
+     * @param string $name
+     *        The tag name.
+     *
+     * @param hashtable $attrs
+     *        Tag xhtml attributes.
+     */
+    function PHPTAL_Tag(&$parser, $name, $attrs)
+    {
+        $this->_parser =& $parser;
+        $this->_name   = $name;
+        $this->_attrs  = $attrs;
+    }
+
+    function appendTemplateAttribute(&$hdlr)
+    {
+        switch ($hdlr->_phptal_type)
+        {
+            case _PHPTAL_REPLACE:
+                $this->_replace_attributes[] =& $hdlr;
+                break;
+            case _PHPTAL_CONTENT:
+                $this->_content_attributes[] =& $hdlr;
+                break;
+            case _PHPTAL_SURROUND:
+                $this->_surround_attributes[] =& $hdlr;
+                break;
+            default:
+                return PEAR::raiseError(
+                "PHPTAL internal error : bad attribute type : "
+                . get_class($hdlr));
+        }
+    }
+
+    function name()
+    {
+        return $this->_name;
+    }
+
+    function isData()
+    {
+        return $this->_name == "#cdata";
+    }
+
+    function attributes()
+    {
+        return $this->_attrs;
+    }
+
+    function setParent(&$node)
+    {
+        $this->_parent =& $node;
+    }
+
+    function &getParent()
+    {
+        return $this->_parent;
+    }
+    
+    function addChild(&$node)
+    {
+        $node->setParent($this);
+        $this->_children[] = &$node;
+    }
+    
+    function setContent($str)
+    {
+        $this->_content = $str;
+    }
+
+    function hasContent()
+    {
+        return (count($this->_content_attributes) == 0 
+            ||  count($this->_children) == 0 
+            ||  strlen($this->_content) == 0);
+    }
+
+    function toString($tab="")
+    {
+        $buf = new StringBuffer();
+        $buf->appendln($tab, '+ node ', $this->name());
+        for ($i=0; $i < count($this->_children); $i++) {
+            $child =& $this->_children[$i];
+            $buf->append($child->toString($tab . "  "));
+            unset($child);
+        }
+        return $buf->toString();
+    }    
+
+    function generateCode(&$g)
+    {
+        // if text node, just print the content and return
+        if ($this->_name == "#cdata") {
+            $g->doPrintString($this->_content);
+            return;
+        }
+
+        if ($this->_name == "#root") {
+            return $this->generateContent($g);
+        }
+        
+        // if replace attributes exists, they will handle
+        // this tag rendering
+        if (count($this->_replace_attributes) > 0) {
+            $err = $this->surroundHead($g);
+            if (PEAR::isError($err)) { return $err; }
+            
+            for ($i=0; $i<count($this->_replace_attributes); $i++) {
+                $h =& $this->_replace_attributes[$i];
+                $err = $h->activate($g, $this);
+                if (PEAR::isError($err)) { return $err; }
+                unset($h);
+            }
+            return $this->surroundFoot($g);
+        }
+
+        $err = $this->surroundHead($g);
+        if (PEAR::isError($err)) { return $err; }
+
+        $this->printHead($g);
+        
+        $err = $this->generateContent($g);
+        if (PEAR::isError($err)) { return $err; }
+  
+        $this->printFoot($g);
+
+        $err = $this->surroundFoot($g); 
+        if (PEAR::isError($err)) { return $err; }
+    }
+
+    function printHead(&$g)
+    {
+        if ($this->headFootDisabled()) return;
+
+        $g->doPrintString('<', $this->_name);
+
+        $this->printAttributes($g);
+        
+        if ($this->hasContent() && !$this->_isXHTMLEmptyElement()) {
+            $g->doPrintString('>');
+        } else {
+            $g->doPrintString('/>');
+        }
+    }
+
+    function printFoot(&$g)
+    { 
+        if ($this->headFootDisabled()) return;
+        
+        if ($this->hasContent() && !$this->_isXHTMLEmptyElement()) {
+            $g->doPrintString('</', $this->_name, '>');
+        }       
+    }
+    
+    function printAttributes(&$g)
+    {
+        global $_phptal_xhtml_boolean_attributes;
+        foreach ($this->_attrs as $key=>$value) {
+            if ($this->_parser->_outputMode() == PHPTAL_XHTML 
+                && in_array(strtolower($key), $_phptal_xhtml_boolean_attributes)) {
+                $g->doPrintString(" $key");
+            } else {
+                $g->doPrintString(" $key=\"$value\"");
+            }
+        }
+    }
+
+    function surroundHead(&$g)
+    {
+        // if some surround attributes, we activate
+        // their header method
+        for ($i=0; $i<count($this->_surround_attributes); $i++) {
+            $h =& $this->_surround_attributes[$i];
+            $err = $h->start($g, $this);
+            if (PEAR::isError($err)) { return $err; }
+            unset($h);
+        }
+    }
+
+    function surroundFoot(&$g)
+    {
+        // close surrounders in reverse order of course
+        for ($i = (count($this->_surround_attributes)-1); $i >= 0; $i--) {
+            $err = $this->_surround_attributes[$i]->end($g, $this);
+            if (PEAR::isError($err)) { return $err; }
+        }
+    }
+    
+    function generateContent(&$g)
+    {
+        if (count($this->_content_attributes) > 0) {
+            // time for content attributes, 
+            foreach ($this->_content_attributes as $h) {
+                $err = $h->activate($g, $this);
+                if (PEAR::isError($err)) { return $err; }
+            }
+        } else {
+            // if none, we just ask children to generate their code
+            foreach ($this->_children as $child) {
+                $err = $child->generateCode($g);
+                if (PEAR::isError($err)) { return $err; }
+            }
+        }
+    }
+
+    function disableHeadFoot()
+    {
+        $this->_head_foot_disabled = true;
+    }
+
+    function headFootDisabled()
+    {
+        return $this->_head_foot_disabled;print_r($this->_root);
+    }
+
+    function _isXHTMLEmptyElement()
+    {
+        global $_phptal_xhtml_empty_tags;
+        if ($this->_parser->_outputMode() != PHPTAL_XHTML) {
+            return false;
+        }
+        return in_array(strtoupper($this->name()), $_phptal_xhtml_empty_tags);
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Template.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Template.php
new file mode 100644 (file)
index 0000000..cef3465
--- /dev/null
@@ -0,0 +1,562 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+
+class PHPTAL_Template
+{
+    var $_ctx;
+    var $_code;
+    var $_codeFile;
+    var $_funcName;
+    var $_sourceFile;
+    var $_error         = false;
+    var $_repository    = false;
+    var $_cacheDir     = false;
+    var $_parent        = false;
+    var $_parentPath   = false;
+    var $_prepared      = false;
+    var $_cacheManager;
+
+    var $_outputMode    = PHPTAL_XHTML;
+
+    var $_inputFilters;
+    var $_outputFilters;
+    var $_resolvers;
+    var $_locator;
+
+    var $_headers = false;
+
+    var $_translator;
+
+    var $_encoding = 'UTF-8';
+    
+    /**
+     * Template object constructor.
+     *
+     * @param string $file -- The source file name
+     * @param string $repository optional -- Your templates root.
+     * @param string $cache_dir optional -- Intermediate php code repository.
+     */
+    function PHPTAL_Template($file, $repository=false, $cache_dir=false)
+    {
+        $this->_sourceFile   = $file;
+        $this->_repository = $repository;
+
+        // deduce intermediate php code cache directory
+        if (!$cache_dir) {
+            if (defined('PHPTAL_CACHE_DIR')) {
+                $cache_dir = PHPTAL_CACHE_DIR; 
+            } else {
+                $cache_dir = PHPTAL_DEFAULT_CACHE_DIR;
+            }
+        }
+        $this->_cacheDir  = $cache_dir;
+
+        // instantiate a new context for this template
+        // !!! this context may be overwritten by a parent context
+        $this->_ctx        = new PHPTAL_Context();
+        
+        // create resolver vector and the default filesystem resolver
+        $this->_resolvers  = new OArray();
+        $this->_resolvers->push(new PHPTAL_SourceResolver());
+        
+        // vector for source filters
+        $this->_inputFilters = new OArray();
+        $this->_outputFilters = new OArray();
+        
+        // if no cache manager set, we instantiate default dummy one
+        if (!isset($this->_cacheManager)) {
+            $this->_cacheManager = new PHPTAL_Cache();
+        }
+    }
+
+    /**
+     * Set template ouput type.
+     *
+     * Default output is XHTML, so you'll have to call this method only for
+     * specific xml documents  with PHPTAL_XML parameter.
+     * 
+     * @param int $mode -- output mode (PHPTAL_XML) as default system use XHTML
+     */
+    function setOutputMode($mode)
+    {
+        $this->_outputMode = $mode;
+    }
+    
+    /**
+     * Replace template context with specified hashtable.
+     *
+     * @param hash hashtable -- Associative array.
+     */
+    function setAll($hash)
+    {
+        $this->_ctx = new PHPTAL_Context($hash);
+    }
+    
+    /**
+     * Set a template context value.
+     * 
+     * @param string $key -- The context key
+     * @param mixed  $value -- The context value
+     */
+    function set($name, $value)
+    {
+        $this->_ctx->set($name, $value);
+    }
+
+    /**
+     * Set a template context value by reference.
+     * 
+     * @param string $name -- The template context key
+     * @param mixed $value -- The template context value
+     */
+    function setRef($name, &$value)
+    {
+        $this->_ctx->setRef($name, $value);
+    }
+
+    /**
+     * Retrieve template context object.
+     *
+     * @return PHPTAL_Context
+     */
+    function &getContext()
+    {
+        return $this->_ctx;
+    }
+
+    /**
+     * Set the template context object.
+     *
+     * @param PHPTAL_Context $ctx -- The context object
+     */
+    function setContext(&$ctx)
+    {
+        $this->_ctx =& $ctx;
+    }
+
+    /**
+     * Set the cache manager to use for Template an Macro calls.
+     *
+     * @param PHPTAL_Cache $mngr -- Cache object that will be used to cache
+     *                              template and macros results.
+     */
+    function setCacheManager(&$mngr)
+    {
+        $this->_cacheManager =& $mngr;
+    }
+
+    /**
+     * Retrieve the cache manager used in this template.
+     *
+     * @return PHPTAL_Cache
+     */
+    function &getCacheManager()
+    {
+        return $this->_cacheManager;
+    }
+
+    /**
+     * Set the I18N implementation to use in this template.
+     *
+     * @param PHPTAL_I18N $tr -- I18N implementation
+     */
+    function setTranslator(&$tr)
+    {
+        $this->_translator =& $tr;
+    }
+    
+    /**
+     * The translator used by this template.
+     *
+     * @return PHPTAL_I18N
+     */
+    function &getTranslator()
+    {
+        return $this->_translator;
+    }
+    
+    /**
+     * Test if the template file exists.
+     * @deprecated use isValid() instead
+     * @return boolean
+     */
+    function fileExists()
+    {
+        return $this->isValid();
+    }
+
+    /**
+     * Test if the template resource exists.
+     * 
+     * @return boolean
+     */    
+    function isValid()
+    {
+        if (isset($this->_locator)) {
+            return true;
+        }
+        
+        // use template resolvers to locate template source data
+        // in most cases, there will be only one resolver in the
+        // resolvers list (the default one) which look on the file 
+        // system.
+
+        $i = $this->_resolvers->getNewIterator();
+        while ($i->isValid()) {
+            $resolver =& $i->value();
+            $locator  =& $resolver->resolve($this->_sourceFile, 
+                                            $this->_repository, 
+                                            $this->_parentPath);
+            if ($locator && !PEAR::isError($locator)) {
+                $this->_locator =& $locator;
+                $this->_real_path = $this->_locator->realPath();
+                return true;
+            }
+            $i->next();
+        }
+        return false;
+    }
+
+    /**
+     * Add a source resolver to the template.
+     *
+     * @param PHPTAL_SourceResolver $resolver
+     *        The source resolver.
+     */
+    function addSourceResolver(&$resolver)
+    {
+        $this->_resolvers->pushRef($resolver);
+    }
+
+    /**
+     * Add filter to this template input filters list.
+     *
+     * @param PHPTAL_Filter $filter 
+     *        A filter which will be invoked on template source.
+     */
+    function addInputFilter(&$filter)
+    {
+        $this->_inputFilters->pushRef($filter);
+    }
+
+    /**
+     * Add an output filter to this template output filters list.
+     *
+     * @param PHPTAL_Filter $filter
+     *        A filter which will be invoked on template output.
+     */
+    function addOutputFilter(&$filter)
+    {
+        $this->_outputFilters->pushRef($filter);
+    }
+    
+    /**
+     * Retrieve the source template real path.
+     *
+     * This method store its result internally if no $file attribute is
+     * specified (work on template internals).
+     *
+     * If a file name is specified, this method will try to locate it
+     * exploring current path (PWD), the current template location, 
+     * the repository and parent template location.
+     * 
+     * @param string $file optional 
+     *        some file name to locate.
+     *        
+     * @throws FileNotFound 
+     * @return string
+     */
+    function realpath($file=false)
+    {
+        // real template path
+        if (!$file) {
+            if ($this->isValid()) {
+                return $this->_real_path;
+            } else {
+                $ex = new FileNotFound($this->_sourceFile . ' not found');
+                return PEAR::raiseError($ex);
+            }
+        }
+        
+        // 
+        // path to some file relative to this template
+        // 
+        $i = $this->_resolvers->getNewIterator();
+        while ($i->isValid()) {
+            $resolver =& $i->value();
+            $locator  =& $resolver->resolve($file, 
+                                            $this->_repository, 
+                                            $this->_real_path);
+            if ($locator) {
+                return $locator->realPath();
+            }
+            $i->next();
+        }
+
+        $ex = new FileNotFound($file . ' not found');
+        return PEAR::raiseError($ex);
+    }
+
+    /**
+     * Set the template result encoding.
+     *
+     * Changing this encoding will change htmlentities behaviour.
+     *
+     * Example:
+     *
+     *          $tpl->setEncoding('ISO-8859-1");
+     *
+     * See http://fr2.php.net/manual/en/function.htmlentities.php for a list of
+     * supported encodings.
+     * 
+     * @param $enc string Template encoding
+     */
+    function setEncoding($enc)
+    {
+        $this->_encoding = $enc;
+    }
+
+    /**
+     * Retrieve the template result encoding.
+     *
+     * @return string
+     */
+    function getEncoding()
+    {
+        return $this->_encoding;
+    }
+
+    // ----------------------------------------------------------------------
+    // private / protected methods
+    // ----------------------------------------------------------------------
+    
+    /**
+     * Set the called template. (internal)
+     *
+     * @access package
+     */
+    function setParent(&$tpl)
+    {
+        $this->_parent =& $tpl;
+        $this->_resolvers = $tpl->_resolvers;
+        $this->_inputFilters = $tpl->_inputFilters;
+        $this->_parentPath = $tpl->realPath();
+        $this->_cacheManager =& $tpl->getCacheManager();
+        $this->_translator =& $tpl->_translator;
+        $this->setOutputMode($tpl->_outputMode);
+    }
+
+    /**
+     * Prepare template execution.
+     *
+     * @access private
+     */
+    function _prepare()
+    {
+        if ($this->_prepared) return;
+        $this->_sourceFile = $this->realpath();
+        
+        // ensure that no error remain
+        if (PEAR::isError($this->_sourceFile)) {
+            return $this->_sourceFile; 
+        }
+        $this->_funcName   = "tpl_" . PHPTAL_MARK . md5($this->_sourceFile);
+        $this->_codeFile   = $this->_cacheDir . $this->_funcName . '.php';
+        $this->_prepared    = true;
+    }
+    
+    /**
+     * Generate php code from template source
+     * 
+     * @access private
+     * @throws PHPTALParseException
+     */
+    function _generateCode()
+    {
+        require_once _phptal_os_path_join(dirname(__FILE__), 'Parser.php');
+
+        $parser = new PHPTAL_Parser();
+        $parser->_outputMode($this->_outputMode);
+        $data   = $this->_locator->data();
+
+        // activate prefilters on data
+        $i = $this->_inputFilters->getNewIterator();
+        while ($i->isValid()){
+            $filter =& $i->value();
+            $data = $filter->filter($data);
+            $i->next();
+        }
+
+        // parse source
+        $result = $parser->parse($this->_real_path, $data);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+
+        // generate and store intermediate php code
+        $this->_code = $parser->generateCode($this->_funcName);
+        if (PEAR::isError($this->_code)) {
+            return $this->_code;
+        }
+    }
+
+    /**
+     * Load cached php code
+     * 
+     * @access private
+     */
+    function _loadCachedCode()
+    {
+        include_once($this->_codeFile);
+        $this->_code = "#loaded";    
+    }
+
+    /**
+     * Cache generated php code.
+     * 
+     * @access private
+     */
+    function _cacheCode()
+    {
+        $fp = @fopen($this->_codeFile, "w");
+        if (!$fp) {
+            return PEAR::raiseError($php_errormsg);
+        }
+        fwrite($fp, $this->_code);
+        fclose($fp);
+    }
+    
+    /**
+     * Load or generate php code.
+     * 
+     * @access private
+     */
+    function _load()
+    {
+        if (isset($this->_code) && !PEAR::isError($this->_code)) { 
+            return; 
+        }
+        
+        if (!defined('PHPTAL_NO_CACHE') 
+            && file_exists($this->_codeFile) 
+            && filemtime($this->_codeFile) >= $this->_locator->lastModified()) {
+            return $this->_loadCachedCode();
+        }
+        
+        $err = $this->_generateCode();
+        if (PEAR::isError($err)) {
+            return $err;
+        }
+        
+        $err = $this->_cacheCode();
+        if (PEAR::isError($err)) {
+            return $err;
+        }
+
+        $err = $this->_loadCachedCode();
+        if (PEAR::isError($err)) { 
+            return $err;
+        }
+    }
+    
+    /**
+     * Execute template with prepared context.
+     *
+     * This method execute the template file and returns the produced string.
+     * 
+     * @return string
+     * @throws 
+     */
+    function execute()
+    {
+        $err = $this->_prepare();
+        if (PEAR::isError($err)) {
+            $this->_ctx->_errorRaised = true;
+            return $err;
+        }
+        return $this->_cacheManager->template($this, 
+                                               $this->_sourceFile, 
+                                               $this->_ctx);
+    }
+
+    /**
+     * Really load/parse/execute the template and process output filters.
+     *
+     * This method is called by cache manager to retrieve the real template
+     * execution value.
+     *
+     * IMPORTANT : The result is post-filtered here !
+     * 
+     * @return string
+     * @access private
+     */
+    function _process()
+    {
+        $err = $this->_load();
+        if (PEAR::isError($err)) { 
+            $this->_ctx->_errorRaised = true;
+            return $err;
+        }
+
+        $this->_ctx->_errorRaised = false;
+        $func = $this->_funcName;
+        if (!function_exists($func)) {
+            $err = "Template function '$func' not found (template source : $this->_sourceFile";
+            return PEAR::raiseError($err);
+        }
+        
+        // ensure translator exists
+        if (!isset($this->_translator)) {
+            $this->_translator = new PHPTAL_I18N();
+        }
+        
+        $res = $func($this);
+        if ($this->_headers) {
+            $res = $this->_headers . $res;
+        }
+        
+        // activate post filters
+        $i = $this->_outputFilters->getNewIterator();
+        while ($i->isValid()) {
+            $filter =& $i->value();
+            $res = $filter->filter($this, $res, PHPTAL_POST_FILTER);
+            $i->next();
+        }
+        return $res;
+    }
+
+    function _translate($key)
+    {
+        return $this->_translator->translate($key);
+    }
+
+    function _setTranslateVar($name, $value)
+    {
+        if (is_object($value)) {
+            $value = $value->toString();
+        }
+        $this->_translator->set($name, $value);
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/XML_Parser.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/XML_Parser.php
new file mode 100644 (file)
index 0000000..ee636b5
--- /dev/null
@@ -0,0 +1,254 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+require_once "Types/Errors.php";
+
+/**
+ * PHPTAL internal xml parser.
+ *
+ * Note: 
+ *
+ * I didn't use the XML/Parser package because of reference problems due to
+ * call_user_func and call_user_method.
+ *
+ * This problem should vanished with automatic object referencing in php4.4 
+ * (ZendEngine2) remind me to remove this parser at this time.
+ * 
+ *
+ * This class uses "xml_*" php functions to parse xml data. 
+ *
+ * To create a new xml parser, extends this class and implements following
+ * methods.
+ *
+ * - onElementStart($tag, $attributes) 
+ * - onElementClose($tag)
+ * - onElementData($data)
+ * - onSpecific($data)
+ *
+ * Here's an exemple of xml parser implementation.
+ *  
+ * <?php
+ * require_once "PHPTAL/XML_Parser.php";
+ *
+ * class MyParser extends PHPTAL_XML_Parser
+ * {
+ *     function onElementStart($tag, $attributes)
+ *     {
+ *         echo "new tag $tag with attributes :", endl;
+ *         print_r($attributes);
+ *     }
+ *     
+ *     function onElementClose($tag)
+ *     {
+ *         echo "tag ",$tag," is closed", endl;
+ *     }
+ *
+ *     function onElementData($data)
+ *     {
+ *         echo "some plain text : ", $data, endl;
+ *     }
+ *
+ *     function onSpecific($data)
+ *     {
+ *         echo "non xml data maybe <?xml...?> :", $data, endl;
+ *     }
+ * };
+ *
+ * // MyParser usage :
+ * $p = new MyParser();
+ * $p->parse( $myString );
+ * 
+ * ?>
+ * 
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class PHPTAL_XML_Parser 
+{
+    var $_file = '#string';
+    var $_tags = array();
+    var $_parser;
+    var $_error;
+    var $_xmlErrors = array(
+        XML_ERROR_NONE                      => "XML_ERROR_NONE",
+        XML_ERROR_NO_MEMORY                 => "XML_ERROR_NO_MEMORY",
+        XML_ERROR_SYNTAX                    => "XML_ERROR_SYNTAX",
+        XML_ERROR_NO_ELEMENTS               => "XML_ERROR_NO_ELEMENTS",
+        XML_ERROR_INVALID_TOKEN             => "XML_ERROR_INVALID_TOKEN",
+        XML_ERROR_UNCLOSED_TOKEN            => "XML_ERROR_UNCLOSED_TOKEN",
+        XML_ERROR_PARTIAL_CHAR              => "XML_ERROR_PARTIAL_CHAR",
+        XML_ERROR_TAG_MISMATCH              => "XML_ERROR_TAG_MISMATCH",
+        XML_ERROR_DUPLICATE_ATTRIBUTE       => "XML_ERROR_DUPLICATE_ATTRIBUTE",
+        XML_ERROR_JUNK_AFTER_DOC_ELEMENT    => "XML_ERROR_JUNK_AFTER_DOC_ELEMENT",
+        XML_ERROR_PARAM_ENTITY_REF          => "XML_ERROR_PARAM_ENTITY_REF",
+        XML_ERROR_UNDEFINED_ENTITY          => "XML_ERROR_UNDEFINED_ENTITY",
+        XML_ERROR_RECURSIVE_ENTITY_REF      => "XML_ERROR_RECURSIVE_ENTITY_REF",
+        XML_ERROR_ASYNC_ENTITY              => "XML_ERROR_ASYNC_ENTITY",
+        XML_ERROR_BAD_CHAR_REF              => "XML_ERROR_BAD_CHAR_REF",
+        XML_ERROR_BINARY_ENTITY_REF         => "XML_ERROR_BINARY_ENTITY_REF",
+        XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF => "XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF",
+        XML_ERROR_MISPLACED_XML_PI          => "XML_ERROR_MISPLACED_XML_PI",
+        XML_ERROR_UNKNOWN_ENCODING          => "XML_ERROR_UNKNOWN_ENCODING",
+        XML_ERROR_INCORRECT_ENCODING        => "XML_ERROR_INCORRECT_ENCODING",
+        XML_ERROR_UNCLOSED_CDATA_SECTION    => "XML_ERROR_UNCLOSED_CDATA_SECTION",
+        XML_ERROR_EXTERNAL_ENTITY_HANDLING  => "XML_ERROR_EXTERNAL_ENTITY_HANDLING",
+        );
+        
+    /**
+     * XML parser constructor.
+     */
+    function PHPTAL_XML_Parser()
+    {
+        $this->__construct();
+    }
+
+    /**
+     * XML parser php4.4 constructor.
+     */
+    function __construct()
+    {
+        $this->_parser = xml_parser_create();
+        xml_set_object($this->_parser, $this);
+        xml_set_element_handler($this->_parser, "_onElementStart", "_onElementClose");
+        xml_set_character_data_handler($this->_parser, "_onElementData");
+        xml_set_default_handler($this->_parser, "_onSpecific");
+        xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, 0);
+    }
+
+    /**
+     * Parse specified data and call parser implementation of callback methods.
+     *
+     * @param data string Xml data to parse.
+     */
+    function _parse($data, $eof=true)
+    {
+        $data = str_replace('&','&amp;', $data);
+        if (!xml_parse($this->_parser, $data)) {
+            // PHPTAL errors first
+            if (PEAR::isError($this->_error)) {
+                return $this->_error;
+            }
+            // then look for parser errors
+            $err = xml_get_error_code($this->_parser);
+            return PEAR::raiseError($this->_xmlErrors[$err]
+                                    .' in '.$this->_file
+                                    .' around line '.$this->getLineNumber());
+        }
+        if (PEAR::isError($this->_error)) {
+            return $this->_error;
+        }
+        return true;
+    }
+    
+    function parseString($data)
+    {
+        return $this->_parse($data, true);
+    }
+    
+    function parseFile($path)
+    {
+        $this->_file = $path;
+        $fp = @fopen($path, "r");
+        if (!$fp) {
+            return PEAR::raiseError($php_errormsg);
+        }
+        while ($data = fread($fp, 1024)) {
+            $err = $this->_parse($data, feof($fp));
+            if (PEAR::isError($err)) {
+                fclose($fp);
+                return $err;
+            }
+        }
+        fclose($fp);
+    }
+
+    function _onElementStart($parser, $tag, $attributes)
+    { 
+        if (PEAR::isError($this->_error)) return;
+        $this->_error = $this->onElementStart($tag, $attributes);
+    }
+
+    function _onElementClose($parser, $tag)
+    {
+        if (PEAR::isError($this->_error)) return;
+        $this->_error = $this->onElementClose($tag);
+    }
+
+    function _onElementData($parser, $data)
+    {
+        if (PEAR::isError($this->_error)) return;
+        $this->_error = $this->onElementData($data);
+    }
+
+    function _onSpecific($parser, $data)
+    {
+        if (PEAR::isError($this->_error)) return;
+        $this->_error = $this->onSpecific($data);
+    }
+
+    /**
+     * Return current parser line number.
+     *
+     * @return int
+     */
+    function getLineNumber()
+    {
+        return xml_get_current_line_number($this->_parser);
+    }
+
+    // 
+    // ABSTRACT METHODS
+    // 
+
+    /**
+     * Abstract callback called when a new xml tag is opened.
+     *
+     * @param string tag Tag name
+     * @param hashtable attributes Associative array of attributes
+     */
+    function onElementStart($tag, $attributes){}
+
+    /**
+     * Abstract callback called when a tag is closed.
+     *
+     * @param string tag Tag name
+     */
+    function onElementClose($tag){}
+
+    /**
+     * Abstract callback called when some #cdata is found.
+     *
+     * @param string data Content
+     */
+    function onElementData($data){}
+
+    /**
+     * Abstract callback called when non tags entities appear in the document.
+     *
+     * This method is called by <?xml ...?> <% %> and other specific things like
+     * <?php ?>.
+     *
+     * @param string data strange data content.
+     */
+    function onSpecific($data){}
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/Types.php b/PHPTAL-NP-0.7.0/libs/Types.php
new file mode 100644 (file)
index 0000000..a39bcf0
--- /dev/null
@@ -0,0 +1,100 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+/**
+ * Static class used in common types internals.
+ *
+ * @static
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class Types
+{
+    /**
+     * Generate a string representation of specified variable.
+     *
+     * @param mixed $var -- variable to represent in a string form.
+     * @static
+     */
+    function toString(&$var)
+    {
+        if (is_object($var)) {
+            return Types::_objToString($var);
+        } elseif (is_array($var)) {
+            if (array_key_exists(0, $var) || count($var) == 0) {
+                return Types::_arrayToString($var);
+            } else {
+                return Types::_hashToString($var);
+            }
+        } elseif (is_resource($var)) {
+            return '#'.gettype($var).'#';
+        }
+        return $var;
+    }
+
+    /**
+     * Generate a string representation of an object calling its toString
+     * method of using its class name.
+     * 
+     * @access protected
+     * @static
+     */
+    function _objToString(&$var)
+    {
+        if (method_exists($var, "toString")) {
+            return $var->toString();
+        } else {
+            return '<' . get_class($var) . ' instance>';
+        }        
+    }
+
+    /**
+     * Generate a string representation of a php array.
+     * 
+     * @access protected
+     * @static
+     */
+    function _arrayToString(&$var)
+    {
+        $values = array();
+        foreach ($var as $val) {
+            $values[] = Types::toString($val);
+        }
+        return '[' . join(', ', $values) . ']';        
+    }
+
+    /**
+     * Generate a string representation of an associative array.
+     *
+     * @access protected
+     * @static 
+     */
+    function _hashToString(&$var)
+    {
+        $values = array();
+        foreach ($var as $key=>$val) {
+            $values[] = '\''. $key . '\': ' . Types::toString($val);
+        }
+        return '{' . join(', ', $values) . '}';        
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/Types/Code.php b/PHPTAL-NP-0.7.0/libs/Types/Code.php
new file mode 100644 (file)
index 0000000..a122229
--- /dev/null
@@ -0,0 +1,219 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+// $id$
+
+require_once "Types/OString.php";
+require_once "Types/OHash.php";
+
+/**
+ * Common php string that extract parameters from an associative array.
+ *
+ * This string is appended to the begin of the produced php function. It
+ * takes function context argument and extract it in named variables.
+ * 
+ * @access private
+ */
+define('_TYPES_CODE_EXTRACT_CODE_CONTEXT_',
+'// BEGIN EXTRACT __context__ 
+if (is_array($__context__)) { extract($__context__); }
+if (is_object($__context__)) { extract($__context__->toHash()); }
+// END EXTRACT __context__
+');
+
+/**
+ * Code class handle and evaluate php code.
+ *
+ * The aim of this class is to dynamically generate executable php code from
+ * php string.
+ *
+ * This kind of object can be safely serialized as the code it represents is
+ * stored in the _code member variable.
+ *
+ * When setting code to this object, a new anonymous function is created
+ * waiting to be invoqued using the execute() method.
+ *
+ * As we can't know how many parameters this function should take, a 'context'
+ * hashtable is used as only parameter. This hash  may contains any number
+ * of arguments with var name compliant keys.
+ *
+ * Code object automatically append 'extract' code string to produced code.
+ *
+ * It's up to the code to assert parameters using 'isset()' php function.
+ *
+ *      <?php
+ *      require_once "Types/Code.php";
+ * 
+ *      $o_code = Code()
+ *      $o_code->setCode('return $foo . $bar . $baz;');
+ *      $res = $o_code->execute(
+ *          'foo', 'foo value ',
+ *          'baz', 'bar value ',
+ *          'baz', 'baz value'
+ *      );
+ *  
+ *      // will print 'foo value bar value baz value'
+ *      echo $res, end;
+ *      ?>
+ *  
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class Code 
+{
+    var $_code;
+    var $_function;
+    var $_compiled = false;
+
+    /**
+     * Construct a new code object.
+     *
+     * @param mixed $code (optional) 
+     *        php code string or object implementing toString method.
+     */
+    function Code($code=false)
+    {
+        $this->__construct($code);
+    }
+
+    function __construct($code=false)
+    {
+        if (!$code) { 
+            return $this; 
+        }
+        if (is_object($code) && get_class($code) == 'code') {
+            $this->_code = $code->getCode();
+        } else {
+            $this->setCode(Types::toString($code));
+        }
+    }
+    
+    /**
+     * Execute code with specific context.
+     *
+     * @param  mixed ...
+     *         The function execution context. This may be an associative
+     *         array, an OHash object, a list of key/value pairs that will 
+     *         be transformed into an associative array
+     *         
+     * @return mixed The execution result.
+     */
+    function &execute()
+    {
+        if (!$this->_compiled) {
+            $err =& $this->compile();
+            if (PEAR::isError($err)) { 
+                return $err;
+            }
+        }
+        $argv = func_get_args();
+        $argc = func_num_args();
+        switch ($argc) {
+            case 1:
+                $context = $argv[0];
+                break;
+            default:
+                $context = OHash::ArrayToHash($argv);
+                break;
+        }
+        $func = $this->_function;
+        return $func($context);
+    }
+
+    /**
+     * Compile php code.
+     *
+     * This function may produce parse errors.
+     *
+     * @throws CodeError
+     */
+    function compile() 
+    {
+        ob_start();
+        $this->_function = create_function('$__context__', $this->_code);
+        $ret = ob_get_contents();
+        ob_end_clean();
+
+        if (!$this->_function) {
+            return PEAR::raiseError($ret);
+        }
+        
+        $this->_compiled = true;
+    }
+    
+    /**
+     * Set function code.
+     *
+     * @param  string $str
+     *         The php code string
+     */
+    function setCode($str)
+    {
+        // add extract code to function code
+        $str = _TYPES_CODE_EXTRACT_CODE_CONTEXT_ . $str;
+        $this->_code = $str;
+    }
+    
+    /**
+     * Retrieve code.
+     *
+     * @return string
+     */
+    function getCode()
+    {
+        return $this->_code;
+    }
+
+    /**
+     * On serialization, we store only code, not additional variables.
+     * 
+     * @access private
+     */
+    function __sleep()
+    {
+        return array("_code");
+    }
+
+    /**
+     * Make a string representation of this object.
+     *
+     * @return string
+     */
+    function toString()
+    {
+        if ($this->_compiled) {
+            return '<Code \''.$this->_function.'\'>';
+        } else {
+            return '<Code \'not compiled\'>';
+        }
+    }
+}
+
+/**
+ * Code compilation error.
+ *
+ * This error handles parse errors an other problems that may occurs while
+ * compiling a php code.
+ */
+class CodeError extends PEAR_Error 
+{
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/Types/Errors.php b/PHPTAL-NP-0.7.0/libs/Types/Errors.php
new file mode 100644 (file)
index 0000000..b15ee91
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * Container out of bound error.
+ */
+class OutOfBounds extends PEAR_Error {}
+
+/**
+ * Unable to locate some data somewhere.
+ * 
+ * This kind of exception was introduced by tof template context.
+ */
+class NameError extends PEAR_Error {}
+
+/**
+ * Mismatched data type.
+ */
+class TypeError extends PEAR_Error {}
+
+/**
+ * Unable to locate a file.
+ */
+class FileNotFound extends PEAR_Error {}
+
+/**
+ * Input output error.
+ */
+class IOException extends PEAR_Error {}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/Types/Iterator.php b/PHPTAL-NP-0.7.0/libs/Types/Iterator.php
new file mode 100644 (file)
index 0000000..ef55e28
--- /dev/null
@@ -0,0 +1,153 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+/**
+ * Iterable interface.
+ *
+ * An iterable object can produce Iterator(s) related to itself.
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class Iterable
+{
+    /**
+     * Retrieve iterable size.
+     */
+    function size(){}
+
+    /**
+     * Get an initialized iterator for this object.
+     */
+    function &getNewIterator(){}
+}
+
+
+/**
+ * Iterator interface.
+ *
+ * This class provides common methods for Iterator objects. 
+ *
+ * An iterator is a 'pointer' to a data item extracted from some collection of
+ * resources.
+ *
+ * The aim of Iterator is to allow some abstraction between your program
+ * resources and the way you fetch these resources.
+ *
+ * Thus, you can loop over a file content and later replace this file with a
+ * database backend whithout changing the program logic.
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class Iterator
+{
+    /**
+     * Reset iterator to first item.
+     *
+     * This method should throw an exception for once only iterators.
+     * 
+     * @throws ResetFailed
+     */
+    function reset()
+    {
+        return PEAR::raiseError('\'reset\' method not implemented');
+    }
+    
+    /**
+     * Test if current item is not the end of iterator.
+     *
+     * @return boolean
+     */
+    function isValid()
+    {
+        return PEAR::raiseError('\'isValid\' method not implemented');
+    }
+    
+    /**
+     * Iterate on the next element and returns the next item.
+     * 
+     * @return mixed (by reference)
+     */
+    function &next()
+    {
+        return PEAR::raiseError('\'next\' method not implemented');
+    }
+    
+    // ----------------------------------------------------------------------
+    // getters
+    // ----------------------------------------------------------------------
+    
+    /**
+     * Retrieve the current item index.
+     * 
+     * @return int
+     */
+    function index()
+    {
+        return PEAR::raiseError('\'index\' method not implemented');
+    }
+    
+    /**
+     * Retrieve current item value.
+     * 
+     * @return mixed (by reference)
+     */
+    function &value()
+    {
+        return PEAR::raiseError('\'value\' method not implemented');
+    }
+
+    // ----------------------------------------------------------------------
+    // optional methods
+    // ----------------------------------------------------------------------
+    
+    /**
+     * (optional) Additional index for hashes.
+     * 
+     * @return string
+     */
+    function key()
+    {
+        return $this->index();
+    }
+    
+    /**
+     * (optional) Remove the current value from container.
+     *
+     * Implement this method only when the iterator can do a secured remove
+     * without breaking other iterators works.
+     */
+    function remove()
+    {
+        return PEAR::raiseError('\'remove\' method not implemented');
+    }
+}
+
+/**
+ * Exception thrown by iterators that can be reseted only once.
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class ResetFailed extends PEAR_Error 
+{
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/Types/OArray.php b/PHPTAL-NP-0.7.0/libs/Types/OArray.php
new file mode 100644 (file)
index 0000000..5bb4577
--- /dev/null
@@ -0,0 +1,408 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+require_once "Types.php";
+require_once "Types/Errors.php";
+require_once "Types/Ref.php";
+require_once "Types/Iterator.php";
+
+/** 
+ * Class wrapper for oriented object arrays.
+ *
+ * This class implements a simple interface quite like java to handle array in
+ * a good old oo way.
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class OArray extends Iterable 
+{
+    var $_array;
+    var $_size = 0;
+
+    /**
+     * OArray constructor.
+     *
+     * @param array $array optional 
+     *        The php array this vector will manage.
+     */
+    function OArray($array=array())
+    {
+        $this->__construct($array);
+    }
+    
+    /**
+     * OArray php4.4 compliant constructor.
+     *
+     * @param array $array optional 
+     *        The php array this vector will manage.
+     */
+    function __construct($array=array())
+    {
+        $this->_array = array();
+        for ($i = 0; $i < count($array); $i++) {
+            $this->pushRef($array[$i]);
+        }
+    }
+
+    /**
+     * Retrieve an iterator ready to used.
+     * @return ArrayIterator
+     */
+    function getNewIterator()
+    {
+        return new ArrayIterator($this);
+    }
+
+    /**
+     * Returns the vector number of elements.
+     * @return int
+     */
+    function size()
+    {
+        return count($this->_array);
+    }
+
+    /**
+     * Returns true if this vector is empty, false otherwise.
+     * @return boolean
+     */
+    function isEmpty()
+    {
+        return $this->size() == 0;
+    }
+
+    /**
+     * Retrieve element at specified index.
+     * @return mixed
+     * @throws OutOfBounds
+     */
+    function &get($i)
+    {
+        if ($i > $this->size() || $i < 0) { 
+            $err = new OutOfBounds("OArray index out of bounds ($i)");
+            // return EX::raise($err);
+            return PEAR::raiseError($err);
+        }
+        return $this->_array[$i]->obj;
+    }
+
+    /**
+     * Retrieve index of specified element.
+     *
+     * @return int The element index of false if element not in vector.
+     */
+    function indexOf($element)
+    {
+        for ($i=0; $i < count($this->_array); $i++) {
+            if ($this->_array[$i]->obj === $element) { 
+                return $i; 
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Set the item at specified index.
+     *
+     * @throws OutOfBounds if index is greated that vector limit
+     * @return Old element
+     */
+    function &set($i, $item)
+    {
+        return $this->setRef($i, $item);
+    }
+
+    /**
+     * Set the item at specified index (by reference).
+     *
+     * @throws OutOfBounds if index is greated that vector limit
+     * @return Old element
+     */
+    function &setRef($i, &$item)
+    {
+        if ($i > $this->size() || $i < 0) { 
+            $err = new OutOfBounds("OArray index out of bounds ($i)");
+            // return EX::raise($err);
+            return PEAR::raiseError($err);
+        }
+        $temp = $this->_array[$i];
+        $this->_array[$i] = Ref($item);
+        return $temp->obj;        
+    }
+
+    /**
+     * Test if the vector contains the specified element.
+     *
+     * @param mixed $item The item we look for.
+     */
+    function contains($o)
+    {
+        for ($i = 0; $i < $this->size(); $i++) {
+            if ($this->_array[$i]->obj === $o) return true;
+        }
+        return false;
+    }
+
+    /**
+     * Add an element to the vector.
+     *
+     * @param mixed $o The item to add.
+     */
+    function add($o)
+    {
+        $this->push($o);
+    }
+
+    /**
+     * Remove object from this vector.
+     *
+     * @param  mixed $o Object to remove.
+     * @return boolean true if object removed false if not found
+     */
+    function remove($o)
+    {
+        $i = $this->indexOf($o);
+        if ($i !== false) {
+            $this->removeIndex($i);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Remove specified index from vector.
+     *
+     * @param  int $i Index
+     * @throws OutOfBounds
+     */
+    function removeIndex($i)
+    {
+        if ($i > $this->size() || $i < 0 ) { 
+            $err = new OutOfBounds("OArray index out of bounds ($i)");
+            // return EX::raise($err);
+            return PEAR::raiseError($err);
+        }
+        
+        // $this->_array = array_splice($this->_array, $i, 1);
+        array_splice($this->_array, $i, 1);
+    }
+
+    /**
+     * Clear vector.
+     */
+    function clear()
+    {
+        $this->_array = array();
+    }
+
+    /**
+     * Add an element at the end of the vector (same as add()).
+     *
+     * @param mixed $o Item to append to vector.
+     */
+    function push($o)
+    {
+        array_push($this->_array, Ref($o));
+    }
+
+    /**
+     * Add an element at the end of the vector (same as add()).
+     *
+     * @param mixed $o Item to append to vector.
+     */
+    function pushRef(&$o)
+    {
+        $this->_array[] = Ref($o);
+    }
+
+    /**
+     * Retrieve vector values.
+     *
+     * The returned array contains references to internal data.
+     *
+     * @return array
+     */
+    function &values()
+    {
+        $v = array();
+        for ($i = 0; $i < $this->size(); $i++) {
+            $v[] =& $this->_array[$i]->obj;
+        }
+        return $v;
+    }
+
+    /**
+     * Remove the last element of the vector and returns it.
+     *
+     * @return mixed
+     */
+    function &pop()
+    {
+        $ref = array_pop($this->_array);
+        return $ref->obj;
+    }
+
+    /**
+     * Extract and return first element of OArray.
+     * @return mixed
+     */
+    function &shift()
+    {
+        $ref = array_shift($this->_array);
+        return$ $ref->obj;
+    }
+
+    /**
+     * Retrieve a php array for this vector.
+     *
+     * @return array
+     */
+    function &toArray()
+    {
+        return $this->values();
+    }
+
+    /**
+     * Retrieve a string representation of the array.
+     */
+    function toString()
+    {
+        return Types::_arrayToString($this->values());
+    }
+};
+
+/**
+ * OArray itertor class.
+ *
+ * This kind of iterators are used to walk throug a OArray object.
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class ArrayIterator extends Iterator
+{
+    var $_src;
+    var $_values;
+    var $_value;
+    var $_i;
+
+    /**
+     * Iterator constructor.
+     *
+     * @param mixed $oarray OArray object or php array.
+     */
+    function ArrayIterator(&$oarray)
+    {
+        return $this->__construct($oarray);
+    }
+    
+    /**
+     * PHP 4.4 compliant constructor.
+     *
+     * @param mixed $oarray OArray object or php array.
+     */
+    function __construct(&$oarray)
+    {
+        if (is_array($oarray)) {
+            $this->_src = new OArray($oarray);
+        } else if (is_a($oarray, 'OArray')) {
+            $this->_src = &$oarray;
+        } else {
+            // ignore error, should throw a bad type error or something like
+            // that but pear does not handle errors in constructors yet
+            $err = new TypeError("ArrayIterator requires OArray object or php array.",
+                                 PEAR_ERROR_DIE);
+            // return EX::raise($err);
+            return PEAR::raiseError($err);
+        }
+        $this->reset();
+    }
+
+    /**
+     * Reset iterator to first array position.
+     */
+    function reset()
+    {
+        $this->_i = 0;
+        $this->_end = false;
+        $this->_values = $this->_src->_array;
+        if (count($this->_values) == 0) {
+            $this->_end = true;
+            return;
+        }
+
+        $this->_value = $this->_values[0];
+    }
+
+    /**
+     * Returns next vector item value.
+     *
+     * @return mixed
+     * @throws OutOfBounds if iterator overpass the vector size.
+     */
+    function &next()
+    {
+        if ($this->_end || ++$this->_i >= count($this->_values)) {
+            $this->_end = true;
+            return null;
+        }
+
+        $this->_value = $this->_values[$this->_i];
+        return $this->_value->obj;
+    }
+
+    /**
+     * Test if the iteractor has not reached its end.
+     * @return boolean
+     */
+    function isValid()
+    {
+        return !$this->_end;
+    }
+
+    /**
+     * Retrieve current iterator index.
+     * @return int
+     */
+    function index()
+    {
+        return $this->_i;
+    }
+
+    /**
+     * Retrieve the current iterator value.
+     * @return mixed
+     */
+    function &value()
+    {
+        return $this->_value->obj;
+    }
+    
+    /**
+     * Delete current index.
+     */
+    function remove()
+    {
+        $this->_src->remove($this->_value->obj);
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/Types/ODate.php b/PHPTAL-NP-0.7.0/libs/Types/ODate.php
new file mode 100644 (file)
index 0000000..c63f75d
--- /dev/null
@@ -0,0 +1,447 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+// $id$
+
+/**
+ * Generic date part format.
+ */
+define('TYPES_DATE_FMT_DATE', '%1$04s-%2$02s-%3$02s');
+/**
+ * French date part format.
+ */
+define('TYPES_DATE_FMT_DATE_FR', '%3$02s/%2$02s/%1$04s');
+/**
+ * Hours format.
+ */
+define('TYPES_DATA_FMT_HOUR', '%4$02s:%5$02s:%6$02s');
+
+/**
+ * Simple date manipulation object.
+ *
+ * Note:
+ * -----
+ * 
+ * ODate::toString() can take a sprintf() format string as first parameter. 
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class ODate 
+{
+    var $_year = 0;
+    var $_month = 0;
+    var $_day = 0;
+    var $_hours = 0;
+    var $_minutes = 0;
+    var $_seconds = 0;
+    
+    /**
+     * ODate constructor.
+     *
+     * This constructor is for php v4.4 compliance.
+     *
+     * @param int $y  optional -- year 
+     * @param int $mt optional -- month
+     * @param int $d  optional -- day
+     * @param int $h  optional -- hour
+     * @param int $m  optional -- minutes
+     * @param int $s  optional -- seconds
+     */
+    function __construct($y=0, $mt=0, $d=0, 
+                         $h=0, $m=0, $s=0) 
+    {
+        $this->setYear($y);
+        $this->setMonth($mt);
+        $this->setDay($d);
+        $this->setHours($h);
+        $this->setMinutes($m);
+        $this->setSeconds($s);
+    }
+    
+    /**
+     * ODate constructor.
+     *
+     * @param int $y  optional -- year
+     * @param int $mt optional -- month
+     * @param int $d  optional -- day
+     * @param int $h  optional -- hour
+     * @param int $m  optional -- minutes
+     * @param int $s  optional -- seconds
+     */
+    function ODate($y=0, $mt=0, $d=0, 
+                  $h=0, $m=0, $s=0) 
+    {
+        $this->__construct($y, $mt, $d, $h, $m, $s);
+    }
+
+    /**
+     * Add a date to current date.
+     */
+    function add($date)
+    {
+        $this->inc($date->getYear(),
+                   $date->getMonth(),
+                   $date->getDay(),
+                   $date->getHours(),
+                   $date->getMinutes(),
+                   $date->getSeconds());
+    }
+
+    /**
+     * Add values to this date.
+     * 
+     * @param int $y  optional -- year
+     * @param int $mt optional -- month
+     * @param int $d  optional -- day
+     * @param int $h  optional -- hour
+     * @param int $m  optional -- minutes
+     * @param int $s  optional -- seconds
+     */
+    function inc($y,$mt,$d,$h,$m,$s)
+    {
+        $this->addSeconds($s);
+        $this->addMinutes($m);        
+        $this->addHours($h);
+        $this->addDays($d);        
+        $this->addMonths($mt);
+        $this->addYears($y);
+    }
+
+    /**
+     * Set date part.
+     *
+     * @param int $y  -- year
+     * @param int $mt -- month
+     * @param int $d  -- day
+     */
+    function setDate($y,$m,$d)
+    { 
+        $this->setYear($y);
+        $this->setMonth($m);
+        $this->setDay($d);
+    }
+    
+    /**
+     * Set time part.
+     * 
+     * @param int $h  -- hour
+     * @param int $m  -- minutes
+     * @param int $s  -- seconds
+     */
+    function setTime($y,$m,$d)
+    {
+        $this->setHours($h);
+        $this->setMinutes($m);
+        $this->setSeconds($s);
+    }  
+
+    /**
+     * Add some years to this date.
+     * 
+     * @param int $y  -- year
+     */
+    function addYears($y)
+    {
+        $this->_year += $y; 
+    }
+
+    /**
+     * Add some months to this date.
+     *
+     * @param int $m  -- month
+     */
+    function addMonths($m)
+    {
+        $this->_month += $m;
+        if ($this->_month > 12) {
+            $this->addYears($this->_month / 12);
+            $this->_month = $this->_month % 12;
+        }
+    }
+
+    /**
+     * Add some days to this date.
+     *
+     * @param int $d  -- days
+     */
+    function addDays($d)
+    {
+        $m = 0;
+        $this->_day += $d;
+        $m = $this->numberOfMonthDays();
+        while ($this->_day > $m) {
+            $this->addMonths(1);
+            $this->_day -= $m;
+            $m = $this->numberOfMonthDays();
+        }
+    }
+
+    /**
+     * Add some hours to this date.
+     *
+     * @param int $h  -- hours
+     */
+    function addHours($h)
+    {
+        $this->_hours += $h;
+        if ($this->_hours >= 24) {
+            $this->addDays($this->_hours / 24);
+            $this->_hours = $this->_hours % 24;
+        }
+    }
+
+    /**
+     * Add minutes to this date.
+     *
+     * @param int $m  -- minutes
+     */
+    function addMinutes($m)
+    {
+        $this->_minutes += $m;
+        if ($this->_minutes >= 60) {
+            $this->addHours($this->_minutes / 60);
+            $this->_minutes = $this->_minutes % 60;
+        }
+    }
+
+    /**
+     * Add seconds to this date.
+     *
+     * @param int $s  -- seconds
+     */
+    function addSeconds($s)
+    {
+        $this->_seconds += $s;
+        if ($this->_seconds >= 60) {
+            $this->addMinutes($this->_seconds / 60);
+            $this->_seconds = $this->_seconds % 60;
+        }
+    }
+    
+    /**
+     * Return true if bissextile year.
+     *
+     * @return boolean
+     */
+    function isBissextile()
+    {
+        if ($this->_year % 400 == 0) return true;
+        if ($this->_year % 100 == 0) return false;
+        if ($this->_year % 4 == 0)   return true;
+        return false;
+    }
+
+    /**
+     * Get the number of days in current month
+     *
+     * @return int
+     */
+    function numberOfMonthDays()
+    {
+        if ($this->_month == 2 && $this->isBissextile()) {
+            return 29;
+        }
+        $DOM = array(-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
+        return $DOM[$this->_month];
+    }
+
+    /**
+     * Set now time values to this object.
+     */
+    function setNow()
+    {
+        $d = getdate();
+        $this->setSeconds($d['seconds']);
+        $this->setMinutes($d['minutes']);
+        $this->setHours($d['hours']);
+        $this->setDay($d['mday']);
+        $this->setMonth($d['mon']);
+        $this->setYear($d['year']);
+    }
+    
+    /**
+     * Ensure that date is correct.
+     */
+    function cleanup()
+    {
+        $this->add(0,0,0,0,0,0);
+    }
+    
+    /**
+     * Compare with another date, return < 0 if less, == 0 if equals, > 0 if
+     * greater.
+     *
+     * @param ODate $date -- date to compare with
+     *
+     * @return int (strcmp)
+     */
+    function compare($date)
+    {
+        return strcmp($this->toNumericString(), 
+                      $date->toNumericString());
+    }
+
+    /**
+     * Return a concatenation of date fields (numeric date).
+     *
+     * @return string
+     */
+    function toNumericString()
+    {
+        return (int)"$this->_year$this->_month$this->_day".
+            "$this->_hours$this->_minutes$this->_seconds";
+    }
+
+    /**
+     * Simple date format.
+     *
+     * @param string $format optional
+     *        Format to pass to sprintf (ex:"%04d-%02d-%02d %02d:%02d:%02d")
+     *
+     * @return string
+     */
+    function toString($format="%04d-%02d-%02d %02d:%02d:%02d")
+    {
+        $this->cleanup();
+        return sprintf($format,
+                       $this->_year,
+                       $this->_month,
+                       $this->_day,
+                       $this->_hours,
+                       $this->_minutes,
+                       $this->_seconds);
+    }
+
+    
+    // 
+    // OTHER GETTER SETTERS
+    // 
+
+    /**
+     * Retrieve year.
+     * @return int
+     */
+    function getYear()
+    { 
+        return $this->_year; 
+    }
+    
+    /**
+     * Retrieve month.
+     * @return int
+     */
+    function getMonth()
+    { 
+        return $this->_month; 
+    }
+    
+    /**
+     * Retrieve day.
+     * @return int
+     */
+    function getDay()
+    { 
+        return $this->_day; 
+    }
+    
+    /**
+     * Retrieve hour.
+     * @return int
+     */
+    function getHours()
+    { 
+        return $this->_hours; 
+    }
+    
+    /**
+     * Retrieve minutes.
+     * @return int
+     */
+    function getMinutes()
+    {
+        return $this->_minutes; 
+    }
+    
+    /**
+     * Retrieve seconds.
+     * @return int
+     */
+    function getSeconds()
+    { 
+        return $this->_seconds; 
+    }
+    
+    /**
+     * Set year.
+     * @param int $y -- year
+     */
+    function setYear($y)
+    { 
+        $this->_year = $y; 
+    }
+    
+    /**
+     * Set month.
+     * @param int $m -- month
+     */
+    function setMonth($m)
+    { 
+        $this->_month = $m; 
+    }
+    
+    /**
+     * Set day.
+     * @param int $d -- day
+     */
+    function setDay($d)
+    { 
+        $this->_day = $d; 
+    }
+    
+    /**
+     * Set hours.
+     * @param int $h -- hours
+     */
+    function setHours($h)
+    { 
+        $this->_hours = $h; 
+    }
+    
+    /**
+     * Set minutes.
+     * @param int $m -- minutes
+     */
+    function setMinutes($m)
+    { 
+        $this->_minutes = $m; 
+    }
+    
+    /**
+     * Set seconds.
+     * @param int $s -- seconds
+     */
+    function setSeconds($s)
+    { 
+        $this->_seconds = $s; 
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/Types/OHash.php b/PHPTAL-NP-0.7.0/libs/Types/OHash.php
new file mode 100644 (file)
index 0000000..53b0a75
--- /dev/null
@@ -0,0 +1,451 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+require_once "Types.php";
+require_once "Types/Errors.php";
+require_once "Types/Ref.php";
+
+/**
+ * Wrapper for oriented object associative arrays.
+ *
+ * This class implements a simple interface quite like java to handle
+ * associatives arrays (Hashtables).
+ *
+ * Note:
+ *
+ * Some problems may occurs with object references until php4.4 to avoid
+ * unwanted object copy, use setRef() method with objects or pass Ref objects
+ * to set().
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class OHash 
+{
+    var $_hash;
+
+    /**
+     * OHash constructor.
+     *
+     * php4.4 compliant constructor
+     * 
+     * @param array $array optional -- An associative php array
+     */
+    function __construct($array=array())
+    {
+        $this->_hash = array();
+        $keys = array_keys($array);
+        foreach ($keys as $key) {
+            $this->_hash[$key] = ref($array[$key]);
+        }                        
+    }
+
+    /**
+     * OHash constructor.
+     *
+     * php4.4 compliant constructor
+     * 
+     * @param array $array optional  -- An associative php array
+     */
+    function OHash($array=array())
+    {
+        $this->__construct($array);
+    }
+
+    /**
+     * Set a value in this hash.
+     *
+     * @param string $key
+     * @param string $value
+     */
+    function set($key, $value)
+    {
+        $this->_hash[$key] = ref($value);
+    }
+
+    /**
+     * Reference set.
+     *
+     * Until php4.4, it's the only way to avoid object/variable copy.
+     *
+     * @param string $key
+     * @param reference $value
+     */
+    function setRef($key, &$value)
+    {
+        $this->_hash[$key] = ref($value);
+    }
+
+    /**
+     * Set a map of values.
+     *
+     * @param mixed $hash An Hash object or an associative php array.
+     */
+    function setAll($hash)
+    {
+        if (!is_array($hash) && is_a($hash, 'OHash')) {
+            $hash = $hash->toHash();
+        }
+        $keys = array_keys($hash);
+        foreach ($keys as $key) {
+            $this->_hash[$key] = ref($hash[$key]);
+        }
+    }
+
+    /**
+     * Retrieve value associated to specified key.
+     * 
+     * @param  string $key
+     * @return reference
+     */
+    function &get($key)
+    {
+        if ($this->containsKey($key)) {
+            return $this->_hash[$key]->obj;
+        }
+        return null;
+    }
+
+    /**
+     * Remove element associated to specified key from hash.
+     *
+     * @param string $key
+     */
+    function remove($key)
+    {
+        $keys = $this->keys();
+        $i = array_search($key, $keys);
+        if ($i !== false) {
+            // unset hash element to fix many bugs that should appear while
+            // iterating and using references to this element.
+            unset($this->_hash[$key]);
+            // return array_splice($this->_hash, $i, 1);
+        }
+    }
+
+    /**
+     * Remove an element from the Hash.
+     *
+     * @param  mixed $o -- Element to remove from Hash
+     */
+    function removeElement(&$o)
+    {
+        $i = 0;
+        $found = false;
+        foreach ($this->_hash as $key => $value) {
+            if ($value->obj === $o || $value == $o) {
+                $found = $i;
+                break;
+            }
+            $i++;
+        }
+        if ($found !== false) {
+            return array_splice($this->_hash, $found, 1);
+        }
+    }
+
+    /**
+     * Returns true is hashtable empty.
+     * 
+     * @return boolean
+     */
+    function isEmpty()
+    {
+        return $this->size() == 0;
+    }
+
+    /**
+     * Retrieve hash size (number of elements).
+     * 
+     * @return int
+     */
+    function size()
+    {
+        return count($this->_hash);
+    }
+
+    /**
+     * Retrieve hash values array.
+     * 
+     * @return hashtable
+     */
+    function &values()
+    {
+        $v = array();
+        foreach ($this->_hash as $key => $ref) {
+            $v[] =& $ref->obj;
+        }
+        return $v;
+    }
+
+    /**
+     * Retrieve hash keys array.
+     * 
+     * @return array
+     */
+    function keys()
+    {
+        return array_keys($this->_hash);
+    }
+
+    /**
+     * Retrieve an hash iterator ready to use.
+     * 
+     * @return HashIterator
+     */
+    function getNewIterator()
+    {
+        return new HashIterator($this);
+    }
+
+    /**
+     * Test if this hash contains specified key.
+     * 
+     * @param  string $key
+     * @return boolean
+     */
+    function containsKey($key)
+    {
+        return array_key_exists($key, $this->_hash);
+    }
+
+    /**
+     * Test if this hash contains specified value.
+     * 
+     * @param mixed $value -- The value to search
+     * @return boolean
+     */
+    function containsValue($value)
+    {
+        foreach ($this->_hash as $k => $v) {
+            if ($v->obj === $value || $v == $value) { 
+                return true; 
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns the php array (hashtable) handled by this object.
+     * 
+     * @return hashtable
+     */
+    function &toHash()
+    {
+        $result = array();
+        foreach ($this->_hash as $key => $value) {
+            $result[$key] =& $value->obj;
+        }
+        return $result;
+    }
+
+    /**
+     * Create an Hash object from a simple php array variable.
+     *
+     * This method assumes that the array is composed of serial key, value
+     * elements. For each pair of array element, the former will be used as key
+     * and the latter as value.
+     *
+     * @param array $array -- php array.
+     *
+     * @return Hash
+     * @static 1
+     */
+    function ArrayToHash($array)
+    {
+        $h = new OHash();
+        while (count($array) > 1) {
+            $key = array_shift($array);
+            $h->set($key, array_shift($array));
+        }
+        return $h;
+    }
+
+    /**
+     * Generate and return a string representation of this hashtable.
+     *
+     * @return string
+     */
+    function toString()
+    {
+        return Types::_hashToString($this->toHash());
+    }
+
+    /**
+     * Sort hashtable on its keys.
+     */
+    function sort()
+    {
+        ksort($this->_hash);
+    }
+}
+
+
+/**
+ * Hash iterator.
+ *
+ * This kind of iterators are used to walk throug Hash objects.
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class HashIterator 
+{
+    var $_src;
+    var $_values;
+    var $_keys;
+    var $_key;
+    var $_value;
+    var $_i   = -1;
+    var $_end = false;
+
+    /**
+     * Iterator constructor.
+     *
+     * @param mixed $hash -- OHash object or associative php array.
+     */
+    function HashIterator(&$hash)
+    {
+        return $this->__construct($hash);
+    }
+    
+    /**
+     * Iterator php4.4 compliant constructor.
+     *
+     * @param  mixed $hash -- OHash object or associative php array.
+     * 
+     * @throws TypeError 
+     *         When $hash is not an array or an Hash object.
+     */
+    function __construct(&$hash)
+    {
+        if (is_array($hash)) {
+            $this->_src = new OHash($hash);
+        } else if (is_a($hash, 'ohash')) {
+            $this->_src  = &$hash;
+        } else {
+            $err = new TypeError('HashIterator requires associative array or OHash');
+            // return EX::raise($err);
+            die($err->toString());
+            return PEAR::raiseError($err);
+        }
+        $this->reset();
+    }
+
+    //
+    // iterator logics
+    //
+
+    /**
+     * Reset iterator to first element.
+     */
+    function reset()
+    {
+        // store a copy of hash references so a modification of source data
+        // won't affect iterator.
+        $this->_values = $this->_src->_hash;
+        $this->_keys = $this->_src->keys();
+        
+        if (count($this->_keys) == 0) {
+            $this->_end = true;
+            return;
+        }
+
+        $this->_i = 0;        
+        $this->_end = false;
+        $this->_key = $this->_keys[0];
+        $this->_value = $this->_values[$this->_key];
+    }
+
+    /**
+     * Test is end of iterator is not reached.
+     */
+    function isValid()
+    {
+        return !$this->_end;
+    }
+
+    /**
+     * Return next Hash item.
+     *
+     * This method also set _key and _value.
+     *
+     * @return mixed (by reference) or false if end reached
+     */
+    function &next()
+    {
+        if ($this->_end || ++$this->_i >= count($this->_keys)){
+            $this->_end = true;
+            return null;
+        }
+
+        $this->_key   = $this->_keys[$this->_i];
+        $this->_value = $this->_values[$this->_key];
+        return $this->_value->obj;
+    }
+
+    // 
+    // getters
+    // 
+
+    /**
+     * Return current iterator key.
+     *
+     * @return string
+     */
+    function key()
+    {
+        return $this->_key;
+    }
+
+    /**
+     * Return current index (position in iteration).
+     *
+     * @return int
+     */
+    function index()
+    {
+        return $this->_i;
+    }
+
+    /**
+     * Return current iterator value.
+     *
+     * @return mixed
+     */
+    function &value()
+    {
+        return $this->_value->obj;
+    }
+
+    // 
+    // optional implementations
+    // 
+    
+    /**
+     * Remove current iterated item from source.
+     */
+    function remove()
+    {
+        $this->_src->remove($this->_key);
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/Types/OString.php b/PHPTAL-NP-0.7.0/libs/Types/OString.php
new file mode 100644 (file)
index 0000000..b3345db
--- /dev/null
@@ -0,0 +1,473 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+
+require_once "Types.php";
+require_once "Types/Errors.php";
+
+/**
+ * Represents end of line string sequence '\n' of '<br/>' depending on
+ * script context.
+ */
+if (!defined('endl')) { 
+    if (isset($GLOBALS['REQUEST_URI'])) { 
+        define('endl', "<br/>\n"); 
+    } else {
+        define('endl', "\n");
+    }
+}
+
+/**
+ * Object String wrapper class.
+ *
+ * This class is an attempt to normalize php strings in an oo way.
+ *
+ * PHP string related functions have different arguments scheme that decrease
+ * code readability in OO programs. This class provides some php functions
+ * in a comprehensible String class.
+ *
+ * The second interest reside in the StringIterator class which normalize
+ * iteration over strings just like any other iterable object.
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class OString 
+{
+    var $_str;
+
+    /**
+     * String constructor.
+     *
+     * @param mixed $str 
+     *        May be an object from a class implementing the
+     *        'toString()' method or a php variable that can be 
+     *        casted into a string.
+     */
+    function OString($str="")
+    {
+        return $this->__construct($str);
+    }
+    
+    /**
+     * String php4.4 constructor.
+     *
+     * @param mixed $str 
+     *        May be an object from a class implementing the
+     *        'toString()' method or a php variable that can be 
+     *        casted into a string.
+     *
+     * @throws TypeError
+     */
+    function __construct($str="")
+    {
+        if (is_object($str)) {
+            if (!method_exists($str, "toString")) {
+                $err = new TypeError('String constructor requires string or '
+                                     . ' object implementing toString() method.',
+                                     PEAR_ERROR_DIE);
+                // return EX::raise($err);
+                return PEAR::raiseError($err); 
+            }
+            $this->_str = $str->toString();
+        } else {
+            $this->_str = $str;
+        }
+    }
+
+    /**
+     * Append string values of arguments to this string.
+     *
+     * @param mixed ... 
+     *        php variables or objects implementing the toString()
+     *        method.
+     */
+    function append()
+    {
+        $args = func_get_args();
+        foreach ($args as $arg) {
+            if (is_object($arg)) {
+                $this->_str .= $arg->toString();
+            } else {
+                $this->_str .= $arg;
+            }
+        }
+    }
+    
+    /**
+     * Retrieve char at specified position.
+     *
+     * @param  int $i Character position
+     * @return char
+     */
+    function charAt($i)
+    {
+        return $this->_str[$i];
+    }
+    
+    /**
+     * Find first index of needle in current string.
+     *
+     * Return the first position of needle in string or *false* if 
+     * not found.
+     * 
+     * @param mixed $needle  object implementing toString or php variable.
+     * @param int   $pos     Search start position 
+     * @return int 
+     */
+    function indexOf($needle, $pos=0)
+    {
+        if (is_object($needle)) { $needle = $needle->toString(); }
+        return strpos($this->_str, $needle, $pos);
+    }
+    
+    /**
+     * Find last occurence of needle in current string.
+     *
+     * Returns the last position of needle in string or *false* if 
+     * not found.
+     *
+     * @param mixed needle object implementing toString or php variable.
+     * @return int 
+     */
+    function lastIndexOf($needle)
+    {
+        if (is_object($needle)) { $needle = $needle->toString(); }
+        return strrpos($this->_str, $needle);
+    }
+    
+    /**
+     * Returns true if the string match the specified regex.
+     *
+     * @param mixed $regex object implementing toString or php string.
+     * @return boolean
+     */
+    function matches($regex)
+    {
+        if (is_object($regex)) { $regex = $regex->toString(); }
+        return preg_match($regex, $this->_str);
+    }
+
+    /**
+     * Returns true if the string contains specified substring.
+     *
+     * @param mixed $str  object implementing toString or php string.
+     * @return boolean
+     */
+    function contains($str)
+    {
+        if (is_object($str)){ $str = $str->toString(); }
+        return (strpos($this->_str, $str) !== false);
+    }
+    
+    /**
+     * Returns true if the string begins with specified token.
+     *
+     * @param  mixed $str object implementing toString or php string.
+     * @return boolean
+     */
+    function startsWith($str)
+    {
+        if (is_object($str)){ $str = $str->toString(); }
+        return preg_match('|^'. preg_quote($str) . '|', $this->_str);
+    }
+    
+    /**
+     * Returns true if the string ends with specified token.
+     *
+     * @param  mixed $str object implementing toString or php string.
+     * @return boolean
+     */
+    function endsWith($str)
+    {
+        if (is_object($str)){ $str = $str->toString(); }
+        return preg_match('|'. preg_quote($str) . '$|', $this->_str);
+    }
+    
+    /**
+     * Replace occurences of 'old' with 'new'.
+     * 
+     * @param  mixed $old token to replace
+     * @param  mixed $new new token
+     * @return string
+     */
+    function replace($old, $new)
+    {
+        if (is_object($old)){ $old = $old->toString(); }
+        if (is_object($new)){ $new = $new->toString(); }
+        return str_replace($old, $new, $this->_str);
+    }
+    
+    /**
+     * Split this string using specified separator.
+     *
+     * @param mixed $sep Separator token
+     *        
+     * @return array of phpstrings
+     */
+    function split($sep)
+    {
+        if (is_object($sep)){ $sep = $sep->toString(); }
+        return split($sep, $this->_str);
+    }
+    
+    /**
+     * Retrieve a sub string.
+     *
+     * @param int $start 
+     *        start offset
+     *        
+     * @param int $end   
+     *        End offset (up to end if no specified)
+     *        
+     * @return string
+     */
+    function substr($start, $end=false)
+    {
+        if ($end === false){ return substr($this->_str, $start); }
+        return substr($this->_str, $start, ($end-$start));
+    }
+
+    /**
+     * Retrieve a sub string giving its length.
+     *
+     * @param int $start  
+     *        start offset
+     *        
+     * @param int $length 
+     *        length from the start offset
+     *        
+     * @return string
+     */
+    function extract($start, $length)
+    {
+        return substr($this->_str, $start, $length);
+    }
+    
+    /**
+     * Return this string lower cased.
+     * @return string
+     */
+    function toLowerCase()
+    {
+        return strtolower($this->_str);
+    }
+    
+    /**
+     * Return this string upper cased.
+     * @return string
+     */
+    function toUpperCase()
+    {
+        return strtoupper($this->_str);
+    }
+    
+    /**
+     * Remove white characters from the beginning and the end of the string.
+     * @return string
+     */
+    function trim()
+    {
+        return trim($this->_str);
+    }
+    
+    /**
+     * Test if this string equals specified object.
+     *
+     * @param mixed $o   
+     *        php string or object implementing the toString() method.
+     * @return boolean
+     */
+    function equals($o)
+    {
+        if (is_object($o)) {
+            return $this->_str == $str->toString();
+        } else { 
+            return $this->_str == $o;
+        }
+    }
+    
+    /**
+     * Return the length of this string.
+     * @return int
+     */
+    function length()
+    {
+        return strlen($this->_str);
+    }
+    
+    /**
+     * Return the php string handled by this object
+     * @return string
+     */
+    function toString()
+    {
+        return $this->_str;
+    }
+
+    /**
+     * Create a string iterator for this String object.
+     *
+     * StringIterators iterate at a character level.
+     *
+     * @return StringIterator
+     */
+    function &getNewIterator()
+    {
+        return new StringIterator($this);
+    }
+}
+
+/**
+ * String buffer class.
+ *
+ * This class represents a buffer that concatenate appended string or objects
+ * into a simple php string.
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class StringBuffer extends OString
+{
+    /**
+     * Append some elements to the buffer with an endl terminator.
+     * 
+     * @param mixed ... 
+     *        List of php variables and/or objects implementing the
+     *        toString() method.
+     */
+    function appendln()
+    {
+        $args = func_get_args();
+        foreach ($args as $arg) {
+            if (is_object($arg)) {
+                $this->_str .= $arg->toString();
+            } else {
+                $this->_str .= $arg;
+            }
+        }        
+        $this->_str .= endl;
+    }
+}
+
+/**
+ * Iterator for php strings and objects implementing toString method.
+ *
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class StringIterator
+{
+    var $_str;
+    var $_index = -1;
+    var $_end = false;
+    var $_value;
+    
+    /**
+     * Constructor a string iterator.
+     *
+     * @param mixed $str 
+     *        String object, string variable, or Object implementing
+     *        the toString() method.
+     */
+    function StringIterator(&$str)
+    {
+        $this->__construct($str);
+    }
+
+    /**
+     * Constructor a string iterator.
+     *
+     * @param mixed $str 
+     *        object implementing toString or php string variable
+     */
+    function __construct(&$str)
+    {
+        if (is_object($str)) {
+            $this->_string = new OString($str->toString());
+        } else if (is_string($str)) {
+            $this->_string = new OString($str);
+        }
+        $this->reset();
+    }
+
+    /**
+     * Reset iterator to the begining of the string.
+     *
+     * If empty string, this iterator assume it is at the end of string.
+     */
+    function reset()
+    {
+        $this->_end = false;
+        $this->_index = 0;
+        if ($this->_string->length() == 0) {
+            $this->_end = true;
+        } else {
+            $this->_value = $this->_string->charAt(0);
+        }
+    }
+    
+    /**
+     * Return next character.
+     * 
+     * @return char
+     */
+    function next()
+    {
+        if ($this->_end || ++$this->_index >= $this->_string->length()) {
+            $this->_end = true;
+            return null;
+        }
+        
+        $this->_value = $this->_string->charAt($this->_index);
+        return $this->_value;
+    }
+    
+    /**
+     * Return true if the end of the string is not reached yet.
+     *
+     * @return boolean
+     */
+    function isValid()
+    {
+        return !$this->_end;
+    }
+    
+    /**
+     * Retrieve current iterator index.
+     * 
+     * @return int
+     */
+    function index()
+    {
+        return $this->_index;
+    }
+    
+    /**
+     * Retrieve current iterator value.
+     *
+     * @return char
+     */
+    function value()
+    {
+        return $this->_value;
+    }
+}
+
+?>
diff --git a/PHPTAL-NP-0.7.0/libs/Types/Ref.php b/PHPTAL-NP-0.7.0/libs/Types/Ref.php
new file mode 100644 (file)
index 0000000..0f81dc7
--- /dev/null
@@ -0,0 +1,145 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+//  
+//  Copyright (c) 2003 Laurent Bedubourg
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License, or (at your option) any later version.
+//  
+//  This library 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
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//  
+//  Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
+//  
+
+/**
+ * Create a new Ref object referencing specified object or variable.
+ *
+ * Any modification of the source object modify the Refence content, any
+ * modification of the reference obj modify the source object.
+ *
+ * The referenced object can be reached using the reference object using the
+ * 'obj' property.
+ *
+ * <?php
+ *
+ * $a = new Foo();
+ * $ref_a = Ref($a);
+ *
+ * $ref_a->obj->doBar();   // call doBar() on $a
+ *
+ * ?>
+ *
+ * @param mixed $obj -- the object or variable to reference.
+ * @return Ref
+ */
+function ref(&$obj)
+{
+    return new Ref($obj);
+}
+
+/**
+ * Returns true if the object is a Ref object.
+ * 
+ * @param mixed $obj -- any variable that must be tested.
+ *
+ * @return boolean
+ */
+function is_ref($obj)
+{
+    return is_object($obj) && get_class($obj) == "ref";
+}
+
+
+/**
+ * Reference class.
+ *
+ * There's a lot to say about references in PHP. The main problem come from the
+ * fact that until ZendEngine2, objects are copied if not referenced.
+ *
+ * This class helps keeping references to objects even while modifying arrays.
+ *
+ * Example :
+ * 
+ * If an array stores objects, using array_values will copy its
+ * elements.
+ *
+ * If an array stores Ref objects referencing real objects, array_values copy
+ * Ref objects but these copies still reference the source object.
+ *
+ * Until ZendEngine2, it is safer to use Ref objects in stead of object
+ * references.
+ *
+ * <?php
+ * 
+ * $a = new Foo('bar');
+ * $v = new Vector();
+ * $v->push(Ref($a));
+ * 
+ * ?>
+ *
+ * Important :
+ *
+ * This object will have no meaning in php 4.4 as PHP will then use references
+ * everywhere objects are involved.
+ * 
+ * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
+ */
+class Ref
+{
+    /**
+     * php reference to data.
+     */
+    var $obj;
+    
+    /**
+     * Reference constructor.
+     *
+     * Important:
+     *
+     * If $r is a reference, the new reference will just be a copy of the
+     * parameter.
+     *
+     * A Ref cannot reference a Ref.
+     * 
+     * @param mixed $r -- the object or data to reference.
+     */
+    function Ref(&$r)
+    {
+        if (is_ref($r)) {
+            $this->obj =& $r->obj;
+        } else {
+            $this->obj =& $r;
+        }
+    }
+
+    /**
+     * Retrieve the type or the referenced variable.
+     * 
+     * @return string
+     */
+    function type()
+    {
+        return gettype($this->obj);
+    }
+    
+    /**
+     * Return the class name of the referenced variable (if object).
+     *
+     * @return string (empty if not an object)
+     */
+    function getClassName()
+    {
+        return get_class($this->obj);
+    }
+}
+
+?>