]> git.sur5r.net Git - contagged/commitdiff
file hierachy reordering
authorAndreas Gohr <gohr@cosmocode.de>
Tue, 19 Jun 2007 14:07:20 +0000 (16:07 +0200)
committerAndreas Gohr <gohr@cosmocode.de>
Tue, 19 Jun 2007 14:07:20 +0000 (16:07 +0200)
darcs-hash:20070619140720-6e07b-2001276d635b4578c12c90724ce6b2cd7f41e785.gz

206 files changed:
COPYING [deleted file]
Contact_Vcard_Parse.php [deleted file]
README [deleted file]
TODO [deleted file]
ajax.php
config.php [deleted file]
doc/COPYING [new file with mode: 0644]
doc/README [new file with mode: 0644]
doc/TODO [new file with mode: 0644]
doc/docs [new file with mode: 0644]
doc/slapd.example [new file with mode: 0644]
entries.conf [deleted file]
entry.php
fields.php [deleted file]
functions.php [deleted file]
help.php
img.php
import.php
importVCF.php [deleted file]
inc/Contact_Vcard_Parse.php [new file with mode: 0644]
inc/config.php [new file with mode: 0644]
inc/fields.php [new file with mode: 0644]
inc/functions.php [new file with mode: 0644]
inc/importVCF.php [new file with mode: 0644]
inc/init.php [new file with mode: 0644]
inc/lang/ca.php [new file with mode: 0644]
inc/lang/de.php [new file with mode: 0644]
inc/lang/en.php [new file with mode: 0644]
inc/lang/fr.php [new file with mode: 0644]
inc/lang/it.php [new file with mode: 0644]
inc/lang/nl.php [new file with mode: 0644]
inc/smarty/Config_File.class.php [new file with mode: 0644]
inc/smarty/Smarty.class.php [new file with mode: 0644]
inc/smarty/Smarty_Compiler.class.php [new file with mode: 0644]
inc/smarty/debug.tpl [new file with mode: 0644]
inc/smarty/internals/core.assemble_plugin_filepath.php [new file with mode: 0644]
inc/smarty/internals/core.assign_smarty_interface.php [new file with mode: 0644]
inc/smarty/internals/core.create_dir_structure.php [new file with mode: 0644]
inc/smarty/internals/core.display_debug_console.php [new file with mode: 0644]
inc/smarty/internals/core.get_include_path.php [new file with mode: 0644]
inc/smarty/internals/core.get_microtime.php [new file with mode: 0644]
inc/smarty/internals/core.get_php_resource.php [new file with mode: 0644]
inc/smarty/internals/core.is_secure.php [new file with mode: 0644]
inc/smarty/internals/core.is_trusted.php [new file with mode: 0644]
inc/smarty/internals/core.load_plugins.php [new file with mode: 0644]
inc/smarty/internals/core.load_resource_plugin.php [new file with mode: 0644]
inc/smarty/internals/core.process_cached_inserts.php [new file with mode: 0644]
inc/smarty/internals/core.process_compiled_include.php [new file with mode: 0644]
inc/smarty/internals/core.read_cache_file.php [new file with mode: 0644]
inc/smarty/internals/core.rm_auto.php [new file with mode: 0644]
inc/smarty/internals/core.rmdir.php [new file with mode: 0644]
inc/smarty/internals/core.run_insert_handler.php [new file with mode: 0644]
inc/smarty/internals/core.smarty_include_php.php [new file with mode: 0644]
inc/smarty/internals/core.write_cache_file.php [new file with mode: 0644]
inc/smarty/internals/core.write_compiled_include.php [new file with mode: 0644]
inc/smarty/internals/core.write_compiled_resource.php [new file with mode: 0644]
inc/smarty/internals/core.write_file.php [new file with mode: 0644]
inc/smarty/plugins/block.textformat.php [new file with mode: 0644]
inc/smarty/plugins/compiler.assign.php [new file with mode: 0644]
inc/smarty/plugins/function.assign.php [new file with mode: 0644]
inc/smarty/plugins/function.assign_debug_info.php [new file with mode: 0644]
inc/smarty/plugins/function.config_load.php [new file with mode: 0644]
inc/smarty/plugins/function.counter.php [new file with mode: 0644]
inc/smarty/plugins/function.cycle.php [new file with mode: 0644]
inc/smarty/plugins/function.debug.php [new file with mode: 0644]
inc/smarty/plugins/function.eval.php [new file with mode: 0644]
inc/smarty/plugins/function.fetch.php [new file with mode: 0644]
inc/smarty/plugins/function.html_checkboxes.php [new file with mode: 0644]
inc/smarty/plugins/function.html_image.php [new file with mode: 0644]
inc/smarty/plugins/function.html_options.php [new file with mode: 0644]
inc/smarty/plugins/function.html_radios.php [new file with mode: 0644]
inc/smarty/plugins/function.html_select_date.php [new file with mode: 0644]
inc/smarty/plugins/function.html_select_time.php [new file with mode: 0644]
inc/smarty/plugins/function.html_table.php [new file with mode: 0644]
inc/smarty/plugins/function.mailto.php [new file with mode: 0644]
inc/smarty/plugins/function.math.php [new file with mode: 0644]
inc/smarty/plugins/function.popup.php [new file with mode: 0644]
inc/smarty/plugins/function.popup_init.php [new file with mode: 0644]
inc/smarty/plugins/modifier.capitalize.php [new file with mode: 0644]
inc/smarty/plugins/modifier.cat.php [new file with mode: 0644]
inc/smarty/plugins/modifier.count_characters.php [new file with mode: 0644]
inc/smarty/plugins/modifier.count_paragraphs.php [new file with mode: 0644]
inc/smarty/plugins/modifier.count_sentences.php [new file with mode: 0644]
inc/smarty/plugins/modifier.count_words.php [new file with mode: 0644]
inc/smarty/plugins/modifier.csv.php [new file with mode: 0644]
inc/smarty/plugins/modifier.date_format.php [new file with mode: 0644]
inc/smarty/plugins/modifier.debug_print_var.php [new file with mode: 0644]
inc/smarty/plugins/modifier.default.php [new file with mode: 0644]
inc/smarty/plugins/modifier.escape.php [new file with mode: 0644]
inc/smarty/plugins/modifier.indent.php [new file with mode: 0644]
inc/smarty/plugins/modifier.lower.php [new file with mode: 0644]
inc/smarty/plugins/modifier.nl2br.php [new file with mode: 0644]
inc/smarty/plugins/modifier.noteparser.php [new file with mode: 0644]
inc/smarty/plugins/modifier.regex_replace.php [new file with mode: 0644]
inc/smarty/plugins/modifier.replace.php [new file with mode: 0644]
inc/smarty/plugins/modifier.spacify.php [new file with mode: 0644]
inc/smarty/plugins/modifier.string_format.php [new file with mode: 0644]
inc/smarty/plugins/modifier.strip.php [new file with mode: 0644]
inc/smarty/plugins/modifier.strip_tags.php [new file with mode: 0644]
inc/smarty/plugins/modifier.truncate.php [new file with mode: 0644]
inc/smarty/plugins/modifier.upper.php [new file with mode: 0644]
inc/smarty/plugins/modifier.wordwrap.php [new file with mode: 0644]
inc/smarty/plugins/outputfilter.trimwhitespace.php [new file with mode: 0644]
inc/smarty/plugins/shared.escape_special_chars.php [new file with mode: 0644]
inc/smarty/plugins/shared.make_timestamp.php [new file with mode: 0644]
inc/template.php [new file with mode: 0644]
index.php
init.php [deleted file]
js/builder.js [deleted file]
js/controls.js [deleted file]
js/date-formatting.js [deleted file]
js/dragdrop.js [deleted file]
js/effects.js [deleted file]
js/formatDate.js [deleted file]
js/gui.js [deleted file]
js/prototype.js [deleted file]
js/scriptaculous.js [deleted file]
js/slider.js [deleted file]
js/unittest.js [deleted file]
lang/ca.php [deleted file]
lang/de.php [deleted file]
lang/en.php [deleted file]
lang/fr.php [deleted file]
lang/it.php [deleted file]
lang/nl.php [deleted file]
ldapab.schema [deleted file]
login.php
orgs.php
slapd.example [deleted file]
smarty/Config_File.class.php [deleted file]
smarty/Smarty.class.php [deleted file]
smarty/Smarty_Compiler.class.php [deleted file]
smarty/debug.tpl [deleted file]
smarty/internals/core.assemble_plugin_filepath.php [deleted file]
smarty/internals/core.assign_smarty_interface.php [deleted file]
smarty/internals/core.create_dir_structure.php [deleted file]
smarty/internals/core.display_debug_console.php [deleted file]
smarty/internals/core.get_include_path.php [deleted file]
smarty/internals/core.get_microtime.php [deleted file]
smarty/internals/core.get_php_resource.php [deleted file]
smarty/internals/core.is_secure.php [deleted file]
smarty/internals/core.is_trusted.php [deleted file]
smarty/internals/core.load_plugins.php [deleted file]
smarty/internals/core.load_resource_plugin.php [deleted file]
smarty/internals/core.process_cached_inserts.php [deleted file]
smarty/internals/core.process_compiled_include.php [deleted file]
smarty/internals/core.read_cache_file.php [deleted file]
smarty/internals/core.rm_auto.php [deleted file]
smarty/internals/core.rmdir.php [deleted file]
smarty/internals/core.run_insert_handler.php [deleted file]
smarty/internals/core.smarty_include_php.php [deleted file]
smarty/internals/core.write_cache_file.php [deleted file]
smarty/internals/core.write_compiled_include.php [deleted file]
smarty/internals/core.write_compiled_resource.php [deleted file]
smarty/internals/core.write_file.php [deleted file]
smarty/plugins/block.textformat.php [deleted file]
smarty/plugins/compiler.assign.php [deleted file]
smarty/plugins/function.assign.php [deleted file]
smarty/plugins/function.assign_debug_info.php [deleted file]
smarty/plugins/function.config_load.php [deleted file]
smarty/plugins/function.counter.php [deleted file]
smarty/plugins/function.cycle.php [deleted file]
smarty/plugins/function.debug.php [deleted file]
smarty/plugins/function.eval.php [deleted file]
smarty/plugins/function.fetch.php [deleted file]
smarty/plugins/function.html_checkboxes.php [deleted file]
smarty/plugins/function.html_image.php [deleted file]
smarty/plugins/function.html_options.php [deleted file]
smarty/plugins/function.html_radios.php [deleted file]
smarty/plugins/function.html_select_date.php [deleted file]
smarty/plugins/function.html_select_time.php [deleted file]
smarty/plugins/function.html_table.php [deleted file]
smarty/plugins/function.mailto.php [deleted file]
smarty/plugins/function.math.php [deleted file]
smarty/plugins/function.popup.php [deleted file]
smarty/plugins/function.popup_init.php [deleted file]
smarty/plugins/modifier.capitalize.php [deleted file]
smarty/plugins/modifier.cat.php [deleted file]
smarty/plugins/modifier.count_characters.php [deleted file]
smarty/plugins/modifier.count_paragraphs.php [deleted file]
smarty/plugins/modifier.count_sentences.php [deleted file]
smarty/plugins/modifier.count_words.php [deleted file]
smarty/plugins/modifier.csv.php [deleted file]
smarty/plugins/modifier.date_format.php [deleted file]
smarty/plugins/modifier.debug_print_var.php [deleted file]
smarty/plugins/modifier.default.php [deleted file]
smarty/plugins/modifier.escape.php [deleted file]
smarty/plugins/modifier.indent.php [deleted file]
smarty/plugins/modifier.lower.php [deleted file]
smarty/plugins/modifier.nl2br.php [deleted file]
smarty/plugins/modifier.noteparser.php [deleted file]
smarty/plugins/modifier.regex_replace.php [deleted file]
smarty/plugins/modifier.replace.php [deleted file]
smarty/plugins/modifier.spacify.php [deleted file]
smarty/plugins/modifier.string_format.php [deleted file]
smarty/plugins/modifier.strip.php [deleted file]
smarty/plugins/modifier.strip_tags.php [deleted file]
smarty/plugins/modifier.truncate.php [deleted file]
smarty/plugins/modifier.upper.php [deleted file]
smarty/plugins/modifier.wordwrap.php [deleted file]
smarty/plugins/outputfilter.trimwhitespace.php [deleted file]
smarty/plugins/shared.escape_special_chars.php [deleted file]
smarty/plugins/shared.make_timestamp.php [deleted file]
tags.php
template.php [deleted file]
xml.php [deleted file]

diff --git a/COPYING b/COPYING
deleted file mode 100644 (file)
index 5b6e7c6..0000000
--- a/COPYING
+++ /dev/null
@@ -1,340 +0,0 @@
-                   GNU GENERAL PUBLIC LICENSE
-                      Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                           Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-\f
-                   GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-\f
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-\f
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-\f
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                           NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-                    END OF TERMS AND CONDITIONS
-\f
-           How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/Contact_Vcard_Parse.php b/Contact_Vcard_Parse.php
deleted file mode 100644 (file)
index da1f16f..0000000
+++ /dev/null
@@ -1,836 +0,0 @@
-<?php
-/* vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4: */ 
-// +----------------------------------------------------------------------+ 
-// | PHP version 4                                                        | 
-// +----------------------------------------------------------------------+ 
-// | Copyright (c) 1997-2002 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: Paul M. Jones <pmjones@ciaweb.net>                          | 
-// +----------------------------------------------------------------------+ 
-// 
-// $Id: Contact_Vcard_Parse.php,v 1.1 2004/06/01 08:48:59 gohr Exp $ 
-
-
-/**
-* 
-* Parser for vCards.
-*
-* This class parses vCard 2.1 and 3.0 sources from file or text into a
-* structured array.
-* 
-* Usage:
-* 
-* <code>
-*     // include this class file
-*     require_once 'Contact_Vcard_Parse.php';
-*     
-*     // instantiate a parser object
-*     $parse = new Contact_Vcard_Parse();
-*     
-*     // parse a vCard file and store the data
-*     // in $cardinfo
-*     $cardinfo = $parse->fromFile('sample.vcf');
-*     
-*     // view the card info array
-*     echo '<pre>';
-*     print_r($cardinfo);
-*     echo '</pre>';
-* </code>
-* 
-*
-* @author Paul M. Jones <pmjones@ciaweb.net>
-* 
-* @package Contact_Vcard_Parse
-* 
-* @version 1.30
-* 
-*/
-
-class Contact_Vcard_Parse {
-    
-    
-    /**
-    * 
-    * Reads a file for parsing, then sends it to $this->fromText()
-    * and returns the results.
-    * 
-    * @access public
-    * 
-    * @param array $filename The filename to read for vCard information.
-    * 
-    * @return array An array of of vCard information extracted from the
-    * file.
-    * 
-    * @see Contact_Vcard_Parse::fromText()
-    * 
-    * @see Contact_Vcard_Parse::_fromArray()
-    * 
-    */
-    
-    function fromFile($filename, $decode_qp = true)
-    {
-        $text = $this->fileGetContents($filename);
-        
-        if ($text === false) {
-            return false;
-        } else {
-            // dump to, and get return from, the fromText() method.
-            return $this->fromText($text, $decode_qp);
-        }
-    }
-    
-    
-    /**
-    * 
-    * Reads the contents of a file.  Included for users whose PHP < 4.3.0.
-    * 
-    * @access public
-    * 
-    * @param array $filename The filename to read for vCard information.
-    * 
-    * @return string|bool The contents of the file if it exists and is
-    * readable, or boolean false if not.
-    * 
-    * @see Contact_Vcard_Parse::fromFile()
-    * 
-    */
-    
-    function fileGetContents($filename)
-    {
-        if (file_exists($filename) &&
-            is_readable($filename)) {
-            
-            $text = '';
-            $len = filesize($filename);
-            
-            $fp = fopen($filename, 'r');
-            while ($line = fread($fp, filesize($filename))) {
-                $text .= $line;
-            }
-            fclose($fp);
-            
-            return $text;
-            
-        } else {
-        
-            return false;
-            
-        }
-    }
-    
-    
-    /**
-    * 
-    * Prepares a block of text for parsing, then sends it through and
-    * returns the results from $this->fromArray().
-    * 
-    * @access public
-    * 
-    * @param array $text A block of text to read for vCard information.
-    * 
-    * @return array An array of vCard information extracted from the
-    * source text.
-    * 
-    * @see Contact_Vcard_Parse::_fromArray()
-    * 
-    */
-    
-    function fromText($text, $decode_qp = true)
-    {
-        // convert all kinds of line endings to Unix-standard and get
-        // rid of double blank lines.
-        $this->convertLineEndings($text);
-        
-        // unfold lines.  concat two lines where line 1 ends in \n and
-        // line 2 starts with a whitespace character.  only removes
-        // the first whitespace character, leaves others in place.
-        $fold_regex = '(\n)([ |\t])';
-        $text = preg_replace("/$fold_regex/i", "", $text);
-        
-        // massage for Macintosh OS X Address Book (remove nulls that
-        // Address Book puts in for unicode chars)
-        $text = str_replace("\x00", '', $text);
-        
-        // convert the resulting text to an array of lines
-        $lines = explode("\n", $text);
-        
-        // parse the array of lines and return vCard info
-        return $this->_fromArray($lines, $decode_qp);
-    }
-    
-    
-    /**
-    * 
-    * Converts line endings in text.
-    * 
-    * Takes any text block and converts all line endings to UNIX
-    * standard. DOS line endings are \r\n, Mac are \r, and UNIX is \n.
-    *
-    * NOTE: Acts on the text block in-place; does not return a value.
-    * 
-    * @access public
-    * 
-    * @param string $text The string on which to convert line endings.
-    * 
-    * @return void
-    * 
-    */
-    
-    function convertLineEndings(&$text)
-    {
-        // DOS
-        $text = str_replace("\r\n", "\n", $text);
-        
-        // Mac
-        $text = str_replace("\r", "\n", $text);
-    }
-    
-    
-    /**
-    * 
-    * Splits a string into an array at semicolons.  Honors backslash-
-    * escaped semicolons (i.e., splits at ';' not '\;').
-    * 
-    * @access public
-    * 
-    * @param string $text The string to split into an array.
-    * 
-    * @param bool $convertSingle If splitting the string results in a
-    * single array element, return a string instead of a one-element
-    * array.
-    * 
-    * @return mixed An array of values, or a single string.
-    * 
-    */
-    
-    function splitBySemi($text, $convertSingle = false)
-    {
-        // we use these double-backs (\\) because they get get converted
-        // to single-backs (\) by preg_split.  the quad-backs (\\\\) end
-        // up as as double-backs (\\), which is what preg_split requires
-        // to indicate a single backslash (\). what a mess.
-        $regex = '(?<!\\\\)(\;)';
-        $tmp = preg_split("/$regex/i", $text);
-        
-        // if there is only one array-element and $convertSingle is
-        // true, then return only the value of that one array element
-        // (instead of returning the array).
-        if ($convertSingle && count($tmp) == 1) {
-            return $tmp[0];
-        } else {
-            return $tmp;
-        }
-    }
-    
-    
-    /**
-    * 
-    * Splits a string into an array at commas.  Honors backslash-
-    * escaped commas (i.e., splits at ',' not '\,').
-    * 
-    * @access public
-    * 
-    * @param string $text The string to split into an array.
-    * 
-    * @param bool $convertSingle If splitting the string results in a
-    * single array element, return a string instead of a one-element
-    * array.
-    * 
-    * @return mixed An array of values, or a single string.
-    * 
-    */
-    
-    function splitByComma($text, $convertSingle = false)
-    {
-        // we use these double-backs (\\) because they get get converted
-        // to single-backs (\) by preg_split.  the quad-backs (\\\\) end
-        // up as as double-backs (\\), which is what preg_split requires
-        // to indicate a single backslash (\). ye gods, how ugly.
-        $regex = '(?<!\\\\)(\,)';
-        $tmp = preg_split("/$regex/i", $text);
-        
-        // if there is only one array-element and $convertSingle is
-        // true, then return only the value of that one array element
-        // (instead of returning the array).
-        if ($convertSingle && count($tmp) == 1) {
-            return $tmp[0];
-        } else {
-            return $tmp;
-        }
-    }
-    
-    
-    /**
-    * 
-    * Used to make string human-readable after being a vCard value.
-    * 
-    * Converts...
-    *     \; => ;
-    *     \, => ,
-    *     literal \n => newline
-    * 
-    * @access public
-    * 
-    * @param mixed $text The text to unescape.
-    * 
-    * @return void
-    * 
-    */
-    
-    function unescape(&$text)
-    {
-        if (is_array($text)) {
-            foreach ($text as $key => $val) {
-                $this->unescape($val);
-                $text[$key] = $val;
-            }
-        } else {
-            $text = str_replace('\;', ';', $text);
-            $text = str_replace('\,', ',', $text);
-            $text = str_replace('\n', "\n", $text);
-        }
-    }
-    
-    
-    /**
-    *
-    * Emulated destructor.
-    *
-    * @access private
-    * @return boolean true
-    *
-    */
-    
-    function _Contact_Vcard_Parse()
-    {
-        return true;
-    }
-    
-    
-    /**
-    * 
-    * Parses an array of source lines and returns an array of vCards.
-    * Each element of the array is itself an array expressing the types,
-    * parameters, and values of each part of the vCard. Processes both
-    * 2.1 and 3.0 vCard sources.
-    *
-    * @access private
-    * 
-    * @param array $source An array of lines to be read for vCard
-    * information.
-    * 
-    * @return array An array of of vCard information extracted from the
-    * source array.
-    * 
-    */
-    
-    function _fromArray($source, $decode_qp = true)
-    {
-        // the info array will hold all resulting vCard information.
-        $info = array();
-        
-        // tells us whether the source text indicates the beginning of a
-        // new vCard with a BEGIN:VCARD tag.
-        $begin = false;
-        
-        // holds information about the current vCard being read from the
-        // source text.
-        $card = array();
-        
-        // loop through each line in the source array
-        foreach ($source as $line) {
-            
-            // if the line is blank, skip it.
-            if (trim($line) == '') {
-                continue;
-            }
-            
-            // find the first instance of ':' on the line.  The part
-            // to the left of the colon is the type and parameters;
-            // the part to the right of the colon is the value data.
-            $pos = strpos($line, ':');
-            
-            // if there is no colon, skip the line.
-            if ($pos === false) {
-                continue;
-            }
-            
-            // get the left and right portions
-            $left = trim(substr($line, 0, $pos));
-            $right = trim(substr($line, $pos+1, strlen($line)));
-            
-            // have we started yet?
-            if (! $begin) {
-                
-                // nope.  does this line indicate the beginning of
-                // a new vCard?
-                if (strtoupper($left) == 'BEGIN' &&
-                    strtoupper($right) == 'VCARD') {
-                    
-                    // tell the loop that we've begun a new card
-                    $begin = true;
-                }
-                
-                // regardless, loop to the next line of source. if begin
-                // is still false, the next loop will check the line. if
-                // begin has now been set to true, the loop will start
-                // collecting card info.
-                continue;
-                
-            } else {
-                
-                // yep, we've started, but we don't know how far along
-                // we are in the card. is this the ending line of the
-                // current vCard?
-                if (strtoupper($left) == 'END' &&
-                    strtoupper($right) == 'VCARD') {
-                    
-                    // yep, we're done. keep the info from the current
-                    // card...
-                    $info[] = $card;
-                    
-                    // ...and reset to grab a new card if one exists in
-                    // the source array.
-                    $begin = false;
-                    $card = array();
-                    
-                } else {
-                    
-                    // we're not on an ending line, so collect info from
-                    // this line into the current card. split the
-                    // left-portion of the line into a type-definition
-                    // (the kind of information) and parameters for the
-                    // type.
-                    $typedef = $this->_getTypeDef($left);
-                    $params = $this->_getParams($left);
-                    
-                    // if we are decoding quoted-printable, do so now.
-                    // QUOTED-PRINTABLE is not allowed in version 3.0,
-                    // but we don't check for versioning, so we do it
-                    // regardless.  ;-)
-                    $this->_decode_qp($params, $right);
-                    
-                    // now get the value-data from the line, based on
-                    // the typedef
-                    switch ($typedef) {
-                        
-                    case 'N':
-                        // structured name of the person
-                        $value = $this->_parseN($right);
-                        break;
-                        
-                    case 'ADR':
-                        // structured address of the person
-                        $value = $this->_parseADR($right);
-                        break;
-                        
-                    case 'NICKNAME':
-                        // nicknames
-                        $value = $this->_parseNICKNAME($right);
-                        break;
-                        
-                    case 'ORG':
-                        // organizations the person belongs to
-                        $value = $this->_parseORG($right);
-                        break;
-                        
-                    case 'CATEGORIES':
-                        // categories to which this card is assigned
-                        $value = $this->_parseCATEGORIES($right);
-                        break;
-                        
-                    case 'GEO':
-                        // geographic coordinates
-                        $value = $this->_parseGEO($right);
-                        break;
-                        
-                    default:
-                        // by default, just grab the plain value. keep
-                        // as an array to make sure *all* values are
-                        // arrays.  for consistency. ;-)
-                        $value = array(array($right));
-                        break;
-                    }
-                    
-                    // add the type, parameters, and value to the
-                    // current card array.  note that we allow multiple
-                    // instances of the same type, which might be dumb
-                    // in some cases (e.g., N).
-                    $card[$typedef][] = array(
-                        'param' => $params,
-                        'value' => $value
-                    );
-                }
-            }
-        }
-        
-        $this->unescape($info);
-        return $info;
-    }
-    
-    
-    /**
-    *
-    * Takes a vCard line and extracts the Type-Definition for the line.
-    * 
-    * @access private
-    *
-    * @param string $text A left-part (before-the-colon part) from a
-    * vCard line.
-    * 
-    * @return string The type definition for the line.
-    * 
-    */
-    
-    function _getTypeDef($text)
-    {
-        // split the text by semicolons
-        $split = $this->splitBySemi($text);
-        
-        // only return first element (the typedef)
-        return $split[0];
-    }
-    
-    
-    /**
-    *
-    * Finds the Type-Definition parameters for a vCard line.
-    * 
-    * @access private
-    * 
-    * @param string $text A left-part (before-the-colon part) from a
-    * vCard line.
-    * 
-    * @return mixed An array of parameters.
-    * 
-    */
-    
-    function _getParams($text)
-    {
-        // split the text by semicolons into an array
-        $split = $this->splitBySemi($text);
-        
-        // drop the first element of the array (the type-definition)
-        array_shift($split);
-        
-        // set up an array to retain the parameters, if any
-        $params = array();
-        
-        // loop through each parameter.  the params may be in the format...
-        // "TYPE=type1,type2,type3"
-        //    ...or...
-        // "TYPE=type1;TYPE=type2;TYPE=type3"
-        foreach ($split as $full) {
-            
-            // split the full parameter at the equal sign so we can tell
-            // the parameter name from the parameter value
-            $tmp = explode("=", $full);
-            
-            // the key is the left portion of the parameter (before
-            // '='). if in 2.1 format, the key may in fact be the
-            // parameter value, not the parameter name.
-            $key = strtoupper(trim($tmp[0]));
-            
-            // get the parameter name by checking to see if it's in
-            // vCard 2.1 or 3.0 format.
-            $name = $this->_getParamName($key);
-            
-            // list of all parameter values
-            $listall = trim($tmp[1]);
-            
-            // if there is a value-list for this parameter, they are
-            // separated by commas, so split them out too.
-            $list = $this->splitByComma($listall);
-            
-            // now loop through each value in the parameter and retain
-            // it.  if the value is blank, that means it's a 2.1-style
-            // param, and the key itself is the value.
-            foreach ($list as $val) {
-                if (trim($val) != '') {
-                    // 3.0 formatted parameter
-                    $params[$name][] = trim($val);
-                } else {
-                    // 2.1 formatted parameter
-                    $params[$name][] = $key;
-                }
-            }
-            
-            // if, after all this, there are no parameter values for the
-            // parameter name, retain no info about the parameter (saves
-            // ram and checking-time later).
-            if (count($params[$name]) == 0) {
-                unset($params[$name]);
-            }
-        }
-        
-        // return the parameters array.
-        return $params;
-    }
-    
-    
-    /**
-    *
-    * Looks at the parameters of a vCard line; if one of them is
-    * ENCODING[] => QUOTED-PRINTABLE then decode the text in-place.
-    * 
-    * @access private
-    * 
-    * @param array $params A parameter array from a vCard line.
-    * 
-    * @param string $text A right-part (after-the-colon part) from a
-    * vCard line.
-    *
-    * @return void
-    * 
-    */
-    
-    function _decode_qp(&$params, &$text)
-    {
-        // loop through each parameter
-        foreach ($params as $param_key => $param_val) {
-            
-            // check to see if it's an encoding param
-            if (trim(strtoupper($param_key)) == 'ENCODING') {
-            
-                // loop through each encoding param value
-                foreach ($param_val as $enc_key => $enc_val) {
-                
-                    // if any of the values are QP, decode the text
-                    // in-place and return
-                    if (trim(strtoupper($enc_val)) == 'QUOTED-PRINTABLE') {
-                        $text = quoted_printable_decode($text);
-                        return;
-                    }
-                }
-            }
-        }
-    }
-    
-    
-    /**
-    * 
-    * Returns parameter names from 2.1-formatted vCards.
-    *
-    * The vCard 2.1 specification allows parameter values without a
-    * name. The parameter name is then determined from the unique
-    * parameter value.
-    * 
-    * Shamelessly lifted from Frank Hellwig <frank@hellwig.org> and his
-    * vCard PHP project <http://vcardphp.sourceforge.net>.
-    * 
-    * @access private
-    * 
-    * @param string $value The first element in a parameter name-value
-    * pair.
-    * 
-    * @return string The proper parameter name (TYPE, ENCODING, or
-    * VALUE).
-    * 
-    */
-     
-    function _getParamName($value)
-    {
-        static $types = array (
-            'DOM', 'INTL', 'POSTAL', 'PARCEL','HOME', 'WORK',
-            'PREF', 'VOICE', 'FAX', 'MSG', 'CELL', 'PAGER',
-            'BBS', 'MODEM', 'CAR', 'ISDN', 'VIDEO',
-            'AOL', 'APPLELINK', 'ATTMAIL', 'CIS', 'EWORLD',
-            'INTERNET', 'IBMMAIL', 'MCIMAIL',
-            'POWERSHARE', 'PRODIGY', 'TLX', 'X400',
-            'GIF', 'CGM', 'WMF', 'BMP', 'MET', 'PMB', 'DIB',
-            'PICT', 'TIFF', 'PDF', 'PS', 'JPEG', 'QTIME',
-            'MPEG', 'MPEG2', 'AVI',
-            'WAVE', 'AIFF', 'PCM',
-            'X509', 'PGP'
-        );
-        
-        // CONTENT-ID added by pmj
-        static $values = array (
-            'INLINE', 'URL', 'CID', 'CONTENT-ID'
-        );
-        
-        // 8BIT added by pmj
-        static $encodings = array (
-            '7BIT', '8BIT', 'QUOTED-PRINTABLE', 'BASE64'
-        );
-        
-        // changed by pmj to the following so that the name defaults to
-        // whatever the original value was.  Frank Hellwig's original
-        // code was "$name = 'UNKNOWN'".
-        $name = $value;
-        
-        if (in_array($value, $types)) {
-            $name = 'TYPE';
-        } elseif (in_array($value, $values)) {
-            $name = 'VALUE';
-        } elseif (in_array($value, $encodings)) {
-            $name = 'ENCODING';
-        }
-        
-        return $name;
-    }
-    
-    
-    /**
-    *
-    * Parses a vCard line value identified as being of the "N"
-    * (structured name) type-defintion.
-    *
-    * @access private
-    *
-    * @param string $text The right-part (after-the-colon part) of a
-    * vCard line.
-    * 
-    * @return array An array of key-value pairs where the key is the
-    * portion-name and the value is the portion-value.  The value itself
-    * may be an array as well if multiple comma-separated values were
-    * indicated in the vCard source.
-    *
-    */
-    
-    function _parseN($text)
-    {
-        $tmp = $this->splitBySemi($text);
-        return array(
-            $this->splitByComma($tmp[0]), // family (last)
-            $this->splitByComma($tmp[1]), // given (first)
-            $this->splitByComma($tmp[2]), // addl (middle)
-            $this->splitByComma($tmp[3]), // prefix
-            $this->splitByComma($tmp[4])  // suffix
-        );
-    }
-    
-    
-    /**
-    *
-    * Parses a vCard line value identified as being of the "ADR"
-    * (structured address) type-defintion.
-    *
-    * @access private
-    *
-    * @param string $text The right-part (after-the-colon part) of a
-    * vCard line.
-    * 
-    * @return array An array of key-value pairs where the key is the
-    * portion-name and the value is the portion-value.  The value itself
-    * may be an array as well if multiple comma-separated values were
-    * indicated in the vCard source.
-    *
-    */
-    
-    function _parseADR($text)
-    {
-        $tmp = $this->splitBySemi($text);
-        return array(
-            $this->splitByComma($tmp[0]), // pob
-            $this->splitByComma($tmp[1]), // extend
-            $this->splitByComma($tmp[2]), // street
-            $this->splitByComma($tmp[3]), // locality (city)
-            $this->splitByComma($tmp[4]), // region (state)
-            $this->splitByComma($tmp[5]), // postcode (ZIP)
-            $this->splitByComma($tmp[6])  // country
-        );
-    }
-    
-    
-    /**
-    * 
-    * Parses a vCard line value identified as being of the "NICKNAME"
-    * (informal or descriptive name) type-defintion.
-    *
-    * @access private
-    * 
-    * @param string $text The right-part (after-the-colon part) of a
-    * vCard line.
-    * 
-    * @return array An array of nicknames.
-    *
-    */
-    
-    function _parseNICKNAME($text)
-    {
-        return array($this->splitByComma($text));
-    }
-    
-    
-    /**
-    * 
-    * Parses a vCard line value identified as being of the "ORG"
-    * (organizational info) type-defintion.
-    *
-    * @access private
-    *
-    * @param string $text The right-part (after-the-colon part) of a
-    * vCard line.
-    * 
-    * @return array An array of organizations; each element of the array
-    * is itself an array, which indicates primary organization and
-    * sub-organizations.
-    *
-    */
-    
-    function _parseORG($text)
-    {
-        $tmp = $this->splitbySemi($text);
-        $list = array();
-        foreach ($tmp as $val) {
-            $list[] = array($val);
-        }
-        
-        return $list;
-    }
-    
-    
-    /**
-    * 
-    * Parses a vCard line value identified as being of the "CATEGORIES"
-    * (card-category) type-defintion.
-    *
-    * @access private
-    * 
-    * @param string $text The right-part (after-the-colon part) of a
-    * vCard line.
-    * 
-    * @return mixed An array of categories.
-    *
-    */
-    
-    function _parseCATEGORIES($text)
-    {
-        return array($this->splitByComma($text));
-    }
-    
-    
-    /**
-    * 
-    * Parses a vCard line value identified as being of the "GEO"
-    * (geographic coordinate) type-defintion.
-    *
-    * @access private
-    *
-    * @param string $text The right-part (after-the-colon part) of a
-    * vCard line.
-    * 
-    * @return mixed An array of lat-lon geocoords.
-    *
-    */
-    
-    function _parseGEO($text)
-    {
-        $tmp = $this->splitBySemi($text);
-        return array(
-            array($tmp[0]), // lat
-            array($tmp[1])  // lon
-        );
-    }
-}
-
-?>
\ No newline at end of file
diff --git a/README b/README
deleted file mode 100644 (file)
index d37c796..0000000
--- a/README
+++ /dev/null
@@ -1,112 +0,0 @@
-=== ABOUT ===
-
-ConTagged is a webbased address book for small companies. It features a public
-address book which is writable for all company staff and a personal address
-book for each staff member. ConTagged requires an already setup LDAP server to
-authenticate users and store it's data.
-
-=== REQUIREMENTS ===
-
-You need to have a running LDAP Server with some users (objectClass=posixUser)
-in it. It is important that you already have these users because LDAPab uses
-them to authenticate.
-
-You need a webserver (peferable Apache) with PHP (4.3 or higher). PHP needs to
-be compiled with LDAP support (compiled in or as extension)
-
-=== SETUP LDAPab ===
-
-Copy the contents of the .tgz file to a directory below your webserver document
-root. Make sure the webserver is able to write to the cache directory which is
-used for the template engine's cache files. A 'chmod 777 cache' will do.
-
-Open the config.php file in your favourite editor and edit the options
-according to your needs. Some knowlege about LDAP may come in handy.
-
-If HTTP auth is wanted have a look at the provided _htaccess file, edit it as
-needed and rename it back to .htaccess
-
-=== SETUP THE LDAP SERVER ===
-
-The following only describes what to do for open-ldap 2.0! If you use any
-other LDAP server you're left to our own.
-
-You need to include the inetOrgPerson schema in you slapd.conf:
-
-  include /etc/ldap/schema/inetorgperson.schema
-
-If youwant to use the extended schema (needed for tagging and birthday support)
-you need to copy the ldapab.schema file to /etc/ldap/schema/ and include it, too.
-
-  include         /etc/ldap/schema/ldapab.schema
-
-Be sure to enable the extended option in config.php.
-
-To setup the access rights add the following statement to your slapd.conf. Of
-course you have to replace "o=cosmocode,c=de" with your own root DN. The first
-entry may have to adjusted also if your users aren't stored in a ou=people
-entry. Make sure you include these lines before other access control lists that
-match these parts of the ldap tree. If you are unsure have a look at the
-included slapd.example file
-
-  access  to dn.regex="(.*,)?ou=contacts,cn=([^,]+),ou=people,(.*)$"
-          by dn.regex="cn=$2,ou=people,$3" write
-          by * none
-
-  access to dn.subtree="ou=contacts,o=cosmocode,c=de"
-         by users write
-         by * read
-
-After this modifications you have to restart the slapd server.
-
-The last thing is to add the contacts leafs to your LDAP tree. You'll need to
-add a global contacts leaf at top.
-
-  eg: 'ou=contacts,o=cosmocode,c=de'
-
-And a contacts leaf for every user.
-
-  eg: 'ou=contacts,cn=Joe Schmoe,ou=people,o=cosmocode,c=de'
-
-
-If you made everything correct you can point your webbrowser to the newly
-installed ConTagged and use it :-) If you encounter problems try to enable
-logging in your LDAP server to see what the problem is.
-
-=== FEEDBACK, PATCHES, SUPPORT ===
-
-This software was developed to satisfy a need in our company. We give it to the
-public because it may be helpful to other companies with the same needs.
-However this is not a supported product. We like to get feedback and patches
-but we can't promise to answer, to fix bugs or include feature wishes. However
-don't hesitate to contact us but understand that our core business has priority
-over this project.
-
-To contact us send a mail to ldapab@cosmocode.de or visit our homepage at
-http://www.cosmocode.de
-
-=== KNOWN BUGS ===
-
-ConTagged was only tested with open-ldap 2.1 - there may be problems with other
-LDAP Servers.
-
-=== LICENSE ===
-
-ConTagged - An LDAP based Company Address Book
-Copyright 2004 - 2006 - CosmoCode GmbH
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of
-the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-See COPYING for details
diff --git a/TODO b/TODO
deleted file mode 100644 (file)
index 478af17..0000000
--- a/TODO
+++ /dev/null
@@ -1,6 +0,0 @@
-Any help is welcome :-)
-
-  - clean up the code
-  - clean up the HTML (make it validate)
-  - clean up the CSS (it's a mess)
-  - spice up interface (some more web2.0 colors and fonts would be a start)
index 997eba1e49e2c3ce9399ac53cf16bbe6cd498ab7..7e16b2f362d974e83880650600bb9ebea1739c09 100644 (file)
--- a/ajax.php
+++ b/ajax.php
@@ -1,14 +1,7 @@
 <?
-require_once('init.php');
+require_once('inc/init.php');
 ldap_login();
 
-
-/*
-echo '<bla><[!CDATA[';
-print_r($_REQUEST);
-echo ']]></bla>';
-*/
-
 $FIELD = preg_replace('/entry\[/','',$_REQUEST['field']);
 $FIELD = preg_replace('/\W+/','',$FIELD);
 
@@ -46,7 +39,7 @@ function ajax_addnote($dn,$note){
   ldap_modify($LDAP_CON,$dn,$entry);
 
 
-  require_once(dirname(__FILE__).'/smarty/plugins/modifier.noteparser.php');
+  require_once(dirname(__FILE__).'/inc/smarty/plugins/modifier.noteparser.php');
   print smarty_modifier_noteparser($note);
 }
 
diff --git a/config.php b/config.php
deleted file mode 100644 (file)
index d46910e..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-<?
-
-  // LDAP URL; if set, takes precedence over ldapserver and ldapport
-  #$conf['ldapurl']     = 'ldaps://ldap.example.com/';
-
-  // Which LDAP Server to use?
-  $conf['ldapserver']  = 'ldap';
-
-  // Which LDAP Port Server to use? (389 is standard, 636 for ssl)
-  $conf['ldapport']    = 389;
-
-  // Use LDAP protocol version 3? (0|1)
-  $conf['ldapv3'] = 1;
-
-  // What is the root dn on this Server?
-  $conf['ldaprootdn']  = 'o=cosmocode, c=de';
-
-  // Where are the user Accounts stored?
-  $conf['usertree']    = 'ou=people, '.$conf['ldaprootdn'];
-
-  // How to match users? %u is replaced by the given login
-  $conf['userfilter']  = '(&(uid=%u)(objectClass=posixAccount))';
-
-  // Use these values to bind to the ldap directory when not logged in (leave blank for anonymous bind)
-  $conf['anonbinddn']  = '';
-  $conf['anonbindpw']  = '';
-
-  // Which language to use (see lang directory)
-  $conf['lang']        = 'en';
-
-  // Where to store public contacts?
-  $conf['publicbook']  = 'ou=contacts, '.$conf['ldaprootdn'];
-
-  // Where to store private contacts (relative to $conf['usertree'])
-  $conf['privatebook'] = 'ou=contacts';
-
-  // Should the public address book be viewable by logged in users only? (0|1)
-  $conf['userlogreq']  = 0;
-
-  // Should the additional schema ldapab.schema be used? (0|1)
-  // Note: openxchange and extended are currently exclusive, do not use both at the same time!
-  $conf['extended']    = 1;
-
-  // Should we use some parts of the openxchange.schema? (0|1)
-  // Note: openxchange and extended are currently exclusive, do not use both at the same time!
-  $conf['openxchange'] = 0;
-
-  // Should we try to login using the username and password provided by httpd? (0|1)
-  $conf['httpd_auth']  = 0;
-
-  // Dateformat for birthdays when using extended schema
-  // see http://www.php.net/manual/en/function.strftime.php
-  #$conf['dateformat']  = '%Y/%m/%d';
-  $conf['dateformat']  = '%d.%m.%Y';
-
-  // Force recompilation of smarty templates?
-  $conf['smartycompile'] = 1;
-
-
diff --git a/doc/COPYING b/doc/COPYING
new file mode 100644 (file)
index 0000000..5b6e7c6
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/doc/README b/doc/README
new file mode 100644 (file)
index 0000000..d37c796
--- /dev/null
@@ -0,0 +1,112 @@
+=== ABOUT ===
+
+ConTagged is a webbased address book for small companies. It features a public
+address book which is writable for all company staff and a personal address
+book for each staff member. ConTagged requires an already setup LDAP server to
+authenticate users and store it's data.
+
+=== REQUIREMENTS ===
+
+You need to have a running LDAP Server with some users (objectClass=posixUser)
+in it. It is important that you already have these users because LDAPab uses
+them to authenticate.
+
+You need a webserver (peferable Apache) with PHP (4.3 or higher). PHP needs to
+be compiled with LDAP support (compiled in or as extension)
+
+=== SETUP LDAPab ===
+
+Copy the contents of the .tgz file to a directory below your webserver document
+root. Make sure the webserver is able to write to the cache directory which is
+used for the template engine's cache files. A 'chmod 777 cache' will do.
+
+Open the config.php file in your favourite editor and edit the options
+according to your needs. Some knowlege about LDAP may come in handy.
+
+If HTTP auth is wanted have a look at the provided _htaccess file, edit it as
+needed and rename it back to .htaccess
+
+=== SETUP THE LDAP SERVER ===
+
+The following only describes what to do for open-ldap 2.0! If you use any
+other LDAP server you're left to our own.
+
+You need to include the inetOrgPerson schema in you slapd.conf:
+
+  include /etc/ldap/schema/inetorgperson.schema
+
+If youwant to use the extended schema (needed for tagging and birthday support)
+you need to copy the ldapab.schema file to /etc/ldap/schema/ and include it, too.
+
+  include         /etc/ldap/schema/ldapab.schema
+
+Be sure to enable the extended option in config.php.
+
+To setup the access rights add the following statement to your slapd.conf. Of
+course you have to replace "o=cosmocode,c=de" with your own root DN. The first
+entry may have to adjusted also if your users aren't stored in a ou=people
+entry. Make sure you include these lines before other access control lists that
+match these parts of the ldap tree. If you are unsure have a look at the
+included slapd.example file
+
+  access  to dn.regex="(.*,)?ou=contacts,cn=([^,]+),ou=people,(.*)$"
+          by dn.regex="cn=$2,ou=people,$3" write
+          by * none
+
+  access to dn.subtree="ou=contacts,o=cosmocode,c=de"
+         by users write
+         by * read
+
+After this modifications you have to restart the slapd server.
+
+The last thing is to add the contacts leafs to your LDAP tree. You'll need to
+add a global contacts leaf at top.
+
+  eg: 'ou=contacts,o=cosmocode,c=de'
+
+And a contacts leaf for every user.
+
+  eg: 'ou=contacts,cn=Joe Schmoe,ou=people,o=cosmocode,c=de'
+
+
+If you made everything correct you can point your webbrowser to the newly
+installed ConTagged and use it :-) If you encounter problems try to enable
+logging in your LDAP server to see what the problem is.
+
+=== FEEDBACK, PATCHES, SUPPORT ===
+
+This software was developed to satisfy a need in our company. We give it to the
+public because it may be helpful to other companies with the same needs.
+However this is not a supported product. We like to get feedback and patches
+but we can't promise to answer, to fix bugs or include feature wishes. However
+don't hesitate to contact us but understand that our core business has priority
+over this project.
+
+To contact us send a mail to ldapab@cosmocode.de or visit our homepage at
+http://www.cosmocode.de
+
+=== KNOWN BUGS ===
+
+ConTagged was only tested with open-ldap 2.1 - there may be problems with other
+LDAP Servers.
+
+=== LICENSE ===
+
+ConTagged - An LDAP based Company Address Book
+Copyright 2004 - 2006 - CosmoCode GmbH
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of
+the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+See COPYING for details
diff --git a/doc/TODO b/doc/TODO
new file mode 100644 (file)
index 0000000..478af17
--- /dev/null
+++ b/doc/TODO
@@ -0,0 +1,6 @@
+Any help is welcome :-)
+
+  - clean up the code
+  - clean up the HTML (make it validate)
+  - clean up the CSS (it's a mess)
+  - spice up interface (some more web2.0 colors and fonts would be a start)
diff --git a/doc/docs b/doc/docs
new file mode 100644 (file)
index 0000000..19f2060
--- /dev/null
+++ b/doc/docs
@@ -0,0 +1,51 @@
+# LDAP 2 Schema
+#
+# This is a schema extension for the LDAPab Addressbook by
+# CosmoCode GmbH www.cosmocode.de
+#
+# CosmoCode owns the following MIB Block:
+# iso.org.dod.internet.private.enterprise.16331.*
+#
+# CosmoCode currently uses the following OID hierachy to organize the IDs:
+#
+# defined in cosmo4ML.schema
+# 1.3.6.1.4.1.16331.1           formel CMS (cosmo4ML prefix)
+# 1.3.6.1.4.1.16331.1.1           SNMP (not used)
+# 1.3.6.1.4.1.16331.1.2           LDAP
+# 1.3.6.1.4.1.16331.1.2.1           AttributeTypes
+# 1.3.6.1.4.1.16331.1.2.2           ObjectClasses
+#
+# defined in ldapab.schema:
+# 1.3.6.1.4.1.16331.2          LDAPab
+# 1.3.6.1.4.1.16331.2.1                  SNMP (not used)
+# 1.3.6.1.4.1.16331.2.2                LDAP
+# 1.3.6.1.4.1.16331.2.2.1           AttributeTypes
+# 1.3.6.1.4.1.16331.2.2.2           ObjectClasses
+
+
+# OID macros for ease of use:
+objectIdentifier cosmocodeOID 1.3.6.1.4.1.16331
+objectIdentifier LDAPab       cosmocodeOID:2.2
+
+
+attributetype ( 1.3.6.1.4.1.16331.2.2.1.1 NAME 'anniversary'
+                DESC 'Holds Birthdays etc.'
+                EQUALITY caseIgnoreMatch
+                ORDERING caseIgnoreOrderingMatch
+                SUBSTR caseIgnoreSubstringsMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+                SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.16331.2.2.1.2 NAME 'marker'
+                DESC 'marking flag'
+                EQUALITY caseIgnoreMatch
+                ORDERING caseIgnoreOrderingMatch
+                SUBSTR caseIgnoreSubstringsMatch
+                SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256}
+               )
+
+objectclass ( 1.3.6.1.4.1.16331.2.2.2.1 NAME 'contactPerson'
+             DESC 'Contact - Addressbook entry'
+              AUXILIARY
+              MAY  ( anniversary $ marker )
+            )
diff --git a/doc/slapd.example b/doc/slapd.example
new file mode 100644 (file)
index 0000000..cd7643a
--- /dev/null
@@ -0,0 +1,111 @@
+# This is the main ldapd configuration file. See slapd.conf(5) for more
+# info on the configuration options.
+
+# Schema and objectClass definitions
+include         /etc/ldap/schema/core.schema
+include         /etc/ldap/schema/cosine.schema
+include         /etc/ldap/schema/nis.schema
+include         /etc/ldap/schema/inetorgperson.schema
+include                /etc/ldap/schema/samba.schema
+include                /etc/ldap/schema/courierimap.schema
+include                /etc/ldap/schema/phpgwaccount.schema
+include                /etc/ldap/schema/phpgwcontact.schema
+include                /etc/ldap/schema/ldapab.schema
+
+
+# Schema check allows for forcing entries to
+# match schemas for their objectClasses's
+schemacheck     on
+
+# Where the pid file is put. The init.d script
+# will not stop the server if you change this.
+pidfile         /var/run/slapd.pid
+
+# List of arguments that were passed to the server
+argsfile        /var/run/slapd.args
+
+# Where to store the replica logs
+replogfile     /var/lib/ldap/replog
+
+# Read slapd.conf(5) for possible values
+#loglevel        256
+loglevel       0
+
+#######################################################################
+# ldbm database definitions
+#######################################################################
+
+# The backend type, ldbm, is the default standard
+database        ldbm
+
+# The base of your directory
+suffix          "o=cosmocode,c=de"
+
+# Where the database file are physically stored
+directory       "/var/lib/ldap"
+
+# Indexing options
+index objectClass eq
+
+# Folgende Indizies sind im samba-LDAP-HOWTO empfohlen;
+
+## support pbb_getsampwnam()
+index uid           pres,eq
+## support pdb_getsampwrid()
+index rid           eq
+
+## uncomment these if you are storing posixAccount and
+## posixGroup entries in the directory as well
+index uidNumber     eq
+index gidNumber     eq
+index cn            eq
+index memberUid     eq
+
+# Save the time that the entry gets modified
+lastmod on
+
+# The userPassword by default can be changed
+# by the entry owning it if they are authenticated.
+# Others should not be able to see it, except the
+# admin entry below
+access to attribute=userPassword
+        by dn="cn=admin,o=cosmocode,c=de" write
+        by anonymous auth
+        by self write
+        by * none
+
+access to attribute=lmPassword
+        by dn="cn=admin,o=cosmocode,c=de" write
+        by anonymous auth
+        by self write
+        by * none
+
+access to attribute=ntPassword
+        by dn="cn=admin,o=cosmocode,c=de" write
+        by anonymous auth
+        by self write
+        by * none
+
+# private LDAP Addressbook is readable and writable for the owner only
+access to dn="(.*,)?ou=contacts,cn=([^,]+),ou=people,(.*)$"
+        by dn="cn=$2,ou=people,$3" write
+        by * none
+
+# global LDAP Addressbook is writable for all authenticated users
+# This entry has to be _before_ any other entry that matches the contact
+# tree eg. the * entry
+access to dn.subtree="ou=contacts,o=cosmocode,c=de"
+       by users write
+       by * read
+
+# The admin dn has full write access
+access to *
+        by dn="cn=admin,o=cosmocode,c=de" write
+        by * read
+
+# For Netscape Roaming support, each user gets a roaming
+# profile for which they have write access to
+#access to dn=".*,ou=Roaming,o=morsnet"
+#        by dn="cn=admin,o=cosmocode,c=de" write
+#        by dnattr=owner write
+
diff --git a/entries.conf b/entries.conf
deleted file mode 100644 (file)
index 0809369..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-dn                                  dn
-sn                                  name
-givenName                           givenname
-title                               title
-o                                   organization
-physicalDeliveryOfficeName          office
-postalAddress                       street
-postalCode                          zip
-l                                   location
-telephoneNumber                     phone
-facsimileTelephoneNumber            fax
-mobile                              mobile
-pager                               pager
-homePhone                           homephone
-homePostalAddress                   homestreet
-photo                               photo
-jpegPhoto                           photo
-labeledURI                          url
-description                         note
-manager                             manager
index ec73909242f0d362b93c6fd239f78dbace847c25..e22452267af40da0d26eaf22ced382c8dec81c77 100644 (file)
--- a/entry.php
+++ b/entry.php
-<?
-  require_once('init.php');
-  ldap_login();
-
-  $users = get_users();
-
-  //select template to use
-  if (empty($_REQUEST['mode'])) { $_REQUEST['mode']='show'; }
-  if( $_SESSION['ldapab']['username'] &&
-     ($_REQUEST['mode']=='edit' || $_REQUEST['mode']=='copy')){
-    $template='entry_edit.tpl';
-  }elseif($_REQUEST['mode']=='vcf'){
-    $template='entry_vcf.tpl';
-  }else{
-    $template='entry_show.tpl';
-  }
-
-  if (empty($_REQUEST['dn'])) {
-    $dn = "";
-  }else{
-    $dn = $_REQUEST['dn'];
-    #$dn = 'cn=bar foo, ou=contacts, o=cosmocode, c=de';
-  }
-
-  //save data if asked for
-  if($_SESSION['ldapab']['username'] && !empty($_REQUEST['save']) && $_REQUEST['save']){
-    // prepare special data
-    $_REQUEST['entry']['photo']  = _getUploadData();
-    $_REQUEST['entry']['marker'] = explode(',',$_REQUEST['entry']['markers']);
-    unset($_REQUEST['entry']['markers']);
-
-    foreach(array_keys($_REQUEST['entry']) as $field){
-        if($FIELDS['_'.$field]){
-            // entry has to be handled as array -> clean it up (trim, unique, sort)
-            $_REQUEST['entry'][$field] = array_map('trim',$_REQUEST['entry'][$field]);
-            $_REQUEST['entry'][$field] = array_unique($_REQUEST['entry'][$field]);
-            $_REQUEST['entry'][$field] = array_filter($_REQUEST['entry'][$field]);
-            natcasesort($_REQUEST['entry'][$field]);
-        }
-    }
-    $dn = _saveData();
+<?php
+require_once('inc/init.php');
+ldap_login();
+
+$users = get_users();
+
+//select template to use
+if (empty($_REQUEST['mode'])) { $_REQUEST['mode']='show'; }
+if( $_SESSION['ldapab']['username'] &&
+   ($_REQUEST['mode']=='edit' || $_REQUEST['mode']=='copy')){
+  $template='entry_edit.tpl';
+}elseif($_REQUEST['mode']=='vcf'){
+  $template='entry_vcf.tpl';
+}else{
+  $template='entry_show.tpl';
+}
+
+if (empty($_REQUEST['dn'])) {
+  $dn = "";
+}else{
+  $dn = $_REQUEST['dn'];
+  #$dn = 'cn=bar foo, ou=contacts, o=cosmocode, c=de';
+}
+
+//save data if asked for
+if($_SESSION['ldapab']['username'] && !empty($_REQUEST['save']) && $_REQUEST['save']){
+  // prepare special data
+  $_REQUEST['entry']['photo']  = _getUploadData();
+  $_REQUEST['entry']['marker'] = explode(',',$_REQUEST['entry']['markers']);
+  unset($_REQUEST['entry']['markers']);
+
+  foreach(array_keys($_REQUEST['entry']) as $field){
+      if($FIELDS['_'.$field]){
+          // entry has to be handled as array -> clean it up (trim, unique, sort)
+          $_REQUEST['entry'][$field] = array_map('trim',$_REQUEST['entry'][$field]);
+          $_REQUEST['entry'][$field] = array_unique($_REQUEST['entry'][$field]);
+          $_REQUEST['entry'][$field] = array_filter($_REQUEST['entry'][$field]);
+          natcasesort($_REQUEST['entry'][$field]);
+      }
   }
+  $dn = _saveData();
+}
 
-  if(empty($dn)){
-    if(!$_REQUEST['mode']=='edit'){
-      $smarty->assign('error','No dn was given');
-      $template = 'error.tpl';
-    }
-  }elseif(!empty($_REQUEST['del']) && $_REQUEST['del']){
-    _delEntry($dn);
-  }elseif(!_fetchData($dn)){
-    $smarty->assign('error',"The requested entry '$dn' was not found");
+if(empty($dn)){
+  if(!$_REQUEST['mode']=='edit'){
+    $smarty->assign('error','No dn was given');
     $template = 'error.tpl';
   }
-
-  //prepare templates
-  $smarty->assign('dn',$dn);
-  $smarty->assign('managers',$users);
-  tpl_std();
-  tpl_orgs();
-  tpl_markers();
-  tpl_categories();
-  tpl_timezone();
-  tpl_country();
-  //display templates
-  if($_REQUEST['mode']=='vcf'){
-    $entry = $smarty->get_template_vars('entry');
-    $filename = $entry['givenname'].'_'.$entry['name'].'.vcf';
-    header("Content-Disposition: attachment; filename=\"$filename\"");
-    header("Content-type: text/x-vcard; name=\"$filename\"; charset=utf-8");
-    $smarty->display($template);
-  }else{
-    header('Content-Type: text/html; charset=utf-8');
-    $smarty->display($template);
+}elseif(!empty($_REQUEST['del']) && $_REQUEST['del']){
+  _delEntry($dn);
+}elseif(!_fetchData($dn)){
+  $smarty->assign('error',"The requested entry '$dn' was not found");
+  $template = 'error.tpl';
+}
+
+//prepare templates
+$smarty->assign('dn',$dn);
+$smarty->assign('managers',$users);
+tpl_std();
+//display templates
+if($_REQUEST['mode']=='vcf'){
+  $entry = $smarty->get_template_vars('entry');
+  $filename = $entry['givenname'].'_'.$entry['name'].'.vcf';
+  header("Content-Disposition: attachment; filename=\"$filename\"");
+  header("Content-type: text/x-vcard; name=\"$filename\"; charset=utf-8");
+  $smarty->display($template);
+}else{
+  header('Content-Type: text/html; charset=utf-8');
+  $smarty->display($template);
+}
+
+//--------------------------------------------------------------
+
+/**
+ * fetches the Data from the LDAP directory and assigns it to
+ * the global smarty object using tpl_entry()
+ */
+function _fetchData($dn){
+  global $LDAP_CON;
+  global $conf;
+  global $smarty;
+  global $users; //contains the users for manager role
+
+  $sr = ldap_search($LDAP_CON,$dn,'(objectClass=inetOrgPerson)');
+  if(!ldap_count_entries($LDAP_CON,$sr)){
+    return false;
   }
+  $result = ldap_get_binentries($LDAP_CON, $sr);
+  $entry  = $result[0];
 
-  //--------------------------------------------------------------
-
-  /**
-   * fetches the Data from the LDAP directory and assigns it to
-   * the global smarty object using tpl_entry()
-   */
-  function _fetchData($dn){
-    global $LDAP_CON;
-    global $conf;
-    global $smarty;
-    global $users; //contains the users for manager role
-
-    $sr = ldap_search($LDAP_CON,$dn,'(objectClass=inetOrgPerson)');
-    if(!ldap_count_entries($LDAP_CON,$sr)){
-      return false;
-    }
-    $result = ldap_get_binentries($LDAP_CON, $sr);
-    $entry  = $result[0];
-
-    //remove dn from entry when copy
-    if(!empty($_REQUEST['mode']) && $_REQUEST['mode'] == 'copy'){
-      $entry['dn']='';
-    }
+  //remove dn from entry when copy
+  if(!empty($_REQUEST['mode']) && $_REQUEST['mode'] == 'copy'){
+    $entry['dn']='';
+  }
 
-    //assign entry to template:
-    tpl_entry($entry);
+  //assign entry to template:
+  tpl_entry($entry);
 
 /*print '<pre>';
 print_r($entry);
 print '</pre>';*/
 
-    // make username from dn for manager:
-    if (empty($entry['manager'])) { $entry['manager']=array(""); }
-    if (empty($users[$entry['manager'][0]])) { $users[$entry['manager'][0]]=''; }
-    $smarty->assign('managername',$users[$entry['manager'][0]]);
-    return true;
+  // make username from dn for manager:
+  if (empty($entry['manager'])) { $entry['manager']=array(""); }
+  if (empty($users[$entry['manager'][0]])) { $users[$entry['manager'][0]]=''; }
+  $smarty->assign('managername',$users[$entry['manager'][0]]);
+  return true;
+}
+
+/**
+ * saves the data from $_REQUEST['entry'] to the LDAP directory
+ *
+ * returns given or constructed dn
+ */
+function _saveData(){
+  global $LDAP_CON;
+  global $conf;
+  global $FIELDS;
+  global $OCLASSES;
+
+  $entry = $_REQUEST['entry'];
+  $dn    = $_REQUEST['dn'];
+  //construct new dn
+  $now    = time();
+  $newdn  = 'uid='.$now;
+  if (empty($_REQUEST['type'])) { $_REQUEST['type']='public'; }
+  if($_REQUEST['type'] == 'private'){
+    $newdn .= ', '.$conf['privatebook'].', '.$_SESSION['ldapab']['binddn'];
+  }else{
+    $newdn .= ', '.$conf['publicbook'];
   }
-
-  /**
-   * saves the data from $_REQUEST['entry'] to the LDAP directory
-   *
-   * returns given or constructed dn
-   */
-  function _saveData(){
-    global $LDAP_CON;
-    global $conf;
-    global $FIELDS;
-    global $OCLASSES;
-
-    $entry = $_REQUEST['entry'];
-    $dn    = $_REQUEST['dn'];
-    //construct new dn
-    $now    = time();
-    $newdn  = 'uid='.$now;
-    if (empty($_REQUEST['type'])) { $_REQUEST['type']='public'; }
-    if($_REQUEST['type'] == 'private'){
-      $newdn .= ', '.$conf['privatebook'].', '.$_SESSION['ldapab']['binddn'];
-    }else{
-      $newdn .= ', '.$conf['publicbook'];
-    }
-    $entry['displayname'] = $entry['givenname'].' '.$entry['name'];;
-    $entry = prepare_ldap_entry($entry);
+  $entry['displayname'] = $entry['givenname'].' '.$entry['name'];;
+  $entry = prepare_ldap_entry($entry);
 
 /*
 print '<pre>';
@@ -143,68 +138,68 @@ print_r($entry);
 print '</pre>';
 */
 
-    if(empty($dn)){
-      //new entry
-      $entry['uid'][] = $now;
-      $r = ldap_add($LDAP_CON,$newdn,$entry);
-      tpl_ldaperror();
-      return $newdn;
-    }else{
-      // update the objectClasses
-      ldap_store_objectclasses($dn,$OCLASSES);
-      unset($entry['objectclass']);
-
-      //modify entry attribute by attribute - this ensure we don't delete unknown stuff
-      foreach (array_values($FIELDS) as $key){
-        if($key == 'dn'){
+  if(empty($dn)){
+    //new entry
+    $entry['uid'][] = $now;
+    $r = ldap_add($LDAP_CON,$newdn,$entry);
+    tpl_ldaperror();
+    return $newdn;
+  }else{
+    // update the objectClasses
+    ldap_store_objectclasses($dn,$OCLASSES);
+    unset($entry['objectclass']);
+
+    //modify entry attribute by attribute - this ensure we don't delete unknown stuff
+    foreach (array_values($FIELDS) as $key){
+      if($key == 'dn'){
+        continue;
+      }elseif(empty($entry[$key])){
+        // field is empty -> handle deletion (except for photo unless deletion triggered)
+        if (empty($_REQUEST['delphoto'])) { $_REQUEST['delphoto']=0; }
+        if($key == 'jpegPhoto' && !$_REQUEST['delphoto']){
           continue;
-        }elseif(empty($entry[$key])){
-          // field is empty -> handle deletion (except for photo unless deletion triggered)
-          if (empty($_REQUEST['delphoto'])) { $_REQUEST['delphoto']=0; }
-          if($key == 'jpegPhoto' && !$_REQUEST['delphoto']){
-            continue;
-          }
-          unset($del);
-          $del[$key]=array();
-          $r = @ldap_mod_replace($LDAP_CON,$dn,$del);
-          tpl_ldaperror("del $key");
-        }else{
-          unset($add);
-          $add[$key]=$entry[$key];
-          $r = @ldap_mod_replace($LDAP_CON,$dn,$add);
-          tpl_ldaperror("mod $key");
         }
+        unset($del);
+        $del[$key]=array();
+        $r = @ldap_mod_replace($LDAP_CON,$dn,$del);
+        tpl_ldaperror("del $key");
+      }else{
+        unset($add);
+        $add[$key]=$entry[$key];
+        $r = @ldap_mod_replace($LDAP_CON,$dn,$add);
+        tpl_ldaperror("mod $key");
       }
-      return $dn;
     }
+    return $dn;
   }
-
-  /**
-   * does as the name says - delete the whole entry
-   */
-  function _delEntry($dn){
-    global $LDAP_CON;
-    if(ldap_full_delete($LDAP_CON,$dn,true)){
-      header("Location: index.php");
-      exit;
-    }
+}
+
+/**
+ * does as the name says - delete the whole entry
+ */
+function _delEntry($dn){
+  global $LDAP_CON;
+  if(ldap_full_delete($LDAP_CON,$dn,true)){
+    header("Location: index.php");
+    exit;
   }
-
-  /**
-   * gets the binary data from an uploaded file
-   */
-  function _getUploadData(){
-    $file = $_FILES['photoupload'];
-
-    if (is_uploaded_file($file['tmp_name'])) {
-      if(preg_match('=image/p?jpe?g=',$file['type'])){
-        $fh = fopen($file['tmp_name'],'r');
-        $data = fread($fh,$file['size']);
-        fclose($fh);
-        unlink($file['tmp_name']);
-        return $data;
-      }
+}
+
+/**
+ * gets the binary data from an uploaded file
+ */
+function _getUploadData(){
+  $file = $_FILES['photoupload'];
+
+  if (is_uploaded_file($file['tmp_name'])) {
+    if(preg_match('=image/p?jpe?g=',$file['type'])){
+      $fh = fopen($file['tmp_name'],'r');
+      $data = fread($fh,$file['size']);
+      fclose($fh);
+      unlink($file['tmp_name']);
+      return $data;
     }
-    return '';
   }
+  return '';
+}
 
diff --git a/fields.php b/fields.php
deleted file mode 100644 (file)
index 8f3d3c3..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-<?php
-/**
- * Configures fieldname - LDAP attribute associations
- *
- * If you use other attributes you may change the assignments here.
- * Note the arrays need to remain flippable, eg. both sides have to
- * be unique
- *
- * Fields starting with a * may contain multiple values (needs to be
- * handled by the template as well)
- */
-
-
-/**
- * The object classes to store with contacts
- */
-$OCLASSES[] = 'inetOrgPerson';
-
-/**
- * The standard fields suported by OpenLDAP's default schemas
- */
-$FIELDS = array(
-    'dn'           => 'dn',                          // don't touch!
-    'name'         => 'sn',
-    'displayname'  => 'cn',
-    'givenname'    => 'givenName',
-    'title'        => 'title',
-    'organization' => 'o',                           // aka. company
-    'office'       => 'physicalDeliveryOfficeName',
-    'street'       => 'postalAddress',
-    'zip'          => 'postalCode',
-    'location'     => 'l',                           // aka. city
-    'phone'        => 'telephoneNumber',
-    'fax'          => 'facsimileTelephoneNumber',
-    'mobile'       => 'mobile',                      // aka. cell phone
-    'pager'        => 'pager',
-    'homephone'    => 'homePhone',
-    'homestreet'   => 'homePostalAddress',
-    'photo'        => 'jpegPhoto',
-    'url'          => 'labeledURI',
-    'note'         => 'description',
-    'manager'      => 'manager',                     // aka. key account
-    '_mail'        => 'mail',
-);
-
-/**
- * If the provided "extended" schema is used the following fields
- * and object classes are added
- */
-$OCLASSES[] = 'contactPerson';
-$FIELDS['anniversary']  = 'anniversary';
-$FIELDS['_marker']      = 'marker';                  // aka. tags
-
-/**
- * If the open exchange schema is used the following fields
- * and object classes are added
- */
-/* comment in if you want to use it
-$OCLASSES[] = 'OXUserObject';
-$FIELDS['country']          = 'userCountry';
-$FIELDS['birthday']         = 'birthDay';
-$FIELDS['ipphone']          = 'IPPhone';
-$FIELDS['_marker']          = 'OXUserCategories';
-$FIELDS['instantmessenger'] = 'OXUserInstantMessenger';
-$FIELDS['timezone']         = 'OXTimeZone';
-$FIELDS['position']         = 'OXUserPosition';
-$FIELDS['certificate']      = 'relClientCert';
-$FIELDS['domain']           = 'domain';
-*/
-
-/**
- * If the Evolution schema is used the following fields
- * and object classes are added
- */
-/* comment in if you want to use it
-$OCLASSES[] = 'evolutionPerson';
-$OCLASSES[] = 'officePerson';
-$FIELDS['department']  = 'ou';
-$FIELDS['state']       = 'st';
-$FIELDS['country']     = 'c';
-$FIELDS['phone']       = 'primaryPhone';
-$FIELDS['switchboard'] = 'companyPhone';
-$FIELDS['note']        = 'note';
-$FIELDS['manager']     = 'seeAlso';
-$FIELDS['birthday']    = 'birthDate';
-$FIELDS['spouse']      = 'spouseName';
-*/
-
-
-/**
- * Flip the array
- */
-$RFIELDS = array_flip($FIELDS);
-
diff --git a/functions.php b/functions.php
deleted file mode 100644 (file)
index 9166d31..0000000
+++ /dev/null
@@ -1,486 +0,0 @@
-<?php
-
-/**
- * assigns some standard variables to smarty templates
- */
-function smarty_std(){
-  global $smarty;
-  $smarty->assign('USER',$_SESSION['ldapab']['username']);
-}
-
-/**
- * Uses Username and Password from Session to initialize the LDAP handle
- * If it fails it redirects to login.php
- */
-function ldap_login(){
-  global $conf;
-  if(!empty($_SESSION['ldapab']['username'])){
-    // existing session! Check if valid
-    if($_SESSION['ldapab']['browserid'] != auth_browseruid()){
-      //session hijacking detected
-      header('Location: login.php?username=');
-      exit;
-    }
-  } elseif ($conf['httpd_auth'] && !empty($_SERVER['PHP_AUTH_USER'])) {
-    // use HTTP auth if wanted and possible
-    $_SESSION['ldapab']['username'] = $_SERVER['PHP_AUTH_USER'];
-    $_SESSION['ldapab']['password'] = $_SERVER['PHP_AUTH_PW'];
-  } elseif (!empty($_COOKIE['ldapabauth'])) {
-    // check persistent cookie
-    $cookie = base64_decode($_COOKIE['ldapabauth']);
-    $cookie = x_Decrypt($cookie,get_cookie_secret());
-    list($u,$p) = unserialize($cookie);
-    $_SESSION['ldapab']['username'] = $u;
-    $_SESSION['ldapab']['password'] = $p;
-  }
-
-  if(empty($_SESSION['ldapab']) ||
-     !do_ldap_bind($_SESSION['ldapab']['username'],
-                   $_SESSION['ldapab']['password'],
-                   $_SESSION['ldapab']['binddn'])){
-    header('Location: login.php?username=');
-    exit;
-  }
-}
-
-/**
- * Creates a global LDAP connection handle called $LDAP_CON
- */
-function do_ldap_bind($user,$pass,$dn=""){
-  global $conf;
-  global $LDAP_CON;
-
-  //create global connection to LDAP if necessary
-  if(!$LDAP_CON){
-    if (!empty($conf['ldapurl'])){
-      $LDAP_CON = ldap_connect($conf['ldapurl']);
-    }else{
-      $LDAP_CON = ldap_connect($conf['ldapserver'],$conf['ldapport']);
-    }
-    if(!$LDAP_CON){
-      die("couldn't connect to LDAP server");
-    }
-  }
-
-  if($conf['ldapv3']) ldap_set_option($LDAP_CON, LDAP_OPT_PROTOCOL_VERSION, 3);
-
-  if(empty($dn)){
-    //anonymous bind to lookup users
-    //blank binddn or blank bindpw will result in anonymous bind
-    if(!ldap_bind($LDAP_CON,$conf['anonbinddn'],$conf['anonbindpw'])){
-      die("can not bind for user lookup");
-    }
-
-    //when no user was given stay connected anonymous
-    if(empty($user)){
-      set_session('','','');
-      return true;
-    }
-
-    //get dn for given user
-    $filter = str_replace('%u',$user,$conf['userfilter']);
-    $sr = ldap_search($LDAP_CON, $conf['usertree'], $filter);;
-    $result = ldap_get_entries($LDAP_CON, $sr);
-    if($result['count'] != 1){
-      set_session('','','');
-      return false;
-    }
-    $dn = $result[0]['dn'];
-  }
-
-  //bind with dn
-  if(ldap_bind($LDAP_CON,$dn,$pass)){
-    //bind successful -> set up session
-    set_session($user,$pass,$dn);
-    return true;
-  }
-  //bind failed -> remove session
-  set_session('','','');
-  return false;
-}
-
-/**
- * Builds a pseudo UID from browser and IP data
- *
- * This is neither unique nor unfakable - still it adds some
- * security. Using the first part of the IP makes sure
- * proxy farms like AOLs are stil okay.
- *
- * @author  Andreas Gohr <andi@splitbrain.org>
- *
- * @return  string  a MD5 sum of various browser headers
- */
-function auth_browseruid(){
-  $uid  = '';
-  if (empty($_SERVER['HTTP_USER_AGENT']))      { $_SERVER['HTTP_USER_AGENT']='USER_AGENT'; }
-  if (empty($_SERVER['HTTP_ACCEPT_ENCODING'])) { $_SERVER['HTTP_ACCEPT_ENCODING']='ACCEPT_ENCODING'; }
-  if (empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { $_SERVER['HTTP_ACCEPT_LANGUAGE']='ACCEPT_LANGUAGE'; }
-  if (empty($_SERVER['HTTP_ACCEPT_CHARSET']))  { $_SERVER['HTTP_ACCEPT_CHARSET']='ACCEPT_CHARSET'; }
-  $uid .= $_SERVER['HTTP_USER_AGENT'];
-  $uid .= $_SERVER['HTTP_ACCEPT_ENCODING'];
-  $uid .= $_SERVER['HTTP_ACCEPT_LANGUAGE'];
-  $uid .= $_SERVER['HTTP_ACCEPT_CHARSET'];
-  $uid .= substr($_SERVER['REMOTE_ADDR'],0,strpos($_SERVER['REMOTE_ADDR'],'.'));
-  return md5($uid);
-}
-
-
-/**
- * saves user data to Session and cookies
- */
-function set_session($user,$pass,$dn){
-  global $conf;
-
-  $rand = rand();
-  $_SESSION['ldapab']['username']  = $user;
-  $_SESSION['ldapab']['binddn']    = $dn;
-  $_SESSION['ldapab']['password']  = $pass;
-  $_SESSION['ldapab']['browserid'] = auth_browseruid();
-
-  // (re)set the persistent auth cookie
-  if($user == ''){
-    setcookie('ldapabauth','',time()+60*60*24*365);
-  }elseif(!empty($_REQUEST['remember'])){
-    $cookie = serialize(array($user,$pass));
-    $cookie = x_Encrypt($cookie,get_cookie_secret());
-    $cookie = base64_encode($cookie);
-    setcookie('ldapabauth',$cookie,time()+60*60*24*365);
-  }
-}
-
-/**
- * Creates a random string to encrypt persistent auth
- * cookies; the string is stored inside the cache dir
- */
-function get_cookie_secret(){
-  $file = dirname(__FILE__).'/cache/.htcookiesecret.php';
-  if(@file_exists($file)){
-    return md5(trim(file($file)));
-  }
-
-  $secret = '<?php #'.(rand()*time()).'?>';
-  if(!$fh = fopen($file,'w')) die("Couldn't write to $file");
-  if(fwrite($fh, $secret) === FALSE) die("Couldn't write to $file");
-  fclose($fh);
-
-  return md5($secret);
-}
-
-/**
- * binary safe function to get all search result data.
- * It will use ldap_get_values_len() instead and build the array
- * note: it's similar with the array returned by ldap_get_entries()
- * except it has no "count" elements
- *
- * @author: Original code by Ovidiu Geaboc <ogeaboc@rdanet.com>
- */
-function ldap_get_binentries($conn,$srchRslt){
-  if(!@ldap_count_entries($conn,$srchRslt)){
-    return null;
-  }
-  $entry = ldap_first_entry($conn, $srchRslt);
-  $i=0;
-  do {
-    $dn = ldap_get_dn($conn,$entry);
-    $attrs = ldap_get_attributes($conn, $entry);
-    for($j=0; $j<$attrs['count']; $j++) {
-      $vals = ldap_get_values_len($conn, $entry,$attrs[$j]);
-      for($k=0; $k<$vals['count']; $k++){
-        $data[$i][$attrs[$j]][$k]=$vals[$k];
-      }
-    }
-    $data[$i]['dn']=$dn;
-    $i++;
-  }while ($entry = ldap_next_entry($conn, $entry));
-
-  return $data;
-}
-
-
-/**
- * loads ldap names and their cleartext meanings from
- * entries.conf file and returns it as hash
- */
-function namedentries($flip=false){
-    trigger_error('deprecated namedentries called',E_USER_WARNING);
-}
-
-/**
- * Creates an array for submission to ldap from websitedata
- */
-function prepare_ldap_entry($in){
-  global $conf;
-  global $FIELDS;
-  global $OCLASSES;
-
-  //check dateformats
-  if(!preg_match('/\d\d\d\d-\d\d-\d\d/',$in['anniversary'])) $in['anniversary']='';
-  if(!preg_match('/\d\d\d\d-\d\d-\d\d/',$in['birthday'])) $in['birthday']='';
-
-  // we map all internal names to the configured LDAP attributes here
-  foreach($in as $key => $value){
-    if($FIELDS[$key]){
-        // normal mapped field
-        $out[$FIELDS[$key]][] = $value;
-    }elseif($FIELDS["_$key"]){
-        // mapped multi field
-        if(is_array($value)){
-            $out[$FIELDS["_$key"]] = $value;
-        }else{
-            $out[$FIELDS["_$key"]][] = $value; //shouldn't happen, but to be sure
-        }
-    }else{
-        // no mapping found - assume it to be a LDAP attribute (shouldn't happen)
-        if(is_array($value)){
-            $out[$key] = $value;
-        }else{
-            $out[$key][] = $value;
-        }
-    }
-  }
-
-  // add the Objectclasses
-  $out['objectclass'] = $OCLASSES;
-
-  return clear_array($out);
-}
-
-/**
- * remove empty element from arrays recursively
- *
- * @author Original by <xntx@msn.com>
- */
-function clear_array ( $a ) {
-  if ($a !== array()) {
-    $b = array();
-    foreach ( $a as $key => $value ) {
-        if (is_array($value)) {
-          if (clear_array($value) !== false) {
-            $b[$key] = clear_array ( $value );
-          }
-        } elseif ($value !== '') {
-          $b[$key] = $value;
-        }
-    }
-    if ($b !== array()) {
-        return $b;
-    } else {
-        return false;
-    }
-  } else {
-    return false;
-  }
-}
-
-/**
- * deletes an entryfrom ldap - optional with recursion
- *
- * @author Original by <gabriel@hrz.uni-marburg.de>
- */
-function ldap_full_delete($ds,$dn,$recursive=false){
-  if($recursive == false){
-    return(ldap_delete($ds,$dn));
-  }else{
-    //searching for sub entries
-    $sr=ldap_list($ds,$dn,"ObjectClass=*",array(""));
-    $info = ldap_get_entries($ds, $sr);
-    for($i=0;$i<$info['count'];$i++){
-      //deleting recursively sub entries
-      $result=myldap_delete($ds,$info[$i]['dn'],$recursive);
-      if(!$result){
-        //return result code, if delete fails
-        return($result);
-      }
-    }
-    return(ldap_delete($ds,$dn));
-  }
-}
-
-/**
- * Returns all User Accounts as assoziative array
- */
-function get_users(){
-  global $conf;
-  global $LDAP_CON;
-
-  $sr = ldap_list($LDAP_CON,$conf['usertree'],"ObjectClass=inetOrgPerson");
-  $result = ldap_get_binentries($LDAP_CON, $sr);
-  $users = array();
-  if(count($result)){
-    foreach ($result as $entry){
-      if(!empty($entry['sn'][0])){
-        $users[$entry['dn']] = $entry['givenName'][0]." ".$entry['sn'][0];
-      }
-    }
-  }
-  return $users;
-}
-
-/**
- * makes sure the given DN contains exactly one space
- * after each ,
- */
-function normalize_dn($dn){
-  $dn = preg_replace('/,/',', ',$dn);
-  $dn = preg_replace('/,\s+/',', ',$dn);
-  return $dn;
-}
-
-/**
- * Merges the given classes with the existing ones
- */
-function ldap_store_objectclasses($dn,$classes){
-  global $conf;
-  global $LDAP_CON;
-
-  $sr     = ldap_search($LDAP_CON,$dn,"objectClass=*",array('objectClass'));
-  $result = ldap_get_binentries($LDAP_CON, $sr);
-  $set    = $result[0]['objectClass'];
-  $set    = array_unique_renumber(array_merge((array)$set,(array)$classes));
-  $add['objectClass'] = $set;
-
-  $r = @ldap_mod_replace($LDAP_CON,$dn,$add);
-  tpl_ldaperror();
-
-/*  print '<pre>';
-  print_r($set);
-  print '</pre>';*/
-}
-
-/**
- * Escape a string to be used in a LDAP filter
- *
- * Ported from Perl's Net::LDAP::Util escape_filter_value
- *
- * @author Andreas Gohr <andi@splitbrain.org>
- */
-function ldap_filterescape($string){
-  return preg_replace('/([\x00-\x1F\*\(\)\\\\])/e',
-                            '"\\\\\".join("",unpack("H2","$1"))',
-                            $string);
-}
-
-/**
- * Queries public and private addressbooks, combining the
- * results
- *
- * @todo This function should be used where ever possible, replacing
- *       lots of duplicate code
- */
-function ldap_queryabooks($filter,$types){
-  global $conf;
-  global $LDAP_CON;
-
-  // make sure $types is an array
-  if(!is_array($types)){
-    $types = explode(',',$types);
-    $types = array_map('trim',$types);
-  }
-
-  $results = array();
-  $result1 = array();
-  $result2 = array();
-
-  // public addressbook
-  $sr      = ldap_list($LDAP_CON,$conf['publicbook'],
-                       $filter,$types);
-  $result1 = ldap_get_binentries($LDAP_CON, $sr);
-  ldap_free_result($sr);
-
-  // private addressbook
-  if(!empty($_SESSION['ldapab']['binddn'])){
-    $sr      = @ldap_list($LDAP_CON,$conf['privatebook'].
-                          ','.$_SESSION['ldapab']['binddn'],
-                          $filter,$types);
-    $result2 = ldap_get_binentries($LDAP_CON, $sr);
-  }
-
-  // return merged results
-  return array_merge((array)$result1,(array)$result2);
-}
-
-/**
- * Makes array unique and renumbers the entries
- *
- * @author <kay_rules@yahoo.com>
- */
-function array_unique_renumber($somearray){
-   $tmparr = array_unique($somearray);
-   $i=0;
-   foreach ($tmparr as $v) {
-       $newarr[$i] = $v;
-       $i++;
-   }
-   return $newarr;
-}
-
-/**
- * Simple XOR encryption
- *
- * @author Dustin Schneider
- * @link http://www.phpbuilder.com/tips/item.php?id=68
- */
-function x_Encrypt($string, $key){
-    for($i=0; $i<strlen($string); $i++){
-        for($j=0; $j<strlen($key); $j++){
-            $string[$i] = $string[$i]^$key[$j];
-        }
-    }
-    return $string;
-}
-
-/**
- * Simple XOR decryption
- *
- * @author Dustin Schneider
- * @link http://www.phpbuilder.com/tips/item.php?id=68
- */
-function x_Decrypt($string, $key){
-    for($i=0; $i<strlen($string); $i++){
-        for($j=0; $j<strlen($key); $j++){
-            $string[$i] = $key[$j]^$string[$i];
-        }
-    }
-    return $string;
-}
-
-/**
- * Decodes UTF8 recursivly for the given array
- *
- * @deprecated
- */
-function utf8_decode_array(&$array) {
-  trigger_error('deprecated utf8_decode_array called',E_USER_WARNING);
-
-  foreach (array_keys($array) as $key) {
-    if($key === 'dn') continue;
-    if($key === 'jpegPhoto') continue;
-    if (is_array($array[$key])) {
-      utf8_decode_array($array[$key]);
-    }else {
-      $array[$key] = utf8_decode($array[$key]);
-    }
-  }
-}
-
-/**
- * Encodes the given array to UTF8 recursively
- *
- * @deprecated
- */
-function utf8_encode_array(&$array) {
-  trigger_error('deprecated utf8_encode_array called',E_USER_WARNING);
-
-  foreach (array_keys($array) as $key) {
-    if($key === 'dn') continue;
-    if($key === 'jpegPhoto') continue;
-    if (is_array($array[$key])) {
-      utf8_encode_array($array[$key]);
-    }else {
-      $array[$key] = utf8_encode($array[$key]);
-    }
-  }
-}
-
-
-?>
index dd933da204bcc2a1746e90e7e5fca3e38679566b..3efcf4dcd16d77b82310663b7d4a8c877a0c1d29 100644 (file)
--- a/help.php
+++ b/help.php
@@ -1,11 +1,11 @@
-<?
-  require_once('init.php');
-  ldap_login();
+<?php
+require_once('inc/init.php');
+ldap_login();
 
-  //prepare templates
-  tpl_std();
-  //display templates
-  header('Content-Type: text/html; charset=utf-8');
-  $smarty->display('help.tpl');
+//prepare templates
+tpl_std();
+//display templates
+header('Content-Type: text/html; charset=utf-8');
+$smarty->display('help.tpl');
 
 ?>
diff --git a/img.php b/img.php
index eeb44713e46bf1b984a66d686a8fcb8ef4c95e5c..27a49b6c90ea1b0a624c5a304da3b4f79c1bb15c 100644 (file)
--- a/img.php
+++ b/img.php
@@ -1,16 +1,16 @@
-<?
-  require_once('init.php');
-  ldap_login();
+<?php
+require_once('inc/init.php');
+ldap_login();
 
-  $dn = $_REQUEST['dn'];
+$dn = $_REQUEST['dn'];
 
-  $sr = ldap_search($LDAP_CON,$dn,'(objectClass=inetOrgPerson)',array('jpegPhoto'));
-  if(!ldap_count_entries($LDAP_CON,$sr)){
-    exit;
-  }
-  $result = ldap_get_binentries($LDAP_CON, $sr);
-  $entry  = $result[0];
+$sr = ldap_search($LDAP_CON,$dn,'(objectClass=inetOrgPerson)',array('jpegPhoto'));
+if(!ldap_count_entries($LDAP_CON,$sr)){
+  exit;
+}
+$result = ldap_get_binentries($LDAP_CON, $sr);
+$entry  = $result[0];
 
-  header("Content-type: image/jpeg");
-  print $entry['jpegPhoto'][0];
+header("Content-type: image/jpeg");
+print $entry['jpegPhoto'][0];
 ?>
index c26e85c08be9747964ecac06eb2a5781ce441ccf..de4d3a25055ad023e4c15558c332e13a8a902036 100644 (file)
 <?
-  require_once('init.php');
-  require_once('Contact_Vcard_Parse.php');
-  require_once('xml.php');
-  ldap_login();
+require_once('inc/init.php');
+require_once('inc/Contact_Vcard_Parse.php');
+ldap_login();
 
-  if(! $_SESSION['ldapab']['username'] ){
-    header("Location: login.php");
-    exit;
-  }
+if(! $_SESSION['ldapab']['username'] ){
+  header("Location: login.php");
+  exit;
+}
 
-  $error = '';
-  if(isset($_FILES['userfile'])){
-    if (is_uploaded_file($_FILES['userfile']['tmp_name'])){
-      if(preg_match('/\.vcf$/i', $_FILES['userfile']['name'])){
-        //parse VCF
-        $vcfparser = new Contact_Vcard_Parse();
-        $vcards    = $vcfparser->fromFile($_FILES['userfile']['tmp_name']);
-      }elseif(preg_match('/^addressbook\.xml$/i', $_FILES['userfile']['name'])){
-        //parse Zaurus Addressbook
-        $contacts  = XML_unserialize(@join('',@file($_FILES['userfile']['tmp_name'])));
-      }else{
-          $error = "Only *.vcf or addressbook.xml are accepted";
-      }
+$error = '';
+if(isset($_FILES['userfile'])){
+  if (is_uploaded_file($_FILES['userfile']['tmp_name'])){
+    if(preg_match('/\.vcf$/i', $_FILES['userfile']['name'])){
+      //parse VCF
+      $vcfparser = new Contact_Vcard_Parse();
+      $vcards    = $vcfparser->fromFile($_FILES['userfile']['tmp_name']);
     }else{
-      switch($_FILES['userfile']['error']){
-       case 0: //no error; possible file attack!
-         $error = "There was a problem with your upload.";
-         break;
-       case 1: //uploaded file exceeds the upload_max_filesize directive in php.ini
-         $error = "The file you are trying to upload is too big.";
-         break;
-       case 2: //uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form
-         $error = "The file you are trying to upload is too big.";
-         break;
-       case 3: //uploaded file was only partially uploaded
-         $error = "The file you are trying upload was only partially uploaded.";
-         break;
-       case 4: //no file was uploaded
-         $error = "You must select a VCF file for upload.";
-         break;
-       default: //a default error, just in case!  :)
-         $error = "There was a problem with your upload.";
-         break;
-      }
-    }
-  }
-
-  //prepare templates for all found entries
-  $list = '';
-  if(count($vcards)){
-    foreach ($vcards as $vcard){
-      $entry = vcard_entry($vcard);
-      $smarty->clear_all_assign();
-      tpl_std();
-      $smarty->assign('entry',$entry);
-      $list .= $smarty->fetch('import_entry.tpl');
+        $error = "Only *.vcf accepted";
     }
-  }elseif(count($contacts)){
-    foreach ($contacts['AddressBook']['Contacts']['Contact'] as $contact){
-      if (!is_array($contact)) continue;
-      $entry = zaurus_entry($contact);
-      $smarty->clear_all_assign();
-      tpl_std();
-      $smarty->assign('entry',$entry);
-      $list .= $smarty->fetch('import_entry.tpl');
+  }else{
+    switch($_FILES['userfile']['error']){
+     case 0: //no error; possible file attack!
+       $error = "There was a problem with your upload.";
+       break;
+     case 1: //uploaded file exceeds the upload_max_filesize directive in php.ini
+       $error = "The file you are trying to upload is too big.";
+       break;
+     case 2: //uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form
+       $error = "The file you are trying to upload is too big.";
+       break;
+     case 3: //uploaded file was only partially uploaded
+       $error = "The file you are trying upload was only partially uploaded.";
+       break;
+     case 4: //no file was uploaded
+       $error = "You must select a VCF file for upload.";
+       break;
+     default: //a default error, just in case!  :)
+       $error = "There was a problem with your upload.";
+       break;
     }
   }
+}
 
-  //prepare templates
-  tpl_std();
-  tpl_orgs();
-  tpl_markers();
-  $smarty->assign('error',$error);
-  $smarty->assign('list',$list);
-  //display templates
-  $smarty->display('header.tpl');
-  $smarty->display('import.tpl');
-  $smarty->display('footer.tpl');
-
+//prepare templates for all found entries
+$list = '';
+if(count($vcards)){
+  foreach ($vcards as $vcard){
+    $entry = vcard_entry($vcard);
+    $smarty->clear_all_assign();
+    tpl_std();
+    $smarty->assign('entry',$entry);
+    $list .= $smarty->fetch('import_entry.tpl');
+  }
+}
 
-function zaurus_entry($cnct){
-  $entry['name']         = $cnct['LastName'];
-  $entry['givenname']    = trim($cnct['FirstName'].' '.$cnct['MiddleName']);
-  $entry['title']        = $cnct['JobTitle'];
-  $entry['organization'] = $cnct['Company'];
-  $entry['office']       = $cnct['Office'];
-  $entry['note']         = $cnct['Notes'];
-  $entry['mail']         = split(' ',$cnct['Emails']);
-  $entry['street']       = $cnct['BusinessStreet'];
-  $entry['location']     = $cnct['BusinessCity'];
-  $entry['zip']          = $cnct['BusinessZip'];
-  $entry['homestreet']   = $cnct['HomeStreet']."\n". //str
-                           $cnct['HomeZip']." ".     //plz
-                           $cnct['HomeCity'];        //ort
-  $entry['homephone']    = $cnct['HomePhone'];
-  $entry['phone']        = $cnct['BusinessPhone'];
-  $entry['fax']          = empty($cnct['BusinessFax']) ? $cnct['HomeFax'] : $cnct['BusinessFax'];
-  $entry['mobile']       = empty($cnct['HomeMobile']) ? $cnct['BusinessMobile'] : $cnct['HomeMobile'];
-  $entry['fax']          = empty($cnct['BusinessFax']) ? $cnct['HomeFax'] : $cnct['BusinessFax'];
+//prepare templates
+tpl_std();
+tpl_orgs();
+tpl_markers();
+$smarty->assign('error',$error);
+$smarty->assign('list',$list);
+//display templates
+$smarty->display('header.tpl');
+$smarty->display('import.tpl');
+$smarty->display('footer.tpl');
 
-  return $entry;
-}
 
 function vcard_entry($vcf){
-  $entry['name']         = $vcf['N'][0]['value'][0][0];
-  $entry['givenname']    = trim($vcf['N'][0]['value'][1][0].' '.$vcf['N'][0]['value'][2][0]);
-  $entry['title']        = $vcf['N'][0]['value'][3][0];
-  $entry['organization'] = $vcf['ORG'][0]['value'][0][0];
-  $entry['office']       = $vcf['ORG'][0]['value'][1][0];
-  $entry['note']         = $vcf['NOTE'][0]['value'][0][0];
-  $entry['url']          = $vcf['URL'][0]['value'][0][0];
-  $bday                  = $vcf['BDAY'][0]['value'][0][0];
-  $entry['anniversary']  = substr($bday,0,4).'-'.substr($bday,4,2).'-'.substr($bday,6,2);
+$entry['name']         = $vcf['N'][0]['value'][0][0];
+$entry['givenname']    = trim($vcf['N'][0]['value'][1][0].' '.$vcf['N'][0]['value'][2][0]);
+$entry['title']        = $vcf['N'][0]['value'][3][0];
+$entry['organization'] = $vcf['ORG'][0]['value'][0][0];
+$entry['office']       = $vcf['ORG'][0]['value'][1][0];
+$entry['note']         = $vcf['NOTE'][0]['value'][0][0];
+$entry['url']          = $vcf['URL'][0]['value'][0][0];
+$bday                  = $vcf['BDAY'][0]['value'][0][0];
+$entry['anniversary']  = substr($bday,0,4).'-'.substr($bday,4,2).'-'.substr($bday,6,2);
 
-  foreach($vcf['TEL'] as $tel){
-    if(   empty($entry['phone']) &&
-          array_search('WORK',$tel['param']['TYPE']) !== FALSE &&
+foreach($vcf['TEL'] as $tel){
+  if(   empty($entry['phone']) &&
+        array_search('WORK',$tel['param']['TYPE']) !== FALSE &&
+        array_search('VOICE',$tel['param']['TYPE']) !== FALSE){
+    // Work phone
+    $entry['phone'] = $tel['value'][0][0];
+  }elseif(empty($entry['fax']) &&
+          array_search('FAX',$tel['param']['TYPE']) !== FALSE){
+    $entry['fax'] = $tel['value'][0][0];
+  }elseif(empty($entry['mobile']) &&
+          array_search('CELL',$tel['param']['TYPE']) !== FALSE){
+    $entry['mobile'] = $tel['value'][0][0];
+  }elseif(empty($entry['pager']) &&
+          array_search('PAGER',$tel['param']['TYPE']) !== FALSE){
+    $entry['pager'] = $tel['value'][0][0];
+  }elseif(empty($entry['homephone']) &&
+          array_search('HOME',$tel['param']['TYPE']) !== FALSE &&
           array_search('VOICE',$tel['param']['TYPE']) !== FALSE){
-      // Work phone
-      $entry['phone'] = $tel['value'][0][0];
-    }elseif(empty($entry['fax']) &&
-            array_search('FAX',$tel['param']['TYPE']) !== FALSE){
-      $entry['fax'] = $tel['value'][0][0];
-    }elseif(empty($entry['mobile']) &&
-            array_search('CELL',$tel['param']['TYPE']) !== FALSE){
-      $entry['mobile'] = $tel['value'][0][0];
-    }elseif(empty($entry['pager']) &&
-            array_search('PAGER',$tel['param']['TYPE']) !== FALSE){
-      $entry['pager'] = $tel['value'][0][0];
-    }elseif(empty($entry['homephone']) &&
-            array_search('HOME',$tel['param']['TYPE']) !== FALSE &&
-            array_search('VOICE',$tel['param']['TYPE']) !== FALSE){
-      $entry['homephone'] = $tel['value'][0][0];
-    }
-  }
-  foreach($vcf['EMAIL'] as $mail){
-    $entry['mail'][] = $mail['value'][0][0];
+    $entry['homephone'] = $tel['value'][0][0];
   }
-  foreach($vcf['ADR'] as $adr){
-    if(array_search('HOME',$adr['param']['TYPE']) !== FALSE){
-      $entry['homestreet'] = $adr['value'][2][0]."\n". //str
-                             $adr['value'][5][0]." ". //plz
-                             $adr['value'][3][0];      //ort
+}
+foreach($vcf['EMAIL'] as $mail){
+  $entry['mail'][] = $mail['value'][0][0];
+}
+foreach($vcf['ADR'] as $adr){
+  if(array_search('HOME',$adr['param']['TYPE']) !== FALSE){
+    $entry['homestreet'] = $adr['value'][2][0]."\n". //str
+                           $adr['value'][5][0]." ". //plz
+                           $adr['value'][3][0];      //ort
 
-    }elseif(array_search('WORK',$adr['param']['TYPE']) !== FALSE){
-      $entry['street']   = $adr['value'][2][0];
-      $entry['location'] = $adr['value'][3][0];
-      $entry['zip']      = $adr['value'][5][0];
-    }
+  }elseif(array_search('WORK',$adr['param']['TYPE']) !== FALSE){
+    $entry['street']   = $adr['value'][2][0];
+    $entry['location'] = $adr['value'][3][0];
+    $entry['zip']      = $adr['value'][5][0];
   }
+}
 
 /*
-  print '<pre>';
-  print_r($entry);
-  print '</pre>';
+print '<pre>';
+print_r($entry);
+print '</pre>';
 */
 
-  return $entry;
+return $entry;
 }
 
 
diff --git a/importVCF.php b/importVCF.php
deleted file mode 100644 (file)
index 1138b99..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-<?
-  require_once('init.php');
-  require_once('Contact_Vcard_Parse.php');
-  ldap_login();
-
-  if(! $_SESSION['ldapab']['username'] ){
-    header("Location: login.php");
-    exit;
-  }
-
-  $error = '';
-  if(isset($_FILES['userfile'])){
-    if(preg_match('/\.vcf$/i', $_FILES['userfile']['name'])){
-      if (is_uploaded_file($_FILES['userfile']['tmp_name'])) {
-        //parse VCF
-                               $vcfparser = new Contact_Vcard_Parse();
-                               $vcards = $vcfparser->fromFile($_FILES['userfile']['tmp_name']);
-      }else{
-        switch($_FILES['userfile']['error']){
-         case 0: //no error; possible file attack!
-           $error = "There was a problem with your upload.";
-           break;
-         case 1: //uploaded file exceeds the upload_max_filesize directive in php.ini
-           $error = "The file you are trying to upload is too big.";
-           break;
-         case 2: //uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form
-           $error = "The file you are trying to upload is too big.";
-           break;
-         case 3: //uploaded file was only partially uploaded
-           $error = "The file you are trying upload was only partially uploaded.";
-           break;
-         case 4: //no file was uploaded
-           $error = "You must select a VCF file for upload.";
-           break;
-         default: //a default error, just in case!  :)
-           $error = "There was a problem with your upload.";
-           break;
-                 }
-      }
-    }else{
-      $error = "Only VCF extension is allowed";
-    }
-  }
-
-  //prepare templates for all found VCARDs
-  $list = '';
-  if (count($vcards)){
-         foreach ($vcards as $vcard){
-         $entry = vcard_entry($vcard);
-       $smarty->clear_all_assign();
-               tpl_std();
-           $smarty->assign('entry',$entry);
-         $list .= $smarty->fetch('importVCF_entry.tpl');
-         }
-       }
-
-  //prepare templates
-  tpl_std();
-  tpl_orgs();
-  tpl_markers();
-  $smarty->assign('error',$error);
-  $smarty->assign('list',$list);
-  //display templates
-  $smarty->display('header.tpl');
-  $smarty->display('importVCF.tpl');
-  $smarty->display('footer.tpl');
-
-
-function vcard_entry($vcf){
-  $entry['name'] = $vcf['N'][0]['value'][0][0];
-  $entry['givenname'] = trim($vcf['N'][0]['value'][1][0].' '.$vcf['N'][0]['value'][2][0]);
-  $entry['title'] = $vcf['N'][0]['value'][3][0];
-  $entry['organization'] = $vcf['ORG'][0]['value'][0][0];
-  $entry['office'] = $vcf['ORG'][0]['value'][1][0];
-  $entry['note'] = $vcf['NOTE'][0]['value'][0][0];
-  $entry['url'] = $vcf['URL'][0]['value'][0][0];
-  $bday = $vcf['BDAY'][0]['value'][0][0];
-  $entry['anniversary'] = substr($bday,0,4).'-'.substr($bday,4,2).'-'.substr($bday,6,2);
-
-  foreach($vcf['TEL'] as $tel){
-    if(   empty($entry['phone']) &&
-          array_search('WORK',$tel['param']['TYPE']) !== FALSE &&
-          array_search('VOICE',$tel['param']['TYPE']) !== FALSE){
-      // Work phone
-                       $entry['phone'] = $tel['value'][0][0];
-    }elseif(empty($entry['fax']) &&
-            array_search('FAX',$tel['param']['TYPE']) !== FALSE){
-                       $entry['fax'] = $tel['value'][0][0];
-    }elseif(empty($entry['mobile']) &&
-            array_search('CELL',$tel['param']['TYPE']) !== FALSE){
-                       $entry['mobile'] = $tel['value'][0][0];
-    }elseif(empty($entry['pager']) &&
-            array_search('PAGER',$tel['param']['TYPE']) !== FALSE){
-                       $entry['pager'] = $tel['value'][0][0];
-    }elseif(empty($entry['homephone']) &&
-            array_search('HOME',$tel['param']['TYPE']) !== FALSE &&
-            array_search('VOICE',$tel['param']['TYPE']) !== FALSE){
-                       $entry['homephone'] = $tel['value'][0][0];
-    }
-  }
-  foreach($vcf['EMAIL'] as $mail){
-    $entry['mail'][] = $mail['value'][0][0];
-  }
-  foreach($vcf['ADR'] as $adr){
-    if(array_search('HOME',$adr['param']['TYPE']) !== FALSE){
-      $entry['homestreet'] = $adr['value'][2][0]."\n". //str
-                                                                                                                $adr['value'][5][0]." ". //plz
-                             $adr['value'][3][0];      //ort
-
-    }elseif(array_search('WORK',$adr['param']['TYPE']) !== FALSE){
-      $entry['street']   = $adr['value'][2][0];
-      $entry['location'] = $adr['value'][3][0];
-      $entry['plz']      = $adr['value'][5][0];
-    }
-  }
-
-/*
-  print '<pre>';
-  print_r($entry);
-  print '</pre>';
-*/
-
-  return $entry;
-}
-
-
-?>
diff --git a/inc/Contact_Vcard_Parse.php b/inc/Contact_Vcard_Parse.php
new file mode 100644 (file)
index 0000000..da1f16f
--- /dev/null
@@ -0,0 +1,836 @@
+<?php
+/* vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4: */ 
+// +----------------------------------------------------------------------+ 
+// | PHP version 4                                                        | 
+// +----------------------------------------------------------------------+ 
+// | Copyright (c) 1997-2002 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: Paul M. Jones <pmjones@ciaweb.net>                          | 
+// +----------------------------------------------------------------------+ 
+// 
+// $Id: Contact_Vcard_Parse.php,v 1.1 2004/06/01 08:48:59 gohr Exp $ 
+
+
+/**
+* 
+* Parser for vCards.
+*
+* This class parses vCard 2.1 and 3.0 sources from file or text into a
+* structured array.
+* 
+* Usage:
+* 
+* <code>
+*     // include this class file
+*     require_once 'Contact_Vcard_Parse.php';
+*     
+*     // instantiate a parser object
+*     $parse = new Contact_Vcard_Parse();
+*     
+*     // parse a vCard file and store the data
+*     // in $cardinfo
+*     $cardinfo = $parse->fromFile('sample.vcf');
+*     
+*     // view the card info array
+*     echo '<pre>';
+*     print_r($cardinfo);
+*     echo '</pre>';
+* </code>
+* 
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+* 
+* @package Contact_Vcard_Parse
+* 
+* @version 1.30
+* 
+*/
+
+class Contact_Vcard_Parse {
+    
+    
+    /**
+    * 
+    * Reads a file for parsing, then sends it to $this->fromText()
+    * and returns the results.
+    * 
+    * @access public
+    * 
+    * @param array $filename The filename to read for vCard information.
+    * 
+    * @return array An array of of vCard information extracted from the
+    * file.
+    * 
+    * @see Contact_Vcard_Parse::fromText()
+    * 
+    * @see Contact_Vcard_Parse::_fromArray()
+    * 
+    */
+    
+    function fromFile($filename, $decode_qp = true)
+    {
+        $text = $this->fileGetContents($filename);
+        
+        if ($text === false) {
+            return false;
+        } else {
+            // dump to, and get return from, the fromText() method.
+            return $this->fromText($text, $decode_qp);
+        }
+    }
+    
+    
+    /**
+    * 
+    * Reads the contents of a file.  Included for users whose PHP < 4.3.0.
+    * 
+    * @access public
+    * 
+    * @param array $filename The filename to read for vCard information.
+    * 
+    * @return string|bool The contents of the file if it exists and is
+    * readable, or boolean false if not.
+    * 
+    * @see Contact_Vcard_Parse::fromFile()
+    * 
+    */
+    
+    function fileGetContents($filename)
+    {
+        if (file_exists($filename) &&
+            is_readable($filename)) {
+            
+            $text = '';
+            $len = filesize($filename);
+            
+            $fp = fopen($filename, 'r');
+            while ($line = fread($fp, filesize($filename))) {
+                $text .= $line;
+            }
+            fclose($fp);
+            
+            return $text;
+            
+        } else {
+        
+            return false;
+            
+        }
+    }
+    
+    
+    /**
+    * 
+    * Prepares a block of text for parsing, then sends it through and
+    * returns the results from $this->fromArray().
+    * 
+    * @access public
+    * 
+    * @param array $text A block of text to read for vCard information.
+    * 
+    * @return array An array of vCard information extracted from the
+    * source text.
+    * 
+    * @see Contact_Vcard_Parse::_fromArray()
+    * 
+    */
+    
+    function fromText($text, $decode_qp = true)
+    {
+        // convert all kinds of line endings to Unix-standard and get
+        // rid of double blank lines.
+        $this->convertLineEndings($text);
+        
+        // unfold lines.  concat two lines where line 1 ends in \n and
+        // line 2 starts with a whitespace character.  only removes
+        // the first whitespace character, leaves others in place.
+        $fold_regex = '(\n)([ |\t])';
+        $text = preg_replace("/$fold_regex/i", "", $text);
+        
+        // massage for Macintosh OS X Address Book (remove nulls that
+        // Address Book puts in for unicode chars)
+        $text = str_replace("\x00", '', $text);
+        
+        // convert the resulting text to an array of lines
+        $lines = explode("\n", $text);
+        
+        // parse the array of lines and return vCard info
+        return $this->_fromArray($lines, $decode_qp);
+    }
+    
+    
+    /**
+    * 
+    * Converts line endings in text.
+    * 
+    * Takes any text block and converts all line endings to UNIX
+    * standard. DOS line endings are \r\n, Mac are \r, and UNIX is \n.
+    *
+    * NOTE: Acts on the text block in-place; does not return a value.
+    * 
+    * @access public
+    * 
+    * @param string $text The string on which to convert line endings.
+    * 
+    * @return void
+    * 
+    */
+    
+    function convertLineEndings(&$text)
+    {
+        // DOS
+        $text = str_replace("\r\n", "\n", $text);
+        
+        // Mac
+        $text = str_replace("\r", "\n", $text);
+    }
+    
+    
+    /**
+    * 
+    * Splits a string into an array at semicolons.  Honors backslash-
+    * escaped semicolons (i.e., splits at ';' not '\;').
+    * 
+    * @access public
+    * 
+    * @param string $text The string to split into an array.
+    * 
+    * @param bool $convertSingle If splitting the string results in a
+    * single array element, return a string instead of a one-element
+    * array.
+    * 
+    * @return mixed An array of values, or a single string.
+    * 
+    */
+    
+    function splitBySemi($text, $convertSingle = false)
+    {
+        // we use these double-backs (\\) because they get get converted
+        // to single-backs (\) by preg_split.  the quad-backs (\\\\) end
+        // up as as double-backs (\\), which is what preg_split requires
+        // to indicate a single backslash (\). what a mess.
+        $regex = '(?<!\\\\)(\;)';
+        $tmp = preg_split("/$regex/i", $text);
+        
+        // if there is only one array-element and $convertSingle is
+        // true, then return only the value of that one array element
+        // (instead of returning the array).
+        if ($convertSingle && count($tmp) == 1) {
+            return $tmp[0];
+        } else {
+            return $tmp;
+        }
+    }
+    
+    
+    /**
+    * 
+    * Splits a string into an array at commas.  Honors backslash-
+    * escaped commas (i.e., splits at ',' not '\,').
+    * 
+    * @access public
+    * 
+    * @param string $text The string to split into an array.
+    * 
+    * @param bool $convertSingle If splitting the string results in a
+    * single array element, return a string instead of a one-element
+    * array.
+    * 
+    * @return mixed An array of values, or a single string.
+    * 
+    */
+    
+    function splitByComma($text, $convertSingle = false)
+    {
+        // we use these double-backs (\\) because they get get converted
+        // to single-backs (\) by preg_split.  the quad-backs (\\\\) end
+        // up as as double-backs (\\), which is what preg_split requires
+        // to indicate a single backslash (\). ye gods, how ugly.
+        $regex = '(?<!\\\\)(\,)';
+        $tmp = preg_split("/$regex/i", $text);
+        
+        // if there is only one array-element and $convertSingle is
+        // true, then return only the value of that one array element
+        // (instead of returning the array).
+        if ($convertSingle && count($tmp) == 1) {
+            return $tmp[0];
+        } else {
+            return $tmp;
+        }
+    }
+    
+    
+    /**
+    * 
+    * Used to make string human-readable after being a vCard value.
+    * 
+    * Converts...
+    *     \; => ;
+    *     \, => ,
+    *     literal \n => newline
+    * 
+    * @access public
+    * 
+    * @param mixed $text The text to unescape.
+    * 
+    * @return void
+    * 
+    */
+    
+    function unescape(&$text)
+    {
+        if (is_array($text)) {
+            foreach ($text as $key => $val) {
+                $this->unescape($val);
+                $text[$key] = $val;
+            }
+        } else {
+            $text = str_replace('\;', ';', $text);
+            $text = str_replace('\,', ',', $text);
+            $text = str_replace('\n', "\n", $text);
+        }
+    }
+    
+    
+    /**
+    *
+    * Emulated destructor.
+    *
+    * @access private
+    * @return boolean true
+    *
+    */
+    
+    function _Contact_Vcard_Parse()
+    {
+        return true;
+    }
+    
+    
+    /**
+    * 
+    * Parses an array of source lines and returns an array of vCards.
+    * Each element of the array is itself an array expressing the types,
+    * parameters, and values of each part of the vCard. Processes both
+    * 2.1 and 3.0 vCard sources.
+    *
+    * @access private
+    * 
+    * @param array $source An array of lines to be read for vCard
+    * information.
+    * 
+    * @return array An array of of vCard information extracted from the
+    * source array.
+    * 
+    */
+    
+    function _fromArray($source, $decode_qp = true)
+    {
+        // the info array will hold all resulting vCard information.
+        $info = array();
+        
+        // tells us whether the source text indicates the beginning of a
+        // new vCard with a BEGIN:VCARD tag.
+        $begin = false;
+        
+        // holds information about the current vCard being read from the
+        // source text.
+        $card = array();
+        
+        // loop through each line in the source array
+        foreach ($source as $line) {
+            
+            // if the line is blank, skip it.
+            if (trim($line) == '') {
+                continue;
+            }
+            
+            // find the first instance of ':' on the line.  The part
+            // to the left of the colon is the type and parameters;
+            // the part to the right of the colon is the value data.
+            $pos = strpos($line, ':');
+            
+            // if there is no colon, skip the line.
+            if ($pos === false) {
+                continue;
+            }
+            
+            // get the left and right portions
+            $left = trim(substr($line, 0, $pos));
+            $right = trim(substr($line, $pos+1, strlen($line)));
+            
+            // have we started yet?
+            if (! $begin) {
+                
+                // nope.  does this line indicate the beginning of
+                // a new vCard?
+                if (strtoupper($left) == 'BEGIN' &&
+                    strtoupper($right) == 'VCARD') {
+                    
+                    // tell the loop that we've begun a new card
+                    $begin = true;
+                }
+                
+                // regardless, loop to the next line of source. if begin
+                // is still false, the next loop will check the line. if
+                // begin has now been set to true, the loop will start
+                // collecting card info.
+                continue;
+                
+            } else {
+                
+                // yep, we've started, but we don't know how far along
+                // we are in the card. is this the ending line of the
+                // current vCard?
+                if (strtoupper($left) == 'END' &&
+                    strtoupper($right) == 'VCARD') {
+                    
+                    // yep, we're done. keep the info from the current
+                    // card...
+                    $info[] = $card;
+                    
+                    // ...and reset to grab a new card if one exists in
+                    // the source array.
+                    $begin = false;
+                    $card = array();
+                    
+                } else {
+                    
+                    // we're not on an ending line, so collect info from
+                    // this line into the current card. split the
+                    // left-portion of the line into a type-definition
+                    // (the kind of information) and parameters for the
+                    // type.
+                    $typedef = $this->_getTypeDef($left);
+                    $params = $this->_getParams($left);
+                    
+                    // if we are decoding quoted-printable, do so now.
+                    // QUOTED-PRINTABLE is not allowed in version 3.0,
+                    // but we don't check for versioning, so we do it
+                    // regardless.  ;-)
+                    $this->_decode_qp($params, $right);
+                    
+                    // now get the value-data from the line, based on
+                    // the typedef
+                    switch ($typedef) {
+                        
+                    case 'N':
+                        // structured name of the person
+                        $value = $this->_parseN($right);
+                        break;
+                        
+                    case 'ADR':
+                        // structured address of the person
+                        $value = $this->_parseADR($right);
+                        break;
+                        
+                    case 'NICKNAME':
+                        // nicknames
+                        $value = $this->_parseNICKNAME($right);
+                        break;
+                        
+                    case 'ORG':
+                        // organizations the person belongs to
+                        $value = $this->_parseORG($right);
+                        break;
+                        
+                    case 'CATEGORIES':
+                        // categories to which this card is assigned
+                        $value = $this->_parseCATEGORIES($right);
+                        break;
+                        
+                    case 'GEO':
+                        // geographic coordinates
+                        $value = $this->_parseGEO($right);
+                        break;
+                        
+                    default:
+                        // by default, just grab the plain value. keep
+                        // as an array to make sure *all* values are
+                        // arrays.  for consistency. ;-)
+                        $value = array(array($right));
+                        break;
+                    }
+                    
+                    // add the type, parameters, and value to the
+                    // current card array.  note that we allow multiple
+                    // instances of the same type, which might be dumb
+                    // in some cases (e.g., N).
+                    $card[$typedef][] = array(
+                        'param' => $params,
+                        'value' => $value
+                    );
+                }
+            }
+        }
+        
+        $this->unescape($info);
+        return $info;
+    }
+    
+    
+    /**
+    *
+    * Takes a vCard line and extracts the Type-Definition for the line.
+    * 
+    * @access private
+    *
+    * @param string $text A left-part (before-the-colon part) from a
+    * vCard line.
+    * 
+    * @return string The type definition for the line.
+    * 
+    */
+    
+    function _getTypeDef($text)
+    {
+        // split the text by semicolons
+        $split = $this->splitBySemi($text);
+        
+        // only return first element (the typedef)
+        return $split[0];
+    }
+    
+    
+    /**
+    *
+    * Finds the Type-Definition parameters for a vCard line.
+    * 
+    * @access private
+    * 
+    * @param string $text A left-part (before-the-colon part) from a
+    * vCard line.
+    * 
+    * @return mixed An array of parameters.
+    * 
+    */
+    
+    function _getParams($text)
+    {
+        // split the text by semicolons into an array
+        $split = $this->splitBySemi($text);
+        
+        // drop the first element of the array (the type-definition)
+        array_shift($split);
+        
+        // set up an array to retain the parameters, if any
+        $params = array();
+        
+        // loop through each parameter.  the params may be in the format...
+        // "TYPE=type1,type2,type3"
+        //    ...or...
+        // "TYPE=type1;TYPE=type2;TYPE=type3"
+        foreach ($split as $full) {
+            
+            // split the full parameter at the equal sign so we can tell
+            // the parameter name from the parameter value
+            $tmp = explode("=", $full);
+            
+            // the key is the left portion of the parameter (before
+            // '='). if in 2.1 format, the key may in fact be the
+            // parameter value, not the parameter name.
+            $key = strtoupper(trim($tmp[0]));
+            
+            // get the parameter name by checking to see if it's in
+            // vCard 2.1 or 3.0 format.
+            $name = $this->_getParamName($key);
+            
+            // list of all parameter values
+            $listall = trim($tmp[1]);
+            
+            // if there is a value-list for this parameter, they are
+            // separated by commas, so split them out too.
+            $list = $this->splitByComma($listall);
+            
+            // now loop through each value in the parameter and retain
+            // it.  if the value is blank, that means it's a 2.1-style
+            // param, and the key itself is the value.
+            foreach ($list as $val) {
+                if (trim($val) != '') {
+                    // 3.0 formatted parameter
+                    $params[$name][] = trim($val);
+                } else {
+                    // 2.1 formatted parameter
+                    $params[$name][] = $key;
+                }
+            }
+            
+            // if, after all this, there are no parameter values for the
+            // parameter name, retain no info about the parameter (saves
+            // ram and checking-time later).
+            if (count($params[$name]) == 0) {
+                unset($params[$name]);
+            }
+        }
+        
+        // return the parameters array.
+        return $params;
+    }
+    
+    
+    /**
+    *
+    * Looks at the parameters of a vCard line; if one of them is
+    * ENCODING[] => QUOTED-PRINTABLE then decode the text in-place.
+    * 
+    * @access private
+    * 
+    * @param array $params A parameter array from a vCard line.
+    * 
+    * @param string $text A right-part (after-the-colon part) from a
+    * vCard line.
+    *
+    * @return void
+    * 
+    */
+    
+    function _decode_qp(&$params, &$text)
+    {
+        // loop through each parameter
+        foreach ($params as $param_key => $param_val) {
+            
+            // check to see if it's an encoding param
+            if (trim(strtoupper($param_key)) == 'ENCODING') {
+            
+                // loop through each encoding param value
+                foreach ($param_val as $enc_key => $enc_val) {
+                
+                    // if any of the values are QP, decode the text
+                    // in-place and return
+                    if (trim(strtoupper($enc_val)) == 'QUOTED-PRINTABLE') {
+                        $text = quoted_printable_decode($text);
+                        return;
+                    }
+                }
+            }
+        }
+    }
+    
+    
+    /**
+    * 
+    * Returns parameter names from 2.1-formatted vCards.
+    *
+    * The vCard 2.1 specification allows parameter values without a
+    * name. The parameter name is then determined from the unique
+    * parameter value.
+    * 
+    * Shamelessly lifted from Frank Hellwig <frank@hellwig.org> and his
+    * vCard PHP project <http://vcardphp.sourceforge.net>.
+    * 
+    * @access private
+    * 
+    * @param string $value The first element in a parameter name-value
+    * pair.
+    * 
+    * @return string The proper parameter name (TYPE, ENCODING, or
+    * VALUE).
+    * 
+    */
+     
+    function _getParamName($value)
+    {
+        static $types = array (
+            'DOM', 'INTL', 'POSTAL', 'PARCEL','HOME', 'WORK',
+            'PREF', 'VOICE', 'FAX', 'MSG', 'CELL', 'PAGER',
+            'BBS', 'MODEM', 'CAR', 'ISDN', 'VIDEO',
+            'AOL', 'APPLELINK', 'ATTMAIL', 'CIS', 'EWORLD',
+            'INTERNET', 'IBMMAIL', 'MCIMAIL',
+            'POWERSHARE', 'PRODIGY', 'TLX', 'X400',
+            'GIF', 'CGM', 'WMF', 'BMP', 'MET', 'PMB', 'DIB',
+            'PICT', 'TIFF', 'PDF', 'PS', 'JPEG', 'QTIME',
+            'MPEG', 'MPEG2', 'AVI',
+            'WAVE', 'AIFF', 'PCM',
+            'X509', 'PGP'
+        );
+        
+        // CONTENT-ID added by pmj
+        static $values = array (
+            'INLINE', 'URL', 'CID', 'CONTENT-ID'
+        );
+        
+        // 8BIT added by pmj
+        static $encodings = array (
+            '7BIT', '8BIT', 'QUOTED-PRINTABLE', 'BASE64'
+        );
+        
+        // changed by pmj to the following so that the name defaults to
+        // whatever the original value was.  Frank Hellwig's original
+        // code was "$name = 'UNKNOWN'".
+        $name = $value;
+        
+        if (in_array($value, $types)) {
+            $name = 'TYPE';
+        } elseif (in_array($value, $values)) {
+            $name = 'VALUE';
+        } elseif (in_array($value, $encodings)) {
+            $name = 'ENCODING';
+        }
+        
+        return $name;
+    }
+    
+    
+    /**
+    *
+    * Parses a vCard line value identified as being of the "N"
+    * (structured name) type-defintion.
+    *
+    * @access private
+    *
+    * @param string $text The right-part (after-the-colon part) of a
+    * vCard line.
+    * 
+    * @return array An array of key-value pairs where the key is the
+    * portion-name and the value is the portion-value.  The value itself
+    * may be an array as well if multiple comma-separated values were
+    * indicated in the vCard source.
+    *
+    */
+    
+    function _parseN($text)
+    {
+        $tmp = $this->splitBySemi($text);
+        return array(
+            $this->splitByComma($tmp[0]), // family (last)
+            $this->splitByComma($tmp[1]), // given (first)
+            $this->splitByComma($tmp[2]), // addl (middle)
+            $this->splitByComma($tmp[3]), // prefix
+            $this->splitByComma($tmp[4])  // suffix
+        );
+    }
+    
+    
+    /**
+    *
+    * Parses a vCard line value identified as being of the "ADR"
+    * (structured address) type-defintion.
+    *
+    * @access private
+    *
+    * @param string $text The right-part (after-the-colon part) of a
+    * vCard line.
+    * 
+    * @return array An array of key-value pairs where the key is the
+    * portion-name and the value is the portion-value.  The value itself
+    * may be an array as well if multiple comma-separated values were
+    * indicated in the vCard source.
+    *
+    */
+    
+    function _parseADR($text)
+    {
+        $tmp = $this->splitBySemi($text);
+        return array(
+            $this->splitByComma($tmp[0]), // pob
+            $this->splitByComma($tmp[1]), // extend
+            $this->splitByComma($tmp[2]), // street
+            $this->splitByComma($tmp[3]), // locality (city)
+            $this->splitByComma($tmp[4]), // region (state)
+            $this->splitByComma($tmp[5]), // postcode (ZIP)
+            $this->splitByComma($tmp[6])  // country
+        );
+    }
+    
+    
+    /**
+    * 
+    * Parses a vCard line value identified as being of the "NICKNAME"
+    * (informal or descriptive name) type-defintion.
+    *
+    * @access private
+    * 
+    * @param string $text The right-part (after-the-colon part) of a
+    * vCard line.
+    * 
+    * @return array An array of nicknames.
+    *
+    */
+    
+    function _parseNICKNAME($text)
+    {
+        return array($this->splitByComma($text));
+    }
+    
+    
+    /**
+    * 
+    * Parses a vCard line value identified as being of the "ORG"
+    * (organizational info) type-defintion.
+    *
+    * @access private
+    *
+    * @param string $text The right-part (after-the-colon part) of a
+    * vCard line.
+    * 
+    * @return array An array of organizations; each element of the array
+    * is itself an array, which indicates primary organization and
+    * sub-organizations.
+    *
+    */
+    
+    function _parseORG($text)
+    {
+        $tmp = $this->splitbySemi($text);
+        $list = array();
+        foreach ($tmp as $val) {
+            $list[] = array($val);
+        }
+        
+        return $list;
+    }
+    
+    
+    /**
+    * 
+    * Parses a vCard line value identified as being of the "CATEGORIES"
+    * (card-category) type-defintion.
+    *
+    * @access private
+    * 
+    * @param string $text The right-part (after-the-colon part) of a
+    * vCard line.
+    * 
+    * @return mixed An array of categories.
+    *
+    */
+    
+    function _parseCATEGORIES($text)
+    {
+        return array($this->splitByComma($text));
+    }
+    
+    
+    /**
+    * 
+    * Parses a vCard line value identified as being of the "GEO"
+    * (geographic coordinate) type-defintion.
+    *
+    * @access private
+    *
+    * @param string $text The right-part (after-the-colon part) of a
+    * vCard line.
+    * 
+    * @return mixed An array of lat-lon geocoords.
+    *
+    */
+    
+    function _parseGEO($text)
+    {
+        $tmp = $this->splitBySemi($text);
+        return array(
+            array($tmp[0]), // lat
+            array($tmp[1])  // lon
+        );
+    }
+}
+
+?>
\ No newline at end of file
diff --git a/inc/config.php b/inc/config.php
new file mode 100644 (file)
index 0000000..d46910e
--- /dev/null
@@ -0,0 +1,59 @@
+<?
+
+  // LDAP URL; if set, takes precedence over ldapserver and ldapport
+  #$conf['ldapurl']     = 'ldaps://ldap.example.com/';
+
+  // Which LDAP Server to use?
+  $conf['ldapserver']  = 'ldap';
+
+  // Which LDAP Port Server to use? (389 is standard, 636 for ssl)
+  $conf['ldapport']    = 389;
+
+  // Use LDAP protocol version 3? (0|1)
+  $conf['ldapv3'] = 1;
+
+  // What is the root dn on this Server?
+  $conf['ldaprootdn']  = 'o=cosmocode, c=de';
+
+  // Where are the user Accounts stored?
+  $conf['usertree']    = 'ou=people, '.$conf['ldaprootdn'];
+
+  // How to match users? %u is replaced by the given login
+  $conf['userfilter']  = '(&(uid=%u)(objectClass=posixAccount))';
+
+  // Use these values to bind to the ldap directory when not logged in (leave blank for anonymous bind)
+  $conf['anonbinddn']  = '';
+  $conf['anonbindpw']  = '';
+
+  // Which language to use (see lang directory)
+  $conf['lang']        = 'en';
+
+  // Where to store public contacts?
+  $conf['publicbook']  = 'ou=contacts, '.$conf['ldaprootdn'];
+
+  // Where to store private contacts (relative to $conf['usertree'])
+  $conf['privatebook'] = 'ou=contacts';
+
+  // Should the public address book be viewable by logged in users only? (0|1)
+  $conf['userlogreq']  = 0;
+
+  // Should the additional schema ldapab.schema be used? (0|1)
+  // Note: openxchange and extended are currently exclusive, do not use both at the same time!
+  $conf['extended']    = 1;
+
+  // Should we use some parts of the openxchange.schema? (0|1)
+  // Note: openxchange and extended are currently exclusive, do not use both at the same time!
+  $conf['openxchange'] = 0;
+
+  // Should we try to login using the username and password provided by httpd? (0|1)
+  $conf['httpd_auth']  = 0;
+
+  // Dateformat for birthdays when using extended schema
+  // see http://www.php.net/manual/en/function.strftime.php
+  #$conf['dateformat']  = '%Y/%m/%d';
+  $conf['dateformat']  = '%d.%m.%Y';
+
+  // Force recompilation of smarty templates?
+  $conf['smartycompile'] = 1;
+
+
diff --git a/inc/fields.php b/inc/fields.php
new file mode 100644 (file)
index 0000000..8f3d3c3
--- /dev/null
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Configures fieldname - LDAP attribute associations
+ *
+ * If you use other attributes you may change the assignments here.
+ * Note the arrays need to remain flippable, eg. both sides have to
+ * be unique
+ *
+ * Fields starting with a * may contain multiple values (needs to be
+ * handled by the template as well)
+ */
+
+
+/**
+ * The object classes to store with contacts
+ */
+$OCLASSES[] = 'inetOrgPerson';
+
+/**
+ * The standard fields suported by OpenLDAP's default schemas
+ */
+$FIELDS = array(
+    'dn'           => 'dn',                          // don't touch!
+    'name'         => 'sn',
+    'displayname'  => 'cn',
+    'givenname'    => 'givenName',
+    'title'        => 'title',
+    'organization' => 'o',                           // aka. company
+    'office'       => 'physicalDeliveryOfficeName',
+    'street'       => 'postalAddress',
+    'zip'          => 'postalCode',
+    'location'     => 'l',                           // aka. city
+    'phone'        => 'telephoneNumber',
+    'fax'          => 'facsimileTelephoneNumber',
+    'mobile'       => 'mobile',                      // aka. cell phone
+    'pager'        => 'pager',
+    'homephone'    => 'homePhone',
+    'homestreet'   => 'homePostalAddress',
+    'photo'        => 'jpegPhoto',
+    'url'          => 'labeledURI',
+    'note'         => 'description',
+    'manager'      => 'manager',                     // aka. key account
+    '_mail'        => 'mail',
+);
+
+/**
+ * If the provided "extended" schema is used the following fields
+ * and object classes are added
+ */
+$OCLASSES[] = 'contactPerson';
+$FIELDS['anniversary']  = 'anniversary';
+$FIELDS['_marker']      = 'marker';                  // aka. tags
+
+/**
+ * If the open exchange schema is used the following fields
+ * and object classes are added
+ */
+/* comment in if you want to use it
+$OCLASSES[] = 'OXUserObject';
+$FIELDS['country']          = 'userCountry';
+$FIELDS['birthday']         = 'birthDay';
+$FIELDS['ipphone']          = 'IPPhone';
+$FIELDS['_marker']          = 'OXUserCategories';
+$FIELDS['instantmessenger'] = 'OXUserInstantMessenger';
+$FIELDS['timezone']         = 'OXTimeZone';
+$FIELDS['position']         = 'OXUserPosition';
+$FIELDS['certificate']      = 'relClientCert';
+$FIELDS['domain']           = 'domain';
+*/
+
+/**
+ * If the Evolution schema is used the following fields
+ * and object classes are added
+ */
+/* comment in if you want to use it
+$OCLASSES[] = 'evolutionPerson';
+$OCLASSES[] = 'officePerson';
+$FIELDS['department']  = 'ou';
+$FIELDS['state']       = 'st';
+$FIELDS['country']     = 'c';
+$FIELDS['phone']       = 'primaryPhone';
+$FIELDS['switchboard'] = 'companyPhone';
+$FIELDS['note']        = 'note';
+$FIELDS['manager']     = 'seeAlso';
+$FIELDS['birthday']    = 'birthDate';
+$FIELDS['spouse']      = 'spouseName';
+*/
+
+
+/**
+ * Flip the array
+ */
+$RFIELDS = array_flip($FIELDS);
+
diff --git a/inc/functions.php b/inc/functions.php
new file mode 100644 (file)
index 0000000..9166d31
--- /dev/null
@@ -0,0 +1,486 @@
+<?php
+
+/**
+ * assigns some standard variables to smarty templates
+ */
+function smarty_std(){
+  global $smarty;
+  $smarty->assign('USER',$_SESSION['ldapab']['username']);
+}
+
+/**
+ * Uses Username and Password from Session to initialize the LDAP handle
+ * If it fails it redirects to login.php
+ */
+function ldap_login(){
+  global $conf;
+  if(!empty($_SESSION['ldapab']['username'])){
+    // existing session! Check if valid
+    if($_SESSION['ldapab']['browserid'] != auth_browseruid()){
+      //session hijacking detected
+      header('Location: login.php?username=');
+      exit;
+    }
+  } elseif ($conf['httpd_auth'] && !empty($_SERVER['PHP_AUTH_USER'])) {
+    // use HTTP auth if wanted and possible
+    $_SESSION['ldapab']['username'] = $_SERVER['PHP_AUTH_USER'];
+    $_SESSION['ldapab']['password'] = $_SERVER['PHP_AUTH_PW'];
+  } elseif (!empty($_COOKIE['ldapabauth'])) {
+    // check persistent cookie
+    $cookie = base64_decode($_COOKIE['ldapabauth']);
+    $cookie = x_Decrypt($cookie,get_cookie_secret());
+    list($u,$p) = unserialize($cookie);
+    $_SESSION['ldapab']['username'] = $u;
+    $_SESSION['ldapab']['password'] = $p;
+  }
+
+  if(empty($_SESSION['ldapab']) ||
+     !do_ldap_bind($_SESSION['ldapab']['username'],
+                   $_SESSION['ldapab']['password'],
+                   $_SESSION['ldapab']['binddn'])){
+    header('Location: login.php?username=');
+    exit;
+  }
+}
+
+/**
+ * Creates a global LDAP connection handle called $LDAP_CON
+ */
+function do_ldap_bind($user,$pass,$dn=""){
+  global $conf;
+  global $LDAP_CON;
+
+  //create global connection to LDAP if necessary
+  if(!$LDAP_CON){
+    if (!empty($conf['ldapurl'])){
+      $LDAP_CON = ldap_connect($conf['ldapurl']);
+    }else{
+      $LDAP_CON = ldap_connect($conf['ldapserver'],$conf['ldapport']);
+    }
+    if(!$LDAP_CON){
+      die("couldn't connect to LDAP server");
+    }
+  }
+
+  if($conf['ldapv3']) ldap_set_option($LDAP_CON, LDAP_OPT_PROTOCOL_VERSION, 3);
+
+  if(empty($dn)){
+    //anonymous bind to lookup users
+    //blank binddn or blank bindpw will result in anonymous bind
+    if(!ldap_bind($LDAP_CON,$conf['anonbinddn'],$conf['anonbindpw'])){
+      die("can not bind for user lookup");
+    }
+
+    //when no user was given stay connected anonymous
+    if(empty($user)){
+      set_session('','','');
+      return true;
+    }
+
+    //get dn for given user
+    $filter = str_replace('%u',$user,$conf['userfilter']);
+    $sr = ldap_search($LDAP_CON, $conf['usertree'], $filter);;
+    $result = ldap_get_entries($LDAP_CON, $sr);
+    if($result['count'] != 1){
+      set_session('','','');
+      return false;
+    }
+    $dn = $result[0]['dn'];
+  }
+
+  //bind with dn
+  if(ldap_bind($LDAP_CON,$dn,$pass)){
+    //bind successful -> set up session
+    set_session($user,$pass,$dn);
+    return true;
+  }
+  //bind failed -> remove session
+  set_session('','','');
+  return false;
+}
+
+/**
+ * Builds a pseudo UID from browser and IP data
+ *
+ * This is neither unique nor unfakable - still it adds some
+ * security. Using the first part of the IP makes sure
+ * proxy farms like AOLs are stil okay.
+ *
+ * @author  Andreas Gohr <andi@splitbrain.org>
+ *
+ * @return  string  a MD5 sum of various browser headers
+ */
+function auth_browseruid(){
+  $uid  = '';
+  if (empty($_SERVER['HTTP_USER_AGENT']))      { $_SERVER['HTTP_USER_AGENT']='USER_AGENT'; }
+  if (empty($_SERVER['HTTP_ACCEPT_ENCODING'])) { $_SERVER['HTTP_ACCEPT_ENCODING']='ACCEPT_ENCODING'; }
+  if (empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { $_SERVER['HTTP_ACCEPT_LANGUAGE']='ACCEPT_LANGUAGE'; }
+  if (empty($_SERVER['HTTP_ACCEPT_CHARSET']))  { $_SERVER['HTTP_ACCEPT_CHARSET']='ACCEPT_CHARSET'; }
+  $uid .= $_SERVER['HTTP_USER_AGENT'];
+  $uid .= $_SERVER['HTTP_ACCEPT_ENCODING'];
+  $uid .= $_SERVER['HTTP_ACCEPT_LANGUAGE'];
+  $uid .= $_SERVER['HTTP_ACCEPT_CHARSET'];
+  $uid .= substr($_SERVER['REMOTE_ADDR'],0,strpos($_SERVER['REMOTE_ADDR'],'.'));
+  return md5($uid);
+}
+
+
+/**
+ * saves user data to Session and cookies
+ */
+function set_session($user,$pass,$dn){
+  global $conf;
+
+  $rand = rand();
+  $_SESSION['ldapab']['username']  = $user;
+  $_SESSION['ldapab']['binddn']    = $dn;
+  $_SESSION['ldapab']['password']  = $pass;
+  $_SESSION['ldapab']['browserid'] = auth_browseruid();
+
+  // (re)set the persistent auth cookie
+  if($user == ''){
+    setcookie('ldapabauth','',time()+60*60*24*365);
+  }elseif(!empty($_REQUEST['remember'])){
+    $cookie = serialize(array($user,$pass));
+    $cookie = x_Encrypt($cookie,get_cookie_secret());
+    $cookie = base64_encode($cookie);
+    setcookie('ldapabauth',$cookie,time()+60*60*24*365);
+  }
+}
+
+/**
+ * Creates a random string to encrypt persistent auth
+ * cookies; the string is stored inside the cache dir
+ */
+function get_cookie_secret(){
+  $file = dirname(__FILE__).'/cache/.htcookiesecret.php';
+  if(@file_exists($file)){
+    return md5(trim(file($file)));
+  }
+
+  $secret = '<?php #'.(rand()*time()).'?>';
+  if(!$fh = fopen($file,'w')) die("Couldn't write to $file");
+  if(fwrite($fh, $secret) === FALSE) die("Couldn't write to $file");
+  fclose($fh);
+
+  return md5($secret);
+}
+
+/**
+ * binary safe function to get all search result data.
+ * It will use ldap_get_values_len() instead and build the array
+ * note: it's similar with the array returned by ldap_get_entries()
+ * except it has no "count" elements
+ *
+ * @author: Original code by Ovidiu Geaboc <ogeaboc@rdanet.com>
+ */
+function ldap_get_binentries($conn,$srchRslt){
+  if(!@ldap_count_entries($conn,$srchRslt)){
+    return null;
+  }
+  $entry = ldap_first_entry($conn, $srchRslt);
+  $i=0;
+  do {
+    $dn = ldap_get_dn($conn,$entry);
+    $attrs = ldap_get_attributes($conn, $entry);
+    for($j=0; $j<$attrs['count']; $j++) {
+      $vals = ldap_get_values_len($conn, $entry,$attrs[$j]);
+      for($k=0; $k<$vals['count']; $k++){
+        $data[$i][$attrs[$j]][$k]=$vals[$k];
+      }
+    }
+    $data[$i]['dn']=$dn;
+    $i++;
+  }while ($entry = ldap_next_entry($conn, $entry));
+
+  return $data;
+}
+
+
+/**
+ * loads ldap names and their cleartext meanings from
+ * entries.conf file and returns it as hash
+ */
+function namedentries($flip=false){
+    trigger_error('deprecated namedentries called',E_USER_WARNING);
+}
+
+/**
+ * Creates an array for submission to ldap from websitedata
+ */
+function prepare_ldap_entry($in){
+  global $conf;
+  global $FIELDS;
+  global $OCLASSES;
+
+  //check dateformats
+  if(!preg_match('/\d\d\d\d-\d\d-\d\d/',$in['anniversary'])) $in['anniversary']='';
+  if(!preg_match('/\d\d\d\d-\d\d-\d\d/',$in['birthday'])) $in['birthday']='';
+
+  // we map all internal names to the configured LDAP attributes here
+  foreach($in as $key => $value){
+    if($FIELDS[$key]){
+        // normal mapped field
+        $out[$FIELDS[$key]][] = $value;
+    }elseif($FIELDS["_$key"]){
+        // mapped multi field
+        if(is_array($value)){
+            $out[$FIELDS["_$key"]] = $value;
+        }else{
+            $out[$FIELDS["_$key"]][] = $value; //shouldn't happen, but to be sure
+        }
+    }else{
+        // no mapping found - assume it to be a LDAP attribute (shouldn't happen)
+        if(is_array($value)){
+            $out[$key] = $value;
+        }else{
+            $out[$key][] = $value;
+        }
+    }
+  }
+
+  // add the Objectclasses
+  $out['objectclass'] = $OCLASSES;
+
+  return clear_array($out);
+}
+
+/**
+ * remove empty element from arrays recursively
+ *
+ * @author Original by <xntx@msn.com>
+ */
+function clear_array ( $a ) {
+  if ($a !== array()) {
+    $b = array();
+    foreach ( $a as $key => $value ) {
+        if (is_array($value)) {
+          if (clear_array($value) !== false) {
+            $b[$key] = clear_array ( $value );
+          }
+        } elseif ($value !== '') {
+          $b[$key] = $value;
+        }
+    }
+    if ($b !== array()) {
+        return $b;
+    } else {
+        return false;
+    }
+  } else {
+    return false;
+  }
+}
+
+/**
+ * deletes an entryfrom ldap - optional with recursion
+ *
+ * @author Original by <gabriel@hrz.uni-marburg.de>
+ */
+function ldap_full_delete($ds,$dn,$recursive=false){
+  if($recursive == false){
+    return(ldap_delete($ds,$dn));
+  }else{
+    //searching for sub entries
+    $sr=ldap_list($ds,$dn,"ObjectClass=*",array(""));
+    $info = ldap_get_entries($ds, $sr);
+    for($i=0;$i<$info['count'];$i++){
+      //deleting recursively sub entries
+      $result=myldap_delete($ds,$info[$i]['dn'],$recursive);
+      if(!$result){
+        //return result code, if delete fails
+        return($result);
+      }
+    }
+    return(ldap_delete($ds,$dn));
+  }
+}
+
+/**
+ * Returns all User Accounts as assoziative array
+ */
+function get_users(){
+  global $conf;
+  global $LDAP_CON;
+
+  $sr = ldap_list($LDAP_CON,$conf['usertree'],"ObjectClass=inetOrgPerson");
+  $result = ldap_get_binentries($LDAP_CON, $sr);
+  $users = array();
+  if(count($result)){
+    foreach ($result as $entry){
+      if(!empty($entry['sn'][0])){
+        $users[$entry['dn']] = $entry['givenName'][0]." ".$entry['sn'][0];
+      }
+    }
+  }
+  return $users;
+}
+
+/**
+ * makes sure the given DN contains exactly one space
+ * after each ,
+ */
+function normalize_dn($dn){
+  $dn = preg_replace('/,/',', ',$dn);
+  $dn = preg_replace('/,\s+/',', ',$dn);
+  return $dn;
+}
+
+/**
+ * Merges the given classes with the existing ones
+ */
+function ldap_store_objectclasses($dn,$classes){
+  global $conf;
+  global $LDAP_CON;
+
+  $sr     = ldap_search($LDAP_CON,$dn,"objectClass=*",array('objectClass'));
+  $result = ldap_get_binentries($LDAP_CON, $sr);
+  $set    = $result[0]['objectClass'];
+  $set    = array_unique_renumber(array_merge((array)$set,(array)$classes));
+  $add['objectClass'] = $set;
+
+  $r = @ldap_mod_replace($LDAP_CON,$dn,$add);
+  tpl_ldaperror();
+
+/*  print '<pre>';
+  print_r($set);
+  print '</pre>';*/
+}
+
+/**
+ * Escape a string to be used in a LDAP filter
+ *
+ * Ported from Perl's Net::LDAP::Util escape_filter_value
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function ldap_filterescape($string){
+  return preg_replace('/([\x00-\x1F\*\(\)\\\\])/e',
+                            '"\\\\\".join("",unpack("H2","$1"))',
+                            $string);
+}
+
+/**
+ * Queries public and private addressbooks, combining the
+ * results
+ *
+ * @todo This function should be used where ever possible, replacing
+ *       lots of duplicate code
+ */
+function ldap_queryabooks($filter,$types){
+  global $conf;
+  global $LDAP_CON;
+
+  // make sure $types is an array
+  if(!is_array($types)){
+    $types = explode(',',$types);
+    $types = array_map('trim',$types);
+  }
+
+  $results = array();
+  $result1 = array();
+  $result2 = array();
+
+  // public addressbook
+  $sr      = ldap_list($LDAP_CON,$conf['publicbook'],
+                       $filter,$types);
+  $result1 = ldap_get_binentries($LDAP_CON, $sr);
+  ldap_free_result($sr);
+
+  // private addressbook
+  if(!empty($_SESSION['ldapab']['binddn'])){
+    $sr      = @ldap_list($LDAP_CON,$conf['privatebook'].
+                          ','.$_SESSION['ldapab']['binddn'],
+                          $filter,$types);
+    $result2 = ldap_get_binentries($LDAP_CON, $sr);
+  }
+
+  // return merged results
+  return array_merge((array)$result1,(array)$result2);
+}
+
+/**
+ * Makes array unique and renumbers the entries
+ *
+ * @author <kay_rules@yahoo.com>
+ */
+function array_unique_renumber($somearray){
+   $tmparr = array_unique($somearray);
+   $i=0;
+   foreach ($tmparr as $v) {
+       $newarr[$i] = $v;
+       $i++;
+   }
+   return $newarr;
+}
+
+/**
+ * Simple XOR encryption
+ *
+ * @author Dustin Schneider
+ * @link http://www.phpbuilder.com/tips/item.php?id=68
+ */
+function x_Encrypt($string, $key){
+    for($i=0; $i<strlen($string); $i++){
+        for($j=0; $j<strlen($key); $j++){
+            $string[$i] = $string[$i]^$key[$j];
+        }
+    }
+    return $string;
+}
+
+/**
+ * Simple XOR decryption
+ *
+ * @author Dustin Schneider
+ * @link http://www.phpbuilder.com/tips/item.php?id=68
+ */
+function x_Decrypt($string, $key){
+    for($i=0; $i<strlen($string); $i++){
+        for($j=0; $j<strlen($key); $j++){
+            $string[$i] = $key[$j]^$string[$i];
+        }
+    }
+    return $string;
+}
+
+/**
+ * Decodes UTF8 recursivly for the given array
+ *
+ * @deprecated
+ */
+function utf8_decode_array(&$array) {
+  trigger_error('deprecated utf8_decode_array called',E_USER_WARNING);
+
+  foreach (array_keys($array) as $key) {
+    if($key === 'dn') continue;
+    if($key === 'jpegPhoto') continue;
+    if (is_array($array[$key])) {
+      utf8_decode_array($array[$key]);
+    }else {
+      $array[$key] = utf8_decode($array[$key]);
+    }
+  }
+}
+
+/**
+ * Encodes the given array to UTF8 recursively
+ *
+ * @deprecated
+ */
+function utf8_encode_array(&$array) {
+  trigger_error('deprecated utf8_encode_array called',E_USER_WARNING);
+
+  foreach (array_keys($array) as $key) {
+    if($key === 'dn') continue;
+    if($key === 'jpegPhoto') continue;
+    if (is_array($array[$key])) {
+      utf8_encode_array($array[$key]);
+    }else {
+      $array[$key] = utf8_encode($array[$key]);
+    }
+  }
+}
+
+
+?>
diff --git a/inc/importVCF.php b/inc/importVCF.php
new file mode 100644 (file)
index 0000000..1138b99
--- /dev/null
@@ -0,0 +1,127 @@
+<?
+  require_once('init.php');
+  require_once('Contact_Vcard_Parse.php');
+  ldap_login();
+
+  if(! $_SESSION['ldapab']['username'] ){
+    header("Location: login.php");
+    exit;
+  }
+
+  $error = '';
+  if(isset($_FILES['userfile'])){
+    if(preg_match('/\.vcf$/i', $_FILES['userfile']['name'])){
+      if (is_uploaded_file($_FILES['userfile']['tmp_name'])) {
+        //parse VCF
+                               $vcfparser = new Contact_Vcard_Parse();
+                               $vcards = $vcfparser->fromFile($_FILES['userfile']['tmp_name']);
+      }else{
+        switch($_FILES['userfile']['error']){
+         case 0: //no error; possible file attack!
+           $error = "There was a problem with your upload.";
+           break;
+         case 1: //uploaded file exceeds the upload_max_filesize directive in php.ini
+           $error = "The file you are trying to upload is too big.";
+           break;
+         case 2: //uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form
+           $error = "The file you are trying to upload is too big.";
+           break;
+         case 3: //uploaded file was only partially uploaded
+           $error = "The file you are trying upload was only partially uploaded.";
+           break;
+         case 4: //no file was uploaded
+           $error = "You must select a VCF file for upload.";
+           break;
+         default: //a default error, just in case!  :)
+           $error = "There was a problem with your upload.";
+           break;
+                 }
+      }
+    }else{
+      $error = "Only VCF extension is allowed";
+    }
+  }
+
+  //prepare templates for all found VCARDs
+  $list = '';
+  if (count($vcards)){
+         foreach ($vcards as $vcard){
+         $entry = vcard_entry($vcard);
+       $smarty->clear_all_assign();
+               tpl_std();
+           $smarty->assign('entry',$entry);
+         $list .= $smarty->fetch('importVCF_entry.tpl');
+         }
+       }
+
+  //prepare templates
+  tpl_std();
+  tpl_orgs();
+  tpl_markers();
+  $smarty->assign('error',$error);
+  $smarty->assign('list',$list);
+  //display templates
+  $smarty->display('header.tpl');
+  $smarty->display('importVCF.tpl');
+  $smarty->display('footer.tpl');
+
+
+function vcard_entry($vcf){
+  $entry['name'] = $vcf['N'][0]['value'][0][0];
+  $entry['givenname'] = trim($vcf['N'][0]['value'][1][0].' '.$vcf['N'][0]['value'][2][0]);
+  $entry['title'] = $vcf['N'][0]['value'][3][0];
+  $entry['organization'] = $vcf['ORG'][0]['value'][0][0];
+  $entry['office'] = $vcf['ORG'][0]['value'][1][0];
+  $entry['note'] = $vcf['NOTE'][0]['value'][0][0];
+  $entry['url'] = $vcf['URL'][0]['value'][0][0];
+  $bday = $vcf['BDAY'][0]['value'][0][0];
+  $entry['anniversary'] = substr($bday,0,4).'-'.substr($bday,4,2).'-'.substr($bday,6,2);
+
+  foreach($vcf['TEL'] as $tel){
+    if(   empty($entry['phone']) &&
+          array_search('WORK',$tel['param']['TYPE']) !== FALSE &&
+          array_search('VOICE',$tel['param']['TYPE']) !== FALSE){
+      // Work phone
+                       $entry['phone'] = $tel['value'][0][0];
+    }elseif(empty($entry['fax']) &&
+            array_search('FAX',$tel['param']['TYPE']) !== FALSE){
+                       $entry['fax'] = $tel['value'][0][0];
+    }elseif(empty($entry['mobile']) &&
+            array_search('CELL',$tel['param']['TYPE']) !== FALSE){
+                       $entry['mobile'] = $tel['value'][0][0];
+    }elseif(empty($entry['pager']) &&
+            array_search('PAGER',$tel['param']['TYPE']) !== FALSE){
+                       $entry['pager'] = $tel['value'][0][0];
+    }elseif(empty($entry['homephone']) &&
+            array_search('HOME',$tel['param']['TYPE']) !== FALSE &&
+            array_search('VOICE',$tel['param']['TYPE']) !== FALSE){
+                       $entry['homephone'] = $tel['value'][0][0];
+    }
+  }
+  foreach($vcf['EMAIL'] as $mail){
+    $entry['mail'][] = $mail['value'][0][0];
+  }
+  foreach($vcf['ADR'] as $adr){
+    if(array_search('HOME',$adr['param']['TYPE']) !== FALSE){
+      $entry['homestreet'] = $adr['value'][2][0]."\n". //str
+                                                                                                                $adr['value'][5][0]." ". //plz
+                             $adr['value'][3][0];      //ort
+
+    }elseif(array_search('WORK',$adr['param']['TYPE']) !== FALSE){
+      $entry['street']   = $adr['value'][2][0];
+      $entry['location'] = $adr['value'][3][0];
+      $entry['plz']      = $adr['value'][5][0];
+    }
+  }
+
+/*
+  print '<pre>';
+  print_r($entry);
+  print '</pre>';
+*/
+
+  return $entry;
+}
+
+
+?>
diff --git a/inc/init.php b/inc/init.php
new file mode 100644 (file)
index 0000000..ad5c900
--- /dev/null
@@ -0,0 +1,42 @@
+<?
+  require_once(dirname(__FILE__).'/config.php');
+  require_once(dirname(__FILE__).'/fields.php');
+  require_once(dirname(__FILE__).'/lang/'.$conf['lang'].'.php');
+  require_once(dirname(__FILE__).'/functions.php');
+  require_once(dirname(__FILE__).'/template.php');
+  require_once(dirname(__FILE__).'/smarty/Smarty.class.php');
+
+  define('NL',"\n");
+
+  //init session
+  session_name("ldapab");
+  session_start();
+
+  //kill magic quotes
+  if (get_magic_quotes_gpc()) {
+    if (!empty($_GET))    remove_magic_quotes($_GET);
+    if (!empty($_POST))   remove_magic_quotes($_POST);
+    if (!empty($_COOKIE)) remove_magic_quotes($_COOKIE);
+    if (!empty($_REQUEST)) remove_magic_quotes($_REQUEST);
+    if (!empty($_SESSION)) remove_magic_quotes($_SESSION);
+    ini_set('magic_quotes_gpc', 0);
+  }
+  set_magic_quotes_runtime(0);
+
+  function remove_magic_quotes(&$array) {
+    foreach (array_keys($array) as $key) {
+      if (is_array($array[$key])) {
+        remove_magic_quotes($array[$key]);
+      }else {
+        $array[$key] = stripslashes($array[$key]);
+      }
+    }
+  }
+
+  //prepare SMARTY object
+  $smarty = new Smarty;
+  $smarty->compile_dir   = dirname(__FILE__).'/../cache';
+  $smarty->use_sub_dirs  = 0;
+  $smarty->template_dir  = dirname(__FILE__).'/../templates';
+  $smarty->force_compile = $conf['smartycompile'];
+?>
diff --git a/inc/lang/ca.php b/inc/lang/ca.php
new file mode 100644 (file)
index 0000000..9464345
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+/**
+ * Catalan language file
+ *
+ * @author Carles Briansó <carles.brianso@antaviana.net>
+ * @author Xavi Pastó <xavi.pasto@antaviana.net>
+ */
+
+$lang['ldapab']           = 'La llibreta d\'adreces LDAP';
+
+$lang['name']             = 'Cognoms';
+$lang['givenname']        = 'Nom';
+$lang['title']            = 'Títol';
+$lang['organization']     = 'Companyia';
+$lang['office']           = 'Oficina';
+$lang['street']           = 'Adreça';
+$lang['zip']              = 'Codi postal';
+$lang['location']         = 'Ciutat';
+$lang['phone']            = 'Telèfon';
+$lang['fax']              = 'Fax';
+$lang['mobile']           = 'Telefon Mòbil';
+$lang['pager']            = 'Buscapersones';
+$lang['homephone']        = 'Telèfon particular';
+$lang['homestreet']       = 'Adreça particular';
+$lang['photo']            = 'Fotografia';
+$lang['url']              = 'Pàgina web';
+$lang['note']             = 'Notes';
+$lang['mail']             = 'Correu electrònic';
+$lang['manager']          = 'Key Account';
+
+$lang['anniversary']      = 'Aniversari';
+$lang['marker']           = 'Tags';
+$lang['tagcloud']         = 'Tots els tags usats, ordenats alfabeticament. Els tags més freqüents es mostren més grans.';
+
+$lang['business']         = 'Feina';
+$lang['private']          = 'Particular';
+$lang['extended']         = 'Informació addicional';
+
+$lang['delphoto']         = 'Esborrar la foto actual';
+
+$lang['notloggedin']      = 'No esteu validats';
+$lang['loggedinas']       = 'L\'usuari validat Ã©s';
+$lang['login']            = 'Valideu-vos';
+$lang['logout']           = 'Sortir';
+$lang['edit']             = 'Editar';
+$lang['show']             = 'Veure';
+$lang['new']              = 'Nou';
+$lang['delete']           = 'Esborrar';
+$lang['copy']             = 'Copiar';
+$lang['csvexport']        = 'CSV';
+$lang['vcfexport']        = 'VCard';
+$lang['vcfimport']        = 'Importar';
+$lang['search']           = 'Buscar';
+$lang['submit']           = 'Enviar';
+$lang['help']             = 'Ajuda';
+$lang['select']           = 'Seleccionar';
+$lang['orgs']             = 'Empreses';
+$lang['upload']           = 'Pujar';
+
+$lang['publicbook']       = 'Llibreta d\'adreçes publica';
+$lang['privatebook']      = 'Llibreta d\'adreçes privada';
+
+$lang['username']         = 'Usuari';
+$lang['password']         = 'Clau';
+$lang['remember']         = 'Recorda\'m en aquest ordinador';
+
+$lang['msg_login']        = 'Valideu-vos, si us plau!';
+$lang['msg_loginfail']    = 'La validació ha fallat';
+$lang['msg_reallydel']    = 'Realment voleu esborrar aquesta l\'entrada?';
+$lang['msg_addto']        = 'Seleccioneu la llibreta d\'addreçes on afegir l\'entrada:';
+$lang['msg_jpegonly']     = 'El sistema només accepta imatges JPEG';
+$lang['msg_dateformat']   = 'YYYY-MM-DD';
+$lang['msg_uploadvcf']    = 'Pugeu un fitxer VCard';
+$lang['msg_tagsep']       = 'Separat per comes';
+
+$lang['err_noentries']    = 'No hi ha entrades';
+$lang['err_ldap']         = 'El servidor LDAP ha tornat els següents errors:';
+
+$lang['openxchange']      = 'Xchange Information';
+$lang['moreopenxchange']  = 'Xchange Information Cont\'d';
+$lang['instantmessenger'] = 'Inst Msg';
+$lang['categories']       = 'Categories';
+$lang['birthday']         = 'Aniversari';
+$lang['domain']           = 'Domini de correu';
+$lang['country']          = 'País';
+$lang['certificate']      = 'x.509 Cert';
+$lang['timezone']         = 'Zona horària';
+$lang['position']         = 'Posició';
+$lang['ipphone']          = 'Telèfon IP';
+
diff --git a/inc/lang/de.php b/inc/lang/de.php
new file mode 100644 (file)
index 0000000..6e84d83
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/**
+ * German language file
+ *
+ * @author Andreas Gohr <gohr@cosmocode.de>
+ */
+
+$lang['ldapab']         = 'Das LDAP Adressbuch';
+
+$lang['name']           = 'Name';
+$lang['givenname']      = 'Vorname';
+$lang['title']          = 'Titel';
+$lang['organization']   = 'Firma';
+$lang['office']         = 'Abteilung';
+$lang['street']         = 'Straße, Nr.';
+$lang['zip']            = 'Postleitzahl';
+$lang['location']       = 'Ort';
+$lang['phone']          = 'Telefon';
+$lang['fax']            = 'FAX';
+$lang['mobile']         = 'Handy';
+$lang['pager']          = 'Pieper';
+$lang['homephone']      = 'Telefon (priv.)';
+$lang['homestreet']     = 'Adresse (priv.)';
+$lang['photo']          = 'Foto';
+$lang['url']            = 'Webseite';
+$lang['note']           = 'Notizen';
+$lang['mail']           = 'E-Mail';
+$lang['manager']        = 'Key Account';
+
+$lang['anniversary']    = 'Jubiläum';
+$lang['marker']         = 'Tags';
+$lang['tagcloud']       = 'Alle verwendeten Tags, alphabetisch sortiert. Häufig verwendete Tags werden größer dargestellt.';
+
+$lang['business']       = 'Geschäftlich';
+$lang['private']        = 'Privat';
+$lang['extended']       = 'Zusätzliche Infos';
+
+$lang['delphoto']       = 'Vorhandenes Foto löschen';
+
+$lang['notloggedin']    = 'Nicht angemeldet';
+$lang['loggedinas']     = 'Angemeldet als';
+$lang['login']          = 'Anmelden';
+$lang['logout']         = 'Abmelden';
+$lang['edit']           = 'Bearbeiten';
+$lang['show']           = 'Anzeigen';
+$lang['new']            = 'Neu';
+$lang['delete']         = 'Löschen';
+$lang['copy']           = 'Kopieren';
+$lang['csvexport']      = 'CSV';
+$lang['vcfexport']      = 'VCard';
+$lang['vcfimport']      = 'Import';
+$lang['search']         = 'Suchen';
+$lang['submit']         = 'Absenden';
+$lang['help']           = 'Hilfe';
+$lang['select']         = 'Auswählen';
+$lang['orgs']           = 'Firmen';
+$lang['upload']         = 'Hochladen';
+
+$lang['publicbook']     = 'Öffentliches Adressbuch';
+$lang['privatebook']    = 'Privates Adressbuch';
+
+
+$lang['username']       = 'Benutzername';
+$lang['password']       = 'Passwort';
+$lang['remember']       = 'Auf diesem Computer angemeldet bleiben';
+
+$lang['msg_login']      = 'Bitte melden sie sich an!';
+$lang['msg_loginfail']  = 'Anmeldung fehlgeschlagen!';
+$lang['msg_reallydel']  = 'Eintrag wirklich löschen?';
+$lang['msg_addto']      = 'Zu welchem Adressbuch soll der Eintrag hinzugefügt werden?';
+$lang['msg_jpegonly']   = 'Nur JPEG';
+$lang['msg_dateformat'] = 'JJJJ-MM-TT';
+$lang['msg_uploadvcf']  = 'Upload VCard File';
+$lang['msg_tagsep']     = 'Durch Komma getrennt';
+
+$lang['err_noentries']  = 'Keine Einträge';
+$lang['err_ldap']       = 'Der LDAP Server lieferte folgende Fehlermeldungen';
+
+
diff --git a/inc/lang/en.php b/inc/lang/en.php
new file mode 100644 (file)
index 0000000..1f2b97d
--- /dev/null
@@ -0,0 +1,94 @@
+<?php
+/**
+ * English language file
+ *
+ * @author Andreas Gohr <gohr@cosmocode.de>
+ */
+
+$lang['ldapab']           = 'The LDAP address book';
+
+$lang['name']             = 'Last Name';
+$lang['givenname']        = 'First Name';
+$lang['title']            = 'Title';
+$lang['organization']     = 'Company';
+$lang['office']           = 'Office';
+$lang['street']           = 'Street No.';
+$lang['zip']              = 'Postal Code';
+$lang['location']         = 'City';
+$lang['state']            = 'State';
+$lang['phone']            = 'Phone';
+$lang['switchboard']      = 'Switchboard';
+$lang['fax']              = 'FAX';
+$lang['mobile']           = 'Mobile';
+$lang['pager']            = 'Pager';
+$lang['homephone']        = 'Phone (priv.)';
+$lang['homestreet']       = 'Address (priv.)';
+$lang['photo']            = 'Picture';
+$lang['url']              = 'Website';
+$lang['note']             = 'Notes';
+$lang['mail']             = 'E-Mail';
+$lang['manager']          = 'Key Account';
+
+$lang['anniversary']      = 'Anniversary';
+$lang['marker']           = 'Tags';
+$lang['tagcloud']         = 'All used tags, sorted alphabetically. Frequently used tags are shown bigger.';
+
+$lang['business']         = 'Business';
+$lang['private']          = 'Private';
+$lang['extended']         = 'Additional Information';
+$lang['communication']    = 'Communication';
+
+$lang['delphoto']         = 'Delete existing photo';
+
+$lang['notloggedin']      = 'Not logged in';
+$lang['loggedinas']       = 'Logged in as';
+$lang['login']            = 'Log in';
+$lang['logout']           = 'Log out';
+$lang['edit']             = 'Edit';
+$lang['show']             = 'Show';
+$lang['new']              = 'New';
+$lang['delete']           = 'Delete';
+$lang['copy']             = 'Copy';
+$lang['csvexport']        = 'CSV';
+$lang['vcfexport']        = 'VCard';
+$lang['vcfimport']        = 'Import';
+$lang['search']           = 'Search';
+$lang['submit']           = 'Save';
+$lang['help']             = 'Help';
+$lang['select']           = 'Select';
+$lang['orgs']             = 'Companies';
+$lang['upload']           = 'Upload';
+
+$lang['publicbook']       = 'Public Addressbook';
+$lang['privatebook']      = 'Private Addressbook';
+
+$lang['username']         = 'Username';
+$lang['password']         = 'Password';
+$lang['remember']         = 'Stay logged in on this computer';
+
+$lang['msg_login']        = 'Please log in!';
+$lang['msg_loginfail']    = 'Log in failed!';
+$lang['msg_reallydel']    = 'Really delete entry?';
+$lang['msg_addto']        = 'Select address book to which the entry should be added:';
+$lang['msg_jpegonly']     = 'JPEG only';
+$lang['msg_dateformat']   = 'YYYY-MM-DD';
+$lang['msg_uploadvcf']    = 'Upload VCard File';
+$lang['msg_tagsep']       = 'Comma separated';
+
+$lang['err_noentries']    = 'No entries';
+$lang['err_ldap']         = 'The LDAP server returned the following errors';
+
+$lang['openxchange']      = 'Xchange Information';
+$lang['moreopenxchange']  = 'Xchange Information Cont\'d';
+$lang['instantmessenger'] = 'Inst Msg';
+$lang['categories']       = 'Categories';
+$lang['birthday']         = 'Birthday';
+$lang['domain']           = 'Mail Domain';
+$lang['country']          = 'Country';
+$lang['certificate']      = 'x.509 Cert';
+$lang['timezone']         = 'Time Zone';
+$lang['position']         = 'Position';
+$lang['department']       = 'Department';
+$lang['ipphone']          = 'IP Phone';
+$lang['spouse']           = 'Spouse';
+?>
diff --git a/inc/lang/fr.php b/inc/lang/fr.php
new file mode 100644 (file)
index 0000000..66aeb96
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+/**
+ * French language file
+ *
+ * @author Geuten Edouard <thegrima@altern.org>
+ */
+
+$lang['ldapab']         = 'Le carnet d\'adresse LDAP';
+
+$lang['name']           = 'Nom de famille';
+$lang['givenname']      = 'Prénom';
+$lang['title']          = 'Titre';
+$lang['organization']   = 'Compagnie';
+$lang['office']         = 'Bureau';
+$lang['street']         = 'N° de rue';
+$lang['zip']            = 'Code Postal';
+$lang['location']       = 'Ville';
+$lang['phone']          = 'Téléphone';
+$lang['fax']            = 'FAX';
+$lang['mobile']         = 'Portable';
+$lang['pager']          = 'Pager';
+$lang['homephone']      = 'Téléphone (priv.)';
+$lang['homestreet']     = 'Adresse (priv.)';
+$lang['photo']          = 'Photo';
+$lang['url']            = 'Site web';
+$lang['note']           = 'Notes';
+$lang['mail']           = 'E-Mail';
+$lang['manager']        = 'Key Account';
+
+$lang['anniversary']    = 'Anniversaire';
+$lang['marker']         = 'Tags';
+$lang['tagcloud']       = 'Tous les marqueurs par ordre alphabétique. Les marqueurs fréquent sont montré plus grand.';
+
+$lang['business']       = 'Business';
+$lang['private']        = 'Privé';
+$lang['extended']       = 'Information Additionelle';
+
+$lang['delphoto']       = 'Effacer la photo existante';
+
+$lang['notloggedin']    = 'Non connecté';
+$lang['loggedinas']     = 'Connecté en tant que';
+$lang['login']          = 'Se connecter';
+$lang['logout']         = 'Se déconnecter';
+$lang['edit']           = 'Editer';
+$lang['show']           = 'Montrer';
+$lang['new']          = 'Nouveau';
+$lang['delete']       = 'Effacer';
+$lang['copy']         = 'Copier';
+$lang['csvexport']      = 'CSV';
+$lang['vcfexport']      = 'VCard';
+$lang['vcfimport']      = 'Import';
+$lang['search']         = 'Rechercher';
+$lang['submit']         = 'Envoyer';
+$lang['help']           = 'Aide';
+$lang['select']         = 'Sélectionner';
+$lang['orgs']           = 'Organisation';
+$lang['upload']         = 'Upload';
+
+$lang['publicbook']     = 'Carnet d\'adresse public';
+$lang['privatebook']    = 'Carnet d\'adresse privé';
+
+$lang['username']       = 'Utilisateur';
+$lang['password']       = 'Mot de passe';
+$lang['remember']       = 'Rester connecté sur cet ordinateur';
+
+$lang['msg_login']      = 'Veuillez vous connecter !';
+$lang['msg_loginfail']  = 'Echec de la connexion !';
+$lang['msg_reallydel']  = 'Voulez-vous vraiment effacer cette entrée ?';
+$lang['msg_addto']      = 'Séléectionnez le carnet d\'adresse ou ajouter une entrée:';
+$lang['msg_jpegonly']   = 'seulement JPEG';
+$lang['msg_dateformat'] = 'YYYY-MM-DD';
+$lang['msg_uploadvcf']  = 'Envoyer un fichier VCard';
+$lang['msg_tagsep']     = 'Séparé par des virgules';
+
+$lang['err_noentries']  = 'Pas d\'entrée';
+$lang['err_ldap']       = 'Le serveur LDAP Ã  retourné les erreurs suivantes';
+
+$lang['openxchange']    = 'Xchange Information';
+$lang['moreopenxchange']    = 'Xchange Information Cont\'d';
+$lang['instantmessenger'] = 'Inst Msg';
+$lang['categories']     = 'Catégories';
+$lang['birthday']       = 'Anniversaire';
+$lang['domain']         = 'Mail Domain';
+$lang['country']        = 'Pays';
+$lang['certificate']    = 'x.509 Cert';
+$lang['timezone']       = 'Fuseau horaire';
+$lang['position']       = 'Position';
+$lang['ipphone']        = 'Téléphone IP';
+
diff --git a/inc/lang/it.php b/inc/lang/it.php
new file mode 100644 (file)
index 0000000..0e24f50
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+/**
+ * Italian language file
+ *
+ * @author Simone Piccardi <piccardi@truelite.it>
+ */ 
+
+$lang['ldapab']           = 'The LDAP address book';
+
+$lang['name']             = 'Cognome';
+$lang['givenname']        = 'Nome';
+$lang['title']            = 'Titolo';
+$lang['organization']     = 'Azienda';
+$lang['office']           = 'Ufficio';
+$lang['street']           = 'Via';
+$lang['zip']              = 'Codice Postale';
+$lang['location']         = 'Citt';
+$lang['phone']            = 'Telefono';
+$lang['fax']              = 'FAX';
+$lang['mobile']           = 'Cellulare';
+$lang['pager']            = 'Pager';
+$lang['homephone']        = 'Telefono (priv.)';
+$lang['homestreet']       = 'Indirizzo (priv.)';
+$lang['photo']            = 'Foto';
+$lang['url']              = 'Sito Web';
+$lang['note']             = 'Note';
+$lang['mail']             = 'E-Mail';
+$lang['manager']          = 'Key Account';
+
+$lang['anniversary']      = 'Compleanno';
+$lang['marker']           = 'Etichetta';
+$lang['tagcloud']         = 'Tutte le etichette in ordine alfaberico. Le piu usate sono piu grandi.';
+
+$lang['business']         = 'Affari';
+$lang['private']          = 'Privato';
+$lang['extended']         = 'Informazione addizionale';
+
+$lang['delphoto']         = 'Cancella foto esistente';
+
+$lang['notloggedin']      = 'Non connesso';
+$lang['loggedinas']       = 'Connesso come';
+$lang['login']            = 'Connetti';
+$lang['logout']           = 'Disconnetti';
+$lang['edit']             = 'Modifica';
+$lang['show']             = 'Mostra';
+$lang['new']              = 'Nuovo';
+$lang['delete']           = 'Cancella';
+$lang['copy']             = 'Copia';
+$lang['csvexport']        = 'CSV';
+$lang['vcfexport']        = 'VCard';
+$lang['vcfimport']        = 'Importa';
+$lang['search']           = 'Cerca';
+$lang['submit']           = 'Invia';
+$lang['help']             = 'Aiuto';
+$lang['select']           = 'Seleziona';
+$lang['orgs']             = 'Aziende';
+$lang['upload']           = 'Carica';
+
+$lang['publicbook']       = 'Indirizzario pubblico';
+$lang['privatebook']      = 'Indirizzario privato';
+
+$lang['username']         = 'Username';
+$lang['password']         = 'Password';
+$lang['remember']         = 'Rimani connesso su questo computer';
+
+$lang['msg_login']        = 'Collegarsi, prego!';
+$lang['msg_loginfail']    = 'Accessi fallito!';
+$lang['msg_reallydel']    = 'Cancella veramente?';
+$lang['msg_addto']        = 'Scegli l\'indirizzario a cui aggiungere la voce:';
+$lang['msg_jpegonly']     = 'Solo JPEG';
+$lang['msg_dateformat']   = 'YYYY-MM-DD';
+$lang['msg_uploadvcf']    = 'Upload VCard File';
+$lang['msg_tagsep']       = 'Separato da virgole';
+
+$lang['err_noentries']    = 'Nessuna voce';
+$lang['err_ldap']         = 'Il server LDAP ha restituito i seguenti errori';
+
+$lang['openxchange']      = 'Xchange Information';
+$lang['moreopenxchange']  = 'Xchange Information Cont\'d';
+$lang['instantmessenger'] = 'Inst Msg';
+$lang['categories']       = 'Categorie';
+$lang['birthday']         = 'Compleanno';
+$lang['domain']           = 'Dominio e-mail';
+$lang['country']          = 'Paese';
+$lang['certificate']      = 'Certificato x.509';
+$lang['timezone']         = 'Fuso orario';
+$lang['position']         = 'Posizione';
+$lang['ipphone']          = 'Telefono IP';
+
diff --git a/inc/lang/nl.php b/inc/lang/nl.php
new file mode 100644 (file)
index 0000000..6c11f73
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+/**
+ * Dutch language file
+ *
+ * @author Riny Heijdendael <riny@heijdendael.nl>
+ */
+
+$lang['ldapab']           = 'Het LDAP adresboek';
+
+$lang['name']             = 'Achternaam';
+$lang['givenname']        = 'Voornaam';
+$lang['title']            = 'Titel';
+$lang['organization']     = 'Bedrijf';
+$lang['office']           = 'Kantoor';
+$lang['street']           = 'Straat';
+$lang['zip']              = 'Postcode';
+$lang['location']         = 'Stad';
+$lang['phone']            = 'Telefoon';
+$lang['fax']              = 'FAX';
+$lang['mobile']           = 'Mobiel';
+$lang['pager']            = 'Pager';
+$lang['homephone']        = 'Telefoon (priv.)';
+$lang['homestreet']       = 'Adres (priv.)';
+$lang['photo']            = 'Afbeelding';
+$lang['url']              = 'Website';
+$lang['note']             = 'Aantekeningen';
+$lang['mail']             = 'E-Mail';
+$lang['manager']          = 'Key Account';
+
+$lang['anniversary']      = 'Verjaardag';
+$lang['marker']           = 'Categorieen';
+$lang['tagcloud']         = 'Alle gebruikte categorieen, op alfabet gesorteerd. Veelgebruikte categorieen worden groter afgebeeld';
+
+$lang['business']         = 'Bedrijf';
+$lang['private']          = 'Prive';
+$lang['extended']         = 'Overige informatie';
+
+$lang['delphoto']         = 'Verwijder bestaande afbeelding';
+
+$lang['notloggedin']      = 'Niet ingelogd';
+$lang['loggedinas']       = 'Ingelogd als';
+$lang['login']            = 'Log in';
+$lang['logout']           = 'Log uit';
+$lang['edit']             = 'Wijzig';
+$lang['show']             = 'Toon';
+$lang['new']              = 'Nieuw';
+$lang['delete']           = 'Verwijder';
+$lang['copy']             = 'Dupliceer';
+$lang['csvexport']        = 'CSV';
+$lang['vcfexport']        = 'VCard';
+$lang['vcfimport']        = 'Importeer';
+$lang['search']           = 'Zoek';
+$lang['submit']           = 'Verstuur';
+$lang['help']             = 'Help';
+$lang['select']           = 'Selecteer';
+$lang['orgs']             = 'Bedrijven';
+$lang['upload']           = 'Upload';
+
+$lang['publicbook']       = 'Publiek Adresboek';
+$lang['privatebook']      = 'Persoonlijk Adresboek';
+
+$lang['username']         = 'Gebruikersnaam';
+$lang['password']         = 'Wachtwoord';
+$lang['remember']         = 'Blijf ingelogd op deze computer';
+
+$lang['msg_login']        = 'Log eerst in SVP!';
+$lang['msg_loginfail']    = 'Inloggen mislukt!';
+$lang['msg_reallydel']    = 'Deze definitief verwijderen?';
+$lang['msg_addto']        = 'Kies adresboek om op te slaan:';
+$lang['msg_jpegonly']     = 'Alleen JPEG afbeeldingen';
+$lang['msg_dateformat']   = 'YYYY-MM-DD';
+$lang['msg_uploadvcf']    = 'Upload VCard bestand';
+$lang['msg_tagsep']       = 'Komma gescheiden (CSV)';
+
+$lang['err_noentries']    = 'Geen gegevens';
+$lang['err_ldap']         = 'De LDAP server meldt de volgende fouten:';
+
+$lang['openxchange']      = 'Xchange Informatie';
+$lang['moreopenxchange']  = 'Xchange Informatie (meer..)';
+$lang['instantmessenger'] = 'Intstant messenger';
+$lang['categories']       = 'Categorieen';
+$lang['birthday']         = 'Verjaardag';
+$lang['domain']           = 'Email domein';
+$lang['country']          = 'Land';
+$lang['certificate']      = 'x.509 Certificaat';
+$lang['timezone']         = 'Tijdzone';
+$lang['position']         = 'Positie';
+$lang['ipphone']          = 'VOIP Telefoon';
+
+
diff --git a/inc/smarty/Config_File.class.php b/inc/smarty/Config_File.class.php
new file mode 100644 (file)
index 0000000..3d7c1b4
--- /dev/null
@@ -0,0 +1,389 @@
+<?php
+
+/**
+ * Config_File class.
+ *
+ * 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
+ *
+ * @link http://smarty.php.net/
+ * @version 2.6.18
+ * @copyright Copyright: 2001-2005 New Digital Group, Inc.
+ * @author Andrei Zmievski <andrei@php.net>
+ * @access public
+ * @package Smarty
+ */
+
+/* $Id: Config_File.class.php,v 1.88 2007/03/06 10:40:06 messju Exp $ */
+
+/**
+ * Config file reading class
+ * @package Smarty
+ */
+class Config_File {
+    /**#@+
+     * Options
+     * @var boolean
+     */
+    /**
+     * Controls whether variables with the same name overwrite each other.
+     */
+    var $overwrite        =    true;
+
+    /**
+     * Controls whether config values of on/true/yes and off/false/no get
+     * converted to boolean values automatically.
+     */
+    var $booleanize        =    true;
+
+    /**
+     * Controls whether hidden config sections/vars are read from the file.
+     */
+    var $read_hidden     =    true;
+
+    /**
+     * Controls whether or not to fix mac or dos formatted newlines.
+     * If set to true, \r or \r\n will be changed to \n.
+     */
+    var $fix_newlines =    true;
+    /**#@-*/
+
+    /** @access private */
+    var $_config_path    = "";
+    var $_config_data    = array();
+    /**#@-*/
+
+    /**
+     * Constructs a new config file class.
+     *
+     * @param string $config_path (optional) path to the config files
+     */
+    function Config_File($config_path = NULL)
+    {
+        if (isset($config_path))
+            $this->set_path($config_path);
+    }
+
+
+    /**
+     * Set the path where configuration files can be found.
+     *
+     * @param string $config_path path to the config files
+     */
+    function set_path($config_path)
+    {
+        if (!empty($config_path)) {
+            if (!is_string($config_path) || !file_exists($config_path) || !is_dir($config_path)) {
+                $this->_trigger_error_msg("Bad config file path '$config_path'");
+                return;
+            }
+            if(substr($config_path, -1) != DIRECTORY_SEPARATOR) {
+                $config_path .= DIRECTORY_SEPARATOR;
+            }
+
+            $this->_config_path = $config_path;
+        }
+    }
+
+
+    /**
+     * Retrieves config info based on the file, section, and variable name.
+     *
+     * @param string $file_name config file to get info for
+     * @param string $section_name (optional) section to get info for
+     * @param string $var_name (optional) variable to get info for
+     * @return string|array a value or array of values
+     */
+    function get($file_name, $section_name = NULL, $var_name = NULL)
+    {
+        if (empty($file_name)) {
+            $this->_trigger_error_msg('Empty config file name');
+            return;
+        } else {
+            $file_name = $this->_config_path . $file_name;
+            if (!isset($this->_config_data[$file_name]))
+                $this->load_file($file_name, false);
+        }
+
+        if (!empty($var_name)) {
+            if (empty($section_name)) {
+                return $this->_config_data[$file_name]["vars"][$var_name];
+            } else {
+                if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name]))
+                    return $this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name];
+                else
+                    return array();
+            }
+        } else {
+            if (empty($section_name)) {
+                return (array)$this->_config_data[$file_name]["vars"];
+            } else {
+                if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"]))
+                    return (array)$this->_config_data[$file_name]["sections"][$section_name]["vars"];
+                else
+                    return array();
+            }
+        }
+    }
+
+
+    /**
+     * Retrieves config info based on the key.
+     *
+     * @param $file_name string config key (filename/section/var)
+     * @return string|array same as get()
+     * @uses get() retrieves information from config file and returns it
+     */
+    function &get_key($config_key)
+    {
+        list($file_name, $section_name, $var_name) = explode('/', $config_key, 3);
+        $result = &$this->get($file_name, $section_name, $var_name);
+        return $result;
+    }
+
+    /**
+     * Get all loaded config file names.
+     *
+     * @return array an array of loaded config file names
+     */
+    function get_file_names()
+    {
+        return array_keys($this->_config_data);
+    }
+
+
+    /**
+     * Get all section names from a loaded file.
+     *
+     * @param string $file_name config file to get section names from
+     * @return array an array of section names from the specified file
+     */
+    function get_section_names($file_name)
+    {
+        $file_name = $this->_config_path . $file_name;
+        if (!isset($this->_config_data[$file_name])) {
+            $this->_trigger_error_msg("Unknown config file '$file_name'");
+            return;
+        }
+
+        return array_keys($this->_config_data[$file_name]["sections"]);
+    }
+
+
+    /**
+     * Get all global or section variable names.
+     *
+     * @param string $file_name config file to get info for
+     * @param string $section_name (optional) section to get info for
+     * @return array an array of variables names from the specified file/section
+     */
+    function get_var_names($file_name, $section = NULL)
+    {
+        if (empty($file_name)) {
+            $this->_trigger_error_msg('Empty config file name');
+            return;
+        } else if (!isset($this->_config_data[$file_name])) {
+            $this->_trigger_error_msg("Unknown config file '$file_name'");
+            return;
+        }
+
+        if (empty($section))
+            return array_keys($this->_config_data[$file_name]["vars"]);
+        else
+            return array_keys($this->_config_data[$file_name]["sections"][$section]["vars"]);
+    }
+
+
+    /**
+     * Clear loaded config data for a certain file or all files.
+     *
+     * @param string $file_name file to clear config data for
+     */
+    function clear($file_name = NULL)
+    {
+        if ($file_name === NULL)
+            $this->_config_data = array();
+        else if (isset($this->_config_data[$file_name]))
+            $this->_config_data[$file_name] = array();
+    }
+
+
+    /**
+     * Load a configuration file manually.
+     *
+     * @param string $file_name file name to load
+     * @param boolean $prepend_path whether current config path should be
+     *                              prepended to the filename
+     */
+    function load_file($file_name, $prepend_path = true)
+    {
+        if ($prepend_path && $this->_config_path != "")
+            $config_file = $this->_config_path . $file_name;
+        else
+            $config_file = $file_name;
+
+        ini_set('track_errors', true);
+        $fp = @fopen($config_file, "r");
+        if (!is_resource($fp)) {
+            $this->_trigger_error_msg("Could not open config file '$config_file'");
+            return false;
+        }
+
+        $contents = ($size = filesize($config_file)) ? fread($fp, $size) : '';
+        fclose($fp);
+
+        $this->_config_data[$config_file] = $this->parse_contents($contents);
+        return true;
+    }
+
+    /**
+     * Store the contents of a file manually.
+     *
+     * @param string $config_file file name of the related contents
+     * @param string $contents the file-contents to parse
+     */
+    function set_file_contents($config_file, $contents)
+    {
+        $this->_config_data[$config_file] = $this->parse_contents($contents);
+        return true;
+    }
+
+    /**
+     * parse the source of a configuration file manually.
+     *
+     * @param string $contents the file-contents to parse
+     */
+    function parse_contents($contents)
+    {
+        if($this->fix_newlines) {
+            // fix mac/dos formatted newlines
+            $contents = preg_replace('!\r\n?!', "\n", $contents);
+        }
+
+        $config_data = array();
+        $config_data['sections'] = array();
+        $config_data['vars'] = array();
+
+        /* reference to fill with data */
+        $vars =& $config_data['vars'];
+
+        /* parse file line by line */
+        preg_match_all('!^.*\r?\n?!m', $contents, $match);
+        $lines = $match[0];
+        for ($i=0, $count=count($lines); $i<$count; $i++) {
+            $line = $lines[$i];
+            if (empty($line)) continue;
+
+            if ( substr($line, 0, 1) == '[' && preg_match('!^\[(.*?)\]!', $line, $match) ) {
+                /* section found */
+                if (substr($match[1], 0, 1) == '.') {
+                    /* hidden section */
+                    if ($this->read_hidden) {
+                        $section_name = substr($match[1], 1);
+                    } else {
+                        /* break reference to $vars to ignore hidden section */
+                        unset($vars);
+                        $vars = array();
+                        continue;
+                    }
+                } else {                    
+                    $section_name = $match[1];
+                }
+                if (!isset($config_data['sections'][$section_name]))
+                    $config_data['sections'][$section_name] = array('vars' => array());
+                $vars =& $config_data['sections'][$section_name]['vars'];
+                continue;
+            }
+
+            if (preg_match('/^\s*(\.?\w+)\s*=\s*(.*)/s', $line, $match)) {
+                /* variable found */
+                $var_name = rtrim($match[1]);
+                if (strpos($match[2], '"""') === 0) {
+                    /* handle multiline-value */
+                    $lines[$i] = substr($match[2], 3);
+                    $var_value = '';
+                    while ($i<$count) {
+                        if (($pos = strpos($lines[$i], '"""')) === false) {
+                            $var_value .= $lines[$i++];
+                        } else {
+                            /* end of multiline-value */
+                            $var_value .= substr($lines[$i], 0, $pos);
+                            break;
+                        }
+                    }
+                    $booleanize = false;
+
+                } else {
+                    /* handle simple value */
+                    $var_value = preg_replace('/^([\'"])(.*)\1$/', '\2', rtrim($match[2]));
+                    $booleanize = $this->booleanize;
+
+                }
+                $this->_set_config_var($vars, $var_name, $var_value, $booleanize);
+            }
+            /* else unparsable line / means it is a comment / means ignore it */
+        }
+        return $config_data;
+    }
+
+    /**#@+ @access private */
+    /**
+     * @param array &$container
+     * @param string $var_name
+     * @param mixed $var_value
+     * @param boolean $booleanize determines whether $var_value is converted to
+     *                            to true/false
+     */
+    function _set_config_var(&$container, $var_name, $var_value, $booleanize)
+    {
+        if (substr($var_name, 0, 1) == '.') {
+            if (!$this->read_hidden)
+                return;
+            else
+                $var_name = substr($var_name, 1);
+        }
+
+        if (!preg_match("/^[a-zA-Z_]\w*$/", $var_name)) {
+            $this->_trigger_error_msg("Bad variable name '$var_name'");
+            return;
+        }
+
+        if ($booleanize) {
+            if (preg_match("/^(on|true|yes)$/i", $var_value))
+                $var_value = true;
+            else if (preg_match("/^(off|false|no)$/i", $var_value))
+                $var_value = false;
+        }
+
+        if (!isset($container[$var_name]) || $this->overwrite)
+            $container[$var_name] = $var_value;
+        else {
+            settype($container[$var_name], 'array');
+            $container[$var_name][] = $var_value;
+        }
+    }
+
+    /**
+     * @uses trigger_error() creates a PHP warning/error
+     * @param string $error_msg
+     * @param integer $error_type one of
+     */
+    function _trigger_error_msg($error_msg, $error_type = E_USER_WARNING)
+    {
+        trigger_error("Config_File error: $error_msg", $error_type);
+    }
+    /**#@-*/
+}
+
+?>
diff --git a/inc/smarty/Smarty.class.php b/inc/smarty/Smarty.class.php
new file mode 100644 (file)
index 0000000..f05e0da
--- /dev/null
@@ -0,0 +1,1944 @@
+<?php
+
+/**
+ * Project:     Smarty: the PHP compiling template engine
+ * File:        Smarty.class.php
+ *
+ * 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
+ *
+ * For questions, help, comments, discussion, etc., please join the
+ * Smarty mailing list. Send a blank e-mail to
+ * smarty-general-subscribe@lists.php.net
+ *
+ * @link http://smarty.php.net/
+ * @copyright 2001-2005 New Digital Group, Inc.
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author Andrei Zmievski <andrei@php.net>
+ * @package Smarty
+ * @version 2.6.18
+ */
+
+/* $Id: Smarty.class.php,v 1.528 2007/03/06 10:40:06 messju Exp $ */
+
+/**
+ * DIR_SEP isn't used anymore, but third party apps might
+ */
+if(!defined('DIR_SEP')) {
+    define('DIR_SEP', DIRECTORY_SEPARATOR);
+}
+
+/**
+ * set SMARTY_DIR to absolute path to Smarty library files.
+ * if not defined, include_path will be used. Sets SMARTY_DIR only if user
+ * application has not already defined it.
+ */
+
+if (!defined('SMARTY_DIR')) {
+    define('SMARTY_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR);
+}
+
+if (!defined('SMARTY_CORE_DIR')) {
+    define('SMARTY_CORE_DIR', SMARTY_DIR . 'internals' . DIRECTORY_SEPARATOR);
+}
+
+define('SMARTY_PHP_PASSTHRU',   0);
+define('SMARTY_PHP_QUOTE',      1);
+define('SMARTY_PHP_REMOVE',     2);
+define('SMARTY_PHP_ALLOW',      3);
+
+/**
+ * @package Smarty
+ */
+class Smarty
+{
+    /**#@+
+     * Smarty Configuration Section
+     */
+
+    /**
+     * The name of the directory where templates are located.
+     *
+     * @var string
+     */
+    var $template_dir    =  'templates';
+
+    /**
+     * The directory where compiled templates are located.
+     *
+     * @var string
+     */
+    var $compile_dir     =  'templates_c';
+
+    /**
+     * The directory where config files are located.
+     *
+     * @var string
+     */
+    var $config_dir      =  'configs';
+
+    /**
+     * An array of directories searched for plugins.
+     *
+     * @var array
+     */
+    var $plugins_dir     =  array('plugins');
+
+    /**
+     * If debugging is enabled, a debug console window will display
+     * when the page loads (make sure your browser allows unrequested
+     * popup windows)
+     *
+     * @var boolean
+     */
+    var $debugging       =  false;
+
+    /**
+     * When set, smarty does uses this value as error_reporting-level.
+     *
+     * @var boolean
+     */
+    var $error_reporting  =  null;
+
+    /**
+     * This is the path to the debug console template. If not set,
+     * the default one will be used.
+     *
+     * @var string
+     */
+    var $debug_tpl       =  '';
+
+    /**
+     * This determines if debugging is enable-able from the browser.
+     * <ul>
+     *  <li>NONE => no debugging control allowed</li>
+     *  <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
+     * </ul>
+     * @link http://www.foo.dom/index.php?SMARTY_DEBUG
+     * @var string
+     */
+    var $debugging_ctrl  =  'NONE';
+
+    /**
+     * This tells Smarty whether to check for recompiling or not. Recompiling
+     * does not need to happen unless a template or config file is changed.
+     * Typically you enable this during development, and disable for
+     * production.
+     *
+     * @var boolean
+     */
+    var $compile_check   =  true;
+
+    /**
+     * This forces templates to compile every time. Useful for development
+     * or debugging.
+     *
+     * @var boolean
+     */
+    var $force_compile   =  false;
+
+    /**
+     * This enables template caching.
+     * <ul>
+     *  <li>0 = no caching</li>
+     *  <li>1 = use class cache_lifetime value</li>
+     *  <li>2 = use cache_lifetime in cache file</li>
+     * </ul>
+     * @var integer
+     */
+    var $caching         =  0;
+
+    /**
+     * The name of the directory for cache files.
+     *
+     * @var string
+     */
+    var $cache_dir       =  'cache';
+
+    /**
+     * This is the number of seconds cached content will persist.
+     * <ul>
+     *  <li>0 = always regenerate cache</li>
+     *  <li>-1 = never expires</li>
+     * </ul>
+     *
+     * @var integer
+     */
+    var $cache_lifetime  =  3600;
+
+    /**
+     * Only used when $caching is enabled. If true, then If-Modified-Since headers
+     * are respected with cached content, and appropriate HTTP headers are sent.
+     * This way repeated hits to a cached page do not send the entire page to the
+     * client every time.
+     *
+     * @var boolean
+     */
+    var $cache_modified_check = false;
+
+    /**
+     * This determines how Smarty handles "<?php ... ?>" tags in templates.
+     * possible values:
+     * <ul>
+     *  <li>SMARTY_PHP_PASSTHRU -> print tags as plain text</li>
+     *  <li>SMARTY_PHP_QUOTE    -> escape tags as entities</li>
+     *  <li>SMARTY_PHP_REMOVE   -> remove php tags</li>
+     *  <li>SMARTY_PHP_ALLOW    -> execute php tags</li>
+     * </ul>
+     *
+     * @var integer
+     */
+    var $php_handling    =  SMARTY_PHP_PASSTHRU;
+
+    /**
+     * This enables template security. When enabled, many things are restricted
+     * in the templates that normally would go unchecked. This is useful when
+     * untrusted parties are editing templates and you want a reasonable level
+     * of security. (no direct execution of PHP in templates for example)
+     *
+     * @var boolean
+     */
+    var $security       =   false;
+
+    /**
+     * This is the list of template directories that are considered secure. This
+     * is used only if {@link $security} is enabled. One directory per array
+     * element.  {@link $template_dir} is in this list implicitly.
+     *
+     * @var array
+     */
+    var $secure_dir     =   array();
+
+    /**
+     * These are the security settings for Smarty. They are used only when
+     * {@link $security} is enabled.
+     *
+     * @var array
+     */
+    var $security_settings  = array(
+                                    'PHP_HANDLING'    => false,
+                                    'IF_FUNCS'        => array('array', 'list',
+                                                               'isset', 'empty',
+                                                               'count', 'sizeof',
+                                                               'in_array', 'is_array',
+                                                               'true', 'false', 'null'),
+                                    'INCLUDE_ANY'     => false,
+                                    'PHP_TAGS'        => false,
+                                    'MODIFIER_FUNCS'  => array('count'),
+                                    'ALLOW_CONSTANTS'  => false
+                                   );
+
+    /**
+     * This is an array of directories where trusted php scripts reside.
+     * {@link $security} is disabled during their inclusion/execution.
+     *
+     * @var array
+     */
+    var $trusted_dir        = array();
+
+    /**
+     * The left delimiter used for the template tags.
+     *
+     * @var string
+     */
+    var $left_delimiter  =  '{';
+
+    /**
+     * The right delimiter used for the template tags.
+     *
+     * @var string
+     */
+    var $right_delimiter =  '}';
+
+    /**
+     * The order in which request variables are registered, similar to
+     * variables_order in php.ini E = Environment, G = GET, P = POST,
+     * C = Cookies, S = Server
+     *
+     * @var string
+     */
+    var $request_vars_order    = 'EGPCS';
+
+    /**
+     * Indicates wether $HTTP_*_VARS[] (request_use_auto_globals=false)
+     * are uses as request-vars or $_*[]-vars. note: if
+     * request_use_auto_globals is true, then $request_vars_order has
+     * no effect, but the php-ini-value "gpc_order"
+     *
+     * @var boolean
+     */
+    var $request_use_auto_globals      = true;
+
+    /**
+     * Set this if you want different sets of compiled files for the same
+     * templates. This is useful for things like different languages.
+     * Instead of creating separate sets of templates per language, you
+     * set different compile_ids like 'en' and 'de'.
+     *
+     * @var string
+     */
+    var $compile_id            = null;
+
+    /**
+     * This tells Smarty whether or not to use sub dirs in the cache/ and
+     * templates_c/ directories. sub directories better organized, but
+     * may not work well with PHP safe mode enabled.
+     *
+     * @var boolean
+     *
+     */
+    var $use_sub_dirs          = false;
+
+    /**
+     * This is a list of the modifiers to apply to all template variables.
+     * Put each modifier in a separate array element in the order you want
+     * them applied. example: <code>array('escape:"htmlall"');</code>
+     *
+     * @var array
+     */
+    var $default_modifiers        = array();
+
+    /**
+     * This is the resource type to be used when not specified
+     * at the beginning of the resource path. examples:
+     * $smarty->display('file:index.tpl');
+     * $smarty->display('db:index.tpl');
+     * $smarty->display('index.tpl'); // will use default resource type
+     * {include file="file:index.tpl"}
+     * {include file="db:index.tpl"}
+     * {include file="index.tpl"} {* will use default resource type *}
+     *
+     * @var array
+     */
+    var $default_resource_type    = 'file';
+
+    /**
+     * The function used for cache file handling. If not set, built-in caching is used.
+     *
+     * @var null|string function name
+     */
+    var $cache_handler_func   = null;
+
+    /**
+     * This indicates which filters are automatically loaded into Smarty.
+     *
+     * @var array array of filter names
+     */
+    var $autoload_filters = array();
+
+    /**#@+
+     * @var boolean
+     */
+    /**
+     * This tells if config file vars of the same name overwrite each other or not.
+     * if disabled, same name variables are accumulated in an array.
+     */
+    var $config_overwrite = true;
+
+    /**
+     * This tells whether or not to automatically booleanize config file variables.
+     * If enabled, then the strings "on", "true", and "yes" are treated as boolean
+     * true, and "off", "false" and "no" are treated as boolean false.
+     */
+    var $config_booleanize = true;
+
+    /**
+     * This tells whether hidden sections [.foobar] are readable from the
+     * tempalates or not. Normally you would never allow this since that is
+     * the point behind hidden sections: the application can access them, but
+     * the templates cannot.
+     */
+    var $config_read_hidden = false;
+
+    /**
+     * This tells whether or not automatically fix newlines in config files.
+     * It basically converts \r (mac) or \r\n (dos) to \n
+     */
+    var $config_fix_newlines = true;
+    /**#@-*/
+
+    /**
+     * If a template cannot be found, this PHP function will be executed.
+     * Useful for creating templates on-the-fly or other special action.
+     *
+     * @var string function name
+     */
+    var $default_template_handler_func = '';
+
+    /**
+     * The file that contains the compiler class. This can a full
+     * pathname, or relative to the php_include path.
+     *
+     * @var string
+     */
+    var $compiler_file        =    'Smarty_Compiler.class.php';
+
+    /**
+     * The class used for compiling templates.
+     *
+     * @var string
+     */
+    var $compiler_class        =   'Smarty_Compiler';
+
+    /**
+     * The class used to load config vars.
+     *
+     * @var string
+     */
+    var $config_class          =   'Config_File';
+
+/**#@+
+ * END Smarty Configuration Section
+ * There should be no need to touch anything below this line.
+ * @access private
+ */
+    /**
+     * where assigned template vars are kept
+     *
+     * @var array
+     */
+    var $_tpl_vars             = array();
+
+    /**
+     * stores run-time $smarty.* vars
+     *
+     * @var null|array
+     */
+    var $_smarty_vars          = null;
+
+    /**
+     * keeps track of sections
+     *
+     * @var array
+     */
+    var $_sections             = array();
+
+    /**
+     * keeps track of foreach blocks
+     *
+     * @var array
+     */
+    var $_foreach              = array();
+
+    /**
+     * keeps track of tag hierarchy
+     *
+     * @var array
+     */
+    var $_tag_stack            = array();
+
+    /**
+     * configuration object
+     *
+     * @var Config_file
+     */
+    var $_conf_obj             = null;
+
+    /**
+     * loaded configuration settings
+     *
+     * @var array
+     */
+    var $_config               = array(array('vars'  => array(), 'files' => array()));
+
+    /**
+     * md5 checksum of the string 'Smarty'
+     *
+     * @var string
+     */
+    var $_smarty_md5           = 'f8d698aea36fcbead2b9d5359ffca76f';
+
+    /**
+     * Smarty version number
+     *
+     * @var string
+     */
+    var $_version              = '2.6.18';
+
+    /**
+     * current template inclusion depth
+     *
+     * @var integer
+     */
+    var $_inclusion_depth      = 0;
+
+    /**
+     * for different compiled templates
+     *
+     * @var string
+     */
+    var $_compile_id           = null;
+
+    /**
+     * text in URL to enable debug mode
+     *
+     * @var string
+     */
+    var $_smarty_debug_id      = 'SMARTY_DEBUG';
+
+    /**
+     * debugging information for debug console
+     *
+     * @var array
+     */
+    var $_smarty_debug_info    = array();
+
+    /**
+     * info that makes up a cache file
+     *
+     * @var array
+     */
+    var $_cache_info           = array();
+
+    /**
+     * default file permissions
+     *
+     * @var integer
+     */
+    var $_file_perms           = 0644;
+
+    /**
+     * default dir permissions
+     *
+     * @var integer
+     */
+    var $_dir_perms               = 0771;
+
+    /**
+     * registered objects
+     *
+     * @var array
+     */
+    var $_reg_objects           = array();
+
+    /**
+     * table keeping track of plugins
+     *
+     * @var array
+     */
+    var $_plugins              = array(
+                                       'modifier'      => array(),
+                                       'function'      => array(),
+                                       'block'         => array(),
+                                       'compiler'      => array(),
+                                       'prefilter'     => array(),
+                                       'postfilter'    => array(),
+                                       'outputfilter'  => array(),
+                                       'resource'      => array(),
+                                       'insert'        => array());
+
+
+    /**
+     * cache serials
+     *
+     * @var array
+     */
+    var $_cache_serials = array();
+
+    /**
+     * name of optional cache include file
+     *
+     * @var string
+     */
+    var $_cache_include = null;
+
+    /**
+     * indicate if the current code is used in a compiled
+     * include
+     *
+     * @var string
+     */
+    var $_cache_including = false;
+
+    /**#@-*/
+    /**
+     * The class constructor.
+     */
+    function Smarty()
+    {
+      $this->assign('SCRIPT_NAME', isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME']
+                    : @$GLOBALS['HTTP_SERVER_VARS']['SCRIPT_NAME']);
+    }
+
+    /**
+     * assigns values to template variables
+     *
+     * @param array|string $tpl_var the template variable name(s)
+     * @param mixed $value the value to assign
+     */
+    function assign($tpl_var, $value = null)
+    {
+        if (is_array($tpl_var)){
+            foreach ($tpl_var as $key => $val) {
+                if ($key != '') {
+                    $this->_tpl_vars[$key] = $val;
+                }
+            }
+        } else {
+            if ($tpl_var != '')
+                $this->_tpl_vars[$tpl_var] = $value;
+        }
+    }
+
+    /**
+     * assigns values to template variables by reference
+     *
+     * @param string $tpl_var the template variable name
+     * @param mixed $value the referenced value to assign
+     */
+    function assign_by_ref($tpl_var, &$value)
+    {
+        if ($tpl_var != '')
+            $this->_tpl_vars[$tpl_var] = &$value;
+    }
+
+    /**
+     * appends values to template variables
+     *
+     * @param array|string $tpl_var the template variable name(s)
+     * @param mixed $value the value to append
+     */
+    function append($tpl_var, $value=null, $merge=false)
+    {
+        if (is_array($tpl_var)) {
+            // $tpl_var is an array, ignore $value
+            foreach ($tpl_var as $_key => $_val) {
+                if ($_key != '') {
+                    if(!@is_array($this->_tpl_vars[$_key])) {
+                        settype($this->_tpl_vars[$_key],'array');
+                    }
+                    if($merge && is_array($_val)) {
+                        foreach($_val as $_mkey => $_mval) {
+                            $this->_tpl_vars[$_key][$_mkey] = $_mval;
+                        }
+                    } else {
+                        $this->_tpl_vars[$_key][] = $_val;
+                    }
+                }
+            }
+        } else {
+            if ($tpl_var != '' && isset($value)) {
+                if(!@is_array($this->_tpl_vars[$tpl_var])) {
+                    settype($this->_tpl_vars[$tpl_var],'array');
+                }
+                if($merge && is_array($value)) {
+                    foreach($value as $_mkey => $_mval) {
+                        $this->_tpl_vars[$tpl_var][$_mkey] = $_mval;
+                    }
+                } else {
+                    $this->_tpl_vars[$tpl_var][] = $value;
+                }
+            }
+        }
+    }
+
+    /**
+     * appends values to template variables by reference
+     *
+     * @param string $tpl_var the template variable name
+     * @param mixed $value the referenced value to append
+     */
+    function append_by_ref($tpl_var, &$value, $merge=false)
+    {
+        if ($tpl_var != '' && isset($value)) {
+            if(!@is_array($this->_tpl_vars[$tpl_var])) {
+             settype($this->_tpl_vars[$tpl_var],'array');
+            }
+            if ($merge && is_array($value)) {
+                foreach($value as $_key => $_val) {
+                    $this->_tpl_vars[$tpl_var][$_key] = &$value[$_key];
+                }
+            } else {
+                $this->_tpl_vars[$tpl_var][] = &$value;
+            }
+        }
+    }
+
+
+    /**
+     * clear the given assigned template variable.
+     *
+     * @param string $tpl_var the template variable to clear
+     */
+    function clear_assign($tpl_var)
+    {
+        if (is_array($tpl_var))
+            foreach ($tpl_var as $curr_var)
+                unset($this->_tpl_vars[$curr_var]);
+        else
+            unset($this->_tpl_vars[$tpl_var]);
+    }
+
+
+    /**
+     * Registers custom function to be used in templates
+     *
+     * @param string $function the name of the template function
+     * @param string $function_impl the name of the PHP function to register
+     */
+    function register_function($function, $function_impl, $cacheable=true, $cache_attrs=null)
+    {
+        $this->_plugins['function'][$function] =
+            array($function_impl, null, null, false, $cacheable, $cache_attrs);
+
+    }
+
+    /**
+     * Unregisters custom function
+     *
+     * @param string $function name of template function
+     */
+    function unregister_function($function)
+    {
+        unset($this->_plugins['function'][$function]);
+    }
+
+    /**
+     * Registers object to be used in templates
+     *
+     * @param string $object name of template object
+     * @param object &$object_impl the referenced PHP object to register
+     * @param null|array $allowed list of allowed methods (empty = all)
+     * @param boolean $smarty_args smarty argument format, else traditional
+     * @param null|array $block_functs list of methods that are block format
+     */
+    function register_object($object, &$object_impl, $allowed = array(), $smarty_args = true, $block_methods = array())
+    {
+        settype($allowed, 'array');
+        settype($smarty_args, 'boolean');
+        $this->_reg_objects[$object] =
+            array(&$object_impl, $allowed, $smarty_args, $block_methods);
+    }
+
+    /**
+     * Unregisters object
+     *
+     * @param string $object name of template object
+     */
+    function unregister_object($object)
+    {
+        unset($this->_reg_objects[$object]);
+    }
+
+
+    /**
+     * Registers block function to be used in templates
+     *
+     * @param string $block name of template block
+     * @param string $block_impl PHP function to register
+     */
+    function register_block($block, $block_impl, $cacheable=true, $cache_attrs=null)
+    {
+        $this->_plugins['block'][$block] =
+            array($block_impl, null, null, false, $cacheable, $cache_attrs);
+    }
+
+    /**
+     * Unregisters block function
+     *
+     * @param string $block name of template function
+     */
+    function unregister_block($block)
+    {
+        unset($this->_plugins['block'][$block]);
+    }
+
+    /**
+     * Registers compiler function
+     *
+     * @param string $function name of template function
+     * @param string $function_impl name of PHP function to register
+     */
+    function register_compiler_function($function, $function_impl, $cacheable=true)
+    {
+        $this->_plugins['compiler'][$function] =
+            array($function_impl, null, null, false, $cacheable);
+    }
+
+    /**
+     * Unregisters compiler function
+     *
+     * @param string $function name of template function
+     */
+    function unregister_compiler_function($function)
+    {
+        unset($this->_plugins['compiler'][$function]);
+    }
+
+    /**
+     * Registers modifier to be used in templates
+     *
+     * @param string $modifier name of template modifier
+     * @param string $modifier_impl name of PHP function to register
+     */
+    function register_modifier($modifier, $modifier_impl)
+    {
+        $this->_plugins['modifier'][$modifier] =
+            array($modifier_impl, null, null, false);
+    }
+
+    /**
+     * Unregisters modifier
+     *
+     * @param string $modifier name of template modifier
+     */
+    function unregister_modifier($modifier)
+    {
+        unset($this->_plugins['modifier'][$modifier]);
+    }
+
+    /**
+     * Registers a resource to fetch a template
+     *
+     * @param string $type name of resource
+     * @param array $functions array of functions to handle resource
+     */
+    function register_resource($type, $functions)
+    {
+        if (count($functions)==4) {
+            $this->_plugins['resource'][$type] =
+                array($functions, false);
+
+        } elseif (count($functions)==5) {
+            $this->_plugins['resource'][$type] =
+                array(array(array(&$functions[0], $functions[1])
+                            ,array(&$functions[0], $functions[2])
+                            ,array(&$functions[0], $functions[3])
+                            ,array(&$functions[0], $functions[4]))
+                      ,false);
+
+        } else {
+            $this->trigger_error("malformed function-list for '$type' in register_resource");
+
+        }
+    }
+
+    /**
+     * Unregisters a resource
+     *
+     * @param string $type name of resource
+     */
+    function unregister_resource($type)
+    {
+        unset($this->_plugins['resource'][$type]);
+    }
+
+    /**
+     * Registers a prefilter function to apply
+     * to a template before compiling
+     *
+     * @param string $function name of PHP function to register
+     */
+    function register_prefilter($function)
+    {
+    $_name = (is_array($function)) ? $function[1] : $function;
+        $this->_plugins['prefilter'][$_name]
+            = array($function, null, null, false);
+    }
+
+    /**
+     * Unregisters a prefilter function
+     *
+     * @param string $function name of PHP function
+     */
+    function unregister_prefilter($function)
+    {
+        unset($this->_plugins['prefilter'][$function]);
+    }
+
+    /**
+     * Registers a postfilter function to apply
+     * to a compiled template after compilation
+     *
+     * @param string $function name of PHP function to register
+     */
+    function register_postfilter($function)
+    {
+    $_name = (is_array($function)) ? $function[1] : $function;
+        $this->_plugins['postfilter'][$_name]
+            = array($function, null, null, false);
+    }
+
+    /**
+     * Unregisters a postfilter function
+     *
+     * @param string $function name of PHP function
+     */
+    function unregister_postfilter($function)
+    {
+        unset($this->_plugins['postfilter'][$function]);
+    }
+
+    /**
+     * Registers an output filter function to apply
+     * to a template output
+     *
+     * @param string $function name of PHP function
+     */
+    function register_outputfilter($function)
+    {
+    $_name = (is_array($function)) ? $function[1] : $function;
+        $this->_plugins['outputfilter'][$_name]
+            = array($function, null, null, false);
+    }
+
+    /**
+     * Unregisters an outputfilter function
+     *
+     * @param string $function name of PHP function
+     */
+    function unregister_outputfilter($function)
+    {
+        unset($this->_plugins['outputfilter'][$function]);
+    }
+
+    /**
+     * load a filter of specified type and name
+     *
+     * @param string $type filter type
+     * @param string $name filter name
+     */
+    function load_filter($type, $name)
+    {
+        switch ($type) {
+            case 'output':
+                $_params = array('plugins' => array(array($type . 'filter', $name, null, null, false)));
+                require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
+                smarty_core_load_plugins($_params, $this);
+                break;
+
+            case 'pre':
+            case 'post':
+                if (!isset($this->_plugins[$type . 'filter'][$name]))
+                    $this->_plugins[$type . 'filter'][$name] = false;
+                break;
+        }
+    }
+
+    /**
+     * clear cached content for the given template and cache id
+     *
+     * @param string $tpl_file name of template file
+     * @param string $cache_id name of cache_id
+     * @param string $compile_id name of compile_id
+     * @param string $exp_time expiration time
+     * @return boolean
+     */
+    function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null)
+    {
+
+        if (!isset($compile_id))
+            $compile_id = $this->compile_id;
+
+        if (!isset($tpl_file))
+            $compile_id = null;
+
+        $_auto_id = $this->_get_auto_id($cache_id, $compile_id);
+
+        if (!empty($this->cache_handler_func)) {
+            return call_user_func_array($this->cache_handler_func,
+                                  array('clear', &$this, &$dummy, $tpl_file, $cache_id, $compile_id, $exp_time));
+        } else {
+            $_params = array('auto_base' => $this->cache_dir,
+                            'auto_source' => $tpl_file,
+                            'auto_id' => $_auto_id,
+                            'exp_time' => $exp_time);
+            require_once(SMARTY_CORE_DIR . 'core.rm_auto.php');
+            return smarty_core_rm_auto($_params, $this);
+        }
+
+    }
+
+
+    /**
+     * clear the entire contents of cache (all templates)
+     *
+     * @param string $exp_time expire time
+     * @return boolean results of {@link smarty_core_rm_auto()}
+     */
+    function clear_all_cache($exp_time = null)
+    {
+        return $this->clear_cache(null, null, null, $exp_time);
+    }
+
+
+    /**
+     * test to see if valid cache exists for this template
+     *
+     * @param string $tpl_file name of template file
+     * @param string $cache_id
+     * @param string $compile_id
+     * @return string|false results of {@link _read_cache_file()}
+     */
+    function is_cached($tpl_file, $cache_id = null, $compile_id = null)
+    {
+        if (!$this->caching)
+            return false;
+
+        if (!isset($compile_id))
+            $compile_id = $this->compile_id;
+
+        $_params = array(
+            'tpl_file' => $tpl_file,
+            'cache_id' => $cache_id,
+            'compile_id' => $compile_id
+        );
+        require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php');
+        return smarty_core_read_cache_file($_params, $this);
+    }
+
+
+    /**
+     * clear all the assigned template variables.
+     *
+     */
+    function clear_all_assign()
+    {
+        $this->_tpl_vars = array();
+    }
+
+    /**
+     * clears compiled version of specified template resource,
+     * or all compiled template files if one is not specified.
+     * This function is for advanced use only, not normally needed.
+     *
+     * @param string $tpl_file
+     * @param string $compile_id
+     * @param string $exp_time
+     * @return boolean results of {@link smarty_core_rm_auto()}
+     */
+    function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp_time = null)
+    {
+        if (!isset($compile_id)) {
+            $compile_id = $this->compile_id;
+        }
+        $_params = array('auto_base' => $this->compile_dir,
+                        'auto_source' => $tpl_file,
+                        'auto_id' => $compile_id,
+                        'exp_time' => $exp_time,
+                        'extensions' => array('.inc', '.php'));
+        require_once(SMARTY_CORE_DIR . 'core.rm_auto.php');
+        return smarty_core_rm_auto($_params, $this);
+    }
+
+    /**
+     * Checks whether requested template exists.
+     *
+     * @param string $tpl_file
+     * @return boolean
+     */
+    function template_exists($tpl_file)
+    {
+        $_params = array('resource_name' => $tpl_file, 'quiet'=>true, 'get_source'=>false);
+        return $this->_fetch_resource_info($_params);
+    }
+
+    /**
+     * Returns an array containing template variables
+     *
+     * @param string $name
+     * @param string $type
+     * @return array
+     */
+    function &get_template_vars($name=null)
+    {
+        if(!isset($name)) {
+            return $this->_tpl_vars;
+        } elseif(isset($this->_tpl_vars[$name])) {
+            return $this->_tpl_vars[$name];
+        } else {
+            // var non-existant, return valid reference
+            $_tmp = null;
+            return $_tmp;   
+        }
+    }
+
+    /**
+     * Returns an array containing config variables
+     *
+     * @param string $name
+     * @param string $type
+     * @return array
+     */
+    function &get_config_vars($name=null)
+    {
+        if(!isset($name) && is_array($this->_config[0])) {
+            return $this->_config[0]['vars'];
+        } else if(isset($this->_config[0]['vars'][$name])) {
+            return $this->_config[0]['vars'][$name];
+        } else {
+            // var non-existant, return valid reference
+            $_tmp = null;
+            return $_tmp;
+        }
+    }
+
+    /**
+     * trigger Smarty error
+     *
+     * @param string $error_msg
+     * @param integer $error_type
+     */
+    function trigger_error($error_msg, $error_type = E_USER_WARNING)
+    {
+        trigger_error("Smarty error: $error_msg", $error_type);
+    }
+
+
+    /**
+     * executes & displays the template results
+     *
+     * @param string $resource_name
+     * @param string $cache_id
+     * @param string $compile_id
+     */
+    function display($resource_name, $cache_id = null, $compile_id = null)
+    {
+        $this->fetch($resource_name, $cache_id, $compile_id, true);
+    }
+
+    /**
+     * executes & returns or displays the template results
+     *
+     * @param string $resource_name
+     * @param string $cache_id
+     * @param string $compile_id
+     * @param boolean $display
+     */
+    function fetch($resource_name, $cache_id = null, $compile_id = null, $display = false)
+    {
+        static $_cache_info = array();
+        
+        $_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(isset($this->error_reporting)
+               ? $this->error_reporting : error_reporting() & ~E_NOTICE);
+
+        if (!$this->debugging && $this->debugging_ctrl == 'URL') {
+            $_query_string = $this->request_use_auto_globals ? $_SERVER['QUERY_STRING'] : $GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING'];
+            if (@strstr($_query_string, $this->_smarty_debug_id)) {
+                if (@strstr($_query_string, $this->_smarty_debug_id . '=on')) {
+                    // enable debugging for this browser session
+                    @setcookie('SMARTY_DEBUG', true);
+                    $this->debugging = true;
+                } elseif (@strstr($_query_string, $this->_smarty_debug_id . '=off')) {
+                    // disable debugging for this browser session
+                    @setcookie('SMARTY_DEBUG', false);
+                    $this->debugging = false;
+                } else {
+                    // enable debugging for this page
+                    $this->debugging = true;
+                }
+            } else {
+                $this->debugging = (bool)($this->request_use_auto_globals ? @$_COOKIE['SMARTY_DEBUG'] : @$GLOBALS['HTTP_COOKIE_VARS']['SMARTY_DEBUG']);
+            }
+        }
+
+        if ($this->debugging) {
+            // capture time for debugging info
+            $_params = array();
+            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+            $_debug_start_time = smarty_core_get_microtime($_params, $this);
+            $this->_smarty_debug_info[] = array('type'      => 'template',
+                                                'filename'  => $resource_name,
+                                                'depth'     => 0);
+            $_included_tpls_idx = count($this->_smarty_debug_info) - 1;
+        }
+
+        if (!isset($compile_id)) {
+            $compile_id = $this->compile_id;
+        }
+
+        $this->_compile_id = $compile_id;
+        $this->_inclusion_depth = 0;
+
+        if ($this->caching) {
+            // save old cache_info, initialize cache_info
+            array_push($_cache_info, $this->_cache_info);
+            $this->_cache_info = array();
+            $_params = array(
+                'tpl_file' => $resource_name,
+                'cache_id' => $cache_id,
+                'compile_id' => $compile_id,
+                'results' => null
+            );
+            require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php');
+            if (smarty_core_read_cache_file($_params, $this)) {
+                $_smarty_results = $_params['results'];
+                if (!empty($this->_cache_info['insert_tags'])) {
+                    $_params = array('plugins' => $this->_cache_info['insert_tags']);
+                    require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
+                    smarty_core_load_plugins($_params, $this);
+                    $_params = array('results' => $_smarty_results);
+                    require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php');
+                    $_smarty_results = smarty_core_process_cached_inserts($_params, $this);
+                }
+                if (!empty($this->_cache_info['cache_serials'])) {
+                    $_params = array('results' => $_smarty_results);
+                    require_once(SMARTY_CORE_DIR . 'core.process_compiled_include.php');
+                    $_smarty_results = smarty_core_process_compiled_include($_params, $this);
+                }
+
+
+                if ($display) {
+                    if ($this->debugging)
+                    {
+                        // capture time for debugging info
+                        $_params = array();
+                        require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+                        $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $_debug_start_time;
+                        require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php');
+                        $_smarty_results .= smarty_core_display_debug_console($_params, $this);
+                    }
+                    if ($this->cache_modified_check) {
+                        $_server_vars = ($this->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
+                        $_last_modified_date = @substr($_server_vars['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_server_vars['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3);
+                        $_gmt_mtime = gmdate('D, d M Y H:i:s', $this->_cache_info['timestamp']).' GMT';
+                        if (@count($this->_cache_info['insert_tags']) == 0
+                            && !$this->_cache_serials
+                            && $_gmt_mtime == $_last_modified_date) {
+                            if (php_sapi_name()=='cgi')
+                                header('Status: 304 Not Modified');
+                            else
+                                header('HTTP/1.1 304 Not Modified');
+
+                        } else {
+                            header('Last-Modified: '.$_gmt_mtime);
+                            echo $_smarty_results;
+                        }
+                    } else {
+                            echo $_smarty_results;
+                    }
+                    error_reporting($_smarty_old_error_level);
+                    // restore initial cache_info
+                    $this->_cache_info = array_pop($_cache_info);
+                    return true;
+                } else {
+                    error_reporting($_smarty_old_error_level);
+                    // restore initial cache_info
+                    $this->_cache_info = array_pop($_cache_info);
+                    return $_smarty_results;
+                }
+            } else {
+                $this->_cache_info['template'][$resource_name] = true;
+                if ($this->cache_modified_check && $display) {
+                    header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');
+                }
+            }
+        }
+
+        // load filters that are marked as autoload
+        if (count($this->autoload_filters)) {
+            foreach ($this->autoload_filters as $_filter_type => $_filters) {
+                foreach ($_filters as $_filter) {
+                    $this->load_filter($_filter_type, $_filter);
+                }
+            }
+        }
+
+        $_smarty_compile_path = $this->_get_compile_path($resource_name);
+
+        // if we just need to display the results, don't perform output
+        // buffering - for speed
+        $_cache_including = $this->_cache_including;
+        $this->_cache_including = false;
+        if ($display && !$this->caching && count($this->_plugins['outputfilter']) == 0) {
+            if ($this->_is_compiled($resource_name, $_smarty_compile_path)
+                    || $this->_compile_resource($resource_name, $_smarty_compile_path))
+            {
+                include($_smarty_compile_path);
+            }
+        } else {
+            ob_start();
+            if ($this->_is_compiled($resource_name, $_smarty_compile_path)
+                    || $this->_compile_resource($resource_name, $_smarty_compile_path))
+            {
+                include($_smarty_compile_path);
+            }
+            $_smarty_results = ob_get_contents();
+            ob_end_clean();
+
+            foreach ((array)$this->_plugins['outputfilter'] as $_output_filter) {
+                $_smarty_results = call_user_func_array($_output_filter[0], array($_smarty_results, &$this));
+            }
+        }
+
+        if ($this->caching) {
+            $_params = array('tpl_file' => $resource_name,
+                        'cache_id' => $cache_id,
+                        'compile_id' => $compile_id,
+                        'results' => $_smarty_results);
+            require_once(SMARTY_CORE_DIR . 'core.write_cache_file.php');
+            smarty_core_write_cache_file($_params, $this);
+            require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php');
+            $_smarty_results = smarty_core_process_cached_inserts($_params, $this);
+
+            if ($this->_cache_serials) {
+                // strip nocache-tags from output
+                $_smarty_results = preg_replace('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!s'
+                                                ,''
+                                                ,$_smarty_results);
+            }
+            // restore initial cache_info
+            $this->_cache_info = array_pop($_cache_info);
+        }
+        $this->_cache_including = $_cache_including;
+
+        if ($display) {
+            if (isset($_smarty_results)) { echo $_smarty_results; }
+            if ($this->debugging) {
+                // capture time for debugging info
+                $_params = array();
+                require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+                $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = (smarty_core_get_microtime($_params, $this) - $_debug_start_time);
+                require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php');
+                echo smarty_core_display_debug_console($_params, $this);
+            }
+            error_reporting($_smarty_old_error_level);
+            return;
+        } else {
+            error_reporting($_smarty_old_error_level);
+            if (isset($_smarty_results)) { return $_smarty_results; }
+        }
+    }
+
+    /**
+     * load configuration values
+     *
+     * @param string $file
+     * @param string $section
+     * @param string $scope
+     */
+    function config_load($file, $section = null, $scope = 'global')
+    {
+        require_once($this->_get_plugin_filepath('function', 'config_load'));
+        smarty_function_config_load(array('file' => $file, 'section' => $section, 'scope' => $scope), $this);
+    }
+
+    /**
+     * return a reference to a registered object
+     *
+     * @param string $name
+     * @return object
+     */
+    function &get_registered_object($name) {
+        if (!isset($this->_reg_objects[$name]))
+        $this->_trigger_fatal_error("'$name' is not a registered object");
+
+        if (!is_object($this->_reg_objects[$name][0]))
+        $this->_trigger_fatal_error("registered '$name' is not an object");
+
+        return $this->_reg_objects[$name][0];
+    }
+
+    /**
+     * clear configuration values
+     *
+     * @param string $var
+     */
+    function clear_config($var = null)
+    {
+        if(!isset($var)) {
+            // clear all values
+            $this->_config = array(array('vars'  => array(),
+                                         'files' => array()));
+        } else {
+            unset($this->_config[0]['vars'][$var]);
+        }
+    }
+
+    /**
+     * get filepath of requested plugin
+     *
+     * @param string $type
+     * @param string $name
+     * @return string|false
+     */
+    function _get_plugin_filepath($type, $name)
+    {
+        $_params = array('type' => $type, 'name' => $name);
+        require_once(SMARTY_CORE_DIR . 'core.assemble_plugin_filepath.php');
+        return smarty_core_assemble_plugin_filepath($_params, $this);
+    }
+
+   /**
+     * test if resource needs compiling
+     *
+     * @param string $resource_name
+     * @param string $compile_path
+     * @return boolean
+     */
+    function _is_compiled($resource_name, $compile_path)
+    {
+        if (!$this->force_compile && file_exists($compile_path)) {
+            if (!$this->compile_check) {
+                // no need to check compiled file
+                return true;
+            } else {
+                // get file source and timestamp
+                $_params = array('resource_name' => $resource_name, 'get_source'=>false);
+                if (!$this->_fetch_resource_info($_params)) {
+                    return false;
+                }
+                if ($_params['resource_timestamp'] <= filemtime($compile_path)) {
+                    // template not expired, no recompile
+                    return true;
+                } else {
+                    // compile template
+                    return false;
+                }
+            }
+        } else {
+            // compiled template does not exist, or forced compile
+            return false;
+        }
+    }
+
+   /**
+     * compile the template
+     *
+     * @param string $resource_name
+     * @param string $compile_path
+     * @return boolean
+     */
+    function _compile_resource($resource_name, $compile_path)
+    {
+
+        $_params = array('resource_name' => $resource_name);
+        if (!$this->_fetch_resource_info($_params)) {
+            return false;
+        }
+
+        $_source_content = $_params['source_content'];
+        $_cache_include    = substr($compile_path, 0, -4).'.inc';
+
+        if ($this->_compile_source($resource_name, $_source_content, $_compiled_content, $_cache_include)) {
+            // if a _cache_serial was set, we also have to write an include-file:
+            if ($this->_cache_include_info) {
+                require_once(SMARTY_CORE_DIR . 'core.write_compiled_include.php');
+                smarty_core_write_compiled_include(array_merge($this->_cache_include_info, array('compiled_content'=>$_compiled_content, 'resource_name'=>$resource_name)),  $this);
+            }
+
+            $_params = array('compile_path'=>$compile_path, 'compiled_content' => $_compiled_content);
+            require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php');
+            smarty_core_write_compiled_resource($_params, $this);
+
+            return true;
+        } else {
+            return false;
+        }
+
+    }
+
+   /**
+     * compile the given source
+     *
+     * @param string $resource_name
+     * @param string $source_content
+     * @param string $compiled_content
+     * @return boolean
+     */
+    function _compile_source($resource_name, &$source_content, &$compiled_content, $cache_include_path=null)
+    {
+        if (file_exists(SMARTY_DIR . $this->compiler_file)) {
+            require_once(SMARTY_DIR . $this->compiler_file);
+        } else {
+            // use include_path
+            require_once($this->compiler_file);
+        }
+
+
+        $smarty_compiler = new $this->compiler_class;
+
+        $smarty_compiler->template_dir      = $this->template_dir;
+        $smarty_compiler->compile_dir       = $this->compile_dir;
+        $smarty_compiler->plugins_dir       = $this->plugins_dir;
+        $smarty_compiler->config_dir        = $this->config_dir;
+        $smarty_compiler->force_compile     = $this->force_compile;
+        $smarty_compiler->caching           = $this->caching;
+        $smarty_compiler->php_handling      = $this->php_handling;
+        $smarty_compiler->left_delimiter    = $this->left_delimiter;
+        $smarty_compiler->right_delimiter   = $this->right_delimiter;
+        $smarty_compiler->_version          = $this->_version;
+        $smarty_compiler->security          = $this->security;
+        $smarty_compiler->secure_dir        = $this->secure_dir;
+        $smarty_compiler->security_settings = $this->security_settings;
+        $smarty_compiler->trusted_dir       = $this->trusted_dir;
+        $smarty_compiler->use_sub_dirs      = $this->use_sub_dirs;
+        $smarty_compiler->_reg_objects      = &$this->_reg_objects;
+        $smarty_compiler->_plugins          = &$this->_plugins;
+        $smarty_compiler->_tpl_vars         = &$this->_tpl_vars;
+        $smarty_compiler->default_modifiers = $this->default_modifiers;
+        $smarty_compiler->compile_id        = $this->_compile_id;
+        $smarty_compiler->_config            = $this->_config;
+        $smarty_compiler->request_use_auto_globals  = $this->request_use_auto_globals;
+
+        if (isset($cache_include_path) && isset($this->_cache_serials[$cache_include_path])) {
+            $smarty_compiler->_cache_serial = $this->_cache_serials[$cache_include_path];
+        }
+        $smarty_compiler->_cache_include = $cache_include_path;
+
+
+        $_results = $smarty_compiler->_compile_file($resource_name, $source_content, $compiled_content);
+
+        if ($smarty_compiler->_cache_serial) {
+            $this->_cache_include_info = array(
+                'cache_serial'=>$smarty_compiler->_cache_serial
+                ,'plugins_code'=>$smarty_compiler->_plugins_code
+                ,'include_file_path' => $cache_include_path);
+
+        } else {
+            $this->_cache_include_info = null;
+
+        }
+
+        return $_results;
+    }
+
+    /**
+     * Get the compile path for this resource
+     *
+     * @param string $resource_name
+     * @return string results of {@link _get_auto_filename()}
+     */
+    function _get_compile_path($resource_name)
+    {
+        return $this->_get_auto_filename($this->compile_dir, $resource_name,
+                                         $this->_compile_id) . '.php';
+    }
+
+    /**
+     * fetch the template info. Gets timestamp, and source
+     * if get_source is true
+     *
+     * sets $source_content to the source of the template, and
+     * $resource_timestamp to its time stamp
+     * @param string $resource_name
+     * @param string $source_content
+     * @param integer $resource_timestamp
+     * @param boolean $get_source
+     * @param boolean $quiet
+     * @return boolean
+     */
+
+    function _fetch_resource_info(&$params)
+    {
+        if(!isset($params['get_source'])) { $params['get_source'] = true; }
+        if(!isset($params['quiet'])) { $params['quiet'] = false; }
+
+        $_return = false;
+        $_params = array('resource_name' => $params['resource_name']) ;
+        if (isset($params['resource_base_path']))
+            $_params['resource_base_path'] = $params['resource_base_path'];
+        else
+            $_params['resource_base_path'] = $this->template_dir;
+
+        if ($this->_parse_resource_name($_params)) {
+            $_resource_type = $_params['resource_type'];
+            $_resource_name = $_params['resource_name'];
+            switch ($_resource_type) {
+                case 'file':
+                    if ($params['get_source']) {
+                        $params['source_content'] = $this->_read_file($_resource_name);
+                    }
+                    $params['resource_timestamp'] = filemtime($_resource_name);
+                    $_return = is_file($_resource_name);
+                    break;
+
+                default:
+                    // call resource functions to fetch the template source and timestamp
+                    if ($params['get_source']) {
+                        $_source_return = isset($this->_plugins['resource'][$_resource_type]) &&
+                            call_user_func_array($this->_plugins['resource'][$_resource_type][0][0],
+                                                 array($_resource_name, &$params['source_content'], &$this));
+                    } else {
+                        $_source_return = true;
+                    }
+
+                    $_timestamp_return = isset($this->_plugins['resource'][$_resource_type]) &&
+                        call_user_func_array($this->_plugins['resource'][$_resource_type][0][1],
+                                             array($_resource_name, &$params['resource_timestamp'], &$this));
+
+                    $_return = $_source_return && $_timestamp_return;
+                    break;
+            }
+        }
+
+        if (!$_return) {
+            // see if we can get a template with the default template handler
+            if (!empty($this->default_template_handler_func)) {
+                if (!is_callable($this->default_template_handler_func)) {
+                    $this->trigger_error("default template handler function \"$this->default_template_handler_func\" doesn't exist.");
+                } else {
+                    $_return = call_user_func_array(
+                        $this->default_template_handler_func,
+                        array($_params['resource_type'], $_params['resource_name'], &$params['source_content'], &$params['resource_timestamp'], &$this));
+                }
+            }
+        }
+
+        if (!$_return) {
+            if (!$params['quiet']) {
+                $this->trigger_error('unable to read resource: "' . $params['resource_name'] . '"');
+            }
+        } else if ($_return && $this->security) {
+            require_once(SMARTY_CORE_DIR . 'core.is_secure.php');
+            if (!smarty_core_is_secure($_params, $this)) {
+                if (!$params['quiet'])
+                    $this->trigger_error('(secure mode) accessing "' . $params['resource_name'] . '" is not allowed');
+                $params['source_content'] = null;
+                $params['resource_timestamp'] = null;
+                return false;
+            }
+        }
+        return $_return;
+    }
+
+
+    /**
+     * parse out the type and name from the resource
+     *
+     * @param string $resource_base_path
+     * @param string $resource_name
+     * @param string $resource_type
+     * @param string $resource_name
+     * @return boolean
+     */
+
+    function _parse_resource_name(&$params)
+    {
+
+        // split tpl_path by the first colon
+        $_resource_name_parts = explode(':', $params['resource_name'], 2);
+
+        if (count($_resource_name_parts) == 1) {
+            // no resource type given
+            $params['resource_type'] = $this->default_resource_type;
+            $params['resource_name'] = $_resource_name_parts[0];
+        } else {
+            if(strlen($_resource_name_parts[0]) == 1) {
+                // 1 char is not resource type, but part of filepath
+                $params['resource_type'] = $this->default_resource_type;
+                $params['resource_name'] = $params['resource_name'];
+            } else {
+                $params['resource_type'] = $_resource_name_parts[0];
+                $params['resource_name'] = $_resource_name_parts[1];
+            }
+        }
+
+        if ($params['resource_type'] == 'file') {
+            if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $params['resource_name'])) {
+                // relative pathname to $params['resource_base_path']
+                // use the first directory where the file is found
+                foreach ((array)$params['resource_base_path'] as $_curr_path) {
+                    $_fullpath = $_curr_path . DIRECTORY_SEPARATOR . $params['resource_name'];
+                    if (file_exists($_fullpath) && is_file($_fullpath)) {
+                        $params['resource_name'] = $_fullpath;
+                        return true;
+                    }
+                    // didn't find the file, try include_path
+                    $_params = array('file_path' => $_fullpath);
+                    require_once(SMARTY_CORE_DIR . 'core.get_include_path.php');
+                    if(smarty_core_get_include_path($_params, $this)) {
+                        $params['resource_name'] = $_params['new_file_path'];
+                        return true;
+                    }
+                }
+                return false;
+            } else {
+                /* absolute path */
+                return file_exists($params['resource_name']);
+            }
+        } elseif (empty($this->_plugins['resource'][$params['resource_type']])) {
+            $_params = array('type' => $params['resource_type']);
+            require_once(SMARTY_CORE_DIR . 'core.load_resource_plugin.php');
+            smarty_core_load_resource_plugin($_params, $this);
+        }
+
+        return true;
+    }
+
+
+    /**
+     * Handle modifiers
+     *
+     * @param string|null $modifier_name
+     * @param array|null $map_array
+     * @return string result of modifiers
+     */
+    function _run_mod_handler()
+    {
+        $_args = func_get_args();
+        list($_modifier_name, $_map_array) = array_splice($_args, 0, 2);
+        list($_func_name, $_tpl_file, $_tpl_line) =
+            $this->_plugins['modifier'][$_modifier_name];
+
+        $_var = $_args[0];
+        foreach ($_var as $_key => $_val) {
+            $_args[0] = $_val;
+            $_var[$_key] = call_user_func_array($_func_name, $_args);
+        }
+        return $_var;
+    }
+
+    /**
+     * Remove starting and ending quotes from the string
+     *
+     * @param string $string
+     * @return string
+     */
+    function _dequote($string)
+    {
+        if ((substr($string, 0, 1) == "'" || substr($string, 0, 1) == '"') &&
+            substr($string, -1) == substr($string, 0, 1))
+            return substr($string, 1, -1);
+        else
+            return $string;
+    }
+
+
+    /**
+     * read in a file
+     *
+     * @param string $filename
+     * @return string
+     */
+    function _read_file($filename)
+    {
+        if ( file_exists($filename) && ($fd = @fopen($filename, 'rb')) ) {
+            $contents = '';
+            while (!feof($fd)) {
+                $contents .= fread($fd, 8192);
+            }
+            fclose($fd);
+            return $contents;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * get a concrete filename for automagically created content
+     *
+     * @param string $auto_base
+     * @param string $auto_source
+     * @param string $auto_id
+     * @return string
+     * @staticvar string|null
+     * @staticvar string|null
+     */
+    function _get_auto_filename($auto_base, $auto_source = null, $auto_id = null)
+    {
+        $_compile_dir_sep =  $this->use_sub_dirs ? DIRECTORY_SEPARATOR : '^';
+        $_return = $auto_base . DIRECTORY_SEPARATOR;
+
+        if(isset($auto_id)) {
+            // make auto_id safe for directory names
+            $auto_id = str_replace('%7C',$_compile_dir_sep,(urlencode($auto_id)));
+            // split into separate directories
+            $_return .= $auto_id . $_compile_dir_sep;
+        }
+
+        if(isset($auto_source)) {
+            // make source name safe for filename
+            $_filename = urlencode(basename($auto_source));
+            $_crc32 = sprintf('%08X', crc32($auto_source));
+            // prepend %% to avoid name conflicts with
+            // with $params['auto_id'] names
+            $_crc32 = substr($_crc32, 0, 2) . $_compile_dir_sep .
+                      substr($_crc32, 0, 3) . $_compile_dir_sep . $_crc32;
+            $_return .= '%%' . $_crc32 . '%%' . $_filename;
+        }
+
+        return $_return;
+    }
+
+    /**
+     * unlink a file, possibly using expiration time
+     *
+     * @param string $resource
+     * @param integer $exp_time
+     */
+    function _unlink($resource, $exp_time = null)
+    {
+        if(isset($exp_time)) {
+            if(time() - @filemtime($resource) >= $exp_time) {
+                return @unlink($resource);
+            }
+        } else {
+            return @unlink($resource);
+        }
+    }
+
+    /**
+     * returns an auto_id for auto-file-functions
+     *
+     * @param string $cache_id
+     * @param string $compile_id
+     * @return string|null
+     */
+    function _get_auto_id($cache_id=null, $compile_id=null) {
+    if (isset($cache_id))
+        return (isset($compile_id)) ? $cache_id . '|' . $compile_id  : $cache_id;
+    elseif(isset($compile_id))
+        return $compile_id;
+    else
+        return null;
+    }
+
+    /**
+     * trigger Smarty plugin error
+     *
+     * @param string $error_msg
+     * @param string $tpl_file
+     * @param integer $tpl_line
+     * @param string $file
+     * @param integer $line
+     * @param integer $error_type
+     */
+    function _trigger_fatal_error($error_msg, $tpl_file = null, $tpl_line = null,
+            $file = null, $line = null, $error_type = E_USER_ERROR)
+    {
+        if(isset($file) && isset($line)) {
+            $info = ' ('.basename($file).", line $line)";
+        } else {
+            $info = '';
+        }
+        if (isset($tpl_line) && isset($tpl_file)) {
+            $this->trigger_error('[in ' . $tpl_file . ' line ' . $tpl_line . "]: $error_msg$info", $error_type);
+        } else {
+            $this->trigger_error($error_msg . $info, $error_type);
+        }
+    }
+
+
+    /**
+     * callback function for preg_replace, to call a non-cacheable block
+     * @return string
+     */
+    function _process_compiled_include_callback($match) {
+        $_func = '_smarty_tplfunc_'.$match[2].'_'.$match[3];
+        ob_start();
+        $_func($this);
+        $_ret = ob_get_contents();
+        ob_end_clean();
+        return $_ret;
+    }
+
+
+    /**
+     * called for included templates
+     *
+     * @param string $_smarty_include_tpl_file
+     * @param string $_smarty_include_vars
+     */
+
+    // $_smarty_include_tpl_file, $_smarty_include_vars
+
+    function _smarty_include($params)
+    {
+        if ($this->debugging) {
+            $_params = array();
+            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+            $debug_start_time = smarty_core_get_microtime($_params, $this);
+            $this->_smarty_debug_info[] = array('type'      => 'template',
+                                                  'filename'  => $params['smarty_include_tpl_file'],
+                                                  'depth'     => ++$this->_inclusion_depth);
+            $included_tpls_idx = count($this->_smarty_debug_info) - 1;
+        }
+
+        $this->_tpl_vars = array_merge($this->_tpl_vars, $params['smarty_include_vars']);
+
+        // config vars are treated as local, so push a copy of the
+        // current ones onto the front of the stack
+        array_unshift($this->_config, $this->_config[0]);
+
+        $_smarty_compile_path = $this->_get_compile_path($params['smarty_include_tpl_file']);
+
+
+        if ($this->_is_compiled($params['smarty_include_tpl_file'], $_smarty_compile_path)
+            || $this->_compile_resource($params['smarty_include_tpl_file'], $_smarty_compile_path))
+        {
+            include($_smarty_compile_path);
+        }
+
+        // pop the local vars off the front of the stack
+        array_shift($this->_config);
+
+        $this->_inclusion_depth--;
+
+        if ($this->debugging) {
+            // capture time for debugging info
+            $_params = array();
+            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+            $this->_smarty_debug_info[$included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $debug_start_time;
+        }
+
+        if ($this->caching) {
+            $this->_cache_info['template'][$params['smarty_include_tpl_file']] = true;
+        }
+    }
+
+
+    /**
+     * get or set an array of cached attributes for function that is
+     * not cacheable
+     * @return array
+     */
+    function &_smarty_cache_attrs($cache_serial, $count) {
+        $_cache_attrs =& $this->_cache_info['cache_attrs'][$cache_serial][$count];
+
+        if ($this->_cache_including) {
+            /* return next set of cache_attrs */
+            $_return = current($_cache_attrs);
+            next($_cache_attrs);
+            return $_return;
+
+        } else {
+            /* add a reference to a new set of cache_attrs */
+            $_cache_attrs[] = array();
+            return $_cache_attrs[count($_cache_attrs)-1];
+
+        }
+
+    }
+
+
+    /**
+     * wrapper for include() retaining $this
+     * @return mixed
+     */
+    function _include($filename, $once=false, $params=null)
+    {
+        if ($once) {
+            return include_once($filename);
+        } else {
+            return include($filename);
+        }
+    }
+
+
+    /**
+     * wrapper for eval() retaining $this
+     * @return mixed
+     */
+    function _eval($code, $params=null)
+    {
+        return eval($code);
+    }
+    /**#@-*/
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/Smarty_Compiler.class.php b/inc/smarty/Smarty_Compiler.class.php
new file mode 100644 (file)
index 0000000..f54cc21
--- /dev/null
@@ -0,0 +1,2327 @@
+<?php
+
+/**
+ * Project:     Smarty: the PHP compiling template engine
+ * File:        Smarty_Compiler.class.php
+ *
+ * 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
+ *
+ * @link http://smarty.php.net/
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author Andrei Zmievski <andrei@php.net>
+ * @version 2.6.18
+ * @copyright 2001-2005 New Digital Group, Inc.
+ * @package Smarty
+ */
+
+/* $Id: Smarty_Compiler.class.php,v 1.395 2007/03/06 10:40:06 messju Exp $ */
+
+/**
+ * Template compiling class
+ * @package Smarty
+ */
+class Smarty_Compiler extends Smarty {
+
+    // internal vars
+    /**#@+
+     * @access private
+     */
+    var $_folded_blocks         =   array();    // keeps folded template blocks
+    var $_current_file          =   null;       // the current template being compiled
+    var $_current_line_no       =   1;          // line number for error messages
+    var $_capture_stack         =   array();    // keeps track of nested capture buffers
+    var $_plugin_info           =   array();    // keeps track of plugins to load
+    var $_init_smarty_vars      =   false;
+    var $_permitted_tokens      =   array('true','false','yes','no','on','off','null');
+    var $_db_qstr_regexp        =   null;        // regexps are setup in the constructor
+    var $_si_qstr_regexp        =   null;
+    var $_qstr_regexp           =   null;
+    var $_func_regexp           =   null;
+    var $_reg_obj_regexp        =   null;
+    var $_var_bracket_regexp    =   null;
+    var $_num_const_regexp      =   null;
+    var $_dvar_guts_regexp      =   null;
+    var $_dvar_regexp           =   null;
+    var $_cvar_regexp           =   null;
+    var $_svar_regexp           =   null;
+    var $_avar_regexp           =   null;
+    var $_mod_regexp            =   null;
+    var $_var_regexp            =   null;
+    var $_parenth_param_regexp  =   null;
+    var $_func_call_regexp      =   null;
+    var $_obj_ext_regexp        =   null;
+    var $_obj_start_regexp      =   null;
+    var $_obj_params_regexp     =   null;
+    var $_obj_call_regexp       =   null;
+    var $_cacheable_state       =   0;
+    var $_cache_attrs_count     =   0;
+    var $_nocache_count         =   0;
+    var $_cache_serial          =   null;
+    var $_cache_include         =   null;
+
+    var $_strip_depth           =   0;
+    var $_additional_newline    =   "\n";
+
+    /**#@-*/
+    /**
+     * The class constructor.
+     */
+    function Smarty_Compiler()
+    {
+        // matches double quoted strings:
+        // "foobar"
+        // "foo\"bar"
+        $this->_db_qstr_regexp = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"';
+
+        // matches single quoted strings:
+        // 'foobar'
+        // 'foo\'bar'
+        $this->_si_qstr_regexp = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'';
+
+        // matches single or double quoted strings
+        $this->_qstr_regexp = '(?:' . $this->_db_qstr_regexp . '|' . $this->_si_qstr_regexp . ')';
+
+        // matches bracket portion of vars
+        // [0]
+        // [foo]
+        // [$bar]
+        $this->_var_bracket_regexp = '\[\$?[\w\.]+\]';
+
+        // matches numerical constants
+        // 30
+        // -12
+        // 13.22
+        $this->_num_const_regexp = '(?:\-?\d+(?:\.\d+)?)';
+
+        // matches $ vars (not objects):
+        // $foo
+        // $foo.bar
+        // $foo.bar.foobar
+        // $foo[0]
+        // $foo[$bar]
+        // $foo[5][blah]
+        // $foo[5].bar[$foobar][4]
+        $this->_dvar_math_regexp = '(?:[\+\*\/\%]|(?:-(?!>)))';
+        $this->_dvar_math_var_regexp = '[\$\w\.\+\-\*\/\%\d\>\[\]]';
+        $this->_dvar_guts_regexp = '\w+(?:' . $this->_var_bracket_regexp
+                . ')*(?:\.\$?\w+(?:' . $this->_var_bracket_regexp . ')*)*(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?';
+        $this->_dvar_regexp = '\$' . $this->_dvar_guts_regexp;
+
+        // matches config vars:
+        // #foo#
+        // #foobar123_foo#
+        $this->_cvar_regexp = '\#\w+\#';
+
+        // matches section vars:
+        // %foo.bar%
+        $this->_svar_regexp = '\%\w+\.\w+\%';
+
+        // matches all valid variables (no quotes, no modifiers)
+        $this->_avar_regexp = '(?:' . $this->_dvar_regexp . '|'
+           . $this->_cvar_regexp . '|' . $this->_svar_regexp . ')';
+
+        // matches valid variable syntax:
+        // $foo
+        // $foo
+        // #foo#
+        // #foo#
+        // "text"
+        // "text"
+        $this->_var_regexp = '(?:' . $this->_avar_regexp . '|' . $this->_qstr_regexp . ')';
+
+        // matches valid object call (one level of object nesting allowed in parameters):
+        // $foo->bar
+        // $foo->bar()
+        // $foo->bar("text")
+        // $foo->bar($foo, $bar, "text")
+        // $foo->bar($foo, "foo")
+        // $foo->bar->foo()
+        // $foo->bar->foo->bar()
+        // $foo->bar($foo->bar)
+        // $foo->bar($foo->bar())
+        // $foo->bar($foo->bar($blah,$foo,44,"foo",$foo[0].bar))
+        $this->_obj_ext_regexp = '\->(?:\$?' . $this->_dvar_guts_regexp . ')';
+        $this->_obj_restricted_param_regexp = '(?:'
+                . '(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')(?:' . $this->_obj_ext_regexp . '(?:\((?:(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')'
+                . '(?:\s*,\s*(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . '))*)?\))?)*)';
+        $this->_obj_single_param_regexp = '(?:\w+|' . $this->_obj_restricted_param_regexp . '(?:\s*,\s*(?:(?:\w+|'
+                . $this->_var_regexp . $this->_obj_restricted_param_regexp . ')))*)';
+        $this->_obj_params_regexp = '\((?:' . $this->_obj_single_param_regexp
+                . '(?:\s*,\s*' . $this->_obj_single_param_regexp . ')*)?\)';
+        $this->_obj_start_regexp = '(?:' . $this->_dvar_regexp . '(?:' . $this->_obj_ext_regexp . ')+)';
+        $this->_obj_call_regexp = '(?:' . $this->_obj_start_regexp . '(?:' . $this->_obj_params_regexp . ')?(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?)';
+        
+        // matches valid modifier syntax:
+        // |foo
+        // |@foo
+        // |foo:"bar"
+        // |foo:$bar
+        // |foo:"bar":$foobar
+        // |foo|bar
+        // |foo:$foo->bar
+        $this->_mod_regexp = '(?:\|@?\w+(?::(?:\w+|' . $this->_num_const_regexp . '|'
+           . $this->_obj_call_regexp . '|' . $this->_avar_regexp . '|' . $this->_qstr_regexp .'))*)';
+
+        // matches valid function name:
+        // foo123
+        // _foo_bar
+        $this->_func_regexp = '[a-zA-Z_]\w*';
+
+        // matches valid registered object:
+        // foo->bar
+        $this->_reg_obj_regexp = '[a-zA-Z_]\w*->[a-zA-Z_]\w*';
+
+        // matches valid parameter values:
+        // true
+        // $foo
+        // $foo|bar
+        // #foo#
+        // #foo#|bar
+        // "text"
+        // "text"|bar
+        // $foo->bar
+        $this->_param_regexp = '(?:\s*(?:' . $this->_obj_call_regexp . '|'
+           . $this->_var_regexp . '|' . $this->_num_const_regexp  . '|\w+)(?>' . $this->_mod_regexp . '*)\s*)';
+
+        // matches valid parenthesised function parameters:
+        //
+        // "text"
+        //    $foo, $bar, "text"
+        // $foo|bar, "foo"|bar, $foo->bar($foo)|bar
+        $this->_parenth_param_regexp = '(?:\((?:\w+|'
+                . $this->_param_regexp . '(?:\s*,\s*(?:(?:\w+|'
+                . $this->_param_regexp . ')))*)?\))';
+
+        // matches valid function call:
+        // foo()
+        // foo_bar($foo)
+        // _foo_bar($foo,"bar")
+        // foo123($foo,$foo->bar(),"foo")
+        $this->_func_call_regexp = '(?:' . $this->_func_regexp . '\s*(?:'
+           . $this->_parenth_param_regexp . '))';
+    }
+
+    /**
+     * compile a resource
+     *
+     * sets $compiled_content to the compiled source
+     * @param string $resource_name
+     * @param string $source_content
+     * @param string $compiled_content
+     * @return true
+     */
+    function _compile_file($resource_name, $source_content, &$compiled_content)
+    {
+
+        if ($this->security) {
+            // do not allow php syntax to be executed unless specified
+            if ($this->php_handling == SMARTY_PHP_ALLOW &&
+                !$this->security_settings['PHP_HANDLING']) {
+                $this->php_handling = SMARTY_PHP_PASSTHRU;
+            }
+        }
+
+        $this->_load_filters();
+
+        $this->_current_file = $resource_name;
+        $this->_current_line_no = 1;
+        $ldq = preg_quote($this->left_delimiter, '~');
+        $rdq = preg_quote($this->right_delimiter, '~');
+
+        // run template source through prefilter functions
+        if (count($this->_plugins['prefilter']) > 0) {
+            foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) {
+                if ($prefilter === false) continue;
+                if ($prefilter[3] || is_callable($prefilter[0])) {
+                    $source_content = call_user_func_array($prefilter[0],
+                                                            array($source_content, &$this));
+                    $this->_plugins['prefilter'][$filter_name][3] = true;
+                } else {
+                    $this->_trigger_fatal_error("[plugin] prefilter '$filter_name' is not implemented");
+                }
+            }
+        }
+
+        /* fetch all special blocks */
+        $search = "~{$ldq}\*(.*?)\*{$rdq}|{$ldq}\s*literal\s*{$rdq}(.*?){$ldq}\s*/literal\s*{$rdq}|{$ldq}\s*php\s*{$rdq}(.*?){$ldq}\s*/php\s*{$rdq}~s";
+
+        preg_match_all($search, $source_content, $match,  PREG_SET_ORDER);
+        $this->_folded_blocks = $match;
+        reset($this->_folded_blocks);
+
+        /* replace special blocks by "{php}" */
+        $source_content = preg_replace($search.'e', "'"
+                                       . $this->_quote_replace($this->left_delimiter) . 'php'
+                                       . "' . str_repeat(\"\n\", substr_count('\\0', \"\n\")) .'"
+                                       . $this->_quote_replace($this->right_delimiter)
+                                       . "'"
+                                       , $source_content);
+
+        /* Gather all template tags. */
+        preg_match_all("~{$ldq}\s*(.*?)\s*{$rdq}~s", $source_content, $_match);
+        $template_tags = $_match[1];
+        /* Split content by template tags to obtain non-template content. */
+        $text_blocks = preg_split("~{$ldq}.*?{$rdq}~s", $source_content);
+
+        /* loop through text blocks */
+        for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) {
+            /* match anything resembling php tags */
+            if (preg_match_all('~(<\?(?:\w+|=)?|\?>|language\s*=\s*[\"\']?\s*php\s*[\"\']?)~is', $text_blocks[$curr_tb], $sp_match)) {
+                /* replace tags with placeholders to prevent recursive replacements */
+                $sp_match[1] = array_unique($sp_match[1]);
+                usort($sp_match[1], '_smarty_sort_length');
+                for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {
+                    $text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],'%%%SMARTYSP'.$curr_sp.'%%%',$text_blocks[$curr_tb]);
+                }
+                /* process each one */
+                for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {
+                    if ($this->php_handling == SMARTY_PHP_PASSTHRU) {
+                        /* echo php contents */
+                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '<?php echo \''.str_replace("'", "\'", $sp_match[1][$curr_sp]).'\'; ?>'."\n", $text_blocks[$curr_tb]);
+                    } else if ($this->php_handling == SMARTY_PHP_QUOTE) {
+                        /* quote php tags */
+                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', htmlspecialchars($sp_match[1][$curr_sp]), $text_blocks[$curr_tb]);
+                    } else if ($this->php_handling == SMARTY_PHP_REMOVE) {
+                        /* remove php tags */
+                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '', $text_blocks[$curr_tb]);
+                    } else {
+                        /* SMARTY_PHP_ALLOW, but echo non php starting tags */
+                        $sp_match[1][$curr_sp] = preg_replace('~(<\?(?!php|=|$))~i', '<?php echo \'\\1\'?>'."\n", $sp_match[1][$curr_sp]);
+                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', $sp_match[1][$curr_sp], $text_blocks[$curr_tb]);
+                    }
+                }
+            }
+        }
+        
+        /* Compile the template tags into PHP code. */
+        $compiled_tags = array();
+        for ($i = 0, $for_max = count($template_tags); $i < $for_max; $i++) {
+            $this->_current_line_no += substr_count($text_blocks[$i], "\n");
+            $compiled_tags[] = $this->_compile_tag($template_tags[$i]);
+            $this->_current_line_no += substr_count($template_tags[$i], "\n");
+        }
+        if (count($this->_tag_stack)>0) {
+            list($_open_tag, $_line_no) = end($this->_tag_stack);
+            $this->_syntax_error("unclosed tag \{$_open_tag} (opened line $_line_no).", E_USER_ERROR, __FILE__, __LINE__);
+            return;
+        }
+
+        /* Reformat $text_blocks between 'strip' and '/strip' tags,
+           removing spaces, tabs and newlines. */
+        $strip = false;
+        for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {
+            if ($compiled_tags[$i] == '{strip}') {
+                $compiled_tags[$i] = '';
+                $strip = true;
+                /* remove leading whitespaces */
+                $text_blocks[$i + 1] = ltrim($text_blocks[$i + 1]);
+            }
+            if ($strip) {
+                /* strip all $text_blocks before the next '/strip' */
+                for ($j = $i + 1; $j < $for_max; $j++) {
+                    /* remove leading and trailing whitespaces of each line */
+                    $text_blocks[$j] = preg_replace('![\t ]*[\r\n]+[\t ]*!', '', $text_blocks[$j]);
+                    if ($compiled_tags[$j] == '{/strip}') {                       
+                        /* remove trailing whitespaces from the last text_block */
+                        $text_blocks[$j] = rtrim($text_blocks[$j]);
+                    }
+                    $text_blocks[$j] = "<?php echo '" . strtr($text_blocks[$j], array("'"=>"\'", "\\"=>"\\\\")) . "'; ?>";
+                    if ($compiled_tags[$j] == '{/strip}') {
+                        $compiled_tags[$j] = "\n"; /* slurped by php, but necessary
+                                    if a newline is following the closing strip-tag */
+                        $strip = false;
+                        $i = $j;
+                        break;
+                    }
+                }
+            }
+        }
+        $compiled_content = '';
+        
+        $tag_guard = '%%%SMARTYOTG' . md5(uniqid(rand(), true)) . '%%%';
+        
+        /* Interleave the compiled contents and text blocks to get the final result. */
+        for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {
+            if ($compiled_tags[$i] == '') {
+                // tag result empty, remove first newline from following text block
+                $text_blocks[$i+1] = preg_replace('~^(\r\n|\r|\n)~', '', $text_blocks[$i+1]);
+            }
+            // replace legit PHP tags with placeholder
+            $text_blocks[$i] = str_replace('<?', $tag_guard, $text_blocks[$i]);
+            $compiled_tags[$i] = str_replace('<?', $tag_guard, $compiled_tags[$i]);
+            
+            $compiled_content .= $text_blocks[$i] . $compiled_tags[$i];
+        }
+        $compiled_content .= str_replace('<?', $tag_guard, $text_blocks[$i]);
+
+        // escape php tags created by interleaving
+        $compiled_content = str_replace('<?', "<?php echo '<?' ?>\n", $compiled_content);
+        $compiled_content = preg_replace("~(?<!')language\s*=\s*[\"\']?\s*php\s*[\"\']?~", "<?php echo 'language=php' ?>\n", $compiled_content);
+
+        // recover legit tags
+        $compiled_content = str_replace($tag_guard, '<?', $compiled_content); 
+        
+        // remove \n from the end of the file, if any
+        if (strlen($compiled_content) && (substr($compiled_content, -1) == "\n") ) {
+            $compiled_content = substr($compiled_content, 0, -1);
+        }
+
+        if (!empty($this->_cache_serial)) {
+            $compiled_content = "<?php \$this->_cache_serials['".$this->_cache_include."'] = '".$this->_cache_serial."'; ?>" . $compiled_content;
+        }
+
+        // run compiled template through postfilter functions
+        if (count($this->_plugins['postfilter']) > 0) {
+            foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) {
+                if ($postfilter === false) continue;
+                if ($postfilter[3] || is_callable($postfilter[0])) {
+                    $compiled_content = call_user_func_array($postfilter[0],
+                                                              array($compiled_content, &$this));
+                    $this->_plugins['postfilter'][$filter_name][3] = true;
+                } else {
+                    $this->_trigger_fatal_error("Smarty plugin error: postfilter '$filter_name' is not implemented");
+                }
+            }
+        }
+
+        // put header at the top of the compiled template
+        $template_header = "<?php /* Smarty version ".$this->_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n";
+        $template_header .= "         compiled from ".strtr(urlencode($resource_name), array('%2F'=>'/', '%3A'=>':'))." */ ?>\n";
+
+        /* Emit code to load needed plugins. */
+        $this->_plugins_code = '';
+        if (count($this->_plugin_info)) {
+            $_plugins_params = "array('plugins' => array(";
+            foreach ($this->_plugin_info as $plugin_type => $plugins) {
+                foreach ($plugins as $plugin_name => $plugin_info) {
+                    $_plugins_params .= "array('$plugin_type', '$plugin_name', '" . strtr($plugin_info[0], array("'" => "\\'", "\\" => "\\\\")) . "', $plugin_info[1], ";
+                    $_plugins_params .= $plugin_info[2] ? 'true),' : 'false),';
+                }
+            }
+            $_plugins_params .= '))';
+            $plugins_code = "<?php require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');\nsmarty_core_load_plugins($_plugins_params, \$this); ?>\n";
+            $template_header .= $plugins_code;
+            $this->_plugin_info = array();
+            $this->_plugins_code = $plugins_code;
+        }
+
+        if ($this->_init_smarty_vars) {
+            $template_header .= "<?php require_once(SMARTY_CORE_DIR . 'core.assign_smarty_interface.php');\nsmarty_core_assign_smarty_interface(null, \$this); ?>\n";
+            $this->_init_smarty_vars = false;
+        }
+
+        $compiled_content = $template_header . $compiled_content;
+        return true;
+    }
+
+    /**
+     * Compile a template tag
+     *
+     * @param string $template_tag
+     * @return string
+     */
+    function _compile_tag($template_tag)
+    {
+        /* Matched comment. */
+        if (substr($template_tag, 0, 1) == '*' && substr($template_tag, -1) == '*')
+            return '';
+        
+        /* Split tag into two three parts: command, command modifiers and the arguments. */
+        if(! preg_match('~^(?:(' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp
+                . '|\/?' . $this->_reg_obj_regexp . '|\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*))
+                      (?:\s+(.*))?$
+                    ~xs', $template_tag, $match)) {
+            $this->_syntax_error("unrecognized tag: $template_tag", E_USER_ERROR, __FILE__, __LINE__);
+        }
+        
+        $tag_command = $match[1];
+        $tag_modifier = isset($match[2]) ? $match[2] : null;
+        $tag_args = isset($match[3]) ? $match[3] : null;
+
+        if (preg_match('~^' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$~', $tag_command)) {
+            /* tag name is a variable or object */
+            $_return = $this->_parse_var_props($tag_command . $tag_modifier);
+            return "<?php echo $_return; ?>" . $this->_additional_newline;
+        }
+
+        /* If the tag name is a registered object, we process it. */
+        if (preg_match('~^\/?' . $this->_reg_obj_regexp . '$~', $tag_command)) {
+            return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier);
+        }
+
+        switch ($tag_command) {
+            case 'include':
+                return $this->_compile_include_tag($tag_args);
+
+            case 'include_php':
+                return $this->_compile_include_php_tag($tag_args);
+
+            case 'if':
+                $this->_push_tag('if');
+                return $this->_compile_if_tag($tag_args);
+
+            case 'else':
+                list($_open_tag) = end($this->_tag_stack);
+                if ($_open_tag != 'if' && $_open_tag != 'elseif')
+                    $this->_syntax_error('unexpected {else}', E_USER_ERROR, __FILE__, __LINE__);
+                else
+                    $this->_push_tag('else');
+                return '<?php else: ?>';
+
+            case 'elseif':
+                list($_open_tag) = end($this->_tag_stack);
+                if ($_open_tag != 'if' && $_open_tag != 'elseif')
+                    $this->_syntax_error('unexpected {elseif}', E_USER_ERROR, __FILE__, __LINE__);
+                if ($_open_tag == 'if')
+                    $this->_push_tag('elseif');
+                return $this->_compile_if_tag($tag_args, true);
+
+            case '/if':
+                $this->_pop_tag('if');
+                return '<?php endif; ?>';
+
+            case 'capture':
+                return $this->_compile_capture_tag(true, $tag_args);
+
+            case '/capture':
+                return $this->_compile_capture_tag(false);
+
+            case 'ldelim':
+                return $this->left_delimiter;
+
+            case 'rdelim':
+                return $this->right_delimiter;
+
+            case 'section':
+                $this->_push_tag('section');
+                return $this->_compile_section_start($tag_args);
+
+            case 'sectionelse':
+                $this->_push_tag('sectionelse');
+                return "<?php endfor; else: ?>";
+                break;
+
+            case '/section':
+                $_open_tag = $this->_pop_tag('section');
+                if ($_open_tag == 'sectionelse')
+                    return "<?php endif; ?>";
+                else
+                    return "<?php endfor; endif; ?>";
+
+            case 'foreach':
+                $this->_push_tag('foreach');
+                return $this->_compile_foreach_start($tag_args);
+                break;
+
+            case 'foreachelse':
+                $this->_push_tag('foreachelse');
+                return "<?php endforeach; else: ?>";
+
+            case '/foreach':
+                $_open_tag = $this->_pop_tag('foreach');
+                if ($_open_tag == 'foreachelse')
+                    return "<?php endif; unset(\$_from); ?>";
+                else
+                    return "<?php endforeach; endif; unset(\$_from); ?>";
+                break;
+
+            case 'strip':
+            case '/strip':
+                if (substr($tag_command, 0, 1)=='/') {
+                    $this->_pop_tag('strip');
+                    if (--$this->_strip_depth==0) { /* outermost closing {/strip} */
+                        $this->_additional_newline = "\n";
+                        return '{' . $tag_command . '}';
+                    }
+                } else {
+                    $this->_push_tag('strip');
+                    if ($this->_strip_depth++==0) { /* outermost opening {strip} */
+                        $this->_additional_newline = "";
+                        return '{' . $tag_command . '}';
+                    }
+                }
+                return '';
+
+            case 'php':
+                /* handle folded tags replaced by {php} */
+                list(, $block) = each($this->_folded_blocks);
+                $this->_current_line_no += substr_count($block[0], "\n");
+                /* the number of matched elements in the regexp in _compile_file()
+                   determins the type of folded tag that was found */
+                switch (count($block)) {
+                    case 2: /* comment */
+                        return '';
+
+                    case 3: /* literal */
+                        return "<?php echo '" . strtr($block[2], array("'"=>"\'", "\\"=>"\\\\")) . "'; ?>" . $this->_additional_newline;
+
+                    case 4: /* php */
+                        if ($this->security && !$this->security_settings['PHP_TAGS']) {
+                            $this->_syntax_error("(secure mode) php tags not permitted", E_USER_WARNING, __FILE__, __LINE__);
+                            return;
+                        }
+                        return '<?php ' . $block[3] .' ?>';
+                }
+                break;
+
+            case 'insert':
+                return $this->_compile_insert_tag($tag_args);
+
+            default:
+                if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) {
+                    return $output;
+                } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) {
+                    return $output;
+                } else if ($this->_compile_custom_tag($tag_command, $tag_args, $tag_modifier, $output)) {
+                    return $output;                    
+                } else {
+                    $this->_syntax_error("unrecognized tag '$tag_command'", E_USER_ERROR, __FILE__, __LINE__);
+                }
+
+        }
+    }
+
+
+    /**
+     * compile the custom compiler tag
+     *
+     * sets $output to the compiled custom compiler tag
+     * @param string $tag_command
+     * @param string $tag_args
+     * @param string $output
+     * @return boolean
+     */
+    function _compile_compiler_tag($tag_command, $tag_args, &$output)
+    {
+        $found = false;
+        $have_function = true;
+
+        /*
+         * First we check if the compiler function has already been registered
+         * or loaded from a plugin file.
+         */
+        if (isset($this->_plugins['compiler'][$tag_command])) {
+            $found = true;
+            $plugin_func = $this->_plugins['compiler'][$tag_command][0];
+            if (!is_callable($plugin_func)) {
+                $message = "compiler function '$tag_command' is not implemented";
+                $have_function = false;
+            }
+        }
+        /*
+         * Otherwise we need to load plugin file and look for the function
+         * inside it.
+         */
+        else if ($plugin_file = $this->_get_plugin_filepath('compiler', $tag_command)) {
+            $found = true;
+
+            include_once $plugin_file;
+
+            $plugin_func = 'smarty_compiler_' . $tag_command;
+            if (!is_callable($plugin_func)) {
+                $message = "plugin function $plugin_func() not found in $plugin_file\n";
+                $have_function = false;
+            } else {
+                $this->_plugins['compiler'][$tag_command] = array($plugin_func, null, null, null, true);
+            }
+        }
+
+        /*
+         * True return value means that we either found a plugin or a
+         * dynamically registered function. False means that we didn't and the
+         * compiler should now emit code to load custom function plugin for this
+         * tag.
+         */
+        if ($found) {
+            if ($have_function) {
+                $output = call_user_func_array($plugin_func, array($tag_args, &$this));
+                if($output != '') {
+                $output = '<?php ' . $this->_push_cacheable_state('compiler', $tag_command)
+                                   . $output
+                                   . $this->_pop_cacheable_state('compiler', $tag_command) . ' ?>';
+                }
+            } else {
+                $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+    /**
+     * compile block function tag
+     *
+     * sets $output to compiled block function tag
+     * @param string $tag_command
+     * @param string $tag_args
+     * @param string $tag_modifier
+     * @param string $output
+     * @return boolean
+     */
+    function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$output)
+    {
+        if (substr($tag_command, 0, 1) == '/') {
+            $start_tag = false;
+            $tag_command = substr($tag_command, 1);
+        } else
+            $start_tag = true;
+
+        $found = false;
+        $have_function = true;
+
+        /*
+         * First we check if the block function has already been registered
+         * or loaded from a plugin file.
+         */
+        if (isset($this->_plugins['block'][$tag_command])) {
+            $found = true;
+            $plugin_func = $this->_plugins['block'][$tag_command][0];
+            if (!is_callable($plugin_func)) {
+                $message = "block function '$tag_command' is not implemented";
+                $have_function = false;
+            }
+        }
+        /*
+         * Otherwise we need to load plugin file and look for the function
+         * inside it.
+         */
+        else if ($plugin_file = $this->_get_plugin_filepath('block', $tag_command)) {
+            $found = true;
+
+            include_once $plugin_file;
+
+            $plugin_func = 'smarty_block_' . $tag_command;
+            if (!function_exists($plugin_func)) {
+                $message = "plugin function $plugin_func() not found in $plugin_file\n";
+                $have_function = false;
+            } else {
+                $this->_plugins['block'][$tag_command] = array($plugin_func, null, null, null, true);
+
+            }
+        }
+
+        if (!$found) {
+            return false;
+        } else if (!$have_function) {
+            $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
+            return true;
+        }
+
+        /*
+         * Even though we've located the plugin function, compilation
+         * happens only once, so the plugin will still need to be loaded
+         * at runtime for future requests.
+         */
+        $this->_add_plugin('block', $tag_command);
+
+        if ($start_tag)
+            $this->_push_tag($tag_command);
+        else
+            $this->_pop_tag($tag_command);
+
+        if ($start_tag) {
+            $output = '<?php ' . $this->_push_cacheable_state('block', $tag_command);
+            $attrs = $this->_parse_attrs($tag_args);
+            $_cache_attrs='';
+            $arg_list = $this->_compile_arg_list('block', $tag_command, $attrs, $_cache_attrs);
+            $output .= "$_cache_attrs\$this->_tag_stack[] = array('$tag_command', array(".implode(',', $arg_list).')); ';
+            $output .= '$_block_repeat=true;' . $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], null, $this, $_block_repeat);';
+            $output .= 'while ($_block_repeat) { ob_start(); ?>';
+        } else {
+            $output = '<?php $_block_content = ob_get_contents(); ob_end_clean(); ';
+            $_out_tag_text = $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], $_block_content, $this, $_block_repeat)';
+            if ($tag_modifier != '') {
+                $this->_parse_modifiers($_out_tag_text, $tag_modifier);
+            }
+            $output .= '$_block_repeat=false;echo ' . $_out_tag_text . '; } ';
+            $output .= " array_pop(\$this->_tag_stack); " . $this->_pop_cacheable_state('block', $tag_command) . '?>';
+        }
+
+        return true;
+    }
+
+
+    /**
+     * compile custom function tag
+     *
+     * @param string $tag_command
+     * @param string $tag_args
+     * @param string $tag_modifier
+     * @return string
+     */
+    function _compile_custom_tag($tag_command, $tag_args, $tag_modifier, &$output)
+    {
+        $found = false;
+        $have_function = true;
+
+        /*
+         * First we check if the custom function has already been registered
+         * or loaded from a plugin file.
+         */
+        if (isset($this->_plugins['function'][$tag_command])) {
+            $found = true;
+            $plugin_func = $this->_plugins['function'][$tag_command][0];
+            if (!is_callable($plugin_func)) {
+                $message = "custom function '$tag_command' is not implemented";
+                $have_function = false;
+            }
+        }
+        /*
+         * Otherwise we need to load plugin file and look for the function
+         * inside it.
+         */
+        else if ($plugin_file = $this->_get_plugin_filepath('function', $tag_command)) {
+            $found = true;
+
+            include_once $plugin_file;
+
+            $plugin_func = 'smarty_function_' . $tag_command;
+            if (!function_exists($plugin_func)) {
+                $message = "plugin function $plugin_func() not found in $plugin_file\n";
+                $have_function = false;
+            } else {
+                $this->_plugins['function'][$tag_command] = array($plugin_func, null, null, null, true);
+
+            }
+        }
+
+        if (!$found) {
+            return false;
+        } else if (!$have_function) {
+            $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
+            return true;
+        }
+
+        /* declare plugin to be loaded on display of the template that
+           we compile right now */
+        $this->_add_plugin('function', $tag_command);
+
+        $_cacheable_state = $this->_push_cacheable_state('function', $tag_command);
+        $attrs = $this->_parse_attrs($tag_args);
+        $_cache_attrs = '';
+        $arg_list = $this->_compile_arg_list('function', $tag_command, $attrs, $_cache_attrs);
+
+        $output = $this->_compile_plugin_call('function', $tag_command).'(array('.implode(',', $arg_list)."), \$this)";
+        if($tag_modifier != '') {
+            $this->_parse_modifiers($output, $tag_modifier);
+        }
+
+        if($output != '') {
+            $output =  '<?php ' . $_cacheable_state . $_cache_attrs . 'echo ' . $output . ';'
+                . $this->_pop_cacheable_state('function', $tag_command) . "?>" . $this->_additional_newline;
+        }
+
+        return true;
+    }
+
+    /**
+     * compile a registered object tag
+     *
+     * @param string $tag_command
+     * @param array $attrs
+     * @param string $tag_modifier
+     * @return string
+     */
+    function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier)
+    {
+        if (substr($tag_command, 0, 1) == '/') {
+            $start_tag = false;
+            $tag_command = substr($tag_command, 1);
+        } else {
+            $start_tag = true;
+        }
+
+        list($object, $obj_comp) = explode('->', $tag_command);
+
+        $arg_list = array();
+        if(count($attrs)) {
+            $_assign_var = false;
+            foreach ($attrs as $arg_name => $arg_value) {
+                if($arg_name == 'assign') {
+                    $_assign_var = $arg_value;
+                    unset($attrs['assign']);
+                    continue;
+                }
+                if (is_bool($arg_value))
+                    $arg_value = $arg_value ? 'true' : 'false';
+                $arg_list[] = "'$arg_name' => $arg_value";
+            }
+        }
+
+        if($this->_reg_objects[$object][2]) {
+            // smarty object argument format
+            $args = "array(".implode(',', (array)$arg_list)."), \$this";
+        } else {
+            // traditional argument format
+            $args = implode(',', array_values($attrs));
+            if (empty($args)) {
+                $args = 'null';
+            }
+        }
+
+        $prefix = '';
+        $postfix = '';
+        $newline = '';
+        if(!is_object($this->_reg_objects[$object][0])) {
+            $this->_trigger_fatal_error("registered '$object' is not an object" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
+        } elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) {
+            $this->_trigger_fatal_error("'$obj_comp' is not a registered component of object '$object'", $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
+        } elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) {
+            // method
+            if(in_array($obj_comp, $this->_reg_objects[$object][3])) {
+                // block method
+                if ($start_tag) {
+                    $prefix = "\$this->_tag_stack[] = array('$obj_comp', $args); ";
+                    $prefix .= "\$_block_repeat=true; \$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], null, \$this, \$_block_repeat); ";
+                    $prefix .= "while (\$_block_repeat) { ob_start();";
+                    $return = null;
+                    $postfix = '';
+                } else {
+                    $prefix = "\$_obj_block_content = ob_get_contents(); ob_end_clean(); \$_block_repeat=false;";
+                    $return = "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], \$_obj_block_content, \$this, \$_block_repeat)";
+                    $postfix = "} array_pop(\$this->_tag_stack);";
+                }
+            } else {
+                // non-block method
+                $return = "\$this->_reg_objects['$object'][0]->$obj_comp($args)";
+            }
+        } else {
+            // property
+            $return = "\$this->_reg_objects['$object'][0]->$obj_comp";
+        }
+
+        if($return != null) {
+            if($tag_modifier != '') {
+                $this->_parse_modifiers($return, $tag_modifier);
+            }
+
+            if(!empty($_assign_var)) {
+                $output = "\$this->assign('" . $this->_dequote($_assign_var) ."',  $return);";
+            } else {
+                $output = 'echo ' . $return . ';';
+                $newline = $this->_additional_newline;
+            }
+        } else {
+            $output = '';
+        }
+
+        return '<?php ' . $prefix . $output . $postfix . "?>" . $newline;
+    }
+
+    /**
+     * Compile {insert ...} tag
+     *
+     * @param string $tag_args
+     * @return string
+     */
+    function _compile_insert_tag($tag_args)
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+        $name = $this->_dequote($attrs['name']);
+
+        if (empty($name)) {
+            return $this->_syntax_error("missing insert name", E_USER_ERROR, __FILE__, __LINE__);
+        }
+        
+        if (!preg_match('~^\w+$~', $name)) {
+            return $this->_syntax_error("'insert: 'name' must be an insert function name", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        if (!empty($attrs['script'])) {
+            $delayed_loading = true;
+        } else {
+            $delayed_loading = false;
+        }
+
+        foreach ($attrs as $arg_name => $arg_value) {
+            if (is_bool($arg_value))
+                $arg_value = $arg_value ? 'true' : 'false';
+            $arg_list[] = "'$arg_name' => $arg_value";
+        }
+
+        $this->_add_plugin('insert', $name, $delayed_loading);
+
+        $_params = "array('args' => array(".implode(', ', (array)$arg_list)."))";
+
+        return "<?php require_once(SMARTY_CORE_DIR . 'core.run_insert_handler.php');\necho smarty_core_run_insert_handler($_params, \$this); ?>" . $this->_additional_newline;
+    }
+
+    /**
+     * Compile {include ...} tag
+     *
+     * @param string $tag_args
+     * @return string
+     */
+    function _compile_include_tag($tag_args)
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+        $arg_list = array();
+
+        if (empty($attrs['file'])) {
+            $this->_syntax_error("missing 'file' attribute in include tag", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        foreach ($attrs as $arg_name => $arg_value) {
+            if ($arg_name == 'file') {
+                $include_file = $arg_value;
+                continue;
+            } else if ($arg_name == 'assign') {
+                $assign_var = $arg_value;
+                continue;
+            }
+            if (is_bool($arg_value))
+                $arg_value = $arg_value ? 'true' : 'false';
+            $arg_list[] = "'$arg_name' => $arg_value";
+        }
+
+        $output = '<?php ';
+
+        if (isset($assign_var)) {
+            $output .= "ob_start();\n";
+        }
+
+        $output .=
+            "\$_smarty_tpl_vars = \$this->_tpl_vars;\n";
+
+
+        $_params = "array('smarty_include_tpl_file' => " . $include_file . ", 'smarty_include_vars' => array(".implode(',', (array)$arg_list)."))";
+        $output .= "\$this->_smarty_include($_params);\n" .
+        "\$this->_tpl_vars = \$_smarty_tpl_vars;\n" .
+        "unset(\$_smarty_tpl_vars);\n";
+
+        if (isset($assign_var)) {
+            $output .= "\$this->assign(" . $assign_var . ", ob_get_contents()); ob_end_clean();\n";
+        }
+
+        $output .= ' ?>';
+
+        return $output;
+
+    }
+
+    /**
+     * Compile {include ...} tag
+     *
+     * @param string $tag_args
+     * @return string
+     */
+    function _compile_include_php_tag($tag_args)
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+
+        if (empty($attrs['file'])) {
+            $this->_syntax_error("missing 'file' attribute in include_php tag", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        $assign_var = (empty($attrs['assign'])) ? '' : $this->_dequote($attrs['assign']);
+        $once_var = (empty($attrs['once']) || $attrs['once']=='false') ? 'false' : 'true';
+
+        $arg_list = array();
+        foreach($attrs as $arg_name => $arg_value) {
+            if($arg_name != 'file' AND $arg_name != 'once' AND $arg_name != 'assign') {
+                if(is_bool($arg_value))
+                    $arg_value = $arg_value ? 'true' : 'false';
+                $arg_list[] = "'$arg_name' => $arg_value";
+            }
+        }
+
+        $_params = "array('smarty_file' => " . $attrs['file'] . ", 'smarty_assign' => '$assign_var', 'smarty_once' => $once_var, 'smarty_include_vars' => array(".implode(',', $arg_list)."))";
+
+        return "<?php require_once(SMARTY_CORE_DIR . 'core.smarty_include_php.php');\nsmarty_core_smarty_include_php($_params, \$this); ?>" . $this->_additional_newline;
+    }
+
+
+    /**
+     * Compile {section ...} tag
+     *
+     * @param string $tag_args
+     * @return string
+     */
+    function _compile_section_start($tag_args)
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+        $arg_list = array();
+
+        $output = '<?php ';
+        $section_name = $attrs['name'];
+        if (empty($section_name)) {
+            $this->_syntax_error("missing section name", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        $output .= "unset(\$this->_sections[$section_name]);\n";
+        $section_props = "\$this->_sections[$section_name]";
+
+        foreach ($attrs as $attr_name => $attr_value) {
+            switch ($attr_name) {
+                case 'loop':
+                    $output .= "{$section_props}['loop'] = is_array(\$_loop=$attr_value) ? count(\$_loop) : max(0, (int)\$_loop); unset(\$_loop);\n";
+                    break;
+
+                case 'show':
+                    if (is_bool($attr_value))
+                        $show_attr_value = $attr_value ? 'true' : 'false';
+                    else
+                        $show_attr_value = "(bool)$attr_value";
+                    $output .= "{$section_props}['show'] = $show_attr_value;\n";
+                    break;
+
+                case 'name':
+                    $output .= "{$section_props}['$attr_name'] = $attr_value;\n";
+                    break;
+
+                case 'max':
+                case 'start':
+                    $output .= "{$section_props}['$attr_name'] = (int)$attr_value;\n";
+                    break;
+
+                case 'step':
+                    $output .= "{$section_props}['$attr_name'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\n";
+                    break;
+
+                default:
+                    $this->_syntax_error("unknown section attribute - '$attr_name'", E_USER_ERROR, __FILE__, __LINE__);
+                    break;
+            }
+        }
+
+        if (!isset($attrs['show']))
+            $output .= "{$section_props}['show'] = true;\n";
+
+        if (!isset($attrs['loop']))
+            $output .= "{$section_props}['loop'] = 1;\n";
+
+        if (!isset($attrs['max']))
+            $output .= "{$section_props}['max'] = {$section_props}['loop'];\n";
+        else
+            $output .= "if ({$section_props}['max'] < 0)\n" .
+                       "    {$section_props}['max'] = {$section_props}['loop'];\n";
+
+        if (!isset($attrs['step']))
+            $output .= "{$section_props}['step'] = 1;\n";
+
+        if (!isset($attrs['start']))
+            $output .= "{$section_props}['start'] = {$section_props}['step'] > 0 ? 0 : {$section_props}['loop']-1;\n";
+        else {
+            $output .= "if ({$section_props}['start'] < 0)\n" .
+                       "    {$section_props}['start'] = max({$section_props}['step'] > 0 ? 0 : -1, {$section_props}['loop'] + {$section_props}['start']);\n" .
+                       "else\n" .
+                       "    {$section_props}['start'] = min({$section_props}['start'], {$section_props}['step'] > 0 ? {$section_props}['loop'] : {$section_props}['loop']-1);\n";
+        }
+
+        $output .= "if ({$section_props}['show']) {\n";
+        if (!isset($attrs['start']) && !isset($attrs['step']) && !isset($attrs['max'])) {
+            $output .= "    {$section_props}['total'] = {$section_props}['loop'];\n";
+        } else {
+            $output .= "    {$section_props}['total'] = min(ceil(({$section_props}['step'] > 0 ? {$section_props}['loop'] - {$section_props}['start'] : {$section_props}['start']+1)/abs({$section_props}['step'])), {$section_props}['max']);\n";
+        }
+        $output .= "    if ({$section_props}['total'] == 0)\n" .
+                   "        {$section_props}['show'] = false;\n" .
+                   "} else\n" .
+                   "    {$section_props}['total'] = 0;\n";
+
+        $output .= "if ({$section_props}['show']):\n";
+        $output .= "
+            for ({$section_props}['index'] = {$section_props}['start'], {$section_props}['iteration'] = 1;
+                 {$section_props}['iteration'] <= {$section_props}['total'];
+                 {$section_props}['index'] += {$section_props}['step'], {$section_props}['iteration']++):\n";
+        $output .= "{$section_props}['rownum'] = {$section_props}['iteration'];\n";
+        $output .= "{$section_props}['index_prev'] = {$section_props}['index'] - {$section_props}['step'];\n";
+        $output .= "{$section_props}['index_next'] = {$section_props}['index'] + {$section_props}['step'];\n";
+        $output .= "{$section_props}['first']      = ({$section_props}['iteration'] == 1);\n";
+        $output .= "{$section_props}['last']       = ({$section_props}['iteration'] == {$section_props}['total']);\n";
+
+        $output .= "?>";
+
+        return $output;
+    }
+
+
+    /**
+     * Compile {foreach ...} tag.
+     *
+     * @param string $tag_args
+     * @return string
+     */
+    function _compile_foreach_start($tag_args)
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+        $arg_list = array();
+
+        if (empty($attrs['from'])) {
+            return $this->_syntax_error("foreach: missing 'from' attribute", E_USER_ERROR, __FILE__, __LINE__);
+        }
+        $from = $attrs['from'];
+
+        if (empty($attrs['item'])) {
+            return $this->_syntax_error("foreach: missing 'item' attribute", E_USER_ERROR, __FILE__, __LINE__);
+        }
+        $item = $this->_dequote($attrs['item']);
+        if (!preg_match('~^\w+$~', $item)) {
+            return $this->_syntax_error("'foreach: 'item' must be a variable name (literal string)", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        if (isset($attrs['key'])) {
+            $key  = $this->_dequote($attrs['key']);
+            if (!preg_match('~^\w+$~', $key)) {
+                return $this->_syntax_error("foreach: 'key' must to be a variable name (literal string)", E_USER_ERROR, __FILE__, __LINE__);
+            }
+            $key_part = "\$this->_tpl_vars['$key'] => ";
+        } else {
+            $key = null;
+            $key_part = '';
+        }
+
+        if (isset($attrs['name'])) {
+            $name = $attrs['name'];
+        } else {
+            $name = null;
+        }
+
+        $output = '<?php ';
+        $output .= "\$_from = $from; if (!is_array(\$_from) && !is_object(\$_from)) { settype(\$_from, 'array'); }";
+        if (isset($name)) {
+            $foreach_props = "\$this->_foreach[$name]";
+            $output .= "{$foreach_props} = array('total' => count(\$_from), 'iteration' => 0);\n";
+            $output .= "if ({$foreach_props}['total'] > 0):\n";
+            $output .= "    foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
+            $output .= "        {$foreach_props}['iteration']++;\n";
+        } else {
+            $output .= "if (count(\$_from)):\n";
+            $output .= "    foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
+        }
+        $output .= '?>';
+
+        return $output;
+    }
+
+
+    /**
+     * Compile {capture} .. {/capture} tags
+     *
+     * @param boolean $start true if this is the {capture} tag
+     * @param string $tag_args
+     * @return string
+     */
+
+    function _compile_capture_tag($start, $tag_args = '')
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+
+        if ($start) {
+            if (isset($attrs['name']))
+                $buffer = $attrs['name'];
+            else
+                $buffer = "'default'";
+
+            if (isset($attrs['assign']))
+                $assign = $attrs['assign'];
+            else
+                $assign = null;
+            $output = "<?php ob_start(); ?>";
+            $this->_capture_stack[] = array($buffer, $assign);
+        } else {
+            list($buffer, $assign) = array_pop($this->_capture_stack);
+            $output = "<?php \$this->_smarty_vars['capture'][$buffer] = ob_get_contents(); ";
+            if (isset($assign)) {
+                $output .= " \$this->assign($assign, ob_get_contents());";
+            }
+            $output .= "ob_end_clean(); ?>";
+        }
+
+        return $output;
+    }
+
+    /**
+     * Compile {if ...} tag
+     *
+     * @param string $tag_args
+     * @param boolean $elseif if true, uses elseif instead of if
+     * @return string
+     */
+    function _compile_if_tag($tag_args, $elseif = false)
+    {
+
+        /* Tokenize args for 'if' tag. */
+        preg_match_all('~(?>
+                ' . $this->_obj_call_regexp . '(?:' . $this->_mod_regexp . '*)? | # valid object call
+                ' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)?    | # var or quoted string
+                \-?0[xX][0-9a-fA-F]+|\-?\d+(?:\.\d+)?|\.\d+|!==|===|==|!=|<>|<<|>>|<=|>=|\&\&|\|\||\(|\)|,|\!|\^|=|\&|\~|<|>|\||\%|\+|\-|\/|\*|\@    | # valid non-word token
+                \b\w+\b                                                        | # valid word token
+                \S+                                                           # anything else
+                )~x', $tag_args, $match);
+
+        $tokens = $match[0];
+
+        if(empty($tokens)) {
+            $_error_msg = $elseif ? "'elseif'" : "'if'";
+            $_error_msg .= ' statement requires arguments'; 
+            $this->_syntax_error($_error_msg, E_USER_ERROR, __FILE__, __LINE__);
+        }
+            
+                
+        // make sure we have balanced parenthesis
+        $token_count = array_count_values($tokens);
+        if(isset($token_count['(']) && $token_count['('] != $token_count[')']) {
+            $this->_syntax_error("unbalanced parenthesis in if statement", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        $is_arg_stack = array();
+
+        for ($i = 0; $i < count($tokens); $i++) {
+
+            $token = &$tokens[$i];
+
+            switch (strtolower($token)) {
+                case '!':
+                case '%':
+                case '!==':
+                case '==':
+                case '===':
+                case '>':
+                case '<':
+                case '!=':
+                case '<>':
+                case '<<':
+                case '>>':
+                case '<=':
+                case '>=':
+                case '&&':
+                case '||':
+                case '|':
+                case '^':
+                case '&':
+                case '~':
+                case ')':
+                case ',':
+                case '+':
+                case '-':
+                case '*':
+                case '/':
+                case '@':
+                    break;
+
+                case 'eq':
+                    $token = '==';
+                    break;
+
+                case 'ne':
+                case 'neq':
+                    $token = '!=';
+                    break;
+
+                case 'lt':
+                    $token = '<';
+                    break;
+
+                case 'le':
+                case 'lte':
+                    $token = '<=';
+                    break;
+
+                case 'gt':
+                    $token = '>';
+                    break;
+
+                case 'ge':
+                case 'gte':
+                    $token = '>=';
+                    break;
+
+                case 'and':
+                    $token = '&&';
+                    break;
+
+                case 'or':
+                    $token = '||';
+                    break;
+
+                case 'not':
+                    $token = '!';
+                    break;
+
+                case 'mod':
+                    $token = '%';
+                    break;
+
+                case '(':
+                    array_push($is_arg_stack, $i);
+                    break;
+
+                case 'is':
+                    /* If last token was a ')', we operate on the parenthesized
+                       expression. The start of the expression is on the stack.
+                       Otherwise, we operate on the last encountered token. */
+                    if ($tokens[$i-1] == ')')
+                        $is_arg_start = array_pop($is_arg_stack);
+                    else
+                        $is_arg_start = $i-1;
+                    /* Construct the argument for 'is' expression, so it knows
+                       what to operate on. */
+                    $is_arg = implode(' ', array_slice($tokens, $is_arg_start, $i - $is_arg_start));
+
+                    /* Pass all tokens from next one until the end to the
+                       'is' expression parsing function. The function will
+                       return modified tokens, where the first one is the result
+                       of the 'is' expression and the rest are the tokens it
+                       didn't touch. */
+                    $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1));
+
+                    /* Replace the old tokens with the new ones. */
+                    array_splice($tokens, $is_arg_start, count($tokens), $new_tokens);
+
+                    /* Adjust argument start so that it won't change from the
+                       current position for the next iteration. */
+                    $i = $is_arg_start;
+                    break;
+
+                default:
+                    if(preg_match('~^' . $this->_func_regexp . '$~', $token) ) {
+                            // function call
+                            if($this->security &&
+                               !in_array($token, $this->security_settings['IF_FUNCS'])) {
+                                $this->_syntax_error("(secure mode) '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__);
+                            }
+                    } elseif(preg_match('~^' . $this->_var_regexp . '$~', $token) && (strpos('+-*/^%&|', substr($token, -1)) === false) && isset($tokens[$i+1]) && $tokens[$i+1] == '(') {
+                        // variable function call
+                        $this->_syntax_error("variable function call '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__);                      
+                    } elseif(preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)$~', $token)) {
+                        // object or variable
+                        $token = $this->_parse_var_props($token);
+                    } elseif(is_numeric($token)) {
+                        // number, skip it
+                    } else {
+                        $this->_syntax_error("unidentified token '$token'", E_USER_ERROR, __FILE__, __LINE__);
+                    }
+                    break;
+            }
+        }
+
+        if ($elseif)
+            return '<?php elseif ('.implode(' ', $tokens).'): ?>';
+        else
+            return '<?php if ('.implode(' ', $tokens).'): ?>';
+    }
+
+
+    function _compile_arg_list($type, $name, $attrs, &$cache_code) {
+        $arg_list = array();
+
+        if (isset($type) && isset($name)
+            && isset($this->_plugins[$type])
+            && isset($this->_plugins[$type][$name])
+            && empty($this->_plugins[$type][$name][4])
+            && is_array($this->_plugins[$type][$name][5])
+            ) {
+            /* we have a list of parameters that should be cached */
+            $_cache_attrs = $this->_plugins[$type][$name][5];
+            $_count = $this->_cache_attrs_count++;
+            $cache_code = "\$_cache_attrs =& \$this->_smarty_cache_attrs('$this->_cache_serial','$_count');";
+
+        } else {
+            /* no parameters are cached */
+            $_cache_attrs = null;
+        }
+
+        foreach ($attrs as $arg_name => $arg_value) {
+            if (is_bool($arg_value))
+                $arg_value = $arg_value ? 'true' : 'false';
+            if (is_null($arg_value))
+                $arg_value = 'null';
+            if ($_cache_attrs && in_array($arg_name, $_cache_attrs)) {
+                $arg_list[] = "'$arg_name' => (\$this->_cache_including) ? \$_cache_attrs['$arg_name'] : (\$_cache_attrs['$arg_name']=$arg_value)";
+            } else {
+                $arg_list[] = "'$arg_name' => $arg_value";
+            }
+        }
+        return $arg_list;
+    }
+
+    /**
+     * Parse is expression
+     *
+     * @param string $is_arg
+     * @param array $tokens
+     * @return array
+     */
+    function _parse_is_expr($is_arg, $tokens)
+    {
+        $expr_end = 0;
+        $negate_expr = false;
+
+        if (($first_token = array_shift($tokens)) == 'not') {
+            $negate_expr = true;
+            $expr_type = array_shift($tokens);
+        } else
+            $expr_type = $first_token;
+
+        switch ($expr_type) {
+            case 'even':
+                if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') {
+                    $expr_end++;
+                    $expr_arg = $tokens[$expr_end++];
+                    $expr = "!(1 & ($is_arg / " . $this->_parse_var_props($expr_arg) . "))";
+                } else
+                    $expr = "!(1 & $is_arg)";
+                break;
+
+            case 'odd':
+                if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') {
+                    $expr_end++;
+                    $expr_arg = $tokens[$expr_end++];
+                    $expr = "(1 & ($is_arg / " . $this->_parse_var_props($expr_arg) . "))";
+                } else
+                    $expr = "(1 & $is_arg)";
+                break;
+
+            case 'div':
+                if (@$tokens[$expr_end] == 'by') {
+                    $expr_end++;
+                    $expr_arg = $tokens[$expr_end++];
+                    $expr = "!($is_arg % " . $this->_parse_var_props($expr_arg) . ")";
+                } else {
+                    $this->_syntax_error("expecting 'by' after 'div'", E_USER_ERROR, __FILE__, __LINE__);
+                }
+                break;
+
+            default:
+                $this->_syntax_error("unknown 'is' expression - '$expr_type'", E_USER_ERROR, __FILE__, __LINE__);
+                break;
+        }
+
+        if ($negate_expr) {
+            $expr = "!($expr)";
+        }
+
+        array_splice($tokens, 0, $expr_end, $expr);
+
+        return $tokens;
+    }
+
+
+    /**
+     * Parse attribute string
+     *
+     * @param string $tag_args
+     * @return array
+     */
+    function _parse_attrs($tag_args)
+    {
+
+        /* Tokenize tag attributes. */
+        preg_match_all('~(?:' . $this->_obj_call_regexp . '|' . $this->_qstr_regexp . ' | (?>[^"\'=\s]+)
+                         )+ |
+                         [=]
+                        ~x', $tag_args, $match);
+        $tokens       = $match[0];
+
+        $attrs = array();
+        /* Parse state:
+            0 - expecting attribute name
+            1 - expecting '='
+            2 - expecting attribute value (not '=') */
+        $state = 0;
+
+        foreach ($tokens as $token) {
+            switch ($state) {
+                case 0:
+                    /* If the token is a valid identifier, we set attribute name
+                       and go to state 1. */
+                    if (preg_match('~^\w+$~', $token)) {
+                        $attr_name = $token;
+                        $state = 1;
+                    } else
+                        $this->_syntax_error("invalid attribute name: '$token'", E_USER_ERROR, __FILE__, __LINE__);
+                    break;
+
+                case 1:
+                    /* If the token is '=', then we go to state 2. */
+                    if ($token == '=') {
+                        $state = 2;
+                    } else
+                        $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__);
+                    break;
+
+                case 2:
+                    /* If token is not '=', we set the attribute value and go to
+                       state 0. */
+                    if ($token != '=') {
+                        /* We booleanize the token if it's a non-quoted possible
+                           boolean value. */
+                        if (preg_match('~^(on|yes|true)$~', $token)) {
+                            $token = 'true';
+                        } else if (preg_match('~^(off|no|false)$~', $token)) {
+                            $token = 'false';
+                        } else if ($token == 'null') {
+                            $token = 'null';
+                        } else if (preg_match('~^' . $this->_num_const_regexp . '|0[xX][0-9a-fA-F]+$~', $token)) {
+                            /* treat integer literally */
+                        } else if (!preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . ')*$~', $token)) {
+                            /* treat as a string, double-quote it escaping quotes */
+                            $token = '"'.addslashes($token).'"';
+                        }
+
+                        $attrs[$attr_name] = $token;
+                        $state = 0;
+                    } else
+                        $this->_syntax_error("'=' cannot be an attribute value", E_USER_ERROR, __FILE__, __LINE__);
+                    break;
+            }
+            $last_token = $token;
+        }
+
+        if($state != 0) {
+            if($state == 1) {
+                $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__);
+            } else {
+                $this->_syntax_error("missing attribute value", E_USER_ERROR, __FILE__, __LINE__);
+            }
+        }
+
+        $this->_parse_vars_props($attrs);
+
+        return $attrs;
+    }
+
+    /**
+     * compile multiple variables and section properties tokens into
+     * PHP code
+     *
+     * @param array $tokens
+     */
+    function _parse_vars_props(&$tokens)
+    {
+        foreach($tokens as $key => $val) {
+            $tokens[$key] = $this->_parse_var_props($val);
+        }
+    }
+
+    /**
+     * compile single variable and section properties token into
+     * PHP code
+     *
+     * @param string $val
+     * @param string $tag_attrs
+     * @return string
+     */
+    function _parse_var_props($val)
+    {
+        $val = trim($val);
+
+        if(preg_match('~^(' . $this->_obj_call_regexp . '|' . $this->_dvar_regexp . ')(' . $this->_mod_regexp . '*)$~', $val, $match)) {
+            // $ variable or object
+            $return = $this->_parse_var($match[1]);
+            $modifiers = $match[2];
+            if (!empty($this->default_modifiers) && !preg_match('~(^|\|)smarty:nodefaults($|\|)~',$modifiers)) {
+                $_default_mod_string = implode('|',(array)$this->default_modifiers);
+                $modifiers = empty($modifiers) ? $_default_mod_string : $_default_mod_string . '|' . $modifiers;
+            }
+            $this->_parse_modifiers($return, $modifiers);
+            return $return;
+        } elseif (preg_match('~^' . $this->_db_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
+                // double quoted text
+                preg_match('~^(' . $this->_db_qstr_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);
+                $return = $this->_expand_quoted_text($match[1]);
+                if($match[2] != '') {
+                    $this->_parse_modifiers($return, $match[2]);
+                }
+                return $return;
+            }
+        elseif(preg_match('~^' . $this->_num_const_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
+                // numerical constant
+                preg_match('~^(' . $this->_num_const_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);
+                if($match[2] != '') {
+                    $this->_parse_modifiers($match[1], $match[2]);
+                    return $match[1];
+                }
+            }
+        elseif(preg_match('~^' . $this->_si_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
+                // single quoted text
+                preg_match('~^(' . $this->_si_qstr_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);
+                if($match[2] != '') {
+                    $this->_parse_modifiers($match[1], $match[2]);
+                    return $match[1];
+                }
+            }
+        elseif(preg_match('~^' . $this->_cvar_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
+                // config var
+                return $this->_parse_conf_var($val);
+            }
+        elseif(preg_match('~^' . $this->_svar_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
+                // section var
+                return $this->_parse_section_prop($val);
+            }
+        elseif(!in_array($val, $this->_permitted_tokens) && !is_numeric($val)) {
+            // literal string
+            return $this->_expand_quoted_text('"' . strtr($val, array('\\' => '\\\\', '"' => '\\"')) .'"');
+        }
+        return $val;
+    }
+
+    /**
+     * expand quoted text with embedded variables
+     *
+     * @param string $var_expr
+     * @return string
+     */
+    function _expand_quoted_text($var_expr)
+    {
+        // if contains unescaped $, expand it
+        if(preg_match_all('~(?:\`(?<!\\\\)\$' . $this->_dvar_guts_regexp . '(?:' . $this->_obj_ext_regexp . ')*\`)|(?:(?<!\\\\)\$\w+(\[[a-zA-Z0-9]+\])*)~', $var_expr, $_match)) {
+            $_match = $_match[0];
+            $_replace = array();
+            foreach($_match as $_var) {
+                $_replace[$_var] = '".(' . $this->_parse_var(str_replace('`','',$_var)) . ')."';
+            }
+            $var_expr = strtr($var_expr, $_replace);
+            $_return = preg_replace('~\.""|(?<!\\\\)""\.~', '', $var_expr);
+        } else {
+            $_return = $var_expr;
+        }
+        // replace double quoted literal string with single quotes
+        $_return = preg_replace('~^"([\s\w]+)"$~',"'\\1'",$_return);
+        return $_return;
+    }
+
+    /**
+     * parse variable expression into PHP code
+     *
+     * @param string $var_expr
+     * @param string $output
+     * @return string
+     */
+    function _parse_var($var_expr)
+    {
+        $_has_math = false;
+        $_math_vars = preg_split('~('.$this->_dvar_math_regexp.'|'.$this->_qstr_regexp.')~', $var_expr, -1, PREG_SPLIT_DELIM_CAPTURE);
+
+        if(count($_math_vars) > 1) {
+            $_first_var = "";
+            $_complete_var = "";
+            $_output = "";
+            // simple check if there is any math, to stop recursion (due to modifiers with "xx % yy" as parameter)
+            foreach($_math_vars as $_k => $_math_var) {
+                $_math_var = $_math_vars[$_k];
+
+                if(!empty($_math_var) || is_numeric($_math_var)) {
+                    // hit a math operator, so process the stuff which came before it
+                    if(preg_match('~^' . $this->_dvar_math_regexp . '$~', $_math_var)) {
+                        $_has_math = true;
+                        if(!empty($_complete_var) || is_numeric($_complete_var)) {
+                            $_output .= $this->_parse_var($_complete_var);
+                        }
+
+                        // just output the math operator to php
+                        $_output .= $_math_var;
+
+                        if(empty($_first_var))
+                            $_first_var = $_complete_var;
+
+                        $_complete_var = "";
+                    } else {
+                        $_complete_var .= $_math_var;
+                    }
+                }
+            }
+            if($_has_math) {
+                if(!empty($_complete_var) || is_numeric($_complete_var))
+                    $_output .= $this->_parse_var($_complete_var);
+
+                // get the modifiers working (only the last var from math + modifier is left)
+                $var_expr = $_complete_var;
+            }
+        }
+
+        // prevent cutting of first digit in the number (we _definitly_ got a number if the first char is a digit)
+        if(is_numeric(substr($var_expr, 0, 1)))
+            $_var_ref = $var_expr;
+        else
+            $_var_ref = substr($var_expr, 1);
+        
+        if(!$_has_math) {
+            
+            // get [foo] and .foo and ->foo and (...) pieces
+            preg_match_all('~(?:^\w+)|' . $this->_obj_params_regexp . '|(?:' . $this->_var_bracket_regexp . ')|->\$?\w+|\.\$?\w+|\S+~', $_var_ref, $match);
+                        
+            $_indexes = $match[0];
+            $_var_name = array_shift($_indexes);
+
+            /* Handle $smarty.* variable references as a special case. */
+            if ($_var_name == 'smarty') {
+                /*
+                 * If the reference could be compiled, use the compiled output;
+                 * otherwise, fall back on the $smarty variable generated at
+                 * run-time.
+                 */
+                if (($smarty_ref = $this->_compile_smarty_ref($_indexes)) !== null) {
+                    $_output = $smarty_ref;
+                } else {
+                    $_var_name = substr(array_shift($_indexes), 1);
+                    $_output = "\$this->_smarty_vars['$_var_name']";
+                }
+            } elseif(is_numeric($_var_name) && is_numeric(substr($var_expr, 0, 1))) {
+                // because . is the operator for accessing arrays thru inidizes we need to put it together again for floating point numbers
+                if(count($_indexes) > 0)
+                {
+                    $_var_name .= implode("", $_indexes);
+                    $_indexes = array();
+                }
+                $_output = $_var_name;
+            } else {
+                $_output = "\$this->_tpl_vars['$_var_name']";
+            }
+
+            foreach ($_indexes as $_index) {
+                if (substr($_index, 0, 1) == '[') {
+                    $_index = substr($_index, 1, -1);
+                    if (is_numeric($_index)) {
+                        $_output .= "[$_index]";
+                    } elseif (substr($_index, 0, 1) == '$') {
+                        if (strpos($_index, '.') !== false) {
+                            $_output .= '[' . $this->_parse_var($_index) . ']';
+                        } else {
+                            $_output .= "[\$this->_tpl_vars['" . substr($_index, 1) . "']]";
+                        }
+                    } else {
+                        $_var_parts = explode('.', $_index);
+                        $_var_section = $_var_parts[0];
+                        $_var_section_prop = isset($_var_parts[1]) ? $_var_parts[1] : 'index';
+                        $_output .= "[\$this->_sections['$_var_section']['$_var_section_prop']]";
+                    }
+                } else if (substr($_index, 0, 1) == '.') {
+                    if (substr($_index, 1, 1) == '$')
+                        $_output .= "[\$this->_tpl_vars['" . substr($_index, 2) . "']]";
+                    else
+                        $_output .= "['" . substr($_index, 1) . "']";
+                } else if (substr($_index,0,2) == '->') {
+                    if(substr($_index,2,2) == '__') {
+                        $this->_syntax_error('call to internal object members is not allowed', E_USER_ERROR, __FILE__, __LINE__);
+                    } elseif($this->security && substr($_index, 2, 1) == '_') {
+                        $this->_syntax_error('(secure) call to private object member is not allowed', E_USER_ERROR, __FILE__, __LINE__);
+                    } elseif (substr($_index, 2, 1) == '$') {
+                        if ($this->security) {
+                            $this->_syntax_error('(secure) call to dynamic object member is not allowed', E_USER_ERROR, __FILE__, __LINE__);
+                        } else {
+                            $_output .= '->{(($_var=$this->_tpl_vars[\''.substr($_index,3).'\']) && substr($_var,0,2)!=\'__\') ? $_var : $this->trigger_error("cannot access property \\"$_var\\"")}';
+                        }
+                    } else {
+                        $_output .= $_index;
+                    }
+                } elseif (substr($_index, 0, 1) == '(') {
+                    $_index = $this->_parse_parenth_args($_index);
+                    $_output .= $_index;
+                } else {
+                    $_output .= $_index;
+                }
+            }
+        }
+
+        return $_output;
+    }
+
+    /**
+     * parse arguments in function call parenthesis
+     *
+     * @param string $parenth_args
+     * @return string
+     */
+    function _parse_parenth_args($parenth_args)
+    {
+        preg_match_all('~' . $this->_param_regexp . '~',$parenth_args, $match);
+        $orig_vals = $match = $match[0];
+        $this->_parse_vars_props($match);
+        $replace = array();
+        for ($i = 0, $count = count($match); $i < $count; $i++) {
+            $replace[$orig_vals[$i]] = $match[$i];
+        }
+        return strtr($parenth_args, $replace);
+    }
+
+    /**
+     * parse configuration variable expression into PHP code
+     *
+     * @param string $conf_var_expr
+     */
+    function _parse_conf_var($conf_var_expr)
+    {
+        $parts = explode('|', $conf_var_expr, 2);
+        $var_ref = $parts[0];
+        $modifiers = isset($parts[1]) ? $parts[1] : '';
+
+        $var_name = substr($var_ref, 1, -1);
+
+        $output = "\$this->_config[0]['vars']['$var_name']";
+
+        $this->_parse_modifiers($output, $modifiers);
+
+        return $output;
+    }
+
+    /**
+     * parse section property expression into PHP code
+     *
+     * @param string $section_prop_expr
+     * @return string
+     */
+    function _parse_section_prop($section_prop_expr)
+    {
+        $parts = explode('|', $section_prop_expr, 2);
+        $var_ref = $parts[0];
+        $modifiers = isset($parts[1]) ? $parts[1] : '';
+
+        preg_match('!%(\w+)\.(\w+)%!', $var_ref, $match);
+        $section_name = $match[1];
+        $prop_name = $match[2];
+
+        $output = "\$this->_sections['$section_name']['$prop_name']";
+
+        $this->_parse_modifiers($output, $modifiers);
+
+        return $output;
+    }
+
+
+    /**
+     * parse modifier chain into PHP code
+     *
+     * sets $output to parsed modified chain
+     * @param string $output
+     * @param string $modifier_string
+     */
+    function _parse_modifiers(&$output, $modifier_string)
+    {
+        preg_match_all('~\|(@?\w+)((?>:(?:'. $this->_qstr_regexp . '|[^|]+))*)~', '|' . $modifier_string, $_match);
+        list(, $_modifiers, $modifier_arg_strings) = $_match;
+
+        for ($_i = 0, $_for_max = count($_modifiers); $_i < $_for_max; $_i++) {
+            $_modifier_name = $_modifiers[$_i];
+
+            if($_modifier_name == 'smarty') {
+                // skip smarty modifier
+                continue;
+            }
+
+            preg_match_all('~:(' . $this->_qstr_regexp . '|[^:]+)~', $modifier_arg_strings[$_i], $_match);
+            $_modifier_args = $_match[1];
+
+            if (substr($_modifier_name, 0, 1) == '@') {
+                $_map_array = false;
+                $_modifier_name = substr($_modifier_name, 1);
+            } else {
+                $_map_array = true;
+            }
+
+            if (empty($this->_plugins['modifier'][$_modifier_name])
+                && !$this->_get_plugin_filepath('modifier', $_modifier_name)
+                && function_exists($_modifier_name)) {
+                if ($this->security && !in_array($_modifier_name, $this->security_settings['MODIFIER_FUNCS'])) {
+                    $this->_trigger_fatal_error("[plugin] (secure mode) modifier '$_modifier_name' is not allowed" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
+                } else {
+                    $this->_plugins['modifier'][$_modifier_name] = array($_modifier_name,  null, null, false);
+                }
+            }
+            $this->_add_plugin('modifier', $_modifier_name);
+
+            $this->_parse_vars_props($_modifier_args);
+
+            if($_modifier_name == 'default') {
+                // supress notifications of default modifier vars and args
+                if(substr($output, 0, 1) == '$') {
+                    $output = '@' . $output;
+                }
+                if(isset($_modifier_args[0]) && substr($_modifier_args[0], 0, 1) == '$') {
+                    $_modifier_args[0] = '@' . $_modifier_args[0];
+                }
+            }
+            if (count($_modifier_args) > 0)
+                $_modifier_args = ', '.implode(', ', $_modifier_args);
+            else
+                $_modifier_args = '';
+
+            if ($_map_array) {
+                $output = "((is_array(\$_tmp=$output)) ? \$this->_run_mod_handler('$_modifier_name', true, \$_tmp$_modifier_args) : " . $this->_compile_plugin_call('modifier', $_modifier_name) . "(\$_tmp$_modifier_args))";
+
+            } else {
+
+                $output = $this->_compile_plugin_call('modifier', $_modifier_name)."($output$_modifier_args)";
+
+            }
+        }
+    }
+
+
+    /**
+     * add plugin
+     *
+     * @param string $type
+     * @param string $name
+     * @param boolean? $delayed_loading
+     */
+    function _add_plugin($type, $name, $delayed_loading = null)
+    {
+        if (!isset($this->_plugin_info[$type])) {
+            $this->_plugin_info[$type] = array();
+        }
+        if (!isset($this->_plugin_info[$type][$name])) {
+            $this->_plugin_info[$type][$name] = array($this->_current_file,
+                                                      $this->_current_line_no,
+                                                      $delayed_loading);
+        }
+    }
+
+
+    /**
+     * Compiles references of type $smarty.foo
+     *
+     * @param string $indexes
+     * @return string
+     */
+    function _compile_smarty_ref(&$indexes)
+    {
+        /* Extract the reference name. */
+        $_ref = substr($indexes[0], 1);
+        foreach($indexes as $_index_no=>$_index) {
+            if (substr($_index, 0, 1) != '.' && $_index_no<2 || !preg_match('~^(\.|\[|->)~', $_index)) {
+                $this->_syntax_error('$smarty' . implode('', array_slice($indexes, 0, 2)) . ' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__);
+            }
+        }
+
+        switch ($_ref) {
+            case 'now':
+                $compiled_ref = 'time()';
+                $_max_index = 1;
+                break;
+
+            case 'foreach':
+                array_shift($indexes);
+                $_var = $this->_parse_var_props(substr($indexes[0], 1));
+                $_propname = substr($indexes[1], 1);
+                $_max_index = 1;
+                switch ($_propname) {
+                    case 'index':
+                        array_shift($indexes);
+                        $compiled_ref = "(\$this->_foreach[$_var]['iteration']-1)";
+                        break;
+                        
+                    case 'first':
+                        array_shift($indexes);
+                        $compiled_ref = "(\$this->_foreach[$_var]['iteration'] <= 1)";
+                        break;
+
+                    case 'last':
+                        array_shift($indexes);
+                        $compiled_ref = "(\$this->_foreach[$_var]['iteration'] == \$this->_foreach[$_var]['total'])";
+                        break;
+                        
+                    case 'show':
+                        array_shift($indexes);
+                        $compiled_ref = "(\$this->_foreach[$_var]['total'] > 0)";
+                        break;
+                        
+                    default:
+                        unset($_max_index);
+                        $compiled_ref = "\$this->_foreach[$_var]";
+                }
+                break;
+
+            case 'section':
+                array_shift($indexes);
+                $_var = $this->_parse_var_props(substr($indexes[0], 1));
+                $compiled_ref = "\$this->_sections[$_var]";
+                break;
+
+            case 'get':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_GET' : "\$GLOBALS['HTTP_GET_VARS']";
+                break;
+
+            case 'post':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_POST' : "\$GLOBALS['HTTP_POST_VARS']";
+                break;
+
+            case 'cookies':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_COOKIE' : "\$GLOBALS['HTTP_COOKIE_VARS']";
+                break;
+
+            case 'env':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_ENV' : "\$GLOBALS['HTTP_ENV_VARS']";
+                break;
+
+            case 'server':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_SERVER' : "\$GLOBALS['HTTP_SERVER_VARS']";
+                break;
+
+            case 'session':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_SESSION' : "\$GLOBALS['HTTP_SESSION_VARS']";
+                break;
+
+            /*
+             * These cases are handled either at run-time or elsewhere in the
+             * compiler.
+             */
+            case 'request':
+                if ($this->request_use_auto_globals) {
+                    $compiled_ref = '$_REQUEST';
+                    break;
+                } else {
+                    $this->_init_smarty_vars = true;
+                }
+                return null;
+
+            case 'capture':
+                return null;
+
+            case 'template':
+                $compiled_ref = "'$this->_current_file'";
+                $_max_index = 1;
+                break;
+
+            case 'version':
+                $compiled_ref = "'$this->_version'";
+                $_max_index = 1;
+                break;
+
+            case 'const':
+                if ($this->security && !$this->security_settings['ALLOW_CONSTANTS']) {
+                    $this->_syntax_error("(secure mode) constants not permitted",
+                                         E_USER_WARNING, __FILE__, __LINE__);
+                    return;
+                }
+                array_shift($indexes);
+                if (preg_match('!^\.\w+$!', $indexes[0])) {
+                    $compiled_ref = '@' . substr($indexes[0], 1);
+                } else {
+                    $_val = $this->_parse_var_props(substr($indexes[0], 1));
+                    $compiled_ref = '@constant(' . $_val . ')';
+                }
+                $_max_index = 1;
+                break;
+
+            case 'config':
+                $compiled_ref = "\$this->_config[0]['vars']";
+                $_max_index = 3;
+                break;
+
+            case 'ldelim':
+                $compiled_ref = "'$this->left_delimiter'";
+                break;
+
+            case 'rdelim':
+                $compiled_ref = "'$this->right_delimiter'";
+                break;
+                
+            default:
+                $this->_syntax_error('$smarty.' . $_ref . ' is an unknown reference', E_USER_ERROR, __FILE__, __LINE__);
+                break;
+        }
+
+        if (isset($_max_index) && count($indexes) > $_max_index) {
+            $this->_syntax_error('$smarty' . implode('', $indexes) .' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        array_shift($indexes);
+        return $compiled_ref;
+    }
+
+    /**
+     * compiles call to plugin of type $type with name $name
+     * returns a string containing the function-name or method call
+     * without the paramter-list that would have follow to make the
+     * call valid php-syntax
+     *
+     * @param string $type
+     * @param string $name
+     * @return string
+     */
+    function _compile_plugin_call($type, $name) {
+        if (isset($this->_plugins[$type][$name])) {
+            /* plugin loaded */
+            if (is_array($this->_plugins[$type][$name][0])) {
+                return ((is_object($this->_plugins[$type][$name][0][0])) ?
+                        "\$this->_plugins['$type']['$name'][0][0]->"    /* method callback */
+                        : (string)($this->_plugins[$type][$name][0][0]).'::'    /* class callback */
+                       ). $this->_plugins[$type][$name][0][1];
+
+            } else {
+                /* function callback */
+                return $this->_plugins[$type][$name][0];
+
+            }
+        } else {
+            /* plugin not loaded -> auto-loadable-plugin */
+            return 'smarty_'.$type.'_'.$name;
+
+        }
+    }
+
+    /**
+     * load pre- and post-filters
+     */
+    function _load_filters()
+    {
+        if (count($this->_plugins['prefilter']) > 0) {
+            foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) {
+                if ($prefilter === false) {
+                    unset($this->_plugins['prefilter'][$filter_name]);
+                    $_params = array('plugins' => array(array('prefilter', $filter_name, null, null, false)));
+                    require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
+                    smarty_core_load_plugins($_params, $this);
+                }
+            }
+        }
+        if (count($this->_plugins['postfilter']) > 0) {
+            foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) {
+                if ($postfilter === false) {
+                    unset($this->_plugins['postfilter'][$filter_name]);
+                    $_params = array('plugins' => array(array('postfilter', $filter_name, null, null, false)));
+                    require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
+                    smarty_core_load_plugins($_params, $this);
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Quote subpattern references
+     *
+     * @param string $string
+     * @return string
+     */
+    function _quote_replace($string)
+    {
+        return strtr($string, array('\\' => '\\\\', '$' => '\\$'));
+    }
+
+    /**
+     * display Smarty syntax error
+     *
+     * @param string $error_msg
+     * @param integer $error_type
+     * @param string $file
+     * @param integer $line
+     */
+    function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=null, $line=null)
+    {
+        $this->_trigger_fatal_error("syntax error: $error_msg", $this->_current_file, $this->_current_line_no, $file, $line, $error_type);
+    }
+
+
+    /**
+     * check if the compilation changes from cacheable to
+     * non-cacheable state with the beginning of the current
+     * plugin. return php-code to reflect the transition.
+     * @return string
+     */
+    function _push_cacheable_state($type, $name) {
+        $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4];
+        if ($_cacheable
+            || 0<$this->_cacheable_state++) return '';
+        if (!isset($this->_cache_serial)) $this->_cache_serial = md5(uniqid('Smarty'));
+        $_ret = 'if ($this->caching && !$this->_cache_including): echo \'{nocache:'
+            . $this->_cache_serial . '#' . $this->_nocache_count
+            . '}\'; endif;';
+        return $_ret;
+    }
+
+
+    /**
+     * check if the compilation changes from non-cacheable to
+     * cacheable state with the end of the current plugin return
+     * php-code to reflect the transition.
+     * @return string
+     */
+    function _pop_cacheable_state($type, $name) {
+        $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4];
+        if ($_cacheable
+            || --$this->_cacheable_state>0) return '';
+        return 'if ($this->caching && !$this->_cache_including): echo \'{/nocache:'
+            . $this->_cache_serial . '#' . ($this->_nocache_count++)
+            . '}\'; endif;';
+    }
+
+
+    /**
+     * push opening tag-name, file-name and line-number on the tag-stack
+     * @param string the opening tag's name
+     */
+    function _push_tag($open_tag)
+    {
+        array_push($this->_tag_stack, array($open_tag, $this->_current_line_no));
+    }
+
+    /**
+     * pop closing tag-name
+     * raise an error if this stack-top doesn't match with the closing tag
+     * @param string the closing tag's name
+     * @return string the opening tag's name
+     */
+    function _pop_tag($close_tag)
+    {
+        $message = '';
+        if (count($this->_tag_stack)>0) {
+            list($_open_tag, $_line_no) = array_pop($this->_tag_stack);
+            if ($close_tag == $_open_tag) {
+                return $_open_tag;
+            }
+            if ($close_tag == 'if' && ($_open_tag == 'else' || $_open_tag == 'elseif' )) {
+                return $this->_pop_tag($close_tag);
+            }
+            if ($close_tag == 'section' && $_open_tag == 'sectionelse') {
+                $this->_pop_tag($close_tag);
+                return $_open_tag;
+            }
+            if ($close_tag == 'foreach' && $_open_tag == 'foreachelse') {
+                $this->_pop_tag($close_tag);
+                return $_open_tag;
+            }
+            if ($_open_tag == 'else' || $_open_tag == 'elseif') {
+                $_open_tag = 'if';
+            } elseif ($_open_tag == 'sectionelse') {
+                $_open_tag = 'section';
+            } elseif ($_open_tag == 'foreachelse') {
+                $_open_tag = 'foreach';
+            }
+            $message = " expected {/$_open_tag} (opened line $_line_no).";
+        }
+        $this->_syntax_error("mismatched tag {/$close_tag}.$message",
+                             E_USER_ERROR, __FILE__, __LINE__);
+    }
+
+}
+
+/**
+ * compare to values by their string length
+ *
+ * @access private
+ * @param string $a
+ * @param string $b
+ * @return 0|-1|1
+ */
+function _smarty_sort_length($a, $b)
+{
+    if($a == $b)
+        return 0;
+
+    if(strlen($a) == strlen($b))
+        return ($a > $b) ? -1 : 1;
+
+    return (strlen($a) > strlen($b)) ? -1 : 1;
+}
+
+
+/* vim: set et: */
+
+?>
diff --git a/inc/smarty/debug.tpl b/inc/smarty/debug.tpl
new file mode 100644 (file)
index 0000000..c05ef5d
--- /dev/null
@@ -0,0 +1,157 @@
+{* Smarty *}
+{* debug.tpl, last updated version 2.1.0 *}
+{assign_debug_info}
+{capture assign=debug_output}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+    <title>Smarty Debug Console</title>
+{literal}
+<style type="text/css">
+/* <![CDATA[ */
+body, h1, h2, td, th, p {
+    font-family: sans-serif;
+    font-weight: normal;
+    font-size: 0.9em;
+    margin: 1px;
+    padding: 0;
+}
+
+h1 {
+    margin: 0;
+    text-align: left;
+    padding: 2px;
+    background-color: #f0c040;
+    color:  black;
+    font-weight: bold;
+    font-size: 1.2em;
+ }
+
+h2 {
+    background-color: #9B410E;
+    color: white;
+    text-align: left;
+    font-weight: bold;
+    padding: 2px;
+    border-top: 1px solid black;
+}
+
+body {
+    background: black; 
+}
+
+p, table, div {
+    background: #f0ead8;
+} 
+
+p {
+    margin: 0;
+    font-style: italic;
+    text-align: center;
+}
+
+table {
+    width: 100%;
+}
+
+th, td {
+    font-family: monospace;
+    vertical-align: top;
+    text-align: left;
+    width: 50%;
+}
+
+td {
+    color: green;
+}
+
+.odd {
+    background-color: #eeeeee;
+}
+
+.even {
+    background-color: #fafafa;
+}
+
+.exectime {
+    font-size: 0.8em;
+    font-style: italic;
+}
+
+#table_assigned_vars th {
+    color: blue;
+}
+
+#table_config_vars th {
+    color: maroon;
+}
+/* ]]> */
+</style>
+{/literal}
+</head>
+<body>
+
+<h1>Smarty Debug Console</h1>
+
+<h2>included templates &amp; config files (load time in seconds)</h2>
+
+<div>
+{section name=templates loop=$_debug_tpls}
+    {section name=indent loop=$_debug_tpls[templates].depth}&nbsp;&nbsp;&nbsp;{/section}
+    <font color={if $_debug_tpls[templates].type eq "template"}brown{elseif $_debug_tpls[templates].type eq "insert"}black{else}green{/if}>
+        {$_debug_tpls[templates].filename|escape:html}</font>
+    {if isset($_debug_tpls[templates].exec_time)}
+        <span class="exectime">
+        ({$_debug_tpls[templates].exec_time|string_format:"%.5f"})
+        {if %templates.index% eq 0}(total){/if}
+        </span>
+    {/if}
+    <br />
+{sectionelse}
+    <p>no templates included</p>
+{/section}
+</div>
+
+<h2>assigned template variables</h2>
+
+<table id="table_assigned_vars">
+    {section name=vars loop=$_debug_keys}
+        <tr class="{cycle values="odd,even"}">
+            <th>{ldelim}${$_debug_keys[vars]|escape:'html'}{rdelim}</th>
+            <td>{$_debug_vals[vars]|@debug_print_var}</td></tr>
+    {sectionelse}
+        <tr><td><p>no template variables assigned</p></td></tr>
+    {/section}
+</table>
+
+<h2>assigned config file variables (outer template scope)</h2>
+
+<table id="table_config_vars">
+    {section name=config_vars loop=$_debug_config_keys}
+        <tr class="{cycle values="odd,even"}">
+            <th>{ldelim}#{$_debug_config_keys[config_vars]|escape:'html'}#{rdelim}</th>
+            <td>{$_debug_config_vals[config_vars]|@debug_print_var}</td></tr>
+    {sectionelse}
+        <tr><td><p>no config vars assigned</p></td></tr>
+    {/section}
+</table>
+</body>
+</html>
+{/capture}
+{if isset($_smarty_debug_output) and $_smarty_debug_output eq "html"}
+    {$debug_output}
+{else}
+<script type="text/javascript">
+// <![CDATA[
+    if ( self.name == '' ) {ldelim}
+       var title = 'Console';
+    {rdelim}
+    else {ldelim}
+       var title = 'Console_' + self.name;
+    {rdelim}
+    _smarty_console = window.open("",title.value,"width=680,height=600,resizable,scrollbars=yes");
+    _smarty_console.document.write('{$debug_output|escape:'javascript'}');
+    _smarty_console.document.close();
+// ]]>
+</script>
+{/if}
\ No newline at end of file
diff --git a/inc/smarty/internals/core.assemble_plugin_filepath.php b/inc/smarty/internals/core.assemble_plugin_filepath.php
new file mode 100644 (file)
index 0000000..690d3dd
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * assemble filepath of requested plugin
+ *
+ * @param string $type
+ * @param string $name
+ * @return string|false
+ */
+function smarty_core_assemble_plugin_filepath($params, &$smarty)
+{
+    static $_filepaths_cache = array();
+
+    $_plugin_filename = $params['type'] . '.' . $params['name'] . '.php';
+    if (isset($_filepaths_cache[$_plugin_filename])) {
+        return $_filepaths_cache[$_plugin_filename];
+    }
+    $_return = false;
+
+    foreach ((array)$smarty->plugins_dir as $_plugin_dir) {
+
+        $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename;
+
+        // see if path is relative
+        if (!preg_match("/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/", $_plugin_dir)) {
+            $_relative_paths[] = $_plugin_dir;
+            // relative path, see if it is in the SMARTY_DIR
+            if (@is_readable(SMARTY_DIR . $_plugin_filepath)) {
+                $_return = SMARTY_DIR . $_plugin_filepath;
+                break;
+            }
+        }
+        // try relative to cwd (or absolute)
+        if (@is_readable($_plugin_filepath)) {
+            $_return = $_plugin_filepath;
+            break;
+        }
+    }
+
+    if($_return === false) {
+        // still not found, try PHP include_path
+        if(isset($_relative_paths)) {
+            foreach ((array)$_relative_paths as $_plugin_dir) {
+
+                $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename;
+
+                $_params = array('file_path' => $_plugin_filepath);
+                require_once(SMARTY_CORE_DIR . 'core.get_include_path.php');
+                if(smarty_core_get_include_path($_params, $smarty)) {
+                    $_return = $_params['new_file_path'];
+                    break;
+                }
+            }
+        }
+    }
+    $_filepaths_cache[$_plugin_filename] = $_return;
+    return $_return;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.assign_smarty_interface.php b/inc/smarty/internals/core.assign_smarty_interface.php
new file mode 100644 (file)
index 0000000..7e65a73
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty assign_smarty_interface core plugin
+ *
+ * Type:     core<br>
+ * Name:     assign_smarty_interface<br>
+ * Purpose:  assign the $smarty interface variable
+ * @param array Format: null
+ * @param Smarty
+ */
+function smarty_core_assign_smarty_interface($params, &$smarty)
+{
+        if (isset($smarty->_smarty_vars) && isset($smarty->_smarty_vars['request'])) {
+            return;
+        }
+
+        $_globals_map = array('g'  => 'HTTP_GET_VARS',
+                             'p'  => 'HTTP_POST_VARS',
+                             'c'  => 'HTTP_COOKIE_VARS',
+                             's'  => 'HTTP_SERVER_VARS',
+                             'e'  => 'HTTP_ENV_VARS');
+
+        $_smarty_vars_request  = array();
+
+        foreach (preg_split('!!', strtolower($smarty->request_vars_order)) as $_c) {
+            if (isset($_globals_map[$_c])) {
+                $_smarty_vars_request = array_merge($_smarty_vars_request, $GLOBALS[$_globals_map[$_c]]);
+            }
+        }
+        $_smarty_vars_request = @array_merge($_smarty_vars_request, $GLOBALS['HTTP_SESSION_VARS']);
+
+        $smarty->_smarty_vars['request'] = $_smarty_vars_request;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.create_dir_structure.php b/inc/smarty/internals/core.create_dir_structure.php
new file mode 100644 (file)
index 0000000..3eecc49
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * create full directory structure
+ *
+ * @param string $dir
+ */
+
+// $dir
+
+function smarty_core_create_dir_structure($params, &$smarty)
+{
+    if (!file_exists($params['dir'])) {
+        $_open_basedir_ini = ini_get('open_basedir');
+
+        if (DIRECTORY_SEPARATOR=='/') {
+            /* unix-style paths */
+            $_dir = $params['dir'];
+            $_dir_parts = preg_split('!/+!', $_dir, -1, PREG_SPLIT_NO_EMPTY);
+            $_new_dir = (substr($_dir, 0, 1)=='/') ? '/' : getcwd().'/';
+            if($_use_open_basedir = !empty($_open_basedir_ini)) {
+                $_open_basedirs = explode(':', $_open_basedir_ini);
+            }
+
+        } else {
+            /* other-style paths */
+            $_dir = str_replace('\\','/', $params['dir']);
+            $_dir_parts = preg_split('!/+!', $_dir, -1, PREG_SPLIT_NO_EMPTY);
+            if (preg_match('!^((//)|([a-zA-Z]:/))!', $_dir, $_root_dir)) {
+                /* leading "//" for network volume, or "[letter]:/" for full path */
+                $_new_dir = $_root_dir[1];
+                /* remove drive-letter from _dir_parts */
+                if (isset($_root_dir[3])) array_shift($_dir_parts);
+
+            } else {
+                $_new_dir = str_replace('\\', '/', getcwd()).'/';
+
+            }
+
+            if($_use_open_basedir = !empty($_open_basedir_ini)) {
+                $_open_basedirs = explode(';', str_replace('\\', '/', $_open_basedir_ini));
+            }
+
+        }
+
+        /* all paths use "/" only from here */
+        foreach ($_dir_parts as $_dir_part) {
+            $_new_dir .= $_dir_part;
+
+            if ($_use_open_basedir) {
+                // do not attempt to test or make directories outside of open_basedir
+                $_make_new_dir = false;
+                foreach ($_open_basedirs as $_open_basedir) {
+                    if (substr($_new_dir, 0, strlen($_open_basedir)) == $_open_basedir) {
+                        $_make_new_dir = true;
+                        break;
+                    }
+                }
+            } else {
+                $_make_new_dir = true;
+            }
+
+            if ($_make_new_dir && !file_exists($_new_dir) && !@mkdir($_new_dir, $smarty->_dir_perms) && !is_dir($_new_dir)) {
+                $smarty->trigger_error("problem creating directory '" . $_new_dir . "'");
+                return false;
+            }
+            $_new_dir .= '/';
+        }
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.display_debug_console.php b/inc/smarty/internals/core.display_debug_console.php
new file mode 100644 (file)
index 0000000..1a80f39
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty debug_console function plugin
+ *
+ * Type:     core<br>
+ * Name:     display_debug_console<br>
+ * Purpose:  display the javascript debug console window
+ * @param array Format: null
+ * @param Smarty
+ */
+function smarty_core_display_debug_console($params, &$smarty)
+{
+    // we must force compile the debug template in case the environment
+    // changed between separate applications.
+
+    if(empty($smarty->debug_tpl)) {
+        // set path to debug template from SMARTY_DIR
+        $smarty->debug_tpl = SMARTY_DIR . 'debug.tpl';
+        if($smarty->security && is_file($smarty->debug_tpl)) {
+            $smarty->secure_dir[] = realpath($smarty->debug_tpl);
+        }
+        $smarty->debug_tpl = 'file:' . SMARTY_DIR . 'debug.tpl';
+    }
+
+    $_ldelim_orig = $smarty->left_delimiter;
+    $_rdelim_orig = $smarty->right_delimiter;
+
+    $smarty->left_delimiter = '{';
+    $smarty->right_delimiter = '}';
+
+    $_compile_id_orig = $smarty->_compile_id;
+    $smarty->_compile_id = null;
+
+    $_compile_path = $smarty->_get_compile_path($smarty->debug_tpl);
+    if ($smarty->_compile_resource($smarty->debug_tpl, $_compile_path))
+    {
+        ob_start();
+        $smarty->_include($_compile_path);
+        $_results = ob_get_contents();
+        ob_end_clean();
+    } else {
+        $_results = '';
+    }
+
+    $smarty->_compile_id = $_compile_id_orig;
+
+    $smarty->left_delimiter = $_ldelim_orig;
+    $smarty->right_delimiter = $_rdelim_orig;
+
+    return $_results;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.get_include_path.php b/inc/smarty/internals/core.get_include_path.php
new file mode 100644 (file)
index 0000000..4343241
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Get path to file from include_path
+ *
+ * @param string $file_path
+ * @param string $new_file_path
+ * @return boolean
+ * @staticvar array|null
+ */
+
+//  $file_path, &$new_file_path
+
+function smarty_core_get_include_path(&$params, &$smarty)
+{
+    static $_path_array = null;
+
+    if(!isset($_path_array)) {
+        $_ini_include_path = ini_get('include_path');
+
+        if(strstr($_ini_include_path,';')) {
+            // windows pathnames
+            $_path_array = explode(';',$_ini_include_path);
+        } else {
+            $_path_array = explode(':',$_ini_include_path);
+        }
+    }
+    foreach ($_path_array as $_include_path) {
+        if (@is_readable($_include_path . DIRECTORY_SEPARATOR . $params['file_path'])) {
+               $params['new_file_path'] = $_include_path . DIRECTORY_SEPARATOR . $params['file_path'];
+            return true;
+        }
+    }
+    return false;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.get_microtime.php b/inc/smarty/internals/core.get_microtime.php
new file mode 100644 (file)
index 0000000..f1a28e0
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Get seconds and microseconds
+ * @return double
+ */
+function smarty_core_get_microtime($params, &$smarty)
+{
+    $mtime = microtime();
+    $mtime = explode(" ", $mtime);
+    $mtime = (double)($mtime[1]) + (double)($mtime[0]);
+    return ($mtime);
+}
+
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.get_php_resource.php b/inc/smarty/internals/core.get_php_resource.php
new file mode 100644 (file)
index 0000000..786d4e7
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Retrieves PHP script resource
+ *
+ * sets $php_resource to the returned resource
+ * @param string $resource
+ * @param string $resource_type
+ * @param  $php_resource
+ * @return boolean
+ */
+
+function smarty_core_get_php_resource(&$params, &$smarty)
+{
+
+    $params['resource_base_path'] = $smarty->trusted_dir;
+    $smarty->_parse_resource_name($params, $smarty);
+
+    /*
+     * Find out if the resource exists.
+     */
+
+    if ($params['resource_type'] == 'file') {
+        $_readable = false;
+        if(file_exists($params['resource_name']) && is_readable($params['resource_name'])) {
+            $_readable = true;
+        } else {
+            // test for file in include_path
+            $_params = array('file_path' => $params['resource_name']);
+            require_once(SMARTY_CORE_DIR . 'core.get_include_path.php');
+            if(smarty_core_get_include_path($_params, $smarty)) {
+                $_include_path = $_params['new_file_path'];
+                $_readable = true;
+            }
+        }
+    } else if ($params['resource_type'] != 'file') {
+        $_template_source = null;
+        $_readable = is_callable($smarty->_plugins['resource'][$params['resource_type']][0][0])
+            && call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][0],
+                                    array($params['resource_name'], &$_template_source, &$smarty));
+    }
+
+    /*
+     * Set the error function, depending on which class calls us.
+     */
+    if (method_exists($smarty, '_syntax_error')) {
+        $_error_funcc = '_syntax_error';
+    } else {
+        $_error_funcc = 'trigger_error';
+    }
+
+    if ($_readable) {
+        if ($smarty->security) {
+            require_once(SMARTY_CORE_DIR . 'core.is_trusted.php');
+            if (!smarty_core_is_trusted($params, $smarty)) {
+                $smarty->$_error_funcc('(secure mode) ' . $params['resource_type'] . ':' . $params['resource_name'] . ' is not trusted');
+                return false;
+            }
+        }
+    } else {
+        $smarty->$_error_funcc($params['resource_type'] . ':' . $params['resource_name'] . ' is not readable');
+        return false;
+    }
+
+    if ($params['resource_type'] == 'file') {
+        $params['php_resource'] = $params['resource_name'];
+    } else {
+        $params['php_resource'] = $_template_source;
+    }
+    return true;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.is_secure.php b/inc/smarty/internals/core.is_secure.php
new file mode 100644 (file)
index 0000000..d54abd4
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * determines if a resource is secure or not.
+ *
+ * @param string $resource_type
+ * @param string $resource_name
+ * @return boolean
+ */
+
+//  $resource_type, $resource_name
+
+function smarty_core_is_secure($params, &$smarty)
+{
+    if (!$smarty->security || $smarty->security_settings['INCLUDE_ANY']) {
+        return true;
+    }
+
+    if ($params['resource_type'] == 'file') {
+        $_rp = realpath($params['resource_name']);
+        if (isset($params['resource_base_path'])) {
+            foreach ((array)$params['resource_base_path'] as $curr_dir) {
+                if ( ($_cd = realpath($curr_dir)) !== false &&
+                     strncmp($_rp, $_cd, strlen($_cd)) == 0 &&
+                     substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR ) {
+                    return true;
+                }
+            }
+        }
+        if (!empty($smarty->secure_dir)) {
+            foreach ((array)$smarty->secure_dir as $curr_dir) {
+                if ( ($_cd = realpath($curr_dir)) !== false) {
+                    if($_cd == $_rp) {
+                        return true;
+                    } elseif (strncmp($_rp, $_cd, strlen($_cd)) == 0 &&
+                        substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR) {
+                        return true;
+                    }
+                }
+            }
+        }
+    } else {
+        // resource is not on local file system
+        return call_user_func_array(
+            $smarty->_plugins['resource'][$params['resource_type']][0][2],
+            array($params['resource_name'], &$smarty));
+    }
+
+    return false;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.is_trusted.php b/inc/smarty/internals/core.is_trusted.php
new file mode 100644 (file)
index 0000000..4299731
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * determines if a resource is trusted or not
+ *
+ * @param string $resource_type
+ * @param string $resource_name
+ * @return boolean
+ */
+
+ // $resource_type, $resource_name
+
+function smarty_core_is_trusted($params, &$smarty)
+{
+    $_smarty_trusted = false;
+    if ($params['resource_type'] == 'file') {
+        if (!empty($smarty->trusted_dir)) {
+            $_rp = realpath($params['resource_name']);
+            foreach ((array)$smarty->trusted_dir as $curr_dir) {
+                if (!empty($curr_dir) && is_readable ($curr_dir)) {
+                    $_cd = realpath($curr_dir);
+                    if (strncmp($_rp, $_cd, strlen($_cd)) == 0
+                        && substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR ) {
+                        $_smarty_trusted = true;
+                        break;
+                    }
+                }
+            }
+        }
+
+    } else {
+        // resource is not on local file system
+        $_smarty_trusted = call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][3],
+                                                array($params['resource_name'], $smarty));
+    }
+
+    return $_smarty_trusted;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.load_plugins.php b/inc/smarty/internals/core.load_plugins.php
new file mode 100644 (file)
index 0000000..6db1dc5
--- /dev/null
@@ -0,0 +1,125 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Load requested plugins
+ *
+ * @param array $plugins
+ */
+
+// $plugins
+
+function smarty_core_load_plugins($params, &$smarty)
+{
+
+    foreach ($params['plugins'] as $_plugin_info) {
+        list($_type, $_name, $_tpl_file, $_tpl_line, $_delayed_loading) = $_plugin_info;
+        $_plugin = &$smarty->_plugins[$_type][$_name];
+
+        /*
+         * We do not load plugin more than once for each instance of Smarty.
+         * The following code checks for that. The plugin can also be
+         * registered dynamically at runtime, in which case template file
+         * and line number will be unknown, so we fill them in.
+         *
+         * The final element of the info array is a flag that indicates
+         * whether the dynamically registered plugin function has been
+         * checked for existence yet or not.
+         */
+        if (isset($_plugin)) {
+            if (empty($_plugin[3])) {
+                if (!is_callable($_plugin[0])) {
+                    $smarty->_trigger_fatal_error("[plugin] $_type '$_name' is not implemented", $_tpl_file, $_tpl_line, __FILE__, __LINE__);
+                } else {
+                    $_plugin[1] = $_tpl_file;
+                    $_plugin[2] = $_tpl_line;
+                    $_plugin[3] = true;
+                    if (!isset($_plugin[4])) $_plugin[4] = true; /* cacheable */
+                }
+            }
+            continue;
+        } else if ($_type == 'insert') {
+            /*
+             * For backwards compatibility, we check for insert functions in
+             * the symbol table before trying to load them as a plugin.
+             */
+            $_plugin_func = 'insert_' . $_name;
+            if (function_exists($_plugin_func)) {
+                $_plugin = array($_plugin_func, $_tpl_file, $_tpl_line, true, false);
+                continue;
+            }
+        }
+
+        $_plugin_file = $smarty->_get_plugin_filepath($_type, $_name);
+
+        if (! $_found = ($_plugin_file != false)) {
+            $_message = "could not load plugin file '$_type.$_name.php'\n";
+        }
+
+        /*
+         * If plugin file is found, it -must- provide the properly named
+         * plugin function. In case it doesn't, simply output the error and
+         * do not fall back on any other method.
+         */
+        if ($_found) {
+            include_once $_plugin_file;
+
+            $_plugin_func = 'smarty_' . $_type . '_' . $_name;
+            if (!function_exists($_plugin_func)) {
+                $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", $_tpl_file, $_tpl_line, __FILE__, __LINE__);
+                continue;
+            }
+        }
+        /*
+         * In case of insert plugins, their code may be loaded later via
+         * 'script' attribute.
+         */
+        else if ($_type == 'insert' && $_delayed_loading) {
+            $_plugin_func = 'smarty_' . $_type . '_' . $_name;
+            $_found = true;
+        }
+
+        /*
+         * Plugin specific processing and error checking.
+         */
+        if (!$_found) {
+            if ($_type == 'modifier') {
+                /*
+                 * In case modifier falls back on using PHP functions
+                 * directly, we only allow those specified in the security
+                 * context.
+                 */
+                if ($smarty->security && !in_array($_name, $smarty->security_settings['MODIFIER_FUNCS'])) {
+                    $_message = "(secure mode) modifier '$_name' is not allowed";
+                } else {
+                    if (!function_exists($_name)) {
+                        $_message = "modifier '$_name' is not implemented";
+                    } else {
+                        $_plugin_func = $_name;
+                        $_found = true;
+                    }
+                }
+            } else if ($_type == 'function') {
+                /*
+                 * This is a catch-all situation.
+                 */
+                $_message = "unknown tag - '$_name'";
+            }
+        }
+
+        if ($_found) {
+            $smarty->_plugins[$_type][$_name] = array($_plugin_func, $_tpl_file, $_tpl_line, true, true);
+        } else {
+            // output error
+            $smarty->_trigger_fatal_error('[plugin] ' . $_message, $_tpl_file, $_tpl_line, __FILE__, __LINE__);
+        }
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.load_resource_plugin.php b/inc/smarty/internals/core.load_resource_plugin.php
new file mode 100644 (file)
index 0000000..a7d37d1
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * load a resource plugin
+ *
+ * @param string $type
+ */
+
+// $type
+
+function smarty_core_load_resource_plugin($params, &$smarty)
+{
+    /*
+     * Resource plugins are not quite like the other ones, so they are
+     * handled differently. The first element of plugin info is the array of
+     * functions provided by the plugin, the second one indicates whether
+     * all of them exist or not.
+     */
+
+    $_plugin = &$smarty->_plugins['resource'][$params['type']];
+    if (isset($_plugin)) {
+        if (!$_plugin[1] && count($_plugin[0])) {
+            $_plugin[1] = true;
+            foreach ($_plugin[0] as $_plugin_func) {
+                if (!is_callable($_plugin_func)) {
+                    $_plugin[1] = false;
+                    break;
+                }
+            }
+        }
+
+        if (!$_plugin[1]) {
+            $smarty->_trigger_fatal_error("[plugin] resource '" . $params['type'] . "' is not implemented", null, null, __FILE__, __LINE__);
+        }
+
+        return;
+    }
+
+    $_plugin_file = $smarty->_get_plugin_filepath('resource', $params['type']);
+    $_found = ($_plugin_file != false);
+
+    if ($_found) {            /*
+         * If the plugin file is found, it -must- provide the properly named
+         * plugin functions.
+         */
+        include_once($_plugin_file);
+
+        /*
+         * Locate functions that we require the plugin to provide.
+         */
+        $_resource_ops = array('source', 'timestamp', 'secure', 'trusted');
+        $_resource_funcs = array();
+        foreach ($_resource_ops as $_op) {
+            $_plugin_func = 'smarty_resource_' . $params['type'] . '_' . $_op;
+            if (!function_exists($_plugin_func)) {
+                $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", null, null, __FILE__, __LINE__);
+                return;
+            } else {
+                $_resource_funcs[] = $_plugin_func;
+            }
+        }
+
+        $smarty->_plugins['resource'][$params['type']] = array($_resource_funcs, true);
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.process_cached_inserts.php b/inc/smarty/internals/core.process_cached_inserts.php
new file mode 100644 (file)
index 0000000..1d78edd
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Replace cached inserts with the actual results
+ *
+ * @param string $results
+ * @return string
+ */
+function smarty_core_process_cached_inserts($params, &$smarty)
+{
+    preg_match_all('!'.$smarty->_smarty_md5.'{insert_cache (.*)}'.$smarty->_smarty_md5.'!Uis',
+                   $params['results'], $match);
+    list($cached_inserts, $insert_args) = $match;
+
+    for ($i = 0, $for_max = count($cached_inserts); $i < $for_max; $i++) {
+        if ($smarty->debugging) {
+            $_params = array();
+            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+            $debug_start_time = smarty_core_get_microtime($_params, $smarty);
+        }
+
+        $args = unserialize($insert_args[$i]);
+        $name = $args['name'];
+
+        if (isset($args['script'])) {
+            $_params = array('resource_name' => $smarty->_dequote($args['script']));
+            require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php');
+            if(!smarty_core_get_php_resource($_params, $smarty)) {
+                return false;
+            }
+            $resource_type = $_params['resource_type'];
+            $php_resource = $_params['php_resource'];
+
+
+            if ($resource_type == 'file') {
+                $smarty->_include($php_resource, true);
+            } else {
+                $smarty->_eval($php_resource);
+            }
+        }
+
+        $function_name = $smarty->_plugins['insert'][$name][0];
+        if (empty($args['assign'])) {
+            $replace = $function_name($args, $smarty);
+        } else {
+            $smarty->assign($args['assign'], $function_name($args, $smarty));
+            $replace = '';
+        }
+
+        $params['results'] = substr_replace($params['results'], $replace, strpos($params['results'], $cached_inserts[$i]), strlen($cached_inserts[$i]));
+        if ($smarty->debugging) {
+            $_params = array();
+            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+            $smarty->_smarty_debug_info[] = array('type'      => 'insert',
+                                                'filename'  => 'insert_'.$name,
+                                                'depth'     => $smarty->_inclusion_depth,
+                                                'exec_time' => smarty_core_get_microtime($_params, $smarty) - $debug_start_time);
+        }
+    }
+
+    return $params['results'];
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.process_compiled_include.php b/inc/smarty/internals/core.process_compiled_include.php
new file mode 100644 (file)
index 0000000..d539423
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Replace nocache-tags by results of the corresponding non-cacheable
+ * functions and return it
+ *
+ * @param string $compiled_tpl
+ * @param string $cached_source
+ * @return string
+ */
+
+function smarty_core_process_compiled_include($params, &$smarty)
+{
+    $_cache_including = $smarty->_cache_including;
+    $smarty->_cache_including = true;
+
+    $_return = $params['results'];
+
+    foreach ($smarty->_cache_info['cache_serials'] as $_include_file_path=>$_cache_serial) {
+        $smarty->_include($_include_file_path, true);
+    }
+
+    foreach ($smarty->_cache_serials as $_include_file_path=>$_cache_serial) {
+        $_return = preg_replace_callback('!(\{nocache\:('.$_cache_serial.')#(\d+)\})!s',
+                                         array(&$smarty, '_process_compiled_include_callback'),
+                                         $_return);
+    }
+    $smarty->_cache_including = $_cache_including;
+    return $_return;
+}
+
+?>
diff --git a/inc/smarty/internals/core.read_cache_file.php b/inc/smarty/internals/core.read_cache_file.php
new file mode 100644 (file)
index 0000000..c60e113
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * read a cache file, determine if it needs to be
+ * regenerated or not
+ *
+ * @param string $tpl_file
+ * @param string $cache_id
+ * @param string $compile_id
+ * @param string $results
+ * @return boolean
+ */
+
+//  $tpl_file, $cache_id, $compile_id, &$results
+
+function smarty_core_read_cache_file(&$params, &$smarty)
+{
+    static  $content_cache = array();
+
+    if ($smarty->force_compile) {
+        // force compile enabled, always regenerate
+        return false;
+    }
+
+    if (isset($content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']])) {
+        list($params['results'], $smarty->_cache_info) = $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']];
+        return true;
+    }
+
+    if (!empty($smarty->cache_handler_func)) {
+        // use cache_handler function
+        call_user_func_array($smarty->cache_handler_func,
+                             array('read', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null));
+    } else {
+        // use local cache file
+        $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']);
+        $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id);
+        $params['results'] = $smarty->_read_file($_cache_file);
+    }
+
+    if (empty($params['results'])) {
+        // nothing to parse (error?), regenerate cache
+        return false;
+    }
+
+    $_contents = $params['results'];
+    $_info_start = strpos($_contents, "\n") + 1;
+    $_info_len = (int)substr($_contents, 0, $_info_start - 1);
+    $_cache_info = unserialize(substr($_contents, $_info_start, $_info_len));
+    $params['results'] = substr($_contents, $_info_start + $_info_len);
+
+    if ($smarty->caching == 2 && isset ($_cache_info['expires'])){
+        // caching by expiration time
+        if ($_cache_info['expires'] > -1 && (time() > $_cache_info['expires'])) {
+            // cache expired, regenerate
+            return false;
+        }
+    } else {
+        // caching by lifetime
+        if ($smarty->cache_lifetime > -1 && (time() - $_cache_info['timestamp'] > $smarty->cache_lifetime)) {
+            // cache expired, regenerate
+            return false;
+        }
+    }
+
+    if ($smarty->compile_check) {
+        $_params = array('get_source' => false, 'quiet'=>true);
+        foreach (array_keys($_cache_info['template']) as $_template_dep) {
+            $_params['resource_name'] = $_template_dep;
+            if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) {
+                // template file has changed, regenerate cache
+                return false;
+            }
+        }
+
+        if (isset($_cache_info['config'])) {
+            $_params = array('resource_base_path' => $smarty->config_dir, 'get_source' => false, 'quiet'=>true);
+            foreach (array_keys($_cache_info['config']) as $_config_dep) {
+                $_params['resource_name'] = $_config_dep;
+                if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) {
+                    // config file has changed, regenerate cache
+                    return false;
+                }
+            }
+        }
+    }
+
+    $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']] = array($params['results'], $_cache_info);
+
+    $smarty->_cache_info = $_cache_info;
+    return true;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.rm_auto.php b/inc/smarty/internals/core.rm_auto.php
new file mode 100644 (file)
index 0000000..b251f64
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * delete an automagically created file by name and id
+ *
+ * @param string $auto_base
+ * @param string $auto_source
+ * @param string $auto_id
+ * @param integer $exp_time
+ * @return boolean
+ */
+
+// $auto_base, $auto_source = null, $auto_id = null, $exp_time = null
+
+function smarty_core_rm_auto($params, &$smarty)
+{
+    if (!@is_dir($params['auto_base']))
+      return false;
+
+    if(!isset($params['auto_id']) && !isset($params['auto_source'])) {
+        $_params = array(
+            'dirname' => $params['auto_base'],
+            'level' => 0,
+            'exp_time' => $params['exp_time']
+        );
+        require_once(SMARTY_CORE_DIR . 'core.rmdir.php');
+        $_res = smarty_core_rmdir($_params, $smarty);
+    } else {
+        $_tname = $smarty->_get_auto_filename($params['auto_base'], $params['auto_source'], $params['auto_id']);
+
+        if(isset($params['auto_source'])) {
+            if (isset($params['extensions'])) {
+                $_res = false;
+                foreach ((array)$params['extensions'] as $_extension)
+                    $_res |= $smarty->_unlink($_tname.$_extension, $params['exp_time']);
+            } else {
+                $_res = $smarty->_unlink($_tname, $params['exp_time']);
+            }
+        } elseif ($smarty->use_sub_dirs) {
+            $_params = array(
+                'dirname' => $_tname,
+                'level' => 1,
+                'exp_time' => $params['exp_time']
+            );
+            require_once(SMARTY_CORE_DIR . 'core.rmdir.php');
+            $_res = smarty_core_rmdir($_params, $smarty);
+        } else {
+            // remove matching file names
+            $_handle = opendir($params['auto_base']);
+            $_res = true;
+            while (false !== ($_filename = readdir($_handle))) {
+                if($_filename == '.' || $_filename == '..') {
+                    continue;
+                } elseif (substr($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, 0, strlen($_tname)) == $_tname) {
+                    $_res &= (bool)$smarty->_unlink($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, $params['exp_time']);
+                }
+            }
+        }
+    }
+
+    return $_res;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.rmdir.php b/inc/smarty/internals/core.rmdir.php
new file mode 100644 (file)
index 0000000..2166c44
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * delete a dir recursively (level=0 -> keep root)
+ * WARNING: no tests, it will try to remove what you tell it!
+ *
+ * @param string $dirname
+ * @param integer $level
+ * @param integer $exp_time
+ * @return boolean
+ */
+
+//  $dirname, $level = 1, $exp_time = null
+
+function smarty_core_rmdir($params, &$smarty)
+{
+   if(!isset($params['level'])) { $params['level'] = 1; }
+   if(!isset($params['exp_time'])) { $params['exp_time'] = null; }
+
+   if($_handle = @opendir($params['dirname'])) {
+
+        while (false !== ($_entry = readdir($_handle))) {
+            if ($_entry != '.' && $_entry != '..') {
+                if (@is_dir($params['dirname'] . DIRECTORY_SEPARATOR . $_entry)) {
+                    $_params = array(
+                        'dirname' => $params['dirname'] . DIRECTORY_SEPARATOR . $_entry,
+                        'level' => $params['level'] + 1,
+                        'exp_time' => $params['exp_time']
+                    );
+                    smarty_core_rmdir($_params, $smarty);
+                }
+                else {
+                    $smarty->_unlink($params['dirname'] . DIRECTORY_SEPARATOR . $_entry, $params['exp_time']);
+                }
+            }
+        }
+        closedir($_handle);
+   }
+
+   if ($params['level']) {
+       return @rmdir($params['dirname']);
+   }
+   return (bool)$_handle;
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.run_insert_handler.php b/inc/smarty/internals/core.run_insert_handler.php
new file mode 100644 (file)
index 0000000..71c3845
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Handle insert tags
+ *
+ * @param array $args
+ * @return string
+ */
+function smarty_core_run_insert_handler($params, &$smarty)
+{
+
+    require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+    if ($smarty->debugging) {
+        $_params = array();
+        $_debug_start_time = smarty_core_get_microtime($_params, $smarty);
+    }
+
+    if ($smarty->caching) {
+        $_arg_string = serialize($params['args']);
+        $_name = $params['args']['name'];
+        if (!isset($smarty->_cache_info['insert_tags'][$_name])) {
+            $smarty->_cache_info['insert_tags'][$_name] = array('insert',
+                                                             $_name,
+                                                             $smarty->_plugins['insert'][$_name][1],
+                                                             $smarty->_plugins['insert'][$_name][2],
+                                                             !empty($params['args']['script']) ? true : false);
+        }
+        return $smarty->_smarty_md5."{insert_cache $_arg_string}".$smarty->_smarty_md5;
+    } else {
+        if (isset($params['args']['script'])) {
+            $_params = array('resource_name' => $smarty->_dequote($params['args']['script']));
+            require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php');
+            if(!smarty_core_get_php_resource($_params, $smarty)) {
+                return false;
+            }
+
+            if ($_params['resource_type'] == 'file') {
+                $smarty->_include($_params['php_resource'], true);
+            } else {
+                $smarty->_eval($_params['php_resource']);
+            }
+            unset($params['args']['script']);
+        }
+
+        $_funcname = $smarty->_plugins['insert'][$params['args']['name']][0];
+        $_content = $_funcname($params['args'], $smarty);
+        if ($smarty->debugging) {
+            $_params = array();
+            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+            $smarty->_smarty_debug_info[] = array('type'      => 'insert',
+                                                'filename'  => 'insert_'.$params['args']['name'],
+                                                'depth'     => $smarty->_inclusion_depth,
+                                                'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time);
+        }
+
+        if (!empty($params['args']["assign"])) {
+            $smarty->assign($params['args']["assign"], $_content);
+        } else {
+            return $_content;
+        }
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.smarty_include_php.php b/inc/smarty/internals/core.smarty_include_php.php
new file mode 100644 (file)
index 0000000..30c6e76
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * called for included php files within templates
+ *
+ * @param string $smarty_file
+ * @param string $smarty_assign variable to assign the included template's
+ *               output into
+ * @param boolean $smarty_once uses include_once if this is true
+ * @param array $smarty_include_vars associative array of vars from
+ *              {include file="blah" var=$var}
+ */
+
+//  $file, $assign, $once, $_smarty_include_vars
+
+function smarty_core_smarty_include_php($params, &$smarty)
+{
+    $_params = array('resource_name' => $params['smarty_file']);
+    require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php');
+    smarty_core_get_php_resource($_params, $smarty);
+    $_smarty_resource_type = $_params['resource_type'];
+    $_smarty_php_resource = $_params['php_resource'];
+
+    if (!empty($params['smarty_assign'])) {
+        ob_start();
+        if ($_smarty_resource_type == 'file') {
+            $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']);
+        } else {
+            $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']);
+        }
+        $smarty->assign($params['smarty_assign'], ob_get_contents());
+        ob_end_clean();
+    } else {
+        if ($_smarty_resource_type == 'file') {
+            $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']);
+        } else {
+            $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']);
+        }
+    }
+}
+
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.write_cache_file.php b/inc/smarty/internals/core.write_cache_file.php
new file mode 100644 (file)
index 0000000..72f785b
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Prepend the cache information to the cache file
+ * and write it
+ *
+ * @param string $tpl_file
+ * @param string $cache_id
+ * @param string $compile_id
+ * @param string $results
+ * @return true|null
+ */
+
+ // $tpl_file, $cache_id, $compile_id, $results
+
+function smarty_core_write_cache_file($params, &$smarty)
+{
+
+    // put timestamp in cache header
+    $smarty->_cache_info['timestamp'] = time();
+    if ($smarty->cache_lifetime > -1){
+        // expiration set
+        $smarty->_cache_info['expires'] = $smarty->_cache_info['timestamp'] + $smarty->cache_lifetime;
+    } else {
+        // cache will never expire
+        $smarty->_cache_info['expires'] = -1;
+    }
+
+    // collapse nocache.../nocache-tags
+    if (preg_match_all('!\{(/?)nocache\:[0-9a-f]{32}#\d+\}!', $params['results'], $match, PREG_PATTERN_ORDER)) {
+        // remove everything between every pair of outermost noache.../nocache-tags
+        // and replace it by a single nocache-tag
+        // this new nocache-tag will be replaced by dynamic contents in
+        // smarty_core_process_compiled_includes() on a cache-read
+        
+        $match_count = count($match[0]);
+        $results = preg_split('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!', $params['results'], -1, PREG_SPLIT_DELIM_CAPTURE);
+        
+        $level = 0;
+        $j = 0;
+        for ($i=0, $results_count = count($results); $i < $results_count && $j < $match_count; $i++) {
+            if ($results[$i] == $match[0][$j]) {
+                // nocache tag
+                if ($match[1][$j]) { // closing tag
+                    $level--;
+                    unset($results[$i]);
+                } else { // opening tag
+                    if ($level++ > 0) unset($results[$i]);
+                }
+                $j++;
+            } elseif ($level > 0) {
+                unset($results[$i]);
+            }
+        }
+        $params['results'] = implode('', $results);
+    }
+    $smarty->_cache_info['cache_serials'] = $smarty->_cache_serials;
+
+    // prepend the cache header info into cache file
+    $_cache_info = serialize($smarty->_cache_info);
+    $params['results'] = strlen($_cache_info) . "\n" . $_cache_info . $params['results'];
+
+    if (!empty($smarty->cache_handler_func)) {
+        // use cache_handler function
+        call_user_func_array($smarty->cache_handler_func,
+                             array('write', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null));
+    } else {
+        // use local cache file
+
+        if(!@is_writable($smarty->cache_dir)) {
+            // cache_dir not writable, see if it exists
+            if(!@is_dir($smarty->cache_dir)) {
+                $smarty->trigger_error('the $cache_dir \'' . $smarty->cache_dir . '\' does not exist, or is not a directory.', E_USER_ERROR);
+                return false;
+            }
+            $smarty->trigger_error('unable to write to $cache_dir \'' . realpath($smarty->cache_dir) . '\'. Be sure $cache_dir is writable by the web server user.', E_USER_ERROR);
+            return false;
+        }
+
+        $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']);
+        $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id);
+        $_params = array('filename' => $_cache_file, 'contents' => $params['results'], 'create_dirs' => true);
+        require_once(SMARTY_CORE_DIR . 'core.write_file.php');
+        smarty_core_write_file($_params, $smarty);
+        return true;
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.write_compiled_include.php b/inc/smarty/internals/core.write_compiled_include.php
new file mode 100644 (file)
index 0000000..c14adb5
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Extract non-cacheable parts out of compiled template and write it
+ *
+ * @param string $compile_path
+ * @param string $template_compiled
+ * @return boolean
+ */
+
+function smarty_core_write_compiled_include($params, &$smarty)
+{
+    $_tag_start = 'if \(\$this->caching && \!\$this->_cache_including\)\: echo \'\{nocache\:('.$params['cache_serial'].')#(\d+)\}\'; endif;';
+    $_tag_end   = 'if \(\$this->caching && \!\$this->_cache_including\)\: echo \'\{/nocache\:(\\2)#(\\3)\}\'; endif;';
+
+    preg_match_all('!('.$_tag_start.'(.*)'.$_tag_end.')!Us',
+                   $params['compiled_content'], $_match_source, PREG_SET_ORDER);
+    
+    // no nocache-parts found: done
+    if (count($_match_source)==0) return;
+
+    // convert the matched php-code to functions
+    $_include_compiled =  "<?php /* Smarty version ".$smarty->_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n";
+    $_include_compiled .= "         compiled from " . strtr(urlencode($params['resource_name']), array('%2F'=>'/', '%3A'=>':')) . " */\n\n";
+
+    $_compile_path = $params['include_file_path'];
+
+    $smarty->_cache_serials[$_compile_path] = $params['cache_serial'];
+    $_include_compiled .= "\$this->_cache_serials['".$_compile_path."'] = '".$params['cache_serial']."';\n\n?>";
+
+    $_include_compiled .= $params['plugins_code'];
+    $_include_compiled .= "<?php";
+
+    $this_varname = ((double)phpversion() >= 5.0) ? '_smarty' : 'this';
+    for ($_i = 0, $_for_max = count($_match_source); $_i < $_for_max; $_i++) {
+        $_match =& $_match_source[$_i];
+        $source = $_match[4];
+        if ($this_varname == '_smarty') {
+            /* rename $this to $_smarty in the sourcecode */
+            $tokens = token_get_all('<?php ' . $_match[4]);
+
+            /* remove trailing <?php */
+            $open_tag = '';
+            while ($tokens) {
+                $token = array_shift($tokens);
+                if (is_array($token)) {
+                    $open_tag .= $token[1];
+                } else {
+                    $open_tag .= $token;
+                }
+                if ($open_tag == '<?php ') break;
+            }
+
+            for ($i=0, $count = count($tokens); $i < $count; $i++) {
+                if (is_array($tokens[$i])) {
+                    if ($tokens[$i][0] == T_VARIABLE && $tokens[$i][1] == '$this') {
+                        $tokens[$i] = '$' . $this_varname;
+                    } else {
+                        $tokens[$i] = $tokens[$i][1];
+                    }                   
+                }
+            }
+            $source = implode('', $tokens);
+        }
+
+        /* add function to compiled include */
+        $_include_compiled .= "
+function _smarty_tplfunc_$_match[2]_$_match[3](&\$$this_varname)
+{
+$source
+}
+
+";
+    }
+    $_include_compiled .= "\n\n?>\n";
+
+    $_params = array('filename' => $_compile_path,
+                     'contents' => $_include_compiled, 'create_dirs' => true);
+
+    require_once(SMARTY_CORE_DIR . 'core.write_file.php');
+    smarty_core_write_file($_params, $smarty);
+    return true;
+}
+
+
+?>
diff --git a/inc/smarty/internals/core.write_compiled_resource.php b/inc/smarty/internals/core.write_compiled_resource.php
new file mode 100644 (file)
index 0000000..b902eff
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * write the compiled resource
+ *
+ * @param string $compile_path
+ * @param string $compiled_content
+ * @return true
+ */
+function smarty_core_write_compiled_resource($params, &$smarty)
+{
+    if(!@is_writable($smarty->compile_dir)) {
+        // compile_dir not writable, see if it exists
+        if(!@is_dir($smarty->compile_dir)) {
+            $smarty->trigger_error('the $compile_dir \'' . $smarty->compile_dir . '\' does not exist, or is not a directory.', E_USER_ERROR);
+            return false;
+        }
+        $smarty->trigger_error('unable to write to $compile_dir \'' . realpath($smarty->compile_dir) . '\'. Be sure $compile_dir is writable by the web server user.', E_USER_ERROR);
+        return false;
+    }
+
+    $_params = array('filename' => $params['compile_path'], 'contents' => $params['compiled_content'], 'create_dirs' => true);
+    require_once(SMARTY_CORE_DIR . 'core.write_file.php');
+    smarty_core_write_file($_params, $smarty);
+    return true;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/internals/core.write_file.php b/inc/smarty/internals/core.write_file.php
new file mode 100644 (file)
index 0000000..8a3a3b3
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * write out a file to disk
+ *
+ * @param string $filename
+ * @param string $contents
+ * @param boolean $create_dirs
+ * @return boolean
+ */
+function smarty_core_write_file($params, &$smarty)
+{
+    $_dirname = dirname($params['filename']);
+
+    if ($params['create_dirs']) {
+        $_params = array('dir' => $_dirname);
+        require_once(SMARTY_CORE_DIR . 'core.create_dir_structure.php');
+        smarty_core_create_dir_structure($_params, $smarty);
+    }
+
+    // write to tmp file, then rename it to avoid file locking race condition
+    $_tmp_file = tempnam($_dirname, 'wrt');
+
+    if (!($fd = @fopen($_tmp_file, 'wb'))) {
+        $_tmp_file = $_dirname . DIRECTORY_SEPARATOR . uniqid('wrt');
+        if (!($fd = @fopen($_tmp_file, 'wb'))) {
+            $smarty->trigger_error("problem writing temporary file '$_tmp_file'");
+            return false;
+        }
+    }
+
+    fwrite($fd, $params['contents']);
+    fclose($fd);
+
+    if (DIRECTORY_SEPARATOR == '\\' || !@rename($_tmp_file, $params['filename'])) {
+        // On platforms and filesystems that cannot overwrite with rename() 
+        // delete the file before renaming it -- because windows always suffers
+        // this, it is short-circuited to avoid the initial rename() attempt
+        @unlink($params['filename']);
+        @rename($_tmp_file, $params['filename']);
+    }
+    @chmod($params['filename'], $smarty->_file_perms);
+
+    return true;
+}
+
+/* vim: set expandtab: */
+
+?>
\ No newline at end of file
diff --git a/inc/smarty/plugins/block.textformat.php b/inc/smarty/plugins/block.textformat.php
new file mode 100644 (file)
index 0000000..8cd010a
--- /dev/null
@@ -0,0 +1,103 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {textformat}{/textformat} block plugin
+ *
+ * Type:     block function<br>
+ * Name:     textformat<br>
+ * Purpose:  format text a certain way with preset styles
+ *           or custom wrap/indent settings<br>
+ * @link http://smarty.php.net/manual/en/language.function.textformat.php {textformat}
+ *       (Smarty online manual)
+ * @param array
+ * <pre>
+ * Params:   style: string (email)
+ *           indent: integer (0)
+ *           wrap: integer (80)
+ *           wrap_char string ("\n")
+ *           indent_char: string (" ")
+ *           wrap_boundary: boolean (true)
+ * </pre>
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @param string contents of the block
+ * @param Smarty clever simulation of a method
+ * @return string string $content re-formatted
+ */
+function smarty_block_textformat($params, $content, &$smarty)
+{
+    if (is_null($content)) {
+        return;
+    }
+
+    $style = null;
+    $indent = 0;
+    $indent_first = 0;
+    $indent_char = ' ';
+    $wrap = 80;
+    $wrap_char = "\n";
+    $wrap_cut = false;
+    $assign = null;
+    
+    foreach ($params as $_key => $_val) {
+        switch ($_key) {
+            case 'style':
+            case 'indent_char':
+            case 'wrap_char':
+            case 'assign':
+                $$_key = (string)$_val;
+                break;
+
+            case 'indent':
+            case 'indent_first':
+            case 'wrap':
+                $$_key = (int)$_val;
+                break;
+
+            case 'wrap_cut':
+                $$_key = (bool)$_val;
+                break;
+
+            default:
+                $smarty->trigger_error("textformat: unknown attribute '$_key'");
+        }
+    }
+
+    if ($style == 'email') {
+        $wrap = 72;
+    }
+
+    // split into paragraphs
+    $_paragraphs = preg_split('![\r\n][\r\n]!',$content);
+    $_output = '';
+
+    for($_x = 0, $_y = count($_paragraphs); $_x < $_y; $_x++) {
+        if ($_paragraphs[$_x] == '') {
+            continue;
+        }
+        // convert mult. spaces & special chars to single space
+        $_paragraphs[$_x] = preg_replace(array('!\s+!','!(^\s+)|(\s+$)!'), array(' ',''), $_paragraphs[$_x]);
+        // indent first line
+        if($indent_first > 0) {
+            $_paragraphs[$_x] = str_repeat($indent_char, $indent_first) . $_paragraphs[$_x];
+        }
+        // wordwrap sentences
+        $_paragraphs[$_x] = wordwrap($_paragraphs[$_x], $wrap - $indent, $wrap_char, $wrap_cut);
+        // indent lines
+        if($indent > 0) {
+            $_paragraphs[$_x] = preg_replace('!^!m', str_repeat($indent_char, $indent), $_paragraphs[$_x]);
+        }
+    }
+    $_output = implode($wrap_char . $wrap_char, $_paragraphs);
+
+    return $assign ? $smarty->assign($assign, $_output) : $_output;
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/compiler.assign.php b/inc/smarty/plugins/compiler.assign.php
new file mode 100644 (file)
index 0000000..be17298
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {assign} compiler function plugin
+ *
+ * Type:     compiler function<br>
+ * Name:     assign<br>
+ * Purpose:  assign a value to a template variable
+ * @link http://smarty.php.net/manual/en/language.custom.functions.php#LANGUAGE.FUNCTION.ASSIGN {assign}
+ *       (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com> (initial author)
+ * @auther messju mohr <messju at lammfellpuschen dot de> (conversion to compiler function)
+ * @param string containing var-attribute and value-attribute
+ * @param Smarty_Compiler
+ */
+function smarty_compiler_assign($tag_attrs, &$compiler)
+{
+    $_params = $compiler->_parse_attrs($tag_attrs);
+
+    if (!isset($_params['var'])) {
+        $compiler->_syntax_error("assign: missing 'var' parameter", E_USER_WARNING);
+        return;
+    }
+
+    if (!isset($_params['value'])) {
+        $compiler->_syntax_error("assign: missing 'value' parameter", E_USER_WARNING);
+        return;
+    }
+
+    return "\$this->assign({$_params['var']}, {$_params['value']});";
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.assign.php b/inc/smarty/plugins/function.assign.php
new file mode 100644 (file)
index 0000000..ad23f04
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {assign} function plugin
+ *
+ * Type:     function<br>
+ * Name:     assign<br>
+ * Purpose:  assign a value to a template variable
+ * @link http://smarty.php.net/manual/en/language.custom.functions.php#LANGUAGE.FUNCTION.ASSIGN {assign}
+ *       (Smarty online manual)
+ * @param array Format: array('var' => variable name, 'value' => value to assign)
+ * @param Smarty
+ */
+function smarty_function_assign($params, &$smarty)
+{
+    extract($params);
+
+    if (empty($var)) {
+        $smarty->trigger_error("assign: missing 'var' parameter");
+        return;
+    }
+
+    if (!in_array('value', array_keys($params))) {
+        $smarty->trigger_error("assign: missing 'value' parameter");
+        return;
+    }
+
+    $smarty->assign($var, $value);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.assign_debug_info.php b/inc/smarty/plugins/function.assign_debug_info.php
new file mode 100644 (file)
index 0000000..6540498
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {assign_debug_info} function plugin
+ *
+ * Type:     function<br>
+ * Name:     assign_debug_info<br>
+ * Purpose:  assign debug info to the template<br>
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @param array unused in this plugin, this plugin uses {@link Smarty::$_config},
+ *              {@link Smarty::$_tpl_vars} and {@link Smarty::$_smarty_debug_info}
+ * @param Smarty
+ */
+function smarty_function_assign_debug_info($params, &$smarty)
+{
+    $assigned_vars = $smarty->_tpl_vars;
+    ksort($assigned_vars);
+    if (@is_array($smarty->_config[0])) {
+        $config_vars = $smarty->_config[0];
+        ksort($config_vars);
+        $smarty->assign("_debug_config_keys", array_keys($config_vars));
+        $smarty->assign("_debug_config_vals", array_values($config_vars));
+    }
+    
+    $included_templates = $smarty->_smarty_debug_info;
+    
+    $smarty->assign("_debug_keys", array_keys($assigned_vars));
+    $smarty->assign("_debug_vals", array_values($assigned_vars));
+    
+    $smarty->assign("_debug_tpls", $included_templates);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.config_load.php b/inc/smarty/plugins/function.config_load.php
new file mode 100644 (file)
index 0000000..db89f63
--- /dev/null
@@ -0,0 +1,142 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {config_load} function plugin
+ *
+ * Type:     function<br>
+ * Name:     config_load<br>
+ * Purpose:  load config file vars
+ * @link http://smarty.php.net/manual/en/language.function.config.load.php {config_load}
+ *       (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author messju mohr <messju at lammfellpuschen dot de> (added use of resources)
+ * @param array Format:
+ * <pre>
+ * array('file' => required config file name,
+ *       'section' => optional config file section to load
+ *       'scope' => local/parent/global
+ *       'global' => overrides scope, setting to parent if true)
+ * </pre>
+ * @param Smarty
+ */
+function smarty_function_config_load($params, &$smarty)
+{
+        if ($smarty->debugging) {
+            $_params = array();
+            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+            $_debug_start_time = smarty_core_get_microtime($_params, $smarty);
+        }
+
+        $_file = isset($params['file']) ? $smarty->_dequote($params['file']) : null;
+        $_section = isset($params['section']) ? $smarty->_dequote($params['section']) : null;
+        $_scope = isset($params['scope']) ? $smarty->_dequote($params['scope']) : 'global';
+        $_global = isset($params['global']) ? $smarty->_dequote($params['global']) : false;
+
+        if (!isset($_file) || strlen($_file) == 0) {
+            $smarty->trigger_error("missing 'file' attribute in config_load tag", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        if (isset($_scope)) {
+            if ($_scope != 'local' &&
+                $_scope != 'parent' &&
+                $_scope != 'global') {
+                $smarty->trigger_error("invalid 'scope' attribute value", E_USER_ERROR, __FILE__, __LINE__);
+            }
+        } else {
+            if ($_global) {
+                $_scope = 'parent';
+            } else {
+                $_scope = 'local';
+            }
+        }
+
+        $_params = array('resource_name' => $_file,
+                         'resource_base_path' => $smarty->config_dir,
+                         'get_source' => false);
+        $smarty->_parse_resource_name($_params);
+        $_file_path = $_params['resource_type'] . ':' . $_params['resource_name'];
+        if (isset($_section))
+            $_compile_file = $smarty->_get_compile_path($_file_path.'|'.$_section);
+        else
+            $_compile_file = $smarty->_get_compile_path($_file_path);
+
+        if($smarty->force_compile || !file_exists($_compile_file)) {
+            $_compile = true;
+        } elseif ($smarty->compile_check) {
+            $_params = array('resource_name' => $_file,
+                             'resource_base_path' => $smarty->config_dir,
+                             'get_source' => false);
+            $_compile = $smarty->_fetch_resource_info($_params) &&
+                $_params['resource_timestamp'] > filemtime($_compile_file);
+        } else {
+            $_compile = false;
+        }
+
+        if($_compile) {
+            // compile config file
+            if(!is_object($smarty->_conf_obj)) {
+                require_once SMARTY_DIR . $smarty->config_class . '.class.php';
+                $smarty->_conf_obj = new $smarty->config_class();
+                $smarty->_conf_obj->overwrite = $smarty->config_overwrite;
+                $smarty->_conf_obj->booleanize = $smarty->config_booleanize;
+                $smarty->_conf_obj->read_hidden = $smarty->config_read_hidden;
+                $smarty->_conf_obj->fix_newlines = $smarty->config_fix_newlines;
+            }
+
+            $_params = array('resource_name' => $_file,
+                             'resource_base_path' => $smarty->config_dir,
+                             $_params['get_source'] = true);
+            if (!$smarty->_fetch_resource_info($_params)) {
+                return;
+            }
+            $smarty->_conf_obj->set_file_contents($_file, $_params['source_content']);
+            $_config_vars = array_merge($smarty->_conf_obj->get($_file),
+                    $smarty->_conf_obj->get($_file, $_section));
+            if(function_exists('var_export')) {
+                $_output = '<?php $_config_vars = ' . var_export($_config_vars, true) . '; ?>';
+            } else {
+                $_output = '<?php $_config_vars = unserialize(\'' . strtr(serialize($_config_vars),array('\''=>'\\\'', '\\'=>'\\\\')) . '\'); ?>';
+            }
+            $_params = (array('compile_path' => $_compile_file, 'compiled_content' => $_output, 'resource_timestamp' => $_params['resource_timestamp']));
+            require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php');
+            smarty_core_write_compiled_resource($_params, $smarty);
+        } else {
+            include($_compile_file);
+        }
+
+        if ($smarty->caching) {
+            $smarty->_cache_info['config'][$_file] = true;
+        }
+
+        $smarty->_config[0]['vars'] = @array_merge($smarty->_config[0]['vars'], $_config_vars);
+        $smarty->_config[0]['files'][$_file] = true;
+
+        if ($_scope == 'parent') {
+                $smarty->_config[1]['vars'] = @array_merge($smarty->_config[1]['vars'], $_config_vars);
+                $smarty->_config[1]['files'][$_file] = true;
+        } else if ($_scope == 'global') {
+            for ($i = 1, $for_max = count($smarty->_config); $i < $for_max; $i++) {
+                $smarty->_config[$i]['vars'] = @array_merge($smarty->_config[$i]['vars'], $_config_vars);
+                $smarty->_config[$i]['files'][$_file] = true;
+            }
+        }
+
+        if ($smarty->debugging) {
+            $_params = array();
+            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+            $smarty->_smarty_debug_info[] = array('type'      => 'config',
+                                                'filename'  => $_file.' ['.$_section.'] '.$_scope,
+                                                'depth'     => $smarty->_inclusion_depth,
+                                                'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time);
+        }
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.counter.php b/inc/smarty/plugins/function.counter.php
new file mode 100644 (file)
index 0000000..1f26db5
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {counter} function plugin
+ *
+ * Type:     function<br>
+ * Name:     counter<br>
+ * Purpose:  print out a counter value
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @link http://smarty.php.net/manual/en/language.function.counter.php {counter}
+ *       (Smarty online manual)
+ * @param array parameters
+ * @param Smarty
+ * @return string|null
+ */
+function smarty_function_counter($params, &$smarty)
+{
+    static $counters = array();
+
+    $name = (isset($params['name'])) ? $params['name'] : 'default';
+    if (!isset($counters[$name])) {
+        $counters[$name] = array(
+            'start'=>1,
+            'skip'=>1,
+            'direction'=>'up',
+            'count'=>1
+            );
+    }
+    $counter =& $counters[$name];
+
+    if (isset($params['start'])) {
+        $counter['start'] = $counter['count'] = (int)$params['start'];
+    }
+
+    if (!empty($params['assign'])) {
+        $counter['assign'] = $params['assign'];
+    }
+
+    if (isset($counter['assign'])) {
+        $smarty->assign($counter['assign'], $counter['count']);
+    }
+    
+    if (isset($params['print'])) {
+        $print = (bool)$params['print'];
+    } else {
+        $print = empty($counter['assign']);
+    }
+
+    if ($print) {
+        $retval = $counter['count'];
+    } else {
+        $retval = null;
+    }
+
+    if (isset($params['skip'])) {
+        $counter['skip'] = $params['skip'];
+    }
+    
+    if (isset($params['direction'])) {
+        $counter['direction'] = $params['direction'];
+    }
+
+    if ($counter['direction'] == "down")
+        $counter['count'] -= $counter['skip'];
+    else
+        $counter['count'] += $counter['skip'];
+    
+    return $retval;
+    
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.cycle.php b/inc/smarty/plugins/function.cycle.php
new file mode 100644 (file)
index 0000000..fe78bb8
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {cycle} function plugin
+ *
+ * Type:     function<br>
+ * Name:     cycle<br>
+ * Date:     May 3, 2002<br>
+ * Purpose:  cycle through given values<br>
+ * Input:
+ *         - name = name of cycle (optional)
+ *         - values = comma separated list of values to cycle,
+ *                    or an array of values to cycle
+ *                    (this can be left out for subsequent calls)
+ *         - reset = boolean - resets given var to true
+ *         - print = boolean - print var or not. default is true
+ *         - advance = boolean - whether or not to advance the cycle
+ *         - delimiter = the value delimiter, default is ","
+ *         - assign = boolean, assigns to template var instead of
+ *                    printed.
+ *
+ * Examples:<br>
+ * <pre>
+ * {cycle values="#eeeeee,#d0d0d0d"}
+ * {cycle name=row values="one,two,three" reset=true}
+ * {cycle name=row}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.cycle.php {cycle}
+ *       (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author credit to Mark Priatel <mpriatel@rogers.com>
+ * @author credit to Gerard <gerard@interfold.com>
+ * @author credit to Jason Sweat <jsweat_php@yahoo.com>
+ * @version  1.3
+ * @param array
+ * @param Smarty
+ * @return string|null
+ */
+function smarty_function_cycle($params, &$smarty)
+{
+    static $cycle_vars;
+    
+    $name = (empty($params['name'])) ? 'default' : $params['name'];
+    $print = (isset($params['print'])) ? (bool)$params['print'] : true;
+    $advance = (isset($params['advance'])) ? (bool)$params['advance'] : true;
+    $reset = (isset($params['reset'])) ? (bool)$params['reset'] : false;
+            
+    if (!in_array('values', array_keys($params))) {
+        if(!isset($cycle_vars[$name]['values'])) {
+            $smarty->trigger_error("cycle: missing 'values' parameter");
+            return;
+        }
+    } else {
+        if(isset($cycle_vars[$name]['values'])
+            && $cycle_vars[$name]['values'] != $params['values'] ) {
+            $cycle_vars[$name]['index'] = 0;
+        }
+        $cycle_vars[$name]['values'] = $params['values'];
+    }
+
+    $cycle_vars[$name]['delimiter'] = (isset($params['delimiter'])) ? $params['delimiter'] : ',';
+    
+    if(is_array($cycle_vars[$name]['values'])) {
+        $cycle_array = $cycle_vars[$name]['values'];
+    } else {
+        $cycle_array = explode($cycle_vars[$name]['delimiter'],$cycle_vars[$name]['values']);
+    }
+    
+    if(!isset($cycle_vars[$name]['index']) || $reset ) {
+        $cycle_vars[$name]['index'] = 0;
+    }
+    
+    if (isset($params['assign'])) {
+        $print = false;
+        $smarty->assign($params['assign'], $cycle_array[$cycle_vars[$name]['index']]);
+    }
+        
+    if($print) {
+        $retval = $cycle_array[$cycle_vars[$name]['index']];
+    } else {
+        $retval = null;
+    }
+
+    if($advance) {
+        if ( $cycle_vars[$name]['index'] >= count($cycle_array) -1 ) {
+            $cycle_vars[$name]['index'] = 0;
+        } else {
+            $cycle_vars[$name]['index']++;
+        }
+    }
+    
+    return $retval;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.debug.php b/inc/smarty/plugins/function.debug.php
new file mode 100644 (file)
index 0000000..4345230
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {debug} function plugin
+ *
+ * Type:     function<br>
+ * Name:     debug<br>
+ * Date:     July 1, 2002<br>
+ * Purpose:  popup debug window
+ * @link http://smarty.php.net/manual/en/language.function.debug.php {debug}
+ *       (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @version  1.0
+ * @param array
+ * @param Smarty
+ * @return string output from {@link Smarty::_generate_debug_output()}
+ */
+function smarty_function_debug($params, &$smarty)
+{
+    if (isset($params['output'])) {
+        $smarty->assign('_smarty_debug_output', $params['output']);
+    }
+    require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php');
+    return smarty_core_display_debug_console(null, $smarty);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.eval.php b/inc/smarty/plugins/function.eval.php
new file mode 100644 (file)
index 0000000..ff0472d
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {eval} function plugin
+ *
+ * Type:     function<br>
+ * Name:     eval<br>
+ * Purpose:  evaluate a template variable as a template<br>
+ * @link http://smarty.php.net/manual/en/language.function.eval.php {eval}
+ *       (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @param array
+ * @param Smarty
+ */
+function smarty_function_eval($params, &$smarty)
+{
+
+    if (!isset($params['var'])) {
+        $smarty->trigger_error("eval: missing 'var' parameter");
+        return;
+    }
+
+    if($params['var'] == '') {
+        return;
+    }
+
+    $smarty->_compile_source('evaluated template', $params['var'], $_var_compiled);
+
+    ob_start();
+    $smarty->_eval('?>' . $_var_compiled);
+    $_contents = ob_get_contents();
+    ob_end_clean();
+
+    if (!empty($params['assign'])) {
+        $smarty->assign($params['assign'], $_contents);
+    } else {
+        return $_contents;
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.fetch.php b/inc/smarty/plugins/function.fetch.php
new file mode 100644 (file)
index 0000000..81b1bfc
--- /dev/null
@@ -0,0 +1,221 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {fetch} plugin
+ *
+ * Type:     function<br>
+ * Name:     fetch<br>
+ * Purpose:  fetch file, web or ftp data and display results
+ * @link http://smarty.php.net/manual/en/language.function.fetch.php {fetch}
+ *       (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @param array
+ * @param Smarty
+ * @return string|null if the assign parameter is passed, Smarty assigns the
+ *                     result to a template variable
+ */
+function smarty_function_fetch($params, &$smarty)
+{
+    if (empty($params['file'])) {
+        $smarty->_trigger_fatal_error("[plugin] parameter 'file' cannot be empty");
+        return;
+    }
+
+    $content = '';
+    if ($smarty->security && !preg_match('!^(http|ftp)://!i', $params['file'])) {
+        $_params = array('resource_type' => 'file', 'resource_name' => $params['file']);
+        require_once(SMARTY_CORE_DIR . 'core.is_secure.php');
+        if(!smarty_core_is_secure($_params, $smarty)) {
+            $smarty->_trigger_fatal_error('[plugin] (secure mode) fetch \'' . $params['file'] . '\' is not allowed');
+            return;
+        }
+        
+        // fetch the file
+        if($fp = @fopen($params['file'],'r')) {
+            while(!feof($fp)) {
+                $content .= fgets ($fp,4096);
+            }
+            fclose($fp);
+        } else {
+            $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] . '\'');
+            return;
+        }
+    } else {
+        // not a local file
+        if(preg_match('!^http://!i',$params['file'])) {
+            // http fetch
+            if($uri_parts = parse_url($params['file'])) {
+                // set defaults
+                $host = $server_name = $uri_parts['host'];
+                $timeout = 30;
+                $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*";
+                $agent = "Smarty Template Engine ".$smarty->_version;
+                $referer = "";
+                $uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/';
+                $uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : '';
+                $_is_proxy = false;
+                if(empty($uri_parts['port'])) {
+                    $port = 80;
+                } else {
+                    $port = $uri_parts['port'];
+                }
+                if(!empty($uri_parts['user'])) {
+                    $user = $uri_parts['user'];
+                }
+                if(!empty($uri_parts['pass'])) {
+                    $pass = $uri_parts['pass'];
+                }
+                // loop through parameters, setup headers
+                foreach($params as $param_key => $param_value) {
+                    switch($param_key) {
+                        case "file":
+                        case "assign":
+                        case "assign_headers":
+                            break;
+                        case "user":
+                            if(!empty($param_value)) {
+                                $user = $param_value;
+                            }
+                            break;
+                        case "pass":
+                            if(!empty($param_value)) {
+                                $pass = $param_value;
+                            }
+                            break;
+                        case "accept":
+                            if(!empty($param_value)) {
+                                $accept = $param_value;
+                            }
+                            break;
+                        case "header":
+                            if(!empty($param_value)) {
+                                if(!preg_match('![\w\d-]+: .+!',$param_value)) {
+                                    $smarty->_trigger_fatal_error("[plugin] invalid header format '".$param_value."'");
+                                    return;
+                                } else {
+                                    $extra_headers[] = $param_value;
+                                }
+                            }
+                            break;
+                        case "proxy_host":
+                            if(!empty($param_value)) {
+                                $proxy_host = $param_value;
+                            }
+                            break;
+                        case "proxy_port":
+                            if(!preg_match('!\D!', $param_value)) {
+                                $proxy_port = (int) $param_value;
+                            } else {
+                                $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'");
+                                return;
+                            }
+                            break;
+                        case "agent":
+                            if(!empty($param_value)) {
+                                $agent = $param_value;
+                            }
+                            break;
+                        case "referer":
+                            if(!empty($param_value)) {
+                                $referer = $param_value;
+                            }
+                            break;
+                        case "timeout":
+                            if(!preg_match('!\D!', $param_value)) {
+                                $timeout = (int) $param_value;
+                            } else {
+                                $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'");
+                                return;
+                            }
+                            break;
+                        default:
+                            $smarty->_trigger_fatal_error("[plugin] unrecognized attribute '".$param_key."'");
+                            return;
+                    }
+                }
+                if(!empty($proxy_host) && !empty($proxy_port)) {
+                    $_is_proxy = true;
+                    $fp = fsockopen($proxy_host,$proxy_port,$errno,$errstr,$timeout);
+                } else {
+                    $fp = fsockopen($server_name,$port,$errno,$errstr,$timeout);
+                }
+
+                if(!$fp) {
+                    $smarty->_trigger_fatal_error("[plugin] unable to fetch: $errstr ($errno)");
+                    return;
+                } else {
+                    if($_is_proxy) {
+                        fputs($fp, 'GET ' . $params['file'] . " HTTP/1.0\r\n");
+                    } else {
+                        fputs($fp, "GET $uri HTTP/1.0\r\n");
+                    }
+                    if(!empty($host)) {
+                        fputs($fp, "Host: $host\r\n");
+                    }
+                    if(!empty($accept)) {
+                        fputs($fp, "Accept: $accept\r\n");
+                    }
+                    if(!empty($agent)) {
+                        fputs($fp, "User-Agent: $agent\r\n");
+                    }
+                    if(!empty($referer)) {
+                        fputs($fp, "Referer: $referer\r\n");
+                    }
+                    if(isset($extra_headers) && is_array($extra_headers)) {
+                        foreach($extra_headers as $curr_header) {
+                            fputs($fp, $curr_header."\r\n");
+                        }
+                    }
+                    if(!empty($user) && !empty($pass)) {
+                        fputs($fp, "Authorization: BASIC ".base64_encode("$user:$pass")."\r\n");
+                    }
+
+                    fputs($fp, "\r\n");
+                    while(!feof($fp)) {
+                        $content .= fgets($fp,4096);
+                    }
+                    fclose($fp);
+                    $csplit = split("\r\n\r\n",$content,2);
+
+                    $content = $csplit[1];
+
+                    if(!empty($params['assign_headers'])) {
+                        $smarty->assign($params['assign_headers'],split("\r\n",$csplit[0]));
+                    }
+                }
+            } else {
+                $smarty->_trigger_fatal_error("[plugin] unable to parse URL, check syntax");
+                return;
+            }
+        } else {
+            // ftp fetch
+            if($fp = @fopen($params['file'],'r')) {
+                while(!feof($fp)) {
+                    $content .= fgets ($fp,4096);
+                }
+                fclose($fp);
+            } else {
+                $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] .'\'');
+                return;
+            }
+        }
+
+    }
+
+
+    if (!empty($params['assign'])) {
+        $smarty->assign($params['assign'],$content);
+    } else {
+        return $content;
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.html_checkboxes.php b/inc/smarty/plugins/function.html_checkboxes.php
new file mode 100644 (file)
index 0000000..ed8ad7f
--- /dev/null
@@ -0,0 +1,143 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_checkboxes} function plugin
+ *
+ * File:       function.html_checkboxes.php<br>
+ * Type:       function<br>
+ * Name:       html_checkboxes<br>
+ * Date:       24.Feb.2003<br>
+ * Purpose:    Prints out a list of checkbox input types<br>
+ * Input:<br>
+ *           - name       (optional) - string default "checkbox"
+ *           - values     (required) - array
+ *           - options    (optional) - associative array
+ *           - checked    (optional) - array default not set
+ *           - separator  (optional) - ie <br> or &nbsp;
+ *           - output     (optional) - the output next to each checkbox
+ *           - assign     (optional) - assign the output as an array to this variable
+ * Examples:
+ * <pre>
+ * {html_checkboxes values=$ids output=$names}
+ * {html_checkboxes values=$ids name='box' separator='<br>' output=$names}
+ * {html_checkboxes values=$ids checked=$checked separator='<br>' output=$names}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.html.checkboxes.php {html_checkboxes}
+ *      (Smarty online manual)
+ * @author     Christopher Kvarme <christopher.kvarme@flashjab.com>
+ * @author credits to Monte Ohrt <monte at ohrt dot com>
+ * @version    1.0
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_checkboxes($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+
+    $name = 'checkbox';
+    $values = null;
+    $options = null;
+    $selected = null;
+    $separator = '';
+    $labels = true;
+    $output = null;
+
+    $extra = '';
+
+    foreach($params as $_key => $_val) {
+        switch($_key) {
+            case 'name':
+            case 'separator':
+                $$_key = $_val;
+                break;
+
+            case 'labels':
+                $$_key = (bool)$_val;
+                break;
+
+            case 'options':
+                $$_key = (array)$_val;
+                break;
+
+            case 'values':
+            case 'output':
+                $$_key = array_values((array)$_val);
+                break;
+
+            case 'checked':
+            case 'selected':
+                $selected = array_map('strval', array_values((array)$_val));
+                break;
+
+            case 'checkboxes':
+                $smarty->trigger_error('html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', E_USER_WARNING);
+                $options = (array)$_val;
+                break;
+
+            case 'assign':
+                break;
+
+            default:
+                if(!is_array($_val)) {
+                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+                } else {
+                    $smarty->trigger_error("html_checkboxes: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (!isset($options) && !isset($values))
+        return ''; /* raise error here? */
+
+    settype($selected, 'array');
+    $_html_result = array();
+
+    if (isset($options)) {
+
+        foreach ($options as $_key=>$_val)
+            $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
+
+
+    } else {
+        foreach ($values as $_i=>$_key) {
+            $_val = isset($output[$_i]) ? $output[$_i] : '';
+            $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
+        }
+
+    }
+
+    if(!empty($params['assign'])) {
+        $smarty->assign($params['assign'], $_html_result);
+    } else {
+        return implode("\n",$_html_result);
+    }
+
+}
+
+function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels) {
+    $_output = '';
+    if ($labels) $_output .= '<label>';
+    $_output .= '<input type="checkbox" name="'
+        . smarty_function_escape_special_chars($name) . '[]" value="'
+        . smarty_function_escape_special_chars($value) . '"';
+
+    if (in_array((string)$value, $selected)) {
+        $_output .= ' checked="checked"';
+    }
+    $_output .= $extra . ' />' . $output;
+    if ($labels) $_output .= '</label>';
+    $_output .=  $separator;
+
+    return $_output;
+}
+
+?>
diff --git a/inc/smarty/plugins/function.html_image.php b/inc/smarty/plugins/function.html_image.php
new file mode 100644 (file)
index 0000000..9abae72
--- /dev/null
@@ -0,0 +1,142 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_image} function plugin
+ *
+ * Type:     function<br>
+ * Name:     html_image<br>
+ * Date:     Feb 24, 2003<br>
+ * Purpose:  format HTML tags for the image<br>
+ * Input:<br>
+ *         - file = file (and path) of image (required)
+ *         - height = image height (optional, default actual height)
+ *         - width = image width (optional, default actual width)
+ *         - basedir = base directory for absolute paths, default
+ *                     is environment variable DOCUMENT_ROOT
+ *         - path_prefix = prefix for path output (optional, default empty)
+ *
+ * Examples: {html_image file="/images/masthead.gif"}
+ * Output:   <img src="/images/masthead.gif" width=400 height=23>
+ * @link http://smarty.php.net/manual/en/language.function.html.image.php {html_image}
+ *      (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @author credits to Duda <duda@big.hu> - wrote first image function
+ *           in repository, helped with lots of functionality
+ * @version  1.0
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_image($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+    
+    $alt = '';
+    $file = '';
+    $height = '';
+    $width = '';
+    $extra = '';
+    $prefix = '';
+    $suffix = '';
+    $path_prefix = '';
+    $server_vars = ($smarty->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
+    $basedir = isset($server_vars['DOCUMENT_ROOT']) ? $server_vars['DOCUMENT_ROOT'] : '';
+    foreach($params as $_key => $_val) {
+        switch($_key) {
+            case 'file':
+            case 'height':
+            case 'width':
+            case 'dpi':
+            case 'path_prefix':
+            case 'basedir':
+                $$_key = $_val;
+                break;
+
+            case 'alt':
+                if(!is_array($_val)) {
+                    $$_key = smarty_function_escape_special_chars($_val);
+                } else {
+                    $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+
+            case 'link':
+            case 'href':
+                $prefix = '<a href="' . $_val . '">';
+                $suffix = '</a>';
+                break;
+
+            default:
+                if(!is_array($_val)) {
+                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+                } else {
+                    $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (empty($file)) {
+        $smarty->trigger_error("html_image: missing 'file' parameter", E_USER_NOTICE);
+        return;
+    }
+
+    if (substr($file,0,1) == '/') {
+        $_image_path = $basedir . $file;
+    } else {
+        $_image_path = $file;
+    }
+    
+    if(!isset($params['width']) || !isset($params['height'])) {
+        if(!$_image_data = @getimagesize($_image_path)) {
+            if(!file_exists($_image_path)) {
+                $smarty->trigger_error("html_image: unable to find '$_image_path'", E_USER_NOTICE);
+                return;
+            } else if(!is_readable($_image_path)) {
+                $smarty->trigger_error("html_image: unable to read '$_image_path'", E_USER_NOTICE);
+                return;
+            } else {
+                $smarty->trigger_error("html_image: '$_image_path' is not a valid image file", E_USER_NOTICE);
+                return;
+            }
+        }
+        if ($smarty->security &&
+            ($_params = array('resource_type' => 'file', 'resource_name' => $_image_path)) &&
+            (require_once(SMARTY_CORE_DIR . 'core.is_secure.php')) &&
+            (!smarty_core_is_secure($_params, $smarty)) ) {
+            $smarty->trigger_error("html_image: (secure) '$_image_path' not in secure directory", E_USER_NOTICE);
+        }        
+        
+        if(!isset($params['width'])) {
+            $width = $_image_data[0];
+        }
+        if(!isset($params['height'])) {
+            $height = $_image_data[1];
+        }
+
+    }
+
+    if(isset($params['dpi'])) {
+        if(strstr($server_vars['HTTP_USER_AGENT'], 'Mac')) {
+            $dpi_default = 72;
+        } else {
+            $dpi_default = 96;
+        }
+        $_resize = $dpi_default/$params['dpi'];
+        $width = round($width * $_resize);
+        $height = round($height * $_resize);
+    }
+
+    return $prefix . '<img src="'.$path_prefix.$file.'" alt="'.$alt.'" width="'.$width.'" height="'.$height.'"'.$extra.' />' . $suffix;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.html_options.php b/inc/smarty/plugins/function.html_options.php
new file mode 100644 (file)
index 0000000..cebadde
--- /dev/null
@@ -0,0 +1,122 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_options} function plugin
+ *
+ * Type:     function<br>
+ * Name:     html_options<br>
+ * Input:<br>
+ *           - name       (optional) - string default "select"
+ *           - values     (required if no options supplied) - array
+ *           - options    (required if no values supplied) - associative array
+ *           - selected   (optional) - string default not set
+ *           - output     (required if not options supplied) - array
+ * Purpose:  Prints the list of <option> tags generated from
+ *           the passed parameters
+ * @link http://smarty.php.net/manual/en/language.function.html.options.php {html_image}
+ *      (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_options($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+    
+    $name = null;
+    $values = null;
+    $options = null;
+    $selected = array();
+    $output = null;
+    
+    $extra = '';
+    
+    foreach($params as $_key => $_val) {
+        switch($_key) {
+            case 'name':
+                $$_key = (string)$_val;
+                break;
+            
+            case 'options':
+                $$_key = (array)$_val;
+                break;
+                
+            case 'values':
+            case 'output':
+                $$_key = array_values((array)$_val);
+                break;
+
+            case 'selected':
+                $$_key = array_map('strval', array_values((array)$_val));
+                break;
+                
+            default:
+                if(!is_array($_val)) {
+                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+                } else {
+                    $smarty->trigger_error("html_options: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (!isset($options) && !isset($values))
+        return ''; /* raise error here? */
+
+    $_html_result = '';
+
+    if (isset($options)) {
+        
+        foreach ($options as $_key=>$_val)
+            $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected);
+
+    } else {
+        
+        foreach ($values as $_i=>$_key) {
+            $_val = isset($output[$_i]) ? $output[$_i] : '';
+            $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected);
+        }
+
+    }
+
+    if(!empty($name)) {
+        $_html_result = '<select name="' . $name . '"' . $extra . '>' . "\n" . $_html_result . '</select>' . "\n";
+    }
+
+    return $_html_result;
+
+}
+
+function smarty_function_html_options_optoutput($key, $value, $selected) {
+    if(!is_array($value)) {
+        $_html_result = '<option label="' . smarty_function_escape_special_chars($value) . '" value="' .
+            smarty_function_escape_special_chars($key) . '"';
+        if (in_array((string)$key, $selected))
+            $_html_result .= ' selected="selected"';
+        $_html_result .= '>' . smarty_function_escape_special_chars($value) . '</option>' . "\n";
+    } else {
+        $_html_result = smarty_function_html_options_optgroup($key, $value, $selected);
+    }
+    return $_html_result;
+}
+
+function smarty_function_html_options_optgroup($key, $values, $selected) {
+    $optgroup_html = '<optgroup label="' . smarty_function_escape_special_chars($key) . '">' . "\n";
+    foreach ($values as $key => $value) {
+        $optgroup_html .= smarty_function_html_options_optoutput($key, $value, $selected);
+    }
+    $optgroup_html .= "</optgroup>\n";
+    return $optgroup_html;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.html_radios.php b/inc/smarty/plugins/function.html_radios.php
new file mode 100644 (file)
index 0000000..7503cfa
--- /dev/null
@@ -0,0 +1,156 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_radios} function plugin
+ *
+ * File:       function.html_radios.php<br>
+ * Type:       function<br>
+ * Name:       html_radios<br>
+ * Date:       24.Feb.2003<br>
+ * Purpose:    Prints out a list of radio input types<br>
+ * Input:<br>
+ *           - name       (optional) - string default "radio"
+ *           - values     (required) - array
+ *           - options    (optional) - associative array
+ *           - checked    (optional) - array default not set
+ *           - separator  (optional) - ie <br> or &nbsp;
+ *           - output     (optional) - the output next to each radio button
+ *           - assign     (optional) - assign the output as an array to this variable
+ * Examples:
+ * <pre>
+ * {html_radios values=$ids output=$names}
+ * {html_radios values=$ids name='box' separator='<br>' output=$names}
+ * {html_radios values=$ids checked=$checked separator='<br>' output=$names}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.html.radios.php {html_radios}
+ *      (Smarty online manual)
+ * @author     Christopher Kvarme <christopher.kvarme@flashjab.com>
+ * @author credits to Monte Ohrt <monte at ohrt dot com>
+ * @version    1.0
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_radios($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+   
+    $name = 'radio';
+    $values = null;
+    $options = null;
+    $selected = null;
+    $separator = '';
+    $labels = true;
+    $label_ids = false;
+    $output = null;
+    $extra = '';
+
+    foreach($params as $_key => $_val) {
+        switch($_key) {
+            case 'name':
+            case 'separator':
+                $$_key = (string)$_val;
+                break;
+
+            case 'checked':
+            case 'selected':
+                if(is_array($_val)) {
+                    $smarty->trigger_error('html_radios: the "' . $_key . '" attribute cannot be an array', E_USER_WARNING);
+                } else {
+                    $selected = (string)$_val;
+                }
+                break;
+
+            case 'labels':
+            case 'label_ids':
+                $$_key = (bool)$_val;
+                break;
+
+            case 'options':
+                $$_key = (array)$_val;
+                break;
+
+            case 'values':
+            case 'output':
+                $$_key = array_values((array)$_val);
+                break;
+
+            case 'radios':
+                $smarty->trigger_error('html_radios: the use of the "radios" attribute is deprecated, use "options" instead', E_USER_WARNING);
+                $options = (array)$_val;
+                break;
+
+            case 'assign':
+                break;
+
+            default:
+                if(!is_array($_val)) {
+                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+                } else {
+                    $smarty->trigger_error("html_radios: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (!isset($options) && !isset($values))
+        return ''; /* raise error here? */
+
+    $_html_result = array();
+
+    if (isset($options)) {
+
+        foreach ($options as $_key=>$_val)
+            $_html_result[] = smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids);
+
+    } else {
+
+        foreach ($values as $_i=>$_key) {
+            $_val = isset($output[$_i]) ? $output[$_i] : '';
+            $_html_result[] = smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids);
+        }
+
+    }
+
+    if(!empty($params['assign'])) {
+        $smarty->assign($params['assign'], $_html_result);
+    } else {
+        return implode("\n",$_html_result);
+    }
+
+}
+
+function smarty_function_html_radios_output($name, $value, $output, $selected, $extra, $separator, $labels, $label_ids) {
+    $_output = '';
+    if ($labels) {
+      if($label_ids) {
+          $_id = smarty_function_escape_special_chars(preg_replace('![^\w\-\.]!', '_', $name . '_' . $value));
+          $_output .= '<label for="' . $_id . '">';
+      } else {
+          $_output .= '<label>';           
+      }
+   }
+   $_output .= '<input type="radio" name="'
+        . smarty_function_escape_special_chars($name) . '" value="'
+        . smarty_function_escape_special_chars($value) . '"';
+
+   if ($labels && $label_ids) $_output .= ' id="' . $_id . '"';
+
+    if ((string)$value==$selected) {
+        $_output .= ' checked="checked"';
+    }
+    $_output .= $extra . ' />' . $output;
+    if ($labels) $_output .= '</label>';
+    $_output .=  $separator;
+
+    return $_output;
+}
+
+?>
diff --git a/inc/smarty/plugins/function.html_select_date.php b/inc/smarty/plugins/function.html_select_date.php
new file mode 100644 (file)
index 0000000..e5eb183
--- /dev/null
@@ -0,0 +1,331 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {html_select_date} plugin
+ *
+ * Type:     function<br>
+ * Name:     html_select_date<br>
+ * Purpose:  Prints the dropdowns for date selection.
+ *
+ * ChangeLog:<br>
+ *           - 1.0 initial release
+ *           - 1.1 added support for +/- N syntax for begin
+ *                and end year values. (Monte)
+ *           - 1.2 added support for yyyy-mm-dd syntax for
+ *                time value. (Jan Rosier)
+ *           - 1.3 added support for choosing format for
+ *                month values (Gary Loescher)
+ *           - 1.3.1 added support for choosing format for
+ *                day values (Marcus Bointon)
+ *           - 1.3.2 support negative timestamps, force year
+ *             dropdown to include given date unless explicitly set (Monte)
+ *           - 1.3.4 fix behaviour of 0000-00-00 00:00:00 dates to match that
+ *             of 0000-00-00 dates (cybot, boots)
+ * @link http://smarty.php.net/manual/en/language.function.html.select.date.php {html_select_date}
+ *      (Smarty online manual)
+ * @version 1.3.4
+ * @author Andrei Zmievski
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_html_select_date($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+    require_once $smarty->_get_plugin_filepath('shared','make_timestamp');
+    require_once $smarty->_get_plugin_filepath('function','html_options');
+    /* Default values. */
+    $prefix          = "Date_";
+    $start_year      = strftime("%Y");
+    $end_year        = $start_year;
+    $display_days    = true;
+    $display_months  = true;
+    $display_years   = true;
+    $month_format    = "%B";
+    /* Write months as numbers by default  GL */
+    $month_value_format = "%m";
+    $day_format      = "%02d";
+    /* Write day values using this format MB */
+    $day_value_format = "%d";
+    $year_as_text    = false;
+    /* Display years in reverse order? Ie. 2000,1999,.... */
+    $reverse_years   = false;
+    /* Should the select boxes be part of an array when returned from PHP?
+       e.g. setting it to "birthday", would create "birthday[Day]",
+       "birthday[Month]" & "birthday[Year]". Can be combined with prefix */
+    $field_array     = null;
+    /* <select size>'s of the different <select> tags.
+       If not set, uses default dropdown. */
+    $day_size        = null;
+    $month_size      = null;
+    $year_size       = null;
+    /* Unparsed attributes common to *ALL* the <select>/<input> tags.
+       An example might be in the template: all_extra ='class ="foo"'. */
+    $all_extra       = null;
+    /* Separate attributes for the tags. */
+    $day_extra       = null;
+    $month_extra     = null;
+    $year_extra      = null;
+    /* Order in which to display the fields.
+       "D" -> day, "M" -> month, "Y" -> year. */
+    $field_order     = 'MDY';
+    /* String printed between the different fields. */
+    $field_separator = "\n";
+    $time = time();
+    $all_empty       = null;
+    $day_empty       = null;
+    $month_empty     = null;
+    $year_empty      = null;
+    $extra_attrs     = '';
+
+    foreach ($params as $_key=>$_value) {
+        switch ($_key) {
+            case 'prefix':
+            case 'time':
+            case 'start_year':
+            case 'end_year':
+            case 'month_format':
+            case 'day_format':
+            case 'day_value_format':
+            case 'field_array':
+            case 'day_size':
+            case 'month_size':
+            case 'year_size':
+            case 'all_extra':
+            case 'day_extra':
+            case 'month_extra':
+            case 'year_extra':
+            case 'field_order':
+            case 'field_separator':
+            case 'month_value_format':
+            case 'month_empty':
+            case 'day_empty':
+            case 'year_empty':
+                $$_key = (string)$_value;
+                break;
+
+            case 'all_empty':
+                $$_key = (string)$_value;
+                $day_empty = $month_empty = $year_empty = $all_empty;
+                break;
+
+            case 'display_days':
+            case 'display_months':
+            case 'display_years':
+            case 'year_as_text':
+            case 'reverse_years':
+                $$_key = (bool)$_value;
+                break;
+
+            default:
+                if(!is_array($_value)) {
+                    $extra_attrs .= ' '.$_key.'="'.smarty_function_escape_special_chars($_value).'"';
+                } else {
+                    $smarty->trigger_error("html_select_date: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (preg_match('!^-\d+$!', $time)) {
+        // negative timestamp, use date()
+        $time = date('Y-m-d', $time);
+    }
+    // If $time is not in format yyyy-mm-dd
+    if (preg_match('/^(\d{0,4}-\d{0,2}-\d{0,2})/', $time, $found)) {
+        $time = $found[1];
+    } else {
+        // use smarty_make_timestamp to get an unix timestamp and
+        // strftime to make yyyy-mm-dd
+        $time = strftime('%Y-%m-%d', smarty_make_timestamp($time));
+    }
+    // Now split this in pieces, which later can be used to set the select
+    $time = explode("-", $time);
+
+    // make syntax "+N" or "-N" work with start_year and end_year
+    if (preg_match('!^(\+|\-)\s*(\d+)$!', $end_year, $match)) {
+        if ($match[1] == '+') {
+            $end_year = strftime('%Y') + $match[2];
+        } else {
+            $end_year = strftime('%Y') - $match[2];
+        }
+    }
+    if (preg_match('!^(\+|\-)\s*(\d+)$!', $start_year, $match)) {
+        if ($match[1] == '+') {
+            $start_year = strftime('%Y') + $match[2];
+        } else {
+            $start_year = strftime('%Y') - $match[2];
+        }
+    }
+    if (strlen($time[0]) > 0) {
+        if ($start_year > $time[0] && !isset($params['start_year'])) {
+            // force start year to include given date if not explicitly set
+            $start_year = $time[0];
+        }
+        if($end_year < $time[0] && !isset($params['end_year'])) {
+            // force end year to include given date if not explicitly set
+            $end_year = $time[0];
+        }
+    }
+
+    $field_order = strtoupper($field_order);
+
+    $html_result = $month_result = $day_result = $year_result = "";
+
+    $field_separator_count = -1;
+    if ($display_months) {
+       $field_separator_count++;
+        $month_names = array();
+        $month_values = array();
+        if(isset($month_empty)) {
+            $month_names[''] = $month_empty;
+            $month_values[''] = '';
+        }
+        for ($i = 1; $i <= 12; $i++) {
+            $month_names[$i] = strftime($month_format, mktime(0, 0, 0, $i, 1, 2000));
+            $month_values[$i] = strftime($month_value_format, mktime(0, 0, 0, $i, 1, 2000));
+        }
+
+        $month_result .= '<select name=';
+        if (null !== $field_array){
+            $month_result .= '"' . $field_array . '[' . $prefix . 'Month]"';
+        } else {
+            $month_result .= '"' . $prefix . 'Month"';
+        }
+        if (null !== $month_size){
+            $month_result .= ' size="' . $month_size . '"';
+        }
+        if (null !== $month_extra){
+            $month_result .= ' ' . $month_extra;
+        }
+        if (null !== $all_extra){
+            $month_result .= ' ' . $all_extra;
+        }
+        $month_result .= $extra_attrs . '>'."\n";
+
+        $month_result .= smarty_function_html_options(array('output'     => $month_names,
+                                                            'values'     => $month_values,
+                                                            'selected'   => (int)$time[1] ? strftime($month_value_format, mktime(0, 0, 0, (int)$time[1], 1, 2000)) : '',
+                                                            'print_result' => false),
+                                                      $smarty);
+        $month_result .= '</select>';
+    }
+
+    if ($display_days) {
+       $field_separator_count++;
+        $days = array();
+        if (isset($day_empty)) {
+            $days[''] = $day_empty;
+            $day_values[''] = '';
+        }
+        for ($i = 1; $i <= 31; $i++) {
+            $days[] = sprintf($day_format, $i);
+            $day_values[] = sprintf($day_value_format, $i);
+        }
+
+        $day_result .= '<select name=';
+        if (null !== $field_array){
+            $day_result .= '"' . $field_array . '[' . $prefix . 'Day]"';
+        } else {
+            $day_result .= '"' . $prefix . 'Day"';
+        }
+        if (null !== $day_size){
+            $day_result .= ' size="' . $day_size . '"';
+        }
+        if (null !== $all_extra){
+            $day_result .= ' ' . $all_extra;
+        }
+        if (null !== $day_extra){
+            $day_result .= ' ' . $day_extra;
+        }
+        $day_result .= $extra_attrs . '>'."\n";
+        $day_result .= smarty_function_html_options(array('output'     => $days,
+                                                          'values'     => $day_values,
+                                                          'selected'   => $time[2],
+                                                          'print_result' => false),
+                                                    $smarty);
+        $day_result .= '</select>';
+    }
+
+    if ($display_years) {
+       $field_separator_count++;
+        if (null !== $field_array){
+            $year_name = $field_array . '[' . $prefix . 'Year]';
+        } else {
+            $year_name = $prefix . 'Year';
+        }
+        if ($year_as_text) {
+            $year_result .= '<input type="text" name="' . $year_name . '" value="' . $time[0] . '" size="4" maxlength="4"';
+            if (null !== $all_extra){
+                $year_result .= ' ' . $all_extra;
+            }
+            if (null !== $year_extra){
+                $year_result .= ' ' . $year_extra;
+            }
+            $year_result .= ' />';
+        } else {
+            $years = range((int)$start_year, (int)$end_year);
+            if ($reverse_years) {
+                rsort($years, SORT_NUMERIC);
+            } else {
+                sort($years, SORT_NUMERIC);
+            }
+            $yearvals = $years;
+            if(isset($year_empty)) {
+                array_unshift($years, $year_empty);
+                array_unshift($yearvals, '');
+            }
+            $year_result .= '<select name="' . $year_name . '"';
+            if (null !== $year_size){
+                $year_result .= ' size="' . $year_size . '"';
+            }
+            if (null !== $all_extra){
+                $year_result .= ' ' . $all_extra;
+            }
+            if (null !== $year_extra){
+                $year_result .= ' ' . $year_extra;
+            }
+            $year_result .= $extra_attrs . '>'."\n";
+            $year_result .= smarty_function_html_options(array('output' => $years,
+                                                               'values' => $yearvals,
+                                                               'selected'   => $time[0],
+                                                               'print_result' => false),
+                                                         $smarty);
+            $year_result .= '</select>';
+        }
+    }
+
+    // Loop thru the field_order field
+    for ($i = 0; $i <= 2; $i++){
+        $c = substr($field_order, $i, 1);
+        switch ($c){
+            case 'D':
+                $html_result .= $day_result;
+                break;
+
+            case 'M':
+                $html_result .= $month_result;
+                break;
+
+            case 'Y':
+                $html_result .= $year_result;
+                break;
+        }
+        // Add the field seperator
+        if($i < $field_separator_count) {
+            $html_result .= $field_separator;
+        }
+    }
+
+    return $html_result;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.html_select_time.php b/inc/smarty/plugins/function.html_select_time.php
new file mode 100644 (file)
index 0000000..2e5be7e
--- /dev/null
@@ -0,0 +1,194 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_select_time} function plugin
+ *
+ * Type:     function<br>
+ * Name:     html_select_time<br>
+ * Purpose:  Prints the dropdowns for time selection
+ * @link http://smarty.php.net/manual/en/language.function.html.select.time.php {html_select_time}
+ *          (Smarty online manual)
+ * @author Roberto Berto <roberto@berto.net>
+ * @credits Monte Ohrt <monte AT ohrt DOT com>
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_make_timestamp()
+ */
+function smarty_function_html_select_time($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','make_timestamp');
+    require_once $smarty->_get_plugin_filepath('function','html_options');
+    /* Default values. */
+    $prefix             = "Time_";
+    $time               = time();
+    $display_hours      = true;
+    $display_minutes    = true;
+    $display_seconds    = true;
+    $display_meridian   = true;
+    $use_24_hours       = true;
+    $minute_interval    = 1;
+    $second_interval    = 1;
+    /* Should the select boxes be part of an array when returned from PHP?
+       e.g. setting it to "birthday", would create "birthday[Hour]",
+       "birthday[Minute]", "birthday[Seconds]" & "birthday[Meridian]".
+       Can be combined with prefix. */
+    $field_array        = null;
+    $all_extra          = null;
+    $hour_extra         = null;
+    $minute_extra       = null;
+    $second_extra       = null;
+    $meridian_extra     = null;
+
+    foreach ($params as $_key=>$_value) {
+        switch ($_key) {
+            case 'prefix':
+            case 'time':
+            case 'field_array':
+            case 'all_extra':
+            case 'hour_extra':
+            case 'minute_extra':
+            case 'second_extra':
+            case 'meridian_extra':
+                $$_key = (string)$_value;
+                break;
+
+            case 'display_hours':
+            case 'display_minutes':
+            case 'display_seconds':
+            case 'display_meridian':
+            case 'use_24_hours':
+                $$_key = (bool)$_value;
+                break;
+
+            case 'minute_interval':
+            case 'second_interval':
+                $$_key = (int)$_value;
+                break;
+
+            default:
+                $smarty->trigger_error("[html_select_time] unknown parameter $_key", E_USER_WARNING);
+        }
+    }
+
+    $time = smarty_make_timestamp($time);
+
+    $html_result = '';
+
+    if ($display_hours) {
+        $hours       = $use_24_hours ? range(0, 23) : range(1, 12);
+        $hour_fmt = $use_24_hours ? '%H' : '%I';
+        for ($i = 0, $for_max = count($hours); $i < $for_max; $i++)
+            $hours[$i] = sprintf('%02d', $hours[$i]);
+        $html_result .= '<select name=';
+        if (null !== $field_array) {
+            $html_result .= '"' . $field_array . '[' . $prefix . 'Hour]"';
+        } else {
+            $html_result .= '"' . $prefix . 'Hour"';
+        }
+        if (null !== $hour_extra){
+            $html_result .= ' ' . $hour_extra;
+        }
+        if (null !== $all_extra){
+            $html_result .= ' ' . $all_extra;
+        }
+        $html_result .= '>'."\n";
+        $html_result .= smarty_function_html_options(array('output'          => $hours,
+                                                           'values'          => $hours,
+                                                           'selected'      => strftime($hour_fmt, $time),
+                                                           'print_result' => false),
+                                                     $smarty);
+        $html_result .= "</select>\n";
+    }
+
+    if ($display_minutes) {
+        $all_minutes = range(0, 59);
+        for ($i = 0, $for_max = count($all_minutes); $i < $for_max; $i+= $minute_interval)
+            $minutes[] = sprintf('%02d', $all_minutes[$i]);
+        $selected = intval(floor(strftime('%M', $time) / $minute_interval) * $minute_interval);
+        $html_result .= '<select name=';
+        if (null !== $field_array) {
+            $html_result .= '"' . $field_array . '[' . $prefix . 'Minute]"';
+        } else {
+            $html_result .= '"' . $prefix . 'Minute"';
+        }
+        if (null !== $minute_extra){
+            $html_result .= ' ' . $minute_extra;
+        }
+        if (null !== $all_extra){
+            $html_result .= ' ' . $all_extra;
+        }
+        $html_result .= '>'."\n";
+        
+        $html_result .= smarty_function_html_options(array('output'          => $minutes,
+                                                           'values'          => $minutes,
+                                                           'selected'      => $selected,
+                                                           'print_result' => false),
+                                                     $smarty);
+        $html_result .= "</select>\n";
+    }
+
+    if ($display_seconds) {
+        $all_seconds = range(0, 59);
+        for ($i = 0, $for_max = count($all_seconds); $i < $for_max; $i+= $second_interval)
+            $seconds[] = sprintf('%02d', $all_seconds[$i]);
+        $selected = intval(floor(strftime('%S', $time) / $second_interval) * $second_interval);
+        $html_result .= '<select name=';
+        if (null !== $field_array) {
+            $html_result .= '"' . $field_array . '[' . $prefix . 'Second]"';
+        } else {
+            $html_result .= '"' . $prefix . 'Second"';
+        }
+        
+        if (null !== $second_extra){
+            $html_result .= ' ' . $second_extra;
+        }
+        if (null !== $all_extra){
+            $html_result .= ' ' . $all_extra;
+        }
+        $html_result .= '>'."\n";
+        
+        $html_result .= smarty_function_html_options(array('output'          => $seconds,
+                                                           'values'          => $seconds,
+                                                           'selected'      => $selected,
+                                                           'print_result' => false),
+                                                     $smarty);
+        $html_result .= "</select>\n";
+    }
+
+    if ($display_meridian && !$use_24_hours) {
+        $html_result .= '<select name=';
+        if (null !== $field_array) {
+            $html_result .= '"' . $field_array . '[' . $prefix . 'Meridian]"';
+        } else {
+            $html_result .= '"' . $prefix . 'Meridian"';
+        }
+        
+        if (null !== $meridian_extra){
+            $html_result .= ' ' . $meridian_extra;
+        }
+        if (null !== $all_extra){
+            $html_result .= ' ' . $all_extra;
+        }
+        $html_result .= '>'."\n";
+        
+        $html_result .= smarty_function_html_options(array('output'          => array('AM', 'PM'),
+                                                           'values'          => array('am', 'pm'),
+                                                           'selected'      => strtolower(strftime('%p', $time)),
+                                                           'print_result' => false),
+                                                     $smarty);
+        $html_result .= "</select>\n";
+    }
+
+    return $html_result;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.html_table.php b/inc/smarty/plugins/function.html_table.php
new file mode 100644 (file)
index 0000000..32aeba8
--- /dev/null
@@ -0,0 +1,177 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_table} function plugin
+ *
+ * Type:     function<br>
+ * Name:     html_table<br>
+ * Date:     Feb 17, 2003<br>
+ * Purpose:  make an html table from an array of data<br>
+ * Input:<br>
+ *         - loop = array to loop through
+ *         - cols = number of columns, comma separated list of column names
+ *                  or array of column names
+ *         - rows = number of rows
+ *         - table_attr = table attributes
+ *         - th_attr = table heading attributes (arrays are cycled)
+ *         - tr_attr = table row attributes (arrays are cycled)
+ *         - td_attr = table cell attributes (arrays are cycled)
+ *         - trailpad = value to pad trailing cells with
+ *         - caption = text for caption element 
+ *         - vdir = vertical direction (default: "down", means top-to-bottom)
+ *         - hdir = horizontal direction (default: "right", means left-to-right)
+ *         - inner = inner loop (default "cols": print $loop line by line,
+ *                   $loop will be printed column by column otherwise)
+ *
+ *
+ * Examples:
+ * <pre>
+ * {table loop=$data}
+ * {table loop=$data cols=4 tr_attr='"bgcolor=red"'}
+ * {table loop=$data cols="first,second,third" tr_attr=$colors}
+ * </pre>
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @author credit to Messju Mohr <messju at lammfellpuschen dot de>
+ * @author credit to boots <boots dot smarty at yahoo dot com>
+ * @version  1.1
+ * @link http://smarty.php.net/manual/en/language.function.html.table.php {html_table}
+ *          (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_html_table($params, &$smarty)
+{
+    $table_attr = 'border="1"';
+    $tr_attr = '';
+    $th_attr = '';
+    $td_attr = '';
+    $cols = $cols_count = 3;
+    $rows = 3;
+    $trailpad = '&nbsp;';
+    $vdir = 'down';
+    $hdir = 'right';
+    $inner = 'cols';
+    $caption = '';
+
+    if (!isset($params['loop'])) {
+        $smarty->trigger_error("html_table: missing 'loop' parameter");
+        return;
+    }
+
+    foreach ($params as $_key=>$_value) {
+        switch ($_key) {
+            case 'loop':
+                $$_key = (array)$_value;
+                break;
+
+            case 'cols':
+                if (is_array($_value) && !empty($_value)) {
+                    $cols = $_value;
+                    $cols_count = count($_value);
+                } elseif (!is_numeric($_value) && is_string($_value) && !empty($_value)) {
+                    $cols = explode(',', $_value);
+                    $cols_count = count($cols);
+                } elseif (!empty($_value)) {
+                    $cols_count = (int)$_value;
+                } else {
+                    $cols_count = $cols;
+                }
+                break;
+
+            case 'rows':
+                $$_key = (int)$_value;
+                break;
+
+            case 'table_attr':
+            case 'trailpad':
+            case 'hdir':
+            case 'vdir':
+            case 'inner':
+            case 'caption':
+                $$_key = (string)$_value;
+                break;
+
+            case 'tr_attr':
+            case 'td_attr':
+            case 'th_attr':
+                $$_key = $_value;
+                break;
+        }
+    }
+
+    $loop_count = count($loop);
+    if (empty($params['rows'])) {
+        /* no rows specified */
+        $rows = ceil($loop_count/$cols_count);
+    } elseif (empty($params['cols'])) {
+        if (!empty($params['rows'])) {
+            /* no cols specified, but rows */
+            $cols_count = ceil($loop_count/$rows);
+        }
+    }
+
+    $output = "<table $table_attr>\n";
+
+    if (!empty($caption)) {
+        $output .= '<caption>' . $caption . "</caption>\n";
+    }
+
+    if (is_array($cols)) {
+        $cols = ($hdir == 'right') ? $cols : array_reverse($cols);
+        $output .= "<thead><tr>\n";
+
+        for ($r=0; $r<$cols_count; $r++) {
+            $output .= '<th' . smarty_function_html_table_cycle('th', $th_attr, $r) . '>';
+            $output .= $cols[$r];
+            $output .= "</th>\n";
+        }
+        $output .= "</tr></thead>\n";
+    }
+
+    $output .= "<tbody>\n";
+    for ($r=0; $r<$rows; $r++) {
+        $output .= "<tr" . smarty_function_html_table_cycle('tr', $tr_attr, $r) . ">\n";
+        $rx =  ($vdir == 'down') ? $r*$cols_count : ($rows-1-$r)*$cols_count;
+
+        for ($c=0; $c<$cols_count; $c++) {
+            $x =  ($hdir == 'right') ? $rx+$c : $rx+$cols_count-1-$c;
+            if ($inner!='cols') {
+                /* shuffle x to loop over rows*/
+                $x = floor($x/$cols_count) + ($x%$cols_count)*$rows;
+            }
+
+            if ($x<$loop_count) {
+                $output .= "<td" . smarty_function_html_table_cycle('td', $td_attr, $c) . ">" . $loop[$x] . "</td>\n";
+            } else {
+                $output .= "<td" . smarty_function_html_table_cycle('td', $td_attr, $c) . ">$trailpad</td>\n";
+            }
+        }
+        $output .= "</tr>\n";
+    }
+    $output .= "</tbody>\n";
+    $output .= "</table>\n";
+    
+    return $output;
+}
+
+function smarty_function_html_table_cycle($name, $var, $no) {
+    if(!is_array($var)) {
+        $ret = $var;
+    } else {
+        $ret = $var[$no % count($var)];
+    }
+    
+    return ($ret) ? ' '.$ret : '';
+}
+
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.mailto.php b/inc/smarty/plugins/function.mailto.php
new file mode 100644 (file)
index 0000000..20e9ed9
--- /dev/null
@@ -0,0 +1,165 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {mailto} function plugin
+ *
+ * Type:     function<br>
+ * Name:     mailto<br>
+ * Date:     May 21, 2002
+ * Purpose:  automate mailto address link creation, and optionally
+ *           encode them.<br>
+ * Input:<br>
+ *         - address = e-mail address
+ *         - text = (optional) text to display, default is address
+ *         - encode = (optional) can be one of:
+ *                * none : no encoding (default)
+ *                * javascript : encode with javascript
+ *                * javascript_charcode : encode with javascript charcode
+ *                * hex : encode with hexidecimal (no javascript)
+ *         - cc = (optional) address(es) to carbon copy
+ *         - bcc = (optional) address(es) to blind carbon copy
+ *         - subject = (optional) e-mail subject
+ *         - newsgroups = (optional) newsgroup(s) to post to
+ *         - followupto = (optional) address(es) to follow up to
+ *         - extra = (optional) extra tags for the href link
+ *
+ * Examples:
+ * <pre>
+ * {mailto address="me@domain.com"}
+ * {mailto address="me@domain.com" encode="javascript"}
+ * {mailto address="me@domain.com" encode="hex"}
+ * {mailto address="me@domain.com" subject="Hello to you!"}
+ * {mailto address="me@domain.com" cc="you@domain.com,they@domain.com"}
+ * {mailto address="me@domain.com" extra='class="mailto"'}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.mailto.php {mailto}
+ *          (Smarty online manual)
+ * @version  1.2
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @author   credits to Jason Sweat (added cc, bcc and subject functionality)
+ * @param    array
+ * @param    Smarty
+ * @return   string
+ */
+function smarty_function_mailto($params, &$smarty)
+{
+    $extra = '';
+
+    if (empty($params['address'])) {
+        $smarty->trigger_error("mailto: missing 'address' parameter");
+        return;
+    } else {
+        $address = $params['address'];
+    }
+
+    $text = $address;
+
+    // netscape and mozilla do not decode %40 (@) in BCC field (bug?)
+    // so, don't encode it.
+    $search = array('%40', '%2C');
+    $replace  = array('@', ',');
+    $mail_parms = array();
+    foreach ($params as $var=>$value) {
+        switch ($var) {
+            case 'cc':
+            case 'bcc':
+            case 'followupto':
+                if (!empty($value))
+                    $mail_parms[] = $var.'='.str_replace($search,$replace,rawurlencode($value));
+                break;
+                
+            case 'subject':
+            case 'newsgroups':
+                $mail_parms[] = $var.'='.rawurlencode($value);
+                break;
+
+            case 'extra':
+            case 'text':
+                $$var = $value;
+
+            default:
+        }
+    }
+
+    $mail_parm_vals = '';
+    for ($i=0; $i<count($mail_parms); $i++) {
+        $mail_parm_vals .= (0==$i) ? '?' : '&';
+        $mail_parm_vals .= $mail_parms[$i];
+    }
+    $address .= $mail_parm_vals;
+
+    $encode = (empty($params['encode'])) ? 'none' : $params['encode'];
+    if (!in_array($encode,array('javascript','javascript_charcode','hex','none')) ) {
+        $smarty->trigger_error("mailto: 'encode' parameter must be none, javascript or hex");
+        return;
+    }
+
+    if ($encode == 'javascript' ) {
+        $string = 'document.write(\'<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>\');';
+
+        $js_encode = '';
+        for ($x=0; $x < strlen($string); $x++) {
+            $js_encode .= '%' . bin2hex($string[$x]);
+        }
+
+        return '<script type="text/javascript">eval(unescape(\''.$js_encode.'\'))</script>';
+
+    } elseif ($encode == 'javascript_charcode' ) {
+        $string = '<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>';
+
+        for($x = 0, $y = strlen($string); $x < $y; $x++ ) {
+            $ord[] = ord($string[$x]);   
+        }
+
+        $_ret = "<script type=\"text/javascript\" language=\"javascript\">\n";
+        $_ret .= "<!--\n";
+        $_ret .= "{document.write(String.fromCharCode(";
+        $_ret .= implode(',',$ord);
+        $_ret .= "))";
+        $_ret .= "}\n";
+        $_ret .= "//-->\n";
+        $_ret .= "</script>\n";
+        
+        return $_ret;
+        
+        
+    } elseif ($encode == 'hex') {
+
+        preg_match('!^(.*)(\?.*)$!',$address,$match);
+        if(!empty($match[2])) {
+            $smarty->trigger_error("mailto: hex encoding does not work with extra attributes. Try javascript.");
+            return;
+        }
+        $address_encode = '';
+        for ($x=0; $x < strlen($address); $x++) {
+            if(preg_match('!\w!',$address[$x])) {
+                $address_encode .= '%' . bin2hex($address[$x]);
+            } else {
+                $address_encode .= $address[$x];
+            }
+        }
+        $text_encode = '';
+        for ($x=0; $x < strlen($text); $x++) {
+            $text_encode .= '&#x' . bin2hex($text[$x]).';';
+        }
+
+        $mailto = "&#109;&#97;&#105;&#108;&#116;&#111;&#58;";
+        return '<a href="'.$mailto.$address_encode.'" '.$extra.'>'.$text_encode.'</a>';
+
+    } else {
+        // no encoding
+        return '<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>';
+
+    }
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.math.php b/inc/smarty/plugins/function.math.php
new file mode 100644 (file)
index 0000000..71672fe
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {math} function plugin
+ *
+ * Type:     function<br>
+ * Name:     math<br>
+ * Purpose:  handle math computations in template<br>
+ * @link http://smarty.php.net/manual/en/language.function.math.php {math}
+ *          (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_math($params, &$smarty)
+{
+    // be sure equation parameter is present
+    if (empty($params['equation'])) {
+        $smarty->trigger_error("math: missing equation parameter");
+        return;
+    }
+
+    $equation = $params['equation'];
+
+    // make sure parenthesis are balanced
+    if (substr_count($equation,"(") != substr_count($equation,")")) {
+        $smarty->trigger_error("math: unbalanced parenthesis");
+        return;
+    }
+
+    // match all vars in equation, make sure all are passed
+    preg_match_all("!(?:0x[a-fA-F0-9]+)|([a-zA-Z][a-zA-Z0-9_]+)!",$equation, $match);
+    $allowed_funcs = array('int','abs','ceil','cos','exp','floor','log','log10',
+                           'max','min','pi','pow','rand','round','sin','sqrt','srand','tan');
+    
+    foreach($match[1] as $curr_var) {
+        if ($curr_var && !in_array($curr_var, array_keys($params)) && !in_array($curr_var, $allowed_funcs)) {
+            $smarty->trigger_error("math: function call $curr_var not allowed");
+            return;
+        }
+    }
+
+    foreach($params as $key => $val) {
+        if ($key != "equation" && $key != "format" && $key != "assign") {
+            // make sure value is not empty
+            if (strlen($val)==0) {
+                $smarty->trigger_error("math: parameter $key is empty");
+                return;
+            }
+            if (!is_numeric($val)) {
+                $smarty->trigger_error("math: parameter $key: is not numeric");
+                return;
+            }
+            $equation = preg_replace("/\b$key\b/", " \$params['$key'] ", $equation);
+        }
+    }
+
+    eval("\$smarty_math_result = ".$equation.";");
+
+    if (empty($params['format'])) {
+        if (empty($params['assign'])) {
+            return $smarty_math_result;
+        } else {
+            $smarty->assign($params['assign'],$smarty_math_result);
+        }
+    } else {
+        if (empty($params['assign'])){
+            printf($params['format'],$smarty_math_result);
+        } else {
+            $smarty->assign($params['assign'],sprintf($params['format'],$smarty_math_result));
+        }
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.popup.php b/inc/smarty/plugins/function.popup.php
new file mode 100644 (file)
index 0000000..3a76b78
--- /dev/null
@@ -0,0 +1,119 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {popup} function plugin
+ *
+ * Type:     function<br>
+ * Name:     popup<br>
+ * Purpose:  make text pop up in windows via overlib
+ * @link http://smarty.php.net/manual/en/language.function.popup.php {popup}
+ *          (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_popup($params, &$smarty)
+{
+    $append = '';
+    foreach ($params as $_key=>$_value) {
+        switch ($_key) {
+            case 'text':
+            case 'trigger':
+            case 'function':
+            case 'inarray':
+                $$_key = (string)$_value;
+                if ($_key == 'function' || $_key == 'inarray')
+                    $append .= ',' . strtoupper($_key) . ",'$_value'";
+                break;
+
+            case 'caption':
+            case 'closetext':
+            case 'status':
+                $append .= ',' . strtoupper($_key) . ",'" . str_replace("'","\'",$_value) . "'";
+                break;
+
+            case 'fgcolor':
+            case 'bgcolor':
+            case 'textcolor':
+            case 'capcolor':
+            case 'closecolor':
+            case 'textfont':
+            case 'captionfont':
+            case 'closefont':
+            case 'fgbackground':
+            case 'bgbackground':
+            case 'caparray':
+            case 'capicon':
+            case 'background':
+            case 'frame':
+                $append .= ',' . strtoupper($_key) . ",'$_value'";
+                break;
+
+            case 'textsize':
+            case 'captionsize':
+            case 'closesize':
+            case 'width':
+            case 'height':
+            case 'border':
+            case 'offsetx':
+            case 'offsety':
+            case 'snapx':
+            case 'snapy':
+            case 'fixx':
+            case 'fixy':
+            case 'padx':
+            case 'pady':
+            case 'timeout':
+            case 'delay':
+                $append .= ',' . strtoupper($_key) . ",$_value";
+                break;
+
+            case 'sticky':
+            case 'left':
+            case 'right':
+            case 'center':
+            case 'above':
+            case 'below':
+            case 'noclose':
+            case 'autostatus':
+            case 'autostatuscap':
+            case 'fullhtml':
+            case 'hauto':
+            case 'vauto':
+            case 'mouseoff':
+            case 'followmouse':
+            case 'closeclick':
+                if ($_value) $append .= ',' . strtoupper($_key);
+                break;
+
+            default:
+                $smarty->trigger_error("[popup] unknown parameter $_key", E_USER_WARNING);
+        }
+    }
+
+    if (empty($text) && !isset($inarray) && empty($function)) {
+        $smarty->trigger_error("overlib: attribute 'text' or 'inarray' or 'function' required");
+        return false;
+    }
+
+    if (empty($trigger)) { $trigger = "onmouseover"; }
+
+    $retval = $trigger . '="return overlib(\''.preg_replace(array("!'!","![\r\n]!"),array("\'",'\r'),$text).'\'';
+    $retval .= $append . ');"';
+    if ($trigger == 'onmouseover')
+       $retval .= ' onmouseout="nd();"';
+
+
+    return $retval;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/function.popup_init.php b/inc/smarty/plugins/function.popup_init.php
new file mode 100644 (file)
index 0000000..93cb454
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {popup_init} function plugin
+ *
+ * Type:     function<br>
+ * Name:     popup_init<br>
+ * Purpose:  initialize overlib
+ * @link http://smarty.php.net/manual/en/language.function.popup.init.php {popup_init}
+ *          (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_popup_init($params, &$smarty)
+{
+    $zindex = 1000;
+    
+    if (!empty($params['zindex'])) {
+        $zindex = $params['zindex'];
+    }
+    
+    if (!empty($params['src'])) {
+        return '<div id="overDiv" style="position:absolute; visibility:hidden; z-index:'.$zindex.';"></div>' . "\n"
+         . '<script type="text/javascript" language="JavaScript" src="'.$params['src'].'"></script>' . "\n";
+    } else {
+        $smarty->trigger_error("popup_init: missing src parameter");
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.capitalize.php b/inc/smarty/plugins/modifier.capitalize.php
new file mode 100644 (file)
index 0000000..4a611d9
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty capitalize modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     capitalize<br>
+ * Purpose:  capitalize words in the string
+ * @link http://smarty.php.net/manual/en/language.modifiers.php#LANGUAGE.MODIFIER.CAPITALIZE
+ *      capitalize (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @return string
+ */
+function smarty_modifier_capitalize($string, $uc_digits = false)
+{
+    smarty_modifier_capitalize_ucfirst(null, $uc_digits);
+    return preg_replace_callback('!\'?\b\w(\w|\')*\b!', 'smarty_modifier_capitalize_ucfirst', $string);
+}
+
+function smarty_modifier_capitalize_ucfirst($string, $uc_digits = null)
+{
+    static $_uc_digits = false;
+    
+    if(isset($uc_digits)) {
+        $_uc_digits = $uc_digits;
+        return;
+    }
+    
+    if(substr($string[0],0,1) != "'" && !preg_match("!\d!",$string[0]) || $_uc_digits)
+        return ucfirst($string[0]);
+    else
+        return $string[0];
+}
+
+
+?>
diff --git a/inc/smarty/plugins/modifier.cat.php b/inc/smarty/plugins/modifier.cat.php
new file mode 100644 (file)
index 0000000..2e37940
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty cat modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     cat<br>
+ * Date:     Feb 24, 2003
+ * Purpose:  catenate a value to a variable
+ * Input:    string to catenate
+ * Example:  {$var|cat:"foo"}
+ * @link http://smarty.php.net/manual/en/language.modifier.cat.php cat
+ *          (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @version 1.0
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_cat($string, $cat)
+{
+    return $string . $cat;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.count_characters.php b/inc/smarty/plugins/modifier.count_characters.php
new file mode 100644 (file)
index 0000000..5ed9a87
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty count_characters modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     count_characteres<br>
+ * Purpose:  count the number of characters in a text
+ * @link http://smarty.php.net/manual/en/language.modifier.count.characters.php
+ *          count_characters (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @param boolean include whitespace in the character count
+ * @return integer
+ */
+function smarty_modifier_count_characters($string, $include_spaces = false)
+{
+    if ($include_spaces)
+       return(strlen($string));
+
+    return preg_match_all("/[^\s]/",$string, $match);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.count_paragraphs.php b/inc/smarty/plugins/modifier.count_paragraphs.php
new file mode 100644 (file)
index 0000000..e0e274d
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty count_paragraphs modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     count_paragraphs<br>
+ * Purpose:  count the number of paragraphs in a text
+ * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php
+ *          count_paragraphs (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @return integer
+ */
+function smarty_modifier_count_paragraphs($string)
+{
+    // count \r or \n characters
+    return count(preg_split('/[\r\n]+/', $string));
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.count_sentences.php b/inc/smarty/plugins/modifier.count_sentences.php
new file mode 100644 (file)
index 0000000..f66ea17
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty count_sentences modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     count_sentences
+ * Purpose:  count the number of sentences in a text
+ * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php
+ *          count_sentences (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @return integer
+ */
+function smarty_modifier_count_sentences($string)
+{
+    // find periods with a word before but not after.
+    return preg_match_all('/[^\s]\.(?!\w)/', $string, $match);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.count_words.php b/inc/smarty/plugins/modifier.count_words.php
new file mode 100644 (file)
index 0000000..9d339f5
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty count_words modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     count_words<br>
+ * Purpose:  count the number of words in a text
+ * @link http://smarty.php.net/manual/en/language.modifier.count.words.php
+ *          count_words (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @return integer
+ */
+function smarty_modifier_count_words($string)
+{
+    // split text by ' ',\r,\n,\f,\t
+    $split_array = preg_split('/\s+/',$string);
+    // count matches that contain alphanumerics
+    $word_count = preg_grep('/[a-zA-Z0-9\\x80-\\xff]/', $split_array);
+
+    return count($word_count);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.csv.php b/inc/smarty/plugins/modifier.csv.php
new file mode 100644 (file)
index 0000000..4c715c4
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty csv modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     csv<br>
+ * Purpose:  format string for CSV output
+ * @author Andreas Gohr <gohr@cosmocode.de>
+ * @param string
+ * @return string
+ */
+function smarty_modifier_csv($string)
+{
+    return '"'.strtr(trim($string),'"','""').'"';
+}
+
+?>
diff --git a/inc/smarty/plugins/modifier.date_format.php b/inc/smarty/plugins/modifier.date_format.php
new file mode 100644 (file)
index 0000000..8cf7d5e
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Include the {@link shared.make_timestamp.php} plugin
+ */
+require_once $smarty->_get_plugin_filepath('shared', 'make_timestamp');
+/**
+ * Smarty date_format modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     date_format<br>
+ * Purpose:  format datestamps via strftime<br>
+ * Input:<br>
+ *         - string: input date string
+ *         - format: strftime format for output
+ *         - default_date: default date if $string is empty
+ * @link http://smarty.php.net/manual/en/language.modifier.date.format.php
+ *          date_format (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @param string
+ * @param string
+ * @return string|void
+ * @uses smarty_make_timestamp()
+ */
+function smarty_modifier_date_format($string, $format = '%b %e, %Y', $default_date = '')
+{
+    if ($string != '') {
+        $timestamp = smarty_make_timestamp($string);
+    } elseif ($default_date != '') {
+        $timestamp = smarty_make_timestamp($default_date);
+    } else {
+        return;
+    }
+    if (DIRECTORY_SEPARATOR == '\\') {
+        $_win_from = array('%D',       '%h', '%n', '%r',          '%R',    '%t', '%T');
+        $_win_to   = array('%m/%d/%y', '%b', "\n", '%I:%M:%S %p', '%H:%M', "\t", '%H:%M:%S');
+        if (strpos($format, '%e') !== false) {
+            $_win_from[] = '%e';
+            $_win_to[]   = sprintf('%\' 2d', date('j', $timestamp));
+        }
+        if (strpos($format, '%l') !== false) {
+            $_win_from[] = '%l';
+            $_win_to[]   = sprintf('%\' 2d', date('h', $timestamp));
+        }
+        $format = str_replace($_win_from, $_win_to, $format);
+    }
+    return strftime($format, $timestamp);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.debug_print_var.php b/inc/smarty/plugins/modifier.debug_print_var.php
new file mode 100644 (file)
index 0000000..e4f7bc0
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty debug_print_var modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     debug_print_var<br>
+ * Purpose:  formats variable contents for display in the console
+ * @link http://smarty.php.net/manual/en/language.modifier.debug.print.var.php
+ *          debug_print_var (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param array|object
+ * @param integer
+ * @param integer
+ * @return string
+ */
+function smarty_modifier_debug_print_var($var, $depth = 0, $length = 40)
+{
+    $_replace = array(
+        "\n" => '<i>\n</i>',
+        "\r" => '<i>\r</i>',
+        "\t" => '<i>\t</i>'
+    );
+
+    switch (gettype($var)) {
+        case 'array' :
+            $results = '<b>Array (' . count($var) . ')</b>';
+            foreach ($var as $curr_key => $curr_val) {
+                $results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
+                    . '<b>' . strtr($curr_key, $_replace) . '</b> =&gt; '
+                    . smarty_modifier_debug_print_var($curr_val, ++$depth, $length);
+                    $depth--;
+            }
+            break;
+        case 'object' :
+            $object_vars = get_object_vars($var);
+            $results = '<b>' . get_class($var) . ' Object (' . count($object_vars) . ')</b>';
+            foreach ($object_vars as $curr_key => $curr_val) {
+                $results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
+                    . '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '
+                    . smarty_modifier_debug_print_var($curr_val, ++$depth, $length);
+                    $depth--;
+            }
+            break;
+        case 'boolean' :
+        case 'NULL' :
+        case 'resource' :
+            if (true === $var) {
+                $results = 'true';
+            } elseif (false === $var) {
+                $results = 'false';
+            } elseif (null === $var) {
+                $results = 'null';
+            } else {
+                $results = htmlspecialchars((string) $var);
+            }
+            $results = '<i>' . $results . '</i>';
+            break;
+        case 'integer' :
+        case 'float' :
+            $results = htmlspecialchars((string) $var);
+            break;
+        case 'string' :
+            $results = strtr($var, $_replace);
+            if (strlen($var) > $length ) {
+                $results = substr($var, 0, $length - 3) . '...';
+            }
+            $results = htmlspecialchars('"' . $results . '"');
+            break;
+        case 'unknown type' :
+        default :
+            $results = strtr((string) $var, $_replace);
+            if (strlen($results) > $length ) {
+                $results = substr($results, 0, $length - 3) . '...';
+            }
+            $results = htmlspecialchars($results);
+    }
+
+    return $results;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.default.php b/inc/smarty/plugins/modifier.default.php
new file mode 100644 (file)
index 0000000..70011fd
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty default modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     default<br>
+ * Purpose:  designate default value for empty variables
+ * @link http://smarty.php.net/manual/en/language.modifier.default.php
+ *          default (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_default($string, $default = '')
+{
+    if (!isset($string) || $string === '')
+        return $default;
+    else
+        return $string;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.escape.php b/inc/smarty/plugins/modifier.escape.php
new file mode 100644 (file)
index 0000000..a2f52b2
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty escape modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     escape<br>
+ * Purpose:  Escape the string according to escapement type
+ * @link http://smarty.php.net/manual/en/language.modifier.escape.php
+ *          escape (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @param html|htmlall|url|quotes|hex|hexentity|javascript
+ * @return string
+ */
+function smarty_modifier_escape($string, $esc_type = 'html', $char_set = 'ISO-8859-1')
+{
+    switch ($esc_type) {
+        case 'html':
+            return htmlspecialchars($string, ENT_QUOTES, $char_set);
+
+        case 'htmlall':
+            return htmlentities($string, ENT_QUOTES, $char_set);
+
+        case 'url':
+            return rawurlencode($string);
+
+        case 'urlpathinfo':
+            return str_replace('%2F','/',rawurlencode($string));
+            
+        case 'quotes':
+            // escape unescaped single quotes
+            return preg_replace("%(?<!\\\\)'%", "\\'", $string);
+
+        case 'hex':
+            // escape every character into hex
+            $return = '';
+            for ($x=0; $x < strlen($string); $x++) {
+                $return .= '%' . bin2hex($string[$x]);
+            }
+            return $return;
+            
+        case 'hexentity':
+            $return = '';
+            for ($x=0; $x < strlen($string); $x++) {
+                $return .= '&#x' . bin2hex($string[$x]) . ';';
+            }
+            return $return;
+
+        case 'decentity':
+            $return = '';
+            for ($x=0; $x < strlen($string); $x++) {
+                $return .= '&#' . ord($string[$x]) . ';';
+            }
+            return $return;
+
+        case 'javascript':
+            // escape quotes and backslashes, newlines, etc.
+            return strtr($string, array('\\'=>'\\\\',"'"=>"\\'",'"'=>'\\"',"\r"=>'\\r',"\n"=>'\\n','</'=>'<\/'));
+            
+        case 'mail':
+            // safe way to display e-mail address on a web page
+            return str_replace(array('@', '.'),array(' [AT] ', ' [DOT] '), $string);
+            
+        case 'nonstd':
+           // escape non-standard chars, such as ms document quotes
+           $_res = '';
+           for($_i = 0, $_len = strlen($string); $_i < $_len; $_i++) {
+               $_ord = ord(substr($string, $_i, 1));
+               // non-standard char, escape it
+               if($_ord >= 126){
+                   $_res .= '&#' . $_ord . ';';
+               }
+               else {
+                   $_res .= substr($string, $_i, 1);
+               }
+           }
+           return $_res;
+
+        default:
+            return $string;
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.indent.php b/inc/smarty/plugins/modifier.indent.php
new file mode 100644 (file)
index 0000000..394147a
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty indent modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     indent<br>
+ * Purpose:  indent lines of text
+ * @link http://smarty.php.net/manual/en/language.modifier.indent.php
+ *          indent (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @param integer
+ * @param string
+ * @return string
+ */
+function smarty_modifier_indent($string,$chars=4,$char=" ")
+{
+    return preg_replace('!^!m',str_repeat($char,$chars),$string);
+}
+
+?>
diff --git a/inc/smarty/plugins/modifier.lower.php b/inc/smarty/plugins/modifier.lower.php
new file mode 100644 (file)
index 0000000..20e7a8d
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty lower modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     lower<br>
+ * Purpose:  convert string to lowercase
+ * @link http://smarty.php.net/manual/en/language.modifier.lower.php
+ *          lower (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @return string
+ */
+function smarty_modifier_lower($string)
+{
+    return strtolower($string);
+}
+
+?>
diff --git a/inc/smarty/plugins/modifier.nl2br.php b/inc/smarty/plugins/modifier.nl2br.php
new file mode 100644 (file)
index 0000000..d6fabff
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty plugin
+ *
+ * Type:     modifier<br>
+ * Name:     nl2br<br>
+ * Date:     Feb 26, 2003
+ * Purpose:  convert \r\n, \r or \n to <<br>>
+ * Input:<br>
+ *         - contents = contents to replace
+ *         - preceed_test = if true, includes preceeding break tags
+ *           in replacement
+ * Example:  {$text|nl2br}
+ * @link http://smarty.php.net/manual/en/language.modifier.nl2br.php
+ *          nl2br (Smarty online manual)
+ * @version  1.0
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @return string
+ */
+function smarty_modifier_nl2br($string)
+{
+    return nl2br($string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.noteparser.php b/inc/smarty/plugins/modifier.noteparser.php
new file mode 100644 (file)
index 0000000..0f96f00
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty plugin
+ *
+ * Type:     modifier
+ * Name:     noteparser
+ * Date:     Feb 26, 2003
+ * Purpose:  Converts plaintext notes to richer HTML (very simple)
+ * Example:  {$entry.note|noteparser}
+ * @author   Andreas Gohr <gohr@cosmocode.de>
+ * @param string
+ * @return string
+ */
+function smarty_modifier_noteparser($string){
+    $string = htmlspecialchars($string);
+
+    $string = preg_replace('!\*\*Call\*\*!i','<img src="pix/phone.png" width="16" height="16" alt="Call" />',$string);
+    $string = preg_replace('!\*\*ToDo\*\*!i','<img src="pix/arrow_right.png" width="16" height="16" alt="ToDo" />',$string);
+    $string = preg_replace('!\*\*Mail\*\*!i','<img src="pix/email.png" width="16" height="16" alt="Mail" />',$string);
+    $string = preg_replace('!\*\*Note\*\*!i','<img src="pix/note.png" width="16" height="16" alt="note" />',$string);
+
+    $string = preg_replace('!\*\*(.*?)\*\*!','<b>\\1</b>',$string);
+    $string = preg_replace('!__(.*?)__!','<u>\\1</u>',$string);
+    $string = preg_replace('!//(.*?)//!','<i>\\1</i>',$string);
+
+    $string = preg_replace('!(https?://[\w;/?:@&=+$\-_.\!~*\\\']+)!i',
+                           '<a href="\\1">\\1</a>',$string);
+
+    $string = preg_replace('!\n\n+!','</p><p>',$string);
+    $string = nl2br($string);
+
+    return '<p>'.$string.'</p>';
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.regex_replace.php b/inc/smarty/plugins/modifier.regex_replace.php
new file mode 100644 (file)
index 0000000..d4d2030
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty regex_replace modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     regex_replace<br>
+ * Purpose:  regular expression search/replace
+ * @link http://smarty.php.net/manual/en/language.modifier.regex.replace.php
+ *          regex_replace (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @param string|array
+ * @param string|array
+ * @return string
+ */
+function smarty_modifier_regex_replace($string, $search, $replace)
+{
+    if (preg_match('!([a-zA-Z\s]+)$!s', $search, $match) && (strpos($match[1], 'e') !== false)) {
+        /* remove eval-modifier from $search */
+        $search = substr($search, 0, -strlen($match[1])) . preg_replace('![e\s]+!', '', $match[1]);
+    }
+       
+    return preg_replace($search, $replace, $string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.replace.php b/inc/smarty/plugins/modifier.replace.php
new file mode 100644 (file)
index 0000000..df041c8
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty replace modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     replace<br>
+ * Purpose:  simple search/replace
+ * @link http://smarty.php.net/manual/en/language.modifier.replace.php
+ *          replace (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_replace($string, $search, $replace)
+{
+    return str_replace($search, $replace, $string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.spacify.php b/inc/smarty/plugins/modifier.spacify.php
new file mode 100644 (file)
index 0000000..c2423f4
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty spacify modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     spacify<br>
+ * Purpose:  add spaces between characters in a string
+ * @link http://smarty.php.net/manual/en/language.modifier.spacify.php
+ *          spacify (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_spacify($string, $spacify_char = ' ')
+{
+    return implode($spacify_char,
+                   preg_split('//', $string, -1, PREG_SPLIT_NO_EMPTY));
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.string_format.php b/inc/smarty/plugins/modifier.string_format.php
new file mode 100644 (file)
index 0000000..9e051a5
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty string_format modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     string_format<br>
+ * Purpose:  format strings via sprintf
+ * @link http://smarty.php.net/manual/en/language.modifier.string.format.php
+ *          string_format (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_string_format($string, $format)
+{
+    return sprintf($format, $string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.strip.php b/inc/smarty/plugins/modifier.strip.php
new file mode 100644 (file)
index 0000000..cc5c453
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty strip modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     strip<br>
+ * Purpose:  Replace all repeated spaces, newlines, tabs
+ *           with a single space or supplied replacement string.<br>
+ * Example:  {$var|strip} {$var|strip:"&nbsp;"}
+ * Date:     September 25th, 2002
+ * @link http://smarty.php.net/manual/en/language.modifier.strip.php
+ *          strip (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @version  1.0
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_strip($text, $replace = ' ')
+{
+    return preg_replace('!\s+!', $replace, $text);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.strip_tags.php b/inc/smarty/plugins/modifier.strip_tags.php
new file mode 100644 (file)
index 0000000..93011a8
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty strip_tags modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     strip_tags<br>
+ * Purpose:  strip html tags from text
+ * @link http://smarty.php.net/manual/en/language.modifier.strip.tags.php
+ *          strip_tags (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @param boolean
+ * @return string
+ */
+function smarty_modifier_strip_tags($string, $replace_with_space = true)
+{
+    if ($replace_with_space)
+        return preg_replace('!<[^>]*?>!', ' ', $string);
+    else
+        return strip_tags($string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.truncate.php b/inc/smarty/plugins/modifier.truncate.php
new file mode 100644 (file)
index 0000000..35c8969
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty truncate modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     truncate<br>
+ * Purpose:  Truncate a string to a certain length if necessary,
+ *           optionally splitting in the middle of a word, and
+ *           appending the $etc string or inserting $etc into the middle.
+ * @link http://smarty.php.net/manual/en/language.modifier.truncate.php
+ *          truncate (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @param integer
+ * @param string
+ * @param boolean
+ * @param boolean
+ * @return string
+ */
+function smarty_modifier_truncate($string, $length = 80, $etc = '...',
+                                  $break_words = false, $middle = false)
+{
+    if ($length == 0)
+        return '';
+
+    if (strlen($string) > $length) {
+        $length -= min($length, strlen($etc));
+        if (!$break_words && !$middle) {
+            $string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length+1));
+        }
+        if(!$middle) {
+            return substr($string, 0, $length) . $etc;
+        } else {
+            return substr($string, 0, $length/2) . $etc . substr($string, -$length/2);
+        }
+    } else {
+        return $string;
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/modifier.upper.php b/inc/smarty/plugins/modifier.upper.php
new file mode 100644 (file)
index 0000000..c12480f
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty upper modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     upper<br>
+ * Purpose:  convert string to uppercase
+ * @link http://smarty.php.net/manual/en/language.modifier.upper.php
+ *          upper (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @return string
+ */
+function smarty_modifier_upper($string)
+{
+    return strtoupper($string);
+}
+
+?>
diff --git a/inc/smarty/plugins/modifier.wordwrap.php b/inc/smarty/plugins/modifier.wordwrap.php
new file mode 100644 (file)
index 0000000..ce07181
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty wordwrap modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     wordwrap<br>
+ * Purpose:  wrap a string of text at a given length
+ * @link http://smarty.php.net/manual/en/language.modifier.wordwrap.php
+ *          wordwrap (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @param integer
+ * @param string
+ * @param boolean
+ * @return string
+ */
+function smarty_modifier_wordwrap($string,$length=80,$break="\n",$cut=false)
+{
+    return wordwrap($string,$length,$break,$cut);
+}
+
+?>
diff --git a/inc/smarty/plugins/outputfilter.trimwhitespace.php b/inc/smarty/plugins/outputfilter.trimwhitespace.php
new file mode 100644 (file)
index 0000000..97b0d21
--- /dev/null
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty trimwhitespace outputfilter plugin
+ *
+ * File:     outputfilter.trimwhitespace.php<br>
+ * Type:     outputfilter<br>
+ * Name:     trimwhitespace<br>
+ * Date:     Jan 25, 2003<br>
+ * Purpose:  trim leading white space and blank lines from
+ *           template source after it gets interpreted, cleaning
+ *           up code and saving bandwidth. Does not affect
+ *           <<PRE>></PRE> and <SCRIPT></SCRIPT> blocks.<br>
+ * Install:  Drop into the plugin directory, call
+ *           <code>$smarty->load_filter('output','trimwhitespace');</code>
+ *           from application.
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @author Contributions from Lars Noschinski <lars@usenet.noschinski.de>
+ * @version  1.3
+ * @param string
+ * @param Smarty
+ */
+function smarty_outputfilter_trimwhitespace($source, &$smarty)
+{
+    // Pull out the script blocks
+    preg_match_all("!<script[^>]+>.*?</script>!is", $source, $match);
+    $_script_blocks = $match[0];
+    $source = preg_replace("!<script[^>]+>.*?</script>!is",
+                           '@@@SMARTY:TRIM:SCRIPT@@@', $source);
+
+    // Pull out the pre blocks
+    preg_match_all("!<pre>.*?</pre>!is", $source, $match);
+    $_pre_blocks = $match[0];
+    $source = preg_replace("!<pre>.*?</pre>!is",
+                           '@@@SMARTY:TRIM:PRE@@@', $source);
+
+    // Pull out the textarea blocks
+    preg_match_all("!<textarea[^>]+>.*?</textarea>!is", $source, $match);
+    $_textarea_blocks = $match[0];
+    $source = preg_replace("!<textarea[^>]+>.*?</textarea>!is",
+                           '@@@SMARTY:TRIM:TEXTAREA@@@', $source);
+
+    // remove all leading spaces, tabs and carriage returns NOT
+    // preceeded by a php close tag.
+    $source = trim(preg_replace('/((?<!\?>)\n)[\s]+/m', '\1', $source));
+
+    // replace textarea blocks
+    smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:TEXTAREA@@@",$_textarea_blocks, $source);
+
+    // replace pre blocks
+    smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:PRE@@@",$_pre_blocks, $source);
+
+    // replace script blocks
+    smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:SCRIPT@@@",$_script_blocks, $source);
+
+    return $source;
+}
+
+function smarty_outputfilter_trimwhitespace_replace($search_str, $replace, &$subject) {
+    $_len = strlen($search_str);
+    $_pos = 0;
+    for ($_i=0, $_count=count($replace); $_i<$_count; $_i++)
+        if (($_pos=strpos($subject, $search_str, $_pos))!==false)
+            $subject = substr_replace($subject, $replace[$_i], $_pos, $_len);
+        else
+            break;
+
+}
+
+?>
diff --git a/inc/smarty/plugins/shared.escape_special_chars.php b/inc/smarty/plugins/shared.escape_special_chars.php
new file mode 100644 (file)
index 0000000..c07ce31
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Smarty shared plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * escape_special_chars common function
+ *
+ * Function: smarty_function_escape_special_chars<br>
+ * Purpose:  used by other smarty functions to escape
+ *           special chars except for already escaped ones
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @return string
+ */
+function smarty_function_escape_special_chars($string)
+{
+    if(!is_array($string)) {
+        $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string);
+        $string = htmlspecialchars($string);
+        $string = str_replace(array('%%%SMARTY_START%%%','%%%SMARTY_END%%%'), array('&',';'), $string);
+    }
+    return $string;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/smarty/plugins/shared.make_timestamp.php b/inc/smarty/plugins/shared.make_timestamp.php
new file mode 100644 (file)
index 0000000..b42eb11
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Smarty shared plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Function: smarty_make_timestamp<br>
+ * Purpose:  used by other smarty functions to make a timestamp
+ *           from a string.
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @return string
+ */
+function smarty_make_timestamp($string)
+{
+    if(empty($string)) {
+        // use "now":
+        $time = time();
+
+    } elseif (preg_match('/^\d{14}$/', $string)) {
+        // it is mysql timestamp format of YYYYMMDDHHMMSS?            
+        $time = mktime(substr($string, 8, 2),substr($string, 10, 2),substr($string, 12, 2),
+                       substr($string, 4, 2),substr($string, 6, 2),substr($string, 0, 4));
+        
+    } elseif (is_numeric($string)) {
+        // it is a numeric string, we handle it as timestamp
+        $time = (int)$string;
+        
+    } else {
+        // strtotime should handle it
+        $time = strtotime($string);
+        if ($time == -1 || $time === false) {
+            // strtotime() was not able to parse $string, use "now":
+            $time = time();
+        }
+    }
+    return $time;
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/inc/template.php b/inc/template.php
new file mode 100644 (file)
index 0000000..c5e850e
--- /dev/null
@@ -0,0 +1,283 @@
+<?
+
+/**
+ * assigns some standard variables to smarty templates
+ */
+function tpl_std(){
+  global $smarty;
+  global $lang;
+  global $conf;
+  global $FIELDS;
+
+  if(empty($_SESSION['ldapab']['username'])){
+    $_SESSION['ldapab']['username'] = '';
+  }
+  if(empty($_SESSION['ldapab']['binddn'])){
+    $_SESSION['ldapab']['binddn'] = '';
+  }
+
+  $smarty->assign('user',$_SESSION['ldapab']['username']);
+  $smarty->assign('binddn',$_SESSION['ldapab']['binddn']);
+  if(!empty($_SESSION['ldapab']['lastlocation'])){
+    $smarty->assign('home',$_SESSION['ldapab']['lastlocation']);
+  }else{
+     $smarty->assign('home','index.php');
+  }
+  $smarty->assign('conf',$conf);
+  $smarty->assign('lang',$lang);
+  $smarty->assign('fields',$FIELDS);
+}
+
+/**
+ * assigns all the interesting data from an ldap result to
+ * the smarty template
+ */
+function tpl_entry($in){
+  global $smarty;
+  global $conf;
+  global $RFIELDS;
+
+  $out=array();
+
+  // handle named entries
+  foreach($RFIELDS as $key => $name){
+    if(empty($in[$key])) continue;
+
+    // keep arrays for multi fields
+    if($name{0} == '_'){
+        $name  = substr($name,1);
+        if(is_array($in[$key])){
+            $out[$name] = $in[$key];
+        }else{
+            $out[$name] = array($in[$key]);
+        }
+    }else{
+        if(is_array($in[$key])){
+            $out[$name] = $in[$key][0];
+        }else{
+            $out[$name] = $in[$key];
+        }
+    }
+  }
+
+  // set the type
+  if (empty($out['dn'])) { $out['dn']=''; }
+  $out['dn']          = normalize_dn($out['dn']);
+  $conf['publicbook'] = normalize_dn($conf['publicbook']);
+  if($out['dn']){
+      if(strstr($out['dn'],$conf['publicbook'])){
+          $out['type'] = 'public';
+      }else{
+          $out['type'] = 'private';
+      }
+  }
+
+  // join marker field to markers
+  if(is_array($out['marker'])) $out['markers'] = join(', ',$out['marker']);
+
+/*
+print '<pre>';
+print_r($out);
+print '</pre>';
+*/
+
+  $smarty->assign('entry',$out);
+}
+
+/**
+ * assigns the last LDAP error to the template
+ */
+function tpl_ldaperror($message=""){
+  global $LDAP_CON;
+  global $__LDAPERROR__;
+  global $smarty;
+  $errno = ldap_errno($LDAP_CON);
+  if($errno){
+    $__LDAPERROR__ .= ldap_err2str($errno);
+    if(!empty($message)){
+      $__LDAPERROR__ .= "($message)";
+    }
+    $__LDAPERROR__ .= '\n';
+  }
+  $smarty->assign("LDAPERRORS",$__LDAPERROR__);
+}
+
+/**
+ * assigns all markers to the template
+ */
+function tpl_markers(){
+  global $conf;
+  global $LDAP_CON;
+  global $smarty;
+
+  if(!$conf['extended']) return;
+
+  $markers = array();
+
+  $sr = ldap_list($LDAP_CON,$conf['publicbook'],"ObjectClass=inetOrgPerson",array("marker"));
+  $result1 = ldap_get_binentries($LDAP_CON, $sr);
+  //check users private addressbook
+  if(!empty($_SESSION['ldapab']['binddn'])){
+    $sr = @ldap_list($LDAP_CON,
+                    $conf['privatebook'].','.$_SESSION['ldapab']['binddn'],
+                    "ObjectClass=inetOrgPerson",array("marker"));
+    $result2 = ldap_get_binentries($LDAP_CON, $sr);
+  }else{
+    $result2 = '';
+  }
+  $result = array_merge((array)$result1,(array)$result2);
+
+  if(count($result)){
+    foreach ($result as $entry){
+      if(!empty($entry['marker']) && count($entry['marker'])){
+        foreach($entry['marker'] as $marker){
+          array_push($markers, $marker);
+        }
+      }
+    }
+  }
+  $markers = array_unique($markers);
+  sort($markers,SORT_STRING);
+
+  $smarty->assign('markers',$markers);
+}
+
+/**
+ * Assigns all distinct organization names to the template
+ */
+function tpl_orgs(){
+  global $conf;
+  global $LDAP_CON;
+  global $smarty;
+  global $FIELDS;
+
+  $orgs = array();
+  $result = ldap_queryabooks("ObjectClass=inetOrgPerson",array($FIELDS['organization']));
+
+  if(count($result)){
+    foreach ($result as $entry){
+      if(!empty($entry[$FIELDS['organization']][0])){
+        array_push($orgs, $entry[$FIELDS['organization']][0]);
+      }
+    }
+  }
+  $orgs = array_unique($orgs);
+  natcasesort($orgs);
+  $smarty->assign('orgs',$orgs);
+}
+
+/**
+ * assigns all categories to the template
+ */
+function tpl_categories(){
+  global $conf;
+  global $LDAP_CON;
+  global $smarty;
+
+  if(!$conf['openxchange']) return;
+
+  $categories = array();
+
+  $sr = ldap_list($LDAP_CON,$conf['publicbook'],"ObjectClass=OXUserObject",array("OXUserCategories"));
+  $result1 = ldap_get_binentries($LDAP_CON, $sr);
+  //check users private addressbook
+  if(!empty($_SESSION['ldapab']['binddn'])){
+    $sr = @ldap_list($LDAP_CON,
+                    $conf['privatebook'].','.$_SESSION['ldapab']['binddn'],
+                    "ObjectClass=OXUserObject",array("OXUserCategories"));
+    $result2 = ldap_get_binentries($LDAP_CON, $sr);
+  }
+  $result = array_merge((array)$result1,(array)$result2);
+
+  if(count($result)){
+    foreach ($result as $entry){
+      if(count($entry['OXUserCategories'])){
+        foreach($entry['OXUserCategories'] as $category){
+          array_push($categories, $category);
+        }
+      }
+    }
+  }
+  $categories = array_unique($categories);
+  sort($categories,SORT_STRING);
+
+  $smarty->assign('categories',$categories);
+}
+
+/**
+ * assigns all timezones to the template
+ */
+function tpl_timezone(){
+  global $conf;
+  global $LDAP_CON;
+  global $smarty;
+
+  if(!$conf['openxchange']) return;
+
+  $timezone = array();
+
+  $sr = ldap_list($LDAP_CON,$conf['publicbook'],"ObjectClass=OXUserObject",array("OXTimeZone"));
+  $result1 = ldap_get_binentries($LDAP_CON, $sr);
+  //check users private addressbook
+  if(!empty($_SESSION['ldapab']['binddn'])){
+    $sr = @ldap_list($LDAP_CON,
+                    $conf['privatebook'].','.$_SESSION['ldapab']['binddn'],
+                    "ObjectClass=OXUserObject",array("OXTimeZone"));
+    $result2 = ldap_get_binentries($LDAP_CON, $sr);
+  }
+  $result = array_merge((array)$result1,(array)$result2);
+
+  if(count($result)){
+    foreach ($result as $entry){
+      if(count($entry['OXTimeZone'])){
+        foreach($entry['OXTimeZone'] as $tz){
+          array_push($timezone, $tz);
+        }
+      }
+    }
+  }
+  $timezone = array_unique($timezone);
+  sort($timezone,SORT_STRING);
+
+  $smarty->assign('timezone',$timezone);
+}
+
+/**
+ * assigns all countries to the template
+ */
+function tpl_country(){
+  global $conf;
+  global $LDAP_CON;
+  global $smarty;
+
+  if(!$conf['openxchange']) return;
+
+  $country = array();
+
+  $sr = ldap_list($LDAP_CON,$conf['publicbook'],"ObjectClass=OXUserObject",array("userCountry"));
+  $result1 = ldap_get_binentries($LDAP_CON, $sr);
+  //check users private addressbook
+  if(!empty($_SESSION['ldapab']['binddn'])){
+    $sr = @ldap_list($LDAP_CON,
+                    $conf['privatebook'].','.$_SESSION['ldapab']['binddn'],
+                    "ObjectClass=OXUserObject",array("userCountry"));
+    $result2 = ldap_get_binentries($LDAP_CON, $sr);
+  }
+  $result = array_merge((array)$result1,(array)$result2);
+
+  if(count($result)){
+    foreach ($result as $entry){
+      if(count($entry['userCountry'])){
+        foreach($entry['userCountry'] as $c){
+          array_push($country, $c);
+        }
+      }
+    }
+  }
+  $country = array_unique($country);
+  sort($country,SORT_STRING);
+
+  $smarty->assign('country',$country);
+}
+
+?>
index 857e69e3ac654b85a4e4d0358a36cad6bb42413d..5bd4fca712ba37020553766e7bde7e8841b1b763 100644 (file)
--- a/index.php
+++ b/index.php
@@ -1,5 +1,6 @@
-<?
-  require_once('init.php');
+<?php
+
+  require_once('inc/init.php');
   ldap_login();
 
   //prepare filter
 
   //prepare templates
   tpl_std();
-  tpl_markers(); //FIXME not needed anymore!?
-  tpl_categories();
-  tpl_timezone();
-  tpl_country();
   if (empty($_REQUEST['filter'])) $_REQUEST['filter']='';
   if (empty($_REQUEST['marker'])) $_REQUEST['marker']='';
   if (empty($_REQUEST['search'])) $_REQUEST['search']='';
diff --git a/init.php b/init.php
deleted file mode 100644 (file)
index 3130292..0000000
--- a/init.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?
-  require_once('config.php');
-  require_once('fields.php');
-  require_once('lang/'.$conf['lang'].'.php');
-  require_once('functions.php');
-  require_once('template.php');
-  require_once('smarty/Smarty.class.php');
-
-  define('NL',"\n");
-
-  //init session
-  session_name("ldapab");
-  session_start();
-
-  //kill magic quotes
-  if (get_magic_quotes_gpc()) {
-    if (!empty($_GET))    remove_magic_quotes($_GET);
-    if (!empty($_POST))   remove_magic_quotes($_POST);
-    if (!empty($_COOKIE)) remove_magic_quotes($_COOKIE);
-    if (!empty($_REQUEST)) remove_magic_quotes($_REQUEST);
-    if (!empty($_SESSION)) remove_magic_quotes($_SESSION);
-    ini_set('magic_quotes_gpc', 0);
-  }
-  set_magic_quotes_runtime(0);
-
-  function remove_magic_quotes(&$array) {
-    foreach (array_keys($array) as $key) {
-      if (is_array($array[$key])) {
-        remove_magic_quotes($array[$key]);
-      }else {
-        $array[$key] = stripslashes($array[$key]);
-      }
-    }
-  }
-
-  //prepare SMARTY object
-  $smarty = new Smarty;
-  $smarty->compile_dir   = './cache';
-  $smarty->use_sub_dirs  = 0;
-  $smarty->template_dir  = './templates';
-  $smarty->force_compile = $conf['smartycompile'];
-?>
diff --git a/js/builder.js b/js/builder.js
deleted file mode 100644 (file)
index 5b15ba9..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-//
-// See scriptaculous.js for full license.
-
-var Builder = {
-  NODEMAP: {
-    AREA: 'map',
-    CAPTION: 'table',
-    COL: 'table',
-    COLGROUP: 'table',
-    LEGEND: 'fieldset',
-    OPTGROUP: 'select',
-    OPTION: 'select',
-    PARAM: 'object',
-    TBODY: 'table',
-    TD: 'table',
-    TFOOT: 'table',
-    TH: 'table',
-    THEAD: 'table',
-    TR: 'table'
-  },
-  // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
-  //       due to a Firefox bug
-  node: function(elementName) {
-    elementName = elementName.toUpperCase();
-    
-    // try innerHTML approach
-    var parentTag = this.NODEMAP[elementName] || 'div';
-    var parentElement = document.createElement(parentTag);
-    try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
-      parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
-    } catch(e) {}
-    var element = parentElement.firstChild || null;
-      
-    // see if browser added wrapping tags
-    if(element && (element.tagName != elementName))
-      element = element.getElementsByTagName(elementName)[0];
-    
-    // fallback to createElement approach
-    if(!element) element = document.createElement(elementName);
-    
-    // abort if nothing could be created
-    if(!element) return;
-
-    // attributes (or text)
-    if(arguments[1])
-      if(this._isStringOrNumber(arguments[1]) ||
-        (arguments[1] instanceof Array)) {
-          this._children(element, arguments[1]);
-        } else {
-          var attrs = this._attributes(arguments[1]);
-          if(attrs.length) {
-            try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
-              parentElement.innerHTML = "<" +elementName + " " +
-                attrs + "></" + elementName + ">";
-            } catch(e) {}
-            element = parentElement.firstChild || null;
-            // workaround firefox 1.0.X bug
-            if(!element) {
-              element = document.createElement(elementName);
-              for(attr in arguments[1]) 
-                element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
-            }
-            if(element.tagName != elementName)
-              element = parentElement.getElementsByTagName(elementName)[0];
-            }
-        } 
-
-    // text, or array of children
-    if(arguments[2])
-      this._children(element, arguments[2]);
-
-     return element;
-  },
-  _text: function(text) {
-     return document.createTextNode(text);
-  },
-  _attributes: function(attributes) {
-    var attrs = [];
-    for(attribute in attributes)
-      attrs.push((attribute=='className' ? 'class' : attribute) +
-          '="' + attributes[attribute].toString().escapeHTML() + '"');
-    return attrs.join(" ");
-  },
-  _children: function(element, children) {
-    if(typeof children=='object') { // array can hold nodes and text
-      children.flatten().each( function(e) {
-        if(typeof e=='object')
-          element.appendChild(e)
-        else
-          if(Builder._isStringOrNumber(e))
-            element.appendChild(Builder._text(e));
-      });
-    } else
-      if(Builder._isStringOrNumber(children)) 
-         element.appendChild(Builder._text(children));
-  },
-  _isStringOrNumber: function(param) {
-    return(typeof param=='string' || typeof param=='number');
-  }
-}
\ No newline at end of file
diff --git a/js/controls.js b/js/controls.js
deleted file mode 100644 (file)
index 3307f2e..0000000
+++ /dev/null
@@ -1,770 +0,0 @@
-// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-//           (c) 2005 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
-//           (c) 2005 Jon Tirsen (http://www.tirsen.com)
-// Contributors:
-//  Richard Livsey
-//  Rahul Bhargava
-//  Rob Wills
-// 
-// See scriptaculous.js for full license.
-
-// Autocompleter.Base handles all the autocompletion functionality 
-// that's independent of the data source for autocompletion. This
-// includes drawing the autocompletion menu, observing keyboard
-// and mouse events, and similar.
-//
-// Specific autocompleters need to provide, at the very least, 
-// a getUpdatedChoices function that will be invoked every time
-// the text inside the monitored textbox changes. This method 
-// should get the text for which to provide autocompletion by
-// invoking this.getToken(), NOT by directly accessing
-// this.element.value. This is to allow incremental tokenized
-// autocompletion. Specific auto-completion logic (AJAX, etc)
-// belongs in getUpdatedChoices.
-//
-// Tokenized incremental autocompletion is enabled automatically
-// when an autocompleter is instantiated with the 'tokens' option
-// in the options parameter, e.g.:
-// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
-// will incrementally autocomplete with a comma as the token.
-// Additionally, ',' in the above example can be replaced with
-// a token array, e.g. { tokens: [',', '\n'] } which
-// enables autocompletion on multiple tokens. This is most 
-// useful when one of the tokens is \n (a newline), as it 
-// allows smart autocompletion after linebreaks.
-
-var Autocompleter = {}
-Autocompleter.Base = function() {};
-Autocompleter.Base.prototype = {
-  baseInitialize: function(element, update, options) {
-    this.element     = $(element); 
-    this.update      = $(update);  
-    this.hasFocus    = false; 
-    this.changed     = false; 
-    this.active      = false; 
-    this.index       = 0;     
-    this.entryCount  = 0;
-
-    if (this.setOptions)
-      this.setOptions(options);
-    else
-      this.options = options || {};
-
-    this.options.paramName    = this.options.paramName || this.element.name;
-    this.options.tokens       = this.options.tokens || [];
-    this.options.frequency    = this.options.frequency || 0.4;
-    this.options.minChars     = this.options.minChars || 1;
-    this.options.onShow       = this.options.onShow || 
-    function(element, update){ 
-      if(!update.style.position || update.style.position=='absolute') {
-        update.style.position = 'absolute';
-        Position.clone(element, update, {setHeight: false, offsetTop: element.offsetHeight});
-      }
-      Effect.Appear(update,{duration:0.15});
-    };
-    this.options.onHide = this.options.onHide || 
-    function(element, update){ new Effect.Fade(update,{duration:0.15}) };
-
-    if (typeof(this.options.tokens) == 'string') 
-      this.options.tokens = new Array(this.options.tokens);
-
-    this.observer = null;
-    
-    this.element.setAttribute('autocomplete','off');
-
-    Element.hide(this.update);
-
-    Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
-    Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));
-  },
-
-  show: function() {
-    if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
-    if(!this.iefix && 
-      (navigator.appVersion.indexOf('MSIE')>0) &&
-      (navigator.userAgent.indexOf('Opera')<0) &&
-      (Element.getStyle(this.update, 'position')=='absolute')) {
-      new Insertion.After(this.update, 
-       '<iframe id="' + this.update.id + '_iefix" '+
-       'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
-       'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
-      this.iefix = $(this.update.id+'_iefix');
-    }
-    if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
-  },
-  
-  fixIEOverlapping: function() {
-    Position.clone(this.update, this.iefix);
-    this.iefix.style.zIndex = 1;
-    this.update.style.zIndex = 2;
-    Element.show(this.iefix);
-  },
-
-  hide: function() {
-    this.stopIndicator();
-    if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
-    if(this.iefix) Element.hide(this.iefix);
-  },
-
-  startIndicator: function() {
-    if(this.options.indicator) Element.show(this.options.indicator);
-  },
-
-  stopIndicator: function() {
-    if(this.options.indicator) Element.hide(this.options.indicator);
-  },
-
-  onKeyPress: function(event) {
-    if(this.active)
-      switch(event.keyCode) {
-       case Event.KEY_TAB:
-       case Event.KEY_RETURN:
-         this.selectEntry();
-         Event.stop(event);
-       case Event.KEY_ESC:
-         this.hide();
-         this.active = false;
-         Event.stop(event);
-         return;
-       case Event.KEY_LEFT:
-       case Event.KEY_RIGHT:
-         return;
-       case Event.KEY_UP:
-         this.markPrevious();
-         this.render();
-         if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
-         return;
-       case Event.KEY_DOWN:
-         this.markNext();
-         this.render();
-         if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
-         return;
-      }
-     else 
-      if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN) 
-        return;
-
-    this.changed = true;
-    this.hasFocus = true;
-
-    if(this.observer) clearTimeout(this.observer);
-      this.observer = 
-        setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
-  },
-
-  onHover: function(event) {
-    var element = Event.findElement(event, 'LI');
-    if(this.index != element.autocompleteIndex) 
-    {
-        this.index = element.autocompleteIndex;
-        this.render();
-    }
-    Event.stop(event);
-  },
-  
-  onClick: function(event) {
-    var element = Event.findElement(event, 'LI');
-    this.index = element.autocompleteIndex;
-    this.selectEntry();
-    this.hide();
-  },
-  
-  onBlur: function(event) {
-    // needed to make click events working
-    setTimeout(this.hide.bind(this), 250);
-    this.hasFocus = false;
-    this.active = false;     
-  }, 
-  
-  render: function() {
-    if(this.entryCount > 0) {
-      for (var i = 0; i < this.entryCount; i++)
-        this.index==i ? 
-          Element.addClassName(this.getEntry(i),"selected") : 
-          Element.removeClassName(this.getEntry(i),"selected");
-        
-      if(this.hasFocus) { 
-        this.show();
-        this.active = true;
-      }
-    } else {
-      this.active = false;
-      this.hide();
-    }
-  },
-  
-  markPrevious: function() {
-    if(this.index > 0) this.index--
-      else this.index = this.entryCount-1;
-  },
-  
-  markNext: function() {
-    if(this.index < this.entryCount-1) this.index++
-      else this.index = 0;
-  },
-  
-  getEntry: function(index) {
-    return this.update.firstChild.childNodes[index];
-  },
-  
-  getCurrentEntry: function() {
-    return this.getEntry(this.index);
-  },
-  
-  selectEntry: function() {
-    this.active = false;
-    this.updateElement(this.getCurrentEntry());
-  },
-
-  updateElement: function(selectedElement) {
-    if (this.options.updateElement) {
-      this.options.updateElement(selectedElement);
-      return;
-    }
-    var value = '';
-    if (this.options.select) {
-      var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];
-      if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
-    } else
-      value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
-    
-    var lastTokenPos = this.findLastToken();
-    if (lastTokenPos != -1) {
-      var newValue = this.element.value.substr(0, lastTokenPos + 1);
-      var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
-      if (whitespace)
-        newValue += whitespace[0];
-      this.element.value = newValue + value;
-    } else {
-      this.element.value = value;
-    }
-    this.element.focus();
-    
-    if (this.options.afterUpdateElement)
-      this.options.afterUpdateElement(this.element, selectedElement);
-  },
-
-  updateChoices: function(choices) {
-    if(!this.changed && this.hasFocus) {
-      this.update.innerHTML = choices;
-      Element.cleanWhitespace(this.update);
-      Element.cleanWhitespace(this.update.firstChild);
-
-      if(this.update.firstChild && this.update.firstChild.childNodes) {
-        this.entryCount = 
-          this.update.firstChild.childNodes.length;
-        for (var i = 0; i < this.entryCount; i++) {
-          var entry = this.getEntry(i);
-          entry.autocompleteIndex = i;
-          this.addObservers(entry);
-        }
-      } else { 
-        this.entryCount = 0;
-      }
-
-      this.stopIndicator();
-
-      this.index = 0;
-      this.render();
-    }
-  },
-
-  addObservers: function(element) {
-    Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
-    Event.observe(element, "click", this.onClick.bindAsEventListener(this));
-  },
-
-  onObserverEvent: function() {
-    this.changed = false;   
-    if(this.getToken().length>=this.options.minChars) {
-      this.startIndicator();
-      this.getUpdatedChoices();
-    } else {
-      this.active = false;
-      this.hide();
-    }
-  },
-
-  getToken: function() {
-    var tokenPos = this.findLastToken();
-    if (tokenPos != -1)
-      var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
-    else
-      var ret = this.element.value;
-
-    return /\n/.test(ret) ? '' : ret;
-  },
-
-  findLastToken: function() {
-    var lastTokenPos = -1;
-
-    for (var i=0; i<this.options.tokens.length; i++) {
-      var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]);
-      if (thisTokenPos > lastTokenPos)
-        lastTokenPos = thisTokenPos;
-    }
-    return lastTokenPos;
-  }
-}
-
-Ajax.Autocompleter = Class.create();
-Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), {
-  initialize: function(element, update, url, options) {
-         this.baseInitialize(element, update, options);
-    this.options.asynchronous  = true;
-    this.options.onComplete    = this.onComplete.bind(this);
-    this.options.defaultParams = this.options.parameters || null;
-    this.url                   = url;
-  },
-
-  getUpdatedChoices: function() {
-    entry = encodeURIComponent(this.options.paramName) + '=' + 
-      encodeURIComponent(this.getToken());
-
-    this.options.parameters = this.options.callback ?
-      this.options.callback(this.element, entry) : entry;
-
-    if(this.options.defaultParams) 
-      this.options.parameters += '&' + this.options.defaultParams;
-
-    new Ajax.Request(this.url, this.options);
-  },
-
-  onComplete: function(request) {
-    this.updateChoices(request.responseText);
-  }
-
-});
-
-// The local array autocompleter. Used when you'd prefer to
-// inject an array of autocompletion options into the page, rather
-// than sending out Ajax queries, which can be quite slow sometimes.
-//
-// The constructor takes four parameters. The first two are, as usual,
-// the id of the monitored textbox, and id of the autocompletion menu.
-// The third is the array you want to autocomplete from, and the fourth
-// is the options block.
-//
-// Extra local autocompletion options:
-// - choices - How many autocompletion choices to offer
-//
-// - partialSearch - If false, the autocompleter will match entered
-//                    text only at the beginning of strings in the 
-//                    autocomplete array. Defaults to true, which will
-//                    match text at the beginning of any *word* in the
-//                    strings in the autocomplete array. If you want to
-//                    search anywhere in the string, additionally set
-//                    the option fullSearch to true (default: off).
-//
-// - fullSsearch - Search anywhere in autocomplete array strings.
-//
-// - partialChars - How many characters to enter before triggering
-//                   a partial match (unlike minChars, which defines
-//                   how many characters are required to do any match
-//                   at all). Defaults to 2.
-//
-// - ignoreCase - Whether to ignore case when autocompleting.
-//                 Defaults to true.
-//
-// It's possible to pass in a custom function as the 'selector' 
-// option, if you prefer to write your own autocompletion logic.
-// In that case, the other options above will not apply unless
-// you support them.
-
-Autocompleter.Local = Class.create();
-Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
-  initialize: function(element, update, array, options) {
-    this.baseInitialize(element, update, options);
-    this.options.array = array;
-  },
-
-  getUpdatedChoices: function() {
-    this.updateChoices(this.options.selector(this));
-  },
-
-  setOptions: function(options) {
-    this.options = Object.extend({
-      choices: 10,
-      partialSearch: true,
-      partialChars: 2,
-      ignoreCase: true,
-      fullSearch: false,
-      selector: function(instance) {
-        var ret       = []; // Beginning matches
-        var partial   = []; // Inside matches
-        var entry     = instance.getToken();
-        var count     = 0;
-
-        for (var i = 0; i < instance.options.array.length &&  
-          ret.length < instance.options.choices ; i++) { 
-
-          var elem = instance.options.array[i];
-          var foundPos = instance.options.ignoreCase ? 
-            elem.toLowerCase().indexOf(entry.toLowerCase()) : 
-            elem.indexOf(entry);
-
-          while (foundPos != -1) {
-            if (foundPos == 0 && elem.length != entry.length) { 
-              ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + 
-                elem.substr(entry.length) + "</li>");
-              break;
-            } else if (entry.length >= instance.options.partialChars && 
-              instance.options.partialSearch && foundPos != -1) {
-              if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
-                partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
-                  elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
-                  foundPos + entry.length) + "</li>");
-                break;
-              }
-            }
-
-            foundPos = instance.options.ignoreCase ? 
-              elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : 
-              elem.indexOf(entry, foundPos + 1);
-
-          }
-        }
-        if (partial.length)
-          ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
-        return "<ul>" + ret.join('') + "</ul>";
-      }
-    }, options || {});
-  }
-});
-
-// AJAX in-place editor
-//
-// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
-
-// Use this if you notice weird scrolling problems on some browsers,
-// the DOM might be a bit confused when this gets called so do this
-// waits 1 ms (with setTimeout) until it does the activation
-Field.scrollFreeActivate = function(field) {
-  setTimeout(function() {
-    Field.activate(field);
-  }, 1);
-}
-
-Ajax.InPlaceEditor = Class.create();
-Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
-Ajax.InPlaceEditor.prototype = {
-  initialize: function(element, url, options) {
-    this.url = url;
-    this.element = $(element);
-
-    this.options = Object.extend({
-      okButton: true,
-      okText: "ok",
-      cancelLink: true,
-      cancelText: "cancel",
-      savingText: "Saving...",
-      clickToEditText: "Click to edit",
-      okText: "ok",
-      rows: 1,
-      onComplete: function(transport, element) {
-        new Effect.Highlight(element, {startcolor: this.options.highlightcolor});
-      },
-      onFailure: function(transport) {
-        alert("Error communicating with the server: " + transport.responseText.stripTags());
-      },
-      callback: function(form) {
-        return Form.serialize(form);
-      },
-      handleLineBreaks: true,
-      loadingText: 'Loading...',
-      savingClassName: 'inplaceeditor-saving',
-      loadingClassName: 'inplaceeditor-loading',
-      formClassName: 'inplaceeditor-form',
-      highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
-      highlightendcolor: "#FFFFFF",
-      externalControl: null,
-      submitOnBlur: false,
-      ajaxOptions: {}
-    }, options || {});
-
-    if(!this.options.formId && this.element.id) {
-      this.options.formId = this.element.id + "-inplaceeditor";
-      if ($(this.options.formId)) {
-        // there's already a form with that name, don't specify an id
-        this.options.formId = null;
-      }
-    }
-    
-    if (this.options.externalControl) {
-      this.options.externalControl = $(this.options.externalControl);
-    }
-    
-    this.originalBackground = Element.getStyle(this.element, 'background-color');
-    if (!this.originalBackground) {
-      this.originalBackground = "transparent";
-    }
-    
-    this.element.title = this.options.clickToEditText;
-    
-    this.onclickListener = this.enterEditMode.bindAsEventListener(this);
-    this.mouseoverListener = this.enterHover.bindAsEventListener(this);
-    this.mouseoutListener = this.leaveHover.bindAsEventListener(this);
-    Event.observe(this.element, 'click', this.onclickListener);
-    Event.observe(this.element, 'mouseover', this.mouseoverListener);
-    Event.observe(this.element, 'mouseout', this.mouseoutListener);
-    if (this.options.externalControl) {
-      Event.observe(this.options.externalControl, 'click', this.onclickListener);
-      Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener);
-      Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener);
-    }
-  },
-  enterEditMode: function(evt) {
-    if (this.saving) return;
-    if (this.editing) return;
-    this.editing = true;
-    this.onEnterEditMode();
-    if (this.options.externalControl) {
-      Element.hide(this.options.externalControl);
-    }
-    Element.hide(this.element);
-    this.createForm();
-    this.element.parentNode.insertBefore(this.form, this.element);
-    Field.scrollFreeActivate(this.editField);
-    // stop the event to avoid a page refresh in Safari
-    if (evt) {
-      Event.stop(evt);
-    }
-    return false;
-  },
-  createForm: function() {
-    this.form = document.createElement("form");
-    this.form.id = this.options.formId;
-    Element.addClassName(this.form, this.options.formClassName)
-    this.form.onsubmit = this.onSubmit.bind(this);
-
-    this.createEditField();
-
-    if (this.options.textarea) {
-      var br = document.createElement("br");
-      this.form.appendChild(br);
-    }
-
-    if (this.options.okButton) {
-      okButton = document.createElement("input");
-      okButton.type = "submit";
-      okButton.value = this.options.okText;
-      this.form.appendChild(okButton);
-    }
-
-    if (this.options.cancelLink) {
-      cancelLink = document.createElement("a");
-      cancelLink.href = "#";
-      cancelLink.appendChild(document.createTextNode(this.options.cancelText));
-      cancelLink.onclick = this.onclickCancel.bind(this);
-      this.form.appendChild(cancelLink);
-    }
-  },
-  hasHTMLLineBreaks: function(string) {
-    if (!this.options.handleLineBreaks) return false;
-    return string.match(/<br/i) || string.match(/<p>/i);
-  },
-  convertHTMLLineBreaks: function(string) {
-    return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, "");
-  },
-  createEditField: function() {
-    var text;
-    if(this.options.loadTextURL) {
-      text = this.options.loadingText;
-    } else {
-      text = this.getText();
-    }
-
-    var obj = this;
-    
-    if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
-      this.options.textarea = false;
-      var textField = document.createElement("input");
-      textField.obj = this;
-      textField.type = "text";
-      textField.name = "value";
-      textField.value = text;
-      textField.style.backgroundColor = this.options.highlightcolor;
-      var size = this.options.size || this.options.cols || 0;
-      if (size != 0) textField.size = size;
-      if (this.options.submitOnBlur)
-        textField.onblur = this.onSubmit.bind(this);
-      this.editField = textField;
-    } else {
-      this.options.textarea = true;
-      var textArea = document.createElement("textarea");
-      textArea.obj = this;
-      textArea.name = "value";
-      textArea.value = this.convertHTMLLineBreaks(text);
-      textArea.rows = this.options.rows;
-      textArea.cols = this.options.cols || 40;
-      if (this.options.submitOnBlur)
-        textArea.onblur = this.onSubmit.bind(this);
-      this.editField = textArea;
-    }
-    
-    if(this.options.loadTextURL) {
-      this.loadExternalText();
-    }
-    this.form.appendChild(this.editField);
-  },
-  getText: function() {
-    return this.element.innerHTML;
-  },
-  loadExternalText: function() {
-    Element.addClassName(this.form, this.options.loadingClassName);
-    this.editField.disabled = true;
-    new Ajax.Request(
-      this.options.loadTextURL,
-      Object.extend({
-        asynchronous: true,
-        onComplete: this.onLoadedExternalText.bind(this)
-      }, this.options.ajaxOptions)
-    );
-  },
-  onLoadedExternalText: function(transport) {
-    Element.removeClassName(this.form, this.options.loadingClassName);
-    this.editField.disabled = false;
-    this.editField.value = transport.responseText.stripTags();
-  },
-  onclickCancel: function() {
-    this.onComplete();
-    this.leaveEditMode();
-    return false;
-  },
-  onFailure: function(transport) {
-    this.options.onFailure(transport);
-    if (this.oldInnerHTML) {
-      this.element.innerHTML = this.oldInnerHTML;
-      this.oldInnerHTML = null;
-    }
-    return false;
-  },
-  onSubmit: function() {
-    // onLoading resets these so we need to save them away for the Ajax call
-    var form = this.form;
-    var value = this.editField.value;
-    
-    // do this first, sometimes the ajax call returns before we get a chance to switch on Saving...
-    // which means this will actually switch on Saving... *after* we've left edit mode causing Saving...
-    // to be displayed indefinitely
-    this.onLoading();
-    
-    new Ajax.Updater(
-      { 
-        success: this.element,
-         // don't update on failure (this could be an option)
-        failure: null
-      },
-      this.url,
-      Object.extend({
-        parameters: this.options.callback(form, value),
-        onComplete: this.onComplete.bind(this),
-        onFailure: this.onFailure.bind(this)
-      }, this.options.ajaxOptions)
-    );
-    // stop the event to avoid a page refresh in Safari
-    if (arguments.length > 1) {
-      Event.stop(arguments[0]);
-    }
-    return false;
-  },
-  onLoading: function() {
-    this.saving = true;
-    this.removeForm();
-    this.leaveHover();
-    this.showSaving();
-  },
-  showSaving: function() {
-    this.oldInnerHTML = this.element.innerHTML;
-    this.element.innerHTML = this.options.savingText;
-    Element.addClassName(this.element, this.options.savingClassName);
-    this.element.style.backgroundColor = this.originalBackground;
-    Element.show(this.element);
-  },
-  removeForm: function() {
-    if(this.form) {
-      if (this.form.parentNode) Element.remove(this.form);
-      this.form = null;
-    }
-  },
-  enterHover: function() {
-    if (this.saving) return;
-    this.element.style.backgroundColor = this.options.highlightcolor;
-    if (this.effect) {
-      this.effect.cancel();
-    }
-    Element.addClassName(this.element, this.options.hoverClassName)
-  },
-  leaveHover: function() {
-    if (this.options.backgroundColor) {
-      this.element.style.backgroundColor = this.oldBackground;
-    }
-    Element.removeClassName(this.element, this.options.hoverClassName)
-    if (this.saving) return;
-    this.effect = new Effect.Highlight(this.element, {
-      startcolor: this.options.highlightcolor,
-      endcolor: this.options.highlightendcolor,
-      restorecolor: this.originalBackground
-    });
-  },
-  leaveEditMode: function() {
-    Element.removeClassName(this.element, this.options.savingClassName);
-    this.removeForm();
-    this.leaveHover();
-    this.element.style.backgroundColor = this.originalBackground;
-    Element.show(this.element);
-    if (this.options.externalControl) {
-      Element.show(this.options.externalControl);
-    }
-    this.editing = false;
-    this.saving = false;
-    this.oldInnerHTML = null;
-    this.onLeaveEditMode();
-  },
-  onComplete: function(transport) {
-    this.leaveEditMode();
-    this.options.onComplete.bind(this)(transport, this.element);
-  },
-  onEnterEditMode: function() {},
-  onLeaveEditMode: function() {},
-  dispose: function() {
-    if (this.oldInnerHTML) {
-      this.element.innerHTML = this.oldInnerHTML;
-    }
-    this.leaveEditMode();
-    Event.stopObserving(this.element, 'click', this.onclickListener);
-    Event.stopObserving(this.element, 'mouseover', this.mouseoverListener);
-    Event.stopObserving(this.element, 'mouseout', this.mouseoutListener);
-    if (this.options.externalControl) {
-      Event.stopObserving(this.options.externalControl, 'click', this.onclickListener);
-      Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener);
-      Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener);
-    }
-  }
-};
-
-// Delayed observer, like Form.Element.Observer, 
-// but waits for delay after last key input
-// Ideal for live-search fields
-
-Form.Element.DelayedObserver = Class.create();
-Form.Element.DelayedObserver.prototype = {
-  initialize: function(element, delay, callback) {
-    this.delay     = delay || 0.5;
-    this.element   = $(element);
-    this.callback  = callback;
-    this.timer     = null;
-    this.lastValue = $F(this.element); 
-    Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
-  },
-  delayedListener: function(event) {
-    if(this.lastValue == $F(this.element)) return;
-    if(this.timer) clearTimeout(this.timer);
-    this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
-    this.lastValue = $F(this.element);
-  },
-  onTimerEvent: function() {
-    this.timer = null;
-    this.callback(this.element, $F(this.element));
-  }
-};
diff --git a/js/date-formatting.js b/js/date-formatting.js
deleted file mode 100644 (file)
index b2848a1..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * A Javascript date chooser.
- * Copyright (C) 2004 Baron Schwartz <baron at sequent dot org>
- * 
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option) any later
- * version.
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
- * details.
- * 
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307  USA
- */
-
-Date.formatFunctions = {count:0};
-
-Date.prototype.dateFormat = function(format) {
-    if (Date.formatFunctions[format] == null) {
-        Date.createNewFormat(format);
-    }
-    var func = Date.formatFunctions[format];
-    return eval("this." + func + "();");
-}
-
-Date.createNewFormat = function(format) {
-    var funcName = "format" + Date.formatFunctions.count++;
-    Date.formatFunctions[format] = funcName;
-    var code = "Date.prototype." + funcName + " = function(){return ";
-    var special = false;
-    var char = '';
-    for (var i = 0; i < format.length; ++i) {
-        char = format.charAt(i);
-        if (!special && char == "\\") {
-            special = true;
-        }
-        else if (special) {
-            special = false;
-            code += "'" + String.escape(char) + "' + ";
-        }
-        else {
-            code += Date.getFormatCode(char);
-        }
-    }
-    eval(code.substring(0, code.length - 3) + ";}");
-}
-
-Date.getFormatCode = function(character) {
-    switch (character) {
-    case "d":
-        return "String.leftPad(this.getDate(), 2, '0') + ";
-    case "D":
-        return "Date.dayNames[this.getDay()].substring(0, 3) + ";
-    case "j":
-        return "this.getDate() + ";
-    case "l":
-        return "Date.dayNames[this.getDay()] + ";
-    case "S":
-        return "this.getSuffix() + ";
-    case "w":
-        return "this.getDay() + ";
-    case "z":
-        return "this.getDayOfYear() + ";
-    case "W":
-        return "this.getWeekOfYear() + ";
-    case "F":
-        return "Date.monthNames[this.getMonth()] + ";
-    case "m":
-        return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
-    case "M":
-        return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
-    case "n":
-        return "(this.getMonth() + 1) + ";
-    case "t":
-        return "this.getDaysInMonth() + ";
-    case "L":
-        return "(this.isLeapYear() ? 1 : 0) + ";
-    case "Y":
-        return "this.getFullYear() + ";
-    case "y":
-        return "('' + this.getFullYear()).substring(2, 4) + ";
-    case "a":
-        return "(this.getHours() < 12 ? 'am' : 'pm') + ";
-    case "A":
-        return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
-    case "g":
-        return "((this.getHours() %12) ? this.getHours() % 12 : 12) + ";
-    case "G":
-        return "this.getHours() + ";
-    case "h":
-        return "String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + ";
-    case "H":
-        return "String.leftPad(this.getHours(), 2, '0') + ";
-    case "i":
-        return "String.leftPad(this.getMinutes(), 2, '0') + ";
-    case "s":
-        return "String.leftPad(this.getSeconds(), 2, '0') + ";
-    case "O":
-        return "this.getGMTOffset() + ";
-    case "T":
-        return "this.getTimezone() + ";
-    case "Z":
-        return "(this.getTimezoneOffset() * -60) + ";
-    default:
-        return "'" + String.escape(character) + "' + ";
-    }
-}
-
-Date.prototype.getTimezone = function() {
-    return this.toString().replace(
-        /^.*? ([A-Z]{3}) [0-9]{4}.*$/, "$1").replace(
-        /^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3");
-}
-
-Date.prototype.getGMTOffset = function() {
-    return (this.getTimezoneOffset() > 0 ? "-" : "+")
-        + String.leftPad(Math.floor(this.getTimezoneOffset() / 60), 2, "0")
-        + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
-}
-
-Date.prototype.getDayOfYear = function() {
-    var num = 0;
-    Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
-    for (var i = 0; i < this.getMonth(); ++i) {
-        num += Date.daysInMonth[i];
-    }
-    return num + this.getDate() - 1;
-}
-
-Date.prototype.getWeekOfYear = function() {
-    // Skip to Thursday of this week
-    var now = this.getDayOfYear() + (4 - this.getDay());
-    // Find the first Thursday of the year
-    var jan1 = new Date(this.getFullYear(), 0, 1);
-    var then = (7 - jan1.getDay() + 4);
-    document.write(then);
-    return String.leftPad(((now - then) / 7) + 1, 2, "0");
-}
-
-Date.prototype.isLeapYear = function() {
-    var year = this.getFullYear();
-    return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
-}
-
-Date.prototype.getFirstDayOfMonth = function() {
-    var day = (this.getDay() - (this.getDate() - 1)) % 7;
-    return (day < 0) ? (day + 7) : day;
-}
-
-Date.prototype.getLastDayOfMonth = function() {
-    var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
-    return (day < 0) ? (day + 7) : day;
-}
-
-Date.prototype.getDaysInMonth = function() {
-    Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
-    return Date.daysInMonth[this.getMonth()];
-}
-
-Date.prototype.getSuffix = function() {
-    switch (this.getDate()) {
-        case 1:
-        case 21:
-        case 31:
-            return "st";
-        case 2:
-        case 22:
-            return "nd";
-        case 3:
-        case 23:
-            return "rd";
-        default:
-            return "th";
-    }
-}
-
-String.escape = function(string) {
-    return string.replace(/('|\\)/g, "\\$1");
-}
-
-String.leftPad = function (val, size, char) {
-    var result = new String(val);
-    if (char == null) {
-        char = " ";
-    }
-    while (result.length < size) {
-        result = char + result;
-    }
-    return result;
-}
-
-Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
-Date.monthNames =
-   ["January",
-    "February",
-    "March",
-    "April",
-    "May",
-    "June",
-    "July",
-    "August",
-    "September",
-    "October",
-    "November",
-    "December"];
-Date.dayNames =
-   ["Sunday",
-    "Monday",
-    "Tuesday",
-    "Wednesday",
-    "Thursday",
-    "Friday",
-    "Saturday"];
-Date.patterns = {
-    ISO8601LongPattern:"Y-m-d H:i:s",
-    ISO8601ShortPattern:"Y-m-d",
-    ShortDatePattern: "n/j/Y",
-    LongDatePattern: "l, F d, Y",
-    FullDateTimePattern: "l, F d, Y g:i:s A",
-    MonthDayPattern: "F d",
-    ShortTimePattern: "g:i A",
-    LongTimePattern: "g:i:s A",
-    SortableDateTimePattern: "Y-m-d\\TH:i:s",
-    UniversalSortableDateTimePattern: "Y-m-d H:i:sO",
-    YearMonthPattern: "F, Y"};
-
-Date.parseIsoDate = function(dateString) {
-    var result = new Date();
-    var re = /^(\d\d\d\d)-(\d\d)-(\d\d)( (\d\d):(\d\d):(\d\d))?$/;
-    var match = dateString.match(re);
-    if (match != null) {
-        if (match[5] != null && match[5] != '') {
-            result = new Date(
-                parseInt(match[1], 10),
-                parseInt(match[2], 10) - 1,
-                parseInt(match[3], 10),
-                parseInt(match[5], 10),
-                parseInt(match[6], 10),
-                parseInt(match[7], 10));
-        }
-        else {
-            result = new Date(
-                parseInt(match[1], 10),
-                parseInt(match[2], 10) - 1,
-                parseInt(match[3], 10));
-        }
-    }
-    return result;
-}
diff --git a/js/dragdrop.js b/js/dragdrop.js
deleted file mode 100644 (file)
index 818ef5e..0000000
+++ /dev/null
@@ -1,585 +0,0 @@
-// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// 
-// See scriptaculous.js for full license.
-
-/*--------------------------------------------------------------------------*/
-
-var Droppables = {
-  drops: [],
-
-  remove: function(element) {
-    this.drops = this.drops.reject(function(d) { return d.element==$(element) });
-  },
-
-  add: function(element) {
-    element = $(element);
-    var options = Object.extend({
-      greedy:     true,
-      hoverclass: null  
-    }, arguments[1] || {});
-
-    // cache containers
-    if(options.containment) {
-      options._containers = [];
-      var containment = options.containment;
-      if((typeof containment == 'object') && 
-        (containment.constructor == Array)) {
-        containment.each( function(c) { options._containers.push($(c)) });
-      } else {
-        options._containers.push($(containment));
-      }
-    }
-    
-    if(options.accept) options.accept = [options.accept].flatten();
-
-    Element.makePositioned(element); // fix IE
-    options.element = element;
-
-    this.drops.push(options);
-  },
-
-  isContained: function(element, drop) {
-    var parentNode = element.parentNode;
-    return drop._containers.detect(function(c) { return parentNode == c });
-  },
-
-  isAffected: function(point, element, drop) {
-    return (
-      (drop.element!=element) &&
-      ((!drop._containers) ||
-        this.isContained(element, drop)) &&
-      ((!drop.accept) ||
-        (Element.classNames(element).detect( 
-          function(v) { return drop.accept.include(v) } ) )) &&
-      Position.within(drop.element, point[0], point[1]) );
-  },
-
-  deactivate: function(drop) {
-    if(drop.hoverclass)
-      Element.removeClassName(drop.element, drop.hoverclass);
-    this.last_active = null;
-  },
-
-  activate: function(drop) {
-    if(drop.hoverclass)
-      Element.addClassName(drop.element, drop.hoverclass);
-    this.last_active = drop;
-  },
-
-  show: function(point, element) {
-    if(!this.drops.length) return;
-    
-    if(this.last_active) this.deactivate(this.last_active);
-    this.drops.each( function(drop) {
-      if(Droppables.isAffected(point, element, drop)) {
-        if(drop.onHover)
-           drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
-        if(drop.greedy) { 
-          Droppables.activate(drop);
-          throw $break;
-        }
-      }
-    });
-  },
-
-  fire: function(event, element) {
-    if(!this.last_active) return;
-    Position.prepare();
-
-    if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
-      if (this.last_active.onDrop) 
-        this.last_active.onDrop(element, this.last_active.element, event);
-  },
-
-  reset: function() {
-    if(this.last_active)
-      this.deactivate(this.last_active);
-  }
-}
-
-var Draggables = {
-  drags: [],
-  observers: [],
-  
-  register: function(draggable) {
-    if(this.drags.length == 0) {
-      this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
-      this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
-      this.eventKeypress  = this.keyPress.bindAsEventListener(this);
-      
-      Event.observe(document, "mouseup", this.eventMouseUp);
-      Event.observe(document, "mousemove", this.eventMouseMove);
-      Event.observe(document, "keypress", this.eventKeypress);
-    }
-    this.drags.push(draggable);
-  },
-  
-  unregister: function(draggable) {
-    this.drags = this.drags.reject(function(d) { return d==draggable });
-    if(this.drags.length == 0) {
-      Event.stopObserving(document, "mouseup", this.eventMouseUp);
-      Event.stopObserving(document, "mousemove", this.eventMouseMove);
-      Event.stopObserving(document, "keypress", this.eventKeypress);
-    }
-  },
-  
-  activate: function(draggable) {
-    window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
-    this.activeDraggable = draggable;
-  },
-  
-  deactivate: function(draggbale) {
-    this.activeDraggable = null;
-  },
-  
-  updateDrag: function(event) {
-    if(!this.activeDraggable) return;
-    var pointer = [Event.pointerX(event), Event.pointerY(event)];
-    // Mozilla-based browsers fire successive mousemove events with
-    // the same coordinates, prevent needless redrawing (moz bug?)
-    if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
-    this._lastPointer = pointer;
-    this.activeDraggable.updateDrag(event, pointer);
-  },
-  
-  endDrag: function(event) {
-    if(!this.activeDraggable) return;
-    this._lastPointer = null;
-    this.activeDraggable.endDrag(event);
-    this.activeDraggable = null;
-  },
-  
-  keyPress: function(event) {
-    if(this.activeDraggable)
-      this.activeDraggable.keyPress(event);
-  },
-  
-  addObserver: function(observer) {
-    this.observers.push(observer);
-    this._cacheObserverCallbacks();
-  },
-  
-  removeObserver: function(element) {  // element instead of observer fixes mem leaks
-    this.observers = this.observers.reject( function(o) { return o.element==element });
-    this._cacheObserverCallbacks();
-  },
-  
-  notify: function(eventName, draggable, event) {  // 'onStart', 'onEnd', 'onDrag'
-    if(this[eventName+'Count'] > 0)
-      this.observers.each( function(o) {
-        if(o[eventName]) o[eventName](eventName, draggable, event);
-      });
-  },
-  
-  _cacheObserverCallbacks: function() {
-    ['onStart','onEnd','onDrag'].each( function(eventName) {
-      Draggables[eventName+'Count'] = Draggables.observers.select(
-        function(o) { return o[eventName]; }
-      ).length;
-    });
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var Draggable = Class.create();
-Draggable.prototype = {
-  initialize: function(element) {
-    var options = Object.extend({
-      handle: false,
-      starteffect: function(element) { 
-        new Effect.Opacity(element, {duration:0.2, from:1.0, to:0.7}); 
-      },
-      reverteffect: function(element, top_offset, left_offset) {
-        var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
-        element._revert = new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur});
-      },
-      endeffect: function(element) { 
-        new Effect.Opacity(element, {duration:0.2, from:0.7, to:1.0}); 
-      },
-      zindex: 1000,
-      revert: false,
-      snap: false   // false, or xy or [x,y] or function(x,y){ return [x,y] }
-    }, arguments[1] || {});
-
-    this.element = $(element);
-    
-    if(options.handle && (typeof options.handle == 'string'))
-      this.handle = Element.childrenWithClassName(this.element, options.handle)[0];  
-    if(!this.handle) this.handle = $(options.handle);
-    if(!this.handle) this.handle = this.element;
-
-    Element.makePositioned(this.element); // fix IE    
-
-    this.delta    = this.currentDelta();
-    this.options  = options;
-    this.dragging = false;   
-
-    this.eventMouseDown = this.initDrag.bindAsEventListener(this);
-    Event.observe(this.handle, "mousedown", this.eventMouseDown);
-    
-    Draggables.register(this);
-  },
-  
-  destroy: function() {
-    Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
-    Draggables.unregister(this);
-  },
-  
-  currentDelta: function() {
-    return([
-      parseInt(Element.getStyle(this.element,'left') || '0'),
-      parseInt(Element.getStyle(this.element,'top') || '0')]);
-  },
-  
-  initDrag: function(event) {
-    if(Event.isLeftClick(event)) {    
-      // abort on form elements, fixes a Firefox issue
-      var src = Event.element(event);
-      if(src.tagName && (
-        src.tagName=='INPUT' ||
-        src.tagName=='SELECT' ||
-        src.tagName=='BUTTON' ||
-        src.tagName=='TEXTAREA')) return;
-        
-      if(this.element._revert) {
-        this.element._revert.cancel();
-        this.element._revert = null;
-      }
-      
-      var pointer = [Event.pointerX(event), Event.pointerY(event)];
-      var pos     = Position.cumulativeOffset(this.element);
-      this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
-      
-      Draggables.activate(this);
-      Event.stop(event);
-    }
-  },
-  
-  startDrag: function(event) {
-    this.dragging = true;
-    
-    if(this.options.zindex) {
-      this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
-      this.element.style.zIndex = this.options.zindex;
-    }
-    
-    if(this.options.ghosting) {
-      this._clone = this.element.cloneNode(true);
-      Position.absolutize(this.element);
-      this.element.parentNode.insertBefore(this._clone, this.element);
-    }
-    
-    Draggables.notify('onStart', this, event);
-    if(this.options.starteffect) this.options.starteffect(this.element);
-  },
-  
-  updateDrag: function(event, pointer) {
-    if(!this.dragging) this.startDrag(event);
-    Position.prepare();
-    Droppables.show(pointer, this.element);
-    Draggables.notify('onDrag', this, event);
-    this.draw(pointer);
-    if(this.options.change) this.options.change(this);
-    
-    // fix AppleWebKit rendering
-    if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
-    Event.stop(event);
-  },
-  
-  finishDrag: function(event, success) {
-    this.dragging = false;
-
-    if(this.options.ghosting) {
-      Position.relativize(this.element);
-      Element.remove(this._clone);
-      this._clone = null;
-    }
-
-    if(success) Droppables.fire(event, this.element);
-    Draggables.notify('onEnd', this, event);
-
-    var revert = this.options.revert;
-    if(revert && typeof revert == 'function') revert = revert(this.element);
-    
-    var d = this.currentDelta();
-    if(revert && this.options.reverteffect) {
-      this.options.reverteffect(this.element, 
-        d[1]-this.delta[1], d[0]-this.delta[0]);
-    } else {
-      this.delta = d;
-    }
-
-    if(this.options.zindex)
-      this.element.style.zIndex = this.originalZ;
-
-    if(this.options.endeffect) 
-      this.options.endeffect(this.element);
-
-    Draggables.deactivate(this);
-    Droppables.reset();
-  },
-  
-  keyPress: function(event) {
-    if(!event.keyCode==Event.KEY_ESC) return;
-    this.finishDrag(event, false);
-    Event.stop(event);
-  },
-  
-  endDrag: function(event) {
-    if(!this.dragging) return;
-    this.finishDrag(event, true);
-    Event.stop(event);
-  },
-  
-  draw: function(point) {
-    var pos = Position.cumulativeOffset(this.element);
-    var d = this.currentDelta();
-    pos[0] -= d[0]; pos[1] -= d[1];
-    
-    var p = [0,1].map(function(i){ return (point[i]-pos[i]-this.offset[i]) }.bind(this));
-    
-    if(this.options.snap) {
-      if(typeof this.options.snap == 'function') {
-        p = this.options.snap(p[0],p[1]);
-      } else {
-      if(this.options.snap instanceof Array) {
-        p = p.map( function(v, i) {
-          return Math.round(v/this.options.snap[i])*this.options.snap[i] }.bind(this))
-      } else {
-        p = p.map( function(v) {
-          return Math.round(v/this.options.snap)*this.options.snap }.bind(this))
-      }
-    }}
-    
-    var style = this.element.style;
-    if((!this.options.constraint) || (this.options.constraint=='horizontal'))
-      style.left = p[0] + "px";
-    if((!this.options.constraint) || (this.options.constraint=='vertical'))
-      style.top  = p[1] + "px";
-    if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var SortableObserver = Class.create();
-SortableObserver.prototype = {
-  initialize: function(element, observer) {
-    this.element   = $(element);
-    this.observer  = observer;
-    this.lastValue = Sortable.serialize(this.element);
-  },
-  
-  onStart: function() {
-    this.lastValue = Sortable.serialize(this.element);
-  },
-  
-  onEnd: function() {
-    Sortable.unmark();
-    if(this.lastValue != Sortable.serialize(this.element))
-      this.observer(this.element)
-  }
-}
-
-var Sortable = {
-  sortables: new Array(),
-  
-  options: function(element){
-    element = $(element);
-    return this.sortables.detect(function(s) { return s.element == element });
-  },
-  
-  destroy: function(element){
-    element = $(element);
-    this.sortables.findAll(function(s) { return s.element == element }).each(function(s){
-      Draggables.removeObserver(s.element);
-      s.droppables.each(function(d){ Droppables.remove(d) });
-      s.draggables.invoke('destroy');
-    });
-    this.sortables = this.sortables.reject(function(s) { return s.element == element });
-  },
-  
-  create: function(element) {
-    element = $(element);
-    var options = Object.extend({ 
-      element:     element,
-      tag:         'li',       // assumes li children, override with tag: 'tagname'
-      dropOnEmpty: false,
-      tree:        false,      // fixme: unimplemented
-      overlap:     'vertical', // one of 'vertical', 'horizontal'
-      constraint:  'vertical', // one of 'vertical', 'horizontal', false
-      containment: element,    // also takes array of elements (or id's); or false
-      handle:      false,      // or a CSS class
-      only:        false,
-      hoverclass:  null,
-      ghosting:    false,
-      format:      null,
-      onChange:    Prototype.emptyFunction,
-      onUpdate:    Prototype.emptyFunction
-    }, arguments[1] || {});
-
-    // clear any old sortable with same element
-    this.destroy(element);
-
-    // build options for the draggables
-    var options_for_draggable = {
-      revert:      true,
-      ghosting:    options.ghosting,
-      constraint:  options.constraint,
-      handle:      options.handle };
-
-    if(options.starteffect)
-      options_for_draggable.starteffect = options.starteffect;
-
-    if(options.reverteffect)
-      options_for_draggable.reverteffect = options.reverteffect;
-    else
-      if(options.ghosting) options_for_draggable.reverteffect = function(element) {
-        element.style.top  = 0;
-        element.style.left = 0;
-      };
-
-    if(options.endeffect)
-      options_for_draggable.endeffect = options.endeffect;
-
-    if(options.zindex)
-      options_for_draggable.zindex = options.zindex;
-
-    // build options for the droppables  
-    var options_for_droppable = {
-      overlap:     options.overlap,
-      containment: options.containment,
-      hoverclass:  options.hoverclass,
-      onHover:     Sortable.onHover,
-      greedy:      !options.dropOnEmpty
-    }
-
-    // fix for gecko engine
-    Element.cleanWhitespace(element); 
-
-    options.draggables = [];
-    options.droppables = [];
-
-    // make it so
-
-    // drop on empty handling
-    if(options.dropOnEmpty) {
-      Droppables.add(element,
-        {containment: options.containment, onHover: Sortable.onEmptyHover, greedy: false});
-      options.droppables.push(element);
-    }
-
-    (this.findElements(element, options) || []).each( function(e) {
-      // handles are per-draggable
-      var handle = options.handle ? 
-        Element.childrenWithClassName(e, options.handle)[0] : e;    
-      options.draggables.push(
-        new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
-      Droppables.add(e, options_for_droppable);
-      options.droppables.push(e);      
-    });
-
-    // keep reference
-    this.sortables.push(options);
-
-    // for onupdate
-    Draggables.addObserver(new SortableObserver(element, options.onUpdate));
-
-  },
-
-  // return all suitable-for-sortable elements in a guaranteed order
-  findElements: function(element, options) {
-    if(!element.hasChildNodes()) return null;
-    var elements = [];
-    $A(element.childNodes).each( function(e) {
-      if(e.tagName && e.tagName.toUpperCase()==options.tag.toUpperCase() &&
-        (!options.only || (Element.hasClassName(e, options.only))))
-          elements.push(e);
-      if(options.tree) {
-        var grandchildren = this.findElements(e, options);
-        if(grandchildren) elements.push(grandchildren);
-      }
-    });
-
-    return (elements.length>0 ? elements.flatten() : null);
-  },
-
-  onHover: function(element, dropon, overlap) {
-    if(overlap>0.5) {
-      Sortable.mark(dropon, 'before');
-      if(dropon.previousSibling != element) {
-        var oldParentNode = element.parentNode;
-        element.style.visibility = "hidden"; // fix gecko rendering
-        dropon.parentNode.insertBefore(element, dropon);
-        if(dropon.parentNode!=oldParentNode) 
-          Sortable.options(oldParentNode).onChange(element);
-        Sortable.options(dropon.parentNode).onChange(element);
-      }
-    } else {
-      Sortable.mark(dropon, 'after');
-      var nextElement = dropon.nextSibling || null;
-      if(nextElement != element) {
-        var oldParentNode = element.parentNode;
-        element.style.visibility = "hidden"; // fix gecko rendering
-        dropon.parentNode.insertBefore(element, nextElement);
-        if(dropon.parentNode!=oldParentNode) 
-          Sortable.options(oldParentNode).onChange(element);
-        Sortable.options(dropon.parentNode).onChange(element);
-      }
-    }
-  },
-
-  onEmptyHover: function(element, dropon) {
-    if(element.parentNode!=dropon) {
-      var oldParentNode = element.parentNode;
-      dropon.appendChild(element);
-      Sortable.options(oldParentNode).onChange(element);
-      Sortable.options(dropon).onChange(element);
-    }
-  },
-
-  unmark: function() {
-    if(Sortable._marker) Element.hide(Sortable._marker);
-  },
-
-  mark: function(dropon, position) {
-    // mark on ghosting only
-    var sortable = Sortable.options(dropon.parentNode);
-    if(sortable && !sortable.ghosting) return; 
-
-    if(!Sortable._marker) {
-      Sortable._marker = $('dropmarker') || document.createElement('DIV');
-      Element.hide(Sortable._marker);
-      Element.addClassName(Sortable._marker, 'dropmarker');
-      Sortable._marker.style.position = 'absolute';
-      document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
-    }    
-    var offsets = Position.cumulativeOffset(dropon);
-    Sortable._marker.style.left = offsets[0] + 'px';
-    Sortable._marker.style.top = offsets[1] + 'px';
-    
-    if(position=='after')
-      if(sortable.overlap == 'horizontal') 
-        Sortable._marker.style.left = (offsets[0]+dropon.clientWidth) + 'px';
-      else
-        Sortable._marker.style.top = (offsets[1]+dropon.clientHeight) + 'px';
-    
-    Element.show(Sortable._marker);
-  },
-
-  serialize: function(element) {
-    element = $(element);
-    var sortableOptions = this.options(element);
-    var options = Object.extend({
-      tag:  sortableOptions.tag,
-      only: sortableOptions.only,
-      name: element.id,
-      format: sortableOptions.format || /^[^_]*_(.*)$/
-    }, arguments[1] || {});
-    return $(this.findElements(element, options) || []).map( function(item) {
-      return (encodeURIComponent(options.name) + "[]=" + 
-              encodeURIComponent(item.id.match(options.format) ? item.id.match(options.format)[1] : ''));
-    }).join("&");
-  }
-}
\ No newline at end of file
diff --git a/js/effects.js b/js/effects.js
deleted file mode 100644 (file)
index d3940a8..0000000
+++ /dev/null
@@ -1,903 +0,0 @@
-// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// Contributors:
-//  Justin Palmer (http://encytemedia.com/)
-//  Mark Pilgrim (http://diveintomark.org/)
-//  Martin Bialasinki
-// 
-// See scriptaculous.js for full license.  
-
-/* ------------- element ext -------------- */  
-// converts rgb() and #xxx to #xxxxxx format,  
-// returns self (or first argument) if not convertable  
-String.prototype.parseColor = function() {  
-  var color = '#';  
-  if(this.slice(0,4) == 'rgb(') {  
-    var cols = this.slice(4,this.length-1).split(',');  
-    var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);  
-  } else {  
-    if(this.slice(0,1) == '#') {  
-      if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();  
-      if(this.length==7) color = this.toLowerCase();  
-    }  
-  }  
-  return(color.length==7 ? color : (arguments[0] || this));  
-}
-
-Element.collectTextNodes = function(element) {  
-  return $A($(element).childNodes).collect( function(node) {
-    return (node.nodeType==3 ? node.nodeValue : 
-      (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
-  }).flatten().join('');
-}
-
-Element.collectTextNodesIgnoreClass = function(element, className) {  
-  return $A($(element).childNodes).collect( function(node) {
-    return (node.nodeType==3 ? node.nodeValue : 
-      ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? 
-        Element.collectTextNodes(node) : ''));
-  }).flatten().join('');
-}
-
-Element.setStyle = function(element, style) {
-  element = $(element);
-  for(k in style) element.style[k.camelize()] = style[k];
-}
-
-Element.setContentZoom = function(element, percent) {  
-  Element.setStyle(element, {fontSize: (percent/100) + 'em'});   
-  if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);  
-}
-
-Element.getOpacity = function(element){  
-  var opacity;
-  if (opacity = Element.getStyle(element, 'opacity'))  
-    return parseFloat(opacity);  
-  if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/))  
-    if(opacity[1]) return parseFloat(opacity[1]) / 100;  
-  return 1.0;  
-}
-
-Element.setOpacity = function(element, value){  
-  element= $(element);  
-  if (value == 1){
-    Element.setStyle(element, { opacity: 
-      (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 
-      0.999999 : null });
-    if(/MSIE/.test(navigator.userAgent))  
-      Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')});  
-  } else {  
-    if(value < 0.00001) value = 0;  
-    Element.setStyle(element, {opacity: value});
-    if(/MSIE/.test(navigator.userAgent))  
-     Element.setStyle(element, 
-       { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') +
-                 'alpha(opacity='+value*100+')' });  
-  }   
-}  
-Element.getInlineOpacity = function(element){  
-  return $(element).style.opacity || '';
-}  
-
-Element.childrenWithClassName = function(element, className) {  
-  return $A($(element).getElementsByTagName('*')).select(
-    function(c) { return Element.hasClassName(c, className) });
-}
-
-Array.prototype.call = function() {
-  var args = arguments;
-  this.each(function(f){ f.apply(this, args) });
-}
-
-/*--------------------------------------------------------------------------*/
-
-var Effect = {
-  tagifyText: function(element) {
-    var tagifyStyle = 'position:relative';
-    if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1';
-    element = $(element);
-    $A(element.childNodes).each( function(child) {
-      if(child.nodeType==3) {
-        child.nodeValue.toArray().each( function(character) {
-          element.insertBefore(
-            Builder.node('span',{style: tagifyStyle},
-              character == ' ' ? String.fromCharCode(160) : character), 
-              child);
-        });
-        Element.remove(child);
-      }
-    });
-  },
-  multiple: function(element, effect) {
-    var elements;
-    if(((typeof element == 'object') || 
-        (typeof element == 'function')) && 
-       (element.length))
-      elements = element;
-    else
-      elements = $(element).childNodes;
-      
-    var options = Object.extend({
-      speed: 0.1,
-      delay: 0.0
-    }, arguments[2] || {});
-    var masterDelay = options.delay;
-
-    $A(elements).each( function(element, index) {
-      new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
-    });
-  },
-  PAIRS: {
-    'slide':  ['SlideDown','SlideUp'],
-    'blind':  ['BlindDown','BlindUp'],
-    'appear': ['Appear','Fade']
-  },
-  toggle: function(element, effect) {
-    element = $(element);
-    effect = (effect || 'appear').toLowerCase();
-    var options = Object.extend({
-      queue: { position:'end', scope:(element.id || 'global') }
-    }, arguments[2] || {});
-    Effect[Element.visible(element) ? 
-      Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
-  }
-};
-
-var Effect2 = Effect; // deprecated
-
-/* ------------- transitions ------------- */
-
-Effect.Transitions = {}
-
-Effect.Transitions.linear = function(pos) {
-  return pos;
-}
-Effect.Transitions.sinoidal = function(pos) {
-  return (-Math.cos(pos*Math.PI)/2) + 0.5;
-}
-Effect.Transitions.reverse  = function(pos) {
-  return 1-pos;
-}
-Effect.Transitions.flicker = function(pos) {
-  return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
-}
-Effect.Transitions.wobble = function(pos) {
-  return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
-}
-Effect.Transitions.pulse = function(pos) {
-  return (Math.floor(pos*10) % 2 == 0 ? 
-    (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10)));
-}
-Effect.Transitions.none = function(pos) {
-  return 0;
-}
-Effect.Transitions.full = function(pos) {
-  return 1;
-}
-
-/* ------------- core effects ------------- */
-
-Effect.ScopedQueue = Class.create();
-Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
-  initialize: function() {
-    this.effects  = [];
-    this.interval = null;
-  },
-  _each: function(iterator) {
-    this.effects._each(iterator);
-  },
-  add: function(effect) {
-    var timestamp = new Date().getTime();
-    
-    var position = (typeof effect.options.queue == 'string') ? 
-      effect.options.queue : effect.options.queue.position;
-    
-    switch(position) {
-      case 'front':
-        // move unstarted effects after this effect  
-        this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
-            e.startOn  += effect.finishOn;
-            e.finishOn += effect.finishOn;
-          });
-        break;
-      case 'end':
-        // start effect after last queued effect has finished
-        timestamp = this.effects.pluck('finishOn').max() || timestamp;
-        break;
-    }
-    
-    effect.startOn  += timestamp;
-    effect.finishOn += timestamp;
-    this.effects.push(effect);
-    if(!this.interval) 
-      this.interval = setInterval(this.loop.bind(this), 40);
-  },
-  remove: function(effect) {
-    this.effects = this.effects.reject(function(e) { return e==effect });
-    if(this.effects.length == 0) {
-      clearInterval(this.interval);
-      this.interval = null;
-    }
-  },
-  loop: function() {
-    var timePos = new Date().getTime();
-    this.effects.invoke('loop', timePos);
-  }
-});
-
-Effect.Queues = {
-  instances: $H(),
-  get: function(queueName) {
-    if(typeof queueName != 'string') return queueName;
-    
-    if(!this.instances[queueName])
-      this.instances[queueName] = new Effect.ScopedQueue();
-      
-    return this.instances[queueName];
-  }
-}
-Effect.Queue = Effect.Queues.get('global');
-
-Effect.DefaultOptions = {
-  transition: Effect.Transitions.sinoidal,
-  duration:   1.0,   // seconds
-  fps:        25.0,  // max. 25fps due to Effect.Queue implementation
-  sync:       false, // true for combining
-  from:       0.0,
-  to:         1.0,
-  delay:      0.0,
-  queue:      'parallel'
-}
-
-Effect.Base = function() {};
-Effect.Base.prototype = {
-  position: null,
-  start: function(options) {
-    this.options      = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
-    this.currentFrame = 0;
-    this.state        = 'idle';
-    this.startOn      = this.options.delay*1000;
-    this.finishOn     = this.startOn + (this.options.duration*1000);
-    this.event('beforeStart');
-    if(!this.options.sync)
-      Effect.Queues.get(typeof this.options.queue == 'string' ? 
-        'global' : this.options.queue.scope).add(this);
-  },
-  loop: function(timePos) {
-    if(timePos >= this.startOn) {
-      if(timePos >= this.finishOn) {
-        this.render(1.0);
-        this.cancel();
-        this.event('beforeFinish');
-        if(this.finish) this.finish(); 
-        this.event('afterFinish');
-        return;  
-      }
-      var pos   = (timePos - this.startOn) / (this.finishOn - this.startOn);
-      var frame = Math.round(pos * this.options.fps * this.options.duration);
-      if(frame > this.currentFrame) {
-        this.render(pos);
-        this.currentFrame = frame;
-      }
-    }
-  },
-  render: function(pos) {
-    if(this.state == 'idle') {
-      this.state = 'running';
-      this.event('beforeSetup');
-      if(this.setup) this.setup();
-      this.event('afterSetup');
-    }
-    if(this.state == 'running') {
-      if(this.options.transition) pos = this.options.transition(pos);
-      pos *= (this.options.to-this.options.from);
-      pos += this.options.from;
-      this.position = pos;
-      this.event('beforeUpdate');
-      if(this.update) this.update(pos);
-      this.event('afterUpdate');
-    }
-  },
-  cancel: function() {
-    if(!this.options.sync)
-      Effect.Queues.get(typeof this.options.queue == 'string' ? 
-        'global' : this.options.queue.scope).remove(this);
-    this.state = 'finished';
-  },
-  event: function(eventName) {
-    if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
-    if(this.options[eventName]) this.options[eventName](this);
-  },
-  inspect: function() {
-    return '#<Effect:' + $H(this).inspect() + ',options:' + $H(this.options).inspect() + '>';
-  }
-}
-
-Effect.Parallel = Class.create();
-Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
-  initialize: function(effects) {
-    this.effects = effects || [];
-    this.start(arguments[1]);
-  },
-  update: function(position) {
-    this.effects.invoke('render', position);
-  },
-  finish: function(position) {
-    this.effects.each( function(effect) {
-      effect.render(1.0);
-      effect.cancel();
-      effect.event('beforeFinish');
-      if(effect.finish) effect.finish(position);
-      effect.event('afterFinish');
-    });
-  }
-});
-
-Effect.Opacity = Class.create();
-Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
-  initialize: function(element) {
-    this.element = $(element);
-    // make this work on IE on elements without 'layout'
-    if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout))
-      Element.setStyle(this.element, {zoom: 1});
-    var options = Object.extend({
-      from: Element.getOpacity(this.element) || 0.0,
-      to:   1.0
-    }, arguments[1] || {});
-    this.start(options);
-  },
-  update: function(position) {
-    Element.setOpacity(this.element, position);
-  }
-});
-
-Effect.Move = Class.create();
-Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
-  initialize: function(element) {
-    this.element = $(element);
-    var options = Object.extend({
-      x:    0,
-      y:    0,
-      mode: 'relative'
-    }, arguments[1] || {});
-    this.start(options);
-  },
-  setup: function() {
-    // Bug in Opera: Opera returns the "real" position of a static element or
-    // relative element that does not have top/left explicitly set.
-    // ==> Always set top and left for position relative elements in your stylesheets 
-    // (to 0 if you do not need them) 
-    Element.makePositioned(this.element);
-    this.originalLeft = parseFloat(Element.getStyle(this.element,'left') || '0');
-    this.originalTop  = parseFloat(Element.getStyle(this.element,'top')  || '0');
-    if(this.options.mode == 'absolute') {
-      // absolute movement, so we need to calc deltaX and deltaY
-      this.options.x = this.options.x - this.originalLeft;
-      this.options.y = this.options.y - this.originalTop;
-    }
-  },
-  update: function(position) {
-    Element.setStyle(this.element, {
-      left: this.options.x  * position + this.originalLeft + 'px',
-      top:  this.options.y  * position + this.originalTop  + 'px'
-    });
-  }
-});
-
-// for backwards compatibility
-Effect.MoveBy = function(element, toTop, toLeft) {
-  return new Effect.Move(element, 
-    Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
-};
-
-Effect.Scale = Class.create();
-Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
-  initialize: function(element, percent) {
-    this.element = $(element)
-    var options = Object.extend({
-      scaleX: true,
-      scaleY: true,
-      scaleContent: true,
-      scaleFromCenter: false,
-      scaleMode: 'box',        // 'box' or 'contents' or {} with provided values
-      scaleFrom: 100.0,
-      scaleTo:   percent
-    }, arguments[2] || {});
-    this.start(options);
-  },
-  setup: function() {
-    this.restoreAfterFinish = this.options.restoreAfterFinish || false;
-    this.elementPositioning = Element.getStyle(this.element,'position');
-    
-    this.originalStyle = {};
-    ['top','left','width','height','fontSize'].each( function(k) {
-      this.originalStyle[k] = this.element.style[k];
-    }.bind(this));
-      
-    this.originalTop  = this.element.offsetTop;
-    this.originalLeft = this.element.offsetLeft;
-    
-    var fontSize = Element.getStyle(this.element,'font-size') || '100%';
-    ['em','px','%'].each( function(fontSizeType) {
-      if(fontSize.indexOf(fontSizeType)>0) {
-        this.fontSize     = parseFloat(fontSize);
-        this.fontSizeType = fontSizeType;
-      }
-    }.bind(this));
-    
-    this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
-    
-    this.dims = null;
-    if(this.options.scaleMode=='box')
-      this.dims = [this.element.offsetHeight, this.element.offsetWidth];
-    if(/^content/.test(this.options.scaleMode))
-      this.dims = [this.element.scrollHeight, this.element.scrollWidth];
-    if(!this.dims)
-      this.dims = [this.options.scaleMode.originalHeight,
-                   this.options.scaleMode.originalWidth];
-  },
-  update: function(position) {
-    var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
-    if(this.options.scaleContent && this.fontSize)
-      Element.setStyle(this.element, {fontSize: this.fontSize * currentScale + this.fontSizeType });
-    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
-  },
-  finish: function(position) {
-    if (this.restoreAfterFinish) Element.setStyle(this.element, this.originalStyle);
-  },
-  setDimensions: function(height, width) {
-    var d = {};
-    if(this.options.scaleX) d.width = width + 'px';
-    if(this.options.scaleY) d.height = height + 'px';
-    if(this.options.scaleFromCenter) {
-      var topd  = (height - this.dims[0])/2;
-      var leftd = (width  - this.dims[1])/2;
-      if(this.elementPositioning == 'absolute') {
-        if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
-        if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
-      } else {
-        if(this.options.scaleY) d.top = -topd + 'px';
-        if(this.options.scaleX) d.left = -leftd + 'px';
-      }
-    }
-    Element.setStyle(this.element, d);
-  }
-});
-
-Effect.Highlight = Class.create();
-Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
-  initialize: function(element) {
-    this.element = $(element);
-    var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
-    this.start(options);
-  },
-  setup: function() {
-    // Prevent executing on elements not in the layout flow
-    if(Element.getStyle(this.element, 'display')=='none') { this.cancel(); return; }
-    // Disable background image during the effect
-    this.oldStyle = {
-      backgroundImage: Element.getStyle(this.element, 'background-image') };
-    Element.setStyle(this.element, {backgroundImage: 'none'});
-    if(!this.options.endcolor)
-      this.options.endcolor = Element.getStyle(this.element, 'background-color').parseColor('#ffffff');
-    if(!this.options.restorecolor)
-      this.options.restorecolor = Element.getStyle(this.element, 'background-color');
-    // init color calculations
-    this._base  = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
-    this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
-  },
-  update: function(position) {
-    Element.setStyle(this.element,{backgroundColor: $R(0,2).inject('#',function(m,v,i){
-      return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
-  },
-  finish: function() {
-    Element.setStyle(this.element, Object.extend(this.oldStyle, {
-      backgroundColor: this.options.restorecolor
-    }));
-  }
-});
-
-Effect.ScrollTo = Class.create();
-Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
-  initialize: function(element) {
-    this.element = $(element);
-    this.start(arguments[1] || {});
-  },
-  setup: function() {
-    Position.prepare();
-    var offsets = Position.cumulativeOffset(this.element);
-    if(this.options.offset) offsets[1] += this.options.offset;
-    var max = window.innerHeight ? 
-      window.height - window.innerHeight :
-      document.body.scrollHeight - 
-        (document.documentElement.clientHeight ? 
-          document.documentElement.clientHeight : document.body.clientHeight);
-    this.scrollStart = Position.deltaY;
-    this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
-  },
-  update: function(position) {
-    Position.prepare();
-    window.scrollTo(Position.deltaX, 
-      this.scrollStart + (position*this.delta));
-  }
-});
-
-/* ------------- combination effects ------------- */
-
-Effect.Fade = function(element) {
-  var oldOpacity = Element.getInlineOpacity(element);
-  var options = Object.extend({
-  from: Element.getOpacity(element) || 1.0,
-  to:   0.0,
-  afterFinishInternal: function(effect) { with(Element) { 
-    if(effect.options.to!=0) return;
-    hide(effect.element);
-    setStyle(effect.element, {opacity: oldOpacity}); }}
-  }, arguments[1] || {});
-  return new Effect.Opacity(element,options);
-}
-
-Effect.Appear = function(element) {
-  var options = Object.extend({
-  from: (Element.getStyle(element, 'display') == 'none' ? 0.0 : Element.getOpacity(element) || 0.0),
-  to:   1.0,
-  beforeSetup: function(effect) { with(Element) {
-    setOpacity(effect.element, effect.options.from);
-    show(effect.element); }}
-  }, arguments[1] || {});
-  return new Effect.Opacity(element,options);
-}
-
-Effect.Puff = function(element) {
-  element = $(element);
-  var oldStyle = { opacity: Element.getInlineOpacity(element), position: Element.getStyle(element, 'position') };
-  return new Effect.Parallel(
-   [ new Effect.Scale(element, 200, 
-      { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), 
-     new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], 
-     Object.extend({ duration: 1.0, 
-      beforeSetupInternal: function(effect) { with(Element) {
-        setStyle(effect.effects[0].element, {position: 'absolute'}); }},
-      afterFinishInternal: function(effect) { with(Element) {
-         hide(effect.effects[0].element);
-         setStyle(effect.effects[0].element, oldStyle); }}
-     }, arguments[1] || {})
-   );
-}
-
-Effect.BlindUp = function(element) {
-  element = $(element);
-  Element.makeClipping(element);
-  return new Effect.Scale(element, 0, 
-    Object.extend({ scaleContent: false, 
-      scaleX: false, 
-      restoreAfterFinish: true,
-      afterFinishInternal: function(effect) { with(Element) {
-        [hide, undoClipping].call(effect.element); }} 
-    }, arguments[1] || {})
-  );
-}
-
-Effect.BlindDown = function(element) {
-  element = $(element);
-  var oldHeight = Element.getStyle(element, 'height');
-  var elementDimensions = Element.getDimensions(element);
-  return new Effect.Scale(element, 100, 
-    Object.extend({ scaleContent: false, 
-      scaleX: false,
-      scaleFrom: 0,
-      scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
-      restoreAfterFinish: true,
-      afterSetup: function(effect) { with(Element) {
-        makeClipping(effect.element);
-        setStyle(effect.element, {height: '0px'});
-        show(effect.element); 
-      }},  
-      afterFinishInternal: function(effect) { with(Element) {
-        undoClipping(effect.element);
-        setStyle(effect.element, {height: oldHeight});
-      }}
-    }, arguments[1] || {})
-  );
-}
-
-Effect.SwitchOff = function(element) {
-  element = $(element);
-  var oldOpacity = Element.getInlineOpacity(element);
-  return new Effect.Appear(element, { 
-    duration: 0.4,
-    from: 0,
-    transition: Effect.Transitions.flicker,
-    afterFinishInternal: function(effect) {
-      new Effect.Scale(effect.element, 1, { 
-        duration: 0.3, scaleFromCenter: true,
-        scaleX: false, scaleContent: false, restoreAfterFinish: true,
-        beforeSetup: function(effect) { with(Element) {
-          [makePositioned,makeClipping].call(effect.element);
-        }},
-        afterFinishInternal: function(effect) { with(Element) {
-          [hide,undoClipping,undoPositioned].call(effect.element);
-          setStyle(effect.element, {opacity: oldOpacity});
-        }}
-      })
-    }
-  });
-}
-
-Effect.DropOut = function(element) {
-  element = $(element);
-  var oldStyle = {
-    top: Element.getStyle(element, 'top'),
-    left: Element.getStyle(element, 'left'),
-    opacity: Element.getInlineOpacity(element) };
-  return new Effect.Parallel(
-    [ new Effect.Move(element, {x: 0, y: 100, sync: true }), 
-      new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
-    Object.extend(
-      { duration: 0.5,
-        beforeSetup: function(effect) { with(Element) {
-          makePositioned(effect.effects[0].element); }},
-        afterFinishInternal: function(effect) { with(Element) {
-          [hide, undoPositioned].call(effect.effects[0].element);
-          setStyle(effect.effects[0].element, oldStyle); }} 
-      }, arguments[1] || {}));
-}
-
-Effect.Shake = function(element) {
-  element = $(element);
-  var oldStyle = {
-    top: Element.getStyle(element, 'top'),
-    left: Element.getStyle(element, 'left') };
-         return new Effect.Move(element, 
-           { x:  20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
-         new Effect.Move(effect.element,
-           { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
-         new Effect.Move(effect.element,
-           { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
-         new Effect.Move(effect.element,
-           { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
-         new Effect.Move(effect.element,
-           { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
-         new Effect.Move(effect.element,
-           { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { with(Element) {
-        undoPositioned(effect.element);
-        setStyle(effect.element, oldStyle);
-  }}}) }}) }}) }}) }}) }});
-}
-
-Effect.SlideDown = function(element) {
-  element = $(element);
-  Element.cleanWhitespace(element);
-  // SlideDown need to have the content of the element wrapped in a container element with fixed height!
-  var oldInnerBottom = Element.getStyle(element.firstChild, 'bottom');
-  var elementDimensions = Element.getDimensions(element);
-  return new Effect.Scale(element, 100, Object.extend({ 
-    scaleContent: false, 
-    scaleX: false, 
-    scaleFrom: 0,
-    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
-    restoreAfterFinish: true,
-    afterSetup: function(effect) { with(Element) {
-      makePositioned(effect.element);
-      makePositioned(effect.element.firstChild);
-      if(window.opera) setStyle(effect.element, {top: ''});
-      makeClipping(effect.element);
-      setStyle(effect.element, {height: '0px'});
-      show(element); }},
-    afterUpdateInternal: function(effect) { with(Element) {
-      setStyle(effect.element.firstChild, {bottom:
-        (effect.dims[0] - effect.element.clientHeight) + 'px' }); }},
-    afterFinishInternal: function(effect) { with(Element) {
-      undoClipping(effect.element); 
-      undoPositioned(effect.element.firstChild);
-      undoPositioned(effect.element);
-      setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); }}
-    }, arguments[1] || {})
-  );
-}
-  
-Effect.SlideUp = function(element) {
-  element = $(element);
-  Element.cleanWhitespace(element);
-  var oldInnerBottom = Element.getStyle(element.firstChild, 'bottom');
-  return new Effect.Scale(element, 0, 
-   Object.extend({ scaleContent: false, 
-    scaleX: false, 
-    scaleMode: 'box',
-    scaleFrom: 100,
-    restoreAfterFinish: true,
-    beforeStartInternal: function(effect) { with(Element) {
-      makePositioned(effect.element);
-      makePositioned(effect.element.firstChild);
-      if(window.opera) setStyle(effect.element, {top: ''});
-      makeClipping(effect.element);
-      show(element); }},  
-    afterUpdateInternal: function(effect) { with(Element) {
-      setStyle(effect.element.firstChild, {bottom:
-        (effect.dims[0] - effect.element.clientHeight) + 'px' }); }},
-    afterFinishInternal: function(effect) { with(Element) {
-        [hide, undoClipping].call(effect.element); 
-        undoPositioned(effect.element.firstChild);
-        undoPositioned(effect.element);
-        setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); }}
-   }, arguments[1] || {})
-  );
-}
-
-// Bug in opera makes the TD containing this element expand for a instance after finish 
-Effect.Squish = function(element) {
-  return new Effect.Scale(element, window.opera ? 1 : 0, 
-    { restoreAfterFinish: true,
-      beforeSetup: function(effect) { with(Element) {
-        makeClipping(effect.element); }},  
-      afterFinishInternal: function(effect) { with(Element) {
-        hide(effect.element); 
-        undoClipping(effect.element); }}
-  });
-}
-
-Effect.Grow = function(element) {
-  element = $(element);
-  var options = Object.extend({
-    direction: 'center',
-    moveTransistion: Effect.Transitions.sinoidal,
-    scaleTransition: Effect.Transitions.sinoidal,
-    opacityTransition: Effect.Transitions.full
-  }, arguments[1] || {});
-  var oldStyle = {
-    top: element.style.top,
-    left: element.style.left,
-    height: element.style.height,
-    width: element.style.width,
-    opacity: Element.getInlineOpacity(element) };
-
-  var dims = Element.getDimensions(element);    
-  var initialMoveX, initialMoveY;
-  var moveX, moveY;
-  
-  switch (options.direction) {
-    case 'top-left':
-      initialMoveX = initialMoveY = moveX = moveY = 0; 
-      break;
-    case 'top-right':
-      initialMoveX = dims.width;
-      initialMoveY = moveY = 0;
-      moveX = -dims.width;
-      break;
-    case 'bottom-left':
-      initialMoveX = moveX = 0;
-      initialMoveY = dims.height;
-      moveY = -dims.height;
-      break;
-    case 'bottom-right':
-      initialMoveX = dims.width;
-      initialMoveY = dims.height;
-      moveX = -dims.width;
-      moveY = -dims.height;
-      break;
-    case 'center':
-      initialMoveX = dims.width / 2;
-      initialMoveY = dims.height / 2;
-      moveX = -dims.width / 2;
-      moveY = -dims.height / 2;
-      break;
-  }
-  
-  return new Effect.Move(element, {
-    x: initialMoveX,
-    y: initialMoveY,
-    duration: 0.01, 
-    beforeSetup: function(effect) { with(Element) {
-      hide(effect.element);
-      makeClipping(effect.element);
-      makePositioned(effect.element);
-    }},
-    afterFinishInternal: function(effect) {
-      new Effect.Parallel(
-        [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
-          new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
-          new Effect.Scale(effect.element, 100, {
-            scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, 
-            sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
-        ], Object.extend({
-             beforeSetup: function(effect) { with(Element) {
-               setStyle(effect.effects[0].element, {height: '0px'});
-               show(effect.effects[0].element); }},
-             afterFinishInternal: function(effect) { with(Element) {
-               [undoClipping, undoPositioned].call(effect.effects[0].element); 
-               setStyle(effect.effects[0].element, oldStyle); }}
-           }, options)
-      )
-    }
-  });
-}
-
-Effect.Shrink = function(element) {
-  element = $(element);
-  var options = Object.extend({
-    direction: 'center',
-    moveTransistion: Effect.Transitions.sinoidal,
-    scaleTransition: Effect.Transitions.sinoidal,
-    opacityTransition: Effect.Transitions.none
-  }, arguments[1] || {});
-  var oldStyle = {
-    top: element.style.top,
-    left: element.style.left,
-    height: element.style.height,
-    width: element.style.width,
-    opacity: Element.getInlineOpacity(element) };
-
-  var dims = Element.getDimensions(element);
-  var moveX, moveY;
-  
-  switch (options.direction) {
-    case 'top-left':
-      moveX = moveY = 0;
-      break;
-    case 'top-right':
-      moveX = dims.width;
-      moveY = 0;
-      break;
-    case 'bottom-left':
-      moveX = 0;
-      moveY = dims.height;
-      break;
-    case 'bottom-right':
-      moveX = dims.width;
-      moveY = dims.height;
-      break;
-    case 'center':  
-      moveX = dims.width / 2;
-      moveY = dims.height / 2;
-      break;
-  }
-  
-  return new Effect.Parallel(
-    [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
-      new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
-      new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
-    ], Object.extend({            
-         beforeStartInternal: function(effect) { with(Element) {
-           [makePositioned, makeClipping].call(effect.effects[0].element) }},
-         afterFinishInternal: function(effect) { with(Element) {
-           [hide, undoClipping, undoPositioned].call(effect.effects[0].element);
-           setStyle(effect.effects[0].element, oldStyle); }}
-       }, options)
-  );
-}
-
-Effect.Pulsate = function(element) {
-  element = $(element);
-  var options    = arguments[1] || {};
-  var oldOpacity = Element.getInlineOpacity(element);
-  var transition = options.transition || Effect.Transitions.sinoidal;
-  var reverser   = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) };
-  reverser.bind(transition);
-  return new Effect.Opacity(element, 
-    Object.extend(Object.extend({  duration: 3.0, from: 0,
-      afterFinishInternal: function(effect) { Element.setStyle(effect.element, {opacity: oldOpacity}); }
-    }, options), {transition: reverser}));
-}
-
-Effect.Fold = function(element) {
-  element = $(element);
-  var oldStyle = {
-    top: element.style.top,
-    left: element.style.left,
-    width: element.style.width,
-    height: element.style.height };
-  Element.makeClipping(element);
-  return new Effect.Scale(element, 5, Object.extend({   
-    scaleContent: false,
-    scaleX: false,
-    afterFinishInternal: function(effect) {
-    new Effect.Scale(element, 1, { 
-      scaleContent: false, 
-      scaleY: false,
-      afterFinishInternal: function(effect) { with(Element) {
-        [hide, undoClipping].call(effect.element); 
-        setStyle(effect.element, oldStyle);
-      }} });
-  }}, arguments[1] || {}));
-}
diff --git a/js/formatDate.js b/js/formatDate.js
deleted file mode 100644 (file)
index 11c6197..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-Array.prototype.exists = function (x) {
-    for (var i = 0; i < this.length; i++) {
-        if (this[i] == x) return true;
-    }
-    return false;
-}
-
-Date.prototype.formatDate = function (input,time) {
-    // formatDate :
-    // a PHP date like function, for formatting date strings
-    // See: http://www.php.net/date
-    //
-    // input : format string
-    // time : epoch time (seconds, and optional)
-    //
-    // if time is not passed, formatting is based on 
-    // the current "this" date object's set time.
-    //
-    // supported:
-    // a, A, B, d, D, F, g, G, h, H, i, j, l (lowercase L), L, 
-    // m, M, n, O, r, s, S, t, U, w, W, y, Y, z
-    //
-    // unsupported:
-    // I (capital i), T, Z    
-
-    var switches =    ["a", "A", "B", "d", "D", "F", "g", "G", "h", "H", 
-                       "i", "j", "l", "L", "m", "M", "n", "O", "r", "s", 
-                       "S", "t", "U", "w", "W", "y", "Y", "z"];
-    var daysLong =    ["Sunday", "Monday", "Tuesday", "Wednesday", 
-                       "Thursday", "Friday", "Saturday"];
-    var daysShort =   ["Sun", "Mon", "Tue", "Wed", 
-                       "Thu", "Fri", "Sat"];
-    var monthsShort = ["Jan", "Feb", "Mar", "Apr",
-                       "May", "Jun", "Jul", "Aug", "Sep",
-                       "Oct", "Nov", "Dec"];
-    var monthsLong =  ["January", "February", "March", "April",
-                       "May", "June", "July", "August", "September",
-                       "October", "November", "December"];
-    var daysSuffix = ["st", "nd", "rd", "th", "th", "th", "th", // 1st - 7th
-                      "th", "th", "th", "th", "th", "th", "th", // 8th - 14th
-                      "th", "th", "th", "th", "th", "th", "st", // 15th - 21st
-                      "nd", "rd", "th", "th", "th", "th", "th", // 22nd - 28th
-                      "th", "th", "st"];                        // 29th - 31st
-
-    function a() {
-        // Lowercase Ante meridiem and Post meridiem
-        return self.getHours() > 11? "pm" : "am";
-    }
-    function A() {
-        // Uppercase Ante meridiem and Post meridiem
-        return self.getHours() > 11? "PM" : "AM";
-    }
-
-    function B(){
-        // Swatch internet time. code simply grabbed from ppk,
-        // since I was feeling lazy:
-        // http://www.xs4all.nl/~ppk/js/beat.html
-        var off = (self.getTimezoneOffset() + 60)*60;
-        var theSeconds = (self.getHours() * 3600) + 
-                         (self.getMinutes() * 60) + 
-                          self.getSeconds() + off;
-        var beat = Math.floor(theSeconds/86.4);
-        if (beat > 1000) beat -= 1000;
-        if (beat < 0) beat += 1000;
-        if ((""+beat).length == 1) beat = "00"+beat;
-        if ((""+beat).length == 2) beat = "0"+beat;
-        return beat;
-    }
-    
-    function d() {
-        // Day of the month, 2 digits with leading zeros
-        return new String(self.getDate()).length == 1?
-        "0"+self.getDate() : self.getDate();
-    }
-    function D() {
-        // A textual representation of a day, three letters
-        return daysShort[self.getDay()];
-    }
-    function F() {
-        // A full textual representation of a month
-        return monthsLong[self.getMonth()];
-    }
-    function g() {
-        // 12-hour format of an hour without leading zeros
-        return self.getHours() > 12? self.getHours()-12 : self.getHours();
-    }
-    function G() {
-        // 24-hour format of an hour without leading zeros
-        return self.getHours();
-    }
-    function h() {
-        // 12-hour format of an hour with leading zeros
-        if (self.getHours() > 12) {
-          var s = new String(self.getHours()-12);
-          return s.length == 1?
-          "0"+ (self.getHours()-12) : self.getHours()-12;
-        } else { 
-          var s = new String(self.getHours());
-          return s.length == 1?
-          "0"+self.getHours() : self.getHours();
-        }  
-    }
-    function H() {
-        // 24-hour format of an hour with leading zeros
-        return new String(self.getHours()).length == 1?
-        "0"+self.getHours() : self.getHours();
-    }
-    function i() {
-        // Minutes with leading zeros
-        return new String(self.getMinutes()).length == 1? 
-        "0"+self.getMinutes() : self.getMinutes(); 
-    }
-    function j() {
-        // Day of the month without leading zeros
-        return self.getDate();
-    }    
-    function l() {
-        // A full textual representation of the day of the week
-        return daysLong[self.getDay()];
-    }
-    function L() {
-        // leap year or not. 1 if leap year, 0 if not.
-        // the logic should match iso's 8601 standard.
-        var y_ = Y();
-        if (         
-            (y_ % 4 == 0 && y_ % 100 != 0) ||
-            (y_ % 4 == 0 && y_ % 100 == 0 && y_ % 400 == 0)
-            ) {
-            return 1;
-        } else {
-            return 0;
-        }
-    }
-    function m() {
-        // Numeric representation of a month, with leading zeros
-        return self.getMonth() < 9?
-        "0"+(self.getMonth()+1) : 
-        self.getMonth()+1;
-    }
-    function M() {
-        // A short textual representation of a month, three letters
-        return monthsShort[self.getMonth()];
-    }
-    function n() {
-        // Numeric representation of a month, without leading zeros
-        return self.getMonth()+1;
-    }
-    function O() {
-        // Difference to Greenwich time (GMT) in hours
-        var os = Math.abs(self.getTimezoneOffset());
-        var h = ""+Math.floor(os/60);
-        var m = ""+(os%60);
-        h.length == 1? h = "0"+h:1;
-        m.length == 1? m = "0"+m:1;
-        return self.getTimezoneOffset() < 0 ? "+"+h+m : "-"+h+m;
-    }
-    function r() {
-        // RFC 822 formatted date
-        var r; // result
-        //  Thu    ,     21          Dec         2000
-        r = D() + ", " + j() + " " + M() + " " + Y() +
-        //        16     :    01     :    07          +0200
-            " " + H() + ":" + i() + ":" + s() + " " + O();
-        return r;
-    }
-    function S() {
-        // English ordinal suffix for the day of the month, 2 characters
-        return daysSuffix[self.getDate()-1];
-    }
-    function s() {
-        // Seconds, with leading zeros
-        return new String(self.getSeconds()).length == 1?
-        "0"+self.getSeconds() : self.getSeconds();
-    }
-    function t() {
-
-        // thanks to Matt Bannon for some much needed code-fixes here!
-        var daysinmonths = [null,31,28,31,30,31,30,31,31,30,31,30,31];
-        if (L()==1 && n()==2) return 29; // leap day
-        return daysinmonths[n()];
-    }
-    function U() {
-        // Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
-        return Math.round(self.getTime()/1000);
-    }
-    function W() {
-        // Weeknumber, as per ISO specification:
-        // http://www.cl.cam.ac.uk/~mgk25/iso-time.html
-        
-        // if the day is three days before newyears eve,
-        // there's a chance it's "week 1" of next year.
-        // here we check for that.
-        var beforeNY = 364+L() - z();
-        var afterNY  = z();
-        var weekday = w()!=0?w()-1:6; // makes sunday (0), into 6.
-        if (beforeNY <= 2 && weekday <= 2-beforeNY) {
-            return 1;
-        }
-        // similarly, if the day is within threedays of newyears
-        // there's a chance it belongs in the old year.
-        var ny = new Date("January 1 " + Y() + " 00:00:00");
-        var nyDay = ny.getDay()!=0?ny.getDay()-1:6;
-        if (
-            (afterNY <= 2) && 
-            (nyDay >=4)  && 
-            (afterNY >= (6-nyDay))
-            ) {
-            // Since I'm not sure we can just always return 53,
-            // i call the function here again, using the last day
-            // of the previous year, as the date, and then just
-            // return that week.
-            var prevNY = new Date("December 31 " + (Y()-1) + " 00:00:00");
-            return prevNY.formatDate("W");
-        }
-        
-        // week 1, is the week that has the first thursday in it.
-        // note that this value is not zero index.
-        if (nyDay <= 3) {
-            // first day of the year fell on a thursday, or earlier.
-            return 1 + Math.floor( ( z() + nyDay ) / 7 );
-        } else {
-            // first day of the year fell on a friday, or later.
-            return 1 + Math.floor( ( z() - ( 7 - nyDay ) ) / 7 );
-        }
-    }
-    function w() {
-        // Numeric representation of the day of the week
-        return self.getDay();
-    }
-    
-    function Y() {
-        // A full numeric representation of a year, 4 digits
-
-        // we first check, if getFullYear is supported. if it
-        // is, we just use that. ppks code is nice, but wont
-        // work with dates outside 1900-2038, or something like that
-        if (self.getFullYear) {
-            var newDate = new Date("January 1 2001 00:00:00 +0000");
-            var x = newDate .getFullYear();
-            if (x == 2001) {              
-                // i trust the method now
-                return self.getFullYear();
-            }
-        }
-        // else, do this:
-        // codes thanks to ppk:
-        // http://www.xs4all.nl/~ppk/js/introdate.html
-        var x = self.getYear();
-        var y = x % 100;
-        y += (y < 38) ? 2000 : 1900;
-        return y;
-    }
-    function y() {
-        // A two-digit representation of a year
-        var y = Y()+"";
-        return y.substring(y.length-2,y.length);
-    }
-    function z() {
-        // The day of the year, zero indexed! 0 through 366
-        var t = new Date("January 1 " + Y() + " 00:00:00");
-        var diff = self.getTime() - t.getTime();
-        return Math.floor(diff/1000/60/60/24);
-    }
-        
-    var self = this;
-    if (time) {
-        // save time
-        var prevTime = self.getTime();
-        self.setTime(time);
-    }
-    
-    var ia = input.split("");
-    var ij = 0;
-    while (ia[ij]) {
-        if (ia[ij] == "\\") {
-            // this is our way of allowing users to escape stuff
-            ia.splice(ij,1);
-        } else {
-            if (switches.exists(ia[ij])) {
-                ia[ij] = eval(ia[ij] + "()");
-            }
-        }
-        ij++;
-    }
-    // reset time, back to what it was
-    if (prevTime) {
-        self.setTime(prevTime);
-    }
-    return ia.join("");
-}
diff --git a/js/gui.js b/js/gui.js
deleted file mode 100644 (file)
index c048c99..0000000
--- a/js/gui.js
+++ /dev/null
@@ -1,148 +0,0 @@
-
-function tedit_showEditor(dn){
-  // if the editor already exists cancel it
-  if($('tedit_editor') !== null){
-    tedit_cleanUp();
-    return;
-  }
-
-  var tags = $('tedit_out').innerHTML;
-  tags = tags.replace(/>[ \n\r]+<a/g,'>, <a');
-  tags = tags.stripTags();
-  tags = tags.replace(/[ \n\r]{2,}/g,' ');
-  tags = tags.replace(/^ /,'');
-  tags = tags.replace(/ $/,'');
-
-  var editor  = '<div id="tedit_editor"><form accept-charset="utf-8">';
-      editor += '<textarea id="tedit_edit">'+tags+'</textarea>';
-      editor += '<div id="tedit_completion" class="autocomplete"></div>';
-      editor += '<img src="pix/accept.png" width="16" height="16" id="tedit_save" class="click" alt="save" /><br />';
-      editor += '<img src="pix/cancel.png" width="16" height="16" id="tedit_cancel" class="click" alt="cancel" />';
-      editor += '</form></div>';
-
-  Element.hide('tedit_out');
-  new Insertion.Top($('tedit_insert'), editor);
-
-  new Ajax.Autocompleter('tedit_edit','tedit_completion', 'ajax.php', {paramName: 'taglookup', tokens: ','});
-
-  Event.observe('tedit_save', 'click', function(){ tedit_saveChanges(dn) }, false);
-  Event.observe('tedit_cancel', 'click', tedit_cleanUp, false);
-  $('tedit_edit').focus();
-}
-
-function tedit_cleanUp(){
-  Element.remove('tedit_editor');
-  Element.show('tedit_out');
-}
-
-function tedit_saveChanges(dn){
-  var content = encodeURI($F('tedit_edit'));
-  dn = encodeURI(dn);
-
-  $('tedit_editor').innerHTML = "Saving...";
-
-  var success = function(resp){tedit_complete(resp)};
-  var failure = function(resp){tedit_failed(resp)};
-  var pars    = 'settags='+dn+'&tags='+content;
-
-  var ajax = new Ajax.Request('ajax.php', {method:'post',postBody:pars,onSuccess:success,onFailure:failure});
-}
-
-function tedit_complete(resp){
-  $('tedit_out').innerHTML = resp.responseText;
-  tedit_cleanUp();
-}
-
-function tedit_failed(resp){
-  tedit_cleanUp();
-  alert("Saving failed.");
-}
-
-
-
-// --------------------------------------------------------------------
-
-/**
- * Create the editor component
- */
-function nedit_showEditor(type,dn,name){
-  // if the editor already exists cancel it
-  if($('nedit_editor') !== null){
-    nedit_cleanUp();
-    return;
-  }
-
-  var editor = '<div id="nedit_editor"><form accept-charset="utf-8">';
-  editor += '<textarea id="nedit_edit">';
-  if(type=='call'){
-    editor += '**Call** ';
-  }else if(type=='mail'){
-    editor += '**Mail** ';
-  }else if(type=='todo'){
-    editor += '**Todo** ';
-  }else if(type=='note'){
-    editor += '**Note** ';
-  }
-
-  var dt = new Date();
-  editor += '//'+dt.formatDate('j. M y H:i')+' '+name+'//: ';
-  editor += '</textarea>';
-
-  editor += '<img src="pix/accept.png" width="16" height="16" id="nedit_save" class="click" alt="save" /><br />';
-  editor += '<img src="pix/cancel.png" width="16" height="16" id="nedit_cancel" class="click" alt="cancel" />';
-  editor += '</form></div>';
-
-  new Insertion.Top($('nedit_insert'), editor);
-
-  Event.observe('nedit_save', 'click', function(){ nedit_saveChanges(dn) }, false);
-  Event.observe('nedit_cancel', 'click', nedit_cleanUp, false);
-  $('nedit_edit').focus();
-};
-
-function nedit_cleanUp(){
-  Element.remove('nedit_editor');
-}
-
-function nedit_saveChanges(dn){
-  var content = encodeURI($F('nedit_edit'));
-  dn = encodeURI(dn);
-  
-  $('nedit_editor').innerHTML = "Saving...";
-
-  var success = function(resp){nedit_complete(resp)};
-  var failure = function(resp){nedit_failed(resp)};
-  var pars    = 'addnote='+dn+'&note='+content;
-
-  var ajax = new Ajax.Request('ajax.php', {method:'post',postBody:pars,onSuccess:success,onFailure:failure});
-}
-
-function nedit_complete(resp){
-  nedit_cleanUp();
-  $('nedit_insert').innerHTML = resp.responseText;
-}
-
-function nedit_failed(resp){
-  nedit_cleanUp();
-  alert("Saving failed.");
-}
-
-
-
-/**
- * initializes all the JS GUI-Stuff
- */
-function init(){
-  if($('taglookup') !== null)
-    new Ajax.Autocompleter('taglookup','tagresult', 'ajax.php', {paramName: 'taglookup', tokens: ','});
-  if($('tageditlookup') !== null)
-    new Ajax.Autocompleter('tageditlookup','tageditresult', 'ajax.php', {paramName: 'taglookup', tokens: ','});
-
-  if($('searchfield') !== null)
-    $('searchfield').focus();
-
-  if($('firstfield') !== null)
-    $('firstfield').focus();
-}
-
-Event.observe(window, 'load', init, false);
-
diff --git a/js/prototype.js b/js/prototype.js
deleted file mode 100644 (file)
index e9ccd3c..0000000
+++ /dev/null
@@ -1,1785 +0,0 @@
-/*  Prototype JavaScript framework, version 1.4.0
- *  (c) 2005 Sam Stephenson <sam@conio.net>
- *
- *  THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
- *  against the source tree, available from the Prototype darcs repository.
- *
- *  Prototype is freely distributable under the terms of an MIT-style license.
- *
- *  For details, see the Prototype web site: http://prototype.conio.net/
- *
-/*--------------------------------------------------------------------------*/
-
-var Prototype = {
-  Version: '1.4.0',
-  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
-
-  emptyFunction: function() {},
-  K: function(x) {return x}
-}
-
-var Class = {
-  create: function() {
-    return function() {
-      this.initialize.apply(this, arguments);
-    }
-  }
-}
-
-var Abstract = new Object();
-
-Object.extend = function(destination, source) {
-  for (property in source) {
-    destination[property] = source[property];
-  }
-  return destination;
-}
-
-Object.inspect = function(object) {
-  try {
-    if (object == undefined) return 'undefined';
-    if (object == null) return 'null';
-    return object.inspect ? object.inspect() : object.toString();
-  } catch (e) {
-    if (e instanceof RangeError) return '...';
-    throw e;
-  }
-}
-
-Function.prototype.bind = function() {
-  var __method = this, args = $A(arguments), object = args.shift();
-  return function() {
-    return __method.apply(object, args.concat($A(arguments)));
-  }
-}
-
-Function.prototype.bindAsEventListener = function(object) {
-  var __method = this;
-  return function(event) {
-    return __method.call(object, event || window.event);
-  }
-}
-
-Object.extend(Number.prototype, {
-  toColorPart: function() {
-    var digits = this.toString(16);
-    if (this < 16) return '0' + digits;
-    return digits;
-  },
-
-  succ: function() {
-    return this + 1;
-  },
-
-  times: function(iterator) {
-    $R(0, this, true).each(iterator);
-    return this;
-  }
-});
-
-var Try = {
-  these: function() {
-    var returnValue;
-
-    for (var i = 0; i < arguments.length; i++) {
-      var lambda = arguments[i];
-      try {
-        returnValue = lambda();
-        break;
-      } catch (e) {}
-    }
-
-    return returnValue;
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var PeriodicalExecuter = Class.create();
-PeriodicalExecuter.prototype = {
-  initialize: function(callback, frequency) {
-    this.callback = callback;
-    this.frequency = frequency;
-    this.currentlyExecuting = false;
-
-    this.registerCallback();
-  },
-
-  registerCallback: function() {
-    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
-  },
-
-  onTimerEvent: function() {
-    if (!this.currentlyExecuting) {
-      try {
-        this.currentlyExecuting = true;
-        this.callback();
-      } finally {
-        this.currentlyExecuting = false;
-      }
-    }
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-function $() {
-  var elements = new Array();
-
-  for (var i = 0; i < arguments.length; i++) {
-    var element = arguments[i];
-    if (typeof element == 'string')
-      element = document.getElementById(element);
-
-    if (arguments.length == 1)
-      return element;
-
-    elements.push(element);
-  }
-
-  return elements;
-}
-Object.extend(String.prototype, {
-  stripTags: function() {
-    return this.replace(/<\/?[^>]+>/gi, '');
-  },
-
-  stripScripts: function() {
-    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
-  },
-
-  extractScripts: function() {
-    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
-    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
-    return (this.match(matchAll) || []).map(function(scriptTag) {
-      return (scriptTag.match(matchOne) || ['', ''])[1];
-    });
-  },
-
-  evalScripts: function() {
-    return this.extractScripts().map(eval);
-  },
-
-  escapeHTML: function() {
-    var div = document.createElement('div');
-    var text = document.createTextNode(this);
-    div.appendChild(text);
-    return div.innerHTML;
-  },
-
-  unescapeHTML: function() {
-    var div = document.createElement('div');
-    div.innerHTML = this.stripTags();
-    return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
-  },
-
-  toQueryParams: function() {
-    var pairs = this.match(/^\??(.*)$/)[1].split('&');
-    return pairs.inject({}, function(params, pairString) {
-      var pair = pairString.split('=');
-      params[pair[0]] = pair[1];
-      return params;
-    });
-  },
-
-  toArray: function() {
-    return this.split('');
-  },
-
-  camelize: function() {
-    var oStringList = this.split('-');
-    if (oStringList.length == 1) return oStringList[0];
-
-    var camelizedString = this.indexOf('-') == 0
-      ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
-      : oStringList[0];
-
-    for (var i = 1, len = oStringList.length; i < len; i++) {
-      var s = oStringList[i];
-      camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
-    }
-
-    return camelizedString;
-  },
-
-  inspect: function() {
-    return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
-  }
-});
-
-String.prototype.parseQuery = String.prototype.toQueryParams;
-
-var $break    = new Object();
-var $continue = new Object();
-
-var Enumerable = {
-  each: function(iterator) {
-    var index = 0;
-    try {
-      this._each(function(value) {
-        try {
-          iterator(value, index++);
-        } catch (e) {
-          if (e != $continue) throw e;
-        }
-      });
-    } catch (e) {
-      if (e != $break) throw e;
-    }
-  },
-
-  all: function(iterator) {
-    var result = true;
-    this.each(function(value, index) {
-      result = result && !!(iterator || Prototype.K)(value, index);
-      if (!result) throw $break;
-    });
-    return result;
-  },
-
-  any: function(iterator) {
-    var result = true;
-    this.each(function(value, index) {
-      if (result = !!(iterator || Prototype.K)(value, index))
-        throw $break;
-    });
-    return result;
-  },
-
-  collect: function(iterator) {
-    var results = [];
-    this.each(function(value, index) {
-      results.push(iterator(value, index));
-    });
-    return results;
-  },
-
-  detect: function (iterator) {
-    var result;
-    this.each(function(value, index) {
-      if (iterator(value, index)) {
-        result = value;
-        throw $break;
-      }
-    });
-    return result;
-  },
-
-  findAll: function(iterator) {
-    var results = [];
-    this.each(function(value, index) {
-      if (iterator(value, index))
-        results.push(value);
-    });
-    return results;
-  },
-
-  grep: function(pattern, iterator) {
-    var results = [];
-    this.each(function(value, index) {
-      var stringValue = value.toString();
-      if (stringValue.match(pattern))
-        results.push((iterator || Prototype.K)(value, index));
-    })
-    return results;
-  },
-
-  include: function(object) {
-    var found = false;
-    this.each(function(value) {
-      if (value == object) {
-        found = true;
-        throw $break;
-      }
-    });
-    return found;
-  },
-
-  inject: function(memo, iterator) {
-    this.each(function(value, index) {
-      memo = iterator(memo, value, index);
-    });
-    return memo;
-  },
-
-  invoke: function(method) {
-    var args = $A(arguments).slice(1);
-    return this.collect(function(value) {
-      return value[method].apply(value, args);
-    });
-  },
-
-  max: function(iterator) {
-    var result;
-    this.each(function(value, index) {
-      value = (iterator || Prototype.K)(value, index);
-      if (value >= (result || value))
-        result = value;
-    });
-    return result;
-  },
-
-  min: function(iterator) {
-    var result;
-    this.each(function(value, index) {
-      value = (iterator || Prototype.K)(value, index);
-      if (value <= (result || value))
-        result = value;
-    });
-    return result;
-  },
-
-  partition: function(iterator) {
-    var trues = [], falses = [];
-    this.each(function(value, index) {
-      ((iterator || Prototype.K)(value, index) ?
-        trues : falses).push(value);
-    });
-    return [trues, falses];
-  },
-
-  pluck: function(property) {
-    var results = [];
-    this.each(function(value, index) {
-      results.push(value[property]);
-    });
-    return results;
-  },
-
-  reject: function(iterator) {
-    var results = [];
-    this.each(function(value, index) {
-      if (!iterator(value, index))
-        results.push(value);
-    });
-    return results;
-  },
-
-  sortBy: function(iterator) {
-    return this.collect(function(value, index) {
-      return {value: value, criteria: iterator(value, index)};
-    }).sort(function(left, right) {
-      var a = left.criteria, b = right.criteria;
-      return a < b ? -1 : a > b ? 1 : 0;
-    }).pluck('value');
-  },
-
-  toArray: function() {
-    return this.collect(Prototype.K);
-  },
-
-  zip: function() {
-    var iterator = Prototype.K, args = $A(arguments);
-    if (typeof args.last() == 'function')
-      iterator = args.pop();
-
-    var collections = [this].concat(args).map($A);
-    return this.map(function(value, index) {
-      iterator(value = collections.pluck(index));
-      return value;
-    });
-  },
-
-  inspect: function() {
-    return '#<Enumerable:' + this.toArray().inspect() + '>';
-  }
-}
-
-Object.extend(Enumerable, {
-  map:     Enumerable.collect,
-  find:    Enumerable.detect,
-  select:  Enumerable.findAll,
-  member:  Enumerable.include,
-  entries: Enumerable.toArray
-});
-var $A = Array.from = function(iterable) {
-  if (!iterable) return [];
-  if (iterable.toArray) {
-    return iterable.toArray();
-  } else {
-    var results = [];
-    for (var i = 0; i < iterable.length; i++)
-      results.push(iterable[i]);
-    return results;
-  }
-}
-
-Object.extend(Array.prototype, Enumerable);
-
-Array.prototype._reverse = Array.prototype.reverse;
-
-Object.extend(Array.prototype, {
-  _each: function(iterator) {
-    for (var i = 0; i < this.length; i++)
-      iterator(this[i]);
-  },
-
-  clear: function() {
-    this.length = 0;
-    return this;
-  },
-
-  first: function() {
-    return this[0];
-  },
-
-  last: function() {
-    return this[this.length - 1];
-  },
-
-  compact: function() {
-    return this.select(function(value) {
-      return value != undefined || value != null;
-    });
-  },
-
-  flatten: function() {
-    return this.inject([], function(array, value) {
-      return array.concat(value.constructor == Array ?
-        value.flatten() : [value]);
-    });
-  },
-
-  without: function() {
-    var values = $A(arguments);
-    return this.select(function(value) {
-      return !values.include(value);
-    });
-  },
-
-  indexOf: function(object) {
-    for (var i = 0; i < this.length; i++)
-      if (this[i] == object) return i;
-    return -1;
-  },
-
-  reverse: function(inline) {
-    return (inline !== false ? this : this.toArray())._reverse();
-  },
-
-  shift: function() {
-    var result = this[0];
-    for (var i = 0; i < this.length - 1; i++)
-      this[i] = this[i + 1];
-    this.length--;
-    return result;
-  },
-
-  inspect: function() {
-    return '[' + this.map(Object.inspect).join(', ') + ']';
-  }
-});
-var Hash = {
-  _each: function(iterator) {
-    for (key in this) {
-      var value = this[key];
-      if (typeof value == 'function') continue;
-
-      var pair = [key, value];
-      pair.key = key;
-      pair.value = value;
-      iterator(pair);
-    }
-  },
-
-  keys: function() {
-    return this.pluck('key');
-  },
-
-  values: function() {
-    return this.pluck('value');
-  },
-
-  merge: function(hash) {
-    return $H(hash).inject($H(this), function(mergedHash, pair) {
-      mergedHash[pair.key] = pair.value;
-      return mergedHash;
-    });
-  },
-
-  toQueryString: function() {
-    return this.map(function(pair) {
-      return pair.map(encodeURIComponent).join('=');
-    }).join('&');
-  },
-
-  inspect: function() {
-    return '#<Hash:{' + this.map(function(pair) {
-      return pair.map(Object.inspect).join(': ');
-    }).join(', ') + '}>';
-  }
-}
-
-function $H(object) {
-  var hash = Object.extend({}, object || {});
-  Object.extend(hash, Enumerable);
-  Object.extend(hash, Hash);
-  return hash;
-}
-ObjectRange = Class.create();
-Object.extend(ObjectRange.prototype, Enumerable);
-Object.extend(ObjectRange.prototype, {
-  initialize: function(start, end, exclusive) {
-    this.start = start;
-    this.end = end;
-    this.exclusive = exclusive;
-  },
-
-  _each: function(iterator) {
-    var value = this.start;
-    do {
-      iterator(value);
-      value = value.succ();
-    } while (this.include(value));
-  },
-
-  include: function(value) {
-    if (value < this.start)
-      return false;
-    if (this.exclusive)
-      return value < this.end;
-    return value <= this.end;
-  }
-});
-
-var $R = function(start, end, exclusive) {
-  return new ObjectRange(start, end, exclusive);
-}
-
-var Ajax = {
-  getTransport: function() {
-    return Try.these(
-      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
-      function() {return new ActiveXObject('Microsoft.XMLHTTP')},
-      function() {return new XMLHttpRequest()}
-    ) || false;
-  },
-
-  activeRequestCount: 0
-}
-
-Ajax.Responders = {
-  responders: [],
-
-  _each: function(iterator) {
-    this.responders._each(iterator);
-  },
-
-  register: function(responderToAdd) {
-    if (!this.include(responderToAdd))
-      this.responders.push(responderToAdd);
-  },
-
-  unregister: function(responderToRemove) {
-    this.responders = this.responders.without(responderToRemove);
-  },
-
-  dispatch: function(callback, request, transport, json) {
-    this.each(function(responder) {
-      if (responder[callback] && typeof responder[callback] == 'function') {
-        try {
-          responder[callback].apply(responder, [request, transport, json]);
-        } catch (e) {}
-      }
-    });
-  }
-};
-
-Object.extend(Ajax.Responders, Enumerable);
-
-Ajax.Responders.register({
-  onCreate: function() {
-    Ajax.activeRequestCount++;
-  },
-
-  onComplete: function() {
-    Ajax.activeRequestCount--;
-  }
-});
-
-Ajax.Base = function() {};
-Ajax.Base.prototype = {
-  setOptions: function(options) {
-    this.options = {
-      method:       'post',
-      asynchronous: true,
-      parameters:   ''
-    }
-    Object.extend(this.options, options || {});
-  },
-
-  responseIsSuccess: function() {
-    return this.transport.status == undefined
-        || this.transport.status == 0
-        || (this.transport.status >= 200 && this.transport.status < 300);
-  },
-
-  responseIsFailure: function() {
-    return !this.responseIsSuccess();
-  }
-}
-
-Ajax.Request = Class.create();
-Ajax.Request.Events =
-  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
-
-Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
-  initialize: function(url, options) {
-    this.transport = Ajax.getTransport();
-    this.setOptions(options);
-    this.request(url);
-  },
-
-  request: function(url) {
-    var parameters = this.options.parameters || '';
-    if (parameters.length > 0) parameters += '&_=';
-
-    try {
-      this.url = url;
-      if (this.options.method == 'get' && parameters.length > 0)
-        this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
-
-      Ajax.Responders.dispatch('onCreate', this, this.transport);
-
-      this.transport.open(this.options.method, this.url,
-        this.options.asynchronous);
-
-      if (this.options.asynchronous) {
-        this.transport.onreadystatechange = this.onStateChange.bind(this);
-        setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
-      }
-
-      this.setRequestHeaders();
-
-      var body = this.options.postBody ? this.options.postBody : parameters;
-      this.transport.send(this.options.method == 'post' ? body : null);
-
-    } catch (e) {
-      this.dispatchException(e);
-    }
-  },
-
-  setRequestHeaders: function() {
-    var requestHeaders =
-      ['X-Requested-With', 'XMLHttpRequest',
-       'X-Prototype-Version', Prototype.Version];
-
-    if (this.options.method == 'post') {
-      requestHeaders.push('Content-type',
-        'application/x-www-form-urlencoded');
-
-      /* Force "Connection: close" for Mozilla browsers to work around
-       * a bug where XMLHttpReqeuest sends an incorrect Content-length
-       * header. See Mozilla Bugzilla #246651.
-       */
-      if (this.transport.overrideMimeType)
-        requestHeaders.push('Connection', 'close');
-    }
-
-    if (this.options.requestHeaders)
-      requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
-
-    for (var i = 0; i < requestHeaders.length; i += 2)
-      this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
-  },
-
-  onStateChange: function() {
-    var readyState = this.transport.readyState;
-    if (readyState != 1)
-      this.respondToReadyState(this.transport.readyState);
-  },
-
-  header: function(name) {
-    try {
-      return this.transport.getResponseHeader(name);
-    } catch (e) {}
-  },
-
-  evalJSON: function() {
-    try {
-      return eval(this.header('X-JSON'));
-    } catch (e) {}
-  },
-
-  evalResponse: function() {
-    try {
-      return eval(this.transport.responseText);
-    } catch (e) {
-      this.dispatchException(e);
-    }
-  },
-
-  respondToReadyState: function(readyState) {
-    var event = Ajax.Request.Events[readyState];
-    var transport = this.transport, json = this.evalJSON();
-
-    if (event == 'Complete') {
-      try {
-        (this.options['on' + this.transport.status]
-         || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
-         || Prototype.emptyFunction)(transport, json);
-      } catch (e) {
-        this.dispatchException(e);
-      }
-
-      if ((this.header('Content-type') || '').match(/^text\/javascript/i))
-        this.evalResponse();
-    }
-
-    try {
-      (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
-      Ajax.Responders.dispatch('on' + event, this, transport, json);
-    } catch (e) {
-      this.dispatchException(e);
-    }
-
-    /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
-    if (event == 'Complete')
-      this.transport.onreadystatechange = Prototype.emptyFunction;
-  },
-
-  dispatchException: function(exception) {
-    (this.options.onException || Prototype.emptyFunction)(this, exception);
-    Ajax.Responders.dispatch('onException', this, exception);
-  }
-});
-
-Ajax.Updater = Class.create();
-
-Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
-  initialize: function(container, url, options) {
-    this.containers = {
-      success: container.success ? $(container.success) : $(container),
-      failure: container.failure ? $(container.failure) :
-        (container.success ? null : $(container))
-    }
-
-    this.transport = Ajax.getTransport();
-    this.setOptions(options);
-
-    var onComplete = this.options.onComplete || Prototype.emptyFunction;
-    this.options.onComplete = (function(transport, object) {
-      this.updateContent();
-      onComplete(transport, object);
-    }).bind(this);
-
-    this.request(url);
-  },
-
-  updateContent: function() {
-    var receiver = this.responseIsSuccess() ?
-      this.containers.success : this.containers.failure;
-    var response = this.transport.responseText;
-
-    if (!this.options.evalScripts)
-      response = response.stripScripts();
-
-    if (receiver) {
-      if (this.options.insertion) {
-        new this.options.insertion(receiver, response);
-      } else {
-        Element.update(receiver, response);
-      }
-    }
-
-    if (this.responseIsSuccess()) {
-      if (this.onComplete)
-        setTimeout(this.onComplete.bind(this), 10);
-    }
-  }
-});
-
-Ajax.PeriodicalUpdater = Class.create();
-Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
-  initialize: function(container, url, options) {
-    this.setOptions(options);
-    this.onComplete = this.options.onComplete;
-
-    this.frequency = (this.options.frequency || 2);
-    this.decay = (this.options.decay || 1);
-
-    this.updater = {};
-    this.container = container;
-    this.url = url;
-
-    this.start();
-  },
-
-  start: function() {
-    this.options.onComplete = this.updateComplete.bind(this);
-    this.onTimerEvent();
-  },
-
-  stop: function() {
-    this.updater.onComplete = undefined;
-    clearTimeout(this.timer);
-    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
-  },
-
-  updateComplete: function(request) {
-    if (this.options.decay) {
-      this.decay = (request.responseText == this.lastText ?
-        this.decay * this.options.decay : 1);
-
-      this.lastText = request.responseText;
-    }
-    this.timer = setTimeout(this.onTimerEvent.bind(this),
-      this.decay * this.frequency * 1000);
-  },
-
-  onTimerEvent: function() {
-    this.updater = new Ajax.Updater(this.container, this.url, this.options);
-  }
-});
-document.getElementsByClassName = function(className, parentElement) {
-  var children = ($(parentElement) || document.body).getElementsByTagName('*');
-  return $A(children).inject([], function(elements, child) {
-    if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
-      elements.push(child);
-    return elements;
-  });
-}
-
-/*--------------------------------------------------------------------------*/
-
-if (!window.Element) {
-  var Element = new Object();
-}
-
-Object.extend(Element, {
-  visible: function(element) {
-    return $(element).style.display != 'none';
-  },
-
-  toggle: function() {
-    for (var i = 0; i < arguments.length; i++) {
-      var element = $(arguments[i]);
-      Element[Element.visible(element) ? 'hide' : 'show'](element);
-    }
-  },
-
-  hide: function() {
-    for (var i = 0; i < arguments.length; i++) {
-      var element = $(arguments[i]);
-      element.style.display = 'none';
-    }
-  },
-
-  show: function() {
-    for (var i = 0; i < arguments.length; i++) {
-      var element = $(arguments[i]);
-      element.style.display = '';
-    }
-  },
-
-  remove: function(element) {
-    element = $(element);
-    element.parentNode.removeChild(element);
-  },
-
-  update: function(element, html) {
-    $(element).innerHTML = html.stripScripts();
-    setTimeout(function() {html.evalScripts()}, 10);
-  },
-
-  getHeight: function(element) {
-    element = $(element);
-    return element.offsetHeight;
-  },
-
-  classNames: function(element) {
-    return new Element.ClassNames(element);
-  },
-
-  hasClassName: function(element, className) {
-    if (!(element = $(element))) return;
-    return Element.classNames(element).include(className);
-  },
-
-  addClassName: function(element, className) {
-    if (!(element = $(element))) return;
-    return Element.classNames(element).add(className);
-  },
-
-  removeClassName: function(element, className) {
-    if (!(element = $(element))) return;
-    return Element.classNames(element).remove(className);
-  },
-
-  // removes whitespace-only text node children
-  cleanWhitespace: function(element) {
-    element = $(element);
-    for (var i = 0; i < element.childNodes.length; i++) {
-      var node = element.childNodes[i];
-      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
-        Element.remove(node);
-    }
-  },
-
-  empty: function(element) {
-    return $(element).innerHTML.match(/^\s*$/);
-  },
-
-  scrollTo: function(element) {
-    element = $(element);
-    var x = element.x ? element.x : element.offsetLeft,
-        y = element.y ? element.y : element.offsetTop;
-    window.scrollTo(x, y);
-  },
-
-  getStyle: function(element, style) {
-    element = $(element);
-    var value = element.style[style.camelize()];
-    if (!value) {
-      if (document.defaultView && document.defaultView.getComputedStyle) {
-        var css = document.defaultView.getComputedStyle(element, null);
-        value = css ? css.getPropertyValue(style) : null;
-      } else if (element.currentStyle) {
-        value = element.currentStyle[style.camelize()];
-      }
-    }
-
-    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
-      if (Element.getStyle(element, 'position') == 'static') value = 'auto';
-
-    return value == 'auto' ? null : value;
-  },
-
-  setStyle: function(element, style) {
-    element = $(element);
-    for (name in style)
-      element.style[name.camelize()] = style[name];
-  },
-
-  getDimensions: function(element) {
-    element = $(element);
-    if (Element.getStyle(element, 'display') != 'none')
-      return {width: element.offsetWidth, height: element.offsetHeight};
-
-    // All *Width and *Height properties give 0 on elements with display none,
-    // so enable the element temporarily
-    var els = element.style;
-    var originalVisibility = els.visibility;
-    var originalPosition = els.position;
-    els.visibility = 'hidden';
-    els.position = 'absolute';
-    els.display = '';
-    var originalWidth = element.clientWidth;
-    var originalHeight = element.clientHeight;
-    els.display = 'none';
-    els.position = originalPosition;
-    els.visibility = originalVisibility;
-    return {width: originalWidth, height: originalHeight};
-  },
-
-  makePositioned: function(element) {
-    element = $(element);
-    var pos = Element.getStyle(element, 'position');
-    if (pos == 'static' || !pos) {
-      element._madePositioned = true;
-      element.style.position = 'relative';
-      // Opera returns the offset relative to the positioning context, when an
-      // element is position relative but top and left have not been defined
-      if (window.opera) {
-        element.style.top = 0;
-        element.style.left = 0;
-      }
-    }
-  },
-
-  undoPositioned: function(element) {
-    element = $(element);
-    if (element._madePositioned) {
-      element._madePositioned = undefined;
-      element.style.position =
-        element.style.top =
-        element.style.left =
-        element.style.bottom =
-        element.style.right = '';
-    }
-  },
-
-  makeClipping: function(element) {
-    element = $(element);
-    if (element._overflow) return;
-    element._overflow = element.style.overflow;
-    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
-      element.style.overflow = 'hidden';
-  },
-
-  undoClipping: function(element) {
-    element = $(element);
-    if (element._overflow) return;
-    element.style.overflow = element._overflow;
-    element._overflow = undefined;
-  }
-});
-
-var Toggle = new Object();
-Toggle.display = Element.toggle;
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.Insertion = function(adjacency) {
-  this.adjacency = adjacency;
-}
-
-Abstract.Insertion.prototype = {
-  initialize: function(element, content) {
-    this.element = $(element);
-    this.content = content.stripScripts();
-
-    if (this.adjacency && this.element.insertAdjacentHTML) {
-      try {
-        this.element.insertAdjacentHTML(this.adjacency, this.content);
-      } catch (e) {
-        if (this.element.tagName.toLowerCase() == 'tbody') {
-          this.insertContent(this.contentFromAnonymousTable());
-        } else {
-          throw e;
-        }
-      }
-    } else {
-      this.range = this.element.ownerDocument.createRange();
-      if (this.initializeRange) this.initializeRange();
-      this.insertContent([this.range.createContextualFragment(this.content)]);
-    }
-
-    setTimeout(function() {content.evalScripts()}, 10);
-  },
-
-  contentFromAnonymousTable: function() {
-    var div = document.createElement('div');
-    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
-    return $A(div.childNodes[0].childNodes[0].childNodes);
-  }
-}
-
-var Insertion = new Object();
-
-Insertion.Before = Class.create();
-Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
-  initializeRange: function() {
-    this.range.setStartBefore(this.element);
-  },
-
-  insertContent: function(fragments) {
-    fragments.each((function(fragment) {
-      this.element.parentNode.insertBefore(fragment, this.element);
-    }).bind(this));
-  }
-});
-
-Insertion.Top = Class.create();
-Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
-  initializeRange: function() {
-    this.range.selectNodeContents(this.element);
-    this.range.collapse(true);
-  },
-
-  insertContent: function(fragments) {
-    fragments.reverse(false).each((function(fragment) {
-      this.element.insertBefore(fragment, this.element.firstChild);
-    }).bind(this));
-  }
-});
-
-Insertion.Bottom = Class.create();
-Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
-  initializeRange: function() {
-    this.range.selectNodeContents(this.element);
-    this.range.collapse(this.element);
-  },
-
-  insertContent: function(fragments) {
-    fragments.each((function(fragment) {
-      this.element.appendChild(fragment);
-    }).bind(this));
-  }
-});
-
-Insertion.After = Class.create();
-Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
-  initializeRange: function() {
-    this.range.setStartAfter(this.element);
-  },
-
-  insertContent: function(fragments) {
-    fragments.each((function(fragment) {
-      this.element.parentNode.insertBefore(fragment,
-        this.element.nextSibling);
-    }).bind(this));
-  }
-});
-
-/*--------------------------------------------------------------------------*/
-
-Element.ClassNames = Class.create();
-Element.ClassNames.prototype = {
-  initialize: function(element) {
-    this.element = $(element);
-  },
-
-  _each: function(iterator) {
-    this.element.className.split(/\s+/).select(function(name) {
-      return name.length > 0;
-    })._each(iterator);
-  },
-
-  set: function(className) {
-    this.element.className = className;
-  },
-
-  add: function(classNameToAdd) {
-    if (this.include(classNameToAdd)) return;
-    this.set(this.toArray().concat(classNameToAdd).join(' '));
-  },
-
-  remove: function(classNameToRemove) {
-    if (!this.include(classNameToRemove)) return;
-    this.set(this.select(function(className) {
-      return className != classNameToRemove;
-    }).join(' '));
-  },
-
-  toString: function() {
-    return this.toArray().join(' ');
-  }
-}
-
-Object.extend(Element.ClassNames.prototype, Enumerable);
-var Field = {
-  clear: function() {
-    for (var i = 0; i < arguments.length; i++)
-      $(arguments[i]).value = '';
-  },
-
-  focus: function(element) {
-    $(element).focus();
-  },
-
-  present: function() {
-    for (var i = 0; i < arguments.length; i++)
-      if ($(arguments[i]).value == '') return false;
-    return true;
-  },
-
-  select: function(element) {
-    $(element).select();
-  },
-
-  activate: function(element) {
-    element = $(element);
-    element.focus();
-    if (element.select)
-      element.select();
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var Form = {
-  serialize: function(form) {
-    var elements = Form.getElements($(form));
-    var queryComponents = new Array();
-
-    for (var i = 0; i < elements.length; i++) {
-      var queryComponent = Form.Element.serialize(elements[i]);
-      if (queryComponent)
-        queryComponents.push(queryComponent);
-    }
-
-    return queryComponents.join('&');
-  },
-
-  getElements: function(form) {
-    form = $(form);
-    var elements = new Array();
-
-    for (tagName in Form.Element.Serializers) {
-      var tagElements = form.getElementsByTagName(tagName);
-      for (var j = 0; j < tagElements.length; j++)
-        elements.push(tagElements[j]);
-    }
-    return elements;
-  },
-
-  getInputs: function(form, typeName, name) {
-    form = $(form);
-    var inputs = form.getElementsByTagName('input');
-
-    if (!typeName && !name)
-      return inputs;
-
-    var matchingInputs = new Array();
-    for (var i = 0; i < inputs.length; i++) {
-      var input = inputs[i];
-      if ((typeName && input.type != typeName) ||
-          (name && input.name != name))
-        continue;
-      matchingInputs.push(input);
-    }
-
-    return matchingInputs;
-  },
-
-  disable: function(form) {
-    var elements = Form.getElements(form);
-    for (var i = 0; i < elements.length; i++) {
-      var element = elements[i];
-      element.blur();
-      element.disabled = 'true';
-    }
-  },
-
-  enable: function(form) {
-    var elements = Form.getElements(form);
-    for (var i = 0; i < elements.length; i++) {
-      var element = elements[i];
-      element.disabled = '';
-    }
-  },
-
-  findFirstElement: function(form) {
-    return Form.getElements(form).find(function(element) {
-      return element.type != 'hidden' && !element.disabled &&
-        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
-    });
-  },
-
-  focusFirstElement: function(form) {
-    Field.activate(Form.findFirstElement(form));
-  },
-
-  reset: function(form) {
-    $(form).reset();
-  }
-}
-
-Form.Element = {
-  serialize: function(element) {
-    element = $(element);
-    var method = element.tagName.toLowerCase();
-    var parameter = Form.Element.Serializers[method](element);
-
-    if (parameter) {
-      var key = encodeURIComponent(parameter[0]);
-      if (key.length == 0) return;
-
-      if (parameter[1].constructor != Array)
-        parameter[1] = [parameter[1]];
-
-      return parameter[1].map(function(value) {
-        return key + '=' + encodeURIComponent(value);
-      }).join('&');
-    }
-  },
-
-  getValue: function(element) {
-    element = $(element);
-    var method = element.tagName.toLowerCase();
-    var parameter = Form.Element.Serializers[method](element);
-
-    if (parameter)
-      return parameter[1];
-  }
-}
-
-Form.Element.Serializers = {
-  input: function(element) {
-    switch (element.type.toLowerCase()) {
-      case 'submit':
-      case 'hidden':
-      case 'password':
-      case 'text':
-        return Form.Element.Serializers.textarea(element);
-      case 'checkbox':
-      case 'radio':
-        return Form.Element.Serializers.inputSelector(element);
-    }
-    return false;
-  },
-
-  inputSelector: function(element) {
-    if (element.checked)
-      return [element.name, element.value];
-  },
-
-  textarea: function(element) {
-    return [element.name, element.value];
-  },
-
-  select: function(element) {
-    return Form.Element.Serializers[element.type == 'select-one' ?
-      'selectOne' : 'selectMany'](element);
-  },
-
-  selectOne: function(element) {
-    var value = '', opt, index = element.selectedIndex;
-    if (index >= 0) {
-      opt = element.options[index];
-      value = opt.value;
-      if (!value && !('value' in opt))
-        value = opt.text;
-    }
-    return [element.name, value];
-  },
-
-  selectMany: function(element) {
-    var value = new Array();
-    for (var i = 0; i < element.length; i++) {
-      var opt = element.options[i];
-      if (opt.selected) {
-        var optValue = opt.value;
-        if (!optValue && !('value' in opt))
-          optValue = opt.text;
-        value.push(optValue);
-      }
-    }
-    return [element.name, value];
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var $F = Form.Element.getValue;
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.TimedObserver = function() {}
-Abstract.TimedObserver.prototype = {
-  initialize: function(element, frequency, callback) {
-    this.frequency = frequency;
-    this.element   = $(element);
-    this.callback  = callback;
-
-    this.lastValue = this.getValue();
-    this.registerCallback();
-  },
-
-  registerCallback: function() {
-    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
-  },
-
-  onTimerEvent: function() {
-    var value = this.getValue();
-    if (this.lastValue != value) {
-      this.callback(this.element, value);
-      this.lastValue = value;
-    }
-  }
-}
-
-Form.Element.Observer = Class.create();
-Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
-  getValue: function() {
-    return Form.Element.getValue(this.element);
-  }
-});
-
-Form.Observer = Class.create();
-Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
-  getValue: function() {
-    return Form.serialize(this.element);
-  }
-});
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.EventObserver = function() {}
-Abstract.EventObserver.prototype = {
-  initialize: function(element, callback) {
-    this.element  = $(element);
-    this.callback = callback;
-
-    this.lastValue = this.getValue();
-    if (this.element.tagName.toLowerCase() == 'form')
-      this.registerFormCallbacks();
-    else
-      this.registerCallback(this.element);
-  },
-
-  onElementEvent: function() {
-    var value = this.getValue();
-    if (this.lastValue != value) {
-      this.callback(this.element, value);
-      this.lastValue = value;
-    }
-  },
-
-  registerFormCallbacks: function() {
-    var elements = Form.getElements(this.element);
-    for (var i = 0; i < elements.length; i++)
-      this.registerCallback(elements[i]);
-  },
-
-  registerCallback: function(element) {
-    if (element.type) {
-      switch (element.type.toLowerCase()) {
-        case 'checkbox':
-        case 'radio':
-          Event.observe(element, 'click', this.onElementEvent.bind(this));
-          break;
-        case 'password':
-        case 'text':
-        case 'textarea':
-        case 'select-one':
-        case 'select-multiple':
-          Event.observe(element, 'change', this.onElementEvent.bind(this));
-          break;
-      }
-    }
-  }
-}
-
-Form.Element.EventObserver = Class.create();
-Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
-  getValue: function() {
-    return Form.Element.getValue(this.element);
-  }
-});
-
-Form.EventObserver = Class.create();
-Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
-  getValue: function() {
-    return Form.serialize(this.element);
-  }
-});
-if (!window.Event) {
-  var Event = new Object();
-}
-
-Object.extend(Event, {
-  KEY_BACKSPACE: 8,
-  KEY_TAB:       9,
-  KEY_RETURN:   13,
-  KEY_ESC:      27,
-  KEY_LEFT:     37,
-  KEY_UP:       38,
-  KEY_RIGHT:    39,
-  KEY_DOWN:     40,
-  KEY_DELETE:   46,
-
-  element: function(event) {
-    return event.target || event.srcElement;
-  },
-
-  isLeftClick: function(event) {
-    return (((event.which) && (event.which == 1)) ||
-            ((event.button) && (event.button == 1)));
-  },
-
-  pointerX: function(event) {
-    return event.pageX || (event.clientX +
-      (document.documentElement.scrollLeft || document.body.scrollLeft));
-  },
-
-  pointerY: function(event) {
-    return event.pageY || (event.clientY +
-      (document.documentElement.scrollTop || document.body.scrollTop));
-  },
-
-  stop: function(event) {
-    if (event.preventDefault) {
-      event.preventDefault();
-      event.stopPropagation();
-    } else {
-      event.returnValue = false;
-      event.cancelBubble = true;
-    }
-  },
-
-  // find the first node with the given tagName, starting from the
-  // node the event was triggered on; traverses the DOM upwards
-  findElement: function(event, tagName) {
-    var element = Event.element(event);
-    while (element.parentNode && (!element.tagName ||
-        (element.tagName.toUpperCase() != tagName.toUpperCase())))
-      element = element.parentNode;
-    return element;
-  },
-
-  observers: false,
-
-  _observeAndCache: function(element, name, observer, useCapture) {
-    if (!this.observers) this.observers = [];
-    if (element.addEventListener) {
-      this.observers.push([element, name, observer, useCapture]);
-      element.addEventListener(name, observer, useCapture);
-    } else if (element.attachEvent) {
-      this.observers.push([element, name, observer, useCapture]);
-      element.attachEvent('on' + name, observer);
-    }
-  },
-
-  unloadCache: function() {
-    if (!Event.observers) return;
-    for (var i = 0; i < Event.observers.length; i++) {
-      Event.stopObserving.apply(this, Event.observers[i]);
-      Event.observers[i][0] = null;
-    }
-    Event.observers = false;
-  },
-
-  observe: function(element, name, observer, useCapture) {
-    var element = $(element);
-    useCapture = useCapture || false;
-
-    if (name == 'keypress' &&
-        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
-        || element.attachEvent))
-      name = 'keydown';
-
-    this._observeAndCache(element, name, observer, useCapture);
-  },
-
-  stopObserving: function(element, name, observer, useCapture) {
-    var element = $(element);
-    useCapture = useCapture || false;
-
-    if (name == 'keypress' &&
-        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
-        || element.detachEvent))
-      name = 'keydown';
-
-    if (element.removeEventListener) {
-      element.removeEventListener(name, observer, useCapture);
-    } else if (element.detachEvent) {
-      element.detachEvent('on' + name, observer);
-    }
-  }
-});
-
-/* prevent memory leaks in IE */
-Event.observe(window, 'unload', Event.unloadCache, false);
-var Position = {
-  // set to true if needed, warning: firefox performance problems
-  // NOT neeeded for page scrolling, only if draggable contained in
-  // scrollable elements
-  includeScrollOffsets: false,
-
-  // must be called before calling withinIncludingScrolloffset, every time the
-  // page is scrolled
-  prepare: function() {
-    this.deltaX =  window.pageXOffset
-                || document.documentElement.scrollLeft
-                || document.body.scrollLeft
-                || 0;
-    this.deltaY =  window.pageYOffset
-                || document.documentElement.scrollTop
-                || document.body.scrollTop
-                || 0;
-  },
-
-  realOffset: function(element) {
-    var valueT = 0, valueL = 0;
-    do {
-      valueT += element.scrollTop  || 0;
-      valueL += element.scrollLeft || 0;
-      element = element.parentNode;
-    } while (element);
-    return [valueL, valueT];
-  },
-
-  cumulativeOffset: function(element) {
-    var valueT = 0, valueL = 0;
-    do {
-      valueT += element.offsetTop  || 0;
-      valueL += element.offsetLeft || 0;
-      element = element.offsetParent;
-    } while (element);
-    return [valueL, valueT];
-  },
-
-  positionedOffset: function(element) {
-    var valueT = 0, valueL = 0;
-    do {
-      valueT += element.offsetTop  || 0;
-      valueL += element.offsetLeft || 0;
-      element = element.offsetParent;
-      if (element) {
-        p = Element.getStyle(element, 'position');
-        if (p == 'relative' || p == 'absolute') break;
-      }
-    } while (element);
-    return [valueL, valueT];
-  },
-
-  offsetParent: function(element) {
-    if (element.offsetParent) return element.offsetParent;
-    if (element == document.body) return element;
-
-    while ((element = element.parentNode) && element != document.body)
-      if (Element.getStyle(element, 'position') != 'static')
-        return element;
-
-    return document.body;
-  },
-
-  // caches x/y coordinate pair to use with overlap
-  within: function(element, x, y) {
-    if (this.includeScrollOffsets)
-      return this.withinIncludingScrolloffsets(element, x, y);
-    this.xcomp = x;
-    this.ycomp = y;
-    this.offset = this.cumulativeOffset(element);
-
-    return (y >= this.offset[1] &&
-            y <  this.offset[1] + element.offsetHeight &&
-            x >= this.offset[0] &&
-            x <  this.offset[0] + element.offsetWidth);
-  },
-
-  withinIncludingScrolloffsets: function(element, x, y) {
-    var offsetcache = this.realOffset(element);
-
-    this.xcomp = x + offsetcache[0] - this.deltaX;
-    this.ycomp = y + offsetcache[1] - this.deltaY;
-    this.offset = this.cumulativeOffset(element);
-
-    return (this.ycomp >= this.offset[1] &&
-            this.ycomp <  this.offset[1] + element.offsetHeight &&
-            this.xcomp >= this.offset[0] &&
-            this.xcomp <  this.offset[0] + element.offsetWidth);
-  },
-
-  // within must be called directly before
-  overlap: function(mode, element) {
-    if (!mode) return 0;
-    if (mode == 'vertical')
-      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
-        element.offsetHeight;
-    if (mode == 'horizontal')
-      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
-        element.offsetWidth;
-  },
-
-  clone: function(source, target) {
-    source = $(source);
-    target = $(target);
-    target.style.position = 'absolute';
-    var offsets = this.cumulativeOffset(source);
-    target.style.top    = offsets[1] + 'px';
-    target.style.left   = offsets[0] + 'px';
-    target.style.width  = source.offsetWidth + 'px';
-    target.style.height = source.offsetHeight + 'px';
-  },
-
-  page: function(forElement) {
-    var valueT = 0, valueL = 0;
-
-    var element = forElement;
-    do {
-      valueT += element.offsetTop  || 0;
-      valueL += element.offsetLeft || 0;
-
-      // Safari fix
-      if (element.offsetParent==document.body)
-        if (Element.getStyle(element,'position')=='absolute') break;
-
-    } while (element = element.offsetParent);
-
-    element = forElement;
-    do {
-      valueT -= element.scrollTop  || 0;
-      valueL -= element.scrollLeft || 0;
-    } while (element = element.parentNode);
-
-    return [valueL, valueT];
-  },
-
-  clone: function(source, target) {
-    var options = Object.extend({
-      setLeft:    true,
-      setTop:     true,
-      setWidth:   true,
-      setHeight:  true,
-      offsetTop:  0,
-      offsetLeft: 0
-    }, arguments[2] || {})
-
-    // find page position of source
-    source = $(source);
-    var p = Position.page(source);
-
-    // find coordinate system to use
-    target = $(target);
-    var delta = [0, 0];
-    var parent = null;
-    // delta [0,0] will do fine with position: fixed elements,
-    // position:absolute needs offsetParent deltas
-    if (Element.getStyle(target,'position') == 'absolute') {
-      parent = Position.offsetParent(target);
-      delta = Position.page(parent);
-    }
-
-    // correct by body offsets (fixes Safari)
-    if (parent == document.body) {
-      delta[0] -= document.body.offsetLeft;
-      delta[1] -= document.body.offsetTop;
-    }
-
-    // set position
-    if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
-    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
-    if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
-    if(options.setHeight) target.style.height = source.offsetHeight + 'px';
-  },
-
-  absolutize: function(element) {
-    element = $(element);
-    if (element.style.position == 'absolute') return;
-    Position.prepare();
-
-    var offsets = Position.positionedOffset(element);
-    var top     = offsets[1];
-    var left    = offsets[0];
-    var width   = element.clientWidth;
-    var height  = element.clientHeight;
-
-    element._originalLeft   = left - parseFloat(element.style.left  || 0);
-    element._originalTop    = top  - parseFloat(element.style.top || 0);
-    element._originalWidth  = element.style.width;
-    element._originalHeight = element.style.height;
-
-    element.style.position = 'absolute';
-    element.style.top    = top + 'px';;
-    element.style.left   = left + 'px';;
-    element.style.width  = width + 'px';;
-    element.style.height = height + 'px';;
-  },
-
-  relativize: function(element) {
-    element = $(element);
-    if (element.style.position == 'relative') return;
-    Position.prepare();
-
-    element.style.position = 'relative';
-    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
-    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
-
-    element.style.top    = top + 'px';
-    element.style.left   = left + 'px';
-    element.style.height = element._originalHeight;
-    element.style.width  = element._originalWidth;
-  }
-}
-
-// Safari returns margins on body which is incorrect if the child is absolutely
-// positioned.  For performance reasons, redefine Position.cumulativeOffset for
-// KHTML/WebKit only.
-if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
-  Position.cumulativeOffset = function(element) {
-    var valueT = 0, valueL = 0;
-    do {
-      valueT += element.offsetTop  || 0;
-      valueL += element.offsetLeft || 0;
-      if (element.offsetParent == document.body)
-        if (Element.getStyle(element, 'position') == 'absolute') break;
-
-      element = element.offsetParent;
-    } while (element);
-
-    return [valueL, valueT];
-  }
-}
\ No newline at end of file
diff --git a/js/scriptaculous.js b/js/scriptaculous.js
deleted file mode 100644 (file)
index dac1228..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// 
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-// 
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-var Scriptaculous = {
-  Version: '1.5.1',
-  require: function(libraryName) {
-    // inserting via DOM fails in Safari 2.0, so brute force approach
-    document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
-  },
-  load: function() {
-    if((typeof Prototype=='undefined') ||
-      parseFloat(Prototype.Version.split(".")[0] + "." +
-                 Prototype.Version.split(".")[1]) < 1.4)
-      throw("script.aculo.us requires the Prototype JavaScript framework >= 1.4.0");
-    
-    $A(document.getElementsByTagName("script")).findAll( function(s) {
-      return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
-    }).each( function(s) {
-      var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
-      var includes = s.src.match(/\?.*load=([a-z,]*)/);
-      (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider').split(',').each(
-       function(include) { Scriptaculous.require(path+include+'.js') });
-    });
-  }
-}
-
-Scriptaculous.load();
\ No newline at end of file
diff --git a/js/slider.js b/js/slider.js
deleted file mode 100644 (file)
index fdd0bcc..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-// Copyright (c) 2005 Marty Haught, Thomas Fuchs 
-//
-// See http://script.aculo.us for more info
-// 
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-// 
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-if(!Control) var Control = {};
-Control.Slider = Class.create();
-
-// options:
-//  axis: 'vertical', or 'horizontal' (default)
-//
-// callbacks:
-//  onChange(value)
-//  onSlide(value)
-Control.Slider.prototype = {
-  initialize: function(handle, track, options) {
-    var slider = this;
-    
-    if(handle instanceof Array) {
-      this.handles = handle.collect( function(e) { return $(e) });
-    } else {
-      this.handles = [$(handle)];
-    }
-    
-    this.track   = $(track);
-    this.options = options || {};
-
-    this.axis      = this.options.axis || 'horizontal';
-    this.increment = this.options.increment || 1;
-    this.step      = parseInt(this.options.step || '1');
-    this.range     = this.options.range || $R(0,1);
-    
-    this.value     = 0; // assure backwards compat
-    this.values    = this.handles.map( function() { return 0 });
-    this.spans     = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
-    this.options.startSpan = $(this.options.startSpan || null);
-    this.options.endSpan   = $(this.options.endSpan || null);
-
-    this.restricted = this.options.restricted || false;
-
-    this.maximum   = this.options.maximum || this.range.end;
-    this.minimum   = this.options.minimum || this.range.start;
-
-    // Will be used to align the handle onto the track, if necessary
-    this.alignX = parseInt(this.options.alignX || '0');
-    this.alignY = parseInt(this.options.alignY || '0');
-    
-    this.trackLength = this.maximumOffset() - this.minimumOffset();
-    this.handleLength = this.isVertical() ? this.handles[0].offsetHeight : this.handles[0].offsetWidth;
-
-    this.active   = false;
-    this.dragging = false;
-    this.disabled = false;
-
-    if(this.options.disabled) this.setDisabled();
-
-    // Allowed values array
-    this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
-    if(this.allowedValues) {
-      this.minimum = this.allowedValues.min();
-      this.maximum = this.allowedValues.max();
-    }
-
-    this.eventMouseDown = this.startDrag.bindAsEventListener(this);
-    this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
-    this.eventMouseMove = this.update.bindAsEventListener(this);
-
-    // Initialize handles in reverse (make sure first handle is active)
-    this.handles.each( function(h,i) {
-      i = slider.handles.length-1-i;
-      slider.setValue(parseFloat(
-        (slider.options.sliderValue instanceof Array ? 
-          slider.options.sliderValue[i] : slider.options.sliderValue) || 
-         slider.range.start), i);
-      Element.makePositioned(h); // fix IE
-      Event.observe(h, "mousedown", slider.eventMouseDown);
-    });
-    
-    Event.observe(this.track, "mousedown", this.eventMouseDown);
-    Event.observe(document, "mouseup", this.eventMouseUp);
-    Event.observe(document, "mousemove", this.eventMouseMove);
-    
-    this.initialized = true;
-  },
-  dispose: function() {
-    var slider = this;    
-    Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
-    Event.stopObserving(document, "mouseup", this.eventMouseUp);
-    Event.stopObserving(document, "mousemove", this.eventMouseMove);
-    this.handles.each( function(h) {
-      Event.stopObserving(h, "mousedown", slider.eventMouseDown);
-    });
-  },
-  setDisabled: function(){
-    this.disabled = true;
-  },
-  setEnabled: function(){
-    this.disabled = false;
-  },  
-  getNearestValue: function(value){
-    if(this.allowedValues){
-      if(value >= this.allowedValues.max()) return(this.allowedValues.max());
-      if(value <= this.allowedValues.min()) return(this.allowedValues.min());
-      
-      var offset = Math.abs(this.allowedValues[0] - value);
-      var newValue = this.allowedValues[0];
-      this.allowedValues.each( function(v) {
-        var currentOffset = Math.abs(v - value);
-        if(currentOffset <= offset){
-          newValue = v;
-          offset = currentOffset;
-        } 
-      });
-      return newValue;
-    }
-    if(value > this.range.end) return this.range.end;
-    if(value < this.range.start) return this.range.start;
-    return value;
-  },
-  setValue: function(sliderValue, handleIdx){
-    if(!this.active) {
-      this.activeHandle    = this.handles[handleIdx];
-      this.activeHandleIdx = handleIdx;
-      this.updateStyles();
-    }
-    handleIdx = handleIdx || this.activeHandleIdx || 0;
-    if(this.initialized && this.restricted) {
-      if((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
-        sliderValue = this.values[handleIdx-1];
-      if((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
-        sliderValue = this.values[handleIdx+1];
-    }
-    sliderValue = this.getNearestValue(sliderValue);
-    this.values[handleIdx] = sliderValue;
-    this.value = this.values[0]; // assure backwards compat
-    
-    this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] = 
-      this.translateToPx(sliderValue);
-    
-    this.drawSpans();
-    if(!this.dragging || !this.event) this.updateFinished();
-  },
-  setValueBy: function(delta, handleIdx) {
-    this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta, 
-      handleIdx || this.activeHandleIdx || 0);
-  },
-  translateToPx: function(value) {
-    return Math.round(
-      ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) * 
-      (value - this.range.start)) + "px";
-  },
-  translateToValue: function(offset) {
-    return ((offset/(this.trackLength-this.handleLength) * 
-      (this.range.end-this.range.start)) + this.range.start);
-  },
-  getRange: function(range) {
-    var v = this.values.sortBy(Prototype.K); 
-    range = range || 0;
-    return $R(v[range],v[range+1]);
-  },
-  minimumOffset: function(){
-    return(this.isVertical() ? this.alignY : this.alignX);
-  },
-  maximumOffset: function(){
-    return(this.isVertical() ?
-      this.track.offsetHeight - this.alignY : this.track.offsetWidth - this.alignX);
-  },  
-  isVertical:  function(){
-    return (this.axis == 'vertical');
-  },
-  drawSpans: function() {
-    var slider = this;
-    if(this.spans)
-      $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
-    if(this.options.startSpan)
-      this.setSpan(this.options.startSpan,
-        $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
-    if(this.options.endSpan)
-      this.setSpan(this.options.endSpan, 
-        $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
-  },
-  setSpan: function(span, range) {
-    if(this.isVertical()) {
-      span.style.top = this.translateToPx(range.start);
-      span.style.height = this.translateToPx(range.end - range.start);
-    } else {
-      span.style.left = this.translateToPx(range.start);
-      span.style.width = this.translateToPx(range.end - range.start);
-    }
-  },
-  updateStyles: function() {
-    this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
-    Element.addClassName(this.activeHandle, 'selected');
-  },
-  startDrag: function(event) {
-    if(Event.isLeftClick(event)) {
-      if(!this.disabled){
-        this.active = true;
-        
-        var handle = Event.element(event);
-        var pointer  = [Event.pointerX(event), Event.pointerY(event)];
-        if(handle==this.track) {
-          var offsets  = Position.cumulativeOffset(this.track); 
-          this.event = event;
-          this.setValue(this.translateToValue( 
-           (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
-          ));
-          var offsets  = Position.cumulativeOffset(this.activeHandle);
-          this.offsetX = (pointer[0] - offsets[0]);
-          this.offsetY = (pointer[1] - offsets[1]);
-        } else {
-          // find the handle (prevents issues with Safari)
-          while((this.handles.indexOf(handle) == -1) && handle.parentNode) 
-            handle = handle.parentNode;
-        
-          this.activeHandle    = handle;
-          this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
-          this.updateStyles();
-        
-          var offsets  = Position.cumulativeOffset(this.activeHandle);
-          this.offsetX = (pointer[0] - offsets[0]);
-          this.offsetY = (pointer[1] - offsets[1]);
-        }
-      }
-      Event.stop(event);
-    }
-  },
-  update: function(event) {
-   if(this.active) {
-      if(!this.dragging) this.dragging = true;
-      this.draw(event);
-      // fix AppleWebKit rendering
-      if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
-      Event.stop(event);
-   }
-  },
-  draw: function(event) {
-    var pointer = [Event.pointerX(event), Event.pointerY(event)];
-    var offsets = Position.cumulativeOffset(this.track);
-    pointer[0] -= this.offsetX + offsets[0];
-    pointer[1] -= this.offsetY + offsets[1];
-    this.event = event;
-    this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
-    if(this.initialized && this.options.onSlide)
-      this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
-  },
-  endDrag: function(event) {
-    if(this.active && this.dragging) {
-      this.finishDrag(event, true);
-      Event.stop(event);
-    }
-    this.active = false;
-    this.dragging = false;
-  },  
-  finishDrag: function(event, success) {
-    this.active = false;
-    this.dragging = false;
-    this.updateFinished();
-  },
-  updateFinished: function() {
-    if(this.initialized && this.options.onChange) 
-      this.options.onChange(this.values.length>1 ? this.values : this.value, this);
-    this.event = null;
-  }
-}
\ No newline at end of file
diff --git a/js/unittest.js b/js/unittest.js
deleted file mode 100644 (file)
index 20941ad..0000000
+++ /dev/null
@@ -1,363 +0,0 @@
-// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-//           (c) 2005 Jon Tirsen (http://www.tirsen.com)
-//           (c) 2005 Michael Schuerig (http://www.schuerig.de/michael/)
-//
-// See scriptaculous.js for full license.
-
-// experimental, Firefox-only
-Event.simulateMouse = function(element, eventName) {
-  var options = Object.extend({
-    pointerX: 0,
-    pointerY: 0,
-    buttons: 0
-  }, arguments[2] || {});
-  var oEvent = document.createEvent("MouseEvents");
-  oEvent.initMouseEvent(eventName, true, true, document.defaultView, 
-    options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY, 
-    false, false, false, false, 0, $(element));
-  
-  if(this.mark) Element.remove(this.mark);
-  this.mark = document.createElement('div');
-  this.mark.appendChild(document.createTextNode(" "));
-  document.body.appendChild(this.mark);
-  this.mark.style.position = 'absolute';
-  this.mark.style.top = options.pointerY + "px";
-  this.mark.style.left = options.pointerX + "px";
-  this.mark.style.width = "5px";
-  this.mark.style.height = "5px;";
-  this.mark.style.borderTop = "1px solid red;"
-  this.mark.style.borderLeft = "1px solid red;"
-  
-  if(this.step)
-    alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
-  
-  $(element).dispatchEvent(oEvent);
-};
-
-// Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2.
-// You need to downgrade to 1.0.4 for now to get this working
-// See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much
-Event.simulateKey = function(element, eventName) {
-  var options = Object.extend({
-    ctrlKey: false,
-    altKey: false,
-    shiftKey: false,
-    metaKey: false,
-    keyCode: 0,
-    charCode: 0
-  }, arguments[2] || {});
-
-  var oEvent = document.createEvent("KeyEvents");
-  oEvent.initKeyEvent(eventName, true, true, window, 
-    options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
-    options.keyCode, options.charCode );
-  $(element).dispatchEvent(oEvent);
-};
-
-Event.simulateKeys = function(element, command) {
-  for(var i=0; i<command.length; i++) {
-    Event.simulateKey(element,'keypress',{charCode:command.charCodeAt(i)});
-  }
-};
-
-var Test = {}
-Test.Unit = {};
-
-// security exception workaround
-Test.Unit.inspect = function(obj) {
-  var info = [];
-
-  if(typeof obj=="string" || 
-     typeof obj=="number") {
-    return obj;
-  } else {
-    for(property in obj)
-      if(typeof obj[property]!="function")
-        info.push(property + ' => ' + 
-          (typeof obj[property] == "string" ?
-            '"' + obj[property] + '"' :
-            obj[property]));
-  }
-
-  return ("'" + obj + "' #" + typeof obj + 
-    ": {" + info.join(", ") + "}");
-}
-
-Test.Unit.Logger = Class.create();
-Test.Unit.Logger.prototype = {
-  initialize: function(log) {
-    this.log = $(log);
-    if (this.log) {
-      this._createLogTable();
-    }
-  },
-  start: function(testName) {
-    if (!this.log) return;
-    this.testName = testName;
-    this.lastLogLine = document.createElement('tr');
-    this.statusCell = document.createElement('td');
-    this.nameCell = document.createElement('td');
-    this.nameCell.appendChild(document.createTextNode(testName));
-    this.messageCell = document.createElement('td');
-    this.lastLogLine.appendChild(this.statusCell);
-    this.lastLogLine.appendChild(this.nameCell);
-    this.lastLogLine.appendChild(this.messageCell);
-    this.loglines.appendChild(this.lastLogLine);
-  },
-  finish: function(status, summary) {
-    if (!this.log) return;
-    this.lastLogLine.className = status;
-    this.statusCell.innerHTML = status;
-    this.messageCell.innerHTML = this._toHTML(summary);
-  },
-  message: function(message) {
-    if (!this.log) return;
-    this.messageCell.innerHTML = this._toHTML(message);
-  },
-  summary: function(summary) {
-    if (!this.log) return;
-    this.logsummary.innerHTML = this._toHTML(summary);
-  },
-  _createLogTable: function() {
-    this.log.innerHTML =
-    '<div id="logsummary"></div>' +
-    '<table id="logtable">' +
-    '<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
-    '<tbody id="loglines"></tbody>' +
-    '</table>';
-    this.logsummary = $('logsummary')
-    this.loglines = $('loglines');
-  },
-  _toHTML: function(txt) {
-    return txt.escapeHTML().replace(/\n/g,"<br/>");
-  }
-}
-
-Test.Unit.Runner = Class.create();
-Test.Unit.Runner.prototype = {
-  initialize: function(testcases) {
-    this.options = Object.extend({
-      testLog: 'testlog'
-    }, arguments[1] || {});
-    this.options.resultsURL = this.parseResultsURLQueryParameter();
-    if (this.options.testLog) {
-      this.options.testLog = $(this.options.testLog) || null;
-    }
-    if(this.options.tests) {
-      this.tests = [];
-      for(var i = 0; i < this.options.tests.length; i++) {
-        if(/^test/.test(this.options.tests[i])) {
-          this.tests.push(new Test.Unit.Testcase(this.options.tests[i], testcases[this.options.tests[i]], testcases["setup"], testcases["teardown"]));
-        }
-      }
-    } else {
-      if (this.options.test) {
-        this.tests = [new Test.Unit.Testcase(this.options.test, testcases[this.options.test], testcases["setup"], testcases["teardown"])];
-      } else {
-        this.tests = [];
-        for(var testcase in testcases) {
-          if(/^test/.test(testcase)) {
-            this.tests.push(new Test.Unit.Testcase(testcase, testcases[testcase], testcases["setup"], testcases["teardown"]));
-          }
-        }
-      }
-    }
-    this.currentTest = 0;
-    this.logger = new Test.Unit.Logger(this.options.testLog);
-    setTimeout(this.runTests.bind(this), 1000);
-  },
-  parseResultsURLQueryParameter: function() {
-    return window.location.search.parseQuery()["resultsURL"];
-  },
-  // Returns:
-  //  "ERROR" if there was an error,
-  //  "FAILURE" if there was a failure, or
-  //  "SUCCESS" if there was neither
-  getResult: function() {
-    var hasFailure = false;
-    for(var i=0;i<this.tests.length;i++) {
-      if (this.tests[i].errors > 0) {
-        return "ERROR";
-      }
-      if (this.tests[i].failures > 0) {
-        hasFailure = true;
-      }
-    }
-    if (hasFailure) {
-      return "FAILURE";
-    } else {
-      return "SUCCESS";
-    }
-  },
-  postResults: function() {
-    if (this.options.resultsURL) {
-      new Ajax.Request(this.options.resultsURL, 
-        { method: 'get', parameters: 'result=' + this.getResult(), asynchronous: false });
-    }
-  },
-  runTests: function() {
-    var test = this.tests[this.currentTest];
-    if (!test) {
-      // finished!
-      this.postResults();
-      this.logger.summary(this.summary());
-      return;
-    }
-    if(!test.isWaiting) {
-      this.logger.start(test.name);
-    }
-    test.run();
-    if(test.isWaiting) {
-      this.logger.message("Waiting for " + test.timeToWait + "ms");
-      setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
-    } else {
-      this.logger.finish(test.status(), test.summary());
-      this.currentTest++;
-      // tail recursive, hopefully the browser will skip the stackframe
-      this.runTests();
-    }
-  },
-  summary: function() {
-    var assertions = 0;
-    var failures = 0;
-    var errors = 0;
-    var messages = [];
-    for(var i=0;i<this.tests.length;i++) {
-      assertions +=   this.tests[i].assertions;
-      failures   +=   this.tests[i].failures;
-      errors     +=   this.tests[i].errors;
-    }
-    return (
-      this.tests.length + " tests, " + 
-      assertions + " assertions, " + 
-      failures   + " failures, " +
-      errors     + " errors");
-  }
-}
-
-Test.Unit.Assertions = Class.create();
-Test.Unit.Assertions.prototype = {
-  initialize: function() {
-    this.assertions = 0;
-    this.failures   = 0;
-    this.errors     = 0;
-    this.messages   = [];
-  },
-  summary: function() {
-    return (
-      this.assertions + " assertions, " + 
-      this.failures   + " failures, " +
-      this.errors     + " errors" + "\n" +
-      this.messages.join("\n"));
-  },
-  pass: function() {
-    this.assertions++;
-  },
-  fail: function(message) {
-    this.failures++;
-    this.messages.push("Failure: " + message);
-  },
-  error: function(error) {
-    this.errors++;
-    this.messages.push(error.name + ": "+ error.message + "(" + Test.Unit.inspect(error) +")");
-  },
-  status: function() {
-    if (this.failures > 0) return 'failed';
-    if (this.errors > 0) return 'error';
-    return 'passed';
-  },
-  assert: function(expression) {
-    var message = arguments[1] || 'assert: got "' + Test.Unit.inspect(expression) + '"';
-    try { expression ? this.pass() : 
-      this.fail(message); }
-    catch(e) { this.error(e); }
-  },
-  assertEqual: function(expected, actual) {
-    var message = arguments[2] || "assertEqual";
-    try { (expected == actual) ? this.pass() :
-      this.fail(message + ': expected "' + Test.Unit.inspect(expected) + 
-        '", actual "' + Test.Unit.inspect(actual) + '"'); }
-    catch(e) { this.error(e); }
-  },
-  assertNotEqual: function(expected, actual) {
-    var message = arguments[2] || "assertNotEqual";
-    try { (expected != actual) ? this.pass() : 
-      this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); }
-    catch(e) { this.error(e); }
-  },
-  assertNull: function(obj) {
-    var message = arguments[1] || 'assertNull'
-    try { (obj==null) ? this.pass() : 
-      this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); }
-    catch(e) { this.error(e); }
-  },
-  assertHidden: function(element) {
-    var message = arguments[1] || 'assertHidden';
-    this.assertEqual("none", element.style.display, message);
-  },
-  assertNotNull: function(object) {
-    var message = arguments[1] || 'assertNotNull';
-    this.assert(object != null, message);
-  },
-  assertInstanceOf: function(expected, actual) {
-    var message = arguments[2] || 'assertInstanceOf';
-    try { 
-      (actual instanceof expected) ? this.pass() : 
-      this.fail(message + ": object was not an instance of the expected type"); }
-    catch(e) { this.error(e); } 
-  },
-  assertNotInstanceOf: function(expected, actual) {
-    var message = arguments[2] || 'assertNotInstanceOf';
-    try { 
-      !(actual instanceof expected) ? this.pass() : 
-      this.fail(message + ": object was an instance of the not expected type"); }
-    catch(e) { this.error(e); } 
-  },
-  _isVisible: function(element) {
-    element = $(element);
-    if(!element.parentNode) return true;
-    this.assertNotNull(element);
-    if(element.style && Element.getStyle(element, 'display') == 'none')
-      return false;
-    
-    return this._isVisible(element.parentNode);
-  },
-  assertNotVisible: function(element) {
-    this.assert(!this._isVisible(element), Test.Unit.inspect(element) + " was not hidden and didn't have a hidden parent either. " + ("" || arguments[1]));
-  },
-  assertVisible: function(element) {
-    this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1]));
-  }
-}
-
-Test.Unit.Testcase = Class.create();
-Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), {
-  initialize: function(name, test, setup, teardown) {
-    Test.Unit.Assertions.prototype.initialize.bind(this)();
-    this.name           = name;
-    this.test           = test || function() {};
-    this.setup          = setup || function() {};
-    this.teardown       = teardown || function() {};
-    this.isWaiting      = false;
-    this.timeToWait     = 1000;
-  },
-  wait: function(time, nextPart) {
-    this.isWaiting = true;
-    this.test = nextPart;
-    this.timeToWait = time;
-  },
-  run: function() {
-    try {
-      try {
-        if (!this.isWaiting) this.setup.bind(this)();
-        this.isWaiting = false;
-        this.test.bind(this)();
-      } finally {
-        if(!this.isWaiting) {
-          this.teardown.bind(this)();
-        }
-      }
-    }
-    catch(e) { this.error(e); }
-  }
-});
\ No newline at end of file
diff --git a/lang/ca.php b/lang/ca.php
deleted file mode 100644 (file)
index 9464345..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-/**
- * Catalan language file
- *
- * @author Carles Briansó <carles.brianso@antaviana.net>
- * @author Xavi Pastó <xavi.pasto@antaviana.net>
- */
-
-$lang['ldapab']           = 'La llibreta d\'adreces LDAP';
-
-$lang['name']             = 'Cognoms';
-$lang['givenname']        = 'Nom';
-$lang['title']            = 'Títol';
-$lang['organization']     = 'Companyia';
-$lang['office']           = 'Oficina';
-$lang['street']           = 'Adreça';
-$lang['zip']              = 'Codi postal';
-$lang['location']         = 'Ciutat';
-$lang['phone']            = 'Telèfon';
-$lang['fax']              = 'Fax';
-$lang['mobile']           = 'Telefon Mòbil';
-$lang['pager']            = 'Buscapersones';
-$lang['homephone']        = 'Telèfon particular';
-$lang['homestreet']       = 'Adreça particular';
-$lang['photo']            = 'Fotografia';
-$lang['url']              = 'Pàgina web';
-$lang['note']             = 'Notes';
-$lang['mail']             = 'Correu electrònic';
-$lang['manager']          = 'Key Account';
-
-$lang['anniversary']      = 'Aniversari';
-$lang['marker']           = 'Tags';
-$lang['tagcloud']         = 'Tots els tags usats, ordenats alfabeticament. Els tags més freqüents es mostren més grans.';
-
-$lang['business']         = 'Feina';
-$lang['private']          = 'Particular';
-$lang['extended']         = 'Informació addicional';
-
-$lang['delphoto']         = 'Esborrar la foto actual';
-
-$lang['notloggedin']      = 'No esteu validats';
-$lang['loggedinas']       = 'L\'usuari validat Ã©s';
-$lang['login']            = 'Valideu-vos';
-$lang['logout']           = 'Sortir';
-$lang['edit']             = 'Editar';
-$lang['show']             = 'Veure';
-$lang['new']              = 'Nou';
-$lang['delete']           = 'Esborrar';
-$lang['copy']             = 'Copiar';
-$lang['csvexport']        = 'CSV';
-$lang['vcfexport']        = 'VCard';
-$lang['vcfimport']        = 'Importar';
-$lang['search']           = 'Buscar';
-$lang['submit']           = 'Enviar';
-$lang['help']             = 'Ajuda';
-$lang['select']           = 'Seleccionar';
-$lang['orgs']             = 'Empreses';
-$lang['upload']           = 'Pujar';
-
-$lang['publicbook']       = 'Llibreta d\'adreçes publica';
-$lang['privatebook']      = 'Llibreta d\'adreçes privada';
-
-$lang['username']         = 'Usuari';
-$lang['password']         = 'Clau';
-$lang['remember']         = 'Recorda\'m en aquest ordinador';
-
-$lang['msg_login']        = 'Valideu-vos, si us plau!';
-$lang['msg_loginfail']    = 'La validació ha fallat';
-$lang['msg_reallydel']    = 'Realment voleu esborrar aquesta l\'entrada?';
-$lang['msg_addto']        = 'Seleccioneu la llibreta d\'addreçes on afegir l\'entrada:';
-$lang['msg_jpegonly']     = 'El sistema només accepta imatges JPEG';
-$lang['msg_dateformat']   = 'YYYY-MM-DD';
-$lang['msg_uploadvcf']    = 'Pugeu un fitxer VCard';
-$lang['msg_tagsep']       = 'Separat per comes';
-
-$lang['err_noentries']    = 'No hi ha entrades';
-$lang['err_ldap']         = 'El servidor LDAP ha tornat els següents errors:';
-
-$lang['openxchange']      = 'Xchange Information';
-$lang['moreopenxchange']  = 'Xchange Information Cont\'d';
-$lang['instantmessenger'] = 'Inst Msg';
-$lang['categories']       = 'Categories';
-$lang['birthday']         = 'Aniversari';
-$lang['domain']           = 'Domini de correu';
-$lang['country']          = 'País';
-$lang['certificate']      = 'x.509 Cert';
-$lang['timezone']         = 'Zona horària';
-$lang['position']         = 'Posició';
-$lang['ipphone']          = 'Telèfon IP';
-
diff --git a/lang/de.php b/lang/de.php
deleted file mode 100644 (file)
index 6e84d83..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-<?php
-/**
- * German language file
- *
- * @author Andreas Gohr <gohr@cosmocode.de>
- */
-
-$lang['ldapab']         = 'Das LDAP Adressbuch';
-
-$lang['name']           = 'Name';
-$lang['givenname']      = 'Vorname';
-$lang['title']          = 'Titel';
-$lang['organization']   = 'Firma';
-$lang['office']         = 'Abteilung';
-$lang['street']         = 'Straße, Nr.';
-$lang['zip']            = 'Postleitzahl';
-$lang['location']       = 'Ort';
-$lang['phone']          = 'Telefon';
-$lang['fax']            = 'FAX';
-$lang['mobile']         = 'Handy';
-$lang['pager']          = 'Pieper';
-$lang['homephone']      = 'Telefon (priv.)';
-$lang['homestreet']     = 'Adresse (priv.)';
-$lang['photo']          = 'Foto';
-$lang['url']            = 'Webseite';
-$lang['note']           = 'Notizen';
-$lang['mail']           = 'E-Mail';
-$lang['manager']        = 'Key Account';
-
-$lang['anniversary']    = 'Jubiläum';
-$lang['marker']         = 'Tags';
-$lang['tagcloud']       = 'Alle verwendeten Tags, alphabetisch sortiert. Häufig verwendete Tags werden größer dargestellt.';
-
-$lang['business']       = 'Geschäftlich';
-$lang['private']        = 'Privat';
-$lang['extended']       = 'Zusätzliche Infos';
-
-$lang['delphoto']       = 'Vorhandenes Foto löschen';
-
-$lang['notloggedin']    = 'Nicht angemeldet';
-$lang['loggedinas']     = 'Angemeldet als';
-$lang['login']          = 'Anmelden';
-$lang['logout']         = 'Abmelden';
-$lang['edit']           = 'Bearbeiten';
-$lang['show']           = 'Anzeigen';
-$lang['new']            = 'Neu';
-$lang['delete']         = 'Löschen';
-$lang['copy']           = 'Kopieren';
-$lang['csvexport']      = 'CSV';
-$lang['vcfexport']      = 'VCard';
-$lang['vcfimport']      = 'Import';
-$lang['search']         = 'Suchen';
-$lang['submit']         = 'Absenden';
-$lang['help']           = 'Hilfe';
-$lang['select']         = 'Auswählen';
-$lang['orgs']           = 'Firmen';
-$lang['upload']         = 'Hochladen';
-
-$lang['publicbook']     = 'Öffentliches Adressbuch';
-$lang['privatebook']    = 'Privates Adressbuch';
-
-
-$lang['username']       = 'Benutzername';
-$lang['password']       = 'Passwort';
-$lang['remember']       = 'Auf diesem Computer angemeldet bleiben';
-
-$lang['msg_login']      = 'Bitte melden sie sich an!';
-$lang['msg_loginfail']  = 'Anmeldung fehlgeschlagen!';
-$lang['msg_reallydel']  = 'Eintrag wirklich löschen?';
-$lang['msg_addto']      = 'Zu welchem Adressbuch soll der Eintrag hinzugefügt werden?';
-$lang['msg_jpegonly']   = 'Nur JPEG';
-$lang['msg_dateformat'] = 'JJJJ-MM-TT';
-$lang['msg_uploadvcf']  = 'Upload VCard File';
-$lang['msg_tagsep']     = 'Durch Komma getrennt';
-
-$lang['err_noentries']  = 'Keine Einträge';
-$lang['err_ldap']       = 'Der LDAP Server lieferte folgende Fehlermeldungen';
-
-
diff --git a/lang/en.php b/lang/en.php
deleted file mode 100644 (file)
index 1f2b97d..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-<?php
-/**
- * English language file
- *
- * @author Andreas Gohr <gohr@cosmocode.de>
- */
-
-$lang['ldapab']           = 'The LDAP address book';
-
-$lang['name']             = 'Last Name';
-$lang['givenname']        = 'First Name';
-$lang['title']            = 'Title';
-$lang['organization']     = 'Company';
-$lang['office']           = 'Office';
-$lang['street']           = 'Street No.';
-$lang['zip']              = 'Postal Code';
-$lang['location']         = 'City';
-$lang['state']            = 'State';
-$lang['phone']            = 'Phone';
-$lang['switchboard']      = 'Switchboard';
-$lang['fax']              = 'FAX';
-$lang['mobile']           = 'Mobile';
-$lang['pager']            = 'Pager';
-$lang['homephone']        = 'Phone (priv.)';
-$lang['homestreet']       = 'Address (priv.)';
-$lang['photo']            = 'Picture';
-$lang['url']              = 'Website';
-$lang['note']             = 'Notes';
-$lang['mail']             = 'E-Mail';
-$lang['manager']          = 'Key Account';
-
-$lang['anniversary']      = 'Anniversary';
-$lang['marker']           = 'Tags';
-$lang['tagcloud']         = 'All used tags, sorted alphabetically. Frequently used tags are shown bigger.';
-
-$lang['business']         = 'Business';
-$lang['private']          = 'Private';
-$lang['extended']         = 'Additional Information';
-$lang['communication']    = 'Communication';
-
-$lang['delphoto']         = 'Delete existing photo';
-
-$lang['notloggedin']      = 'Not logged in';
-$lang['loggedinas']       = 'Logged in as';
-$lang['login']            = 'Log in';
-$lang['logout']           = 'Log out';
-$lang['edit']             = 'Edit';
-$lang['show']             = 'Show';
-$lang['new']              = 'New';
-$lang['delete']           = 'Delete';
-$lang['copy']             = 'Copy';
-$lang['csvexport']        = 'CSV';
-$lang['vcfexport']        = 'VCard';
-$lang['vcfimport']        = 'Import';
-$lang['search']           = 'Search';
-$lang['submit']           = 'Save';
-$lang['help']             = 'Help';
-$lang['select']           = 'Select';
-$lang['orgs']             = 'Companies';
-$lang['upload']           = 'Upload';
-
-$lang['publicbook']       = 'Public Addressbook';
-$lang['privatebook']      = 'Private Addressbook';
-
-$lang['username']         = 'Username';
-$lang['password']         = 'Password';
-$lang['remember']         = 'Stay logged in on this computer';
-
-$lang['msg_login']        = 'Please log in!';
-$lang['msg_loginfail']    = 'Log in failed!';
-$lang['msg_reallydel']    = 'Really delete entry?';
-$lang['msg_addto']        = 'Select address book to which the entry should be added:';
-$lang['msg_jpegonly']     = 'JPEG only';
-$lang['msg_dateformat']   = 'YYYY-MM-DD';
-$lang['msg_uploadvcf']    = 'Upload VCard File';
-$lang['msg_tagsep']       = 'Comma separated';
-
-$lang['err_noentries']    = 'No entries';
-$lang['err_ldap']         = 'The LDAP server returned the following errors';
-
-$lang['openxchange']      = 'Xchange Information';
-$lang['moreopenxchange']  = 'Xchange Information Cont\'d';
-$lang['instantmessenger'] = 'Inst Msg';
-$lang['categories']       = 'Categories';
-$lang['birthday']         = 'Birthday';
-$lang['domain']           = 'Mail Domain';
-$lang['country']          = 'Country';
-$lang['certificate']      = 'x.509 Cert';
-$lang['timezone']         = 'Time Zone';
-$lang['position']         = 'Position';
-$lang['department']       = 'Department';
-$lang['ipphone']          = 'IP Phone';
-$lang['spouse']           = 'Spouse';
-?>
diff --git a/lang/fr.php b/lang/fr.php
deleted file mode 100644 (file)
index 66aeb96..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-<?php
-/**
- * French language file
- *
- * @author Geuten Edouard <thegrima@altern.org>
- */
-
-$lang['ldapab']         = 'Le carnet d\'adresse LDAP';
-
-$lang['name']           = 'Nom de famille';
-$lang['givenname']      = 'Prénom';
-$lang['title']          = 'Titre';
-$lang['organization']   = 'Compagnie';
-$lang['office']         = 'Bureau';
-$lang['street']         = 'N° de rue';
-$lang['zip']            = 'Code Postal';
-$lang['location']       = 'Ville';
-$lang['phone']          = 'Téléphone';
-$lang['fax']            = 'FAX';
-$lang['mobile']         = 'Portable';
-$lang['pager']          = 'Pager';
-$lang['homephone']      = 'Téléphone (priv.)';
-$lang['homestreet']     = 'Adresse (priv.)';
-$lang['photo']          = 'Photo';
-$lang['url']            = 'Site web';
-$lang['note']           = 'Notes';
-$lang['mail']           = 'E-Mail';
-$lang['manager']        = 'Key Account';
-
-$lang['anniversary']    = 'Anniversaire';
-$lang['marker']         = 'Tags';
-$lang['tagcloud']       = 'Tous les marqueurs par ordre alphabétique. Les marqueurs fréquent sont montré plus grand.';
-
-$lang['business']       = 'Business';
-$lang['private']        = 'Privé';
-$lang['extended']       = 'Information Additionelle';
-
-$lang['delphoto']       = 'Effacer la photo existante';
-
-$lang['notloggedin']    = 'Non connecté';
-$lang['loggedinas']     = 'Connecté en tant que';
-$lang['login']          = 'Se connecter';
-$lang['logout']         = 'Se déconnecter';
-$lang['edit']           = 'Editer';
-$lang['show']           = 'Montrer';
-$lang['new']          = 'Nouveau';
-$lang['delete']       = 'Effacer';
-$lang['copy']         = 'Copier';
-$lang['csvexport']      = 'CSV';
-$lang['vcfexport']      = 'VCard';
-$lang['vcfimport']      = 'Import';
-$lang['search']         = 'Rechercher';
-$lang['submit']         = 'Envoyer';
-$lang['help']           = 'Aide';
-$lang['select']         = 'Sélectionner';
-$lang['orgs']           = 'Organisation';
-$lang['upload']         = 'Upload';
-
-$lang['publicbook']     = 'Carnet d\'adresse public';
-$lang['privatebook']    = 'Carnet d\'adresse privé';
-
-$lang['username']       = 'Utilisateur';
-$lang['password']       = 'Mot de passe';
-$lang['remember']       = 'Rester connecté sur cet ordinateur';
-
-$lang['msg_login']      = 'Veuillez vous connecter !';
-$lang['msg_loginfail']  = 'Echec de la connexion !';
-$lang['msg_reallydel']  = 'Voulez-vous vraiment effacer cette entrée ?';
-$lang['msg_addto']      = 'Séléectionnez le carnet d\'adresse ou ajouter une entrée:';
-$lang['msg_jpegonly']   = 'seulement JPEG';
-$lang['msg_dateformat'] = 'YYYY-MM-DD';
-$lang['msg_uploadvcf']  = 'Envoyer un fichier VCard';
-$lang['msg_tagsep']     = 'Séparé par des virgules';
-
-$lang['err_noentries']  = 'Pas d\'entrée';
-$lang['err_ldap']       = 'Le serveur LDAP Ã  retourné les erreurs suivantes';
-
-$lang['openxchange']    = 'Xchange Information';
-$lang['moreopenxchange']    = 'Xchange Information Cont\'d';
-$lang['instantmessenger'] = 'Inst Msg';
-$lang['categories']     = 'Catégories';
-$lang['birthday']       = 'Anniversaire';
-$lang['domain']         = 'Mail Domain';
-$lang['country']        = 'Pays';
-$lang['certificate']    = 'x.509 Cert';
-$lang['timezone']       = 'Fuseau horaire';
-$lang['position']       = 'Position';
-$lang['ipphone']        = 'Téléphone IP';
-
diff --git a/lang/it.php b/lang/it.php
deleted file mode 100644 (file)
index 0e24f50..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-<?php
-/**
- * Italian language file
- *
- * @author Simone Piccardi <piccardi@truelite.it>
- */ 
-
-$lang['ldapab']           = 'The LDAP address book';
-
-$lang['name']             = 'Cognome';
-$lang['givenname']        = 'Nome';
-$lang['title']            = 'Titolo';
-$lang['organization']     = 'Azienda';
-$lang['office']           = 'Ufficio';
-$lang['street']           = 'Via';
-$lang['zip']              = 'Codice Postale';
-$lang['location']         = 'Citt';
-$lang['phone']            = 'Telefono';
-$lang['fax']              = 'FAX';
-$lang['mobile']           = 'Cellulare';
-$lang['pager']            = 'Pager';
-$lang['homephone']        = 'Telefono (priv.)';
-$lang['homestreet']       = 'Indirizzo (priv.)';
-$lang['photo']            = 'Foto';
-$lang['url']              = 'Sito Web';
-$lang['note']             = 'Note';
-$lang['mail']             = 'E-Mail';
-$lang['manager']          = 'Key Account';
-
-$lang['anniversary']      = 'Compleanno';
-$lang['marker']           = 'Etichetta';
-$lang['tagcloud']         = 'Tutte le etichette in ordine alfaberico. Le piu usate sono piu grandi.';
-
-$lang['business']         = 'Affari';
-$lang['private']          = 'Privato';
-$lang['extended']         = 'Informazione addizionale';
-
-$lang['delphoto']         = 'Cancella foto esistente';
-
-$lang['notloggedin']      = 'Non connesso';
-$lang['loggedinas']       = 'Connesso come';
-$lang['login']            = 'Connetti';
-$lang['logout']           = 'Disconnetti';
-$lang['edit']             = 'Modifica';
-$lang['show']             = 'Mostra';
-$lang['new']              = 'Nuovo';
-$lang['delete']           = 'Cancella';
-$lang['copy']             = 'Copia';
-$lang['csvexport']        = 'CSV';
-$lang['vcfexport']        = 'VCard';
-$lang['vcfimport']        = 'Importa';
-$lang['search']           = 'Cerca';
-$lang['submit']           = 'Invia';
-$lang['help']             = 'Aiuto';
-$lang['select']           = 'Seleziona';
-$lang['orgs']             = 'Aziende';
-$lang['upload']           = 'Carica';
-
-$lang['publicbook']       = 'Indirizzario pubblico';
-$lang['privatebook']      = 'Indirizzario privato';
-
-$lang['username']         = 'Username';
-$lang['password']         = 'Password';
-$lang['remember']         = 'Rimani connesso su questo computer';
-
-$lang['msg_login']        = 'Collegarsi, prego!';
-$lang['msg_loginfail']    = 'Accessi fallito!';
-$lang['msg_reallydel']    = 'Cancella veramente?';
-$lang['msg_addto']        = 'Scegli l\'indirizzario a cui aggiungere la voce:';
-$lang['msg_jpegonly']     = 'Solo JPEG';
-$lang['msg_dateformat']   = 'YYYY-MM-DD';
-$lang['msg_uploadvcf']    = 'Upload VCard File';
-$lang['msg_tagsep']       = 'Separato da virgole';
-
-$lang['err_noentries']    = 'Nessuna voce';
-$lang['err_ldap']         = 'Il server LDAP ha restituito i seguenti errori';
-
-$lang['openxchange']      = 'Xchange Information';
-$lang['moreopenxchange']  = 'Xchange Information Cont\'d';
-$lang['instantmessenger'] = 'Inst Msg';
-$lang['categories']       = 'Categorie';
-$lang['birthday']         = 'Compleanno';
-$lang['domain']           = 'Dominio e-mail';
-$lang['country']          = 'Paese';
-$lang['certificate']      = 'Certificato x.509';
-$lang['timezone']         = 'Fuso orario';
-$lang['position']         = 'Posizione';
-$lang['ipphone']          = 'Telefono IP';
-
diff --git a/lang/nl.php b/lang/nl.php
deleted file mode 100644 (file)
index 6c11f73..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-/**
- * Dutch language file
- *
- * @author Riny Heijdendael <riny@heijdendael.nl>
- */
-
-$lang['ldapab']           = 'Het LDAP adresboek';
-
-$lang['name']             = 'Achternaam';
-$lang['givenname']        = 'Voornaam';
-$lang['title']            = 'Titel';
-$lang['organization']     = 'Bedrijf';
-$lang['office']           = 'Kantoor';
-$lang['street']           = 'Straat';
-$lang['zip']              = 'Postcode';
-$lang['location']         = 'Stad';
-$lang['phone']            = 'Telefoon';
-$lang['fax']              = 'FAX';
-$lang['mobile']           = 'Mobiel';
-$lang['pager']            = 'Pager';
-$lang['homephone']        = 'Telefoon (priv.)';
-$lang['homestreet']       = 'Adres (priv.)';
-$lang['photo']            = 'Afbeelding';
-$lang['url']              = 'Website';
-$lang['note']             = 'Aantekeningen';
-$lang['mail']             = 'E-Mail';
-$lang['manager']          = 'Key Account';
-
-$lang['anniversary']      = 'Verjaardag';
-$lang['marker']           = 'Categorieen';
-$lang['tagcloud']         = 'Alle gebruikte categorieen, op alfabet gesorteerd. Veelgebruikte categorieen worden groter afgebeeld';
-
-$lang['business']         = 'Bedrijf';
-$lang['private']          = 'Prive';
-$lang['extended']         = 'Overige informatie';
-
-$lang['delphoto']         = 'Verwijder bestaande afbeelding';
-
-$lang['notloggedin']      = 'Niet ingelogd';
-$lang['loggedinas']       = 'Ingelogd als';
-$lang['login']            = 'Log in';
-$lang['logout']           = 'Log uit';
-$lang['edit']             = 'Wijzig';
-$lang['show']             = 'Toon';
-$lang['new']              = 'Nieuw';
-$lang['delete']           = 'Verwijder';
-$lang['copy']             = 'Dupliceer';
-$lang['csvexport']        = 'CSV';
-$lang['vcfexport']        = 'VCard';
-$lang['vcfimport']        = 'Importeer';
-$lang['search']           = 'Zoek';
-$lang['submit']           = 'Verstuur';
-$lang['help']             = 'Help';
-$lang['select']           = 'Selecteer';
-$lang['orgs']             = 'Bedrijven';
-$lang['upload']           = 'Upload';
-
-$lang['publicbook']       = 'Publiek Adresboek';
-$lang['privatebook']      = 'Persoonlijk Adresboek';
-
-$lang['username']         = 'Gebruikersnaam';
-$lang['password']         = 'Wachtwoord';
-$lang['remember']         = 'Blijf ingelogd op deze computer';
-
-$lang['msg_login']        = 'Log eerst in SVP!';
-$lang['msg_loginfail']    = 'Inloggen mislukt!';
-$lang['msg_reallydel']    = 'Deze definitief verwijderen?';
-$lang['msg_addto']        = 'Kies adresboek om op te slaan:';
-$lang['msg_jpegonly']     = 'Alleen JPEG afbeeldingen';
-$lang['msg_dateformat']   = 'YYYY-MM-DD';
-$lang['msg_uploadvcf']    = 'Upload VCard bestand';
-$lang['msg_tagsep']       = 'Komma gescheiden (CSV)';
-
-$lang['err_noentries']    = 'Geen gegevens';
-$lang['err_ldap']         = 'De LDAP server meldt de volgende fouten:';
-
-$lang['openxchange']      = 'Xchange Informatie';
-$lang['moreopenxchange']  = 'Xchange Informatie (meer..)';
-$lang['instantmessenger'] = 'Intstant messenger';
-$lang['categories']       = 'Categorieen';
-$lang['birthday']         = 'Verjaardag';
-$lang['domain']           = 'Email domein';
-$lang['country']          = 'Land';
-$lang['certificate']      = 'x.509 Certificaat';
-$lang['timezone']         = 'Tijdzone';
-$lang['position']         = 'Positie';
-$lang['ipphone']          = 'VOIP Telefoon';
-
-
diff --git a/ldapab.schema b/ldapab.schema
deleted file mode 100644 (file)
index 19f2060..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-# LDAP 2 Schema
-#
-# This is a schema extension for the LDAPab Addressbook by
-# CosmoCode GmbH www.cosmocode.de
-#
-# CosmoCode owns the following MIB Block:
-# iso.org.dod.internet.private.enterprise.16331.*
-#
-# CosmoCode currently uses the following OID hierachy to organize the IDs:
-#
-# defined in cosmo4ML.schema
-# 1.3.6.1.4.1.16331.1           formel CMS (cosmo4ML prefix)
-# 1.3.6.1.4.1.16331.1.1           SNMP (not used)
-# 1.3.6.1.4.1.16331.1.2           LDAP
-# 1.3.6.1.4.1.16331.1.2.1           AttributeTypes
-# 1.3.6.1.4.1.16331.1.2.2           ObjectClasses
-#
-# defined in ldapab.schema:
-# 1.3.6.1.4.1.16331.2          LDAPab
-# 1.3.6.1.4.1.16331.2.1                  SNMP (not used)
-# 1.3.6.1.4.1.16331.2.2                LDAP
-# 1.3.6.1.4.1.16331.2.2.1           AttributeTypes
-# 1.3.6.1.4.1.16331.2.2.2           ObjectClasses
-
-
-# OID macros for ease of use:
-objectIdentifier cosmocodeOID 1.3.6.1.4.1.16331
-objectIdentifier LDAPab       cosmocodeOID:2.2
-
-
-attributetype ( 1.3.6.1.4.1.16331.2.2.1.1 NAME 'anniversary'
-                DESC 'Holds Birthdays etc.'
-                EQUALITY caseIgnoreMatch
-                ORDERING caseIgnoreOrderingMatch
-                SUBSTR caseIgnoreSubstringsMatch
-                SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
-                SINGLE-VALUE )
-
-attributetype ( 1.3.6.1.4.1.16331.2.2.1.2 NAME 'marker'
-                DESC 'marking flag'
-                EQUALITY caseIgnoreMatch
-                ORDERING caseIgnoreOrderingMatch
-                SUBSTR caseIgnoreSubstringsMatch
-                SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256}
-               )
-
-objectclass ( 1.3.6.1.4.1.16331.2.2.2.1 NAME 'contactPerson'
-             DESC 'Contact - Addressbook entry'
-              AUXILIARY
-              MAY  ( anniversary $ marker )
-            )
index 524d75f8487247c907e89a5304ff8d7666dd6ecb..7df3d520cff04ffb03d4e27231e3bf633d88fea1 100644 (file)
--- a/login.php
+++ b/login.php
@@ -3,7 +3,7 @@
  * Do the login/logout process
  */
 
-require_once('init.php');
+require_once('inc/init.php');
 
 $msg = $lang['msg_login'];
 if(isset($_REQUEST['username'])){
index 6e79970ab28e807e6e9d7b747e1afc8f12ea31f5..0f6426ce80a23568d2228a93cb66749a5b821d6b 100644 (file)
--- a/orgs.php
+++ b/orgs.php
@@ -1,5 +1,5 @@
 <?
-  require_once('init.php');
+  require_once('inc/init.php');
   ldap_login();
 
   //prepare templates
diff --git a/slapd.example b/slapd.example
deleted file mode 100644 (file)
index cd7643a..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-# This is the main ldapd configuration file. See slapd.conf(5) for more
-# info on the configuration options.
-
-# Schema and objectClass definitions
-include         /etc/ldap/schema/core.schema
-include         /etc/ldap/schema/cosine.schema
-include         /etc/ldap/schema/nis.schema
-include         /etc/ldap/schema/inetorgperson.schema
-include                /etc/ldap/schema/samba.schema
-include                /etc/ldap/schema/courierimap.schema
-include                /etc/ldap/schema/phpgwaccount.schema
-include                /etc/ldap/schema/phpgwcontact.schema
-include                /etc/ldap/schema/ldapab.schema
-
-
-# Schema check allows for forcing entries to
-# match schemas for their objectClasses's
-schemacheck     on
-
-# Where the pid file is put. The init.d script
-# will not stop the server if you change this.
-pidfile         /var/run/slapd.pid
-
-# List of arguments that were passed to the server
-argsfile        /var/run/slapd.args
-
-# Where to store the replica logs
-replogfile     /var/lib/ldap/replog
-
-# Read slapd.conf(5) for possible values
-#loglevel        256
-loglevel       0
-
-#######################################################################
-# ldbm database definitions
-#######################################################################
-
-# The backend type, ldbm, is the default standard
-database        ldbm
-
-# The base of your directory
-suffix          "o=cosmocode,c=de"
-
-# Where the database file are physically stored
-directory       "/var/lib/ldap"
-
-# Indexing options
-index objectClass eq
-
-# Folgende Indizies sind im samba-LDAP-HOWTO empfohlen;
-
-## support pbb_getsampwnam()
-index uid           pres,eq
-## support pdb_getsampwrid()
-index rid           eq
-
-## uncomment these if you are storing posixAccount and
-## posixGroup entries in the directory as well
-index uidNumber     eq
-index gidNumber     eq
-index cn            eq
-index memberUid     eq
-
-# Save the time that the entry gets modified
-lastmod on
-
-# The userPassword by default can be changed
-# by the entry owning it if they are authenticated.
-# Others should not be able to see it, except the
-# admin entry below
-access to attribute=userPassword
-        by dn="cn=admin,o=cosmocode,c=de" write
-        by anonymous auth
-        by self write
-        by * none
-
-access to attribute=lmPassword
-        by dn="cn=admin,o=cosmocode,c=de" write
-        by anonymous auth
-        by self write
-        by * none
-
-access to attribute=ntPassword
-        by dn="cn=admin,o=cosmocode,c=de" write
-        by anonymous auth
-        by self write
-        by * none
-
-# private LDAP Addressbook is readable and writable for the owner only
-access to dn="(.*,)?ou=contacts,cn=([^,]+),ou=people,(.*)$"
-        by dn="cn=$2,ou=people,$3" write
-        by * none
-
-# global LDAP Addressbook is writable for all authenticated users
-# This entry has to be _before_ any other entry that matches the contact
-# tree eg. the * entry
-access to dn.subtree="ou=contacts,o=cosmocode,c=de"
-       by users write
-       by * read
-
-# The admin dn has full write access
-access to *
-        by dn="cn=admin,o=cosmocode,c=de" write
-        by * read
-
-# For Netscape Roaming support, each user gets a roaming
-# profile for which they have write access to
-#access to dn=".*,ou=Roaming,o=morsnet"
-#        by dn="cn=admin,o=cosmocode,c=de" write
-#        by dnattr=owner write
-
diff --git a/smarty/Config_File.class.php b/smarty/Config_File.class.php
deleted file mode 100644 (file)
index 3d7c1b4..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-<?php
-
-/**
- * Config_File class.
- *
- * 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
- *
- * @link http://smarty.php.net/
- * @version 2.6.18
- * @copyright Copyright: 2001-2005 New Digital Group, Inc.
- * @author Andrei Zmievski <andrei@php.net>
- * @access public
- * @package Smarty
- */
-
-/* $Id: Config_File.class.php,v 1.88 2007/03/06 10:40:06 messju Exp $ */
-
-/**
- * Config file reading class
- * @package Smarty
- */
-class Config_File {
-    /**#@+
-     * Options
-     * @var boolean
-     */
-    /**
-     * Controls whether variables with the same name overwrite each other.
-     */
-    var $overwrite        =    true;
-
-    /**
-     * Controls whether config values of on/true/yes and off/false/no get
-     * converted to boolean values automatically.
-     */
-    var $booleanize        =    true;
-
-    /**
-     * Controls whether hidden config sections/vars are read from the file.
-     */
-    var $read_hidden     =    true;
-
-    /**
-     * Controls whether or not to fix mac or dos formatted newlines.
-     * If set to true, \r or \r\n will be changed to \n.
-     */
-    var $fix_newlines =    true;
-    /**#@-*/
-
-    /** @access private */
-    var $_config_path    = "";
-    var $_config_data    = array();
-    /**#@-*/
-
-    /**
-     * Constructs a new config file class.
-     *
-     * @param string $config_path (optional) path to the config files
-     */
-    function Config_File($config_path = NULL)
-    {
-        if (isset($config_path))
-            $this->set_path($config_path);
-    }
-
-
-    /**
-     * Set the path where configuration files can be found.
-     *
-     * @param string $config_path path to the config files
-     */
-    function set_path($config_path)
-    {
-        if (!empty($config_path)) {
-            if (!is_string($config_path) || !file_exists($config_path) || !is_dir($config_path)) {
-                $this->_trigger_error_msg("Bad config file path '$config_path'");
-                return;
-            }
-            if(substr($config_path, -1) != DIRECTORY_SEPARATOR) {
-                $config_path .= DIRECTORY_SEPARATOR;
-            }
-
-            $this->_config_path = $config_path;
-        }
-    }
-
-
-    /**
-     * Retrieves config info based on the file, section, and variable name.
-     *
-     * @param string $file_name config file to get info for
-     * @param string $section_name (optional) section to get info for
-     * @param string $var_name (optional) variable to get info for
-     * @return string|array a value or array of values
-     */
-    function get($file_name, $section_name = NULL, $var_name = NULL)
-    {
-        if (empty($file_name)) {
-            $this->_trigger_error_msg('Empty config file name');
-            return;
-        } else {
-            $file_name = $this->_config_path . $file_name;
-            if (!isset($this->_config_data[$file_name]))
-                $this->load_file($file_name, false);
-        }
-
-        if (!empty($var_name)) {
-            if (empty($section_name)) {
-                return $this->_config_data[$file_name]["vars"][$var_name];
-            } else {
-                if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name]))
-                    return $this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name];
-                else
-                    return array();
-            }
-        } else {
-            if (empty($section_name)) {
-                return (array)$this->_config_data[$file_name]["vars"];
-            } else {
-                if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"]))
-                    return (array)$this->_config_data[$file_name]["sections"][$section_name]["vars"];
-                else
-                    return array();
-            }
-        }
-    }
-
-
-    /**
-     * Retrieves config info based on the key.
-     *
-     * @param $file_name string config key (filename/section/var)
-     * @return string|array same as get()
-     * @uses get() retrieves information from config file and returns it
-     */
-    function &get_key($config_key)
-    {
-        list($file_name, $section_name, $var_name) = explode('/', $config_key, 3);
-        $result = &$this->get($file_name, $section_name, $var_name);
-        return $result;
-    }
-
-    /**
-     * Get all loaded config file names.
-     *
-     * @return array an array of loaded config file names
-     */
-    function get_file_names()
-    {
-        return array_keys($this->_config_data);
-    }
-
-
-    /**
-     * Get all section names from a loaded file.
-     *
-     * @param string $file_name config file to get section names from
-     * @return array an array of section names from the specified file
-     */
-    function get_section_names($file_name)
-    {
-        $file_name = $this->_config_path . $file_name;
-        if (!isset($this->_config_data[$file_name])) {
-            $this->_trigger_error_msg("Unknown config file '$file_name'");
-            return;
-        }
-
-        return array_keys($this->_config_data[$file_name]["sections"]);
-    }
-
-
-    /**
-     * Get all global or section variable names.
-     *
-     * @param string $file_name config file to get info for
-     * @param string $section_name (optional) section to get info for
-     * @return array an array of variables names from the specified file/section
-     */
-    function get_var_names($file_name, $section = NULL)
-    {
-        if (empty($file_name)) {
-            $this->_trigger_error_msg('Empty config file name');
-            return;
-        } else if (!isset($this->_config_data[$file_name])) {
-            $this->_trigger_error_msg("Unknown config file '$file_name'");
-            return;
-        }
-
-        if (empty($section))
-            return array_keys($this->_config_data[$file_name]["vars"]);
-        else
-            return array_keys($this->_config_data[$file_name]["sections"][$section]["vars"]);
-    }
-
-
-    /**
-     * Clear loaded config data for a certain file or all files.
-     *
-     * @param string $file_name file to clear config data for
-     */
-    function clear($file_name = NULL)
-    {
-        if ($file_name === NULL)
-            $this->_config_data = array();
-        else if (isset($this->_config_data[$file_name]))
-            $this->_config_data[$file_name] = array();
-    }
-
-
-    /**
-     * Load a configuration file manually.
-     *
-     * @param string $file_name file name to load
-     * @param boolean $prepend_path whether current config path should be
-     *                              prepended to the filename
-     */
-    function load_file($file_name, $prepend_path = true)
-    {
-        if ($prepend_path && $this->_config_path != "")
-            $config_file = $this->_config_path . $file_name;
-        else
-            $config_file = $file_name;
-
-        ini_set('track_errors', true);
-        $fp = @fopen($config_file, "r");
-        if (!is_resource($fp)) {
-            $this->_trigger_error_msg("Could not open config file '$config_file'");
-            return false;
-        }
-
-        $contents = ($size = filesize($config_file)) ? fread($fp, $size) : '';
-        fclose($fp);
-
-        $this->_config_data[$config_file] = $this->parse_contents($contents);
-        return true;
-    }
-
-    /**
-     * Store the contents of a file manually.
-     *
-     * @param string $config_file file name of the related contents
-     * @param string $contents the file-contents to parse
-     */
-    function set_file_contents($config_file, $contents)
-    {
-        $this->_config_data[$config_file] = $this->parse_contents($contents);
-        return true;
-    }
-
-    /**
-     * parse the source of a configuration file manually.
-     *
-     * @param string $contents the file-contents to parse
-     */
-    function parse_contents($contents)
-    {
-        if($this->fix_newlines) {
-            // fix mac/dos formatted newlines
-            $contents = preg_replace('!\r\n?!', "\n", $contents);
-        }
-
-        $config_data = array();
-        $config_data['sections'] = array();
-        $config_data['vars'] = array();
-
-        /* reference to fill with data */
-        $vars =& $config_data['vars'];
-
-        /* parse file line by line */
-        preg_match_all('!^.*\r?\n?!m', $contents, $match);
-        $lines = $match[0];
-        for ($i=0, $count=count($lines); $i<$count; $i++) {
-            $line = $lines[$i];
-            if (empty($line)) continue;
-
-            if ( substr($line, 0, 1) == '[' && preg_match('!^\[(.*?)\]!', $line, $match) ) {
-                /* section found */
-                if (substr($match[1], 0, 1) == '.') {
-                    /* hidden section */
-                    if ($this->read_hidden) {
-                        $section_name = substr($match[1], 1);
-                    } else {
-                        /* break reference to $vars to ignore hidden section */
-                        unset($vars);
-                        $vars = array();
-                        continue;
-                    }
-                } else {                    
-                    $section_name = $match[1];
-                }
-                if (!isset($config_data['sections'][$section_name]))
-                    $config_data['sections'][$section_name] = array('vars' => array());
-                $vars =& $config_data['sections'][$section_name]['vars'];
-                continue;
-            }
-
-            if (preg_match('/^\s*(\.?\w+)\s*=\s*(.*)/s', $line, $match)) {
-                /* variable found */
-                $var_name = rtrim($match[1]);
-                if (strpos($match[2], '"""') === 0) {
-                    /* handle multiline-value */
-                    $lines[$i] = substr($match[2], 3);
-                    $var_value = '';
-                    while ($i<$count) {
-                        if (($pos = strpos($lines[$i], '"""')) === false) {
-                            $var_value .= $lines[$i++];
-                        } else {
-                            /* end of multiline-value */
-                            $var_value .= substr($lines[$i], 0, $pos);
-                            break;
-                        }
-                    }
-                    $booleanize = false;
-
-                } else {
-                    /* handle simple value */
-                    $var_value = preg_replace('/^([\'"])(.*)\1$/', '\2', rtrim($match[2]));
-                    $booleanize = $this->booleanize;
-
-                }
-                $this->_set_config_var($vars, $var_name, $var_value, $booleanize);
-            }
-            /* else unparsable line / means it is a comment / means ignore it */
-        }
-        return $config_data;
-    }
-
-    /**#@+ @access private */
-    /**
-     * @param array &$container
-     * @param string $var_name
-     * @param mixed $var_value
-     * @param boolean $booleanize determines whether $var_value is converted to
-     *                            to true/false
-     */
-    function _set_config_var(&$container, $var_name, $var_value, $booleanize)
-    {
-        if (substr($var_name, 0, 1) == '.') {
-            if (!$this->read_hidden)
-                return;
-            else
-                $var_name = substr($var_name, 1);
-        }
-
-        if (!preg_match("/^[a-zA-Z_]\w*$/", $var_name)) {
-            $this->_trigger_error_msg("Bad variable name '$var_name'");
-            return;
-        }
-
-        if ($booleanize) {
-            if (preg_match("/^(on|true|yes)$/i", $var_value))
-                $var_value = true;
-            else if (preg_match("/^(off|false|no)$/i", $var_value))
-                $var_value = false;
-        }
-
-        if (!isset($container[$var_name]) || $this->overwrite)
-            $container[$var_name] = $var_value;
-        else {
-            settype($container[$var_name], 'array');
-            $container[$var_name][] = $var_value;
-        }
-    }
-
-    /**
-     * @uses trigger_error() creates a PHP warning/error
-     * @param string $error_msg
-     * @param integer $error_type one of
-     */
-    function _trigger_error_msg($error_msg, $error_type = E_USER_WARNING)
-    {
-        trigger_error("Config_File error: $error_msg", $error_type);
-    }
-    /**#@-*/
-}
-
-?>
diff --git a/smarty/Smarty.class.php b/smarty/Smarty.class.php
deleted file mode 100644 (file)
index f05e0da..0000000
+++ /dev/null
@@ -1,1944 +0,0 @@
-<?php
-
-/**
- * Project:     Smarty: the PHP compiling template engine
- * File:        Smarty.class.php
- *
- * 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
- *
- * For questions, help, comments, discussion, etc., please join the
- * Smarty mailing list. Send a blank e-mail to
- * smarty-general-subscribe@lists.php.net
- *
- * @link http://smarty.php.net/
- * @copyright 2001-2005 New Digital Group, Inc.
- * @author Monte Ohrt <monte at ohrt dot com>
- * @author Andrei Zmievski <andrei@php.net>
- * @package Smarty
- * @version 2.6.18
- */
-
-/* $Id: Smarty.class.php,v 1.528 2007/03/06 10:40:06 messju Exp $ */
-
-/**
- * DIR_SEP isn't used anymore, but third party apps might
- */
-if(!defined('DIR_SEP')) {
-    define('DIR_SEP', DIRECTORY_SEPARATOR);
-}
-
-/**
- * set SMARTY_DIR to absolute path to Smarty library files.
- * if not defined, include_path will be used. Sets SMARTY_DIR only if user
- * application has not already defined it.
- */
-
-if (!defined('SMARTY_DIR')) {
-    define('SMARTY_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR);
-}
-
-if (!defined('SMARTY_CORE_DIR')) {
-    define('SMARTY_CORE_DIR', SMARTY_DIR . 'internals' . DIRECTORY_SEPARATOR);
-}
-
-define('SMARTY_PHP_PASSTHRU',   0);
-define('SMARTY_PHP_QUOTE',      1);
-define('SMARTY_PHP_REMOVE',     2);
-define('SMARTY_PHP_ALLOW',      3);
-
-/**
- * @package Smarty
- */
-class Smarty
-{
-    /**#@+
-     * Smarty Configuration Section
-     */
-
-    /**
-     * The name of the directory where templates are located.
-     *
-     * @var string
-     */
-    var $template_dir    =  'templates';
-
-    /**
-     * The directory where compiled templates are located.
-     *
-     * @var string
-     */
-    var $compile_dir     =  'templates_c';
-
-    /**
-     * The directory where config files are located.
-     *
-     * @var string
-     */
-    var $config_dir      =  'configs';
-
-    /**
-     * An array of directories searched for plugins.
-     *
-     * @var array
-     */
-    var $plugins_dir     =  array('plugins');
-
-    /**
-     * If debugging is enabled, a debug console window will display
-     * when the page loads (make sure your browser allows unrequested
-     * popup windows)
-     *
-     * @var boolean
-     */
-    var $debugging       =  false;
-
-    /**
-     * When set, smarty does uses this value as error_reporting-level.
-     *
-     * @var boolean
-     */
-    var $error_reporting  =  null;
-
-    /**
-     * This is the path to the debug console template. If not set,
-     * the default one will be used.
-     *
-     * @var string
-     */
-    var $debug_tpl       =  '';
-
-    /**
-     * This determines if debugging is enable-able from the browser.
-     * <ul>
-     *  <li>NONE => no debugging control allowed</li>
-     *  <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
-     * </ul>
-     * @link http://www.foo.dom/index.php?SMARTY_DEBUG
-     * @var string
-     */
-    var $debugging_ctrl  =  'NONE';
-
-    /**
-     * This tells Smarty whether to check for recompiling or not. Recompiling
-     * does not need to happen unless a template or config file is changed.
-     * Typically you enable this during development, and disable for
-     * production.
-     *
-     * @var boolean
-     */
-    var $compile_check   =  true;
-
-    /**
-     * This forces templates to compile every time. Useful for development
-     * or debugging.
-     *
-     * @var boolean
-     */
-    var $force_compile   =  false;
-
-    /**
-     * This enables template caching.
-     * <ul>
-     *  <li>0 = no caching</li>
-     *  <li>1 = use class cache_lifetime value</li>
-     *  <li>2 = use cache_lifetime in cache file</li>
-     * </ul>
-     * @var integer
-     */
-    var $caching         =  0;
-
-    /**
-     * The name of the directory for cache files.
-     *
-     * @var string
-     */
-    var $cache_dir       =  'cache';
-
-    /**
-     * This is the number of seconds cached content will persist.
-     * <ul>
-     *  <li>0 = always regenerate cache</li>
-     *  <li>-1 = never expires</li>
-     * </ul>
-     *
-     * @var integer
-     */
-    var $cache_lifetime  =  3600;
-
-    /**
-     * Only used when $caching is enabled. If true, then If-Modified-Since headers
-     * are respected with cached content, and appropriate HTTP headers are sent.
-     * This way repeated hits to a cached page do not send the entire page to the
-     * client every time.
-     *
-     * @var boolean
-     */
-    var $cache_modified_check = false;
-
-    /**
-     * This determines how Smarty handles "<?php ... ?>" tags in templates.
-     * possible values:
-     * <ul>
-     *  <li>SMARTY_PHP_PASSTHRU -> print tags as plain text</li>
-     *  <li>SMARTY_PHP_QUOTE    -> escape tags as entities</li>
-     *  <li>SMARTY_PHP_REMOVE   -> remove php tags</li>
-     *  <li>SMARTY_PHP_ALLOW    -> execute php tags</li>
-     * </ul>
-     *
-     * @var integer
-     */
-    var $php_handling    =  SMARTY_PHP_PASSTHRU;
-
-    /**
-     * This enables template security. When enabled, many things are restricted
-     * in the templates that normally would go unchecked. This is useful when
-     * untrusted parties are editing templates and you want a reasonable level
-     * of security. (no direct execution of PHP in templates for example)
-     *
-     * @var boolean
-     */
-    var $security       =   false;
-
-    /**
-     * This is the list of template directories that are considered secure. This
-     * is used only if {@link $security} is enabled. One directory per array
-     * element.  {@link $template_dir} is in this list implicitly.
-     *
-     * @var array
-     */
-    var $secure_dir     =   array();
-
-    /**
-     * These are the security settings for Smarty. They are used only when
-     * {@link $security} is enabled.
-     *
-     * @var array
-     */
-    var $security_settings  = array(
-                                    'PHP_HANDLING'    => false,
-                                    'IF_FUNCS'        => array('array', 'list',
-                                                               'isset', 'empty',
-                                                               'count', 'sizeof',
-                                                               'in_array', 'is_array',
-                                                               'true', 'false', 'null'),
-                                    'INCLUDE_ANY'     => false,
-                                    'PHP_TAGS'        => false,
-                                    'MODIFIER_FUNCS'  => array('count'),
-                                    'ALLOW_CONSTANTS'  => false
-                                   );
-
-    /**
-     * This is an array of directories where trusted php scripts reside.
-     * {@link $security} is disabled during their inclusion/execution.
-     *
-     * @var array
-     */
-    var $trusted_dir        = array();
-
-    /**
-     * The left delimiter used for the template tags.
-     *
-     * @var string
-     */
-    var $left_delimiter  =  '{';
-
-    /**
-     * The right delimiter used for the template tags.
-     *
-     * @var string
-     */
-    var $right_delimiter =  '}';
-
-    /**
-     * The order in which request variables are registered, similar to
-     * variables_order in php.ini E = Environment, G = GET, P = POST,
-     * C = Cookies, S = Server
-     *
-     * @var string
-     */
-    var $request_vars_order    = 'EGPCS';
-
-    /**
-     * Indicates wether $HTTP_*_VARS[] (request_use_auto_globals=false)
-     * are uses as request-vars or $_*[]-vars. note: if
-     * request_use_auto_globals is true, then $request_vars_order has
-     * no effect, but the php-ini-value "gpc_order"
-     *
-     * @var boolean
-     */
-    var $request_use_auto_globals      = true;
-
-    /**
-     * Set this if you want different sets of compiled files for the same
-     * templates. This is useful for things like different languages.
-     * Instead of creating separate sets of templates per language, you
-     * set different compile_ids like 'en' and 'de'.
-     *
-     * @var string
-     */
-    var $compile_id            = null;
-
-    /**
-     * This tells Smarty whether or not to use sub dirs in the cache/ and
-     * templates_c/ directories. sub directories better organized, but
-     * may not work well with PHP safe mode enabled.
-     *
-     * @var boolean
-     *
-     */
-    var $use_sub_dirs          = false;
-
-    /**
-     * This is a list of the modifiers to apply to all template variables.
-     * Put each modifier in a separate array element in the order you want
-     * them applied. example: <code>array('escape:"htmlall"');</code>
-     *
-     * @var array
-     */
-    var $default_modifiers        = array();
-
-    /**
-     * This is the resource type to be used when not specified
-     * at the beginning of the resource path. examples:
-     * $smarty->display('file:index.tpl');
-     * $smarty->display('db:index.tpl');
-     * $smarty->display('index.tpl'); // will use default resource type
-     * {include file="file:index.tpl"}
-     * {include file="db:index.tpl"}
-     * {include file="index.tpl"} {* will use default resource type *}
-     *
-     * @var array
-     */
-    var $default_resource_type    = 'file';
-
-    /**
-     * The function used for cache file handling. If not set, built-in caching is used.
-     *
-     * @var null|string function name
-     */
-    var $cache_handler_func   = null;
-
-    /**
-     * This indicates which filters are automatically loaded into Smarty.
-     *
-     * @var array array of filter names
-     */
-    var $autoload_filters = array();
-
-    /**#@+
-     * @var boolean
-     */
-    /**
-     * This tells if config file vars of the same name overwrite each other or not.
-     * if disabled, same name variables are accumulated in an array.
-     */
-    var $config_overwrite = true;
-
-    /**
-     * This tells whether or not to automatically booleanize config file variables.
-     * If enabled, then the strings "on", "true", and "yes" are treated as boolean
-     * true, and "off", "false" and "no" are treated as boolean false.
-     */
-    var $config_booleanize = true;
-
-    /**
-     * This tells whether hidden sections [.foobar] are readable from the
-     * tempalates or not. Normally you would never allow this since that is
-     * the point behind hidden sections: the application can access them, but
-     * the templates cannot.
-     */
-    var $config_read_hidden = false;
-
-    /**
-     * This tells whether or not automatically fix newlines in config files.
-     * It basically converts \r (mac) or \r\n (dos) to \n
-     */
-    var $config_fix_newlines = true;
-    /**#@-*/
-
-    /**
-     * If a template cannot be found, this PHP function will be executed.
-     * Useful for creating templates on-the-fly or other special action.
-     *
-     * @var string function name
-     */
-    var $default_template_handler_func = '';
-
-    /**
-     * The file that contains the compiler class. This can a full
-     * pathname, or relative to the php_include path.
-     *
-     * @var string
-     */
-    var $compiler_file        =    'Smarty_Compiler.class.php';
-
-    /**
-     * The class used for compiling templates.
-     *
-     * @var string
-     */
-    var $compiler_class        =   'Smarty_Compiler';
-
-    /**
-     * The class used to load config vars.
-     *
-     * @var string
-     */
-    var $config_class          =   'Config_File';
-
-/**#@+
- * END Smarty Configuration Section
- * There should be no need to touch anything below this line.
- * @access private
- */
-    /**
-     * where assigned template vars are kept
-     *
-     * @var array
-     */
-    var $_tpl_vars             = array();
-
-    /**
-     * stores run-time $smarty.* vars
-     *
-     * @var null|array
-     */
-    var $_smarty_vars          = null;
-
-    /**
-     * keeps track of sections
-     *
-     * @var array
-     */
-    var $_sections             = array();
-
-    /**
-     * keeps track of foreach blocks
-     *
-     * @var array
-     */
-    var $_foreach              = array();
-
-    /**
-     * keeps track of tag hierarchy
-     *
-     * @var array
-     */
-    var $_tag_stack            = array();
-
-    /**
-     * configuration object
-     *
-     * @var Config_file
-     */
-    var $_conf_obj             = null;
-
-    /**
-     * loaded configuration settings
-     *
-     * @var array
-     */
-    var $_config               = array(array('vars'  => array(), 'files' => array()));
-
-    /**
-     * md5 checksum of the string 'Smarty'
-     *
-     * @var string
-     */
-    var $_smarty_md5           = 'f8d698aea36fcbead2b9d5359ffca76f';
-
-    /**
-     * Smarty version number
-     *
-     * @var string
-     */
-    var $_version              = '2.6.18';
-
-    /**
-     * current template inclusion depth
-     *
-     * @var integer
-     */
-    var $_inclusion_depth      = 0;
-
-    /**
-     * for different compiled templates
-     *
-     * @var string
-     */
-    var $_compile_id           = null;
-
-    /**
-     * text in URL to enable debug mode
-     *
-     * @var string
-     */
-    var $_smarty_debug_id      = 'SMARTY_DEBUG';
-
-    /**
-     * debugging information for debug console
-     *
-     * @var array
-     */
-    var $_smarty_debug_info    = array();
-
-    /**
-     * info that makes up a cache file
-     *
-     * @var array
-     */
-    var $_cache_info           = array();
-
-    /**
-     * default file permissions
-     *
-     * @var integer
-     */
-    var $_file_perms           = 0644;
-
-    /**
-     * default dir permissions
-     *
-     * @var integer
-     */
-    var $_dir_perms               = 0771;
-
-    /**
-     * registered objects
-     *
-     * @var array
-     */
-    var $_reg_objects           = array();
-
-    /**
-     * table keeping track of plugins
-     *
-     * @var array
-     */
-    var $_plugins              = array(
-                                       'modifier'      => array(),
-                                       'function'      => array(),
-                                       'block'         => array(),
-                                       'compiler'      => array(),
-                                       'prefilter'     => array(),
-                                       'postfilter'    => array(),
-                                       'outputfilter'  => array(),
-                                       'resource'      => array(),
-                                       'insert'        => array());
-
-
-    /**
-     * cache serials
-     *
-     * @var array
-     */
-    var $_cache_serials = array();
-
-    /**
-     * name of optional cache include file
-     *
-     * @var string
-     */
-    var $_cache_include = null;
-
-    /**
-     * indicate if the current code is used in a compiled
-     * include
-     *
-     * @var string
-     */
-    var $_cache_including = false;
-
-    /**#@-*/
-    /**
-     * The class constructor.
-     */
-    function Smarty()
-    {
-      $this->assign('SCRIPT_NAME', isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME']
-                    : @$GLOBALS['HTTP_SERVER_VARS']['SCRIPT_NAME']);
-    }
-
-    /**
-     * assigns values to template variables
-     *
-     * @param array|string $tpl_var the template variable name(s)
-     * @param mixed $value the value to assign
-     */
-    function assign($tpl_var, $value = null)
-    {
-        if (is_array($tpl_var)){
-            foreach ($tpl_var as $key => $val) {
-                if ($key != '') {
-                    $this->_tpl_vars[$key] = $val;
-                }
-            }
-        } else {
-            if ($tpl_var != '')
-                $this->_tpl_vars[$tpl_var] = $value;
-        }
-    }
-
-    /**
-     * assigns values to template variables by reference
-     *
-     * @param string $tpl_var the template variable name
-     * @param mixed $value the referenced value to assign
-     */
-    function assign_by_ref($tpl_var, &$value)
-    {
-        if ($tpl_var != '')
-            $this->_tpl_vars[$tpl_var] = &$value;
-    }
-
-    /**
-     * appends values to template variables
-     *
-     * @param array|string $tpl_var the template variable name(s)
-     * @param mixed $value the value to append
-     */
-    function append($tpl_var, $value=null, $merge=false)
-    {
-        if (is_array($tpl_var)) {
-            // $tpl_var is an array, ignore $value
-            foreach ($tpl_var as $_key => $_val) {
-                if ($_key != '') {
-                    if(!@is_array($this->_tpl_vars[$_key])) {
-                        settype($this->_tpl_vars[$_key],'array');
-                    }
-                    if($merge && is_array($_val)) {
-                        foreach($_val as $_mkey => $_mval) {
-                            $this->_tpl_vars[$_key][$_mkey] = $_mval;
-                        }
-                    } else {
-                        $this->_tpl_vars[$_key][] = $_val;
-                    }
-                }
-            }
-        } else {
-            if ($tpl_var != '' && isset($value)) {
-                if(!@is_array($this->_tpl_vars[$tpl_var])) {
-                    settype($this->_tpl_vars[$tpl_var],'array');
-                }
-                if($merge && is_array($value)) {
-                    foreach($value as $_mkey => $_mval) {
-                        $this->_tpl_vars[$tpl_var][$_mkey] = $_mval;
-                    }
-                } else {
-                    $this->_tpl_vars[$tpl_var][] = $value;
-                }
-            }
-        }
-    }
-
-    /**
-     * appends values to template variables by reference
-     *
-     * @param string $tpl_var the template variable name
-     * @param mixed $value the referenced value to append
-     */
-    function append_by_ref($tpl_var, &$value, $merge=false)
-    {
-        if ($tpl_var != '' && isset($value)) {
-            if(!@is_array($this->_tpl_vars[$tpl_var])) {
-             settype($this->_tpl_vars[$tpl_var],'array');
-            }
-            if ($merge && is_array($value)) {
-                foreach($value as $_key => $_val) {
-                    $this->_tpl_vars[$tpl_var][$_key] = &$value[$_key];
-                }
-            } else {
-                $this->_tpl_vars[$tpl_var][] = &$value;
-            }
-        }
-    }
-
-
-    /**
-     * clear the given assigned template variable.
-     *
-     * @param string $tpl_var the template variable to clear
-     */
-    function clear_assign($tpl_var)
-    {
-        if (is_array($tpl_var))
-            foreach ($tpl_var as $curr_var)
-                unset($this->_tpl_vars[$curr_var]);
-        else
-            unset($this->_tpl_vars[$tpl_var]);
-    }
-
-
-    /**
-     * Registers custom function to be used in templates
-     *
-     * @param string $function the name of the template function
-     * @param string $function_impl the name of the PHP function to register
-     */
-    function register_function($function, $function_impl, $cacheable=true, $cache_attrs=null)
-    {
-        $this->_plugins['function'][$function] =
-            array($function_impl, null, null, false, $cacheable, $cache_attrs);
-
-    }
-
-    /**
-     * Unregisters custom function
-     *
-     * @param string $function name of template function
-     */
-    function unregister_function($function)
-    {
-        unset($this->_plugins['function'][$function]);
-    }
-
-    /**
-     * Registers object to be used in templates
-     *
-     * @param string $object name of template object
-     * @param object &$object_impl the referenced PHP object to register
-     * @param null|array $allowed list of allowed methods (empty = all)
-     * @param boolean $smarty_args smarty argument format, else traditional
-     * @param null|array $block_functs list of methods that are block format
-     */
-    function register_object($object, &$object_impl, $allowed = array(), $smarty_args = true, $block_methods = array())
-    {
-        settype($allowed, 'array');
-        settype($smarty_args, 'boolean');
-        $this->_reg_objects[$object] =
-            array(&$object_impl, $allowed, $smarty_args, $block_methods);
-    }
-
-    /**
-     * Unregisters object
-     *
-     * @param string $object name of template object
-     */
-    function unregister_object($object)
-    {
-        unset($this->_reg_objects[$object]);
-    }
-
-
-    /**
-     * Registers block function to be used in templates
-     *
-     * @param string $block name of template block
-     * @param string $block_impl PHP function to register
-     */
-    function register_block($block, $block_impl, $cacheable=true, $cache_attrs=null)
-    {
-        $this->_plugins['block'][$block] =
-            array($block_impl, null, null, false, $cacheable, $cache_attrs);
-    }
-
-    /**
-     * Unregisters block function
-     *
-     * @param string $block name of template function
-     */
-    function unregister_block($block)
-    {
-        unset($this->_plugins['block'][$block]);
-    }
-
-    /**
-     * Registers compiler function
-     *
-     * @param string $function name of template function
-     * @param string $function_impl name of PHP function to register
-     */
-    function register_compiler_function($function, $function_impl, $cacheable=true)
-    {
-        $this->_plugins['compiler'][$function] =
-            array($function_impl, null, null, false, $cacheable);
-    }
-
-    /**
-     * Unregisters compiler function
-     *
-     * @param string $function name of template function
-     */
-    function unregister_compiler_function($function)
-    {
-        unset($this->_plugins['compiler'][$function]);
-    }
-
-    /**
-     * Registers modifier to be used in templates
-     *
-     * @param string $modifier name of template modifier
-     * @param string $modifier_impl name of PHP function to register
-     */
-    function register_modifier($modifier, $modifier_impl)
-    {
-        $this->_plugins['modifier'][$modifier] =
-            array($modifier_impl, null, null, false);
-    }
-
-    /**
-     * Unregisters modifier
-     *
-     * @param string $modifier name of template modifier
-     */
-    function unregister_modifier($modifier)
-    {
-        unset($this->_plugins['modifier'][$modifier]);
-    }
-
-    /**
-     * Registers a resource to fetch a template
-     *
-     * @param string $type name of resource
-     * @param array $functions array of functions to handle resource
-     */
-    function register_resource($type, $functions)
-    {
-        if (count($functions)==4) {
-            $this->_plugins['resource'][$type] =
-                array($functions, false);
-
-        } elseif (count($functions)==5) {
-            $this->_plugins['resource'][$type] =
-                array(array(array(&$functions[0], $functions[1])
-                            ,array(&$functions[0], $functions[2])
-                            ,array(&$functions[0], $functions[3])
-                            ,array(&$functions[0], $functions[4]))
-                      ,false);
-
-        } else {
-            $this->trigger_error("malformed function-list for '$type' in register_resource");
-
-        }
-    }
-
-    /**
-     * Unregisters a resource
-     *
-     * @param string $type name of resource
-     */
-    function unregister_resource($type)
-    {
-        unset($this->_plugins['resource'][$type]);
-    }
-
-    /**
-     * Registers a prefilter function to apply
-     * to a template before compiling
-     *
-     * @param string $function name of PHP function to register
-     */
-    function register_prefilter($function)
-    {
-    $_name = (is_array($function)) ? $function[1] : $function;
-        $this->_plugins['prefilter'][$_name]
-            = array($function, null, null, false);
-    }
-
-    /**
-     * Unregisters a prefilter function
-     *
-     * @param string $function name of PHP function
-     */
-    function unregister_prefilter($function)
-    {
-        unset($this->_plugins['prefilter'][$function]);
-    }
-
-    /**
-     * Registers a postfilter function to apply
-     * to a compiled template after compilation
-     *
-     * @param string $function name of PHP function to register
-     */
-    function register_postfilter($function)
-    {
-    $_name = (is_array($function)) ? $function[1] : $function;
-        $this->_plugins['postfilter'][$_name]
-            = array($function, null, null, false);
-    }
-
-    /**
-     * Unregisters a postfilter function
-     *
-     * @param string $function name of PHP function
-     */
-    function unregister_postfilter($function)
-    {
-        unset($this->_plugins['postfilter'][$function]);
-    }
-
-    /**
-     * Registers an output filter function to apply
-     * to a template output
-     *
-     * @param string $function name of PHP function
-     */
-    function register_outputfilter($function)
-    {
-    $_name = (is_array($function)) ? $function[1] : $function;
-        $this->_plugins['outputfilter'][$_name]
-            = array($function, null, null, false);
-    }
-
-    /**
-     * Unregisters an outputfilter function
-     *
-     * @param string $function name of PHP function
-     */
-    function unregister_outputfilter($function)
-    {
-        unset($this->_plugins['outputfilter'][$function]);
-    }
-
-    /**
-     * load a filter of specified type and name
-     *
-     * @param string $type filter type
-     * @param string $name filter name
-     */
-    function load_filter($type, $name)
-    {
-        switch ($type) {
-            case 'output':
-                $_params = array('plugins' => array(array($type . 'filter', $name, null, null, false)));
-                require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
-                smarty_core_load_plugins($_params, $this);
-                break;
-
-            case 'pre':
-            case 'post':
-                if (!isset($this->_plugins[$type . 'filter'][$name]))
-                    $this->_plugins[$type . 'filter'][$name] = false;
-                break;
-        }
-    }
-
-    /**
-     * clear cached content for the given template and cache id
-     *
-     * @param string $tpl_file name of template file
-     * @param string $cache_id name of cache_id
-     * @param string $compile_id name of compile_id
-     * @param string $exp_time expiration time
-     * @return boolean
-     */
-    function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null)
-    {
-
-        if (!isset($compile_id))
-            $compile_id = $this->compile_id;
-
-        if (!isset($tpl_file))
-            $compile_id = null;
-
-        $_auto_id = $this->_get_auto_id($cache_id, $compile_id);
-
-        if (!empty($this->cache_handler_func)) {
-            return call_user_func_array($this->cache_handler_func,
-                                  array('clear', &$this, &$dummy, $tpl_file, $cache_id, $compile_id, $exp_time));
-        } else {
-            $_params = array('auto_base' => $this->cache_dir,
-                            'auto_source' => $tpl_file,
-                            'auto_id' => $_auto_id,
-                            'exp_time' => $exp_time);
-            require_once(SMARTY_CORE_DIR . 'core.rm_auto.php');
-            return smarty_core_rm_auto($_params, $this);
-        }
-
-    }
-
-
-    /**
-     * clear the entire contents of cache (all templates)
-     *
-     * @param string $exp_time expire time
-     * @return boolean results of {@link smarty_core_rm_auto()}
-     */
-    function clear_all_cache($exp_time = null)
-    {
-        return $this->clear_cache(null, null, null, $exp_time);
-    }
-
-
-    /**
-     * test to see if valid cache exists for this template
-     *
-     * @param string $tpl_file name of template file
-     * @param string $cache_id
-     * @param string $compile_id
-     * @return string|false results of {@link _read_cache_file()}
-     */
-    function is_cached($tpl_file, $cache_id = null, $compile_id = null)
-    {
-        if (!$this->caching)
-            return false;
-
-        if (!isset($compile_id))
-            $compile_id = $this->compile_id;
-
-        $_params = array(
-            'tpl_file' => $tpl_file,
-            'cache_id' => $cache_id,
-            'compile_id' => $compile_id
-        );
-        require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php');
-        return smarty_core_read_cache_file($_params, $this);
-    }
-
-
-    /**
-     * clear all the assigned template variables.
-     *
-     */
-    function clear_all_assign()
-    {
-        $this->_tpl_vars = array();
-    }
-
-    /**
-     * clears compiled version of specified template resource,
-     * or all compiled template files if one is not specified.
-     * This function is for advanced use only, not normally needed.
-     *
-     * @param string $tpl_file
-     * @param string $compile_id
-     * @param string $exp_time
-     * @return boolean results of {@link smarty_core_rm_auto()}
-     */
-    function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp_time = null)
-    {
-        if (!isset($compile_id)) {
-            $compile_id = $this->compile_id;
-        }
-        $_params = array('auto_base' => $this->compile_dir,
-                        'auto_source' => $tpl_file,
-                        'auto_id' => $compile_id,
-                        'exp_time' => $exp_time,
-                        'extensions' => array('.inc', '.php'));
-        require_once(SMARTY_CORE_DIR . 'core.rm_auto.php');
-        return smarty_core_rm_auto($_params, $this);
-    }
-
-    /**
-     * Checks whether requested template exists.
-     *
-     * @param string $tpl_file
-     * @return boolean
-     */
-    function template_exists($tpl_file)
-    {
-        $_params = array('resource_name' => $tpl_file, 'quiet'=>true, 'get_source'=>false);
-        return $this->_fetch_resource_info($_params);
-    }
-
-    /**
-     * Returns an array containing template variables
-     *
-     * @param string $name
-     * @param string $type
-     * @return array
-     */
-    function &get_template_vars($name=null)
-    {
-        if(!isset($name)) {
-            return $this->_tpl_vars;
-        } elseif(isset($this->_tpl_vars[$name])) {
-            return $this->_tpl_vars[$name];
-        } else {
-            // var non-existant, return valid reference
-            $_tmp = null;
-            return $_tmp;   
-        }
-    }
-
-    /**
-     * Returns an array containing config variables
-     *
-     * @param string $name
-     * @param string $type
-     * @return array
-     */
-    function &get_config_vars($name=null)
-    {
-        if(!isset($name) && is_array($this->_config[0])) {
-            return $this->_config[0]['vars'];
-        } else if(isset($this->_config[0]['vars'][$name])) {
-            return $this->_config[0]['vars'][$name];
-        } else {
-            // var non-existant, return valid reference
-            $_tmp = null;
-            return $_tmp;
-        }
-    }
-
-    /**
-     * trigger Smarty error
-     *
-     * @param string $error_msg
-     * @param integer $error_type
-     */
-    function trigger_error($error_msg, $error_type = E_USER_WARNING)
-    {
-        trigger_error("Smarty error: $error_msg", $error_type);
-    }
-
-
-    /**
-     * executes & displays the template results
-     *
-     * @param string $resource_name
-     * @param string $cache_id
-     * @param string $compile_id
-     */
-    function display($resource_name, $cache_id = null, $compile_id = null)
-    {
-        $this->fetch($resource_name, $cache_id, $compile_id, true);
-    }
-
-    /**
-     * executes & returns or displays the template results
-     *
-     * @param string $resource_name
-     * @param string $cache_id
-     * @param string $compile_id
-     * @param boolean $display
-     */
-    function fetch($resource_name, $cache_id = null, $compile_id = null, $display = false)
-    {
-        static $_cache_info = array();
-        
-        $_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(isset($this->error_reporting)
-               ? $this->error_reporting : error_reporting() & ~E_NOTICE);
-
-        if (!$this->debugging && $this->debugging_ctrl == 'URL') {
-            $_query_string = $this->request_use_auto_globals ? $_SERVER['QUERY_STRING'] : $GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING'];
-            if (@strstr($_query_string, $this->_smarty_debug_id)) {
-                if (@strstr($_query_string, $this->_smarty_debug_id . '=on')) {
-                    // enable debugging for this browser session
-                    @setcookie('SMARTY_DEBUG', true);
-                    $this->debugging = true;
-                } elseif (@strstr($_query_string, $this->_smarty_debug_id . '=off')) {
-                    // disable debugging for this browser session
-                    @setcookie('SMARTY_DEBUG', false);
-                    $this->debugging = false;
-                } else {
-                    // enable debugging for this page
-                    $this->debugging = true;
-                }
-            } else {
-                $this->debugging = (bool)($this->request_use_auto_globals ? @$_COOKIE['SMARTY_DEBUG'] : @$GLOBALS['HTTP_COOKIE_VARS']['SMARTY_DEBUG']);
-            }
-        }
-
-        if ($this->debugging) {
-            // capture time for debugging info
-            $_params = array();
-            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
-            $_debug_start_time = smarty_core_get_microtime($_params, $this);
-            $this->_smarty_debug_info[] = array('type'      => 'template',
-                                                'filename'  => $resource_name,
-                                                'depth'     => 0);
-            $_included_tpls_idx = count($this->_smarty_debug_info) - 1;
-        }
-
-        if (!isset($compile_id)) {
-            $compile_id = $this->compile_id;
-        }
-
-        $this->_compile_id = $compile_id;
-        $this->_inclusion_depth = 0;
-
-        if ($this->caching) {
-            // save old cache_info, initialize cache_info
-            array_push($_cache_info, $this->_cache_info);
-            $this->_cache_info = array();
-            $_params = array(
-                'tpl_file' => $resource_name,
-                'cache_id' => $cache_id,
-                'compile_id' => $compile_id,
-                'results' => null
-            );
-            require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php');
-            if (smarty_core_read_cache_file($_params, $this)) {
-                $_smarty_results = $_params['results'];
-                if (!empty($this->_cache_info['insert_tags'])) {
-                    $_params = array('plugins' => $this->_cache_info['insert_tags']);
-                    require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
-                    smarty_core_load_plugins($_params, $this);
-                    $_params = array('results' => $_smarty_results);
-                    require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php');
-                    $_smarty_results = smarty_core_process_cached_inserts($_params, $this);
-                }
-                if (!empty($this->_cache_info['cache_serials'])) {
-                    $_params = array('results' => $_smarty_results);
-                    require_once(SMARTY_CORE_DIR . 'core.process_compiled_include.php');
-                    $_smarty_results = smarty_core_process_compiled_include($_params, $this);
-                }
-
-
-                if ($display) {
-                    if ($this->debugging)
-                    {
-                        // capture time for debugging info
-                        $_params = array();
-                        require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
-                        $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $_debug_start_time;
-                        require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php');
-                        $_smarty_results .= smarty_core_display_debug_console($_params, $this);
-                    }
-                    if ($this->cache_modified_check) {
-                        $_server_vars = ($this->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
-                        $_last_modified_date = @substr($_server_vars['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_server_vars['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3);
-                        $_gmt_mtime = gmdate('D, d M Y H:i:s', $this->_cache_info['timestamp']).' GMT';
-                        if (@count($this->_cache_info['insert_tags']) == 0
-                            && !$this->_cache_serials
-                            && $_gmt_mtime == $_last_modified_date) {
-                            if (php_sapi_name()=='cgi')
-                                header('Status: 304 Not Modified');
-                            else
-                                header('HTTP/1.1 304 Not Modified');
-
-                        } else {
-                            header('Last-Modified: '.$_gmt_mtime);
-                            echo $_smarty_results;
-                        }
-                    } else {
-                            echo $_smarty_results;
-                    }
-                    error_reporting($_smarty_old_error_level);
-                    // restore initial cache_info
-                    $this->_cache_info = array_pop($_cache_info);
-                    return true;
-                } else {
-                    error_reporting($_smarty_old_error_level);
-                    // restore initial cache_info
-                    $this->_cache_info = array_pop($_cache_info);
-                    return $_smarty_results;
-                }
-            } else {
-                $this->_cache_info['template'][$resource_name] = true;
-                if ($this->cache_modified_check && $display) {
-                    header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');
-                }
-            }
-        }
-
-        // load filters that are marked as autoload
-        if (count($this->autoload_filters)) {
-            foreach ($this->autoload_filters as $_filter_type => $_filters) {
-                foreach ($_filters as $_filter) {
-                    $this->load_filter($_filter_type, $_filter);
-                }
-            }
-        }
-
-        $_smarty_compile_path = $this->_get_compile_path($resource_name);
-
-        // if we just need to display the results, don't perform output
-        // buffering - for speed
-        $_cache_including = $this->_cache_including;
-        $this->_cache_including = false;
-        if ($display && !$this->caching && count($this->_plugins['outputfilter']) == 0) {
-            if ($this->_is_compiled($resource_name, $_smarty_compile_path)
-                    || $this->_compile_resource($resource_name, $_smarty_compile_path))
-            {
-                include($_smarty_compile_path);
-            }
-        } else {
-            ob_start();
-            if ($this->_is_compiled($resource_name, $_smarty_compile_path)
-                    || $this->_compile_resource($resource_name, $_smarty_compile_path))
-            {
-                include($_smarty_compile_path);
-            }
-            $_smarty_results = ob_get_contents();
-            ob_end_clean();
-
-            foreach ((array)$this->_plugins['outputfilter'] as $_output_filter) {
-                $_smarty_results = call_user_func_array($_output_filter[0], array($_smarty_results, &$this));
-            }
-        }
-
-        if ($this->caching) {
-            $_params = array('tpl_file' => $resource_name,
-                        'cache_id' => $cache_id,
-                        'compile_id' => $compile_id,
-                        'results' => $_smarty_results);
-            require_once(SMARTY_CORE_DIR . 'core.write_cache_file.php');
-            smarty_core_write_cache_file($_params, $this);
-            require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php');
-            $_smarty_results = smarty_core_process_cached_inserts($_params, $this);
-
-            if ($this->_cache_serials) {
-                // strip nocache-tags from output
-                $_smarty_results = preg_replace('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!s'
-                                                ,''
-                                                ,$_smarty_results);
-            }
-            // restore initial cache_info
-            $this->_cache_info = array_pop($_cache_info);
-        }
-        $this->_cache_including = $_cache_including;
-
-        if ($display) {
-            if (isset($_smarty_results)) { echo $_smarty_results; }
-            if ($this->debugging) {
-                // capture time for debugging info
-                $_params = array();
-                require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
-                $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = (smarty_core_get_microtime($_params, $this) - $_debug_start_time);
-                require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php');
-                echo smarty_core_display_debug_console($_params, $this);
-            }
-            error_reporting($_smarty_old_error_level);
-            return;
-        } else {
-            error_reporting($_smarty_old_error_level);
-            if (isset($_smarty_results)) { return $_smarty_results; }
-        }
-    }
-
-    /**
-     * load configuration values
-     *
-     * @param string $file
-     * @param string $section
-     * @param string $scope
-     */
-    function config_load($file, $section = null, $scope = 'global')
-    {
-        require_once($this->_get_plugin_filepath('function', 'config_load'));
-        smarty_function_config_load(array('file' => $file, 'section' => $section, 'scope' => $scope), $this);
-    }
-
-    /**
-     * return a reference to a registered object
-     *
-     * @param string $name
-     * @return object
-     */
-    function &get_registered_object($name) {
-        if (!isset($this->_reg_objects[$name]))
-        $this->_trigger_fatal_error("'$name' is not a registered object");
-
-        if (!is_object($this->_reg_objects[$name][0]))
-        $this->_trigger_fatal_error("registered '$name' is not an object");
-
-        return $this->_reg_objects[$name][0];
-    }
-
-    /**
-     * clear configuration values
-     *
-     * @param string $var
-     */
-    function clear_config($var = null)
-    {
-        if(!isset($var)) {
-            // clear all values
-            $this->_config = array(array('vars'  => array(),
-                                         'files' => array()));
-        } else {
-            unset($this->_config[0]['vars'][$var]);
-        }
-    }
-
-    /**
-     * get filepath of requested plugin
-     *
-     * @param string $type
-     * @param string $name
-     * @return string|false
-     */
-    function _get_plugin_filepath($type, $name)
-    {
-        $_params = array('type' => $type, 'name' => $name);
-        require_once(SMARTY_CORE_DIR . 'core.assemble_plugin_filepath.php');
-        return smarty_core_assemble_plugin_filepath($_params, $this);
-    }
-
-   /**
-     * test if resource needs compiling
-     *
-     * @param string $resource_name
-     * @param string $compile_path
-     * @return boolean
-     */
-    function _is_compiled($resource_name, $compile_path)
-    {
-        if (!$this->force_compile && file_exists($compile_path)) {
-            if (!$this->compile_check) {
-                // no need to check compiled file
-                return true;
-            } else {
-                // get file source and timestamp
-                $_params = array('resource_name' => $resource_name, 'get_source'=>false);
-                if (!$this->_fetch_resource_info($_params)) {
-                    return false;
-                }
-                if ($_params['resource_timestamp'] <= filemtime($compile_path)) {
-                    // template not expired, no recompile
-                    return true;
-                } else {
-                    // compile template
-                    return false;
-                }
-            }
-        } else {
-            // compiled template does not exist, or forced compile
-            return false;
-        }
-    }
-
-   /**
-     * compile the template
-     *
-     * @param string $resource_name
-     * @param string $compile_path
-     * @return boolean
-     */
-    function _compile_resource($resource_name, $compile_path)
-    {
-
-        $_params = array('resource_name' => $resource_name);
-        if (!$this->_fetch_resource_info($_params)) {
-            return false;
-        }
-
-        $_source_content = $_params['source_content'];
-        $_cache_include    = substr($compile_path, 0, -4).'.inc';
-
-        if ($this->_compile_source($resource_name, $_source_content, $_compiled_content, $_cache_include)) {
-            // if a _cache_serial was set, we also have to write an include-file:
-            if ($this->_cache_include_info) {
-                require_once(SMARTY_CORE_DIR . 'core.write_compiled_include.php');
-                smarty_core_write_compiled_include(array_merge($this->_cache_include_info, array('compiled_content'=>$_compiled_content, 'resource_name'=>$resource_name)),  $this);
-            }
-
-            $_params = array('compile_path'=>$compile_path, 'compiled_content' => $_compiled_content);
-            require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php');
-            smarty_core_write_compiled_resource($_params, $this);
-
-            return true;
-        } else {
-            return false;
-        }
-
-    }
-
-   /**
-     * compile the given source
-     *
-     * @param string $resource_name
-     * @param string $source_content
-     * @param string $compiled_content
-     * @return boolean
-     */
-    function _compile_source($resource_name, &$source_content, &$compiled_content, $cache_include_path=null)
-    {
-        if (file_exists(SMARTY_DIR . $this->compiler_file)) {
-            require_once(SMARTY_DIR . $this->compiler_file);
-        } else {
-            // use include_path
-            require_once($this->compiler_file);
-        }
-
-
-        $smarty_compiler = new $this->compiler_class;
-
-        $smarty_compiler->template_dir      = $this->template_dir;
-        $smarty_compiler->compile_dir       = $this->compile_dir;
-        $smarty_compiler->plugins_dir       = $this->plugins_dir;
-        $smarty_compiler->config_dir        = $this->config_dir;
-        $smarty_compiler->force_compile     = $this->force_compile;
-        $smarty_compiler->caching           = $this->caching;
-        $smarty_compiler->php_handling      = $this->php_handling;
-        $smarty_compiler->left_delimiter    = $this->left_delimiter;
-        $smarty_compiler->right_delimiter   = $this->right_delimiter;
-        $smarty_compiler->_version          = $this->_version;
-        $smarty_compiler->security          = $this->security;
-        $smarty_compiler->secure_dir        = $this->secure_dir;
-        $smarty_compiler->security_settings = $this->security_settings;
-        $smarty_compiler->trusted_dir       = $this->trusted_dir;
-        $smarty_compiler->use_sub_dirs      = $this->use_sub_dirs;
-        $smarty_compiler->_reg_objects      = &$this->_reg_objects;
-        $smarty_compiler->_plugins          = &$this->_plugins;
-        $smarty_compiler->_tpl_vars         = &$this->_tpl_vars;
-        $smarty_compiler->default_modifiers = $this->default_modifiers;
-        $smarty_compiler->compile_id        = $this->_compile_id;
-        $smarty_compiler->_config            = $this->_config;
-        $smarty_compiler->request_use_auto_globals  = $this->request_use_auto_globals;
-
-        if (isset($cache_include_path) && isset($this->_cache_serials[$cache_include_path])) {
-            $smarty_compiler->_cache_serial = $this->_cache_serials[$cache_include_path];
-        }
-        $smarty_compiler->_cache_include = $cache_include_path;
-
-
-        $_results = $smarty_compiler->_compile_file($resource_name, $source_content, $compiled_content);
-
-        if ($smarty_compiler->_cache_serial) {
-            $this->_cache_include_info = array(
-                'cache_serial'=>$smarty_compiler->_cache_serial
-                ,'plugins_code'=>$smarty_compiler->_plugins_code
-                ,'include_file_path' => $cache_include_path);
-
-        } else {
-            $this->_cache_include_info = null;
-
-        }
-
-        return $_results;
-    }
-
-    /**
-     * Get the compile path for this resource
-     *
-     * @param string $resource_name
-     * @return string results of {@link _get_auto_filename()}
-     */
-    function _get_compile_path($resource_name)
-    {
-        return $this->_get_auto_filename($this->compile_dir, $resource_name,
-                                         $this->_compile_id) . '.php';
-    }
-
-    /**
-     * fetch the template info. Gets timestamp, and source
-     * if get_source is true
-     *
-     * sets $source_content to the source of the template, and
-     * $resource_timestamp to its time stamp
-     * @param string $resource_name
-     * @param string $source_content
-     * @param integer $resource_timestamp
-     * @param boolean $get_source
-     * @param boolean $quiet
-     * @return boolean
-     */
-
-    function _fetch_resource_info(&$params)
-    {
-        if(!isset($params['get_source'])) { $params['get_source'] = true; }
-        if(!isset($params['quiet'])) { $params['quiet'] = false; }
-
-        $_return = false;
-        $_params = array('resource_name' => $params['resource_name']) ;
-        if (isset($params['resource_base_path']))
-            $_params['resource_base_path'] = $params['resource_base_path'];
-        else
-            $_params['resource_base_path'] = $this->template_dir;
-
-        if ($this->_parse_resource_name($_params)) {
-            $_resource_type = $_params['resource_type'];
-            $_resource_name = $_params['resource_name'];
-            switch ($_resource_type) {
-                case 'file':
-                    if ($params['get_source']) {
-                        $params['source_content'] = $this->_read_file($_resource_name);
-                    }
-                    $params['resource_timestamp'] = filemtime($_resource_name);
-                    $_return = is_file($_resource_name);
-                    break;
-
-                default:
-                    // call resource functions to fetch the template source and timestamp
-                    if ($params['get_source']) {
-                        $_source_return = isset($this->_plugins['resource'][$_resource_type]) &&
-                            call_user_func_array($this->_plugins['resource'][$_resource_type][0][0],
-                                                 array($_resource_name, &$params['source_content'], &$this));
-                    } else {
-                        $_source_return = true;
-                    }
-
-                    $_timestamp_return = isset($this->_plugins['resource'][$_resource_type]) &&
-                        call_user_func_array($this->_plugins['resource'][$_resource_type][0][1],
-                                             array($_resource_name, &$params['resource_timestamp'], &$this));
-
-                    $_return = $_source_return && $_timestamp_return;
-                    break;
-            }
-        }
-
-        if (!$_return) {
-            // see if we can get a template with the default template handler
-            if (!empty($this->default_template_handler_func)) {
-                if (!is_callable($this->default_template_handler_func)) {
-                    $this->trigger_error("default template handler function \"$this->default_template_handler_func\" doesn't exist.");
-                } else {
-                    $_return = call_user_func_array(
-                        $this->default_template_handler_func,
-                        array($_params['resource_type'], $_params['resource_name'], &$params['source_content'], &$params['resource_timestamp'], &$this));
-                }
-            }
-        }
-
-        if (!$_return) {
-            if (!$params['quiet']) {
-                $this->trigger_error('unable to read resource: "' . $params['resource_name'] . '"');
-            }
-        } else if ($_return && $this->security) {
-            require_once(SMARTY_CORE_DIR . 'core.is_secure.php');
-            if (!smarty_core_is_secure($_params, $this)) {
-                if (!$params['quiet'])
-                    $this->trigger_error('(secure mode) accessing "' . $params['resource_name'] . '" is not allowed');
-                $params['source_content'] = null;
-                $params['resource_timestamp'] = null;
-                return false;
-            }
-        }
-        return $_return;
-    }
-
-
-    /**
-     * parse out the type and name from the resource
-     *
-     * @param string $resource_base_path
-     * @param string $resource_name
-     * @param string $resource_type
-     * @param string $resource_name
-     * @return boolean
-     */
-
-    function _parse_resource_name(&$params)
-    {
-
-        // split tpl_path by the first colon
-        $_resource_name_parts = explode(':', $params['resource_name'], 2);
-
-        if (count($_resource_name_parts) == 1) {
-            // no resource type given
-            $params['resource_type'] = $this->default_resource_type;
-            $params['resource_name'] = $_resource_name_parts[0];
-        } else {
-            if(strlen($_resource_name_parts[0]) == 1) {
-                // 1 char is not resource type, but part of filepath
-                $params['resource_type'] = $this->default_resource_type;
-                $params['resource_name'] = $params['resource_name'];
-            } else {
-                $params['resource_type'] = $_resource_name_parts[0];
-                $params['resource_name'] = $_resource_name_parts[1];
-            }
-        }
-
-        if ($params['resource_type'] == 'file') {
-            if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $params['resource_name'])) {
-                // relative pathname to $params['resource_base_path']
-                // use the first directory where the file is found
-                foreach ((array)$params['resource_base_path'] as $_curr_path) {
-                    $_fullpath = $_curr_path . DIRECTORY_SEPARATOR . $params['resource_name'];
-                    if (file_exists($_fullpath) && is_file($_fullpath)) {
-                        $params['resource_name'] = $_fullpath;
-                        return true;
-                    }
-                    // didn't find the file, try include_path
-                    $_params = array('file_path' => $_fullpath);
-                    require_once(SMARTY_CORE_DIR . 'core.get_include_path.php');
-                    if(smarty_core_get_include_path($_params, $this)) {
-                        $params['resource_name'] = $_params['new_file_path'];
-                        return true;
-                    }
-                }
-                return false;
-            } else {
-                /* absolute path */
-                return file_exists($params['resource_name']);
-            }
-        } elseif (empty($this->_plugins['resource'][$params['resource_type']])) {
-            $_params = array('type' => $params['resource_type']);
-            require_once(SMARTY_CORE_DIR . 'core.load_resource_plugin.php');
-            smarty_core_load_resource_plugin($_params, $this);
-        }
-
-        return true;
-    }
-
-
-    /**
-     * Handle modifiers
-     *
-     * @param string|null $modifier_name
-     * @param array|null $map_array
-     * @return string result of modifiers
-     */
-    function _run_mod_handler()
-    {
-        $_args = func_get_args();
-        list($_modifier_name, $_map_array) = array_splice($_args, 0, 2);
-        list($_func_name, $_tpl_file, $_tpl_line) =
-            $this->_plugins['modifier'][$_modifier_name];
-
-        $_var = $_args[0];
-        foreach ($_var as $_key => $_val) {
-            $_args[0] = $_val;
-            $_var[$_key] = call_user_func_array($_func_name, $_args);
-        }
-        return $_var;
-    }
-
-    /**
-     * Remove starting and ending quotes from the string
-     *
-     * @param string $string
-     * @return string
-     */
-    function _dequote($string)
-    {
-        if ((substr($string, 0, 1) == "'" || substr($string, 0, 1) == '"') &&
-            substr($string, -1) == substr($string, 0, 1))
-            return substr($string, 1, -1);
-        else
-            return $string;
-    }
-
-
-    /**
-     * read in a file
-     *
-     * @param string $filename
-     * @return string
-     */
-    function _read_file($filename)
-    {
-        if ( file_exists($filename) && ($fd = @fopen($filename, 'rb')) ) {
-            $contents = '';
-            while (!feof($fd)) {
-                $contents .= fread($fd, 8192);
-            }
-            fclose($fd);
-            return $contents;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * get a concrete filename for automagically created content
-     *
-     * @param string $auto_base
-     * @param string $auto_source
-     * @param string $auto_id
-     * @return string
-     * @staticvar string|null
-     * @staticvar string|null
-     */
-    function _get_auto_filename($auto_base, $auto_source = null, $auto_id = null)
-    {
-        $_compile_dir_sep =  $this->use_sub_dirs ? DIRECTORY_SEPARATOR : '^';
-        $_return = $auto_base . DIRECTORY_SEPARATOR;
-
-        if(isset($auto_id)) {
-            // make auto_id safe for directory names
-            $auto_id = str_replace('%7C',$_compile_dir_sep,(urlencode($auto_id)));
-            // split into separate directories
-            $_return .= $auto_id . $_compile_dir_sep;
-        }
-
-        if(isset($auto_source)) {
-            // make source name safe for filename
-            $_filename = urlencode(basename($auto_source));
-            $_crc32 = sprintf('%08X', crc32($auto_source));
-            // prepend %% to avoid name conflicts with
-            // with $params['auto_id'] names
-            $_crc32 = substr($_crc32, 0, 2) . $_compile_dir_sep .
-                      substr($_crc32, 0, 3) . $_compile_dir_sep . $_crc32;
-            $_return .= '%%' . $_crc32 . '%%' . $_filename;
-        }
-
-        return $_return;
-    }
-
-    /**
-     * unlink a file, possibly using expiration time
-     *
-     * @param string $resource
-     * @param integer $exp_time
-     */
-    function _unlink($resource, $exp_time = null)
-    {
-        if(isset($exp_time)) {
-            if(time() - @filemtime($resource) >= $exp_time) {
-                return @unlink($resource);
-            }
-        } else {
-            return @unlink($resource);
-        }
-    }
-
-    /**
-     * returns an auto_id for auto-file-functions
-     *
-     * @param string $cache_id
-     * @param string $compile_id
-     * @return string|null
-     */
-    function _get_auto_id($cache_id=null, $compile_id=null) {
-    if (isset($cache_id))
-        return (isset($compile_id)) ? $cache_id . '|' . $compile_id  : $cache_id;
-    elseif(isset($compile_id))
-        return $compile_id;
-    else
-        return null;
-    }
-
-    /**
-     * trigger Smarty plugin error
-     *
-     * @param string $error_msg
-     * @param string $tpl_file
-     * @param integer $tpl_line
-     * @param string $file
-     * @param integer $line
-     * @param integer $error_type
-     */
-    function _trigger_fatal_error($error_msg, $tpl_file = null, $tpl_line = null,
-            $file = null, $line = null, $error_type = E_USER_ERROR)
-    {
-        if(isset($file) && isset($line)) {
-            $info = ' ('.basename($file).", line $line)";
-        } else {
-            $info = '';
-        }
-        if (isset($tpl_line) && isset($tpl_file)) {
-            $this->trigger_error('[in ' . $tpl_file . ' line ' . $tpl_line . "]: $error_msg$info", $error_type);
-        } else {
-            $this->trigger_error($error_msg . $info, $error_type);
-        }
-    }
-
-
-    /**
-     * callback function for preg_replace, to call a non-cacheable block
-     * @return string
-     */
-    function _process_compiled_include_callback($match) {
-        $_func = '_smarty_tplfunc_'.$match[2].'_'.$match[3];
-        ob_start();
-        $_func($this);
-        $_ret = ob_get_contents();
-        ob_end_clean();
-        return $_ret;
-    }
-
-
-    /**
-     * called for included templates
-     *
-     * @param string $_smarty_include_tpl_file
-     * @param string $_smarty_include_vars
-     */
-
-    // $_smarty_include_tpl_file, $_smarty_include_vars
-
-    function _smarty_include($params)
-    {
-        if ($this->debugging) {
-            $_params = array();
-            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
-            $debug_start_time = smarty_core_get_microtime($_params, $this);
-            $this->_smarty_debug_info[] = array('type'      => 'template',
-                                                  'filename'  => $params['smarty_include_tpl_file'],
-                                                  'depth'     => ++$this->_inclusion_depth);
-            $included_tpls_idx = count($this->_smarty_debug_info) - 1;
-        }
-
-        $this->_tpl_vars = array_merge($this->_tpl_vars, $params['smarty_include_vars']);
-
-        // config vars are treated as local, so push a copy of the
-        // current ones onto the front of the stack
-        array_unshift($this->_config, $this->_config[0]);
-
-        $_smarty_compile_path = $this->_get_compile_path($params['smarty_include_tpl_file']);
-
-
-        if ($this->_is_compiled($params['smarty_include_tpl_file'], $_smarty_compile_path)
-            || $this->_compile_resource($params['smarty_include_tpl_file'], $_smarty_compile_path))
-        {
-            include($_smarty_compile_path);
-        }
-
-        // pop the local vars off the front of the stack
-        array_shift($this->_config);
-
-        $this->_inclusion_depth--;
-
-        if ($this->debugging) {
-            // capture time for debugging info
-            $_params = array();
-            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
-            $this->_smarty_debug_info[$included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $debug_start_time;
-        }
-
-        if ($this->caching) {
-            $this->_cache_info['template'][$params['smarty_include_tpl_file']] = true;
-        }
-    }
-
-
-    /**
-     * get or set an array of cached attributes for function that is
-     * not cacheable
-     * @return array
-     */
-    function &_smarty_cache_attrs($cache_serial, $count) {
-        $_cache_attrs =& $this->_cache_info['cache_attrs'][$cache_serial][$count];
-
-        if ($this->_cache_including) {
-            /* return next set of cache_attrs */
-            $_return = current($_cache_attrs);
-            next($_cache_attrs);
-            return $_return;
-
-        } else {
-            /* add a reference to a new set of cache_attrs */
-            $_cache_attrs[] = array();
-            return $_cache_attrs[count($_cache_attrs)-1];
-
-        }
-
-    }
-
-
-    /**
-     * wrapper for include() retaining $this
-     * @return mixed
-     */
-    function _include($filename, $once=false, $params=null)
-    {
-        if ($once) {
-            return include_once($filename);
-        } else {
-            return include($filename);
-        }
-    }
-
-
-    /**
-     * wrapper for eval() retaining $this
-     * @return mixed
-     */
-    function _eval($code, $params=null)
-    {
-        return eval($code);
-    }
-    /**#@-*/
-
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/Smarty_Compiler.class.php b/smarty/Smarty_Compiler.class.php
deleted file mode 100644 (file)
index f54cc21..0000000
+++ /dev/null
@@ -1,2327 +0,0 @@
-<?php
-
-/**
- * Project:     Smarty: the PHP compiling template engine
- * File:        Smarty_Compiler.class.php
- *
- * 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
- *
- * @link http://smarty.php.net/
- * @author Monte Ohrt <monte at ohrt dot com>
- * @author Andrei Zmievski <andrei@php.net>
- * @version 2.6.18
- * @copyright 2001-2005 New Digital Group, Inc.
- * @package Smarty
- */
-
-/* $Id: Smarty_Compiler.class.php,v 1.395 2007/03/06 10:40:06 messju Exp $ */
-
-/**
- * Template compiling class
- * @package Smarty
- */
-class Smarty_Compiler extends Smarty {
-
-    // internal vars
-    /**#@+
-     * @access private
-     */
-    var $_folded_blocks         =   array();    // keeps folded template blocks
-    var $_current_file          =   null;       // the current template being compiled
-    var $_current_line_no       =   1;          // line number for error messages
-    var $_capture_stack         =   array();    // keeps track of nested capture buffers
-    var $_plugin_info           =   array();    // keeps track of plugins to load
-    var $_init_smarty_vars      =   false;
-    var $_permitted_tokens      =   array('true','false','yes','no','on','off','null');
-    var $_db_qstr_regexp        =   null;        // regexps are setup in the constructor
-    var $_si_qstr_regexp        =   null;
-    var $_qstr_regexp           =   null;
-    var $_func_regexp           =   null;
-    var $_reg_obj_regexp        =   null;
-    var $_var_bracket_regexp    =   null;
-    var $_num_const_regexp      =   null;
-    var $_dvar_guts_regexp      =   null;
-    var $_dvar_regexp           =   null;
-    var $_cvar_regexp           =   null;
-    var $_svar_regexp           =   null;
-    var $_avar_regexp           =   null;
-    var $_mod_regexp            =   null;
-    var $_var_regexp            =   null;
-    var $_parenth_param_regexp  =   null;
-    var $_func_call_regexp      =   null;
-    var $_obj_ext_regexp        =   null;
-    var $_obj_start_regexp      =   null;
-    var $_obj_params_regexp     =   null;
-    var $_obj_call_regexp       =   null;
-    var $_cacheable_state       =   0;
-    var $_cache_attrs_count     =   0;
-    var $_nocache_count         =   0;
-    var $_cache_serial          =   null;
-    var $_cache_include         =   null;
-
-    var $_strip_depth           =   0;
-    var $_additional_newline    =   "\n";
-
-    /**#@-*/
-    /**
-     * The class constructor.
-     */
-    function Smarty_Compiler()
-    {
-        // matches double quoted strings:
-        // "foobar"
-        // "foo\"bar"
-        $this->_db_qstr_regexp = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"';
-
-        // matches single quoted strings:
-        // 'foobar'
-        // 'foo\'bar'
-        $this->_si_qstr_regexp = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'';
-
-        // matches single or double quoted strings
-        $this->_qstr_regexp = '(?:' . $this->_db_qstr_regexp . '|' . $this->_si_qstr_regexp . ')';
-
-        // matches bracket portion of vars
-        // [0]
-        // [foo]
-        // [$bar]
-        $this->_var_bracket_regexp = '\[\$?[\w\.]+\]';
-
-        // matches numerical constants
-        // 30
-        // -12
-        // 13.22
-        $this->_num_const_regexp = '(?:\-?\d+(?:\.\d+)?)';
-
-        // matches $ vars (not objects):
-        // $foo
-        // $foo.bar
-        // $foo.bar.foobar
-        // $foo[0]
-        // $foo[$bar]
-        // $foo[5][blah]
-        // $foo[5].bar[$foobar][4]
-        $this->_dvar_math_regexp = '(?:[\+\*\/\%]|(?:-(?!>)))';
-        $this->_dvar_math_var_regexp = '[\$\w\.\+\-\*\/\%\d\>\[\]]';
-        $this->_dvar_guts_regexp = '\w+(?:' . $this->_var_bracket_regexp
-                . ')*(?:\.\$?\w+(?:' . $this->_var_bracket_regexp . ')*)*(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?';
-        $this->_dvar_regexp = '\$' . $this->_dvar_guts_regexp;
-
-        // matches config vars:
-        // #foo#
-        // #foobar123_foo#
-        $this->_cvar_regexp = '\#\w+\#';
-
-        // matches section vars:
-        // %foo.bar%
-        $this->_svar_regexp = '\%\w+\.\w+\%';
-
-        // matches all valid variables (no quotes, no modifiers)
-        $this->_avar_regexp = '(?:' . $this->_dvar_regexp . '|'
-           . $this->_cvar_regexp . '|' . $this->_svar_regexp . ')';
-
-        // matches valid variable syntax:
-        // $foo
-        // $foo
-        // #foo#
-        // #foo#
-        // "text"
-        // "text"
-        $this->_var_regexp = '(?:' . $this->_avar_regexp . '|' . $this->_qstr_regexp . ')';
-
-        // matches valid object call (one level of object nesting allowed in parameters):
-        // $foo->bar
-        // $foo->bar()
-        // $foo->bar("text")
-        // $foo->bar($foo, $bar, "text")
-        // $foo->bar($foo, "foo")
-        // $foo->bar->foo()
-        // $foo->bar->foo->bar()
-        // $foo->bar($foo->bar)
-        // $foo->bar($foo->bar())
-        // $foo->bar($foo->bar($blah,$foo,44,"foo",$foo[0].bar))
-        $this->_obj_ext_regexp = '\->(?:\$?' . $this->_dvar_guts_regexp . ')';
-        $this->_obj_restricted_param_regexp = '(?:'
-                . '(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')(?:' . $this->_obj_ext_regexp . '(?:\((?:(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')'
-                . '(?:\s*,\s*(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . '))*)?\))?)*)';
-        $this->_obj_single_param_regexp = '(?:\w+|' . $this->_obj_restricted_param_regexp . '(?:\s*,\s*(?:(?:\w+|'
-                . $this->_var_regexp . $this->_obj_restricted_param_regexp . ')))*)';
-        $this->_obj_params_regexp = '\((?:' . $this->_obj_single_param_regexp
-                . '(?:\s*,\s*' . $this->_obj_single_param_regexp . ')*)?\)';
-        $this->_obj_start_regexp = '(?:' . $this->_dvar_regexp . '(?:' . $this->_obj_ext_regexp . ')+)';
-        $this->_obj_call_regexp = '(?:' . $this->_obj_start_regexp . '(?:' . $this->_obj_params_regexp . ')?(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?)';
-        
-        // matches valid modifier syntax:
-        // |foo
-        // |@foo
-        // |foo:"bar"
-        // |foo:$bar
-        // |foo:"bar":$foobar
-        // |foo|bar
-        // |foo:$foo->bar
-        $this->_mod_regexp = '(?:\|@?\w+(?::(?:\w+|' . $this->_num_const_regexp . '|'
-           . $this->_obj_call_regexp . '|' . $this->_avar_regexp . '|' . $this->_qstr_regexp .'))*)';
-
-        // matches valid function name:
-        // foo123
-        // _foo_bar
-        $this->_func_regexp = '[a-zA-Z_]\w*';
-
-        // matches valid registered object:
-        // foo->bar
-        $this->_reg_obj_regexp = '[a-zA-Z_]\w*->[a-zA-Z_]\w*';
-
-        // matches valid parameter values:
-        // true
-        // $foo
-        // $foo|bar
-        // #foo#
-        // #foo#|bar
-        // "text"
-        // "text"|bar
-        // $foo->bar
-        $this->_param_regexp = '(?:\s*(?:' . $this->_obj_call_regexp . '|'
-           . $this->_var_regexp . '|' . $this->_num_const_regexp  . '|\w+)(?>' . $this->_mod_regexp . '*)\s*)';
-
-        // matches valid parenthesised function parameters:
-        //
-        // "text"
-        //    $foo, $bar, "text"
-        // $foo|bar, "foo"|bar, $foo->bar($foo)|bar
-        $this->_parenth_param_regexp = '(?:\((?:\w+|'
-                . $this->_param_regexp . '(?:\s*,\s*(?:(?:\w+|'
-                . $this->_param_regexp . ')))*)?\))';
-
-        // matches valid function call:
-        // foo()
-        // foo_bar($foo)
-        // _foo_bar($foo,"bar")
-        // foo123($foo,$foo->bar(),"foo")
-        $this->_func_call_regexp = '(?:' . $this->_func_regexp . '\s*(?:'
-           . $this->_parenth_param_regexp . '))';
-    }
-
-    /**
-     * compile a resource
-     *
-     * sets $compiled_content to the compiled source
-     * @param string $resource_name
-     * @param string $source_content
-     * @param string $compiled_content
-     * @return true
-     */
-    function _compile_file($resource_name, $source_content, &$compiled_content)
-    {
-
-        if ($this->security) {
-            // do not allow php syntax to be executed unless specified
-            if ($this->php_handling == SMARTY_PHP_ALLOW &&
-                !$this->security_settings['PHP_HANDLING']) {
-                $this->php_handling = SMARTY_PHP_PASSTHRU;
-            }
-        }
-
-        $this->_load_filters();
-
-        $this->_current_file = $resource_name;
-        $this->_current_line_no = 1;
-        $ldq = preg_quote($this->left_delimiter, '~');
-        $rdq = preg_quote($this->right_delimiter, '~');
-
-        // run template source through prefilter functions
-        if (count($this->_plugins['prefilter']) > 0) {
-            foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) {
-                if ($prefilter === false) continue;
-                if ($prefilter[3] || is_callable($prefilter[0])) {
-                    $source_content = call_user_func_array($prefilter[0],
-                                                            array($source_content, &$this));
-                    $this->_plugins['prefilter'][$filter_name][3] = true;
-                } else {
-                    $this->_trigger_fatal_error("[plugin] prefilter '$filter_name' is not implemented");
-                }
-            }
-        }
-
-        /* fetch all special blocks */
-        $search = "~{$ldq}\*(.*?)\*{$rdq}|{$ldq}\s*literal\s*{$rdq}(.*?){$ldq}\s*/literal\s*{$rdq}|{$ldq}\s*php\s*{$rdq}(.*?){$ldq}\s*/php\s*{$rdq}~s";
-
-        preg_match_all($search, $source_content, $match,  PREG_SET_ORDER);
-        $this->_folded_blocks = $match;
-        reset($this->_folded_blocks);
-
-        /* replace special blocks by "{php}" */
-        $source_content = preg_replace($search.'e', "'"
-                                       . $this->_quote_replace($this->left_delimiter) . 'php'
-                                       . "' . str_repeat(\"\n\", substr_count('\\0', \"\n\")) .'"
-                                       . $this->_quote_replace($this->right_delimiter)
-                                       . "'"
-                                       , $source_content);
-
-        /* Gather all template tags. */
-        preg_match_all("~{$ldq}\s*(.*?)\s*{$rdq}~s", $source_content, $_match);
-        $template_tags = $_match[1];
-        /* Split content by template tags to obtain non-template content. */
-        $text_blocks = preg_split("~{$ldq}.*?{$rdq}~s", $source_content);
-
-        /* loop through text blocks */
-        for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) {
-            /* match anything resembling php tags */
-            if (preg_match_all('~(<\?(?:\w+|=)?|\?>|language\s*=\s*[\"\']?\s*php\s*[\"\']?)~is', $text_blocks[$curr_tb], $sp_match)) {
-                /* replace tags with placeholders to prevent recursive replacements */
-                $sp_match[1] = array_unique($sp_match[1]);
-                usort($sp_match[1], '_smarty_sort_length');
-                for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {
-                    $text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],'%%%SMARTYSP'.$curr_sp.'%%%',$text_blocks[$curr_tb]);
-                }
-                /* process each one */
-                for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {
-                    if ($this->php_handling == SMARTY_PHP_PASSTHRU) {
-                        /* echo php contents */
-                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '<?php echo \''.str_replace("'", "\'", $sp_match[1][$curr_sp]).'\'; ?>'."\n", $text_blocks[$curr_tb]);
-                    } else if ($this->php_handling == SMARTY_PHP_QUOTE) {
-                        /* quote php tags */
-                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', htmlspecialchars($sp_match[1][$curr_sp]), $text_blocks[$curr_tb]);
-                    } else if ($this->php_handling == SMARTY_PHP_REMOVE) {
-                        /* remove php tags */
-                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '', $text_blocks[$curr_tb]);
-                    } else {
-                        /* SMARTY_PHP_ALLOW, but echo non php starting tags */
-                        $sp_match[1][$curr_sp] = preg_replace('~(<\?(?!php|=|$))~i', '<?php echo \'\\1\'?>'."\n", $sp_match[1][$curr_sp]);
-                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', $sp_match[1][$curr_sp], $text_blocks[$curr_tb]);
-                    }
-                }
-            }
-        }
-        
-        /* Compile the template tags into PHP code. */
-        $compiled_tags = array();
-        for ($i = 0, $for_max = count($template_tags); $i < $for_max; $i++) {
-            $this->_current_line_no += substr_count($text_blocks[$i], "\n");
-            $compiled_tags[] = $this->_compile_tag($template_tags[$i]);
-            $this->_current_line_no += substr_count($template_tags[$i], "\n");
-        }
-        if (count($this->_tag_stack)>0) {
-            list($_open_tag, $_line_no) = end($this->_tag_stack);
-            $this->_syntax_error("unclosed tag \{$_open_tag} (opened line $_line_no).", E_USER_ERROR, __FILE__, __LINE__);
-            return;
-        }
-
-        /* Reformat $text_blocks between 'strip' and '/strip' tags,
-           removing spaces, tabs and newlines. */
-        $strip = false;
-        for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {
-            if ($compiled_tags[$i] == '{strip}') {
-                $compiled_tags[$i] = '';
-                $strip = true;
-                /* remove leading whitespaces */
-                $text_blocks[$i + 1] = ltrim($text_blocks[$i + 1]);
-            }
-            if ($strip) {
-                /* strip all $text_blocks before the next '/strip' */
-                for ($j = $i + 1; $j < $for_max; $j++) {
-                    /* remove leading and trailing whitespaces of each line */
-                    $text_blocks[$j] = preg_replace('![\t ]*[\r\n]+[\t ]*!', '', $text_blocks[$j]);
-                    if ($compiled_tags[$j] == '{/strip}') {                       
-                        /* remove trailing whitespaces from the last text_block */
-                        $text_blocks[$j] = rtrim($text_blocks[$j]);
-                    }
-                    $text_blocks[$j] = "<?php echo '" . strtr($text_blocks[$j], array("'"=>"\'", "\\"=>"\\\\")) . "'; ?>";
-                    if ($compiled_tags[$j] == '{/strip}') {
-                        $compiled_tags[$j] = "\n"; /* slurped by php, but necessary
-                                    if a newline is following the closing strip-tag */
-                        $strip = false;
-                        $i = $j;
-                        break;
-                    }
-                }
-            }
-        }
-        $compiled_content = '';
-        
-        $tag_guard = '%%%SMARTYOTG' . md5(uniqid(rand(), true)) . '%%%';
-        
-        /* Interleave the compiled contents and text blocks to get the final result. */
-        for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {
-            if ($compiled_tags[$i] == '') {
-                // tag result empty, remove first newline from following text block
-                $text_blocks[$i+1] = preg_replace('~^(\r\n|\r|\n)~', '', $text_blocks[$i+1]);
-            }
-            // replace legit PHP tags with placeholder
-            $text_blocks[$i] = str_replace('<?', $tag_guard, $text_blocks[$i]);
-            $compiled_tags[$i] = str_replace('<?', $tag_guard, $compiled_tags[$i]);
-            
-            $compiled_content .= $text_blocks[$i] . $compiled_tags[$i];
-        }
-        $compiled_content .= str_replace('<?', $tag_guard, $text_blocks[$i]);
-
-        // escape php tags created by interleaving
-        $compiled_content = str_replace('<?', "<?php echo '<?' ?>\n", $compiled_content);
-        $compiled_content = preg_replace("~(?<!')language\s*=\s*[\"\']?\s*php\s*[\"\']?~", "<?php echo 'language=php' ?>\n", $compiled_content);
-
-        // recover legit tags
-        $compiled_content = str_replace($tag_guard, '<?', $compiled_content); 
-        
-        // remove \n from the end of the file, if any
-        if (strlen($compiled_content) && (substr($compiled_content, -1) == "\n") ) {
-            $compiled_content = substr($compiled_content, 0, -1);
-        }
-
-        if (!empty($this->_cache_serial)) {
-            $compiled_content = "<?php \$this->_cache_serials['".$this->_cache_include."'] = '".$this->_cache_serial."'; ?>" . $compiled_content;
-        }
-
-        // run compiled template through postfilter functions
-        if (count($this->_plugins['postfilter']) > 0) {
-            foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) {
-                if ($postfilter === false) continue;
-                if ($postfilter[3] || is_callable($postfilter[0])) {
-                    $compiled_content = call_user_func_array($postfilter[0],
-                                                              array($compiled_content, &$this));
-                    $this->_plugins['postfilter'][$filter_name][3] = true;
-                } else {
-                    $this->_trigger_fatal_error("Smarty plugin error: postfilter '$filter_name' is not implemented");
-                }
-            }
-        }
-
-        // put header at the top of the compiled template
-        $template_header = "<?php /* Smarty version ".$this->_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n";
-        $template_header .= "         compiled from ".strtr(urlencode($resource_name), array('%2F'=>'/', '%3A'=>':'))." */ ?>\n";
-
-        /* Emit code to load needed plugins. */
-        $this->_plugins_code = '';
-        if (count($this->_plugin_info)) {
-            $_plugins_params = "array('plugins' => array(";
-            foreach ($this->_plugin_info as $plugin_type => $plugins) {
-                foreach ($plugins as $plugin_name => $plugin_info) {
-                    $_plugins_params .= "array('$plugin_type', '$plugin_name', '" . strtr($plugin_info[0], array("'" => "\\'", "\\" => "\\\\")) . "', $plugin_info[1], ";
-                    $_plugins_params .= $plugin_info[2] ? 'true),' : 'false),';
-                }
-            }
-            $_plugins_params .= '))';
-            $plugins_code = "<?php require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');\nsmarty_core_load_plugins($_plugins_params, \$this); ?>\n";
-            $template_header .= $plugins_code;
-            $this->_plugin_info = array();
-            $this->_plugins_code = $plugins_code;
-        }
-
-        if ($this->_init_smarty_vars) {
-            $template_header .= "<?php require_once(SMARTY_CORE_DIR . 'core.assign_smarty_interface.php');\nsmarty_core_assign_smarty_interface(null, \$this); ?>\n";
-            $this->_init_smarty_vars = false;
-        }
-
-        $compiled_content = $template_header . $compiled_content;
-        return true;
-    }
-
-    /**
-     * Compile a template tag
-     *
-     * @param string $template_tag
-     * @return string
-     */
-    function _compile_tag($template_tag)
-    {
-        /* Matched comment. */
-        if (substr($template_tag, 0, 1) == '*' && substr($template_tag, -1) == '*')
-            return '';
-        
-        /* Split tag into two three parts: command, command modifiers and the arguments. */
-        if(! preg_match('~^(?:(' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp
-                . '|\/?' . $this->_reg_obj_regexp . '|\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*))
-                      (?:\s+(.*))?$
-                    ~xs', $template_tag, $match)) {
-            $this->_syntax_error("unrecognized tag: $template_tag", E_USER_ERROR, __FILE__, __LINE__);
-        }
-        
-        $tag_command = $match[1];
-        $tag_modifier = isset($match[2]) ? $match[2] : null;
-        $tag_args = isset($match[3]) ? $match[3] : null;
-
-        if (preg_match('~^' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$~', $tag_command)) {
-            /* tag name is a variable or object */
-            $_return = $this->_parse_var_props($tag_command . $tag_modifier);
-            return "<?php echo $_return; ?>" . $this->_additional_newline;
-        }
-
-        /* If the tag name is a registered object, we process it. */
-        if (preg_match('~^\/?' . $this->_reg_obj_regexp . '$~', $tag_command)) {
-            return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier);
-        }
-
-        switch ($tag_command) {
-            case 'include':
-                return $this->_compile_include_tag($tag_args);
-
-            case 'include_php':
-                return $this->_compile_include_php_tag($tag_args);
-
-            case 'if':
-                $this->_push_tag('if');
-                return $this->_compile_if_tag($tag_args);
-
-            case 'else':
-                list($_open_tag) = end($this->_tag_stack);
-                if ($_open_tag != 'if' && $_open_tag != 'elseif')
-                    $this->_syntax_error('unexpected {else}', E_USER_ERROR, __FILE__, __LINE__);
-                else
-                    $this->_push_tag('else');
-                return '<?php else: ?>';
-
-            case 'elseif':
-                list($_open_tag) = end($this->_tag_stack);
-                if ($_open_tag != 'if' && $_open_tag != 'elseif')
-                    $this->_syntax_error('unexpected {elseif}', E_USER_ERROR, __FILE__, __LINE__);
-                if ($_open_tag == 'if')
-                    $this->_push_tag('elseif');
-                return $this->_compile_if_tag($tag_args, true);
-
-            case '/if':
-                $this->_pop_tag('if');
-                return '<?php endif; ?>';
-
-            case 'capture':
-                return $this->_compile_capture_tag(true, $tag_args);
-
-            case '/capture':
-                return $this->_compile_capture_tag(false);
-
-            case 'ldelim':
-                return $this->left_delimiter;
-
-            case 'rdelim':
-                return $this->right_delimiter;
-
-            case 'section':
-                $this->_push_tag('section');
-                return $this->_compile_section_start($tag_args);
-
-            case 'sectionelse':
-                $this->_push_tag('sectionelse');
-                return "<?php endfor; else: ?>";
-                break;
-
-            case '/section':
-                $_open_tag = $this->_pop_tag('section');
-                if ($_open_tag == 'sectionelse')
-                    return "<?php endif; ?>";
-                else
-                    return "<?php endfor; endif; ?>";
-
-            case 'foreach':
-                $this->_push_tag('foreach');
-                return $this->_compile_foreach_start($tag_args);
-                break;
-
-            case 'foreachelse':
-                $this->_push_tag('foreachelse');
-                return "<?php endforeach; else: ?>";
-
-            case '/foreach':
-                $_open_tag = $this->_pop_tag('foreach');
-                if ($_open_tag == 'foreachelse')
-                    return "<?php endif; unset(\$_from); ?>";
-                else
-                    return "<?php endforeach; endif; unset(\$_from); ?>";
-                break;
-
-            case 'strip':
-            case '/strip':
-                if (substr($tag_command, 0, 1)=='/') {
-                    $this->_pop_tag('strip');
-                    if (--$this->_strip_depth==0) { /* outermost closing {/strip} */
-                        $this->_additional_newline = "\n";
-                        return '{' . $tag_command . '}';
-                    }
-                } else {
-                    $this->_push_tag('strip');
-                    if ($this->_strip_depth++==0) { /* outermost opening {strip} */
-                        $this->_additional_newline = "";
-                        return '{' . $tag_command . '}';
-                    }
-                }
-                return '';
-
-            case 'php':
-                /* handle folded tags replaced by {php} */
-                list(, $block) = each($this->_folded_blocks);
-                $this->_current_line_no += substr_count($block[0], "\n");
-                /* the number of matched elements in the regexp in _compile_file()
-                   determins the type of folded tag that was found */
-                switch (count($block)) {
-                    case 2: /* comment */
-                        return '';
-
-                    case 3: /* literal */
-                        return "<?php echo '" . strtr($block[2], array("'"=>"\'", "\\"=>"\\\\")) . "'; ?>" . $this->_additional_newline;
-
-                    case 4: /* php */
-                        if ($this->security && !$this->security_settings['PHP_TAGS']) {
-                            $this->_syntax_error("(secure mode) php tags not permitted", E_USER_WARNING, __FILE__, __LINE__);
-                            return;
-                        }
-                        return '<?php ' . $block[3] .' ?>';
-                }
-                break;
-
-            case 'insert':
-                return $this->_compile_insert_tag($tag_args);
-
-            default:
-                if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) {
-                    return $output;
-                } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) {
-                    return $output;
-                } else if ($this->_compile_custom_tag($tag_command, $tag_args, $tag_modifier, $output)) {
-                    return $output;                    
-                } else {
-                    $this->_syntax_error("unrecognized tag '$tag_command'", E_USER_ERROR, __FILE__, __LINE__);
-                }
-
-        }
-    }
-
-
-    /**
-     * compile the custom compiler tag
-     *
-     * sets $output to the compiled custom compiler tag
-     * @param string $tag_command
-     * @param string $tag_args
-     * @param string $output
-     * @return boolean
-     */
-    function _compile_compiler_tag($tag_command, $tag_args, &$output)
-    {
-        $found = false;
-        $have_function = true;
-
-        /*
-         * First we check if the compiler function has already been registered
-         * or loaded from a plugin file.
-         */
-        if (isset($this->_plugins['compiler'][$tag_command])) {
-            $found = true;
-            $plugin_func = $this->_plugins['compiler'][$tag_command][0];
-            if (!is_callable($plugin_func)) {
-                $message = "compiler function '$tag_command' is not implemented";
-                $have_function = false;
-            }
-        }
-        /*
-         * Otherwise we need to load plugin file and look for the function
-         * inside it.
-         */
-        else if ($plugin_file = $this->_get_plugin_filepath('compiler', $tag_command)) {
-            $found = true;
-
-            include_once $plugin_file;
-
-            $plugin_func = 'smarty_compiler_' . $tag_command;
-            if (!is_callable($plugin_func)) {
-                $message = "plugin function $plugin_func() not found in $plugin_file\n";
-                $have_function = false;
-            } else {
-                $this->_plugins['compiler'][$tag_command] = array($plugin_func, null, null, null, true);
-            }
-        }
-
-        /*
-         * True return value means that we either found a plugin or a
-         * dynamically registered function. False means that we didn't and the
-         * compiler should now emit code to load custom function plugin for this
-         * tag.
-         */
-        if ($found) {
-            if ($have_function) {
-                $output = call_user_func_array($plugin_func, array($tag_args, &$this));
-                if($output != '') {
-                $output = '<?php ' . $this->_push_cacheable_state('compiler', $tag_command)
-                                   . $output
-                                   . $this->_pop_cacheable_state('compiler', $tag_command) . ' ?>';
-                }
-            } else {
-                $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
-            }
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-
-    /**
-     * compile block function tag
-     *
-     * sets $output to compiled block function tag
-     * @param string $tag_command
-     * @param string $tag_args
-     * @param string $tag_modifier
-     * @param string $output
-     * @return boolean
-     */
-    function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$output)
-    {
-        if (substr($tag_command, 0, 1) == '/') {
-            $start_tag = false;
-            $tag_command = substr($tag_command, 1);
-        } else
-            $start_tag = true;
-
-        $found = false;
-        $have_function = true;
-
-        /*
-         * First we check if the block function has already been registered
-         * or loaded from a plugin file.
-         */
-        if (isset($this->_plugins['block'][$tag_command])) {
-            $found = true;
-            $plugin_func = $this->_plugins['block'][$tag_command][0];
-            if (!is_callable($plugin_func)) {
-                $message = "block function '$tag_command' is not implemented";
-                $have_function = false;
-            }
-        }
-        /*
-         * Otherwise we need to load plugin file and look for the function
-         * inside it.
-         */
-        else if ($plugin_file = $this->_get_plugin_filepath('block', $tag_command)) {
-            $found = true;
-
-            include_once $plugin_file;
-
-            $plugin_func = 'smarty_block_' . $tag_command;
-            if (!function_exists($plugin_func)) {
-                $message = "plugin function $plugin_func() not found in $plugin_file\n";
-                $have_function = false;
-            } else {
-                $this->_plugins['block'][$tag_command] = array($plugin_func, null, null, null, true);
-
-            }
-        }
-
-        if (!$found) {
-            return false;
-        } else if (!$have_function) {
-            $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
-            return true;
-        }
-
-        /*
-         * Even though we've located the plugin function, compilation
-         * happens only once, so the plugin will still need to be loaded
-         * at runtime for future requests.
-         */
-        $this->_add_plugin('block', $tag_command);
-
-        if ($start_tag)
-            $this->_push_tag($tag_command);
-        else
-            $this->_pop_tag($tag_command);
-
-        if ($start_tag) {
-            $output = '<?php ' . $this->_push_cacheable_state('block', $tag_command);
-            $attrs = $this->_parse_attrs($tag_args);
-            $_cache_attrs='';
-            $arg_list = $this->_compile_arg_list('block', $tag_command, $attrs, $_cache_attrs);
-            $output .= "$_cache_attrs\$this->_tag_stack[] = array('$tag_command', array(".implode(',', $arg_list).')); ';
-            $output .= '$_block_repeat=true;' . $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], null, $this, $_block_repeat);';
-            $output .= 'while ($_block_repeat) { ob_start(); ?>';
-        } else {
-            $output = '<?php $_block_content = ob_get_contents(); ob_end_clean(); ';
-            $_out_tag_text = $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], $_block_content, $this, $_block_repeat)';
-            if ($tag_modifier != '') {
-                $this->_parse_modifiers($_out_tag_text, $tag_modifier);
-            }
-            $output .= '$_block_repeat=false;echo ' . $_out_tag_text . '; } ';
-            $output .= " array_pop(\$this->_tag_stack); " . $this->_pop_cacheable_state('block', $tag_command) . '?>';
-        }
-
-        return true;
-    }
-
-
-    /**
-     * compile custom function tag
-     *
-     * @param string $tag_command
-     * @param string $tag_args
-     * @param string $tag_modifier
-     * @return string
-     */
-    function _compile_custom_tag($tag_command, $tag_args, $tag_modifier, &$output)
-    {
-        $found = false;
-        $have_function = true;
-
-        /*
-         * First we check if the custom function has already been registered
-         * or loaded from a plugin file.
-         */
-        if (isset($this->_plugins['function'][$tag_command])) {
-            $found = true;
-            $plugin_func = $this->_plugins['function'][$tag_command][0];
-            if (!is_callable($plugin_func)) {
-                $message = "custom function '$tag_command' is not implemented";
-                $have_function = false;
-            }
-        }
-        /*
-         * Otherwise we need to load plugin file and look for the function
-         * inside it.
-         */
-        else if ($plugin_file = $this->_get_plugin_filepath('function', $tag_command)) {
-            $found = true;
-
-            include_once $plugin_file;
-
-            $plugin_func = 'smarty_function_' . $tag_command;
-            if (!function_exists($plugin_func)) {
-                $message = "plugin function $plugin_func() not found in $plugin_file\n";
-                $have_function = false;
-            } else {
-                $this->_plugins['function'][$tag_command] = array($plugin_func, null, null, null, true);
-
-            }
-        }
-
-        if (!$found) {
-            return false;
-        } else if (!$have_function) {
-            $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
-            return true;
-        }
-
-        /* declare plugin to be loaded on display of the template that
-           we compile right now */
-        $this->_add_plugin('function', $tag_command);
-
-        $_cacheable_state = $this->_push_cacheable_state('function', $tag_command);
-        $attrs = $this->_parse_attrs($tag_args);
-        $_cache_attrs = '';
-        $arg_list = $this->_compile_arg_list('function', $tag_command, $attrs, $_cache_attrs);
-
-        $output = $this->_compile_plugin_call('function', $tag_command).'(array('.implode(',', $arg_list)."), \$this)";
-        if($tag_modifier != '') {
-            $this->_parse_modifiers($output, $tag_modifier);
-        }
-
-        if($output != '') {
-            $output =  '<?php ' . $_cacheable_state . $_cache_attrs . 'echo ' . $output . ';'
-                . $this->_pop_cacheable_state('function', $tag_command) . "?>" . $this->_additional_newline;
-        }
-
-        return true;
-    }
-
-    /**
-     * compile a registered object tag
-     *
-     * @param string $tag_command
-     * @param array $attrs
-     * @param string $tag_modifier
-     * @return string
-     */
-    function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier)
-    {
-        if (substr($tag_command, 0, 1) == '/') {
-            $start_tag = false;
-            $tag_command = substr($tag_command, 1);
-        } else {
-            $start_tag = true;
-        }
-
-        list($object, $obj_comp) = explode('->', $tag_command);
-
-        $arg_list = array();
-        if(count($attrs)) {
-            $_assign_var = false;
-            foreach ($attrs as $arg_name => $arg_value) {
-                if($arg_name == 'assign') {
-                    $_assign_var = $arg_value;
-                    unset($attrs['assign']);
-                    continue;
-                }
-                if (is_bool($arg_value))
-                    $arg_value = $arg_value ? 'true' : 'false';
-                $arg_list[] = "'$arg_name' => $arg_value";
-            }
-        }
-
-        if($this->_reg_objects[$object][2]) {
-            // smarty object argument format
-            $args = "array(".implode(',', (array)$arg_list)."), \$this";
-        } else {
-            // traditional argument format
-            $args = implode(',', array_values($attrs));
-            if (empty($args)) {
-                $args = 'null';
-            }
-        }
-
-        $prefix = '';
-        $postfix = '';
-        $newline = '';
-        if(!is_object($this->_reg_objects[$object][0])) {
-            $this->_trigger_fatal_error("registered '$object' is not an object" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
-        } elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) {
-            $this->_trigger_fatal_error("'$obj_comp' is not a registered component of object '$object'", $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
-        } elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) {
-            // method
-            if(in_array($obj_comp, $this->_reg_objects[$object][3])) {
-                // block method
-                if ($start_tag) {
-                    $prefix = "\$this->_tag_stack[] = array('$obj_comp', $args); ";
-                    $prefix .= "\$_block_repeat=true; \$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], null, \$this, \$_block_repeat); ";
-                    $prefix .= "while (\$_block_repeat) { ob_start();";
-                    $return = null;
-                    $postfix = '';
-                } else {
-                    $prefix = "\$_obj_block_content = ob_get_contents(); ob_end_clean(); \$_block_repeat=false;";
-                    $return = "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], \$_obj_block_content, \$this, \$_block_repeat)";
-                    $postfix = "} array_pop(\$this->_tag_stack);";
-                }
-            } else {
-                // non-block method
-                $return = "\$this->_reg_objects['$object'][0]->$obj_comp($args)";
-            }
-        } else {
-            // property
-            $return = "\$this->_reg_objects['$object'][0]->$obj_comp";
-        }
-
-        if($return != null) {
-            if($tag_modifier != '') {
-                $this->_parse_modifiers($return, $tag_modifier);
-            }
-
-            if(!empty($_assign_var)) {
-                $output = "\$this->assign('" . $this->_dequote($_assign_var) ."',  $return);";
-            } else {
-                $output = 'echo ' . $return . ';';
-                $newline = $this->_additional_newline;
-            }
-        } else {
-            $output = '';
-        }
-
-        return '<?php ' . $prefix . $output . $postfix . "?>" . $newline;
-    }
-
-    /**
-     * Compile {insert ...} tag
-     *
-     * @param string $tag_args
-     * @return string
-     */
-    function _compile_insert_tag($tag_args)
-    {
-        $attrs = $this->_parse_attrs($tag_args);
-        $name = $this->_dequote($attrs['name']);
-
-        if (empty($name)) {
-            return $this->_syntax_error("missing insert name", E_USER_ERROR, __FILE__, __LINE__);
-        }
-        
-        if (!preg_match('~^\w+$~', $name)) {
-            return $this->_syntax_error("'insert: 'name' must be an insert function name", E_USER_ERROR, __FILE__, __LINE__);
-        }
-
-        if (!empty($attrs['script'])) {
-            $delayed_loading = true;
-        } else {
-            $delayed_loading = false;
-        }
-
-        foreach ($attrs as $arg_name => $arg_value) {
-            if (is_bool($arg_value))
-                $arg_value = $arg_value ? 'true' : 'false';
-            $arg_list[] = "'$arg_name' => $arg_value";
-        }
-
-        $this->_add_plugin('insert', $name, $delayed_loading);
-
-        $_params = "array('args' => array(".implode(', ', (array)$arg_list)."))";
-
-        return "<?php require_once(SMARTY_CORE_DIR . 'core.run_insert_handler.php');\necho smarty_core_run_insert_handler($_params, \$this); ?>" . $this->_additional_newline;
-    }
-
-    /**
-     * Compile {include ...} tag
-     *
-     * @param string $tag_args
-     * @return string
-     */
-    function _compile_include_tag($tag_args)
-    {
-        $attrs = $this->_parse_attrs($tag_args);
-        $arg_list = array();
-
-        if (empty($attrs['file'])) {
-            $this->_syntax_error("missing 'file' attribute in include tag", E_USER_ERROR, __FILE__, __LINE__);
-        }
-
-        foreach ($attrs as $arg_name => $arg_value) {
-            if ($arg_name == 'file') {
-                $include_file = $arg_value;
-                continue;
-            } else if ($arg_name == 'assign') {
-                $assign_var = $arg_value;
-                continue;
-            }
-            if (is_bool($arg_value))
-                $arg_value = $arg_value ? 'true' : 'false';
-            $arg_list[] = "'$arg_name' => $arg_value";
-        }
-
-        $output = '<?php ';
-
-        if (isset($assign_var)) {
-            $output .= "ob_start();\n";
-        }
-
-        $output .=
-            "\$_smarty_tpl_vars = \$this->_tpl_vars;\n";
-
-
-        $_params = "array('smarty_include_tpl_file' => " . $include_file . ", 'smarty_include_vars' => array(".implode(',', (array)$arg_list)."))";
-        $output .= "\$this->_smarty_include($_params);\n" .
-        "\$this->_tpl_vars = \$_smarty_tpl_vars;\n" .
-        "unset(\$_smarty_tpl_vars);\n";
-
-        if (isset($assign_var)) {
-            $output .= "\$this->assign(" . $assign_var . ", ob_get_contents()); ob_end_clean();\n";
-        }
-
-        $output .= ' ?>';
-
-        return $output;
-
-    }
-
-    /**
-     * Compile {include ...} tag
-     *
-     * @param string $tag_args
-     * @return string
-     */
-    function _compile_include_php_tag($tag_args)
-    {
-        $attrs = $this->_parse_attrs($tag_args);
-
-        if (empty($attrs['file'])) {
-            $this->_syntax_error("missing 'file' attribute in include_php tag", E_USER_ERROR, __FILE__, __LINE__);
-        }
-
-        $assign_var = (empty($attrs['assign'])) ? '' : $this->_dequote($attrs['assign']);
-        $once_var = (empty($attrs['once']) || $attrs['once']=='false') ? 'false' : 'true';
-
-        $arg_list = array();
-        foreach($attrs as $arg_name => $arg_value) {
-            if($arg_name != 'file' AND $arg_name != 'once' AND $arg_name != 'assign') {
-                if(is_bool($arg_value))
-                    $arg_value = $arg_value ? 'true' : 'false';
-                $arg_list[] = "'$arg_name' => $arg_value";
-            }
-        }
-
-        $_params = "array('smarty_file' => " . $attrs['file'] . ", 'smarty_assign' => '$assign_var', 'smarty_once' => $once_var, 'smarty_include_vars' => array(".implode(',', $arg_list)."))";
-
-        return "<?php require_once(SMARTY_CORE_DIR . 'core.smarty_include_php.php');\nsmarty_core_smarty_include_php($_params, \$this); ?>" . $this->_additional_newline;
-    }
-
-
-    /**
-     * Compile {section ...} tag
-     *
-     * @param string $tag_args
-     * @return string
-     */
-    function _compile_section_start($tag_args)
-    {
-        $attrs = $this->_parse_attrs($tag_args);
-        $arg_list = array();
-
-        $output = '<?php ';
-        $section_name = $attrs['name'];
-        if (empty($section_name)) {
-            $this->_syntax_error("missing section name", E_USER_ERROR, __FILE__, __LINE__);
-        }
-
-        $output .= "unset(\$this->_sections[$section_name]);\n";
-        $section_props = "\$this->_sections[$section_name]";
-
-        foreach ($attrs as $attr_name => $attr_value) {
-            switch ($attr_name) {
-                case 'loop':
-                    $output .= "{$section_props}['loop'] = is_array(\$_loop=$attr_value) ? count(\$_loop) : max(0, (int)\$_loop); unset(\$_loop);\n";
-                    break;
-
-                case 'show':
-                    if (is_bool($attr_value))
-                        $show_attr_value = $attr_value ? 'true' : 'false';
-                    else
-                        $show_attr_value = "(bool)$attr_value";
-                    $output .= "{$section_props}['show'] = $show_attr_value;\n";
-                    break;
-
-                case 'name':
-                    $output .= "{$section_props}['$attr_name'] = $attr_value;\n";
-                    break;
-
-                case 'max':
-                case 'start':
-                    $output .= "{$section_props}['$attr_name'] = (int)$attr_value;\n";
-                    break;
-
-                case 'step':
-                    $output .= "{$section_props}['$attr_name'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\n";
-                    break;
-
-                default:
-                    $this->_syntax_error("unknown section attribute - '$attr_name'", E_USER_ERROR, __FILE__, __LINE__);
-                    break;
-            }
-        }
-
-        if (!isset($attrs['show']))
-            $output .= "{$section_props}['show'] = true;\n";
-
-        if (!isset($attrs['loop']))
-            $output .= "{$section_props}['loop'] = 1;\n";
-
-        if (!isset($attrs['max']))
-            $output .= "{$section_props}['max'] = {$section_props}['loop'];\n";
-        else
-            $output .= "if ({$section_props}['max'] < 0)\n" .
-                       "    {$section_props}['max'] = {$section_props}['loop'];\n";
-
-        if (!isset($attrs['step']))
-            $output .= "{$section_props}['step'] = 1;\n";
-
-        if (!isset($attrs['start']))
-            $output .= "{$section_props}['start'] = {$section_props}['step'] > 0 ? 0 : {$section_props}['loop']-1;\n";
-        else {
-            $output .= "if ({$section_props}['start'] < 0)\n" .
-                       "    {$section_props}['start'] = max({$section_props}['step'] > 0 ? 0 : -1, {$section_props}['loop'] + {$section_props}['start']);\n" .
-                       "else\n" .
-                       "    {$section_props}['start'] = min({$section_props}['start'], {$section_props}['step'] > 0 ? {$section_props}['loop'] : {$section_props}['loop']-1);\n";
-        }
-
-        $output .= "if ({$section_props}['show']) {\n";
-        if (!isset($attrs['start']) && !isset($attrs['step']) && !isset($attrs['max'])) {
-            $output .= "    {$section_props}['total'] = {$section_props}['loop'];\n";
-        } else {
-            $output .= "    {$section_props}['total'] = min(ceil(({$section_props}['step'] > 0 ? {$section_props}['loop'] - {$section_props}['start'] : {$section_props}['start']+1)/abs({$section_props}['step'])), {$section_props}['max']);\n";
-        }
-        $output .= "    if ({$section_props}['total'] == 0)\n" .
-                   "        {$section_props}['show'] = false;\n" .
-                   "} else\n" .
-                   "    {$section_props}['total'] = 0;\n";
-
-        $output .= "if ({$section_props}['show']):\n";
-        $output .= "
-            for ({$section_props}['index'] = {$section_props}['start'], {$section_props}['iteration'] = 1;
-                 {$section_props}['iteration'] <= {$section_props}['total'];
-                 {$section_props}['index'] += {$section_props}['step'], {$section_props}['iteration']++):\n";
-        $output .= "{$section_props}['rownum'] = {$section_props}['iteration'];\n";
-        $output .= "{$section_props}['index_prev'] = {$section_props}['index'] - {$section_props}['step'];\n";
-        $output .= "{$section_props}['index_next'] = {$section_props}['index'] + {$section_props}['step'];\n";
-        $output .= "{$section_props}['first']      = ({$section_props}['iteration'] == 1);\n";
-        $output .= "{$section_props}['last']       = ({$section_props}['iteration'] == {$section_props}['total']);\n";
-
-        $output .= "?>";
-
-        return $output;
-    }
-
-
-    /**
-     * Compile {foreach ...} tag.
-     *
-     * @param string $tag_args
-     * @return string
-     */
-    function _compile_foreach_start($tag_args)
-    {
-        $attrs = $this->_parse_attrs($tag_args);
-        $arg_list = array();
-
-        if (empty($attrs['from'])) {
-            return $this->_syntax_error("foreach: missing 'from' attribute", E_USER_ERROR, __FILE__, __LINE__);
-        }
-        $from = $attrs['from'];
-
-        if (empty($attrs['item'])) {
-            return $this->_syntax_error("foreach: missing 'item' attribute", E_USER_ERROR, __FILE__, __LINE__);
-        }
-        $item = $this->_dequote($attrs['item']);
-        if (!preg_match('~^\w+$~', $item)) {
-            return $this->_syntax_error("'foreach: 'item' must be a variable name (literal string)", E_USER_ERROR, __FILE__, __LINE__);
-        }
-
-        if (isset($attrs['key'])) {
-            $key  = $this->_dequote($attrs['key']);
-            if (!preg_match('~^\w+$~', $key)) {
-                return $this->_syntax_error("foreach: 'key' must to be a variable name (literal string)", E_USER_ERROR, __FILE__, __LINE__);
-            }
-            $key_part = "\$this->_tpl_vars['$key'] => ";
-        } else {
-            $key = null;
-            $key_part = '';
-        }
-
-        if (isset($attrs['name'])) {
-            $name = $attrs['name'];
-        } else {
-            $name = null;
-        }
-
-        $output = '<?php ';
-        $output .= "\$_from = $from; if (!is_array(\$_from) && !is_object(\$_from)) { settype(\$_from, 'array'); }";
-        if (isset($name)) {
-            $foreach_props = "\$this->_foreach[$name]";
-            $output .= "{$foreach_props} = array('total' => count(\$_from), 'iteration' => 0);\n";
-            $output .= "if ({$foreach_props}['total'] > 0):\n";
-            $output .= "    foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
-            $output .= "        {$foreach_props}['iteration']++;\n";
-        } else {
-            $output .= "if (count(\$_from)):\n";
-            $output .= "    foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
-        }
-        $output .= '?>';
-
-        return $output;
-    }
-
-
-    /**
-     * Compile {capture} .. {/capture} tags
-     *
-     * @param boolean $start true if this is the {capture} tag
-     * @param string $tag_args
-     * @return string
-     */
-
-    function _compile_capture_tag($start, $tag_args = '')
-    {
-        $attrs = $this->_parse_attrs($tag_args);
-
-        if ($start) {
-            if (isset($attrs['name']))
-                $buffer = $attrs['name'];
-            else
-                $buffer = "'default'";
-
-            if (isset($attrs['assign']))
-                $assign = $attrs['assign'];
-            else
-                $assign = null;
-            $output = "<?php ob_start(); ?>";
-            $this->_capture_stack[] = array($buffer, $assign);
-        } else {
-            list($buffer, $assign) = array_pop($this->_capture_stack);
-            $output = "<?php \$this->_smarty_vars['capture'][$buffer] = ob_get_contents(); ";
-            if (isset($assign)) {
-                $output .= " \$this->assign($assign, ob_get_contents());";
-            }
-            $output .= "ob_end_clean(); ?>";
-        }
-
-        return $output;
-    }
-
-    /**
-     * Compile {if ...} tag
-     *
-     * @param string $tag_args
-     * @param boolean $elseif if true, uses elseif instead of if
-     * @return string
-     */
-    function _compile_if_tag($tag_args, $elseif = false)
-    {
-
-        /* Tokenize args for 'if' tag. */
-        preg_match_all('~(?>
-                ' . $this->_obj_call_regexp . '(?:' . $this->_mod_regexp . '*)? | # valid object call
-                ' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)?    | # var or quoted string
-                \-?0[xX][0-9a-fA-F]+|\-?\d+(?:\.\d+)?|\.\d+|!==|===|==|!=|<>|<<|>>|<=|>=|\&\&|\|\||\(|\)|,|\!|\^|=|\&|\~|<|>|\||\%|\+|\-|\/|\*|\@    | # valid non-word token
-                \b\w+\b                                                        | # valid word token
-                \S+                                                           # anything else
-                )~x', $tag_args, $match);
-
-        $tokens = $match[0];
-
-        if(empty($tokens)) {
-            $_error_msg = $elseif ? "'elseif'" : "'if'";
-            $_error_msg .= ' statement requires arguments'; 
-            $this->_syntax_error($_error_msg, E_USER_ERROR, __FILE__, __LINE__);
-        }
-            
-                
-        // make sure we have balanced parenthesis
-        $token_count = array_count_values($tokens);
-        if(isset($token_count['(']) && $token_count['('] != $token_count[')']) {
-            $this->_syntax_error("unbalanced parenthesis in if statement", E_USER_ERROR, __FILE__, __LINE__);
-        }
-
-        $is_arg_stack = array();
-
-        for ($i = 0; $i < count($tokens); $i++) {
-
-            $token = &$tokens[$i];
-
-            switch (strtolower($token)) {
-                case '!':
-                case '%':
-                case '!==':
-                case '==':
-                case '===':
-                case '>':
-                case '<':
-                case '!=':
-                case '<>':
-                case '<<':
-                case '>>':
-                case '<=':
-                case '>=':
-                case '&&':
-                case '||':
-                case '|':
-                case '^':
-                case '&':
-                case '~':
-                case ')':
-                case ',':
-                case '+':
-                case '-':
-                case '*':
-                case '/':
-                case '@':
-                    break;
-
-                case 'eq':
-                    $token = '==';
-                    break;
-
-                case 'ne':
-                case 'neq':
-                    $token = '!=';
-                    break;
-
-                case 'lt':
-                    $token = '<';
-                    break;
-
-                case 'le':
-                case 'lte':
-                    $token = '<=';
-                    break;
-
-                case 'gt':
-                    $token = '>';
-                    break;
-
-                case 'ge':
-                case 'gte':
-                    $token = '>=';
-                    break;
-
-                case 'and':
-                    $token = '&&';
-                    break;
-
-                case 'or':
-                    $token = '||';
-                    break;
-
-                case 'not':
-                    $token = '!';
-                    break;
-
-                case 'mod':
-                    $token = '%';
-                    break;
-
-                case '(':
-                    array_push($is_arg_stack, $i);
-                    break;
-
-                case 'is':
-                    /* If last token was a ')', we operate on the parenthesized
-                       expression. The start of the expression is on the stack.
-                       Otherwise, we operate on the last encountered token. */
-                    if ($tokens[$i-1] == ')')
-                        $is_arg_start = array_pop($is_arg_stack);
-                    else
-                        $is_arg_start = $i-1;
-                    /* Construct the argument for 'is' expression, so it knows
-                       what to operate on. */
-                    $is_arg = implode(' ', array_slice($tokens, $is_arg_start, $i - $is_arg_start));
-
-                    /* Pass all tokens from next one until the end to the
-                       'is' expression parsing function. The function will
-                       return modified tokens, where the first one is the result
-                       of the 'is' expression and the rest are the tokens it
-                       didn't touch. */
-                    $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1));
-
-                    /* Replace the old tokens with the new ones. */
-                    array_splice($tokens, $is_arg_start, count($tokens), $new_tokens);
-
-                    /* Adjust argument start so that it won't change from the
-                       current position for the next iteration. */
-                    $i = $is_arg_start;
-                    break;
-
-                default:
-                    if(preg_match('~^' . $this->_func_regexp . '$~', $token) ) {
-                            // function call
-                            if($this->security &&
-                               !in_array($token, $this->security_settings['IF_FUNCS'])) {
-                                $this->_syntax_error("(secure mode) '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__);
-                            }
-                    } elseif(preg_match('~^' . $this->_var_regexp . '$~', $token) && (strpos('+-*/^%&|', substr($token, -1)) === false) && isset($tokens[$i+1]) && $tokens[$i+1] == '(') {
-                        // variable function call
-                        $this->_syntax_error("variable function call '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__);                      
-                    } elseif(preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)$~', $token)) {
-                        // object or variable
-                        $token = $this->_parse_var_props($token);
-                    } elseif(is_numeric($token)) {
-                        // number, skip it
-                    } else {
-                        $this->_syntax_error("unidentified token '$token'", E_USER_ERROR, __FILE__, __LINE__);
-                    }
-                    break;
-            }
-        }
-
-        if ($elseif)
-            return '<?php elseif ('.implode(' ', $tokens).'): ?>';
-        else
-            return '<?php if ('.implode(' ', $tokens).'): ?>';
-    }
-
-
-    function _compile_arg_list($type, $name, $attrs, &$cache_code) {
-        $arg_list = array();
-
-        if (isset($type) && isset($name)
-            && isset($this->_plugins[$type])
-            && isset($this->_plugins[$type][$name])
-            && empty($this->_plugins[$type][$name][4])
-            && is_array($this->_plugins[$type][$name][5])
-            ) {
-            /* we have a list of parameters that should be cached */
-            $_cache_attrs = $this->_plugins[$type][$name][5];
-            $_count = $this->_cache_attrs_count++;
-            $cache_code = "\$_cache_attrs =& \$this->_smarty_cache_attrs('$this->_cache_serial','$_count');";
-
-        } else {
-            /* no parameters are cached */
-            $_cache_attrs = null;
-        }
-
-        foreach ($attrs as $arg_name => $arg_value) {
-            if (is_bool($arg_value))
-                $arg_value = $arg_value ? 'true' : 'false';
-            if (is_null($arg_value))
-                $arg_value = 'null';
-            if ($_cache_attrs && in_array($arg_name, $_cache_attrs)) {
-                $arg_list[] = "'$arg_name' => (\$this->_cache_including) ? \$_cache_attrs['$arg_name'] : (\$_cache_attrs['$arg_name']=$arg_value)";
-            } else {
-                $arg_list[] = "'$arg_name' => $arg_value";
-            }
-        }
-        return $arg_list;
-    }
-
-    /**
-     * Parse is expression
-     *
-     * @param string $is_arg
-     * @param array $tokens
-     * @return array
-     */
-    function _parse_is_expr($is_arg, $tokens)
-    {
-        $expr_end = 0;
-        $negate_expr = false;
-
-        if (($first_token = array_shift($tokens)) == 'not') {
-            $negate_expr = true;
-            $expr_type = array_shift($tokens);
-        } else
-            $expr_type = $first_token;
-
-        switch ($expr_type) {
-            case 'even':
-                if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') {
-                    $expr_end++;
-                    $expr_arg = $tokens[$expr_end++];
-                    $expr = "!(1 & ($is_arg / " . $this->_parse_var_props($expr_arg) . "))";
-                } else
-                    $expr = "!(1 & $is_arg)";
-                break;
-
-            case 'odd':
-                if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') {
-                    $expr_end++;
-                    $expr_arg = $tokens[$expr_end++];
-                    $expr = "(1 & ($is_arg / " . $this->_parse_var_props($expr_arg) . "))";
-                } else
-                    $expr = "(1 & $is_arg)";
-                break;
-
-            case 'div':
-                if (@$tokens[$expr_end] == 'by') {
-                    $expr_end++;
-                    $expr_arg = $tokens[$expr_end++];
-                    $expr = "!($is_arg % " . $this->_parse_var_props($expr_arg) . ")";
-                } else {
-                    $this->_syntax_error("expecting 'by' after 'div'", E_USER_ERROR, __FILE__, __LINE__);
-                }
-                break;
-
-            default:
-                $this->_syntax_error("unknown 'is' expression - '$expr_type'", E_USER_ERROR, __FILE__, __LINE__);
-                break;
-        }
-
-        if ($negate_expr) {
-            $expr = "!($expr)";
-        }
-
-        array_splice($tokens, 0, $expr_end, $expr);
-
-        return $tokens;
-    }
-
-
-    /**
-     * Parse attribute string
-     *
-     * @param string $tag_args
-     * @return array
-     */
-    function _parse_attrs($tag_args)
-    {
-
-        /* Tokenize tag attributes. */
-        preg_match_all('~(?:' . $this->_obj_call_regexp . '|' . $this->_qstr_regexp . ' | (?>[^"\'=\s]+)
-                         )+ |
-                         [=]
-                        ~x', $tag_args, $match);
-        $tokens       = $match[0];
-
-        $attrs = array();
-        /* Parse state:
-            0 - expecting attribute name
-            1 - expecting '='
-            2 - expecting attribute value (not '=') */
-        $state = 0;
-
-        foreach ($tokens as $token) {
-            switch ($state) {
-                case 0:
-                    /* If the token is a valid identifier, we set attribute name
-                       and go to state 1. */
-                    if (preg_match('~^\w+$~', $token)) {
-                        $attr_name = $token;
-                        $state = 1;
-                    } else
-                        $this->_syntax_error("invalid attribute name: '$token'", E_USER_ERROR, __FILE__, __LINE__);
-                    break;
-
-                case 1:
-                    /* If the token is '=', then we go to state 2. */
-                    if ($token == '=') {
-                        $state = 2;
-                    } else
-                        $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__);
-                    break;
-
-                case 2:
-                    /* If token is not '=', we set the attribute value and go to
-                       state 0. */
-                    if ($token != '=') {
-                        /* We booleanize the token if it's a non-quoted possible
-                           boolean value. */
-                        if (preg_match('~^(on|yes|true)$~', $token)) {
-                            $token = 'true';
-                        } else if (preg_match('~^(off|no|false)$~', $token)) {
-                            $token = 'false';
-                        } else if ($token == 'null') {
-                            $token = 'null';
-                        } else if (preg_match('~^' . $this->_num_const_regexp . '|0[xX][0-9a-fA-F]+$~', $token)) {
-                            /* treat integer literally */
-                        } else if (!preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . ')*$~', $token)) {
-                            /* treat as a string, double-quote it escaping quotes */
-                            $token = '"'.addslashes($token).'"';
-                        }
-
-                        $attrs[$attr_name] = $token;
-                        $state = 0;
-                    } else
-                        $this->_syntax_error("'=' cannot be an attribute value", E_USER_ERROR, __FILE__, __LINE__);
-                    break;
-            }
-            $last_token = $token;
-        }
-
-        if($state != 0) {
-            if($state == 1) {
-                $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__);
-            } else {
-                $this->_syntax_error("missing attribute value", E_USER_ERROR, __FILE__, __LINE__);
-            }
-        }
-
-        $this->_parse_vars_props($attrs);
-
-        return $attrs;
-    }
-
-    /**
-     * compile multiple variables and section properties tokens into
-     * PHP code
-     *
-     * @param array $tokens
-     */
-    function _parse_vars_props(&$tokens)
-    {
-        foreach($tokens as $key => $val) {
-            $tokens[$key] = $this->_parse_var_props($val);
-        }
-    }
-
-    /**
-     * compile single variable and section properties token into
-     * PHP code
-     *
-     * @param string $val
-     * @param string $tag_attrs
-     * @return string
-     */
-    function _parse_var_props($val)
-    {
-        $val = trim($val);
-
-        if(preg_match('~^(' . $this->_obj_call_regexp . '|' . $this->_dvar_regexp . ')(' . $this->_mod_regexp . '*)$~', $val, $match)) {
-            // $ variable or object
-            $return = $this->_parse_var($match[1]);
-            $modifiers = $match[2];
-            if (!empty($this->default_modifiers) && !preg_match('~(^|\|)smarty:nodefaults($|\|)~',$modifiers)) {
-                $_default_mod_string = implode('|',(array)$this->default_modifiers);
-                $modifiers = empty($modifiers) ? $_default_mod_string : $_default_mod_string . '|' . $modifiers;
-            }
-            $this->_parse_modifiers($return, $modifiers);
-            return $return;
-        } elseif (preg_match('~^' . $this->_db_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
-                // double quoted text
-                preg_match('~^(' . $this->_db_qstr_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);
-                $return = $this->_expand_quoted_text($match[1]);
-                if($match[2] != '') {
-                    $this->_parse_modifiers($return, $match[2]);
-                }
-                return $return;
-            }
-        elseif(preg_match('~^' . $this->_num_const_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
-                // numerical constant
-                preg_match('~^(' . $this->_num_const_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);
-                if($match[2] != '') {
-                    $this->_parse_modifiers($match[1], $match[2]);
-                    return $match[1];
-                }
-            }
-        elseif(preg_match('~^' . $this->_si_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
-                // single quoted text
-                preg_match('~^(' . $this->_si_qstr_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);
-                if($match[2] != '') {
-                    $this->_parse_modifiers($match[1], $match[2]);
-                    return $match[1];
-                }
-            }
-        elseif(preg_match('~^' . $this->_cvar_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
-                // config var
-                return $this->_parse_conf_var($val);
-            }
-        elseif(preg_match('~^' . $this->_svar_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
-                // section var
-                return $this->_parse_section_prop($val);
-            }
-        elseif(!in_array($val, $this->_permitted_tokens) && !is_numeric($val)) {
-            // literal string
-            return $this->_expand_quoted_text('"' . strtr($val, array('\\' => '\\\\', '"' => '\\"')) .'"');
-        }
-        return $val;
-    }
-
-    /**
-     * expand quoted text with embedded variables
-     *
-     * @param string $var_expr
-     * @return string
-     */
-    function _expand_quoted_text($var_expr)
-    {
-        // if contains unescaped $, expand it
-        if(preg_match_all('~(?:\`(?<!\\\\)\$' . $this->_dvar_guts_regexp . '(?:' . $this->_obj_ext_regexp . ')*\`)|(?:(?<!\\\\)\$\w+(\[[a-zA-Z0-9]+\])*)~', $var_expr, $_match)) {
-            $_match = $_match[0];
-            $_replace = array();
-            foreach($_match as $_var) {
-                $_replace[$_var] = '".(' . $this->_parse_var(str_replace('`','',$_var)) . ')."';
-            }
-            $var_expr = strtr($var_expr, $_replace);
-            $_return = preg_replace('~\.""|(?<!\\\\)""\.~', '', $var_expr);
-        } else {
-            $_return = $var_expr;
-        }
-        // replace double quoted literal string with single quotes
-        $_return = preg_replace('~^"([\s\w]+)"$~',"'\\1'",$_return);
-        return $_return;
-    }
-
-    /**
-     * parse variable expression into PHP code
-     *
-     * @param string $var_expr
-     * @param string $output
-     * @return string
-     */
-    function _parse_var($var_expr)
-    {
-        $_has_math = false;
-        $_math_vars = preg_split('~('.$this->_dvar_math_regexp.'|'.$this->_qstr_regexp.')~', $var_expr, -1, PREG_SPLIT_DELIM_CAPTURE);
-
-        if(count($_math_vars) > 1) {
-            $_first_var = "";
-            $_complete_var = "";
-            $_output = "";
-            // simple check if there is any math, to stop recursion (due to modifiers with "xx % yy" as parameter)
-            foreach($_math_vars as $_k => $_math_var) {
-                $_math_var = $_math_vars[$_k];
-
-                if(!empty($_math_var) || is_numeric($_math_var)) {
-                    // hit a math operator, so process the stuff which came before it
-                    if(preg_match('~^' . $this->_dvar_math_regexp . '$~', $_math_var)) {
-                        $_has_math = true;
-                        if(!empty($_complete_var) || is_numeric($_complete_var)) {
-                            $_output .= $this->_parse_var($_complete_var);
-                        }
-
-                        // just output the math operator to php
-                        $_output .= $_math_var;
-
-                        if(empty($_first_var))
-                            $_first_var = $_complete_var;
-
-                        $_complete_var = "";
-                    } else {
-                        $_complete_var .= $_math_var;
-                    }
-                }
-            }
-            if($_has_math) {
-                if(!empty($_complete_var) || is_numeric($_complete_var))
-                    $_output .= $this->_parse_var($_complete_var);
-
-                // get the modifiers working (only the last var from math + modifier is left)
-                $var_expr = $_complete_var;
-            }
-        }
-
-        // prevent cutting of first digit in the number (we _definitly_ got a number if the first char is a digit)
-        if(is_numeric(substr($var_expr, 0, 1)))
-            $_var_ref = $var_expr;
-        else
-            $_var_ref = substr($var_expr, 1);
-        
-        if(!$_has_math) {
-            
-            // get [foo] and .foo and ->foo and (...) pieces
-            preg_match_all('~(?:^\w+)|' . $this->_obj_params_regexp . '|(?:' . $this->_var_bracket_regexp . ')|->\$?\w+|\.\$?\w+|\S+~', $_var_ref, $match);
-                        
-            $_indexes = $match[0];
-            $_var_name = array_shift($_indexes);
-
-            /* Handle $smarty.* variable references as a special case. */
-            if ($_var_name == 'smarty') {
-                /*
-                 * If the reference could be compiled, use the compiled output;
-                 * otherwise, fall back on the $smarty variable generated at
-                 * run-time.
-                 */
-                if (($smarty_ref = $this->_compile_smarty_ref($_indexes)) !== null) {
-                    $_output = $smarty_ref;
-                } else {
-                    $_var_name = substr(array_shift($_indexes), 1);
-                    $_output = "\$this->_smarty_vars['$_var_name']";
-                }
-            } elseif(is_numeric($_var_name) && is_numeric(substr($var_expr, 0, 1))) {
-                // because . is the operator for accessing arrays thru inidizes we need to put it together again for floating point numbers
-                if(count($_indexes) > 0)
-                {
-                    $_var_name .= implode("", $_indexes);
-                    $_indexes = array();
-                }
-                $_output = $_var_name;
-            } else {
-                $_output = "\$this->_tpl_vars['$_var_name']";
-            }
-
-            foreach ($_indexes as $_index) {
-                if (substr($_index, 0, 1) == '[') {
-                    $_index = substr($_index, 1, -1);
-                    if (is_numeric($_index)) {
-                        $_output .= "[$_index]";
-                    } elseif (substr($_index, 0, 1) == '$') {
-                        if (strpos($_index, '.') !== false) {
-                            $_output .= '[' . $this->_parse_var($_index) . ']';
-                        } else {
-                            $_output .= "[\$this->_tpl_vars['" . substr($_index, 1) . "']]";
-                        }
-                    } else {
-                        $_var_parts = explode('.', $_index);
-                        $_var_section = $_var_parts[0];
-                        $_var_section_prop = isset($_var_parts[1]) ? $_var_parts[1] : 'index';
-                        $_output .= "[\$this->_sections['$_var_section']['$_var_section_prop']]";
-                    }
-                } else if (substr($_index, 0, 1) == '.') {
-                    if (substr($_index, 1, 1) == '$')
-                        $_output .= "[\$this->_tpl_vars['" . substr($_index, 2) . "']]";
-                    else
-                        $_output .= "['" . substr($_index, 1) . "']";
-                } else if (substr($_index,0,2) == '->') {
-                    if(substr($_index,2,2) == '__') {
-                        $this->_syntax_error('call to internal object members is not allowed', E_USER_ERROR, __FILE__, __LINE__);
-                    } elseif($this->security && substr($_index, 2, 1) == '_') {
-                        $this->_syntax_error('(secure) call to private object member is not allowed', E_USER_ERROR, __FILE__, __LINE__);
-                    } elseif (substr($_index, 2, 1) == '$') {
-                        if ($this->security) {
-                            $this->_syntax_error('(secure) call to dynamic object member is not allowed', E_USER_ERROR, __FILE__, __LINE__);
-                        } else {
-                            $_output .= '->{(($_var=$this->_tpl_vars[\''.substr($_index,3).'\']) && substr($_var,0,2)!=\'__\') ? $_var : $this->trigger_error("cannot access property \\"$_var\\"")}';
-                        }
-                    } else {
-                        $_output .= $_index;
-                    }
-                } elseif (substr($_index, 0, 1) == '(') {
-                    $_index = $this->_parse_parenth_args($_index);
-                    $_output .= $_index;
-                } else {
-                    $_output .= $_index;
-                }
-            }
-        }
-
-        return $_output;
-    }
-
-    /**
-     * parse arguments in function call parenthesis
-     *
-     * @param string $parenth_args
-     * @return string
-     */
-    function _parse_parenth_args($parenth_args)
-    {
-        preg_match_all('~' . $this->_param_regexp . '~',$parenth_args, $match);
-        $orig_vals = $match = $match[0];
-        $this->_parse_vars_props($match);
-        $replace = array();
-        for ($i = 0, $count = count($match); $i < $count; $i++) {
-            $replace[$orig_vals[$i]] = $match[$i];
-        }
-        return strtr($parenth_args, $replace);
-    }
-
-    /**
-     * parse configuration variable expression into PHP code
-     *
-     * @param string $conf_var_expr
-     */
-    function _parse_conf_var($conf_var_expr)
-    {
-        $parts = explode('|', $conf_var_expr, 2);
-        $var_ref = $parts[0];
-        $modifiers = isset($parts[1]) ? $parts[1] : '';
-
-        $var_name = substr($var_ref, 1, -1);
-
-        $output = "\$this->_config[0]['vars']['$var_name']";
-
-        $this->_parse_modifiers($output, $modifiers);
-
-        return $output;
-    }
-
-    /**
-     * parse section property expression into PHP code
-     *
-     * @param string $section_prop_expr
-     * @return string
-     */
-    function _parse_section_prop($section_prop_expr)
-    {
-        $parts = explode('|', $section_prop_expr, 2);
-        $var_ref = $parts[0];
-        $modifiers = isset($parts[1]) ? $parts[1] : '';
-
-        preg_match('!%(\w+)\.(\w+)%!', $var_ref, $match);
-        $section_name = $match[1];
-        $prop_name = $match[2];
-
-        $output = "\$this->_sections['$section_name']['$prop_name']";
-
-        $this->_parse_modifiers($output, $modifiers);
-
-        return $output;
-    }
-
-
-    /**
-     * parse modifier chain into PHP code
-     *
-     * sets $output to parsed modified chain
-     * @param string $output
-     * @param string $modifier_string
-     */
-    function _parse_modifiers(&$output, $modifier_string)
-    {
-        preg_match_all('~\|(@?\w+)((?>:(?:'. $this->_qstr_regexp . '|[^|]+))*)~', '|' . $modifier_string, $_match);
-        list(, $_modifiers, $modifier_arg_strings) = $_match;
-
-        for ($_i = 0, $_for_max = count($_modifiers); $_i < $_for_max; $_i++) {
-            $_modifier_name = $_modifiers[$_i];
-
-            if($_modifier_name == 'smarty') {
-                // skip smarty modifier
-                continue;
-            }
-
-            preg_match_all('~:(' . $this->_qstr_regexp . '|[^:]+)~', $modifier_arg_strings[$_i], $_match);
-            $_modifier_args = $_match[1];
-
-            if (substr($_modifier_name, 0, 1) == '@') {
-                $_map_array = false;
-                $_modifier_name = substr($_modifier_name, 1);
-            } else {
-                $_map_array = true;
-            }
-
-            if (empty($this->_plugins['modifier'][$_modifier_name])
-                && !$this->_get_plugin_filepath('modifier', $_modifier_name)
-                && function_exists($_modifier_name)) {
-                if ($this->security && !in_array($_modifier_name, $this->security_settings['MODIFIER_FUNCS'])) {
-                    $this->_trigger_fatal_error("[plugin] (secure mode) modifier '$_modifier_name' is not allowed" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
-                } else {
-                    $this->_plugins['modifier'][$_modifier_name] = array($_modifier_name,  null, null, false);
-                }
-            }
-            $this->_add_plugin('modifier', $_modifier_name);
-
-            $this->_parse_vars_props($_modifier_args);
-
-            if($_modifier_name == 'default') {
-                // supress notifications of default modifier vars and args
-                if(substr($output, 0, 1) == '$') {
-                    $output = '@' . $output;
-                }
-                if(isset($_modifier_args[0]) && substr($_modifier_args[0], 0, 1) == '$') {
-                    $_modifier_args[0] = '@' . $_modifier_args[0];
-                }
-            }
-            if (count($_modifier_args) > 0)
-                $_modifier_args = ', '.implode(', ', $_modifier_args);
-            else
-                $_modifier_args = '';
-
-            if ($_map_array) {
-                $output = "((is_array(\$_tmp=$output)) ? \$this->_run_mod_handler('$_modifier_name', true, \$_tmp$_modifier_args) : " . $this->_compile_plugin_call('modifier', $_modifier_name) . "(\$_tmp$_modifier_args))";
-
-            } else {
-
-                $output = $this->_compile_plugin_call('modifier', $_modifier_name)."($output$_modifier_args)";
-
-            }
-        }
-    }
-
-
-    /**
-     * add plugin
-     *
-     * @param string $type
-     * @param string $name
-     * @param boolean? $delayed_loading
-     */
-    function _add_plugin($type, $name, $delayed_loading = null)
-    {
-        if (!isset($this->_plugin_info[$type])) {
-            $this->_plugin_info[$type] = array();
-        }
-        if (!isset($this->_plugin_info[$type][$name])) {
-            $this->_plugin_info[$type][$name] = array($this->_current_file,
-                                                      $this->_current_line_no,
-                                                      $delayed_loading);
-        }
-    }
-
-
-    /**
-     * Compiles references of type $smarty.foo
-     *
-     * @param string $indexes
-     * @return string
-     */
-    function _compile_smarty_ref(&$indexes)
-    {
-        /* Extract the reference name. */
-        $_ref = substr($indexes[0], 1);
-        foreach($indexes as $_index_no=>$_index) {
-            if (substr($_index, 0, 1) != '.' && $_index_no<2 || !preg_match('~^(\.|\[|->)~', $_index)) {
-                $this->_syntax_error('$smarty' . implode('', array_slice($indexes, 0, 2)) . ' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__);
-            }
-        }
-
-        switch ($_ref) {
-            case 'now':
-                $compiled_ref = 'time()';
-                $_max_index = 1;
-                break;
-
-            case 'foreach':
-                array_shift($indexes);
-                $_var = $this->_parse_var_props(substr($indexes[0], 1));
-                $_propname = substr($indexes[1], 1);
-                $_max_index = 1;
-                switch ($_propname) {
-                    case 'index':
-                        array_shift($indexes);
-                        $compiled_ref = "(\$this->_foreach[$_var]['iteration']-1)";
-                        break;
-                        
-                    case 'first':
-                        array_shift($indexes);
-                        $compiled_ref = "(\$this->_foreach[$_var]['iteration'] <= 1)";
-                        break;
-
-                    case 'last':
-                        array_shift($indexes);
-                        $compiled_ref = "(\$this->_foreach[$_var]['iteration'] == \$this->_foreach[$_var]['total'])";
-                        break;
-                        
-                    case 'show':
-                        array_shift($indexes);
-                        $compiled_ref = "(\$this->_foreach[$_var]['total'] > 0)";
-                        break;
-                        
-                    default:
-                        unset($_max_index);
-                        $compiled_ref = "\$this->_foreach[$_var]";
-                }
-                break;
-
-            case 'section':
-                array_shift($indexes);
-                $_var = $this->_parse_var_props(substr($indexes[0], 1));
-                $compiled_ref = "\$this->_sections[$_var]";
-                break;
-
-            case 'get':
-                $compiled_ref = ($this->request_use_auto_globals) ? '$_GET' : "\$GLOBALS['HTTP_GET_VARS']";
-                break;
-
-            case 'post':
-                $compiled_ref = ($this->request_use_auto_globals) ? '$_POST' : "\$GLOBALS['HTTP_POST_VARS']";
-                break;
-
-            case 'cookies':
-                $compiled_ref = ($this->request_use_auto_globals) ? '$_COOKIE' : "\$GLOBALS['HTTP_COOKIE_VARS']";
-                break;
-
-            case 'env':
-                $compiled_ref = ($this->request_use_auto_globals) ? '$_ENV' : "\$GLOBALS['HTTP_ENV_VARS']";
-                break;
-
-            case 'server':
-                $compiled_ref = ($this->request_use_auto_globals) ? '$_SERVER' : "\$GLOBALS['HTTP_SERVER_VARS']";
-                break;
-
-            case 'session':
-                $compiled_ref = ($this->request_use_auto_globals) ? '$_SESSION' : "\$GLOBALS['HTTP_SESSION_VARS']";
-                break;
-
-            /*
-             * These cases are handled either at run-time or elsewhere in the
-             * compiler.
-             */
-            case 'request':
-                if ($this->request_use_auto_globals) {
-                    $compiled_ref = '$_REQUEST';
-                    break;
-                } else {
-                    $this->_init_smarty_vars = true;
-                }
-                return null;
-
-            case 'capture':
-                return null;
-
-            case 'template':
-                $compiled_ref = "'$this->_current_file'";
-                $_max_index = 1;
-                break;
-
-            case 'version':
-                $compiled_ref = "'$this->_version'";
-                $_max_index = 1;
-                break;
-
-            case 'const':
-                if ($this->security && !$this->security_settings['ALLOW_CONSTANTS']) {
-                    $this->_syntax_error("(secure mode) constants not permitted",
-                                         E_USER_WARNING, __FILE__, __LINE__);
-                    return;
-                }
-                array_shift($indexes);
-                if (preg_match('!^\.\w+$!', $indexes[0])) {
-                    $compiled_ref = '@' . substr($indexes[0], 1);
-                } else {
-                    $_val = $this->_parse_var_props(substr($indexes[0], 1));
-                    $compiled_ref = '@constant(' . $_val . ')';
-                }
-                $_max_index = 1;
-                break;
-
-            case 'config':
-                $compiled_ref = "\$this->_config[0]['vars']";
-                $_max_index = 3;
-                break;
-
-            case 'ldelim':
-                $compiled_ref = "'$this->left_delimiter'";
-                break;
-
-            case 'rdelim':
-                $compiled_ref = "'$this->right_delimiter'";
-                break;
-                
-            default:
-                $this->_syntax_error('$smarty.' . $_ref . ' is an unknown reference', E_USER_ERROR, __FILE__, __LINE__);
-                break;
-        }
-
-        if (isset($_max_index) && count($indexes) > $_max_index) {
-            $this->_syntax_error('$smarty' . implode('', $indexes) .' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__);
-        }
-
-        array_shift($indexes);
-        return $compiled_ref;
-    }
-
-    /**
-     * compiles call to plugin of type $type with name $name
-     * returns a string containing the function-name or method call
-     * without the paramter-list that would have follow to make the
-     * call valid php-syntax
-     *
-     * @param string $type
-     * @param string $name
-     * @return string
-     */
-    function _compile_plugin_call($type, $name) {
-        if (isset($this->_plugins[$type][$name])) {
-            /* plugin loaded */
-            if (is_array($this->_plugins[$type][$name][0])) {
-                return ((is_object($this->_plugins[$type][$name][0][0])) ?
-                        "\$this->_plugins['$type']['$name'][0][0]->"    /* method callback */
-                        : (string)($this->_plugins[$type][$name][0][0]).'::'    /* class callback */
-                       ). $this->_plugins[$type][$name][0][1];
-
-            } else {
-                /* function callback */
-                return $this->_plugins[$type][$name][0];
-
-            }
-        } else {
-            /* plugin not loaded -> auto-loadable-plugin */
-            return 'smarty_'.$type.'_'.$name;
-
-        }
-    }
-
-    /**
-     * load pre- and post-filters
-     */
-    function _load_filters()
-    {
-        if (count($this->_plugins['prefilter']) > 0) {
-            foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) {
-                if ($prefilter === false) {
-                    unset($this->_plugins['prefilter'][$filter_name]);
-                    $_params = array('plugins' => array(array('prefilter', $filter_name, null, null, false)));
-                    require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
-                    smarty_core_load_plugins($_params, $this);
-                }
-            }
-        }
-        if (count($this->_plugins['postfilter']) > 0) {
-            foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) {
-                if ($postfilter === false) {
-                    unset($this->_plugins['postfilter'][$filter_name]);
-                    $_params = array('plugins' => array(array('postfilter', $filter_name, null, null, false)));
-                    require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
-                    smarty_core_load_plugins($_params, $this);
-                }
-            }
-        }
-    }
-
-
-    /**
-     * Quote subpattern references
-     *
-     * @param string $string
-     * @return string
-     */
-    function _quote_replace($string)
-    {
-        return strtr($string, array('\\' => '\\\\', '$' => '\\$'));
-    }
-
-    /**
-     * display Smarty syntax error
-     *
-     * @param string $error_msg
-     * @param integer $error_type
-     * @param string $file
-     * @param integer $line
-     */
-    function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=null, $line=null)
-    {
-        $this->_trigger_fatal_error("syntax error: $error_msg", $this->_current_file, $this->_current_line_no, $file, $line, $error_type);
-    }
-
-
-    /**
-     * check if the compilation changes from cacheable to
-     * non-cacheable state with the beginning of the current
-     * plugin. return php-code to reflect the transition.
-     * @return string
-     */
-    function _push_cacheable_state($type, $name) {
-        $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4];
-        if ($_cacheable
-            || 0<$this->_cacheable_state++) return '';
-        if (!isset($this->_cache_serial)) $this->_cache_serial = md5(uniqid('Smarty'));
-        $_ret = 'if ($this->caching && !$this->_cache_including): echo \'{nocache:'
-            . $this->_cache_serial . '#' . $this->_nocache_count
-            . '}\'; endif;';
-        return $_ret;
-    }
-
-
-    /**
-     * check if the compilation changes from non-cacheable to
-     * cacheable state with the end of the current plugin return
-     * php-code to reflect the transition.
-     * @return string
-     */
-    function _pop_cacheable_state($type, $name) {
-        $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4];
-        if ($_cacheable
-            || --$this->_cacheable_state>0) return '';
-        return 'if ($this->caching && !$this->_cache_including): echo \'{/nocache:'
-            . $this->_cache_serial . '#' . ($this->_nocache_count++)
-            . '}\'; endif;';
-    }
-
-
-    /**
-     * push opening tag-name, file-name and line-number on the tag-stack
-     * @param string the opening tag's name
-     */
-    function _push_tag($open_tag)
-    {
-        array_push($this->_tag_stack, array($open_tag, $this->_current_line_no));
-    }
-
-    /**
-     * pop closing tag-name
-     * raise an error if this stack-top doesn't match with the closing tag
-     * @param string the closing tag's name
-     * @return string the opening tag's name
-     */
-    function _pop_tag($close_tag)
-    {
-        $message = '';
-        if (count($this->_tag_stack)>0) {
-            list($_open_tag, $_line_no) = array_pop($this->_tag_stack);
-            if ($close_tag == $_open_tag) {
-                return $_open_tag;
-            }
-            if ($close_tag == 'if' && ($_open_tag == 'else' || $_open_tag == 'elseif' )) {
-                return $this->_pop_tag($close_tag);
-            }
-            if ($close_tag == 'section' && $_open_tag == 'sectionelse') {
-                $this->_pop_tag($close_tag);
-                return $_open_tag;
-            }
-            if ($close_tag == 'foreach' && $_open_tag == 'foreachelse') {
-                $this->_pop_tag($close_tag);
-                return $_open_tag;
-            }
-            if ($_open_tag == 'else' || $_open_tag == 'elseif') {
-                $_open_tag = 'if';
-            } elseif ($_open_tag == 'sectionelse') {
-                $_open_tag = 'section';
-            } elseif ($_open_tag == 'foreachelse') {
-                $_open_tag = 'foreach';
-            }
-            $message = " expected {/$_open_tag} (opened line $_line_no).";
-        }
-        $this->_syntax_error("mismatched tag {/$close_tag}.$message",
-                             E_USER_ERROR, __FILE__, __LINE__);
-    }
-
-}
-
-/**
- * compare to values by their string length
- *
- * @access private
- * @param string $a
- * @param string $b
- * @return 0|-1|1
- */
-function _smarty_sort_length($a, $b)
-{
-    if($a == $b)
-        return 0;
-
-    if(strlen($a) == strlen($b))
-        return ($a > $b) ? -1 : 1;
-
-    return (strlen($a) > strlen($b)) ? -1 : 1;
-}
-
-
-/* vim: set et: */
-
-?>
diff --git a/smarty/debug.tpl b/smarty/debug.tpl
deleted file mode 100644 (file)
index c05ef5d..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-{* Smarty *}
-{* debug.tpl, last updated version 2.1.0 *}
-{assign_debug_info}
-{capture assign=debug_output}
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-<head>
-    <title>Smarty Debug Console</title>
-{literal}
-<style type="text/css">
-/* <![CDATA[ */
-body, h1, h2, td, th, p {
-    font-family: sans-serif;
-    font-weight: normal;
-    font-size: 0.9em;
-    margin: 1px;
-    padding: 0;
-}
-
-h1 {
-    margin: 0;
-    text-align: left;
-    padding: 2px;
-    background-color: #f0c040;
-    color:  black;
-    font-weight: bold;
-    font-size: 1.2em;
- }
-
-h2 {
-    background-color: #9B410E;
-    color: white;
-    text-align: left;
-    font-weight: bold;
-    padding: 2px;
-    border-top: 1px solid black;
-}
-
-body {
-    background: black; 
-}
-
-p, table, div {
-    background: #f0ead8;
-} 
-
-p {
-    margin: 0;
-    font-style: italic;
-    text-align: center;
-}
-
-table {
-    width: 100%;
-}
-
-th, td {
-    font-family: monospace;
-    vertical-align: top;
-    text-align: left;
-    width: 50%;
-}
-
-td {
-    color: green;
-}
-
-.odd {
-    background-color: #eeeeee;
-}
-
-.even {
-    background-color: #fafafa;
-}
-
-.exectime {
-    font-size: 0.8em;
-    font-style: italic;
-}
-
-#table_assigned_vars th {
-    color: blue;
-}
-
-#table_config_vars th {
-    color: maroon;
-}
-/* ]]> */
-</style>
-{/literal}
-</head>
-<body>
-
-<h1>Smarty Debug Console</h1>
-
-<h2>included templates &amp; config files (load time in seconds)</h2>
-
-<div>
-{section name=templates loop=$_debug_tpls}
-    {section name=indent loop=$_debug_tpls[templates].depth}&nbsp;&nbsp;&nbsp;{/section}
-    <font color={if $_debug_tpls[templates].type eq "template"}brown{elseif $_debug_tpls[templates].type eq "insert"}black{else}green{/if}>
-        {$_debug_tpls[templates].filename|escape:html}</font>
-    {if isset($_debug_tpls[templates].exec_time)}
-        <span class="exectime">
-        ({$_debug_tpls[templates].exec_time|string_format:"%.5f"})
-        {if %templates.index% eq 0}(total){/if}
-        </span>
-    {/if}
-    <br />
-{sectionelse}
-    <p>no templates included</p>
-{/section}
-</div>
-
-<h2>assigned template variables</h2>
-
-<table id="table_assigned_vars">
-    {section name=vars loop=$_debug_keys}
-        <tr class="{cycle values="odd,even"}">
-            <th>{ldelim}${$_debug_keys[vars]|escape:'html'}{rdelim}</th>
-            <td>{$_debug_vals[vars]|@debug_print_var}</td></tr>
-    {sectionelse}
-        <tr><td><p>no template variables assigned</p></td></tr>
-    {/section}
-</table>
-
-<h2>assigned config file variables (outer template scope)</h2>
-
-<table id="table_config_vars">
-    {section name=config_vars loop=$_debug_config_keys}
-        <tr class="{cycle values="odd,even"}">
-            <th>{ldelim}#{$_debug_config_keys[config_vars]|escape:'html'}#{rdelim}</th>
-            <td>{$_debug_config_vals[config_vars]|@debug_print_var}</td></tr>
-    {sectionelse}
-        <tr><td><p>no config vars assigned</p></td></tr>
-    {/section}
-</table>
-</body>
-</html>
-{/capture}
-{if isset($_smarty_debug_output) and $_smarty_debug_output eq "html"}
-    {$debug_output}
-{else}
-<script type="text/javascript">
-// <![CDATA[
-    if ( self.name == '' ) {ldelim}
-       var title = 'Console';
-    {rdelim}
-    else {ldelim}
-       var title = 'Console_' + self.name;
-    {rdelim}
-    _smarty_console = window.open("",title.value,"width=680,height=600,resizable,scrollbars=yes");
-    _smarty_console.document.write('{$debug_output|escape:'javascript'}');
-    _smarty_console.document.close();
-// ]]>
-</script>
-{/if}
\ No newline at end of file
diff --git a/smarty/internals/core.assemble_plugin_filepath.php b/smarty/internals/core.assemble_plugin_filepath.php
deleted file mode 100644 (file)
index 690d3dd..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * assemble filepath of requested plugin
- *
- * @param string $type
- * @param string $name
- * @return string|false
- */
-function smarty_core_assemble_plugin_filepath($params, &$smarty)
-{
-    static $_filepaths_cache = array();
-
-    $_plugin_filename = $params['type'] . '.' . $params['name'] . '.php';
-    if (isset($_filepaths_cache[$_plugin_filename])) {
-        return $_filepaths_cache[$_plugin_filename];
-    }
-    $_return = false;
-
-    foreach ((array)$smarty->plugins_dir as $_plugin_dir) {
-
-        $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename;
-
-        // see if path is relative
-        if (!preg_match("/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/", $_plugin_dir)) {
-            $_relative_paths[] = $_plugin_dir;
-            // relative path, see if it is in the SMARTY_DIR
-            if (@is_readable(SMARTY_DIR . $_plugin_filepath)) {
-                $_return = SMARTY_DIR . $_plugin_filepath;
-                break;
-            }
-        }
-        // try relative to cwd (or absolute)
-        if (@is_readable($_plugin_filepath)) {
-            $_return = $_plugin_filepath;
-            break;
-        }
-    }
-
-    if($_return === false) {
-        // still not found, try PHP include_path
-        if(isset($_relative_paths)) {
-            foreach ((array)$_relative_paths as $_plugin_dir) {
-
-                $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename;
-
-                $_params = array('file_path' => $_plugin_filepath);
-                require_once(SMARTY_CORE_DIR . 'core.get_include_path.php');
-                if(smarty_core_get_include_path($_params, $smarty)) {
-                    $_return = $_params['new_file_path'];
-                    break;
-                }
-            }
-        }
-    }
-    $_filepaths_cache[$_plugin_filename] = $_return;
-    return $_return;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.assign_smarty_interface.php b/smarty/internals/core.assign_smarty_interface.php
deleted file mode 100644 (file)
index 7e65a73..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Smarty assign_smarty_interface core plugin
- *
- * Type:     core<br>
- * Name:     assign_smarty_interface<br>
- * Purpose:  assign the $smarty interface variable
- * @param array Format: null
- * @param Smarty
- */
-function smarty_core_assign_smarty_interface($params, &$smarty)
-{
-        if (isset($smarty->_smarty_vars) && isset($smarty->_smarty_vars['request'])) {
-            return;
-        }
-
-        $_globals_map = array('g'  => 'HTTP_GET_VARS',
-                             'p'  => 'HTTP_POST_VARS',
-                             'c'  => 'HTTP_COOKIE_VARS',
-                             's'  => 'HTTP_SERVER_VARS',
-                             'e'  => 'HTTP_ENV_VARS');
-
-        $_smarty_vars_request  = array();
-
-        foreach (preg_split('!!', strtolower($smarty->request_vars_order)) as $_c) {
-            if (isset($_globals_map[$_c])) {
-                $_smarty_vars_request = array_merge($_smarty_vars_request, $GLOBALS[$_globals_map[$_c]]);
-            }
-        }
-        $_smarty_vars_request = @array_merge($_smarty_vars_request, $GLOBALS['HTTP_SESSION_VARS']);
-
-        $smarty->_smarty_vars['request'] = $_smarty_vars_request;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.create_dir_structure.php b/smarty/internals/core.create_dir_structure.php
deleted file mode 100644 (file)
index 3eecc49..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * create full directory structure
- *
- * @param string $dir
- */
-
-// $dir
-
-function smarty_core_create_dir_structure($params, &$smarty)
-{
-    if (!file_exists($params['dir'])) {
-        $_open_basedir_ini = ini_get('open_basedir');
-
-        if (DIRECTORY_SEPARATOR=='/') {
-            /* unix-style paths */
-            $_dir = $params['dir'];
-            $_dir_parts = preg_split('!/+!', $_dir, -1, PREG_SPLIT_NO_EMPTY);
-            $_new_dir = (substr($_dir, 0, 1)=='/') ? '/' : getcwd().'/';
-            if($_use_open_basedir = !empty($_open_basedir_ini)) {
-                $_open_basedirs = explode(':', $_open_basedir_ini);
-            }
-
-        } else {
-            /* other-style paths */
-            $_dir = str_replace('\\','/', $params['dir']);
-            $_dir_parts = preg_split('!/+!', $_dir, -1, PREG_SPLIT_NO_EMPTY);
-            if (preg_match('!^((//)|([a-zA-Z]:/))!', $_dir, $_root_dir)) {
-                /* leading "//" for network volume, or "[letter]:/" for full path */
-                $_new_dir = $_root_dir[1];
-                /* remove drive-letter from _dir_parts */
-                if (isset($_root_dir[3])) array_shift($_dir_parts);
-
-            } else {
-                $_new_dir = str_replace('\\', '/', getcwd()).'/';
-
-            }
-
-            if($_use_open_basedir = !empty($_open_basedir_ini)) {
-                $_open_basedirs = explode(';', str_replace('\\', '/', $_open_basedir_ini));
-            }
-
-        }
-
-        /* all paths use "/" only from here */
-        foreach ($_dir_parts as $_dir_part) {
-            $_new_dir .= $_dir_part;
-
-            if ($_use_open_basedir) {
-                // do not attempt to test or make directories outside of open_basedir
-                $_make_new_dir = false;
-                foreach ($_open_basedirs as $_open_basedir) {
-                    if (substr($_new_dir, 0, strlen($_open_basedir)) == $_open_basedir) {
-                        $_make_new_dir = true;
-                        break;
-                    }
-                }
-            } else {
-                $_make_new_dir = true;
-            }
-
-            if ($_make_new_dir && !file_exists($_new_dir) && !@mkdir($_new_dir, $smarty->_dir_perms) && !is_dir($_new_dir)) {
-                $smarty->trigger_error("problem creating directory '" . $_new_dir . "'");
-                return false;
-            }
-            $_new_dir .= '/';
-        }
-    }
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.display_debug_console.php b/smarty/internals/core.display_debug_console.php
deleted file mode 100644 (file)
index 1a80f39..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Smarty debug_console function plugin
- *
- * Type:     core<br>
- * Name:     display_debug_console<br>
- * Purpose:  display the javascript debug console window
- * @param array Format: null
- * @param Smarty
- */
-function smarty_core_display_debug_console($params, &$smarty)
-{
-    // we must force compile the debug template in case the environment
-    // changed between separate applications.
-
-    if(empty($smarty->debug_tpl)) {
-        // set path to debug template from SMARTY_DIR
-        $smarty->debug_tpl = SMARTY_DIR . 'debug.tpl';
-        if($smarty->security && is_file($smarty->debug_tpl)) {
-            $smarty->secure_dir[] = realpath($smarty->debug_tpl);
-        }
-        $smarty->debug_tpl = 'file:' . SMARTY_DIR . 'debug.tpl';
-    }
-
-    $_ldelim_orig = $smarty->left_delimiter;
-    $_rdelim_orig = $smarty->right_delimiter;
-
-    $smarty->left_delimiter = '{';
-    $smarty->right_delimiter = '}';
-
-    $_compile_id_orig = $smarty->_compile_id;
-    $smarty->_compile_id = null;
-
-    $_compile_path = $smarty->_get_compile_path($smarty->debug_tpl);
-    if ($smarty->_compile_resource($smarty->debug_tpl, $_compile_path))
-    {
-        ob_start();
-        $smarty->_include($_compile_path);
-        $_results = ob_get_contents();
-        ob_end_clean();
-    } else {
-        $_results = '';
-    }
-
-    $smarty->_compile_id = $_compile_id_orig;
-
-    $smarty->left_delimiter = $_ldelim_orig;
-    $smarty->right_delimiter = $_rdelim_orig;
-
-    return $_results;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.get_include_path.php b/smarty/internals/core.get_include_path.php
deleted file mode 100644 (file)
index 4343241..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Get path to file from include_path
- *
- * @param string $file_path
- * @param string $new_file_path
- * @return boolean
- * @staticvar array|null
- */
-
-//  $file_path, &$new_file_path
-
-function smarty_core_get_include_path(&$params, &$smarty)
-{
-    static $_path_array = null;
-
-    if(!isset($_path_array)) {
-        $_ini_include_path = ini_get('include_path');
-
-        if(strstr($_ini_include_path,';')) {
-            // windows pathnames
-            $_path_array = explode(';',$_ini_include_path);
-        } else {
-            $_path_array = explode(':',$_ini_include_path);
-        }
-    }
-    foreach ($_path_array as $_include_path) {
-        if (@is_readable($_include_path . DIRECTORY_SEPARATOR . $params['file_path'])) {
-               $params['new_file_path'] = $_include_path . DIRECTORY_SEPARATOR . $params['file_path'];
-            return true;
-        }
-    }
-    return false;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.get_microtime.php b/smarty/internals/core.get_microtime.php
deleted file mode 100644 (file)
index f1a28e0..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Get seconds and microseconds
- * @return double
- */
-function smarty_core_get_microtime($params, &$smarty)
-{
-    $mtime = microtime();
-    $mtime = explode(" ", $mtime);
-    $mtime = (double)($mtime[1]) + (double)($mtime[0]);
-    return ($mtime);
-}
-
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.get_php_resource.php b/smarty/internals/core.get_php_resource.php
deleted file mode 100644 (file)
index 786d4e7..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Retrieves PHP script resource
- *
- * sets $php_resource to the returned resource
- * @param string $resource
- * @param string $resource_type
- * @param  $php_resource
- * @return boolean
- */
-
-function smarty_core_get_php_resource(&$params, &$smarty)
-{
-
-    $params['resource_base_path'] = $smarty->trusted_dir;
-    $smarty->_parse_resource_name($params, $smarty);
-
-    /*
-     * Find out if the resource exists.
-     */
-
-    if ($params['resource_type'] == 'file') {
-        $_readable = false;
-        if(file_exists($params['resource_name']) && is_readable($params['resource_name'])) {
-            $_readable = true;
-        } else {
-            // test for file in include_path
-            $_params = array('file_path' => $params['resource_name']);
-            require_once(SMARTY_CORE_DIR . 'core.get_include_path.php');
-            if(smarty_core_get_include_path($_params, $smarty)) {
-                $_include_path = $_params['new_file_path'];
-                $_readable = true;
-            }
-        }
-    } else if ($params['resource_type'] != 'file') {
-        $_template_source = null;
-        $_readable = is_callable($smarty->_plugins['resource'][$params['resource_type']][0][0])
-            && call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][0],
-                                    array($params['resource_name'], &$_template_source, &$smarty));
-    }
-
-    /*
-     * Set the error function, depending on which class calls us.
-     */
-    if (method_exists($smarty, '_syntax_error')) {
-        $_error_funcc = '_syntax_error';
-    } else {
-        $_error_funcc = 'trigger_error';
-    }
-
-    if ($_readable) {
-        if ($smarty->security) {
-            require_once(SMARTY_CORE_DIR . 'core.is_trusted.php');
-            if (!smarty_core_is_trusted($params, $smarty)) {
-                $smarty->$_error_funcc('(secure mode) ' . $params['resource_type'] . ':' . $params['resource_name'] . ' is not trusted');
-                return false;
-            }
-        }
-    } else {
-        $smarty->$_error_funcc($params['resource_type'] . ':' . $params['resource_name'] . ' is not readable');
-        return false;
-    }
-
-    if ($params['resource_type'] == 'file') {
-        $params['php_resource'] = $params['resource_name'];
-    } else {
-        $params['php_resource'] = $_template_source;
-    }
-    return true;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.is_secure.php b/smarty/internals/core.is_secure.php
deleted file mode 100644 (file)
index d54abd4..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * determines if a resource is secure or not.
- *
- * @param string $resource_type
- * @param string $resource_name
- * @return boolean
- */
-
-//  $resource_type, $resource_name
-
-function smarty_core_is_secure($params, &$smarty)
-{
-    if (!$smarty->security || $smarty->security_settings['INCLUDE_ANY']) {
-        return true;
-    }
-
-    if ($params['resource_type'] == 'file') {
-        $_rp = realpath($params['resource_name']);
-        if (isset($params['resource_base_path'])) {
-            foreach ((array)$params['resource_base_path'] as $curr_dir) {
-                if ( ($_cd = realpath($curr_dir)) !== false &&
-                     strncmp($_rp, $_cd, strlen($_cd)) == 0 &&
-                     substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR ) {
-                    return true;
-                }
-            }
-        }
-        if (!empty($smarty->secure_dir)) {
-            foreach ((array)$smarty->secure_dir as $curr_dir) {
-                if ( ($_cd = realpath($curr_dir)) !== false) {
-                    if($_cd == $_rp) {
-                        return true;
-                    } elseif (strncmp($_rp, $_cd, strlen($_cd)) == 0 &&
-                        substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR) {
-                        return true;
-                    }
-                }
-            }
-        }
-    } else {
-        // resource is not on local file system
-        return call_user_func_array(
-            $smarty->_plugins['resource'][$params['resource_type']][0][2],
-            array($params['resource_name'], &$smarty));
-    }
-
-    return false;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.is_trusted.php b/smarty/internals/core.is_trusted.php
deleted file mode 100644 (file)
index 4299731..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * determines if a resource is trusted or not
- *
- * @param string $resource_type
- * @param string $resource_name
- * @return boolean
- */
-
- // $resource_type, $resource_name
-
-function smarty_core_is_trusted($params, &$smarty)
-{
-    $_smarty_trusted = false;
-    if ($params['resource_type'] == 'file') {
-        if (!empty($smarty->trusted_dir)) {
-            $_rp = realpath($params['resource_name']);
-            foreach ((array)$smarty->trusted_dir as $curr_dir) {
-                if (!empty($curr_dir) && is_readable ($curr_dir)) {
-                    $_cd = realpath($curr_dir);
-                    if (strncmp($_rp, $_cd, strlen($_cd)) == 0
-                        && substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR ) {
-                        $_smarty_trusted = true;
-                        break;
-                    }
-                }
-            }
-        }
-
-    } else {
-        // resource is not on local file system
-        $_smarty_trusted = call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][3],
-                                                array($params['resource_name'], $smarty));
-    }
-
-    return $_smarty_trusted;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.load_plugins.php b/smarty/internals/core.load_plugins.php
deleted file mode 100644 (file)
index 6db1dc5..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Load requested plugins
- *
- * @param array $plugins
- */
-
-// $plugins
-
-function smarty_core_load_plugins($params, &$smarty)
-{
-
-    foreach ($params['plugins'] as $_plugin_info) {
-        list($_type, $_name, $_tpl_file, $_tpl_line, $_delayed_loading) = $_plugin_info;
-        $_plugin = &$smarty->_plugins[$_type][$_name];
-
-        /*
-         * We do not load plugin more than once for each instance of Smarty.
-         * The following code checks for that. The plugin can also be
-         * registered dynamically at runtime, in which case template file
-         * and line number will be unknown, so we fill them in.
-         *
-         * The final element of the info array is a flag that indicates
-         * whether the dynamically registered plugin function has been
-         * checked for existence yet or not.
-         */
-        if (isset($_plugin)) {
-            if (empty($_plugin[3])) {
-                if (!is_callable($_plugin[0])) {
-                    $smarty->_trigger_fatal_error("[plugin] $_type '$_name' is not implemented", $_tpl_file, $_tpl_line, __FILE__, __LINE__);
-                } else {
-                    $_plugin[1] = $_tpl_file;
-                    $_plugin[2] = $_tpl_line;
-                    $_plugin[3] = true;
-                    if (!isset($_plugin[4])) $_plugin[4] = true; /* cacheable */
-                }
-            }
-            continue;
-        } else if ($_type == 'insert') {
-            /*
-             * For backwards compatibility, we check for insert functions in
-             * the symbol table before trying to load them as a plugin.
-             */
-            $_plugin_func = 'insert_' . $_name;
-            if (function_exists($_plugin_func)) {
-                $_plugin = array($_plugin_func, $_tpl_file, $_tpl_line, true, false);
-                continue;
-            }
-        }
-
-        $_plugin_file = $smarty->_get_plugin_filepath($_type, $_name);
-
-        if (! $_found = ($_plugin_file != false)) {
-            $_message = "could not load plugin file '$_type.$_name.php'\n";
-        }
-
-        /*
-         * If plugin file is found, it -must- provide the properly named
-         * plugin function. In case it doesn't, simply output the error and
-         * do not fall back on any other method.
-         */
-        if ($_found) {
-            include_once $_plugin_file;
-
-            $_plugin_func = 'smarty_' . $_type . '_' . $_name;
-            if (!function_exists($_plugin_func)) {
-                $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", $_tpl_file, $_tpl_line, __FILE__, __LINE__);
-                continue;
-            }
-        }
-        /*
-         * In case of insert plugins, their code may be loaded later via
-         * 'script' attribute.
-         */
-        else if ($_type == 'insert' && $_delayed_loading) {
-            $_plugin_func = 'smarty_' . $_type . '_' . $_name;
-            $_found = true;
-        }
-
-        /*
-         * Plugin specific processing and error checking.
-         */
-        if (!$_found) {
-            if ($_type == 'modifier') {
-                /*
-                 * In case modifier falls back on using PHP functions
-                 * directly, we only allow those specified in the security
-                 * context.
-                 */
-                if ($smarty->security && !in_array($_name, $smarty->security_settings['MODIFIER_FUNCS'])) {
-                    $_message = "(secure mode) modifier '$_name' is not allowed";
-                } else {
-                    if (!function_exists($_name)) {
-                        $_message = "modifier '$_name' is not implemented";
-                    } else {
-                        $_plugin_func = $_name;
-                        $_found = true;
-                    }
-                }
-            } else if ($_type == 'function') {
-                /*
-                 * This is a catch-all situation.
-                 */
-                $_message = "unknown tag - '$_name'";
-            }
-        }
-
-        if ($_found) {
-            $smarty->_plugins[$_type][$_name] = array($_plugin_func, $_tpl_file, $_tpl_line, true, true);
-        } else {
-            // output error
-            $smarty->_trigger_fatal_error('[plugin] ' . $_message, $_tpl_file, $_tpl_line, __FILE__, __LINE__);
-        }
-    }
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.load_resource_plugin.php b/smarty/internals/core.load_resource_plugin.php
deleted file mode 100644 (file)
index a7d37d1..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * load a resource plugin
- *
- * @param string $type
- */
-
-// $type
-
-function smarty_core_load_resource_plugin($params, &$smarty)
-{
-    /*
-     * Resource plugins are not quite like the other ones, so they are
-     * handled differently. The first element of plugin info is the array of
-     * functions provided by the plugin, the second one indicates whether
-     * all of them exist or not.
-     */
-
-    $_plugin = &$smarty->_plugins['resource'][$params['type']];
-    if (isset($_plugin)) {
-        if (!$_plugin[1] && count($_plugin[0])) {
-            $_plugin[1] = true;
-            foreach ($_plugin[0] as $_plugin_func) {
-                if (!is_callable($_plugin_func)) {
-                    $_plugin[1] = false;
-                    break;
-                }
-            }
-        }
-
-        if (!$_plugin[1]) {
-            $smarty->_trigger_fatal_error("[plugin] resource '" . $params['type'] . "' is not implemented", null, null, __FILE__, __LINE__);
-        }
-
-        return;
-    }
-
-    $_plugin_file = $smarty->_get_plugin_filepath('resource', $params['type']);
-    $_found = ($_plugin_file != false);
-
-    if ($_found) {            /*
-         * If the plugin file is found, it -must- provide the properly named
-         * plugin functions.
-         */
-        include_once($_plugin_file);
-
-        /*
-         * Locate functions that we require the plugin to provide.
-         */
-        $_resource_ops = array('source', 'timestamp', 'secure', 'trusted');
-        $_resource_funcs = array();
-        foreach ($_resource_ops as $_op) {
-            $_plugin_func = 'smarty_resource_' . $params['type'] . '_' . $_op;
-            if (!function_exists($_plugin_func)) {
-                $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", null, null, __FILE__, __LINE__);
-                return;
-            } else {
-                $_resource_funcs[] = $_plugin_func;
-            }
-        }
-
-        $smarty->_plugins['resource'][$params['type']] = array($_resource_funcs, true);
-    }
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.process_cached_inserts.php b/smarty/internals/core.process_cached_inserts.php
deleted file mode 100644 (file)
index 1d78edd..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Replace cached inserts with the actual results
- *
- * @param string $results
- * @return string
- */
-function smarty_core_process_cached_inserts($params, &$smarty)
-{
-    preg_match_all('!'.$smarty->_smarty_md5.'{insert_cache (.*)}'.$smarty->_smarty_md5.'!Uis',
-                   $params['results'], $match);
-    list($cached_inserts, $insert_args) = $match;
-
-    for ($i = 0, $for_max = count($cached_inserts); $i < $for_max; $i++) {
-        if ($smarty->debugging) {
-            $_params = array();
-            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
-            $debug_start_time = smarty_core_get_microtime($_params, $smarty);
-        }
-
-        $args = unserialize($insert_args[$i]);
-        $name = $args['name'];
-
-        if (isset($args['script'])) {
-            $_params = array('resource_name' => $smarty->_dequote($args['script']));
-            require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php');
-            if(!smarty_core_get_php_resource($_params, $smarty)) {
-                return false;
-            }
-            $resource_type = $_params['resource_type'];
-            $php_resource = $_params['php_resource'];
-
-
-            if ($resource_type == 'file') {
-                $smarty->_include($php_resource, true);
-            } else {
-                $smarty->_eval($php_resource);
-            }
-        }
-
-        $function_name = $smarty->_plugins['insert'][$name][0];
-        if (empty($args['assign'])) {
-            $replace = $function_name($args, $smarty);
-        } else {
-            $smarty->assign($args['assign'], $function_name($args, $smarty));
-            $replace = '';
-        }
-
-        $params['results'] = substr_replace($params['results'], $replace, strpos($params['results'], $cached_inserts[$i]), strlen($cached_inserts[$i]));
-        if ($smarty->debugging) {
-            $_params = array();
-            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
-            $smarty->_smarty_debug_info[] = array('type'      => 'insert',
-                                                'filename'  => 'insert_'.$name,
-                                                'depth'     => $smarty->_inclusion_depth,
-                                                'exec_time' => smarty_core_get_microtime($_params, $smarty) - $debug_start_time);
-        }
-    }
-
-    return $params['results'];
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.process_compiled_include.php b/smarty/internals/core.process_compiled_include.php
deleted file mode 100644 (file)
index d539423..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Replace nocache-tags by results of the corresponding non-cacheable
- * functions and return it
- *
- * @param string $compiled_tpl
- * @param string $cached_source
- * @return string
- */
-
-function smarty_core_process_compiled_include($params, &$smarty)
-{
-    $_cache_including = $smarty->_cache_including;
-    $smarty->_cache_including = true;
-
-    $_return = $params['results'];
-
-    foreach ($smarty->_cache_info['cache_serials'] as $_include_file_path=>$_cache_serial) {
-        $smarty->_include($_include_file_path, true);
-    }
-
-    foreach ($smarty->_cache_serials as $_include_file_path=>$_cache_serial) {
-        $_return = preg_replace_callback('!(\{nocache\:('.$_cache_serial.')#(\d+)\})!s',
-                                         array(&$smarty, '_process_compiled_include_callback'),
-                                         $_return);
-    }
-    $smarty->_cache_including = $_cache_including;
-    return $_return;
-}
-
-?>
diff --git a/smarty/internals/core.read_cache_file.php b/smarty/internals/core.read_cache_file.php
deleted file mode 100644 (file)
index c60e113..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * read a cache file, determine if it needs to be
- * regenerated or not
- *
- * @param string $tpl_file
- * @param string $cache_id
- * @param string $compile_id
- * @param string $results
- * @return boolean
- */
-
-//  $tpl_file, $cache_id, $compile_id, &$results
-
-function smarty_core_read_cache_file(&$params, &$smarty)
-{
-    static  $content_cache = array();
-
-    if ($smarty->force_compile) {
-        // force compile enabled, always regenerate
-        return false;
-    }
-
-    if (isset($content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']])) {
-        list($params['results'], $smarty->_cache_info) = $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']];
-        return true;
-    }
-
-    if (!empty($smarty->cache_handler_func)) {
-        // use cache_handler function
-        call_user_func_array($smarty->cache_handler_func,
-                             array('read', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null));
-    } else {
-        // use local cache file
-        $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']);
-        $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id);
-        $params['results'] = $smarty->_read_file($_cache_file);
-    }
-
-    if (empty($params['results'])) {
-        // nothing to parse (error?), regenerate cache
-        return false;
-    }
-
-    $_contents = $params['results'];
-    $_info_start = strpos($_contents, "\n") + 1;
-    $_info_len = (int)substr($_contents, 0, $_info_start - 1);
-    $_cache_info = unserialize(substr($_contents, $_info_start, $_info_len));
-    $params['results'] = substr($_contents, $_info_start + $_info_len);
-
-    if ($smarty->caching == 2 && isset ($_cache_info['expires'])){
-        // caching by expiration time
-        if ($_cache_info['expires'] > -1 && (time() > $_cache_info['expires'])) {
-            // cache expired, regenerate
-            return false;
-        }
-    } else {
-        // caching by lifetime
-        if ($smarty->cache_lifetime > -1 && (time() - $_cache_info['timestamp'] > $smarty->cache_lifetime)) {
-            // cache expired, regenerate
-            return false;
-        }
-    }
-
-    if ($smarty->compile_check) {
-        $_params = array('get_source' => false, 'quiet'=>true);
-        foreach (array_keys($_cache_info['template']) as $_template_dep) {
-            $_params['resource_name'] = $_template_dep;
-            if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) {
-                // template file has changed, regenerate cache
-                return false;
-            }
-        }
-
-        if (isset($_cache_info['config'])) {
-            $_params = array('resource_base_path' => $smarty->config_dir, 'get_source' => false, 'quiet'=>true);
-            foreach (array_keys($_cache_info['config']) as $_config_dep) {
-                $_params['resource_name'] = $_config_dep;
-                if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) {
-                    // config file has changed, regenerate cache
-                    return false;
-                }
-            }
-        }
-    }
-
-    $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']] = array($params['results'], $_cache_info);
-
-    $smarty->_cache_info = $_cache_info;
-    return true;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.rm_auto.php b/smarty/internals/core.rm_auto.php
deleted file mode 100644 (file)
index b251f64..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * delete an automagically created file by name and id
- *
- * @param string $auto_base
- * @param string $auto_source
- * @param string $auto_id
- * @param integer $exp_time
- * @return boolean
- */
-
-// $auto_base, $auto_source = null, $auto_id = null, $exp_time = null
-
-function smarty_core_rm_auto($params, &$smarty)
-{
-    if (!@is_dir($params['auto_base']))
-      return false;
-
-    if(!isset($params['auto_id']) && !isset($params['auto_source'])) {
-        $_params = array(
-            'dirname' => $params['auto_base'],
-            'level' => 0,
-            'exp_time' => $params['exp_time']
-        );
-        require_once(SMARTY_CORE_DIR . 'core.rmdir.php');
-        $_res = smarty_core_rmdir($_params, $smarty);
-    } else {
-        $_tname = $smarty->_get_auto_filename($params['auto_base'], $params['auto_source'], $params['auto_id']);
-
-        if(isset($params['auto_source'])) {
-            if (isset($params['extensions'])) {
-                $_res = false;
-                foreach ((array)$params['extensions'] as $_extension)
-                    $_res |= $smarty->_unlink($_tname.$_extension, $params['exp_time']);
-            } else {
-                $_res = $smarty->_unlink($_tname, $params['exp_time']);
-            }
-        } elseif ($smarty->use_sub_dirs) {
-            $_params = array(
-                'dirname' => $_tname,
-                'level' => 1,
-                'exp_time' => $params['exp_time']
-            );
-            require_once(SMARTY_CORE_DIR . 'core.rmdir.php');
-            $_res = smarty_core_rmdir($_params, $smarty);
-        } else {
-            // remove matching file names
-            $_handle = opendir($params['auto_base']);
-            $_res = true;
-            while (false !== ($_filename = readdir($_handle))) {
-                if($_filename == '.' || $_filename == '..') {
-                    continue;
-                } elseif (substr($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, 0, strlen($_tname)) == $_tname) {
-                    $_res &= (bool)$smarty->_unlink($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, $params['exp_time']);
-                }
-            }
-        }
-    }
-
-    return $_res;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.rmdir.php b/smarty/internals/core.rmdir.php
deleted file mode 100644 (file)
index 2166c44..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * delete a dir recursively (level=0 -> keep root)
- * WARNING: no tests, it will try to remove what you tell it!
- *
- * @param string $dirname
- * @param integer $level
- * @param integer $exp_time
- * @return boolean
- */
-
-//  $dirname, $level = 1, $exp_time = null
-
-function smarty_core_rmdir($params, &$smarty)
-{
-   if(!isset($params['level'])) { $params['level'] = 1; }
-   if(!isset($params['exp_time'])) { $params['exp_time'] = null; }
-
-   if($_handle = @opendir($params['dirname'])) {
-
-        while (false !== ($_entry = readdir($_handle))) {
-            if ($_entry != '.' && $_entry != '..') {
-                if (@is_dir($params['dirname'] . DIRECTORY_SEPARATOR . $_entry)) {
-                    $_params = array(
-                        'dirname' => $params['dirname'] . DIRECTORY_SEPARATOR . $_entry,
-                        'level' => $params['level'] + 1,
-                        'exp_time' => $params['exp_time']
-                    );
-                    smarty_core_rmdir($_params, $smarty);
-                }
-                else {
-                    $smarty->_unlink($params['dirname'] . DIRECTORY_SEPARATOR . $_entry, $params['exp_time']);
-                }
-            }
-        }
-        closedir($_handle);
-   }
-
-   if ($params['level']) {
-       return @rmdir($params['dirname']);
-   }
-   return (bool)$_handle;
-
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.run_insert_handler.php b/smarty/internals/core.run_insert_handler.php
deleted file mode 100644 (file)
index 71c3845..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Handle insert tags
- *
- * @param array $args
- * @return string
- */
-function smarty_core_run_insert_handler($params, &$smarty)
-{
-
-    require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
-    if ($smarty->debugging) {
-        $_params = array();
-        $_debug_start_time = smarty_core_get_microtime($_params, $smarty);
-    }
-
-    if ($smarty->caching) {
-        $_arg_string = serialize($params['args']);
-        $_name = $params['args']['name'];
-        if (!isset($smarty->_cache_info['insert_tags'][$_name])) {
-            $smarty->_cache_info['insert_tags'][$_name] = array('insert',
-                                                             $_name,
-                                                             $smarty->_plugins['insert'][$_name][1],
-                                                             $smarty->_plugins['insert'][$_name][2],
-                                                             !empty($params['args']['script']) ? true : false);
-        }
-        return $smarty->_smarty_md5."{insert_cache $_arg_string}".$smarty->_smarty_md5;
-    } else {
-        if (isset($params['args']['script'])) {
-            $_params = array('resource_name' => $smarty->_dequote($params['args']['script']));
-            require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php');
-            if(!smarty_core_get_php_resource($_params, $smarty)) {
-                return false;
-            }
-
-            if ($_params['resource_type'] == 'file') {
-                $smarty->_include($_params['php_resource'], true);
-            } else {
-                $smarty->_eval($_params['php_resource']);
-            }
-            unset($params['args']['script']);
-        }
-
-        $_funcname = $smarty->_plugins['insert'][$params['args']['name']][0];
-        $_content = $_funcname($params['args'], $smarty);
-        if ($smarty->debugging) {
-            $_params = array();
-            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
-            $smarty->_smarty_debug_info[] = array('type'      => 'insert',
-                                                'filename'  => 'insert_'.$params['args']['name'],
-                                                'depth'     => $smarty->_inclusion_depth,
-                                                'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time);
-        }
-
-        if (!empty($params['args']["assign"])) {
-            $smarty->assign($params['args']["assign"], $_content);
-        } else {
-            return $_content;
-        }
-    }
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.smarty_include_php.php b/smarty/internals/core.smarty_include_php.php
deleted file mode 100644 (file)
index 30c6e76..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * called for included php files within templates
- *
- * @param string $smarty_file
- * @param string $smarty_assign variable to assign the included template's
- *               output into
- * @param boolean $smarty_once uses include_once if this is true
- * @param array $smarty_include_vars associative array of vars from
- *              {include file="blah" var=$var}
- */
-
-//  $file, $assign, $once, $_smarty_include_vars
-
-function smarty_core_smarty_include_php($params, &$smarty)
-{
-    $_params = array('resource_name' => $params['smarty_file']);
-    require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php');
-    smarty_core_get_php_resource($_params, $smarty);
-    $_smarty_resource_type = $_params['resource_type'];
-    $_smarty_php_resource = $_params['php_resource'];
-
-    if (!empty($params['smarty_assign'])) {
-        ob_start();
-        if ($_smarty_resource_type == 'file') {
-            $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']);
-        } else {
-            $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']);
-        }
-        $smarty->assign($params['smarty_assign'], ob_get_contents());
-        ob_end_clean();
-    } else {
-        if ($_smarty_resource_type == 'file') {
-            $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']);
-        } else {
-            $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']);
-        }
-    }
-}
-
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.write_cache_file.php b/smarty/internals/core.write_cache_file.php
deleted file mode 100644 (file)
index 72f785b..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Prepend the cache information to the cache file
- * and write it
- *
- * @param string $tpl_file
- * @param string $cache_id
- * @param string $compile_id
- * @param string $results
- * @return true|null
- */
-
- // $tpl_file, $cache_id, $compile_id, $results
-
-function smarty_core_write_cache_file($params, &$smarty)
-{
-
-    // put timestamp in cache header
-    $smarty->_cache_info['timestamp'] = time();
-    if ($smarty->cache_lifetime > -1){
-        // expiration set
-        $smarty->_cache_info['expires'] = $smarty->_cache_info['timestamp'] + $smarty->cache_lifetime;
-    } else {
-        // cache will never expire
-        $smarty->_cache_info['expires'] = -1;
-    }
-
-    // collapse nocache.../nocache-tags
-    if (preg_match_all('!\{(/?)nocache\:[0-9a-f]{32}#\d+\}!', $params['results'], $match, PREG_PATTERN_ORDER)) {
-        // remove everything between every pair of outermost noache.../nocache-tags
-        // and replace it by a single nocache-tag
-        // this new nocache-tag will be replaced by dynamic contents in
-        // smarty_core_process_compiled_includes() on a cache-read
-        
-        $match_count = count($match[0]);
-        $results = preg_split('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!', $params['results'], -1, PREG_SPLIT_DELIM_CAPTURE);
-        
-        $level = 0;
-        $j = 0;
-        for ($i=0, $results_count = count($results); $i < $results_count && $j < $match_count; $i++) {
-            if ($results[$i] == $match[0][$j]) {
-                // nocache tag
-                if ($match[1][$j]) { // closing tag
-                    $level--;
-                    unset($results[$i]);
-                } else { // opening tag
-                    if ($level++ > 0) unset($results[$i]);
-                }
-                $j++;
-            } elseif ($level > 0) {
-                unset($results[$i]);
-            }
-        }
-        $params['results'] = implode('', $results);
-    }
-    $smarty->_cache_info['cache_serials'] = $smarty->_cache_serials;
-
-    // prepend the cache header info into cache file
-    $_cache_info = serialize($smarty->_cache_info);
-    $params['results'] = strlen($_cache_info) . "\n" . $_cache_info . $params['results'];
-
-    if (!empty($smarty->cache_handler_func)) {
-        // use cache_handler function
-        call_user_func_array($smarty->cache_handler_func,
-                             array('write', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null));
-    } else {
-        // use local cache file
-
-        if(!@is_writable($smarty->cache_dir)) {
-            // cache_dir not writable, see if it exists
-            if(!@is_dir($smarty->cache_dir)) {
-                $smarty->trigger_error('the $cache_dir \'' . $smarty->cache_dir . '\' does not exist, or is not a directory.', E_USER_ERROR);
-                return false;
-            }
-            $smarty->trigger_error('unable to write to $cache_dir \'' . realpath($smarty->cache_dir) . '\'. Be sure $cache_dir is writable by the web server user.', E_USER_ERROR);
-            return false;
-        }
-
-        $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']);
-        $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id);
-        $_params = array('filename' => $_cache_file, 'contents' => $params['results'], 'create_dirs' => true);
-        require_once(SMARTY_CORE_DIR . 'core.write_file.php');
-        smarty_core_write_file($_params, $smarty);
-        return true;
-    }
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.write_compiled_include.php b/smarty/internals/core.write_compiled_include.php
deleted file mode 100644 (file)
index c14adb5..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Extract non-cacheable parts out of compiled template and write it
- *
- * @param string $compile_path
- * @param string $template_compiled
- * @return boolean
- */
-
-function smarty_core_write_compiled_include($params, &$smarty)
-{
-    $_tag_start = 'if \(\$this->caching && \!\$this->_cache_including\)\: echo \'\{nocache\:('.$params['cache_serial'].')#(\d+)\}\'; endif;';
-    $_tag_end   = 'if \(\$this->caching && \!\$this->_cache_including\)\: echo \'\{/nocache\:(\\2)#(\\3)\}\'; endif;';
-
-    preg_match_all('!('.$_tag_start.'(.*)'.$_tag_end.')!Us',
-                   $params['compiled_content'], $_match_source, PREG_SET_ORDER);
-    
-    // no nocache-parts found: done
-    if (count($_match_source)==0) return;
-
-    // convert the matched php-code to functions
-    $_include_compiled =  "<?php /* Smarty version ".$smarty->_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n";
-    $_include_compiled .= "         compiled from " . strtr(urlencode($params['resource_name']), array('%2F'=>'/', '%3A'=>':')) . " */\n\n";
-
-    $_compile_path = $params['include_file_path'];
-
-    $smarty->_cache_serials[$_compile_path] = $params['cache_serial'];
-    $_include_compiled .= "\$this->_cache_serials['".$_compile_path."'] = '".$params['cache_serial']."';\n\n?>";
-
-    $_include_compiled .= $params['plugins_code'];
-    $_include_compiled .= "<?php";
-
-    $this_varname = ((double)phpversion() >= 5.0) ? '_smarty' : 'this';
-    for ($_i = 0, $_for_max = count($_match_source); $_i < $_for_max; $_i++) {
-        $_match =& $_match_source[$_i];
-        $source = $_match[4];
-        if ($this_varname == '_smarty') {
-            /* rename $this to $_smarty in the sourcecode */
-            $tokens = token_get_all('<?php ' . $_match[4]);
-
-            /* remove trailing <?php */
-            $open_tag = '';
-            while ($tokens) {
-                $token = array_shift($tokens);
-                if (is_array($token)) {
-                    $open_tag .= $token[1];
-                } else {
-                    $open_tag .= $token;
-                }
-                if ($open_tag == '<?php ') break;
-            }
-
-            for ($i=0, $count = count($tokens); $i < $count; $i++) {
-                if (is_array($tokens[$i])) {
-                    if ($tokens[$i][0] == T_VARIABLE && $tokens[$i][1] == '$this') {
-                        $tokens[$i] = '$' . $this_varname;
-                    } else {
-                        $tokens[$i] = $tokens[$i][1];
-                    }                   
-                }
-            }
-            $source = implode('', $tokens);
-        }
-
-        /* add function to compiled include */
-        $_include_compiled .= "
-function _smarty_tplfunc_$_match[2]_$_match[3](&\$$this_varname)
-{
-$source
-}
-
-";
-    }
-    $_include_compiled .= "\n\n?>\n";
-
-    $_params = array('filename' => $_compile_path,
-                     'contents' => $_include_compiled, 'create_dirs' => true);
-
-    require_once(SMARTY_CORE_DIR . 'core.write_file.php');
-    smarty_core_write_file($_params, $smarty);
-    return true;
-}
-
-
-?>
diff --git a/smarty/internals/core.write_compiled_resource.php b/smarty/internals/core.write_compiled_resource.php
deleted file mode 100644 (file)
index b902eff..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * write the compiled resource
- *
- * @param string $compile_path
- * @param string $compiled_content
- * @return true
- */
-function smarty_core_write_compiled_resource($params, &$smarty)
-{
-    if(!@is_writable($smarty->compile_dir)) {
-        // compile_dir not writable, see if it exists
-        if(!@is_dir($smarty->compile_dir)) {
-            $smarty->trigger_error('the $compile_dir \'' . $smarty->compile_dir . '\' does not exist, or is not a directory.', E_USER_ERROR);
-            return false;
-        }
-        $smarty->trigger_error('unable to write to $compile_dir \'' . realpath($smarty->compile_dir) . '\'. Be sure $compile_dir is writable by the web server user.', E_USER_ERROR);
-        return false;
-    }
-
-    $_params = array('filename' => $params['compile_path'], 'contents' => $params['compiled_content'], 'create_dirs' => true);
-    require_once(SMARTY_CORE_DIR . 'core.write_file.php');
-    smarty_core_write_file($_params, $smarty);
-    return true;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/internals/core.write_file.php b/smarty/internals/core.write_file.php
deleted file mode 100644 (file)
index 8a3a3b3..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * write out a file to disk
- *
- * @param string $filename
- * @param string $contents
- * @param boolean $create_dirs
- * @return boolean
- */
-function smarty_core_write_file($params, &$smarty)
-{
-    $_dirname = dirname($params['filename']);
-
-    if ($params['create_dirs']) {
-        $_params = array('dir' => $_dirname);
-        require_once(SMARTY_CORE_DIR . 'core.create_dir_structure.php');
-        smarty_core_create_dir_structure($_params, $smarty);
-    }
-
-    // write to tmp file, then rename it to avoid file locking race condition
-    $_tmp_file = tempnam($_dirname, 'wrt');
-
-    if (!($fd = @fopen($_tmp_file, 'wb'))) {
-        $_tmp_file = $_dirname . DIRECTORY_SEPARATOR . uniqid('wrt');
-        if (!($fd = @fopen($_tmp_file, 'wb'))) {
-            $smarty->trigger_error("problem writing temporary file '$_tmp_file'");
-            return false;
-        }
-    }
-
-    fwrite($fd, $params['contents']);
-    fclose($fd);
-
-    if (DIRECTORY_SEPARATOR == '\\' || !@rename($_tmp_file, $params['filename'])) {
-        // On platforms and filesystems that cannot overwrite with rename() 
-        // delete the file before renaming it -- because windows always suffers
-        // this, it is short-circuited to avoid the initial rename() attempt
-        @unlink($params['filename']);
-        @rename($_tmp_file, $params['filename']);
-    }
-    @chmod($params['filename'], $smarty->_file_perms);
-
-    return true;
-}
-
-/* vim: set expandtab: */
-
-?>
\ No newline at end of file
diff --git a/smarty/plugins/block.textformat.php b/smarty/plugins/block.textformat.php
deleted file mode 100644 (file)
index 8cd010a..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Smarty {textformat}{/textformat} block plugin
- *
- * Type:     block function<br>
- * Name:     textformat<br>
- * Purpose:  format text a certain way with preset styles
- *           or custom wrap/indent settings<br>
- * @link http://smarty.php.net/manual/en/language.function.textformat.php {textformat}
- *       (Smarty online manual)
- * @param array
- * <pre>
- * Params:   style: string (email)
- *           indent: integer (0)
- *           wrap: integer (80)
- *           wrap_char string ("\n")
- *           indent_char: string (" ")
- *           wrap_boundary: boolean (true)
- * </pre>
- * @author Monte Ohrt <monte at ohrt dot com>
- * @param string contents of the block
- * @param Smarty clever simulation of a method
- * @return string string $content re-formatted
- */
-function smarty_block_textformat($params, $content, &$smarty)
-{
-    if (is_null($content)) {
-        return;
-    }
-
-    $style = null;
-    $indent = 0;
-    $indent_first = 0;
-    $indent_char = ' ';
-    $wrap = 80;
-    $wrap_char = "\n";
-    $wrap_cut = false;
-    $assign = null;
-    
-    foreach ($params as $_key => $_val) {
-        switch ($_key) {
-            case 'style':
-            case 'indent_char':
-            case 'wrap_char':
-            case 'assign':
-                $$_key = (string)$_val;
-                break;
-
-            case 'indent':
-            case 'indent_first':
-            case 'wrap':
-                $$_key = (int)$_val;
-                break;
-
-            case 'wrap_cut':
-                $$_key = (bool)$_val;
-                break;
-
-            default:
-                $smarty->trigger_error("textformat: unknown attribute '$_key'");
-        }
-    }
-
-    if ($style == 'email') {
-        $wrap = 72;
-    }
-
-    // split into paragraphs
-    $_paragraphs = preg_split('![\r\n][\r\n]!',$content);
-    $_output = '';
-
-    for($_x = 0, $_y = count($_paragraphs); $_x < $_y; $_x++) {
-        if ($_paragraphs[$_x] == '') {
-            continue;
-        }
-        // convert mult. spaces & special chars to single space
-        $_paragraphs[$_x] = preg_replace(array('!\s+!','!(^\s+)|(\s+$)!'), array(' ',''), $_paragraphs[$_x]);
-        // indent first line
-        if($indent_first > 0) {
-            $_paragraphs[$_x] = str_repeat($indent_char, $indent_first) . $_paragraphs[$_x];
-        }
-        // wordwrap sentences
-        $_paragraphs[$_x] = wordwrap($_paragraphs[$_x], $wrap - $indent, $wrap_char, $wrap_cut);
-        // indent lines
-        if($indent > 0) {
-            $_paragraphs[$_x] = preg_replace('!^!m', str_repeat($indent_char, $indent), $_paragraphs[$_x]);
-        }
-    }
-    $_output = implode($wrap_char . $wrap_char, $_paragraphs);
-
-    return $assign ? $smarty->assign($assign, $_output) : $_output;
-
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/compiler.assign.php b/smarty/plugins/compiler.assign.php
deleted file mode 100644 (file)
index be17298..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Smarty {assign} compiler function plugin
- *
- * Type:     compiler function<br>
- * Name:     assign<br>
- * Purpose:  assign a value to a template variable
- * @link http://smarty.php.net/manual/en/language.custom.functions.php#LANGUAGE.FUNCTION.ASSIGN {assign}
- *       (Smarty online manual)
- * @author Monte Ohrt <monte at ohrt dot com> (initial author)
- * @auther messju mohr <messju at lammfellpuschen dot de> (conversion to compiler function)
- * @param string containing var-attribute and value-attribute
- * @param Smarty_Compiler
- */
-function smarty_compiler_assign($tag_attrs, &$compiler)
-{
-    $_params = $compiler->_parse_attrs($tag_attrs);
-
-    if (!isset($_params['var'])) {
-        $compiler->_syntax_error("assign: missing 'var' parameter", E_USER_WARNING);
-        return;
-    }
-
-    if (!isset($_params['value'])) {
-        $compiler->_syntax_error("assign: missing 'value' parameter", E_USER_WARNING);
-        return;
-    }
-
-    return "\$this->assign({$_params['var']}, {$_params['value']});";
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.assign.php b/smarty/plugins/function.assign.php
deleted file mode 100644 (file)
index ad23f04..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Smarty {assign} function plugin
- *
- * Type:     function<br>
- * Name:     assign<br>
- * Purpose:  assign a value to a template variable
- * @link http://smarty.php.net/manual/en/language.custom.functions.php#LANGUAGE.FUNCTION.ASSIGN {assign}
- *       (Smarty online manual)
- * @param array Format: array('var' => variable name, 'value' => value to assign)
- * @param Smarty
- */
-function smarty_function_assign($params, &$smarty)
-{
-    extract($params);
-
-    if (empty($var)) {
-        $smarty->trigger_error("assign: missing 'var' parameter");
-        return;
-    }
-
-    if (!in_array('value', array_keys($params))) {
-        $smarty->trigger_error("assign: missing 'value' parameter");
-        return;
-    }
-
-    $smarty->assign($var, $value);
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.assign_debug_info.php b/smarty/plugins/function.assign_debug_info.php
deleted file mode 100644 (file)
index 6540498..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Smarty {assign_debug_info} function plugin
- *
- * Type:     function<br>
- * Name:     assign_debug_info<br>
- * Purpose:  assign debug info to the template<br>
- * @author Monte Ohrt <monte at ohrt dot com>
- * @param array unused in this plugin, this plugin uses {@link Smarty::$_config},
- *              {@link Smarty::$_tpl_vars} and {@link Smarty::$_smarty_debug_info}
- * @param Smarty
- */
-function smarty_function_assign_debug_info($params, &$smarty)
-{
-    $assigned_vars = $smarty->_tpl_vars;
-    ksort($assigned_vars);
-    if (@is_array($smarty->_config[0])) {
-        $config_vars = $smarty->_config[0];
-        ksort($config_vars);
-        $smarty->assign("_debug_config_keys", array_keys($config_vars));
-        $smarty->assign("_debug_config_vals", array_values($config_vars));
-    }
-    
-    $included_templates = $smarty->_smarty_debug_info;
-    
-    $smarty->assign("_debug_keys", array_keys($assigned_vars));
-    $smarty->assign("_debug_vals", array_values($assigned_vars));
-    
-    $smarty->assign("_debug_tpls", $included_templates);
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.config_load.php b/smarty/plugins/function.config_load.php
deleted file mode 100644 (file)
index db89f63..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Smarty {config_load} function plugin
- *
- * Type:     function<br>
- * Name:     config_load<br>
- * Purpose:  load config file vars
- * @link http://smarty.php.net/manual/en/language.function.config.load.php {config_load}
- *       (Smarty online manual)
- * @author Monte Ohrt <monte at ohrt dot com>
- * @author messju mohr <messju at lammfellpuschen dot de> (added use of resources)
- * @param array Format:
- * <pre>
- * array('file' => required config file name,
- *       'section' => optional config file section to load
- *       'scope' => local/parent/global
- *       'global' => overrides scope, setting to parent if true)
- * </pre>
- * @param Smarty
- */
-function smarty_function_config_load($params, &$smarty)
-{
-        if ($smarty->debugging) {
-            $_params = array();
-            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
-            $_debug_start_time = smarty_core_get_microtime($_params, $smarty);
-        }
-
-        $_file = isset($params['file']) ? $smarty->_dequote($params['file']) : null;
-        $_section = isset($params['section']) ? $smarty->_dequote($params['section']) : null;
-        $_scope = isset($params['scope']) ? $smarty->_dequote($params['scope']) : 'global';
-        $_global = isset($params['global']) ? $smarty->_dequote($params['global']) : false;
-
-        if (!isset($_file) || strlen($_file) == 0) {
-            $smarty->trigger_error("missing 'file' attribute in config_load tag", E_USER_ERROR, __FILE__, __LINE__);
-        }
-
-        if (isset($_scope)) {
-            if ($_scope != 'local' &&
-                $_scope != 'parent' &&
-                $_scope != 'global') {
-                $smarty->trigger_error("invalid 'scope' attribute value", E_USER_ERROR, __FILE__, __LINE__);
-            }
-        } else {
-            if ($_global) {
-                $_scope = 'parent';
-            } else {
-                $_scope = 'local';
-            }
-        }
-
-        $_params = array('resource_name' => $_file,
-                         'resource_base_path' => $smarty->config_dir,
-                         'get_source' => false);
-        $smarty->_parse_resource_name($_params);
-        $_file_path = $_params['resource_type'] . ':' . $_params['resource_name'];
-        if (isset($_section))
-            $_compile_file = $smarty->_get_compile_path($_file_path.'|'.$_section);
-        else
-            $_compile_file = $smarty->_get_compile_path($_file_path);
-
-        if($smarty->force_compile || !file_exists($_compile_file)) {
-            $_compile = true;
-        } elseif ($smarty->compile_check) {
-            $_params = array('resource_name' => $_file,
-                             'resource_base_path' => $smarty->config_dir,
-                             'get_source' => false);
-            $_compile = $smarty->_fetch_resource_info($_params) &&
-                $_params['resource_timestamp'] > filemtime($_compile_file);
-        } else {
-            $_compile = false;
-        }
-
-        if($_compile) {
-            // compile config file
-            if(!is_object($smarty->_conf_obj)) {
-                require_once SMARTY_DIR . $smarty->config_class . '.class.php';
-                $smarty->_conf_obj = new $smarty->config_class();
-                $smarty->_conf_obj->overwrite = $smarty->config_overwrite;
-                $smarty->_conf_obj->booleanize = $smarty->config_booleanize;
-                $smarty->_conf_obj->read_hidden = $smarty->config_read_hidden;
-                $smarty->_conf_obj->fix_newlines = $smarty->config_fix_newlines;
-            }
-
-            $_params = array('resource_name' => $_file,
-                             'resource_base_path' => $smarty->config_dir,
-                             $_params['get_source'] = true);
-            if (!$smarty->_fetch_resource_info($_params)) {
-                return;
-            }
-            $smarty->_conf_obj->set_file_contents($_file, $_params['source_content']);
-            $_config_vars = array_merge($smarty->_conf_obj->get($_file),
-                    $smarty->_conf_obj->get($_file, $_section));
-            if(function_exists('var_export')) {
-                $_output = '<?php $_config_vars = ' . var_export($_config_vars, true) . '; ?>';
-            } else {
-                $_output = '<?php $_config_vars = unserialize(\'' . strtr(serialize($_config_vars),array('\''=>'\\\'', '\\'=>'\\\\')) . '\'); ?>';
-            }
-            $_params = (array('compile_path' => $_compile_file, 'compiled_content' => $_output, 'resource_timestamp' => $_params['resource_timestamp']));
-            require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php');
-            smarty_core_write_compiled_resource($_params, $smarty);
-        } else {
-            include($_compile_file);
-        }
-
-        if ($smarty->caching) {
-            $smarty->_cache_info['config'][$_file] = true;
-        }
-
-        $smarty->_config[0]['vars'] = @array_merge($smarty->_config[0]['vars'], $_config_vars);
-        $smarty->_config[0]['files'][$_file] = true;
-
-        if ($_scope == 'parent') {
-                $smarty->_config[1]['vars'] = @array_merge($smarty->_config[1]['vars'], $_config_vars);
-                $smarty->_config[1]['files'][$_file] = true;
-        } else if ($_scope == 'global') {
-            for ($i = 1, $for_max = count($smarty->_config); $i < $for_max; $i++) {
-                $smarty->_config[$i]['vars'] = @array_merge($smarty->_config[$i]['vars'], $_config_vars);
-                $smarty->_config[$i]['files'][$_file] = true;
-            }
-        }
-
-        if ($smarty->debugging) {
-            $_params = array();
-            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
-            $smarty->_smarty_debug_info[] = array('type'      => 'config',
-                                                'filename'  => $_file.' ['.$_section.'] '.$_scope,
-                                                'depth'     => $smarty->_inclusion_depth,
-                                                'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time);
-        }
-
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.counter.php b/smarty/plugins/function.counter.php
deleted file mode 100644 (file)
index 1f26db5..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty {counter} function plugin
- *
- * Type:     function<br>
- * Name:     counter<br>
- * Purpose:  print out a counter value
- * @author Monte Ohrt <monte at ohrt dot com>
- * @link http://smarty.php.net/manual/en/language.function.counter.php {counter}
- *       (Smarty online manual)
- * @param array parameters
- * @param Smarty
- * @return string|null
- */
-function smarty_function_counter($params, &$smarty)
-{
-    static $counters = array();
-
-    $name = (isset($params['name'])) ? $params['name'] : 'default';
-    if (!isset($counters[$name])) {
-        $counters[$name] = array(
-            'start'=>1,
-            'skip'=>1,
-            'direction'=>'up',
-            'count'=>1
-            );
-    }
-    $counter =& $counters[$name];
-
-    if (isset($params['start'])) {
-        $counter['start'] = $counter['count'] = (int)$params['start'];
-    }
-
-    if (!empty($params['assign'])) {
-        $counter['assign'] = $params['assign'];
-    }
-
-    if (isset($counter['assign'])) {
-        $smarty->assign($counter['assign'], $counter['count']);
-    }
-    
-    if (isset($params['print'])) {
-        $print = (bool)$params['print'];
-    } else {
-        $print = empty($counter['assign']);
-    }
-
-    if ($print) {
-        $retval = $counter['count'];
-    } else {
-        $retval = null;
-    }
-
-    if (isset($params['skip'])) {
-        $counter['skip'] = $params['skip'];
-    }
-    
-    if (isset($params['direction'])) {
-        $counter['direction'] = $params['direction'];
-    }
-
-    if ($counter['direction'] == "down")
-        $counter['count'] -= $counter['skip'];
-    else
-        $counter['count'] += $counter['skip'];
-    
-    return $retval;
-    
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.cycle.php b/smarty/plugins/function.cycle.php
deleted file mode 100644 (file)
index fe78bb8..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Smarty {cycle} function plugin
- *
- * Type:     function<br>
- * Name:     cycle<br>
- * Date:     May 3, 2002<br>
- * Purpose:  cycle through given values<br>
- * Input:
- *         - name = name of cycle (optional)
- *         - values = comma separated list of values to cycle,
- *                    or an array of values to cycle
- *                    (this can be left out for subsequent calls)
- *         - reset = boolean - resets given var to true
- *         - print = boolean - print var or not. default is true
- *         - advance = boolean - whether or not to advance the cycle
- *         - delimiter = the value delimiter, default is ","
- *         - assign = boolean, assigns to template var instead of
- *                    printed.
- *
- * Examples:<br>
- * <pre>
- * {cycle values="#eeeeee,#d0d0d0d"}
- * {cycle name=row values="one,two,three" reset=true}
- * {cycle name=row}
- * </pre>
- * @link http://smarty.php.net/manual/en/language.function.cycle.php {cycle}
- *       (Smarty online manual)
- * @author Monte Ohrt <monte at ohrt dot com>
- * @author credit to Mark Priatel <mpriatel@rogers.com>
- * @author credit to Gerard <gerard@interfold.com>
- * @author credit to Jason Sweat <jsweat_php@yahoo.com>
- * @version  1.3
- * @param array
- * @param Smarty
- * @return string|null
- */
-function smarty_function_cycle($params, &$smarty)
-{
-    static $cycle_vars;
-    
-    $name = (empty($params['name'])) ? 'default' : $params['name'];
-    $print = (isset($params['print'])) ? (bool)$params['print'] : true;
-    $advance = (isset($params['advance'])) ? (bool)$params['advance'] : true;
-    $reset = (isset($params['reset'])) ? (bool)$params['reset'] : false;
-            
-    if (!in_array('values', array_keys($params))) {
-        if(!isset($cycle_vars[$name]['values'])) {
-            $smarty->trigger_error("cycle: missing 'values' parameter");
-            return;
-        }
-    } else {
-        if(isset($cycle_vars[$name]['values'])
-            && $cycle_vars[$name]['values'] != $params['values'] ) {
-            $cycle_vars[$name]['index'] = 0;
-        }
-        $cycle_vars[$name]['values'] = $params['values'];
-    }
-
-    $cycle_vars[$name]['delimiter'] = (isset($params['delimiter'])) ? $params['delimiter'] : ',';
-    
-    if(is_array($cycle_vars[$name]['values'])) {
-        $cycle_array = $cycle_vars[$name]['values'];
-    } else {
-        $cycle_array = explode($cycle_vars[$name]['delimiter'],$cycle_vars[$name]['values']);
-    }
-    
-    if(!isset($cycle_vars[$name]['index']) || $reset ) {
-        $cycle_vars[$name]['index'] = 0;
-    }
-    
-    if (isset($params['assign'])) {
-        $print = false;
-        $smarty->assign($params['assign'], $cycle_array[$cycle_vars[$name]['index']]);
-    }
-        
-    if($print) {
-        $retval = $cycle_array[$cycle_vars[$name]['index']];
-    } else {
-        $retval = null;
-    }
-
-    if($advance) {
-        if ( $cycle_vars[$name]['index'] >= count($cycle_array) -1 ) {
-            $cycle_vars[$name]['index'] = 0;
-        } else {
-            $cycle_vars[$name]['index']++;
-        }
-    }
-    
-    return $retval;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.debug.php b/smarty/plugins/function.debug.php
deleted file mode 100644 (file)
index 4345230..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty {debug} function plugin
- *
- * Type:     function<br>
- * Name:     debug<br>
- * Date:     July 1, 2002<br>
- * Purpose:  popup debug window
- * @link http://smarty.php.net/manual/en/language.function.debug.php {debug}
- *       (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @version  1.0
- * @param array
- * @param Smarty
- * @return string output from {@link Smarty::_generate_debug_output()}
- */
-function smarty_function_debug($params, &$smarty)
-{
-    if (isset($params['output'])) {
-        $smarty->assign('_smarty_debug_output', $params['output']);
-    }
-    require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php');
-    return smarty_core_display_debug_console(null, $smarty);
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.eval.php b/smarty/plugins/function.eval.php
deleted file mode 100644 (file)
index ff0472d..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty {eval} function plugin
- *
- * Type:     function<br>
- * Name:     eval<br>
- * Purpose:  evaluate a template variable as a template<br>
- * @link http://smarty.php.net/manual/en/language.function.eval.php {eval}
- *       (Smarty online manual)
- * @author Monte Ohrt <monte at ohrt dot com>
- * @param array
- * @param Smarty
- */
-function smarty_function_eval($params, &$smarty)
-{
-
-    if (!isset($params['var'])) {
-        $smarty->trigger_error("eval: missing 'var' parameter");
-        return;
-    }
-
-    if($params['var'] == '') {
-        return;
-    }
-
-    $smarty->_compile_source('evaluated template', $params['var'], $_var_compiled);
-
-    ob_start();
-    $smarty->_eval('?>' . $_var_compiled);
-    $_contents = ob_get_contents();
-    ob_end_clean();
-
-    if (!empty($params['assign'])) {
-        $smarty->assign($params['assign'], $_contents);
-    } else {
-        return $_contents;
-    }
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.fetch.php b/smarty/plugins/function.fetch.php
deleted file mode 100644 (file)
index 81b1bfc..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty {fetch} plugin
- *
- * Type:     function<br>
- * Name:     fetch<br>
- * Purpose:  fetch file, web or ftp data and display results
- * @link http://smarty.php.net/manual/en/language.function.fetch.php {fetch}
- *       (Smarty online manual)
- * @author Monte Ohrt <monte at ohrt dot com>
- * @param array
- * @param Smarty
- * @return string|null if the assign parameter is passed, Smarty assigns the
- *                     result to a template variable
- */
-function smarty_function_fetch($params, &$smarty)
-{
-    if (empty($params['file'])) {
-        $smarty->_trigger_fatal_error("[plugin] parameter 'file' cannot be empty");
-        return;
-    }
-
-    $content = '';
-    if ($smarty->security && !preg_match('!^(http|ftp)://!i', $params['file'])) {
-        $_params = array('resource_type' => 'file', 'resource_name' => $params['file']);
-        require_once(SMARTY_CORE_DIR . 'core.is_secure.php');
-        if(!smarty_core_is_secure($_params, $smarty)) {
-            $smarty->_trigger_fatal_error('[plugin] (secure mode) fetch \'' . $params['file'] . '\' is not allowed');
-            return;
-        }
-        
-        // fetch the file
-        if($fp = @fopen($params['file'],'r')) {
-            while(!feof($fp)) {
-                $content .= fgets ($fp,4096);
-            }
-            fclose($fp);
-        } else {
-            $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] . '\'');
-            return;
-        }
-    } else {
-        // not a local file
-        if(preg_match('!^http://!i',$params['file'])) {
-            // http fetch
-            if($uri_parts = parse_url($params['file'])) {
-                // set defaults
-                $host = $server_name = $uri_parts['host'];
-                $timeout = 30;
-                $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*";
-                $agent = "Smarty Template Engine ".$smarty->_version;
-                $referer = "";
-                $uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/';
-                $uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : '';
-                $_is_proxy = false;
-                if(empty($uri_parts['port'])) {
-                    $port = 80;
-                } else {
-                    $port = $uri_parts['port'];
-                }
-                if(!empty($uri_parts['user'])) {
-                    $user = $uri_parts['user'];
-                }
-                if(!empty($uri_parts['pass'])) {
-                    $pass = $uri_parts['pass'];
-                }
-                // loop through parameters, setup headers
-                foreach($params as $param_key => $param_value) {
-                    switch($param_key) {
-                        case "file":
-                        case "assign":
-                        case "assign_headers":
-                            break;
-                        case "user":
-                            if(!empty($param_value)) {
-                                $user = $param_value;
-                            }
-                            break;
-                        case "pass":
-                            if(!empty($param_value)) {
-                                $pass = $param_value;
-                            }
-                            break;
-                        case "accept":
-                            if(!empty($param_value)) {
-                                $accept = $param_value;
-                            }
-                            break;
-                        case "header":
-                            if(!empty($param_value)) {
-                                if(!preg_match('![\w\d-]+: .+!',$param_value)) {
-                                    $smarty->_trigger_fatal_error("[plugin] invalid header format '".$param_value."'");
-                                    return;
-                                } else {
-                                    $extra_headers[] = $param_value;
-                                }
-                            }
-                            break;
-                        case "proxy_host":
-                            if(!empty($param_value)) {
-                                $proxy_host = $param_value;
-                            }
-                            break;
-                        case "proxy_port":
-                            if(!preg_match('!\D!', $param_value)) {
-                                $proxy_port = (int) $param_value;
-                            } else {
-                                $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'");
-                                return;
-                            }
-                            break;
-                        case "agent":
-                            if(!empty($param_value)) {
-                                $agent = $param_value;
-                            }
-                            break;
-                        case "referer":
-                            if(!empty($param_value)) {
-                                $referer = $param_value;
-                            }
-                            break;
-                        case "timeout":
-                            if(!preg_match('!\D!', $param_value)) {
-                                $timeout = (int) $param_value;
-                            } else {
-                                $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'");
-                                return;
-                            }
-                            break;
-                        default:
-                            $smarty->_trigger_fatal_error("[plugin] unrecognized attribute '".$param_key."'");
-                            return;
-                    }
-                }
-                if(!empty($proxy_host) && !empty($proxy_port)) {
-                    $_is_proxy = true;
-                    $fp = fsockopen($proxy_host,$proxy_port,$errno,$errstr,$timeout);
-                } else {
-                    $fp = fsockopen($server_name,$port,$errno,$errstr,$timeout);
-                }
-
-                if(!$fp) {
-                    $smarty->_trigger_fatal_error("[plugin] unable to fetch: $errstr ($errno)");
-                    return;
-                } else {
-                    if($_is_proxy) {
-                        fputs($fp, 'GET ' . $params['file'] . " HTTP/1.0\r\n");
-                    } else {
-                        fputs($fp, "GET $uri HTTP/1.0\r\n");
-                    }
-                    if(!empty($host)) {
-                        fputs($fp, "Host: $host\r\n");
-                    }
-                    if(!empty($accept)) {
-                        fputs($fp, "Accept: $accept\r\n");
-                    }
-                    if(!empty($agent)) {
-                        fputs($fp, "User-Agent: $agent\r\n");
-                    }
-                    if(!empty($referer)) {
-                        fputs($fp, "Referer: $referer\r\n");
-                    }
-                    if(isset($extra_headers) && is_array($extra_headers)) {
-                        foreach($extra_headers as $curr_header) {
-                            fputs($fp, $curr_header."\r\n");
-                        }
-                    }
-                    if(!empty($user) && !empty($pass)) {
-                        fputs($fp, "Authorization: BASIC ".base64_encode("$user:$pass")."\r\n");
-                    }
-
-                    fputs($fp, "\r\n");
-                    while(!feof($fp)) {
-                        $content .= fgets($fp,4096);
-                    }
-                    fclose($fp);
-                    $csplit = split("\r\n\r\n",$content,2);
-
-                    $content = $csplit[1];
-
-                    if(!empty($params['assign_headers'])) {
-                        $smarty->assign($params['assign_headers'],split("\r\n",$csplit[0]));
-                    }
-                }
-            } else {
-                $smarty->_trigger_fatal_error("[plugin] unable to parse URL, check syntax");
-                return;
-            }
-        } else {
-            // ftp fetch
-            if($fp = @fopen($params['file'],'r')) {
-                while(!feof($fp)) {
-                    $content .= fgets ($fp,4096);
-                }
-                fclose($fp);
-            } else {
-                $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] .'\'');
-                return;
-            }
-        }
-
-    }
-
-
-    if (!empty($params['assign'])) {
-        $smarty->assign($params['assign'],$content);
-    } else {
-        return $content;
-    }
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.html_checkboxes.php b/smarty/plugins/function.html_checkboxes.php
deleted file mode 100644 (file)
index ed8ad7f..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty {html_checkboxes} function plugin
- *
- * File:       function.html_checkboxes.php<br>
- * Type:       function<br>
- * Name:       html_checkboxes<br>
- * Date:       24.Feb.2003<br>
- * Purpose:    Prints out a list of checkbox input types<br>
- * Input:<br>
- *           - name       (optional) - string default "checkbox"
- *           - values     (required) - array
- *           - options    (optional) - associative array
- *           - checked    (optional) - array default not set
- *           - separator  (optional) - ie <br> or &nbsp;
- *           - output     (optional) - the output next to each checkbox
- *           - assign     (optional) - assign the output as an array to this variable
- * Examples:
- * <pre>
- * {html_checkboxes values=$ids output=$names}
- * {html_checkboxes values=$ids name='box' separator='<br>' output=$names}
- * {html_checkboxes values=$ids checked=$checked separator='<br>' output=$names}
- * </pre>
- * @link http://smarty.php.net/manual/en/language.function.html.checkboxes.php {html_checkboxes}
- *      (Smarty online manual)
- * @author     Christopher Kvarme <christopher.kvarme@flashjab.com>
- * @author credits to Monte Ohrt <monte at ohrt dot com>
- * @version    1.0
- * @param array
- * @param Smarty
- * @return string
- * @uses smarty_function_escape_special_chars()
- */
-function smarty_function_html_checkboxes($params, &$smarty)
-{
-    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
-
-    $name = 'checkbox';
-    $values = null;
-    $options = null;
-    $selected = null;
-    $separator = '';
-    $labels = true;
-    $output = null;
-
-    $extra = '';
-
-    foreach($params as $_key => $_val) {
-        switch($_key) {
-            case 'name':
-            case 'separator':
-                $$_key = $_val;
-                break;
-
-            case 'labels':
-                $$_key = (bool)$_val;
-                break;
-
-            case 'options':
-                $$_key = (array)$_val;
-                break;
-
-            case 'values':
-            case 'output':
-                $$_key = array_values((array)$_val);
-                break;
-
-            case 'checked':
-            case 'selected':
-                $selected = array_map('strval', array_values((array)$_val));
-                break;
-
-            case 'checkboxes':
-                $smarty->trigger_error('html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', E_USER_WARNING);
-                $options = (array)$_val;
-                break;
-
-            case 'assign':
-                break;
-
-            default:
-                if(!is_array($_val)) {
-                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
-                } else {
-                    $smarty->trigger_error("html_checkboxes: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
-                }
-                break;
-        }
-    }
-
-    if (!isset($options) && !isset($values))
-        return ''; /* raise error here? */
-
-    settype($selected, 'array');
-    $_html_result = array();
-
-    if (isset($options)) {
-
-        foreach ($options as $_key=>$_val)
-            $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
-
-
-    } else {
-        foreach ($values as $_i=>$_key) {
-            $_val = isset($output[$_i]) ? $output[$_i] : '';
-            $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
-        }
-
-    }
-
-    if(!empty($params['assign'])) {
-        $smarty->assign($params['assign'], $_html_result);
-    } else {
-        return implode("\n",$_html_result);
-    }
-
-}
-
-function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels) {
-    $_output = '';
-    if ($labels) $_output .= '<label>';
-    $_output .= '<input type="checkbox" name="'
-        . smarty_function_escape_special_chars($name) . '[]" value="'
-        . smarty_function_escape_special_chars($value) . '"';
-
-    if (in_array((string)$value, $selected)) {
-        $_output .= ' checked="checked"';
-    }
-    $_output .= $extra . ' />' . $output;
-    if ($labels) $_output .= '</label>';
-    $_output .=  $separator;
-
-    return $_output;
-}
-
-?>
diff --git a/smarty/plugins/function.html_image.php b/smarty/plugins/function.html_image.php
deleted file mode 100644 (file)
index 9abae72..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty {html_image} function plugin
- *
- * Type:     function<br>
- * Name:     html_image<br>
- * Date:     Feb 24, 2003<br>
- * Purpose:  format HTML tags for the image<br>
- * Input:<br>
- *         - file = file (and path) of image (required)
- *         - height = image height (optional, default actual height)
- *         - width = image width (optional, default actual width)
- *         - basedir = base directory for absolute paths, default
- *                     is environment variable DOCUMENT_ROOT
- *         - path_prefix = prefix for path output (optional, default empty)
- *
- * Examples: {html_image file="/images/masthead.gif"}
- * Output:   <img src="/images/masthead.gif" width=400 height=23>
- * @link http://smarty.php.net/manual/en/language.function.html.image.php {html_image}
- *      (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @author credits to Duda <duda@big.hu> - wrote first image function
- *           in repository, helped with lots of functionality
- * @version  1.0
- * @param array
- * @param Smarty
- * @return string
- * @uses smarty_function_escape_special_chars()
- */
-function smarty_function_html_image($params, &$smarty)
-{
-    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
-    
-    $alt = '';
-    $file = '';
-    $height = '';
-    $width = '';
-    $extra = '';
-    $prefix = '';
-    $suffix = '';
-    $path_prefix = '';
-    $server_vars = ($smarty->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
-    $basedir = isset($server_vars['DOCUMENT_ROOT']) ? $server_vars['DOCUMENT_ROOT'] : '';
-    foreach($params as $_key => $_val) {
-        switch($_key) {
-            case 'file':
-            case 'height':
-            case 'width':
-            case 'dpi':
-            case 'path_prefix':
-            case 'basedir':
-                $$_key = $_val;
-                break;
-
-            case 'alt':
-                if(!is_array($_val)) {
-                    $$_key = smarty_function_escape_special_chars($_val);
-                } else {
-                    $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
-                }
-                break;
-
-            case 'link':
-            case 'href':
-                $prefix = '<a href="' . $_val . '">';
-                $suffix = '</a>';
-                break;
-
-            default:
-                if(!is_array($_val)) {
-                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
-                } else {
-                    $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
-                }
-                break;
-        }
-    }
-
-    if (empty($file)) {
-        $smarty->trigger_error("html_image: missing 'file' parameter", E_USER_NOTICE);
-        return;
-    }
-
-    if (substr($file,0,1) == '/') {
-        $_image_path = $basedir . $file;
-    } else {
-        $_image_path = $file;
-    }
-    
-    if(!isset($params['width']) || !isset($params['height'])) {
-        if(!$_image_data = @getimagesize($_image_path)) {
-            if(!file_exists($_image_path)) {
-                $smarty->trigger_error("html_image: unable to find '$_image_path'", E_USER_NOTICE);
-                return;
-            } else if(!is_readable($_image_path)) {
-                $smarty->trigger_error("html_image: unable to read '$_image_path'", E_USER_NOTICE);
-                return;
-            } else {
-                $smarty->trigger_error("html_image: '$_image_path' is not a valid image file", E_USER_NOTICE);
-                return;
-            }
-        }
-        if ($smarty->security &&
-            ($_params = array('resource_type' => 'file', 'resource_name' => $_image_path)) &&
-            (require_once(SMARTY_CORE_DIR . 'core.is_secure.php')) &&
-            (!smarty_core_is_secure($_params, $smarty)) ) {
-            $smarty->trigger_error("html_image: (secure) '$_image_path' not in secure directory", E_USER_NOTICE);
-        }        
-        
-        if(!isset($params['width'])) {
-            $width = $_image_data[0];
-        }
-        if(!isset($params['height'])) {
-            $height = $_image_data[1];
-        }
-
-    }
-
-    if(isset($params['dpi'])) {
-        if(strstr($server_vars['HTTP_USER_AGENT'], 'Mac')) {
-            $dpi_default = 72;
-        } else {
-            $dpi_default = 96;
-        }
-        $_resize = $dpi_default/$params['dpi'];
-        $width = round($width * $_resize);
-        $height = round($height * $_resize);
-    }
-
-    return $prefix . '<img src="'.$path_prefix.$file.'" alt="'.$alt.'" width="'.$width.'" height="'.$height.'"'.$extra.' />' . $suffix;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.html_options.php b/smarty/plugins/function.html_options.php
deleted file mode 100644 (file)
index cebadde..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty {html_options} function plugin
- *
- * Type:     function<br>
- * Name:     html_options<br>
- * Input:<br>
- *           - name       (optional) - string default "select"
- *           - values     (required if no options supplied) - array
- *           - options    (required if no values supplied) - associative array
- *           - selected   (optional) - string default not set
- *           - output     (required if not options supplied) - array
- * Purpose:  Prints the list of <option> tags generated from
- *           the passed parameters
- * @link http://smarty.php.net/manual/en/language.function.html.options.php {html_image}
- *      (Smarty online manual)
- * @author Monte Ohrt <monte at ohrt dot com>
- * @param array
- * @param Smarty
- * @return string
- * @uses smarty_function_escape_special_chars()
- */
-function smarty_function_html_options($params, &$smarty)
-{
-    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
-    
-    $name = null;
-    $values = null;
-    $options = null;
-    $selected = array();
-    $output = null;
-    
-    $extra = '';
-    
-    foreach($params as $_key => $_val) {
-        switch($_key) {
-            case 'name':
-                $$_key = (string)$_val;
-                break;
-            
-            case 'options':
-                $$_key = (array)$_val;
-                break;
-                
-            case 'values':
-            case 'output':
-                $$_key = array_values((array)$_val);
-                break;
-
-            case 'selected':
-                $$_key = array_map('strval', array_values((array)$_val));
-                break;
-                
-            default:
-                if(!is_array($_val)) {
-                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
-                } else {
-                    $smarty->trigger_error("html_options: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
-                }
-                break;
-        }
-    }
-
-    if (!isset($options) && !isset($values))
-        return ''; /* raise error here? */
-
-    $_html_result = '';
-
-    if (isset($options)) {
-        
-        foreach ($options as $_key=>$_val)
-            $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected);
-
-    } else {
-        
-        foreach ($values as $_i=>$_key) {
-            $_val = isset($output[$_i]) ? $output[$_i] : '';
-            $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected);
-        }
-
-    }
-
-    if(!empty($name)) {
-        $_html_result = '<select name="' . $name . '"' . $extra . '>' . "\n" . $_html_result . '</select>' . "\n";
-    }
-
-    return $_html_result;
-
-}
-
-function smarty_function_html_options_optoutput($key, $value, $selected) {
-    if(!is_array($value)) {
-        $_html_result = '<option label="' . smarty_function_escape_special_chars($value) . '" value="' .
-            smarty_function_escape_special_chars($key) . '"';
-        if (in_array((string)$key, $selected))
-            $_html_result .= ' selected="selected"';
-        $_html_result .= '>' . smarty_function_escape_special_chars($value) . '</option>' . "\n";
-    } else {
-        $_html_result = smarty_function_html_options_optgroup($key, $value, $selected);
-    }
-    return $_html_result;
-}
-
-function smarty_function_html_options_optgroup($key, $values, $selected) {
-    $optgroup_html = '<optgroup label="' . smarty_function_escape_special_chars($key) . '">' . "\n";
-    foreach ($values as $key => $value) {
-        $optgroup_html .= smarty_function_html_options_optoutput($key, $value, $selected);
-    }
-    $optgroup_html .= "</optgroup>\n";
-    return $optgroup_html;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.html_radios.php b/smarty/plugins/function.html_radios.php
deleted file mode 100644 (file)
index 7503cfa..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty {html_radios} function plugin
- *
- * File:       function.html_radios.php<br>
- * Type:       function<br>
- * Name:       html_radios<br>
- * Date:       24.Feb.2003<br>
- * Purpose:    Prints out a list of radio input types<br>
- * Input:<br>
- *           - name       (optional) - string default "radio"
- *           - values     (required) - array
- *           - options    (optional) - associative array
- *           - checked    (optional) - array default not set
- *           - separator  (optional) - ie <br> or &nbsp;
- *           - output     (optional) - the output next to each radio button
- *           - assign     (optional) - assign the output as an array to this variable
- * Examples:
- * <pre>
- * {html_radios values=$ids output=$names}
- * {html_radios values=$ids name='box' separator='<br>' output=$names}
- * {html_radios values=$ids checked=$checked separator='<br>' output=$names}
- * </pre>
- * @link http://smarty.php.net/manual/en/language.function.html.radios.php {html_radios}
- *      (Smarty online manual)
- * @author     Christopher Kvarme <christopher.kvarme@flashjab.com>
- * @author credits to Monte Ohrt <monte at ohrt dot com>
- * @version    1.0
- * @param array
- * @param Smarty
- * @return string
- * @uses smarty_function_escape_special_chars()
- */
-function smarty_function_html_radios($params, &$smarty)
-{
-    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
-   
-    $name = 'radio';
-    $values = null;
-    $options = null;
-    $selected = null;
-    $separator = '';
-    $labels = true;
-    $label_ids = false;
-    $output = null;
-    $extra = '';
-
-    foreach($params as $_key => $_val) {
-        switch($_key) {
-            case 'name':
-            case 'separator':
-                $$_key = (string)$_val;
-                break;
-
-            case 'checked':
-            case 'selected':
-                if(is_array($_val)) {
-                    $smarty->trigger_error('html_radios: the "' . $_key . '" attribute cannot be an array', E_USER_WARNING);
-                } else {
-                    $selected = (string)$_val;
-                }
-                break;
-
-            case 'labels':
-            case 'label_ids':
-                $$_key = (bool)$_val;
-                break;
-
-            case 'options':
-                $$_key = (array)$_val;
-                break;
-
-            case 'values':
-            case 'output':
-                $$_key = array_values((array)$_val);
-                break;
-
-            case 'radios':
-                $smarty->trigger_error('html_radios: the use of the "radios" attribute is deprecated, use "options" instead', E_USER_WARNING);
-                $options = (array)$_val;
-                break;
-
-            case 'assign':
-                break;
-
-            default:
-                if(!is_array($_val)) {
-                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
-                } else {
-                    $smarty->trigger_error("html_radios: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
-                }
-                break;
-        }
-    }
-
-    if (!isset($options) && !isset($values))
-        return ''; /* raise error here? */
-
-    $_html_result = array();
-
-    if (isset($options)) {
-
-        foreach ($options as $_key=>$_val)
-            $_html_result[] = smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids);
-
-    } else {
-
-        foreach ($values as $_i=>$_key) {
-            $_val = isset($output[$_i]) ? $output[$_i] : '';
-            $_html_result[] = smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids);
-        }
-
-    }
-
-    if(!empty($params['assign'])) {
-        $smarty->assign($params['assign'], $_html_result);
-    } else {
-        return implode("\n",$_html_result);
-    }
-
-}
-
-function smarty_function_html_radios_output($name, $value, $output, $selected, $extra, $separator, $labels, $label_ids) {
-    $_output = '';
-    if ($labels) {
-      if($label_ids) {
-          $_id = smarty_function_escape_special_chars(preg_replace('![^\w\-\.]!', '_', $name . '_' . $value));
-          $_output .= '<label for="' . $_id . '">';
-      } else {
-          $_output .= '<label>';           
-      }
-   }
-   $_output .= '<input type="radio" name="'
-        . smarty_function_escape_special_chars($name) . '" value="'
-        . smarty_function_escape_special_chars($value) . '"';
-
-   if ($labels && $label_ids) $_output .= ' id="' . $_id . '"';
-
-    if ((string)$value==$selected) {
-        $_output .= ' checked="checked"';
-    }
-    $_output .= $extra . ' />' . $output;
-    if ($labels) $_output .= '</label>';
-    $_output .=  $separator;
-
-    return $_output;
-}
-
-?>
diff --git a/smarty/plugins/function.html_select_date.php b/smarty/plugins/function.html_select_date.php
deleted file mode 100644 (file)
index e5eb183..0000000
+++ /dev/null
@@ -1,331 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Smarty {html_select_date} plugin
- *
- * Type:     function<br>
- * Name:     html_select_date<br>
- * Purpose:  Prints the dropdowns for date selection.
- *
- * ChangeLog:<br>
- *           - 1.0 initial release
- *           - 1.1 added support for +/- N syntax for begin
- *                and end year values. (Monte)
- *           - 1.2 added support for yyyy-mm-dd syntax for
- *                time value. (Jan Rosier)
- *           - 1.3 added support for choosing format for
- *                month values (Gary Loescher)
- *           - 1.3.1 added support for choosing format for
- *                day values (Marcus Bointon)
- *           - 1.3.2 support negative timestamps, force year
- *             dropdown to include given date unless explicitly set (Monte)
- *           - 1.3.4 fix behaviour of 0000-00-00 00:00:00 dates to match that
- *             of 0000-00-00 dates (cybot, boots)
- * @link http://smarty.php.net/manual/en/language.function.html.select.date.php {html_select_date}
- *      (Smarty online manual)
- * @version 1.3.4
- * @author Andrei Zmievski
- * @author Monte Ohrt <monte at ohrt dot com>
- * @param array
- * @param Smarty
- * @return string
- */
-function smarty_function_html_select_date($params, &$smarty)
-{
-    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
-    require_once $smarty->_get_plugin_filepath('shared','make_timestamp');
-    require_once $smarty->_get_plugin_filepath('function','html_options');
-    /* Default values. */
-    $prefix          = "Date_";
-    $start_year      = strftime("%Y");
-    $end_year        = $start_year;
-    $display_days    = true;
-    $display_months  = true;
-    $display_years   = true;
-    $month_format    = "%B";
-    /* Write months as numbers by default  GL */
-    $month_value_format = "%m";
-    $day_format      = "%02d";
-    /* Write day values using this format MB */
-    $day_value_format = "%d";
-    $year_as_text    = false;
-    /* Display years in reverse order? Ie. 2000,1999,.... */
-    $reverse_years   = false;
-    /* Should the select boxes be part of an array when returned from PHP?
-       e.g. setting it to "birthday", would create "birthday[Day]",
-       "birthday[Month]" & "birthday[Year]". Can be combined with prefix */
-    $field_array     = null;
-    /* <select size>'s of the different <select> tags.
-       If not set, uses default dropdown. */
-    $day_size        = null;
-    $month_size      = null;
-    $year_size       = null;
-    /* Unparsed attributes common to *ALL* the <select>/<input> tags.
-       An example might be in the template: all_extra ='class ="foo"'. */
-    $all_extra       = null;
-    /* Separate attributes for the tags. */
-    $day_extra       = null;
-    $month_extra     = null;
-    $year_extra      = null;
-    /* Order in which to display the fields.
-       "D" -> day, "M" -> month, "Y" -> year. */
-    $field_order     = 'MDY';
-    /* String printed between the different fields. */
-    $field_separator = "\n";
-    $time = time();
-    $all_empty       = null;
-    $day_empty       = null;
-    $month_empty     = null;
-    $year_empty      = null;
-    $extra_attrs     = '';
-
-    foreach ($params as $_key=>$_value) {
-        switch ($_key) {
-            case 'prefix':
-            case 'time':
-            case 'start_year':
-            case 'end_year':
-            case 'month_format':
-            case 'day_format':
-            case 'day_value_format':
-            case 'field_array':
-            case 'day_size':
-            case 'month_size':
-            case 'year_size':
-            case 'all_extra':
-            case 'day_extra':
-            case 'month_extra':
-            case 'year_extra':
-            case 'field_order':
-            case 'field_separator':
-            case 'month_value_format':
-            case 'month_empty':
-            case 'day_empty':
-            case 'year_empty':
-                $$_key = (string)$_value;
-                break;
-
-            case 'all_empty':
-                $$_key = (string)$_value;
-                $day_empty = $month_empty = $year_empty = $all_empty;
-                break;
-
-            case 'display_days':
-            case 'display_months':
-            case 'display_years':
-            case 'year_as_text':
-            case 'reverse_years':
-                $$_key = (bool)$_value;
-                break;
-
-            default:
-                if(!is_array($_value)) {
-                    $extra_attrs .= ' '.$_key.'="'.smarty_function_escape_special_chars($_value).'"';
-                } else {
-                    $smarty->trigger_error("html_select_date: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
-                }
-                break;
-        }
-    }
-
-    if (preg_match('!^-\d+$!', $time)) {
-        // negative timestamp, use date()
-        $time = date('Y-m-d', $time);
-    }
-    // If $time is not in format yyyy-mm-dd
-    if (preg_match('/^(\d{0,4}-\d{0,2}-\d{0,2})/', $time, $found)) {
-        $time = $found[1];
-    } else {
-        // use smarty_make_timestamp to get an unix timestamp and
-        // strftime to make yyyy-mm-dd
-        $time = strftime('%Y-%m-%d', smarty_make_timestamp($time));
-    }
-    // Now split this in pieces, which later can be used to set the select
-    $time = explode("-", $time);
-
-    // make syntax "+N" or "-N" work with start_year and end_year
-    if (preg_match('!^(\+|\-)\s*(\d+)$!', $end_year, $match)) {
-        if ($match[1] == '+') {
-            $end_year = strftime('%Y') + $match[2];
-        } else {
-            $end_year = strftime('%Y') - $match[2];
-        }
-    }
-    if (preg_match('!^(\+|\-)\s*(\d+)$!', $start_year, $match)) {
-        if ($match[1] == '+') {
-            $start_year = strftime('%Y') + $match[2];
-        } else {
-            $start_year = strftime('%Y') - $match[2];
-        }
-    }
-    if (strlen($time[0]) > 0) {
-        if ($start_year > $time[0] && !isset($params['start_year'])) {
-            // force start year to include given date if not explicitly set
-            $start_year = $time[0];
-        }
-        if($end_year < $time[0] && !isset($params['end_year'])) {
-            // force end year to include given date if not explicitly set
-            $end_year = $time[0];
-        }
-    }
-
-    $field_order = strtoupper($field_order);
-
-    $html_result = $month_result = $day_result = $year_result = "";
-
-    $field_separator_count = -1;
-    if ($display_months) {
-       $field_separator_count++;
-        $month_names = array();
-        $month_values = array();
-        if(isset($month_empty)) {
-            $month_names[''] = $month_empty;
-            $month_values[''] = '';
-        }
-        for ($i = 1; $i <= 12; $i++) {
-            $month_names[$i] = strftime($month_format, mktime(0, 0, 0, $i, 1, 2000));
-            $month_values[$i] = strftime($month_value_format, mktime(0, 0, 0, $i, 1, 2000));
-        }
-
-        $month_result .= '<select name=';
-        if (null !== $field_array){
-            $month_result .= '"' . $field_array . '[' . $prefix . 'Month]"';
-        } else {
-            $month_result .= '"' . $prefix . 'Month"';
-        }
-        if (null !== $month_size){
-            $month_result .= ' size="' . $month_size . '"';
-        }
-        if (null !== $month_extra){
-            $month_result .= ' ' . $month_extra;
-        }
-        if (null !== $all_extra){
-            $month_result .= ' ' . $all_extra;
-        }
-        $month_result .= $extra_attrs . '>'."\n";
-
-        $month_result .= smarty_function_html_options(array('output'     => $month_names,
-                                                            'values'     => $month_values,
-                                                            'selected'   => (int)$time[1] ? strftime($month_value_format, mktime(0, 0, 0, (int)$time[1], 1, 2000)) : '',
-                                                            'print_result' => false),
-                                                      $smarty);
-        $month_result .= '</select>';
-    }
-
-    if ($display_days) {
-       $field_separator_count++;
-        $days = array();
-        if (isset($day_empty)) {
-            $days[''] = $day_empty;
-            $day_values[''] = '';
-        }
-        for ($i = 1; $i <= 31; $i++) {
-            $days[] = sprintf($day_format, $i);
-            $day_values[] = sprintf($day_value_format, $i);
-        }
-
-        $day_result .= '<select name=';
-        if (null !== $field_array){
-            $day_result .= '"' . $field_array . '[' . $prefix . 'Day]"';
-        } else {
-            $day_result .= '"' . $prefix . 'Day"';
-        }
-        if (null !== $day_size){
-            $day_result .= ' size="' . $day_size . '"';
-        }
-        if (null !== $all_extra){
-            $day_result .= ' ' . $all_extra;
-        }
-        if (null !== $day_extra){
-            $day_result .= ' ' . $day_extra;
-        }
-        $day_result .= $extra_attrs . '>'."\n";
-        $day_result .= smarty_function_html_options(array('output'     => $days,
-                                                          'values'     => $day_values,
-                                                          'selected'   => $time[2],
-                                                          'print_result' => false),
-                                                    $smarty);
-        $day_result .= '</select>';
-    }
-
-    if ($display_years) {
-       $field_separator_count++;
-        if (null !== $field_array){
-            $year_name = $field_array . '[' . $prefix . 'Year]';
-        } else {
-            $year_name = $prefix . 'Year';
-        }
-        if ($year_as_text) {
-            $year_result .= '<input type="text" name="' . $year_name . '" value="' . $time[0] . '" size="4" maxlength="4"';
-            if (null !== $all_extra){
-                $year_result .= ' ' . $all_extra;
-            }
-            if (null !== $year_extra){
-                $year_result .= ' ' . $year_extra;
-            }
-            $year_result .= ' />';
-        } else {
-            $years = range((int)$start_year, (int)$end_year);
-            if ($reverse_years) {
-                rsort($years, SORT_NUMERIC);
-            } else {
-                sort($years, SORT_NUMERIC);
-            }
-            $yearvals = $years;
-            if(isset($year_empty)) {
-                array_unshift($years, $year_empty);
-                array_unshift($yearvals, '');
-            }
-            $year_result .= '<select name="' . $year_name . '"';
-            if (null !== $year_size){
-                $year_result .= ' size="' . $year_size . '"';
-            }
-            if (null !== $all_extra){
-                $year_result .= ' ' . $all_extra;
-            }
-            if (null !== $year_extra){
-                $year_result .= ' ' . $year_extra;
-            }
-            $year_result .= $extra_attrs . '>'."\n";
-            $year_result .= smarty_function_html_options(array('output' => $years,
-                                                               'values' => $yearvals,
-                                                               'selected'   => $time[0],
-                                                               'print_result' => false),
-                                                         $smarty);
-            $year_result .= '</select>';
-        }
-    }
-
-    // Loop thru the field_order field
-    for ($i = 0; $i <= 2; $i++){
-        $c = substr($field_order, $i, 1);
-        switch ($c){
-            case 'D':
-                $html_result .= $day_result;
-                break;
-
-            case 'M':
-                $html_result .= $month_result;
-                break;
-
-            case 'Y':
-                $html_result .= $year_result;
-                break;
-        }
-        // Add the field seperator
-        if($i < $field_separator_count) {
-            $html_result .= $field_separator;
-        }
-    }
-
-    return $html_result;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.html_select_time.php b/smarty/plugins/function.html_select_time.php
deleted file mode 100644 (file)
index 2e5be7e..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty {html_select_time} function plugin
- *
- * Type:     function<br>
- * Name:     html_select_time<br>
- * Purpose:  Prints the dropdowns for time selection
- * @link http://smarty.php.net/manual/en/language.function.html.select.time.php {html_select_time}
- *          (Smarty online manual)
- * @author Roberto Berto <roberto@berto.net>
- * @credits Monte Ohrt <monte AT ohrt DOT com>
- * @param array
- * @param Smarty
- * @return string
- * @uses smarty_make_timestamp()
- */
-function smarty_function_html_select_time($params, &$smarty)
-{
-    require_once $smarty->_get_plugin_filepath('shared','make_timestamp');
-    require_once $smarty->_get_plugin_filepath('function','html_options');
-    /* Default values. */
-    $prefix             = "Time_";
-    $time               = time();
-    $display_hours      = true;
-    $display_minutes    = true;
-    $display_seconds    = true;
-    $display_meridian   = true;
-    $use_24_hours       = true;
-    $minute_interval    = 1;
-    $second_interval    = 1;
-    /* Should the select boxes be part of an array when returned from PHP?
-       e.g. setting it to "birthday", would create "birthday[Hour]",
-       "birthday[Minute]", "birthday[Seconds]" & "birthday[Meridian]".
-       Can be combined with prefix. */
-    $field_array        = null;
-    $all_extra          = null;
-    $hour_extra         = null;
-    $minute_extra       = null;
-    $second_extra       = null;
-    $meridian_extra     = null;
-
-    foreach ($params as $_key=>$_value) {
-        switch ($_key) {
-            case 'prefix':
-            case 'time':
-            case 'field_array':
-            case 'all_extra':
-            case 'hour_extra':
-            case 'minute_extra':
-            case 'second_extra':
-            case 'meridian_extra':
-                $$_key = (string)$_value;
-                break;
-
-            case 'display_hours':
-            case 'display_minutes':
-            case 'display_seconds':
-            case 'display_meridian':
-            case 'use_24_hours':
-                $$_key = (bool)$_value;
-                break;
-
-            case 'minute_interval':
-            case 'second_interval':
-                $$_key = (int)$_value;
-                break;
-
-            default:
-                $smarty->trigger_error("[html_select_time] unknown parameter $_key", E_USER_WARNING);
-        }
-    }
-
-    $time = smarty_make_timestamp($time);
-
-    $html_result = '';
-
-    if ($display_hours) {
-        $hours       = $use_24_hours ? range(0, 23) : range(1, 12);
-        $hour_fmt = $use_24_hours ? '%H' : '%I';
-        for ($i = 0, $for_max = count($hours); $i < $for_max; $i++)
-            $hours[$i] = sprintf('%02d', $hours[$i]);
-        $html_result .= '<select name=';
-        if (null !== $field_array) {
-            $html_result .= '"' . $field_array . '[' . $prefix . 'Hour]"';
-        } else {
-            $html_result .= '"' . $prefix . 'Hour"';
-        }
-        if (null !== $hour_extra){
-            $html_result .= ' ' . $hour_extra;
-        }
-        if (null !== $all_extra){
-            $html_result .= ' ' . $all_extra;
-        }
-        $html_result .= '>'."\n";
-        $html_result .= smarty_function_html_options(array('output'          => $hours,
-                                                           'values'          => $hours,
-                                                           'selected'      => strftime($hour_fmt, $time),
-                                                           'print_result' => false),
-                                                     $smarty);
-        $html_result .= "</select>\n";
-    }
-
-    if ($display_minutes) {
-        $all_minutes = range(0, 59);
-        for ($i = 0, $for_max = count($all_minutes); $i < $for_max; $i+= $minute_interval)
-            $minutes[] = sprintf('%02d', $all_minutes[$i]);
-        $selected = intval(floor(strftime('%M', $time) / $minute_interval) * $minute_interval);
-        $html_result .= '<select name=';
-        if (null !== $field_array) {
-            $html_result .= '"' . $field_array . '[' . $prefix . 'Minute]"';
-        } else {
-            $html_result .= '"' . $prefix . 'Minute"';
-        }
-        if (null !== $minute_extra){
-            $html_result .= ' ' . $minute_extra;
-        }
-        if (null !== $all_extra){
-            $html_result .= ' ' . $all_extra;
-        }
-        $html_result .= '>'."\n";
-        
-        $html_result .= smarty_function_html_options(array('output'          => $minutes,
-                                                           'values'          => $minutes,
-                                                           'selected'      => $selected,
-                                                           'print_result' => false),
-                                                     $smarty);
-        $html_result .= "</select>\n";
-    }
-
-    if ($display_seconds) {
-        $all_seconds = range(0, 59);
-        for ($i = 0, $for_max = count($all_seconds); $i < $for_max; $i+= $second_interval)
-            $seconds[] = sprintf('%02d', $all_seconds[$i]);
-        $selected = intval(floor(strftime('%S', $time) / $second_interval) * $second_interval);
-        $html_result .= '<select name=';
-        if (null !== $field_array) {
-            $html_result .= '"' . $field_array . '[' . $prefix . 'Second]"';
-        } else {
-            $html_result .= '"' . $prefix . 'Second"';
-        }
-        
-        if (null !== $second_extra){
-            $html_result .= ' ' . $second_extra;
-        }
-        if (null !== $all_extra){
-            $html_result .= ' ' . $all_extra;
-        }
-        $html_result .= '>'."\n";
-        
-        $html_result .= smarty_function_html_options(array('output'          => $seconds,
-                                                           'values'          => $seconds,
-                                                           'selected'      => $selected,
-                                                           'print_result' => false),
-                                                     $smarty);
-        $html_result .= "</select>\n";
-    }
-
-    if ($display_meridian && !$use_24_hours) {
-        $html_result .= '<select name=';
-        if (null !== $field_array) {
-            $html_result .= '"' . $field_array . '[' . $prefix . 'Meridian]"';
-        } else {
-            $html_result .= '"' . $prefix . 'Meridian"';
-        }
-        
-        if (null !== $meridian_extra){
-            $html_result .= ' ' . $meridian_extra;
-        }
-        if (null !== $all_extra){
-            $html_result .= ' ' . $all_extra;
-        }
-        $html_result .= '>'."\n";
-        
-        $html_result .= smarty_function_html_options(array('output'          => array('AM', 'PM'),
-                                                           'values'          => array('am', 'pm'),
-                                                           'selected'      => strtolower(strftime('%p', $time)),
-                                                           'print_result' => false),
-                                                     $smarty);
-        $html_result .= "</select>\n";
-    }
-
-    return $html_result;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.html_table.php b/smarty/plugins/function.html_table.php
deleted file mode 100644 (file)
index 32aeba8..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty {html_table} function plugin
- *
- * Type:     function<br>
- * Name:     html_table<br>
- * Date:     Feb 17, 2003<br>
- * Purpose:  make an html table from an array of data<br>
- * Input:<br>
- *         - loop = array to loop through
- *         - cols = number of columns, comma separated list of column names
- *                  or array of column names
- *         - rows = number of rows
- *         - table_attr = table attributes
- *         - th_attr = table heading attributes (arrays are cycled)
- *         - tr_attr = table row attributes (arrays are cycled)
- *         - td_attr = table cell attributes (arrays are cycled)
- *         - trailpad = value to pad trailing cells with
- *         - caption = text for caption element 
- *         - vdir = vertical direction (default: "down", means top-to-bottom)
- *         - hdir = horizontal direction (default: "right", means left-to-right)
- *         - inner = inner loop (default "cols": print $loop line by line,
- *                   $loop will be printed column by column otherwise)
- *
- *
- * Examples:
- * <pre>
- * {table loop=$data}
- * {table loop=$data cols=4 tr_attr='"bgcolor=red"'}
- * {table loop=$data cols="first,second,third" tr_attr=$colors}
- * </pre>
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @author credit to Messju Mohr <messju at lammfellpuschen dot de>
- * @author credit to boots <boots dot smarty at yahoo dot com>
- * @version  1.1
- * @link http://smarty.php.net/manual/en/language.function.html.table.php {html_table}
- *          (Smarty online manual)
- * @param array
- * @param Smarty
- * @return string
- */
-function smarty_function_html_table($params, &$smarty)
-{
-    $table_attr = 'border="1"';
-    $tr_attr = '';
-    $th_attr = '';
-    $td_attr = '';
-    $cols = $cols_count = 3;
-    $rows = 3;
-    $trailpad = '&nbsp;';
-    $vdir = 'down';
-    $hdir = 'right';
-    $inner = 'cols';
-    $caption = '';
-
-    if (!isset($params['loop'])) {
-        $smarty->trigger_error("html_table: missing 'loop' parameter");
-        return;
-    }
-
-    foreach ($params as $_key=>$_value) {
-        switch ($_key) {
-            case 'loop':
-                $$_key = (array)$_value;
-                break;
-
-            case 'cols':
-                if (is_array($_value) && !empty($_value)) {
-                    $cols = $_value;
-                    $cols_count = count($_value);
-                } elseif (!is_numeric($_value) && is_string($_value) && !empty($_value)) {
-                    $cols = explode(',', $_value);
-                    $cols_count = count($cols);
-                } elseif (!empty($_value)) {
-                    $cols_count = (int)$_value;
-                } else {
-                    $cols_count = $cols;
-                }
-                break;
-
-            case 'rows':
-                $$_key = (int)$_value;
-                break;
-
-            case 'table_attr':
-            case 'trailpad':
-            case 'hdir':
-            case 'vdir':
-            case 'inner':
-            case 'caption':
-                $$_key = (string)$_value;
-                break;
-
-            case 'tr_attr':
-            case 'td_attr':
-            case 'th_attr':
-                $$_key = $_value;
-                break;
-        }
-    }
-
-    $loop_count = count($loop);
-    if (empty($params['rows'])) {
-        /* no rows specified */
-        $rows = ceil($loop_count/$cols_count);
-    } elseif (empty($params['cols'])) {
-        if (!empty($params['rows'])) {
-            /* no cols specified, but rows */
-            $cols_count = ceil($loop_count/$rows);
-        }
-    }
-
-    $output = "<table $table_attr>\n";
-
-    if (!empty($caption)) {
-        $output .= '<caption>' . $caption . "</caption>\n";
-    }
-
-    if (is_array($cols)) {
-        $cols = ($hdir == 'right') ? $cols : array_reverse($cols);
-        $output .= "<thead><tr>\n";
-
-        for ($r=0; $r<$cols_count; $r++) {
-            $output .= '<th' . smarty_function_html_table_cycle('th', $th_attr, $r) . '>';
-            $output .= $cols[$r];
-            $output .= "</th>\n";
-        }
-        $output .= "</tr></thead>\n";
-    }
-
-    $output .= "<tbody>\n";
-    for ($r=0; $r<$rows; $r++) {
-        $output .= "<tr" . smarty_function_html_table_cycle('tr', $tr_attr, $r) . ">\n";
-        $rx =  ($vdir == 'down') ? $r*$cols_count : ($rows-1-$r)*$cols_count;
-
-        for ($c=0; $c<$cols_count; $c++) {
-            $x =  ($hdir == 'right') ? $rx+$c : $rx+$cols_count-1-$c;
-            if ($inner!='cols') {
-                /* shuffle x to loop over rows*/
-                $x = floor($x/$cols_count) + ($x%$cols_count)*$rows;
-            }
-
-            if ($x<$loop_count) {
-                $output .= "<td" . smarty_function_html_table_cycle('td', $td_attr, $c) . ">" . $loop[$x] . "</td>\n";
-            } else {
-                $output .= "<td" . smarty_function_html_table_cycle('td', $td_attr, $c) . ">$trailpad</td>\n";
-            }
-        }
-        $output .= "</tr>\n";
-    }
-    $output .= "</tbody>\n";
-    $output .= "</table>\n";
-    
-    return $output;
-}
-
-function smarty_function_html_table_cycle($name, $var, $no) {
-    if(!is_array($var)) {
-        $ret = $var;
-    } else {
-        $ret = $var[$no % count($var)];
-    }
-    
-    return ($ret) ? ' '.$ret : '';
-}
-
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.mailto.php b/smarty/plugins/function.mailto.php
deleted file mode 100644 (file)
index 20e9ed9..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty {mailto} function plugin
- *
- * Type:     function<br>
- * Name:     mailto<br>
- * Date:     May 21, 2002
- * Purpose:  automate mailto address link creation, and optionally
- *           encode them.<br>
- * Input:<br>
- *         - address = e-mail address
- *         - text = (optional) text to display, default is address
- *         - encode = (optional) can be one of:
- *                * none : no encoding (default)
- *                * javascript : encode with javascript
- *                * javascript_charcode : encode with javascript charcode
- *                * hex : encode with hexidecimal (no javascript)
- *         - cc = (optional) address(es) to carbon copy
- *         - bcc = (optional) address(es) to blind carbon copy
- *         - subject = (optional) e-mail subject
- *         - newsgroups = (optional) newsgroup(s) to post to
- *         - followupto = (optional) address(es) to follow up to
- *         - extra = (optional) extra tags for the href link
- *
- * Examples:
- * <pre>
- * {mailto address="me@domain.com"}
- * {mailto address="me@domain.com" encode="javascript"}
- * {mailto address="me@domain.com" encode="hex"}
- * {mailto address="me@domain.com" subject="Hello to you!"}
- * {mailto address="me@domain.com" cc="you@domain.com,they@domain.com"}
- * {mailto address="me@domain.com" extra='class="mailto"'}
- * </pre>
- * @link http://smarty.php.net/manual/en/language.function.mailto.php {mailto}
- *          (Smarty online manual)
- * @version  1.2
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @author   credits to Jason Sweat (added cc, bcc and subject functionality)
- * @param    array
- * @param    Smarty
- * @return   string
- */
-function smarty_function_mailto($params, &$smarty)
-{
-    $extra = '';
-
-    if (empty($params['address'])) {
-        $smarty->trigger_error("mailto: missing 'address' parameter");
-        return;
-    } else {
-        $address = $params['address'];
-    }
-
-    $text = $address;
-
-    // netscape and mozilla do not decode %40 (@) in BCC field (bug?)
-    // so, don't encode it.
-    $search = array('%40', '%2C');
-    $replace  = array('@', ',');
-    $mail_parms = array();
-    foreach ($params as $var=>$value) {
-        switch ($var) {
-            case 'cc':
-            case 'bcc':
-            case 'followupto':
-                if (!empty($value))
-                    $mail_parms[] = $var.'='.str_replace($search,$replace,rawurlencode($value));
-                break;
-                
-            case 'subject':
-            case 'newsgroups':
-                $mail_parms[] = $var.'='.rawurlencode($value);
-                break;
-
-            case 'extra':
-            case 'text':
-                $$var = $value;
-
-            default:
-        }
-    }
-
-    $mail_parm_vals = '';
-    for ($i=0; $i<count($mail_parms); $i++) {
-        $mail_parm_vals .= (0==$i) ? '?' : '&';
-        $mail_parm_vals .= $mail_parms[$i];
-    }
-    $address .= $mail_parm_vals;
-
-    $encode = (empty($params['encode'])) ? 'none' : $params['encode'];
-    if (!in_array($encode,array('javascript','javascript_charcode','hex','none')) ) {
-        $smarty->trigger_error("mailto: 'encode' parameter must be none, javascript or hex");
-        return;
-    }
-
-    if ($encode == 'javascript' ) {
-        $string = 'document.write(\'<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>\');';
-
-        $js_encode = '';
-        for ($x=0; $x < strlen($string); $x++) {
-            $js_encode .= '%' . bin2hex($string[$x]);
-        }
-
-        return '<script type="text/javascript">eval(unescape(\''.$js_encode.'\'))</script>';
-
-    } elseif ($encode == 'javascript_charcode' ) {
-        $string = '<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>';
-
-        for($x = 0, $y = strlen($string); $x < $y; $x++ ) {
-            $ord[] = ord($string[$x]);   
-        }
-
-        $_ret = "<script type=\"text/javascript\" language=\"javascript\">\n";
-        $_ret .= "<!--\n";
-        $_ret .= "{document.write(String.fromCharCode(";
-        $_ret .= implode(',',$ord);
-        $_ret .= "))";
-        $_ret .= "}\n";
-        $_ret .= "//-->\n";
-        $_ret .= "</script>\n";
-        
-        return $_ret;
-        
-        
-    } elseif ($encode == 'hex') {
-
-        preg_match('!^(.*)(\?.*)$!',$address,$match);
-        if(!empty($match[2])) {
-            $smarty->trigger_error("mailto: hex encoding does not work with extra attributes. Try javascript.");
-            return;
-        }
-        $address_encode = '';
-        for ($x=0; $x < strlen($address); $x++) {
-            if(preg_match('!\w!',$address[$x])) {
-                $address_encode .= '%' . bin2hex($address[$x]);
-            } else {
-                $address_encode .= $address[$x];
-            }
-        }
-        $text_encode = '';
-        for ($x=0; $x < strlen($text); $x++) {
-            $text_encode .= '&#x' . bin2hex($text[$x]).';';
-        }
-
-        $mailto = "&#109;&#97;&#105;&#108;&#116;&#111;&#58;";
-        return '<a href="'.$mailto.$address_encode.'" '.$extra.'>'.$text_encode.'</a>';
-
-    } else {
-        // no encoding
-        return '<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>';
-
-    }
-
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.math.php b/smarty/plugins/function.math.php
deleted file mode 100644 (file)
index 71672fe..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty {math} function plugin
- *
- * Type:     function<br>
- * Name:     math<br>
- * Purpose:  handle math computations in template<br>
- * @link http://smarty.php.net/manual/en/language.function.math.php {math}
- *          (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param array
- * @param Smarty
- * @return string
- */
-function smarty_function_math($params, &$smarty)
-{
-    // be sure equation parameter is present
-    if (empty($params['equation'])) {
-        $smarty->trigger_error("math: missing equation parameter");
-        return;
-    }
-
-    $equation = $params['equation'];
-
-    // make sure parenthesis are balanced
-    if (substr_count($equation,"(") != substr_count($equation,")")) {
-        $smarty->trigger_error("math: unbalanced parenthesis");
-        return;
-    }
-
-    // match all vars in equation, make sure all are passed
-    preg_match_all("!(?:0x[a-fA-F0-9]+)|([a-zA-Z][a-zA-Z0-9_]+)!",$equation, $match);
-    $allowed_funcs = array('int','abs','ceil','cos','exp','floor','log','log10',
-                           'max','min','pi','pow','rand','round','sin','sqrt','srand','tan');
-    
-    foreach($match[1] as $curr_var) {
-        if ($curr_var && !in_array($curr_var, array_keys($params)) && !in_array($curr_var, $allowed_funcs)) {
-            $smarty->trigger_error("math: function call $curr_var not allowed");
-            return;
-        }
-    }
-
-    foreach($params as $key => $val) {
-        if ($key != "equation" && $key != "format" && $key != "assign") {
-            // make sure value is not empty
-            if (strlen($val)==0) {
-                $smarty->trigger_error("math: parameter $key is empty");
-                return;
-            }
-            if (!is_numeric($val)) {
-                $smarty->trigger_error("math: parameter $key: is not numeric");
-                return;
-            }
-            $equation = preg_replace("/\b$key\b/", " \$params['$key'] ", $equation);
-        }
-    }
-
-    eval("\$smarty_math_result = ".$equation.";");
-
-    if (empty($params['format'])) {
-        if (empty($params['assign'])) {
-            return $smarty_math_result;
-        } else {
-            $smarty->assign($params['assign'],$smarty_math_result);
-        }
-    } else {
-        if (empty($params['assign'])){
-            printf($params['format'],$smarty_math_result);
-        } else {
-            $smarty->assign($params['assign'],sprintf($params['format'],$smarty_math_result));
-        }
-    }
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.popup.php b/smarty/plugins/function.popup.php
deleted file mode 100644 (file)
index 3a76b78..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty {popup} function plugin
- *
- * Type:     function<br>
- * Name:     popup<br>
- * Purpose:  make text pop up in windows via overlib
- * @link http://smarty.php.net/manual/en/language.function.popup.php {popup}
- *          (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param array
- * @param Smarty
- * @return string
- */
-function smarty_function_popup($params, &$smarty)
-{
-    $append = '';
-    foreach ($params as $_key=>$_value) {
-        switch ($_key) {
-            case 'text':
-            case 'trigger':
-            case 'function':
-            case 'inarray':
-                $$_key = (string)$_value;
-                if ($_key == 'function' || $_key == 'inarray')
-                    $append .= ',' . strtoupper($_key) . ",'$_value'";
-                break;
-
-            case 'caption':
-            case 'closetext':
-            case 'status':
-                $append .= ',' . strtoupper($_key) . ",'" . str_replace("'","\'",$_value) . "'";
-                break;
-
-            case 'fgcolor':
-            case 'bgcolor':
-            case 'textcolor':
-            case 'capcolor':
-            case 'closecolor':
-            case 'textfont':
-            case 'captionfont':
-            case 'closefont':
-            case 'fgbackground':
-            case 'bgbackground':
-            case 'caparray':
-            case 'capicon':
-            case 'background':
-            case 'frame':
-                $append .= ',' . strtoupper($_key) . ",'$_value'";
-                break;
-
-            case 'textsize':
-            case 'captionsize':
-            case 'closesize':
-            case 'width':
-            case 'height':
-            case 'border':
-            case 'offsetx':
-            case 'offsety':
-            case 'snapx':
-            case 'snapy':
-            case 'fixx':
-            case 'fixy':
-            case 'padx':
-            case 'pady':
-            case 'timeout':
-            case 'delay':
-                $append .= ',' . strtoupper($_key) . ",$_value";
-                break;
-
-            case 'sticky':
-            case 'left':
-            case 'right':
-            case 'center':
-            case 'above':
-            case 'below':
-            case 'noclose':
-            case 'autostatus':
-            case 'autostatuscap':
-            case 'fullhtml':
-            case 'hauto':
-            case 'vauto':
-            case 'mouseoff':
-            case 'followmouse':
-            case 'closeclick':
-                if ($_value) $append .= ',' . strtoupper($_key);
-                break;
-
-            default:
-                $smarty->trigger_error("[popup] unknown parameter $_key", E_USER_WARNING);
-        }
-    }
-
-    if (empty($text) && !isset($inarray) && empty($function)) {
-        $smarty->trigger_error("overlib: attribute 'text' or 'inarray' or 'function' required");
-        return false;
-    }
-
-    if (empty($trigger)) { $trigger = "onmouseover"; }
-
-    $retval = $trigger . '="return overlib(\''.preg_replace(array("!'!","![\r\n]!"),array("\'",'\r'),$text).'\'';
-    $retval .= $append . ');"';
-    if ($trigger == 'onmouseover')
-       $retval .= ' onmouseout="nd();"';
-
-
-    return $retval;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/function.popup_init.php b/smarty/plugins/function.popup_init.php
deleted file mode 100644 (file)
index 93cb454..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty {popup_init} function plugin
- *
- * Type:     function<br>
- * Name:     popup_init<br>
- * Purpose:  initialize overlib
- * @link http://smarty.php.net/manual/en/language.function.popup.init.php {popup_init}
- *          (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param array
- * @param Smarty
- * @return string
- */
-function smarty_function_popup_init($params, &$smarty)
-{
-    $zindex = 1000;
-    
-    if (!empty($params['zindex'])) {
-        $zindex = $params['zindex'];
-    }
-    
-    if (!empty($params['src'])) {
-        return '<div id="overDiv" style="position:absolute; visibility:hidden; z-index:'.$zindex.';"></div>' . "\n"
-         . '<script type="text/javascript" language="JavaScript" src="'.$params['src'].'"></script>' . "\n";
-    } else {
-        $smarty->trigger_error("popup_init: missing src parameter");
-    }
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.capitalize.php b/smarty/plugins/modifier.capitalize.php
deleted file mode 100644 (file)
index 4a611d9..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty capitalize modifier plugin
- *
- * Type:     modifier<br>
- * Name:     capitalize<br>
- * Purpose:  capitalize words in the string
- * @link http://smarty.php.net/manual/en/language.modifiers.php#LANGUAGE.MODIFIER.CAPITALIZE
- *      capitalize (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @return string
- */
-function smarty_modifier_capitalize($string, $uc_digits = false)
-{
-    smarty_modifier_capitalize_ucfirst(null, $uc_digits);
-    return preg_replace_callback('!\'?\b\w(\w|\')*\b!', 'smarty_modifier_capitalize_ucfirst', $string);
-}
-
-function smarty_modifier_capitalize_ucfirst($string, $uc_digits = null)
-{
-    static $_uc_digits = false;
-    
-    if(isset($uc_digits)) {
-        $_uc_digits = $uc_digits;
-        return;
-    }
-    
-    if(substr($string[0],0,1) != "'" && !preg_match("!\d!",$string[0]) || $_uc_digits)
-        return ucfirst($string[0]);
-    else
-        return $string[0];
-}
-
-
-?>
diff --git a/smarty/plugins/modifier.cat.php b/smarty/plugins/modifier.cat.php
deleted file mode 100644 (file)
index 2e37940..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty cat modifier plugin
- *
- * Type:     modifier<br>
- * Name:     cat<br>
- * Date:     Feb 24, 2003
- * Purpose:  catenate a value to a variable
- * Input:    string to catenate
- * Example:  {$var|cat:"foo"}
- * @link http://smarty.php.net/manual/en/language.modifier.cat.php cat
- *          (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @version 1.0
- * @param string
- * @param string
- * @return string
- */
-function smarty_modifier_cat($string, $cat)
-{
-    return $string . $cat;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.count_characters.php b/smarty/plugins/modifier.count_characters.php
deleted file mode 100644 (file)
index 5ed9a87..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty count_characters modifier plugin
- *
- * Type:     modifier<br>
- * Name:     count_characteres<br>
- * Purpose:  count the number of characters in a text
- * @link http://smarty.php.net/manual/en/language.modifier.count.characters.php
- *          count_characters (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @param boolean include whitespace in the character count
- * @return integer
- */
-function smarty_modifier_count_characters($string, $include_spaces = false)
-{
-    if ($include_spaces)
-       return(strlen($string));
-
-    return preg_match_all("/[^\s]/",$string, $match);
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.count_paragraphs.php b/smarty/plugins/modifier.count_paragraphs.php
deleted file mode 100644 (file)
index e0e274d..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty count_paragraphs modifier plugin
- *
- * Type:     modifier<br>
- * Name:     count_paragraphs<br>
- * Purpose:  count the number of paragraphs in a text
- * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php
- *          count_paragraphs (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @return integer
- */
-function smarty_modifier_count_paragraphs($string)
-{
-    // count \r or \n characters
-    return count(preg_split('/[\r\n]+/', $string));
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.count_sentences.php b/smarty/plugins/modifier.count_sentences.php
deleted file mode 100644 (file)
index f66ea17..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty count_sentences modifier plugin
- *
- * Type:     modifier<br>
- * Name:     count_sentences
- * Purpose:  count the number of sentences in a text
- * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php
- *          count_sentences (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @return integer
- */
-function smarty_modifier_count_sentences($string)
-{
-    // find periods with a word before but not after.
-    return preg_match_all('/[^\s]\.(?!\w)/', $string, $match);
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.count_words.php b/smarty/plugins/modifier.count_words.php
deleted file mode 100644 (file)
index 9d339f5..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty count_words modifier plugin
- *
- * Type:     modifier<br>
- * Name:     count_words<br>
- * Purpose:  count the number of words in a text
- * @link http://smarty.php.net/manual/en/language.modifier.count.words.php
- *          count_words (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @return integer
- */
-function smarty_modifier_count_words($string)
-{
-    // split text by ' ',\r,\n,\f,\t
-    $split_array = preg_split('/\s+/',$string);
-    // count matches that contain alphanumerics
-    $word_count = preg_grep('/[a-zA-Z0-9\\x80-\\xff]/', $split_array);
-
-    return count($word_count);
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.csv.php b/smarty/plugins/modifier.csv.php
deleted file mode 100644 (file)
index 4c715c4..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty csv modifier plugin
- *
- * Type:     modifier<br>
- * Name:     csv<br>
- * Purpose:  format string for CSV output
- * @author Andreas Gohr <gohr@cosmocode.de>
- * @param string
- * @return string
- */
-function smarty_modifier_csv($string)
-{
-    return '"'.strtr(trim($string),'"','""').'"';
-}
-
-?>
diff --git a/smarty/plugins/modifier.date_format.php b/smarty/plugins/modifier.date_format.php
deleted file mode 100644 (file)
index 8cf7d5e..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Include the {@link shared.make_timestamp.php} plugin
- */
-require_once $smarty->_get_plugin_filepath('shared', 'make_timestamp');
-/**
- * Smarty date_format modifier plugin
- *
- * Type:     modifier<br>
- * Name:     date_format<br>
- * Purpose:  format datestamps via strftime<br>
- * Input:<br>
- *         - string: input date string
- *         - format: strftime format for output
- *         - default_date: default date if $string is empty
- * @link http://smarty.php.net/manual/en/language.modifier.date.format.php
- *          date_format (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @param string
- * @param string
- * @return string|void
- * @uses smarty_make_timestamp()
- */
-function smarty_modifier_date_format($string, $format = '%b %e, %Y', $default_date = '')
-{
-    if ($string != '') {
-        $timestamp = smarty_make_timestamp($string);
-    } elseif ($default_date != '') {
-        $timestamp = smarty_make_timestamp($default_date);
-    } else {
-        return;
-    }
-    if (DIRECTORY_SEPARATOR == '\\') {
-        $_win_from = array('%D',       '%h', '%n', '%r',          '%R',    '%t', '%T');
-        $_win_to   = array('%m/%d/%y', '%b', "\n", '%I:%M:%S %p', '%H:%M', "\t", '%H:%M:%S');
-        if (strpos($format, '%e') !== false) {
-            $_win_from[] = '%e';
-            $_win_to[]   = sprintf('%\' 2d', date('j', $timestamp));
-        }
-        if (strpos($format, '%l') !== false) {
-            $_win_from[] = '%l';
-            $_win_to[]   = sprintf('%\' 2d', date('h', $timestamp));
-        }
-        $format = str_replace($_win_from, $_win_to, $format);
-    }
-    return strftime($format, $timestamp);
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.debug_print_var.php b/smarty/plugins/modifier.debug_print_var.php
deleted file mode 100644 (file)
index e4f7bc0..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty debug_print_var modifier plugin
- *
- * Type:     modifier<br>
- * Name:     debug_print_var<br>
- * Purpose:  formats variable contents for display in the console
- * @link http://smarty.php.net/manual/en/language.modifier.debug.print.var.php
- *          debug_print_var (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param array|object
- * @param integer
- * @param integer
- * @return string
- */
-function smarty_modifier_debug_print_var($var, $depth = 0, $length = 40)
-{
-    $_replace = array(
-        "\n" => '<i>\n</i>',
-        "\r" => '<i>\r</i>',
-        "\t" => '<i>\t</i>'
-    );
-
-    switch (gettype($var)) {
-        case 'array' :
-            $results = '<b>Array (' . count($var) . ')</b>';
-            foreach ($var as $curr_key => $curr_val) {
-                $results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
-                    . '<b>' . strtr($curr_key, $_replace) . '</b> =&gt; '
-                    . smarty_modifier_debug_print_var($curr_val, ++$depth, $length);
-                    $depth--;
-            }
-            break;
-        case 'object' :
-            $object_vars = get_object_vars($var);
-            $results = '<b>' . get_class($var) . ' Object (' . count($object_vars) . ')</b>';
-            foreach ($object_vars as $curr_key => $curr_val) {
-                $results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
-                    . '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '
-                    . smarty_modifier_debug_print_var($curr_val, ++$depth, $length);
-                    $depth--;
-            }
-            break;
-        case 'boolean' :
-        case 'NULL' :
-        case 'resource' :
-            if (true === $var) {
-                $results = 'true';
-            } elseif (false === $var) {
-                $results = 'false';
-            } elseif (null === $var) {
-                $results = 'null';
-            } else {
-                $results = htmlspecialchars((string) $var);
-            }
-            $results = '<i>' . $results . '</i>';
-            break;
-        case 'integer' :
-        case 'float' :
-            $results = htmlspecialchars((string) $var);
-            break;
-        case 'string' :
-            $results = strtr($var, $_replace);
-            if (strlen($var) > $length ) {
-                $results = substr($var, 0, $length - 3) . '...';
-            }
-            $results = htmlspecialchars('"' . $results . '"');
-            break;
-        case 'unknown type' :
-        default :
-            $results = strtr((string) $var, $_replace);
-            if (strlen($results) > $length ) {
-                $results = substr($results, 0, $length - 3) . '...';
-            }
-            $results = htmlspecialchars($results);
-    }
-
-    return $results;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.default.php b/smarty/plugins/modifier.default.php
deleted file mode 100644 (file)
index 70011fd..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty default modifier plugin
- *
- * Type:     modifier<br>
- * Name:     default<br>
- * Purpose:  designate default value for empty variables
- * @link http://smarty.php.net/manual/en/language.modifier.default.php
- *          default (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @param string
- * @return string
- */
-function smarty_modifier_default($string, $default = '')
-{
-    if (!isset($string) || $string === '')
-        return $default;
-    else
-        return $string;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.escape.php b/smarty/plugins/modifier.escape.php
deleted file mode 100644 (file)
index a2f52b2..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty escape modifier plugin
- *
- * Type:     modifier<br>
- * Name:     escape<br>
- * Purpose:  Escape the string according to escapement type
- * @link http://smarty.php.net/manual/en/language.modifier.escape.php
- *          escape (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @param html|htmlall|url|quotes|hex|hexentity|javascript
- * @return string
- */
-function smarty_modifier_escape($string, $esc_type = 'html', $char_set = 'ISO-8859-1')
-{
-    switch ($esc_type) {
-        case 'html':
-            return htmlspecialchars($string, ENT_QUOTES, $char_set);
-
-        case 'htmlall':
-            return htmlentities($string, ENT_QUOTES, $char_set);
-
-        case 'url':
-            return rawurlencode($string);
-
-        case 'urlpathinfo':
-            return str_replace('%2F','/',rawurlencode($string));
-            
-        case 'quotes':
-            // escape unescaped single quotes
-            return preg_replace("%(?<!\\\\)'%", "\\'", $string);
-
-        case 'hex':
-            // escape every character into hex
-            $return = '';
-            for ($x=0; $x < strlen($string); $x++) {
-                $return .= '%' . bin2hex($string[$x]);
-            }
-            return $return;
-            
-        case 'hexentity':
-            $return = '';
-            for ($x=0; $x < strlen($string); $x++) {
-                $return .= '&#x' . bin2hex($string[$x]) . ';';
-            }
-            return $return;
-
-        case 'decentity':
-            $return = '';
-            for ($x=0; $x < strlen($string); $x++) {
-                $return .= '&#' . ord($string[$x]) . ';';
-            }
-            return $return;
-
-        case 'javascript':
-            // escape quotes and backslashes, newlines, etc.
-            return strtr($string, array('\\'=>'\\\\',"'"=>"\\'",'"'=>'\\"',"\r"=>'\\r',"\n"=>'\\n','</'=>'<\/'));
-            
-        case 'mail':
-            // safe way to display e-mail address on a web page
-            return str_replace(array('@', '.'),array(' [AT] ', ' [DOT] '), $string);
-            
-        case 'nonstd':
-           // escape non-standard chars, such as ms document quotes
-           $_res = '';
-           for($_i = 0, $_len = strlen($string); $_i < $_len; $_i++) {
-               $_ord = ord(substr($string, $_i, 1));
-               // non-standard char, escape it
-               if($_ord >= 126){
-                   $_res .= '&#' . $_ord . ';';
-               }
-               else {
-                   $_res .= substr($string, $_i, 1);
-               }
-           }
-           return $_res;
-
-        default:
-            return $string;
-    }
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.indent.php b/smarty/plugins/modifier.indent.php
deleted file mode 100644 (file)
index 394147a..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty indent modifier plugin
- *
- * Type:     modifier<br>
- * Name:     indent<br>
- * Purpose:  indent lines of text
- * @link http://smarty.php.net/manual/en/language.modifier.indent.php
- *          indent (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @param integer
- * @param string
- * @return string
- */
-function smarty_modifier_indent($string,$chars=4,$char=" ")
-{
-    return preg_replace('!^!m',str_repeat($char,$chars),$string);
-}
-
-?>
diff --git a/smarty/plugins/modifier.lower.php b/smarty/plugins/modifier.lower.php
deleted file mode 100644 (file)
index 20e7a8d..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty lower modifier plugin
- *
- * Type:     modifier<br>
- * Name:     lower<br>
- * Purpose:  convert string to lowercase
- * @link http://smarty.php.net/manual/en/language.modifier.lower.php
- *          lower (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @return string
- */
-function smarty_modifier_lower($string)
-{
-    return strtolower($string);
-}
-
-?>
diff --git a/smarty/plugins/modifier.nl2br.php b/smarty/plugins/modifier.nl2br.php
deleted file mode 100644 (file)
index d6fabff..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty plugin
- *
- * Type:     modifier<br>
- * Name:     nl2br<br>
- * Date:     Feb 26, 2003
- * Purpose:  convert \r\n, \r or \n to <<br>>
- * Input:<br>
- *         - contents = contents to replace
- *         - preceed_test = if true, includes preceeding break tags
- *           in replacement
- * Example:  {$text|nl2br}
- * @link http://smarty.php.net/manual/en/language.modifier.nl2br.php
- *          nl2br (Smarty online manual)
- * @version  1.0
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @return string
- */
-function smarty_modifier_nl2br($string)
-{
-    return nl2br($string);
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.noteparser.php b/smarty/plugins/modifier.noteparser.php
deleted file mode 100644 (file)
index 0f96f00..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty plugin
- *
- * Type:     modifier
- * Name:     noteparser
- * Date:     Feb 26, 2003
- * Purpose:  Converts plaintext notes to richer HTML (very simple)
- * Example:  {$entry.note|noteparser}
- * @author   Andreas Gohr <gohr@cosmocode.de>
- * @param string
- * @return string
- */
-function smarty_modifier_noteparser($string){
-    $string = htmlspecialchars($string);
-
-    $string = preg_replace('!\*\*Call\*\*!i','<img src="pix/phone.png" width="16" height="16" alt="Call" />',$string);
-    $string = preg_replace('!\*\*ToDo\*\*!i','<img src="pix/arrow_right.png" width="16" height="16" alt="ToDo" />',$string);
-    $string = preg_replace('!\*\*Mail\*\*!i','<img src="pix/email.png" width="16" height="16" alt="Mail" />',$string);
-    $string = preg_replace('!\*\*Note\*\*!i','<img src="pix/note.png" width="16" height="16" alt="note" />',$string);
-
-    $string = preg_replace('!\*\*(.*?)\*\*!','<b>\\1</b>',$string);
-    $string = preg_replace('!__(.*?)__!','<u>\\1</u>',$string);
-    $string = preg_replace('!//(.*?)//!','<i>\\1</i>',$string);
-
-    $string = preg_replace('!(https?://[\w;/?:@&=+$\-_.\!~*\\\']+)!i',
-                           '<a href="\\1">\\1</a>',$string);
-
-    $string = preg_replace('!\n\n+!','</p><p>',$string);
-    $string = nl2br($string);
-
-    return '<p>'.$string.'</p>';
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.regex_replace.php b/smarty/plugins/modifier.regex_replace.php
deleted file mode 100644 (file)
index d4d2030..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty regex_replace modifier plugin
- *
- * Type:     modifier<br>
- * Name:     regex_replace<br>
- * Purpose:  regular expression search/replace
- * @link http://smarty.php.net/manual/en/language.modifier.regex.replace.php
- *          regex_replace (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @param string|array
- * @param string|array
- * @return string
- */
-function smarty_modifier_regex_replace($string, $search, $replace)
-{
-    if (preg_match('!([a-zA-Z\s]+)$!s', $search, $match) && (strpos($match[1], 'e') !== false)) {
-        /* remove eval-modifier from $search */
-        $search = substr($search, 0, -strlen($match[1])) . preg_replace('![e\s]+!', '', $match[1]);
-    }
-       
-    return preg_replace($search, $replace, $string);
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.replace.php b/smarty/plugins/modifier.replace.php
deleted file mode 100644 (file)
index df041c8..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty replace modifier plugin
- *
- * Type:     modifier<br>
- * Name:     replace<br>
- * Purpose:  simple search/replace
- * @link http://smarty.php.net/manual/en/language.modifier.replace.php
- *          replace (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @param string
- * @param string
- * @return string
- */
-function smarty_modifier_replace($string, $search, $replace)
-{
-    return str_replace($search, $replace, $string);
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.spacify.php b/smarty/plugins/modifier.spacify.php
deleted file mode 100644 (file)
index c2423f4..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty spacify modifier plugin
- *
- * Type:     modifier<br>
- * Name:     spacify<br>
- * Purpose:  add spaces between characters in a string
- * @link http://smarty.php.net/manual/en/language.modifier.spacify.php
- *          spacify (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @param string
- * @return string
- */
-function smarty_modifier_spacify($string, $spacify_char = ' ')
-{
-    return implode($spacify_char,
-                   preg_split('//', $string, -1, PREG_SPLIT_NO_EMPTY));
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.string_format.php b/smarty/plugins/modifier.string_format.php
deleted file mode 100644 (file)
index 9e051a5..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty string_format modifier plugin
- *
- * Type:     modifier<br>
- * Name:     string_format<br>
- * Purpose:  format strings via sprintf
- * @link http://smarty.php.net/manual/en/language.modifier.string.format.php
- *          string_format (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @param string
- * @return string
- */
-function smarty_modifier_string_format($string, $format)
-{
-    return sprintf($format, $string);
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.strip.php b/smarty/plugins/modifier.strip.php
deleted file mode 100644 (file)
index cc5c453..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty strip modifier plugin
- *
- * Type:     modifier<br>
- * Name:     strip<br>
- * Purpose:  Replace all repeated spaces, newlines, tabs
- *           with a single space or supplied replacement string.<br>
- * Example:  {$var|strip} {$var|strip:"&nbsp;"}
- * Date:     September 25th, 2002
- * @link http://smarty.php.net/manual/en/language.modifier.strip.php
- *          strip (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @version  1.0
- * @param string
- * @param string
- * @return string
- */
-function smarty_modifier_strip($text, $replace = ' ')
-{
-    return preg_replace('!\s+!', $replace, $text);
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.strip_tags.php b/smarty/plugins/modifier.strip_tags.php
deleted file mode 100644 (file)
index 93011a8..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty strip_tags modifier plugin
- *
- * Type:     modifier<br>
- * Name:     strip_tags<br>
- * Purpose:  strip html tags from text
- * @link http://smarty.php.net/manual/en/language.modifier.strip.tags.php
- *          strip_tags (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @param boolean
- * @return string
- */
-function smarty_modifier_strip_tags($string, $replace_with_space = true)
-{
-    if ($replace_with_space)
-        return preg_replace('!<[^>]*?>!', ' ', $string);
-    else
-        return strip_tags($string);
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.truncate.php b/smarty/plugins/modifier.truncate.php
deleted file mode 100644 (file)
index 35c8969..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty truncate modifier plugin
- *
- * Type:     modifier<br>
- * Name:     truncate<br>
- * Purpose:  Truncate a string to a certain length if necessary,
- *           optionally splitting in the middle of a word, and
- *           appending the $etc string or inserting $etc into the middle.
- * @link http://smarty.php.net/manual/en/language.modifier.truncate.php
- *          truncate (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @param integer
- * @param string
- * @param boolean
- * @param boolean
- * @return string
- */
-function smarty_modifier_truncate($string, $length = 80, $etc = '...',
-                                  $break_words = false, $middle = false)
-{
-    if ($length == 0)
-        return '';
-
-    if (strlen($string) > $length) {
-        $length -= min($length, strlen($etc));
-        if (!$break_words && !$middle) {
-            $string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length+1));
-        }
-        if(!$middle) {
-            return substr($string, 0, $length) . $etc;
-        } else {
-            return substr($string, 0, $length/2) . $etc . substr($string, -$length/2);
-        }
-    } else {
-        return $string;
-    }
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/modifier.upper.php b/smarty/plugins/modifier.upper.php
deleted file mode 100644 (file)
index c12480f..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty upper modifier plugin
- *
- * Type:     modifier<br>
- * Name:     upper<br>
- * Purpose:  convert string to uppercase
- * @link http://smarty.php.net/manual/en/language.modifier.upper.php
- *          upper (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @return string
- */
-function smarty_modifier_upper($string)
-{
-    return strtoupper($string);
-}
-
-?>
diff --git a/smarty/plugins/modifier.wordwrap.php b/smarty/plugins/modifier.wordwrap.php
deleted file mode 100644 (file)
index ce07181..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Smarty wordwrap modifier plugin
- *
- * Type:     modifier<br>
- * Name:     wordwrap<br>
- * Purpose:  wrap a string of text at a given length
- * @link http://smarty.php.net/manual/en/language.modifier.wordwrap.php
- *          wordwrap (Smarty online manual)
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @param integer
- * @param string
- * @param boolean
- * @return string
- */
-function smarty_modifier_wordwrap($string,$length=80,$break="\n",$cut=false)
-{
-    return wordwrap($string,$length,$break,$cut);
-}
-
-?>
diff --git a/smarty/plugins/outputfilter.trimwhitespace.php b/smarty/plugins/outputfilter.trimwhitespace.php
deleted file mode 100644 (file)
index 97b0d21..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-<?php
-/**
- * Smarty plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-/**
- * Smarty trimwhitespace outputfilter plugin
- *
- * File:     outputfilter.trimwhitespace.php<br>
- * Type:     outputfilter<br>
- * Name:     trimwhitespace<br>
- * Date:     Jan 25, 2003<br>
- * Purpose:  trim leading white space and blank lines from
- *           template source after it gets interpreted, cleaning
- *           up code and saving bandwidth. Does not affect
- *           <<PRE>></PRE> and <SCRIPT></SCRIPT> blocks.<br>
- * Install:  Drop into the plugin directory, call
- *           <code>$smarty->load_filter('output','trimwhitespace');</code>
- *           from application.
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @author Contributions from Lars Noschinski <lars@usenet.noschinski.de>
- * @version  1.3
- * @param string
- * @param Smarty
- */
-function smarty_outputfilter_trimwhitespace($source, &$smarty)
-{
-    // Pull out the script blocks
-    preg_match_all("!<script[^>]+>.*?</script>!is", $source, $match);
-    $_script_blocks = $match[0];
-    $source = preg_replace("!<script[^>]+>.*?</script>!is",
-                           '@@@SMARTY:TRIM:SCRIPT@@@', $source);
-
-    // Pull out the pre blocks
-    preg_match_all("!<pre>.*?</pre>!is", $source, $match);
-    $_pre_blocks = $match[0];
-    $source = preg_replace("!<pre>.*?</pre>!is",
-                           '@@@SMARTY:TRIM:PRE@@@', $source);
-
-    // Pull out the textarea blocks
-    preg_match_all("!<textarea[^>]+>.*?</textarea>!is", $source, $match);
-    $_textarea_blocks = $match[0];
-    $source = preg_replace("!<textarea[^>]+>.*?</textarea>!is",
-                           '@@@SMARTY:TRIM:TEXTAREA@@@', $source);
-
-    // remove all leading spaces, tabs and carriage returns NOT
-    // preceeded by a php close tag.
-    $source = trim(preg_replace('/((?<!\?>)\n)[\s]+/m', '\1', $source));
-
-    // replace textarea blocks
-    smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:TEXTAREA@@@",$_textarea_blocks, $source);
-
-    // replace pre blocks
-    smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:PRE@@@",$_pre_blocks, $source);
-
-    // replace script blocks
-    smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:SCRIPT@@@",$_script_blocks, $source);
-
-    return $source;
-}
-
-function smarty_outputfilter_trimwhitespace_replace($search_str, $replace, &$subject) {
-    $_len = strlen($search_str);
-    $_pos = 0;
-    for ($_i=0, $_count=count($replace); $_i<$_count; $_i++)
-        if (($_pos=strpos($subject, $search_str, $_pos))!==false)
-            $subject = substr_replace($subject, $replace[$_i], $_pos, $_len);
-        else
-            break;
-
-}
-
-?>
diff --git a/smarty/plugins/shared.escape_special_chars.php b/smarty/plugins/shared.escape_special_chars.php
deleted file mode 100644 (file)
index c07ce31..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-/**
- * Smarty shared plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * escape_special_chars common function
- *
- * Function: smarty_function_escape_special_chars<br>
- * Purpose:  used by other smarty functions to escape
- *           special chars except for already escaped ones
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @return string
- */
-function smarty_function_escape_special_chars($string)
-{
-    if(!is_array($string)) {
-        $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string);
-        $string = htmlspecialchars($string);
-        $string = str_replace(array('%%%SMARTY_START%%%','%%%SMARTY_END%%%'), array('&',';'), $string);
-    }
-    return $string;
-}
-
-/* vim: set expandtab: */
-
-?>
diff --git a/smarty/plugins/shared.make_timestamp.php b/smarty/plugins/shared.make_timestamp.php
deleted file mode 100644 (file)
index b42eb11..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-/**
- * Smarty shared plugin
- * @package Smarty
- * @subpackage plugins
- */
-
-
-/**
- * Function: smarty_make_timestamp<br>
- * Purpose:  used by other smarty functions to make a timestamp
- *           from a string.
- * @author   Monte Ohrt <monte at ohrt dot com>
- * @param string
- * @return string
- */
-function smarty_make_timestamp($string)
-{
-    if(empty($string)) {
-        // use "now":
-        $time = time();
-
-    } elseif (preg_match('/^\d{14}$/', $string)) {
-        // it is mysql timestamp format of YYYYMMDDHHMMSS?            
-        $time = mktime(substr($string, 8, 2),substr($string, 10, 2),substr($string, 12, 2),
-                       substr($string, 4, 2),substr($string, 6, 2),substr($string, 0, 4));
-        
-    } elseif (is_numeric($string)) {
-        // it is a numeric string, we handle it as timestamp
-        $time = (int)$string;
-        
-    } else {
-        // strtotime should handle it
-        $time = strtotime($string);
-        if ($time == -1 || $time === false) {
-            // strtotime() was not able to parse $string, use "now":
-            $time = time();
-        }
-    }
-    return $time;
-
-}
-
-/* vim: set expandtab: */
-
-?>
index a1af7a98031a8db312d63b3cbb246ed9b8cdd2e4..3b06df663b898a4a723dca1d4f69497edce83478 100644 (file)
--- a/tags.php
+++ b/tags.php
@@ -1,5 +1,5 @@
-<?
-  require_once('init.php');
+<?php
+  require_once('inc/init.php');
   ldap_login();
 
   //prepare templates
diff --git a/template.php b/template.php
deleted file mode 100644 (file)
index c5e850e..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-<?
-
-/**
- * assigns some standard variables to smarty templates
- */
-function tpl_std(){
-  global $smarty;
-  global $lang;
-  global $conf;
-  global $FIELDS;
-
-  if(empty($_SESSION['ldapab']['username'])){
-    $_SESSION['ldapab']['username'] = '';
-  }
-  if(empty($_SESSION['ldapab']['binddn'])){
-    $_SESSION['ldapab']['binddn'] = '';
-  }
-
-  $smarty->assign('user',$_SESSION['ldapab']['username']);
-  $smarty->assign('binddn',$_SESSION['ldapab']['binddn']);
-  if(!empty($_SESSION['ldapab']['lastlocation'])){
-    $smarty->assign('home',$_SESSION['ldapab']['lastlocation']);
-  }else{
-     $smarty->assign('home','index.php');
-  }
-  $smarty->assign('conf',$conf);
-  $smarty->assign('lang',$lang);
-  $smarty->assign('fields',$FIELDS);
-}
-
-/**
- * assigns all the interesting data from an ldap result to
- * the smarty template
- */
-function tpl_entry($in){
-  global $smarty;
-  global $conf;
-  global $RFIELDS;
-
-  $out=array();
-
-  // handle named entries
-  foreach($RFIELDS as $key => $name){
-    if(empty($in[$key])) continue;
-
-    // keep arrays for multi fields
-    if($name{0} == '_'){
-        $name  = substr($name,1);
-        if(is_array($in[$key])){
-            $out[$name] = $in[$key];
-        }else{
-            $out[$name] = array($in[$key]);
-        }
-    }else{
-        if(is_array($in[$key])){
-            $out[$name] = $in[$key][0];
-        }else{
-            $out[$name] = $in[$key];
-        }
-    }
-  }
-
-  // set the type
-  if (empty($out['dn'])) { $out['dn']=''; }
-  $out['dn']          = normalize_dn($out['dn']);
-  $conf['publicbook'] = normalize_dn($conf['publicbook']);
-  if($out['dn']){
-      if(strstr($out['dn'],$conf['publicbook'])){
-          $out['type'] = 'public';
-      }else{
-          $out['type'] = 'private';
-      }
-  }
-
-  // join marker field to markers
-  if(is_array($out['marker'])) $out['markers'] = join(', ',$out['marker']);
-
-/*
-print '<pre>';
-print_r($out);
-print '</pre>';
-*/
-
-  $smarty->assign('entry',$out);
-}
-
-/**
- * assigns the last LDAP error to the template
- */
-function tpl_ldaperror($message=""){
-  global $LDAP_CON;
-  global $__LDAPERROR__;
-  global $smarty;
-  $errno = ldap_errno($LDAP_CON);
-  if($errno){
-    $__LDAPERROR__ .= ldap_err2str($errno);
-    if(!empty($message)){
-      $__LDAPERROR__ .= "($message)";
-    }
-    $__LDAPERROR__ .= '\n';
-  }
-  $smarty->assign("LDAPERRORS",$__LDAPERROR__);
-}
-
-/**
- * assigns all markers to the template
- */
-function tpl_markers(){
-  global $conf;
-  global $LDAP_CON;
-  global $smarty;
-
-  if(!$conf['extended']) return;
-
-  $markers = array();
-
-  $sr = ldap_list($LDAP_CON,$conf['publicbook'],"ObjectClass=inetOrgPerson",array("marker"));
-  $result1 = ldap_get_binentries($LDAP_CON, $sr);
-  //check users private addressbook
-  if(!empty($_SESSION['ldapab']['binddn'])){
-    $sr = @ldap_list($LDAP_CON,
-                    $conf['privatebook'].','.$_SESSION['ldapab']['binddn'],
-                    "ObjectClass=inetOrgPerson",array("marker"));
-    $result2 = ldap_get_binentries($LDAP_CON, $sr);
-  }else{
-    $result2 = '';
-  }
-  $result = array_merge((array)$result1,(array)$result2);
-
-  if(count($result)){
-    foreach ($result as $entry){
-      if(!empty($entry['marker']) && count($entry['marker'])){
-        foreach($entry['marker'] as $marker){
-          array_push($markers, $marker);
-        }
-      }
-    }
-  }
-  $markers = array_unique($markers);
-  sort($markers,SORT_STRING);
-
-  $smarty->assign('markers',$markers);
-}
-
-/**
- * Assigns all distinct organization names to the template
- */
-function tpl_orgs(){
-  global $conf;
-  global $LDAP_CON;
-  global $smarty;
-  global $FIELDS;
-
-  $orgs = array();
-  $result = ldap_queryabooks("ObjectClass=inetOrgPerson",array($FIELDS['organization']));
-
-  if(count($result)){
-    foreach ($result as $entry){
-      if(!empty($entry[$FIELDS['organization']][0])){
-        array_push($orgs, $entry[$FIELDS['organization']][0]);
-      }
-    }
-  }
-  $orgs = array_unique($orgs);
-  natcasesort($orgs);
-  $smarty->assign('orgs',$orgs);
-}
-
-/**
- * assigns all categories to the template
- */
-function tpl_categories(){
-  global $conf;
-  global $LDAP_CON;
-  global $smarty;
-
-  if(!$conf['openxchange']) return;
-
-  $categories = array();
-
-  $sr = ldap_list($LDAP_CON,$conf['publicbook'],"ObjectClass=OXUserObject",array("OXUserCategories"));
-  $result1 = ldap_get_binentries($LDAP_CON, $sr);
-  //check users private addressbook
-  if(!empty($_SESSION['ldapab']['binddn'])){
-    $sr = @ldap_list($LDAP_CON,
-                    $conf['privatebook'].','.$_SESSION['ldapab']['binddn'],
-                    "ObjectClass=OXUserObject",array("OXUserCategories"));
-    $result2 = ldap_get_binentries($LDAP_CON, $sr);
-  }
-  $result = array_merge((array)$result1,(array)$result2);
-
-  if(count($result)){
-    foreach ($result as $entry){
-      if(count($entry['OXUserCategories'])){
-        foreach($entry['OXUserCategories'] as $category){
-          array_push($categories, $category);
-        }
-      }
-    }
-  }
-  $categories = array_unique($categories);
-  sort($categories,SORT_STRING);
-
-  $smarty->assign('categories',$categories);
-}
-
-/**
- * assigns all timezones to the template
- */
-function tpl_timezone(){
-  global $conf;
-  global $LDAP_CON;
-  global $smarty;
-
-  if(!$conf['openxchange']) return;
-
-  $timezone = array();
-
-  $sr = ldap_list($LDAP_CON,$conf['publicbook'],"ObjectClass=OXUserObject",array("OXTimeZone"));
-  $result1 = ldap_get_binentries($LDAP_CON, $sr);
-  //check users private addressbook
-  if(!empty($_SESSION['ldapab']['binddn'])){
-    $sr = @ldap_list($LDAP_CON,
-                    $conf['privatebook'].','.$_SESSION['ldapab']['binddn'],
-                    "ObjectClass=OXUserObject",array("OXTimeZone"));
-    $result2 = ldap_get_binentries($LDAP_CON, $sr);
-  }
-  $result = array_merge((array)$result1,(array)$result2);
-
-  if(count($result)){
-    foreach ($result as $entry){
-      if(count($entry['OXTimeZone'])){
-        foreach($entry['OXTimeZone'] as $tz){
-          array_push($timezone, $tz);
-        }
-      }
-    }
-  }
-  $timezone = array_unique($timezone);
-  sort($timezone,SORT_STRING);
-
-  $smarty->assign('timezone',$timezone);
-}
-
-/**
- * assigns all countries to the template
- */
-function tpl_country(){
-  global $conf;
-  global $LDAP_CON;
-  global $smarty;
-
-  if(!$conf['openxchange']) return;
-
-  $country = array();
-
-  $sr = ldap_list($LDAP_CON,$conf['publicbook'],"ObjectClass=OXUserObject",array("userCountry"));
-  $result1 = ldap_get_binentries($LDAP_CON, $sr);
-  //check users private addressbook
-  if(!empty($_SESSION['ldapab']['binddn'])){
-    $sr = @ldap_list($LDAP_CON,
-                    $conf['privatebook'].','.$_SESSION['ldapab']['binddn'],
-                    "ObjectClass=OXUserObject",array("userCountry"));
-    $result2 = ldap_get_binentries($LDAP_CON, $sr);
-  }
-  $result = array_merge((array)$result1,(array)$result2);
-
-  if(count($result)){
-    foreach ($result as $entry){
-      if(count($entry['userCountry'])){
-        foreach($entry['userCountry'] as $c){
-          array_push($country, $c);
-        }
-      }
-    }
-  }
-  $country = array_unique($country);
-  sort($country,SORT_STRING);
-
-  $smarty->assign('country',$country);
-}
-
-?>
diff --git a/xml.php b/xml.php
deleted file mode 100644 (file)
index 2f987f7..0000000
--- a/xml.php
+++ /dev/null
@@ -1,139 +0,0 @@
-<?php
-###################################################################################
-#
-# XML Library, by Keith Devens, version 1.0
-# http://keithdevens.com/software/phpxml
-#
-# This code is Open Source, released under terms similar to the Artistic License.
-# Read the license at http://keithdevens.com/software/license
-#
-###################################################################################
-
-###################################################################################
-# XML_unserialize: takes raw XML as a parameter (a string)
-# and returns an equivalent PHP data structure
-###################################################################################
-function & XML_unserialize(&$xml){
-       $xml_parser = &new XML();
-       $data = &$xml_parser->parse($xml);
-       $xml_parser->destruct();
-       return $data;
-}
-###################################################################################
-# XML_serialize: serializes any PHP data structure into XML
-# Takes one parameter: the data to serialize. Must be an array.
-###################################################################################
-function & XML_serialize(&$data, $level = 0, $prior_key = NULL){
-       #assumes a hash, keys are the tag names
-       $xml_parts = '';
-       while(list($key, $value) = each($data)){
-               if(!strpos($key, ' attr')){ #if it's not an attribute
-                       #... we don't treat attributes by themselves.
-                       #note that implies that for an empty element that has attributes, you still
-                       #need to set the element to NULL
-
-                       $attributes = array();
-                       if(array_key_exists("$key attr", $data)){ #if there's an attribute for this element
-                               while(list($attr_name, $attr_value) = each($data["$key attr"]))
-                                       $attributes[] = $attr_name.'="'.htmlspecialchars($attr_value).'"';
-                               reset($data["$key attr"]);
-                       }
-
-                       if(is_array($value) and array_key_exists(0, $value)){
-                               #numeric array (note that you can't have numeric keys at two levels in a row)
-                               $xml_parts .= XML_serialize($value, $level, $key);
-                       }else{
-                               if($prior_key) $key = $prior_key;
-                               #(i.e. if we're in a numeric array, replace the number with the actual tag)
-
-                               $xml_parts .= str_repeat("\t", $level).'<'.$key;
-                               if($attributes) $xml_parts .= ' '.join(' ',$attributes);
-
-                               if(is_null($value))
-                                       $xml_parts .= " />\r\n";
-                               elseif(!is_array($value))
-                                       $xml_parts .= '>'.htmlspecialchars($value)."</$key>\r\n";
-                               else
-                                       $xml_parts .= ">\r\n".XML_serialize($value, $level+1).str_repeat("\t", $level)."</$key>\r\n";
-                       }
-               }
-       }
-       reset($data);
-       if($level == 0) return "<?xml version=\"1.0\" ?>\r\n".$xml_parts;
-       return $xml_parts;
-}
-###################################################################################
-# XML class: utility class to be used with PHP's XML handling functions
-###################################################################################
-class XML {
-       var $parser;   #a reference to the XML parser
-       var $document; #the entire XML structure built up so far
-       var $parent;   #a pointer to the current parent - the parent will be an array
-       var $stack;    #a stack of the most recent parent at each nesting level
-       var $last_opened_tag; #keeps track of the last tag opened.
-
-       function XML(){
-               $this->parser = &xml_parser_create();
-               xml_parser_set_option(&$this->parser, XML_OPTION_CASE_FOLDING, 0);
-               xml_set_object(&$this->parser, &$this);
-               xml_set_element_handler(&$this->parser, 'open','close');
-               xml_set_character_data_handler(&$this->parser, 'data');
-       }
-       function destruct(){
-               xml_parser_free(&$this->parser);
-       }
-       function & parse(&$data){
-               $this->document = array();
-               $this->parent   = &$this->document;
-               $this->stack    = array();
-               return xml_parse(&$this->parser, &$data, true) ? $this->document : NULL;
-       }
-       function open(&$parser, $tag, $attributes){
-               $this->data = array(); #stores temporary cdata
-               $this->last_opened_tag = $tag;
-               if(is_array($this->parent) and array_key_exists($tag,$this->parent)){ #if you've seen this tag before
-                       if(is_array($this->parent[$tag]) and array_key_exists(0,$this->parent[$tag])){ #if the keys are numeric
-                               #this is the third or later instance of $tag we've come across
-                               $key = count_numeric_items($this->parent[$tag]);
-                       }else{
-                               #this is the second instance of $tag that we've seen
-                               #shift around
-                               if(array_key_exists("$tag attr",$this->parent)){
-                                       $arr = array('0 attr'=>&$this->parent["$tag attr"], &$this->parent[$tag]);                                      unset($this->parent["$tag attr"]);
-                               }else{
-                                       $arr = array(&$this->parent[$tag]);
-                               }
-                               $this->parent[$tag] = &$arr;
-                               $key = 1;
-                       }
-                       $this->parent = &$this->parent[$tag];
-               }else{
-                       $key = $tag;
-               }
-               if($attributes)
-                       $this->parent["$key attr"] = $attributes;
-
-               $this->parent[$key] = NULL; #it turns out you can take a reference to NULL :)
-               $this->parent       = &$this->parent[$key];
-               $this->stack[]      = &$this->parent;
-       }
-       function data(&$parser, $data){
-               if($this->last_opened_tag != NULL) #you don't need to store whitespace in between tags
-                       $this->data[] = $data;
-       }
-       function close(&$parser, $tag){
-               static $just_closed = false;
-               if($this->last_opened_tag == $tag){
-                       if($this->data)
-                               $this->parent = join('',$this->data);
-                       $this->last_opened_tag = NULL;
-               }
-               array_pop($this->stack);
-               if($this->stack)
-                       $this->parent = &$this->stack[count($this->stack)-1];
-       }
-}
-function count_numeric_items(&$array){
-       return is_array($array) ? count(array_filter(array_keys($array), 'is_numeric')) : 0;
-}
-?>
\ No newline at end of file