--- /dev/null
+
+Juan Luis Francés, bacula_list AT veloxia.com
--- /dev/null
+ 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
--- /dev/null
+25-10-2004 Bacula web 1.1
+ - Add array_fill function (as Mikael suggested)
+ - Fix url encode of links. (reported by Phil Stracchino)
+ - Upgrade Smarty to 2.6.6 version.
+ - Add French translation
+
+04-08-2004 Bacula web 1.0
+ - Add Italian translation
+ - Change some colors of graphs. More clear now (I hope).
+ - (0000012) Fix, don't load config in report.php
+ - (0000015) Fix, error date in When expire? field.
+
+14-06-2004 Bacula web 1.0 Beta2
+ - (0000009) Fix incorrect date of "select report".
+ - (0000010) Fix incorrect symbolic link (Add paths.php).
+ - (0000008) Fix elapsed time of execution of jobs more than 24h in Lite mode.
+
+11-06-2004 Bacula-web 1.0 Beta1
+ - Check connection error (reported by Thomas Contamine)
+ - register_globals on/off compatible (reported by Thomas Contamine)
+ - Fix bug in graph type=69. The data now is correct.
+ - Fix config system.
+ - Very internal fixes.
+ + Add "Last report".
--- /dev/null
+This is my little contribution to the bacula community and the
+best backup software (http://www.bacula.org).
+
+OFFICIAL WEB
+*************
+Not yet.
+
+Sorry for any inconvenience, I've had no time to have this done.
+
+News and bugs: http://indpnday.com/bacula_stuff/bacula-web/mantisbt/login_page.php
+
+REQUERIMENTS:
+**************
+
+ - Web server (Tested with apache)
+ - PHP (Tested with php.4.3.4)
+ - Gettext (Optional)
+ - GD 2.x
+ - TrueType (optional)
+ - Pear DB (http://pear.php.net/package/DB)
+ - MySQL,SQLite or PgSQL
+ - Bacula (Oh!, yes, you need this ;-) ) http://www.bacula.org
+
+
+INSTALL
+*******
+- Copy this distribution to root directory or a subdirectory of your webroot.
+- Edit configs/bacula.conf with your preferences
+- Run "test.php" from your browser.
+
+
+NOTES
+*****
+- Best resolution: 1024x768
+- Best viewed with Firefox.
+- Tested with Microsoft Explorer.
+- Restart web server if language changes isn't showing itself.
+
+KNOWN BUGS
+**********
+- In Pie graphs, the margins don't work. It is a phplot bug.
+- The total elapsed time "calculation" is rudimentary. If you have 2 or more concurrency jobs this is not real.
+
+Send your bugs at this link: http://indpnday.com/bacula_stuff/bacula-web/mantisbt/login_page.php
+
+TEMPLATES
+*********
+- In this version you will have to edit code pages (*.php) to show diferent templates.
+- Bacula-web needs a good designer!!! ;-)
+
+TRANSLATIONS
+************
+- Edit "messages.po" and send me, please, with your LANGUAGE code.
+
+- You can extract strings with this command:
+$ ./tsmarty2c.php templates > lang.c
+$ xgettext lang.c
+- Now you must have this file: messages.po
+- Edit and send me, please.
+
+
+PS: Feel free to make improvements to the code. All suggestions are welcome.
+
+Temporal contact: bacula_list [at] veloxia.com
+
+
+Bacula®is a registered trademark of Kern Sibbald and John Walker
--- /dev/null
+- Add support to PDF creation.
+- Build documentation of classes.
+- Improve check errors routines.
+- Improve security. (stats.php mainly)
+- Optimize database querys (Very poor now) (TO_DAYS,etc.).
+- Autoresolution of web and graphics (Now only 1024x768)
+- Translate some code to english
+- Remove "select report" from index page. (done)
+- Add "select report" in report page (done)
+- "General Report" graph only for the last 30 days. (done)
+- SQLPrepareData - type = ALL_CLIENTS_PERIOD_REPORT
+- WebConsole!!!
+- Show Full from Lite Mode (done)
+- Calculate time to expire one volume. (done)
+- Elapsed time to report page on each client. (done)
+- Elapsed time of full execution of clients. (rudimentaryly done)
+- Graph generator for "General data".
+- Icons ;-)
+- Change template from bacula.config
+- Improve the language support
+- Multi catalog
+- Show clients and their jobs in a selectable menu.
--- /dev/null
+<?php
+
+// For PHP version < 4.2.0 missing the array_fill function,
+// I provide here an alternative. -Philippe
+
+function array_fill($iStart, $iLen, $vValue) {
+ $aResult = array();
+ for ($iCount = $iStart; $iCount < $iLen + $iStart; $iCount++) {
+ $aResult[$iCount] = $vValue;
+ }
+ return $aResult;
+}
+
+?>
\ No newline at end of file
--- /dev/null
+<?
+/*
++-------------------------------------------------------------------------+
+| Copyright (C) 2004 Juan Luis Francés Jiménez |
+| |
+| 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. |
++-------------------------------------------------------------------------+
+*/
+
+define('CONFIG_DIR', "configs");
+define('CONFIG_FILE', "bacula.conf");
+define('BACULA_TYPE_BYTES_FILES', 1);
+define('BACULA_TYPE_FILES_JOBID', 2);
+define('BACULA_TYPE_BYTES_ENDTIME_ALLJOBS', 69);
+
+require_once "paths.php";
+require_once "DB.php"; // Pear DB
+require_once($smarty_path."Config_File.class.php");
+
+if (!function_exists('array_fill')) { // For PHP < 4.2.0 users
+ require_once('array_fill.func.php');
+}
+
+class Bweb extends DB {
+
+ var $StartDate;
+ var $EndDate;
+
+
+
+ function Bweb() {
+
+ $conf = new Config_File (CONFIG_DIR);
+
+
+ $this->dsn[hostspec] = $conf->get(CONFIG_FILE,"DATABASE","host");
+ $this->dsn[username] = $conf->get(CONFIG_FILE,"DATABASE","login");
+ $this->dsn[password] = $conf->get(CONFIG_FILE,"DATABASE","pass");
+ $this->dsn[database] = $conf->get(CONFIG_FILE,"DATABASE","db_name");
+ $this->dsn[phptype] = $conf->get(CONFIG_FILE,"DATABASE","db_type"); // mysql, (sqlite, pgsql) -->> Yet not checked
+ if ( $conf->get(CONFIG_FILE,"DATABASE","db_port") )
+ $this->dsn[port] = $conf->get(CONFIG_FILE,"DATABASE","db_port");
+
+ $this->link =& $this->connect($this->dsn);
+
+ if (DB::isError($this->link))
+ die($this->link->getMessage());
+
+ register_shutdown_function(array(&$this,'close'));
+ }
+
+
+
+ function close() {
+
+ $this->link->disconnect();
+ }
+
+
+
+ function CalculateBytesPeriod($server,$StartDate,$EndPeriod) { // Bytes transferred in a period.
+
+ $result =& $this->link->query("select SUM(JobBytes) from Job WHERE EndTime < '$EndPeriod' and EndTime > '$StartDate' and Name='$server'")
+ or die("Error query row 68");
+ $return =& $result->fetchRow();
+ return $return[0];
+ }//end function
+
+
+
+ function CalculateFilesPeriod($server,$StartDate,$EndPeriod) { // Number of files transferred in a period.
+
+ $result =& $this->link->query("select SUM(JobFiles) from Job WHERE EndTime < '$EndPeriod' and EndTime > '$StartDate' and Name='$server'")
+ or die("Error query row 78");
+ $return =& $result->fetchRow();
+ return $return[0];
+ }//end function
+
+
+
+ function PrepareDate($StartDateMonth,$StartDateDay,$StartDateYear,$EndDateMonth,$EndDateDay,$EndDateYear) { // Convert date for Smarty. Check if only works with Mysql.
+
+ $this->StartDate=$StartDateYear."-".$StartDateMonth."-".$StartDateDay." 00:00:00";
+ $this->EndDate=$EndDateYear."-".$EndDateMonth."-".$EndDateDay." 23:59:59"; // last day full
+
+ }//end function
+
+
+
+ function GetDataVolumes() {
+
+ $volume = array();
+ $res = $this->link->query("SELECT Name FROM Pool");
+ while ( $tmp =& $res->fetchRow() ) {
+ $result = $this->link->query("select Media.VolumeName, Media.VolBytes,Media.VolStatus,Pool.Name,Media.MediaType,Media.LastWritten,FROM_UNIXTIME(UNIX_TIMESTAMP(Media.LastWritten)+Media.VolRetention ) as expire from Pool LEFT JOIN Media ON Media.PoolId=Pool.PoolId where Name='$tmp[0]' order by Media.VolumeName");
+ while ( $tmp1 = $result->fetchRow() ) {
+ $pos = array_key_exists($tmp[0],$volume);
+ if ($pos != FALSE)
+ array_push($volume["$tmp[0]"],$tmp1);
+ else
+ $volume += array($tmp[0]=>array($tmp1));
+ }
+ }
+
+ $res->free();
+ $result->free();
+ return $volume;
+ }
+
+}
+
+class BGraph {
+
+ var $type;
+ var $sizex;
+ var $sizey;
+ var $MarginBottom;
+ var $MarginLeft;
+ var $Leg;
+
+
+
+ function BShowGraph($datos,$title,$xlabel,$ylabel,$leyenda,$tipo="lines") {
+
+ global $type;
+
+ require_once ("external_packages/phplot/phplot.php");
+
+ if ( empty($this->sizex) || empty($this->sizey) ) { //Default size
+ $this->sizex = "600";
+ $this->sizey = "400";
+ }
+ if ( empty($this->MarginBottom) ) {
+ $this->MarginBottom = 120;
+ }
+
+ $legend = $leyenda;
+// $bgcolor = array(222,206,215); // Background color of graph
+ $bgcolor = array(207,231,231);
+ $fgcolor = array(110,41,57);
+
+
+
+ $graph = new PHPlot($this->sizex,$this->sizey,"","");
+
+ if ( !empty($type) )
+ $graph->setDataType($type);
+
+ $graph->SetDataValues($datos);
+ $graph->SetPlotType($tipo);
+// $graph->SetUseTTF(1);
+ $graph->SetBackgroundColor($bgcolor);
+
+ $graph->SetLegendPixels(1,20);
+ $graph->SetDataColors(array('SkyBlue','purple','PeachPuff','aquamarine1','#2CB04B','beige','#9F865F','#135568','orchid','navy','red', 'black', 'blue', 'green', 'brown', 'yellow','cyan','orange','#B9F5A7','#AFAFAF'));
+ $graph->SetTitle($title);
+ $graph->SetXLabel($xlabel);
+ $graph->SetYLabel($ylabel);
+ $graph->SetPlotAreaWorld("","","","");
+
+ if ( count($datos) > 5 )
+ $graph->SetXDataLabelAngle(90);
+ else
+ $graph->SetXDataLabelAngle(0);
+// $graph->SetNumXTicks(10);
+// $graph->SetXDataLabelPos('none');
+// $graph->SetXTickLabelPos('plotdown');
+
+// $graph->SetXGridLabelType("time");
+// $graph->SetXTimeFormat("%b ") ;
+
+ if ( $this->Leg == 1 ) {
+ $this->MarginLeftWithLegend($legend);
+ $graph->SetMarginsPixels($this->MarginLeft,10,35,$this->MarginBottom);
+ $graph->SetLegend($legend);
+ }
+ else
+ $graph->SetMarginsPixels(90,35,35,$this->MarginBottom);
+// $graph->SetDataColors(array($fgcolor),array( "black"));
+ $graph->SetFileFormat( "png");
+// $graph->DoScaleData(1,1);
+// $graph->DoMovingAverage(1,1,1);
+ $graph->DrawGraph();
+
+ }//end Crear
+
+
+//Estupidez que tengo que cambiar. !!!!!!!!!!!
+ function SetDataType($typ) {
+
+ global $type;
+ $type = $typ;
+ }
+
+ function MarginLeftWithLegend($clients) {
+
+ $maxlen = 0;
+
+ while (next($clients)) {
+ $tmp = strlen (current($clients));
+ if ( $tmp > $maxlen )
+ $maxlen = $tmp;
+ }
+ $this->MarginLeft = $maxlen * 11;
+ }
+
+}//end class
+
+
+
+
+
+class BCreateGraph extends BGraph {
+
+ var $BD_bacula;
+ var $izquierda;
+ var $derecha;
+ var $StartDate;
+ var $EndDate;
+ var $elapsed; // Default elapsed time to show complex graphs
+
+
+
+ function BCreateGraph() {
+
+ $this->StartDate = "1900-01-01";
+ $this->EndDate = "4000-01-01";
+ $this->elapsed = "86400"; // 24 hours in seconds.
+
+ }
+
+
+
+ function BCreate($server,$tipo_dato,$title,$tipo="bars",$xlabel="",$ylabel="") {
+
+ global $DB_bacula;
+ global $izquierda;
+ global $derecha;
+ global $clientes;
+
+ $this->clientes=array();
+ $DB_bacula = new Bweb();
+ $datos = $this->SQLPrepareData($server,$tipo_dato);
+
+ if ( empty($datos) ) { //No data = No stats = Empty graph
+ header("Content-type: image/png");
+ $img= @ImageCreate(200,100) or die ("Cannot intialize GD stream");
+ $bgc= ImageColorAllocate($img, 0, 255,255);
+ $txc= ImageColorAllocate($img, 0,0,0);
+ ImageString($img, 5, 4, 4, "None data to process", $txc);
+ ImagePng($img);
+ ImageDestroy($img);
+ return;
+ }
+
+ if ( empty ($xlabel) ) { // If no label, table names like leyends
+ $xlabel=$derecha; $ylabel=$izquierda;
+ }
+
+ $this->SetDataType("text-data");
+ $this->BShowGraph($datos,$title,$xlabel,$ylabel,$this->clientes,$tipo);
+
+ }
+
+
+
+ function SQLPrepareData($servidor,$tipo_dato=0) { // Prepare bytes data from database.
+
+ global $DB_bacula;
+ global $izquierda;
+ global $derecha;
+
+ if ( $tipo_dato<30 ) { // Simple graph. Only 2 data
+
+ switch ($tipo_dato)
+ {
+ case BACULA_TYPE_BYTES_FILES:
+ $izquierda="JobBytes";
+ $derecha="JobFiles";
+ break;
+ case BACULA_TYPE_FILES_JOBID:
+ $izquierda="JobFiles";
+ $derecha="Jobid";
+ break;
+ default:
+ $izquierda="JobBytes";
+ $derecha="EndTime";
+ break;
+ }
+ $result = $DB_bacula->link->query("select $derecha,$izquierda from Job where Name='$servidor' and EndTime < '$this->EndDate' and EndTime > '$this->StartDate' order by SchedTime asc")
+ or die ("Ivalid query row 295");
+ while ( $row = $result->fetchRow(DB_FETCHMODE_ASSOC) ) {
+ $whole_result[] = array_merge($row["$derecha"],$row[$izquierda]);
+ }
+ $result->free();
+ } else { // Complex graph. 3 or more data.
+
+ switch ( $tipo_dato )
+ {
+ case '30': // Unused, at this time.
+ $result = $DB_bacula->link->query("select JobBytes,JobFiles,Jobid from Job where Name='$servidor' order by EndTime asc")
+ or die ("Invalid query row 306");
+ while ( $row = $result->fetchRow(DB_FETCHMODE_ASSOC) )
+ $whole_result[] = array_merge($row["Jobid"],$row["JobFiles"],$row["JobBytes"]);
+ $result->free();
+ break;
+ case BACULA_TYPE_BYTES_ENDTIME_ALLJOBS: // Special: Generic graph from all clientes.
+ $i = -1; // Counter of number of jobs of one cliente. SP: Contador del número de jobs totales de un cliente.
+ $i2 = 0; // Counter of number of keys of array. SP: Contador del número de valores del array.
+
+ $res = $DB_bacula->link->query("select Name from Job where UNIX_TIMESTAMP(EndTime) > UNIX_TIMESTAMP(NOW())-$this->elapsed group by Name order by Name desc")
+ or die ("Invalid query row 316");
+ $resdata=$DB_bacula->link->query("select date_format(EndTime,\"%Y-%m-%d\") from Job where UNIX_TIMESTAMP(EndTime) > UNIX_TIMESTAMP(NOW())-$this->elapsed group by date_format(EndTime,\"%Y-%m-%d\") order by EndTime")
+ or die ("Invalid query row 318");
+
+ while ( $tmpdata = $res->fetchRow() )
+ array_push($this->clientes,$tmpdata[0]);
+
+// echo "<pre>";
+// print_r ($this->clientes);
+// echo "</pre>";
+
+
+ $spr = array(); // Temporal array
+ $spr2 = array(); // Temporal array
+ $whole_result = array();
+
+ while ( $tmpdata = $resdata->fetchRow() ) {
+ $count++;
+ array_push($spr,$tmpdata[0]);
+ $result = $DB_bacula->link->query("select date_format(EndTime,\"%Y-%m-%d\"),SUM(JobBytes),Name,count(Name) as Nname from Job WHERE EndTime like '$tmpdata[0]%' group by Name order by Name desc")
+ or die ("invalid query row 336");
+ while ( $row = $result->fetchRow(DB_FETCHMODE_ASSOC) ) {
+ $spr2 = array_merge($spr2,array($row["Name"]=>$row["SUM(JobBytes)"]));
+ $i = $result->numRows();
+ }
+
+
+// echo "<pre>";
+// print_r ($spr2);
+// echo "</pre>";
+
+ reset ($this->clientes);
+ do {
+ if ( $spr2[current($this->clientes)] != NULL)
+ array_push($spr,$spr2[current($this->clientes)]);
+ else
+ array_push($spr,0);
+ } while ( next($this->clientes) );
+
+ if ( $i2 < $i )
+ $i2 = $i;
+
+ if ( $tmpdata[0] != $row["EndTime"] )
+ array_push($whole_result,$spr);
+
+ $spr = array();
+ $spr2 = array();
+ }
+
+ for ( $i = 0; $i < count($whole_result); $i++ ) { // To equal the arrays so that the graph is not unsquared. SP:Igualamos las matrices para que la gráfica no se descuadre
+ $tmp = count($whole_result[$i]);
+ if ( $i2 < $tmp ) // Estupidez?. Check this code later...
+ continue;
+ $tmp = $i2 - $tmp;
+ for ( $a = 0; $a <= $tmp; $a++ )
+ array_push($whole_result[$i],"0"); // Fill the array
+ }
+ $resdata->free();
+// echo "DEBUG:<br>";
+// echo "<pre>";
+// print_r ($whole_result);
+// echo "</pre>";
+ break;
+
+ default:
+ break;
+ }
+ }
+// $result->free();
+ return $whole_result;
+ }//end function
+
+
+
+ //Conversión de la fecha a Mysql-format para Smarty. THE SAME FUNCTION AT 2 CLASSES. THIS WAY IS BUGGY. TO SOLVE LATER.
+ function PrepareDate($StartDateMonth,$StartDateDay,$StartDateYear,$EndDateMonth,$EndDateDay,$EndDateYear){
+
+ $this->StartDate = $StartDateYear."-".$StartDateMonth."-".$StartDateDay." 00:00:00";
+ $this->EndDate = $EndDateYear."-".$EndDateMonth."-".$EndDateDay." 23:59:00";
+
+ }//end function
+
+
+}//end class
+
+?>
\ No newline at end of file
--- /dev/null
+deny from all
--- /dev/null
+# This is the config file.
+# Please, modify with your preferences
+
+# Title of main window
+title = Bacula-Web 1.1
+
+# If http://www.domain.com/bacula/
+# root = /bacula
+root = /bacula-web
+
+# Show a box with a detailed report at index or Status report
+# I'll remove this in future versions.
+IndexReport = 0
+
+# Secs since last run. Default 24h.
+# Unused in this version
+# LastRun = 86400
+
+
+# Mode of index page: Full or Lite
+# Only useful if IndexReport = 0
+#
+# Lite: Only shows a little report for the last 24h.
+# Maybe you would want this if you have very much jobs.
+# Full: This shows a full table with detailed data
+# Maybe you would want this if you have a bit of jobs.
+mode = Lite
+
+
+
+# LANGUAGE
+# In this version only:
+# en_EN -> English
+# es_ES -> Spanish
+# it_IT -> Italian, Mantained by Gian Domenico Messina (gianni.messina AT c-ict.it).
+# fr_FR -> Frech, Mantained by Morgan LEFIEUX (comete AT daknet.org).
+lang = en_EN
+
+
+
+# DATABASE INFORMATION
+# --------------------
+# This section contains the database configuration.
+# You must create a user or to give it permissions to access
+# from web machine.
+
+[.DATABASE]
+# Your database host or IP
+host = localhost
+
+# Your database login
+login = bacula
+
+# Your database password.
+# For empty passwords use this:
+# pass =
+pass =
+
+# Your database name
+db_name = bacula
+
+# Your database type: mysql,sqlite,pgsql
+db_type = mysql
+
+# Uncomment this and modify it if your database runs on a non standard port.
+# db_port = 3306
+
--- /dev/null
+2004-01-28 19:12 migueldb
+
+ * phplot.php (rel-5-0):
+
+ + DrawGraph(): Fixed graph drawing order for default plots
+ (bars). Removed some redundant lines of code.
+
+2004-01-28 18:58 migueldb
+
+ * doc/quickstart.html (rel-5-0):
+
+ + More stuff...
+
+2004-01-28 18:49 migueldb
+
+ * phplot.php (rel-5-0):
+
+ + DrawPieChart(): fixed use of old variable.
+
+ + First steps for data labels autoadjustement and skipping.
+
+2004-01-27 12:12 migueldb
+
+ * phplot.php (rel-5-0):
+
+ + Added missing SetSkipTopTick()
+
+ + Some comments.
+
+ + Fixed option checking for a couple of functions. Added some
+ more.
+
+2004-01-27 00:03 migueldb
+
+ * doc/index.php (rel-5-0): [no log message]
+
+2004-01-25 20:28 migueldb
+
+ * doc/index.php:
+
+ + Fixed typo.
+
+2004-01-25 19:57 migueldb
+
+ * doc/index.php:
+
+ + Commit for 5.0rc1.
+
+2004-01-25 19:50 migueldb
+
+ * README.txt, doc/index.php, doc/quickstart.html, doc/schema.html:
+
+ + Commit for 5.0rc1.
+
+2004-01-25 19:44 migueldb
+
+ * phplot.php:
+
+ + Added missing SetDrawXDataLabelLines() and
+ SetDrawYDataLabelLines().
+
+ + Added some parameter checking with CheckOption().
+
+ + Added some comments.
+
+2004-01-25 19:32 migueldb
+
+ * examples/: create_chart.php, example3.php, format_chart.php:
+
+ + Commiting for 5.0rc1
+
+2004-01-25 18:21 migueldb
+
+ * examples/example8.php: [no log message]
+
+2004-01-25 18:20 migueldb
+
+ * doc/style.css:
+
+ + Added 'box' style.
+
+2004-01-25 17:11 migueldb
+
+ * phplot.php:
+
+ + Set*Colors(): should be faster when using default values.
+
+ + array_pad_array() non class-member function added.
+
+ + PadArrays(): now pads arrays with themselves, to mimic previous
+ behaviour, uses array_pad_array()
+
+ + DrawAxisLegend(): skeleton added. To do.
+
+2004-01-24 23:18 migueldb
+
+ * phplot_data.php:
+
+ + DoMovingAverage(): some corrections. The legend isn't correctly
+ updated yet.
+
+2004-01-24 23:16 migueldb
+
+ * phplot.php:
+
+ + PadArrays(): added. Formerly in SetDataValues(), now called
+ from DrawGraph(). Fixes SetLineWidths() buggy behaviour.
+
+ + Added MINY and MAXY constants, for DrawXDataLine().
+
+ + DrawGraph(): changed order when drawing axis, to avoid
+ overwriting.
+
+2004-01-21 20:08 migueldb
+
+ * doc/quickstart.html:
+
+ + More corrections
+
+ + Some links
+
+ + $Id$ tag
+
+2004-01-21 19:55 migueldb
+
+ * doc/quickstart.html:
+
+ + HTML heavily cleaned
+
+ + Some corrections
+
+2004-01-21 18:47 migueldb
+
+ * doc/index.php:
+
+ + Added quickstart.
+
+ + More things in whishlist.
+
+2004-01-21 18:46 migueldb
+
+ * doc/quickstart.html:
+
+ + Doc by Afan. With slight corrections.
+
+2004-01-21 18:43 migueldb
+
+ * phplot.php:
+
+ + Small changes to functions' documentation.
+
+2004-01-21 18:06 migueldb
+
+ * phplot_data.php:
+
+ + renamed tedious data_values to data
+
+ + work still in progress
+
+2004-01-21 18:03 migueldb
+
+ * phplot.php:
+
+ + Added check for __FUNCTION__ for old PHP versions.
+
+ + DrawPieChart(): 'data-data' support added.
+
+ + DrawGraph(): added check to avoid calling FindDataLimits()
+ twice.
+
+ + DrawXDataLine(): Added.
+
+ + DrawXDataLabels(): Added support for vertical lines to data
+ points via DrawXDataLine()
+
+ + FindDataLimits(): Added calculation of per-row min_y and max_y,
+ for DrawDataLine()
+
+2003-12-30 13:26 migueldb
+
+ * phplot.php:
+
+ + SetDataValues(). Now reads a reference and copies it to
+ $this->data, a numeric array. All indices are converted to
+ numeric. num_recs[] holds the number of records per data row.
+
+ + FindDataLimits(). Works with new $this->data
+
+ + The following functions now work with the new data set and use
+ faster loops:
+
+ + DrawDots()
+
+ + DrawDotsError()
+
+ + DrawThinBarLines()
+
+ + DrawPieChart(). Minimum changes.
+
+ + DrawLines()
+
+ + DrawArea(). Other optimizations too.
+
+ + DrawBars(). Other things too.
+
+2003-12-30 00:01 migueldb
+
+ * phplot_data.php:
+
+ + Fixed constructor. Added parameters to fit PHPlot()'s
+
+ + Fixed many "undefined index" errors.
+
+ + DoMovingAverage(): puts data in a new row, and sets colors and
+ legend. Won't work for the moment.
+
+2003-12-29 21:58 migueldb
+
+ * phplot_data.php:
+
+ + Formatted after phplot.php style (PEAR)
+
+ + Added Doxygen comments.
+
+ + DoScaleData(): Optimized with for loops. Needs testing.
+
+ + DoMovingAverage(): Optimized. Changed behaviour with first
+ elements in dataset. Needs testing.
+
+ + DoExponentialMovingAverage(): added. Needs testing.
+
+2003-12-27 14:52 migueldb
+
+ * phplot.php:
+
+ + Removed some (done) TODO marks.
+
+2003-12-27 14:06 migueldb
+
+ * examples/test_setup.php: [no log message]
+
+2003-12-27 14:06 migueldb
+
+ * examples/nav.html:
+
+ + This was unnecessary.
+
+2003-12-27 14:01 migueldb
+
+ * README.txt, LICENSE.GPL, LICENSE.PHP_3_0: [no log message]
+
+2003-12-27 13:46 migueldb
+
+ * doc/index.php:
+
+ + Added all the examples.
+
+ + Added 5.0 version number.
+
+ + Added myself as author.
+
+2003-12-27 13:44 migueldb
+
+ * examples/example9.php:
+
+ + Changed to follow phplot function renaming (again!)
+
+2003-12-24 13:39 migueldb
+
+ * examples/: create_chart.php, format_chart.php:
+
+ + New data type: randfunction, using data-data-error.
+
+2003-12-24 13:38 migueldb
+
+ * examples/: data_sample1.php, data_sample2.php, data_sample3.php,
+ data_sample4.php:
+
+ + Moved data type selection links to format_chart.php
+
+2003-12-24 13:36 migueldb
+
+ * phplot.php:
+
+ + Fixed spurious ticks bug.
+
+ + Corrected some comments.
+
+2003-12-24 12:47 migueldb
+
+ * examples/example4.php: Ooops! I deleted the wrong file!
+
+2003-12-24 12:39 migueldb
+
+ * examples/data_sample5.php:
+
+ + New 'randfunction' data type in example-o-matic. Taken from
+ deleted example4.php and test1.php.
+
+2003-12-24 12:37 migueldb
+
+ * examples/example4.php:
+
+ + Inserted example in example-o-matic as 'randfunction'
+
+2003-12-24 10:38 migueldb
+
+ * phplot.php:
+
+ + Fixed silly typo.
+
+2003-12-23 17:40 migueldb
+
+ * phplot.php:
+
+ + All renaming with leading underscores undone for compatibility.
+ It was a mess.
+
+ + Fixed a couple function call typos.
+
+ + Fixed axis position calculation.
+
+2003-12-17 16:28 migueldb
+
+ * examples/create_chart.php:
+
+ + Fixed to work with phplot.php v1.69
+
+2003-12-17 16:28 migueldb
+
+ * phplot.php:
+
+ + Added skip_left_tick and skip_right tick for x axis.
+
+ + Added y_label_angle (last commit)
+
+ + Fixed automatic axis positioning for plots with negative values
+ or log scales.
+
+ + Deleted messy SetGridParams(), SetTickParams() and
+ SetDataLabelParams(). I realized they were a bad idea of mine...
+ :(
+
+ + Some more code grouping and reorganisation.
+
+2003-12-15 16:52 migueldb
+
+ * examples/: create_chart.php, format_chart.php:
+
+ + Added x/y tick crossing lenghts.
+
+ + Added x axis and y axis positioning.
+
+ + Corrected some label placement options.
+
+2003-12-15 16:50 migueldb
+
+ * examples/: example4.php, example9.php:
+
+ + Updated examples to work with new PHPlot.
+
+ + Fixed some things.
+
+2003-12-15 16:48 migueldb
+
+ * phplot.php:
+
+ + x_tick_pos: added support for 'xaxis' position.
+
+ + x_tick_label_pos: added support for 'xaxis' position.
+
+ + DrawYTick(): fixed 'yaxis'
+
+ + Set[X|Y]TickCrossing(): added. Draw ticks crossing axis by a
+ specified length in pixels.
+
+ + DrawText(): improved vertical centering for TTF.
+
+ + SetDrawBrokenLines(): fixed silly thing.
+
+ + _DrawPlotBorder(): new option 'right' and 'sides'
+
+ + DrawLinesError(): removed some 'ifs' for speed.
+
+ + DrawDotsError(): removed some 'ifs' for speed.
+
+ + Minor corrections here and there.
+
+2003-12-13 04:58 migueldb
+
+ * phplot.php:
+
+ + DrawGraph(): Fixed drawing order error.
+
+2003-12-13 04:44 migueldb
+
+ * phplot.php:
+
+ + _SetIndexColors(): removed. When sessions were not set, indexes
+ were being calculated twice
+
+ + Centralized color and style defaults in _SetDefaultStyles()
+ (former _SetDefaultColors())
+
+ + SetLineWidth(): superseded by new SetLineWidths(). Now using an
+ array of values for per-line setting.
+
+ + DrawDashedLine(): added again for backward compatibility.
+
+ + DrawBars(): Faster shading.
+
+ + DrawYTicks(): slightly improved, DrawYTick() modified too.
+
+ + DrawGraph(): plot borders now drawn after plots.
+
+ + Added color and style variable declarations for easier
+ modification.
+
+ + More formatting. Some renaming undone for backwards
+ compatibility.
+
+2003-12-10 04:04 migueldb
+
+ * examples/: data_sample1.php, data_sample2.php:
+
+ + New plot type 'squared' added.
+
+2003-12-10 04:03 migueldb
+
+ * examples/: create_chart.php, format_chart.php:
+
+ + New option 'Draw broken lines' added.
+
+2003-12-10 04:00 migueldb
+
+ * phplot.php:
+
+ + Better available graph room usage.
+
+ + More renaming and formatting...
+
+ + Parameter validation with _CheckOption(), but I might drop it
+ if it slows everything down.
+
+ + DrawBinary() is again DrawSquared()... ooops. :) It is at least
+ now working.
+
+ + DrawSquared() done, quite silly thing, though.
+
+ + SetBrokenLines() added. Tells whether to draw lines for missing
+ Y data.
+
+2003-12-10 01:32 migueldb
+
+ * doc/schema.html:
+
+ + Simple [go to index] link.
+
+ + Typos fixed.
+
+2003-12-10 00:56 migueldb
+
+ * phplot.php:
+
+ + Reworking PEAR coding standards conformance, I had quite
+ screwed it up. Vim regexes are proving veeeery useful ;)
+
+ + Important comment about the destructor and class instantiation.
+
+ + Internal methods will now have a prepended underscore. I'm
+ renaming them little by little.
+
+ + SetDefaultDashedStyle(): now accepts any string as style.
+
+ + DrawSquared() renamed to DrawBinary()
+
+ + _CalcMargins(): corrected [x|y]_tick_label_width calculation.
+
+2003-12-07 18:58 migueldb
+
+ * examples/: example6.php, example7.php:
+
+ + SetDrawXDataLabels(false);
+
+2003-12-07 18:30 migueldb
+
+ * phplot.php:
+
+ + DrawDotsError(): doesn't fail anymore if data type isn't
+ data-data-error (might include text-data-error in the future).
+
+ + More variables changed to bool.
+
+ + SetNewPlotAreaPixels(): removed, SetPlotAreaPixels() now does
+ the same work.
+
+ + SetMarginsPixels(): now updates margin variables.
+
+ + SetTitle(): fixed wrong height calc for empty title.
+
+ + Removed many internal variable declarations. See the beggining
+ of the class declaration for comments on this. This might be a
+ bit stupid... :-?
+
+ + DrawSquared(): plot type on the works, addressing Feature
+ Request [558302]. Just the skeleton for now.
+
+2003-12-07 02:12 migueldb
+
+ * phplot.php:
+
+ + SetInputFile(): deallocates previously allocated 'img'
+
+ + Added 'line_spacing' and SetLineSpacing()
+
+ + InitImage(): deleted, moved into the constructor
+
+ + DrawError(): shows plain text message if 'img' unavailable.
+
+ + SetXTitle(): Fixed x_title_height calculation for TTF.
+
+ + More code reorganisation. As I seem to be alone in this, that
+ should be no problem...
+
+2003-12-07 01:12 migueldb
+
+ * phplot.php:
+
+ + TTF font provided with package now works (it wasn't being
+ found).
+
+ + TTF placement a bit adjusted.
+
+ + SetTitle(): Fixed wrong title height calculation for TTFonts.
+
+ + DrawLegend(): TTF support added.
+
+ + DrawDot(): renamed dot type 'crosshair' to 'plus'. Added
+ 'cross' and 'trianglemid'.
+
+ + FormatTickLabel(): now used for tick and data labels. Renamed
+ to FormatLabel().
+
+ + draw_x_data_label: variable removed, now using
+ [x/y]_data_label_pos for both x and y data labels.
+
+ + draw_x_data_label_lines: parameter added.
+
+ + line_width: minor usage fixes.
+
+ + SetXDataLabelAngle() renamed to SetXLabelAngle(). Old function
+ kept in 'deprecated' section.
+
+ + Changed some options to bool format.
+
+ + Tried to make better decisions on Set*LabelParams() regarding
+ placement.
+
+ + Removed superfluous DrawLabels() function.
+
+ + Moved CalcXHeights() and CalcYWidths() into CalcMargins() for
+ speed (unperceptible I must admit) and clarity.
+
+ + Other changes here and there...
+
+2003-12-07 01:06 migueldb
+
+ * examples/data_sample2.php:
+
+ + Added missing data.
+
+2003-12-07 01:05 migueldb
+
+ * examples/: create_chart.php, data_sample1.php: [no log message]
+
+2003-12-07 01:04 migueldb
+
+ * examples/format_chart.php:
+
+ + Added a check to see if we are being called from the right
+ place.
+
+ + New data label angle option.
+
+ + New line and error bar line width options.
+
+ + New data label options.
+
+ + New point types.
+
+ + Some corrections.
+
+2003-12-06 21:12 migueldb
+
+ * examples/nav.html: [no log message]
+
+2003-12-06 21:09 migueldb
+
+ * examples/test_setup.php:
+
+ + Added nav. bar
+
+2003-12-06 21:08 migueldb
+
+ * examples/nav.html:
+
+ + Simple navigation bar, not very useful yet.
+
+2003-12-06 20:43 migueldb
+
+ * doc/style.css:
+
+ + New "nav" class.
+
+2003-12-06 20:42 migueldb
+
+ * doc/index.php:
+
+ + New index, now calls some php.
+
+2003-12-06 20:41 migueldb
+
+ * doc/php_test.php:
+
+ + Added the test for php functionality in index.php, so this file
+ is no longer necessary.
+
+2003-12-05 19:13 migueldb
+
+ * examples/inline_image.php:
+
+ + Added warning message when called on its own.
+
+2003-11-28 01:21 migueldb
+
+ * phplot.php:
+
+ + Default title position='none' for better positioning of
+ elements.
+
+ + xtr(), yrt(): return value round()ed
+
+ + DrawLines(): better (?) management of incomplete data sets. No
+ begin or end points forced. No more "undefined offset x in ..."
+
+ + DrawArea(): more modifications when working with incomplete
+ data sets. No extra beginning or ending points.
+
+2003-11-26 17:52 migueldb
+
+ * phplot.php: [no log message]
+
+2003-11-26 17:16 migueldb
+
+ * examples/: create_chart.php, format_chart.php:
+
+ + Added shading option
+
+2003-11-26 16:43 migueldb
+
+ * phplot.php:
+
+ + Added spaces after every comma, around every equal sign for
+ prettier code. :)
+
+ + DrawXTitle(): Another fix. Removed the check for tick_pos I
+ just introduced. Works better now.
+
+ + _PHPlot(): destructor added.
+
+ + Comments, indenting, and a couple of minor corrections here and
+ there.
+
+2003-11-26 12:19 migueldb
+
+ * phplot.php: l
+
+ + DrawXTitle(): check for tick_label_pos when calculating title
+ position (before the title would be misplaced under certain
+ circumstances)
+
+ + Added SetIndexDarkColor() and $ndx_data_dark_color[] calculated
+ from $data_colors[], for shadows.
+
+ + New data type (one value per data row) 'text-data-once' for pie
+ charts
+
+ + DrawPieChart(): some optimisations. Shading added.
+
+2003-11-25 17:30 migueldb
+
+ * examples/create_chart.php:
+
+ + Now accepts point size from format_chart.php.
+
+2003-11-25 17:29 migueldb
+
+ * examples/format_chart.php:
+
+ + New point type 'crosshair' added to the options.
+
+ + Link to the documentation index at the bottom of the page.
+
+2003-11-25 17:28 migueldb
+
+ * examples/data_sample1.php:
+
+ + Fixed wrong comment.
+
+2003-11-25 17:28 migueldb
+
+ * phplot.php:
+
+ + DrawDot(): added new variables to avoid calls to ytr() and
+ xtr(), replaced imagefilledrectangle() with imageline() in
+ "halfline" and "line" modes.
+
+ + DrawDot(): added point type 'crosshair'
+
+ + DrawArea(): modified to follow the structure of the other plot
+ drawing methods. Removed obsolete DrawAreaSeries()
+
+ + DrawLines(): same modifications as with other plot drawing
+ methods.
+
+ + Removed dummy DrawLineSeries()
+
+ + More use of imagesetthickness()
+
+2003-11-25 01:34 migueldb
+
+ * phplot.php: Right now working on richer data label placement, but
+ in the meantime:
+
+ + Removed unnecessary (and wrong) right alignment option in
+ FormatTickLabel()
+
+ + Removed unused (thought it better :) DrawPlotLabel
+
+ + DrawYErrorBar(): uses imagesetthickness()
+
+ + DrawDots() optimised and cleaned.
+
+ + DrawThinBarLines() optimised and cleaned.
+
+ + DrawDotsError() optimised (I hope!)
+
+ + DrawLinesError() optimised. Fixed a bug with multiple lines
+
+ + Other small things, as usual...
+
+2003-11-25 01:27 migueldb
+
+ * examples/data_sample2.php:
+
+ + Removed bogus <td> tag.
+
+2003-11-25 00:49 migueldb
+
+ * examples/data_sample4.php:
+
+ + Added 'thinbarline' data plot option.
+
+2003-11-25 00:48 migueldb
+
+ * examples/data_sample1.php:
+
+ + Added thinbarline plot mode.
+
+ + Added comment on 'text-data' data type.
+
+2003-11-24 23:32 migueldb
+
+ * examples/: data_sample1.php, data_sample2.php, data_sample4.php,
+ format_chart.php:
+
+ + Replaced old data type "linear" with new "data" everywhere.
+
+2003-11-24 23:32 migueldb
+
+ * examples/create_chart.php:
+
+ + Accepts new $data_row format from data_sample3.php
+ (data-data-error format)
+
+ + Replaced old data type "linear" with new "data".
+
+2003-11-24 23:30 migueldb
+
+ * examples/data_sample3.php:
+
+ + Replaced old "linear" with new "data" everywhere.
+
+ + Modified code and $data_row organization to allow for easier
+ changes.
+
+ + Added another set of values (to have two lines in the example)
+
+2003-11-24 21:06 migueldb
+
+ * examples/data_sample3.php:
+
+ + Removed bogus <td> tag
+
+ + Added slashes to input tags end
+
+2003-11-24 17:44 migueldb
+
+ * phplot.php:
+
+ + Fixed a typo.
+
+2003-11-24 17:00 migueldb
+
+ * doc/style.css:
+
+ + Added new classes for the docs.
+
+2003-11-24 16:37 migueldb
+
+ * phplot.php:
+
+ + Added SetDefaultDashedStyle()
+
+ + Replaced outdated call to imagesetstyle() with SetDashedStyle()
+
+ + Moved the check for dashed_grid from constructor (where it
+ could lead to strange behaviour) into DrawXTicks() and
+ DrawYticks() (BTW, shouldn't these be renamed?)
+
+2003-11-24 16:12 migueldb
+
+ * examples/: data_sample1.php, data_sample2.php, data_sample3.php,
+ data_sample4.php:
+
+ + HTML tags to lowercase.
+
+ + Added missing closing tags.
+
+ + Indented code.
+
+2003-11-24 16:05 migueldb
+
+ * examples/create_chart.php:
+
+ + Modified to work with the new format_chart.php
+
+2003-11-24 16:04 migueldb
+
+ * examples/format_chart.php:
+
+ + New layout
+
+ + Many new options
+
+ + Some introductory words
+
+ + Removed "you have to reload" warning (the default behaviour for
+ PHPlot now is to send no-cache header)
+
+ + Small corrections
+
+2003-11-24 14:46 migueldb
+
+ * phplot.php:
+
+ + Added checks for tick placement in CalcMargins()
+
+ + Uninportant renaming of some internal variables.
+
+2003-11-24 14:25 migueldb
+
+ * phplot.php:
+
+ + Some more renaming for consistency: vtick, vert_tick, etc are
+ now y_tick_
+
+ + Same for htick -> x_tick_
+
+ + + Draw*Ticks() renamed following the same scheme
+
+ + Grouped tick label parameter setting functions in
+ SetTickLabelParams(). Left original ones in 'deprecated'
+
+ + Grouped grid parameter setting functions in SetGridParams().
+ Left original ones in 'deprecated'
+
+ + Grouped Title setting and positioning in Set*Title(). Left
+ original ones in 'deprecated'
+
+ + Slight modifications to data label placement
+
+2003-11-23 23:53 migueldb
+
+ * phplot.php:
+
+ + Corrected a typo.
+
+2003-11-23 23:39 migueldb
+
+ * phplot.php:
+
+ + Restructured internal font management: font variables are now
+ hashes with all associated info. DrawText() now only needs that
+ and chooses whether to draw TrueType or not. Almost every "if
+ ($this->use_ttf)" check removed as a result.
+
+ + Added SetDefaultTTFont()
+
+ + When drawing pie charts (no axis titles nor labels), maximize
+ plot area.
+
+2003-11-23 21:42 migueldb
+
+ * doc/schema.html: [no log message]
+
+2003-11-23 21:37 migueldb
+
+ * doc/: style.css, php_test.php:
+
+ + First commit
+
+2003-11-23 21:36 migueldb
+
+ * examples/test_setup.php:
+
+ + Added stylesheet
+
+ + Silly change
+
+2003-11-23 21:35 migueldb
+
+ * examples/inline_image.php:
+
+ + Silly change
+
+2003-11-23 21:34 migueldb
+
+ * examples/create_chart.php:
+
+ + Renamed SetYLabel() and SetXLabel() to SetYTitle() and
+ SetXTitle()
+
+2003-11-23 21:33 migueldb
+
+ * examples/format_chart.php:
+
+ + Added file format option
+
+ + Added stylesheet
+
+2003-11-23 20:00 migueldb
+
+ * phplot.php:
+
+ + DrawText(): horizontal (left, center and right) and vertical
+ (top, center, bottom) alignment finished.
+
+ + Replaced all outdated ocurrences of ImageString() with calls to
+ DrawText().
+
+ + Removed redundant text placement calculations.
+
+ + DrawLegend() now draws the legend box more accurately (final
+ solution to bug #527867)
+
+2003-11-23 02:02 migueldb
+
+ * phplot.php:
+
+ + tick_length and tick_length2 now are htick_length and
+ vtick_length.
+
+ + Included SetHTickLength() and SetVTickLength()
+
+ + Fixed silly bug with SetDefaultFonts()
+
+ + SetUseTTF() now resets the fonts.
+
+ + More room for title
+
+2003-11-22 23:40 migueldb
+
+ * phplot.php:
+
+ + Somewhat clearer naming convention for labels, ticks, titles
+ and fonts.
+
+ + X tick labels and X Title can be: plotdow, plotup, both, none
+
+ + Y tick labels and Y Title can be: plotleft, plotright, both,
+ none
+
+ + Renamed some Set*() internal functions to Calc*() (Set
+
+ + is to be left for "public" methods)
+
+ + More doxygen comments
+
+ + Optimised FindDataLimits()
+
+ + A few bugfixes
+
+2003-11-22 18:04 migueldb
+
+ * examples/test_setup.php:
+
+ + Added wbmp format
+
+ + Now using imagetypes() instead of function_exists()
+
+2003-11-22 13:57 migueldb
+
+ * examples/test_setup.php:
+
+ + Graphic formats availability checks now use function_exists()
+
+ + HTML code restructured.
+
+2003-11-22 13:55 migueldb
+
+ * examples/create_chart.php:
+
+ + Using $_GET and $_POST
+
+ + SetImageFormat() option added
+
+2003-11-22 13:54 migueldb
+
+ * examples/format_chart.php:
+
+ + HTML code rewritten, better layout
+
+ + Image format option
+
+2003-11-22 03:02 migueldb
+
+ * phplot.php:
+
+ + Improved datalabel_font
+
+ + + Added SetDatalabelFontSize()
+
+ + Added many more doxygen comments.
+
+ + Other micro-changes.
+
+2003-11-22 02:06 migueldb
+
+ * examples/inline_image.php:
+
+ + register_globals default (PHP4) setting taken into account
+
+2003-11-22 01:46 migueldb
+
+ * phplot.php:
+
+ + Bug #790745 fixed. Thx. to the poster.
+
+ + DrawError() now accepts position and centers text
+
+ + '[423202] Catch error on empty arrays' solved. No more 'divide
+ by zero's
+
+ + Some (random) doxygen comments inserted. It might be a good
+ idea for auto-docs.
+
+2003-11-21 22:27 migueldb
+
+ * phplot.php: My first commit, here are the changes (that I
+ remember)
+
+ + Y axis tick and label options now work
+
+ + X axis tick and label options: plotdown,plotup,both,none
+
+ + Implemented tick_length2 for rightmost/upper side
+
+ + More default data colors assigned to data_color and error_color
+ arrays
+
+ + Deprecated draw_vert_ticks and SetDrawVertTicks() in favor of
+ 'none' value in vert_tick_position
+
+ + Better? upper,lower, rightmost margin calculation
+
+ + Dashed grid lines
+
+ + Added FormatTickLabel(). Removed redundant code in
+ DrawHorizontalTicks()
+
+ + Removed all calls left to DrawDataLabel(), moved to
+ "deprecated"...
+
+ + Moved some code and functions around.
+
+ + Attempted correction for Bug [440065] "Pie labels not centered
+ correctly"
+
+ + Corrected '$which_pt not an acceptable plot type' typo [682068]
+
+ + Now using SetFileFormat() for PHP4
+
+ + Bug [484235] might be solved by now (not sure!)
+
+2003-11-21 20:42 migueldb
+
+ * examples/create_chart.php: Now works with register_globals off
+
+2002-06-21 01:35 afan
+
+ * examples/test_setup.php: Testing update: (Moved GIF to last
+ check)
+
+2002-04-30 15:25 afan
+
+ * phplot.php: Fixed error in pie graphs with data=0. Changed
+ functions and tabs to PEAR standards
+
+ Afan
+
+2002-02-22 03:15 afan
+
+ * phplot.php: No changes - just settting up new server
+
+2001-04-19 03:03 afan
+
+ * phplot.php, examples/inline_image.php: fix error on function
+
+2001-04-19 00:18 mdj_guardian
+
+ * phplot.php: Fixed problem with example 8. Also modified the
+ default y_padding value so the examples with zero on the bottom
+ turn out that way.
+
+2001-04-18 07:18 mdj_guardian
+
+ * phplot.php: Made the following changes:
+
+ + Fixed the case of built in functions to match PHP documentation
+
+ + Modified SetFileFormat to work in PHP3 & 4 with no changes
+
+ + Improved auto-scaling signifcantly (SetVertPadding, y_padding,
+ SetPlotAreaWorld) (needs docs and examples)
+
+ + Fixed a problem in DrawDashedLine when the line segments were
+ zero length
+
+ + Modified DrawLegend to fix positioning of lower right corner of
+ box. Was cutting through text
+
+ + Removed a duplicated line in FindDataLimits
+
+2001-04-08 15:58 afan
+
+ * phplot.php: Minor change to formatting
+
+2001-03-27 07:42 afan
+
+ * phplot.php, phplot_data.php, examples/data.php,
+ examples/data_sample1.php, examples/data_sample3.php,
+ examples/example1.php, examples/example2.php,
+ examples/example3.php, examples/example4.php,
+ examples/example6.php, examples/example7.php,
+ examples/example8.php, examples/example9.php,
+ examples/format_chart.php, examples/inline_image.php,
+ examples/test_setup.php: Committing 4.4.6
+
+2001-03-19 16:08 afan
+
+ * phplot.php, doc/user_functions.html: Cleaned up Shading Function
+ for Bars Bug Fix in Placement of Datalabels.
+
+2001-03-17 16:40 afan
+
+ * examples/: data.php, data_date.php, data_date2.php,
+ data_sample1.php, data_sample2.php, data_sample3.php,
+ example1.php, example2.php, example3.php, example6.php,
+ example7.php, example8.php, example9.php, format_chart.php,
+ inline_image.php, test_setup.php: changed examples from ? to ?php
+ format.
+
+2001-03-16 13:59 afan
+
+ * phplot.php: Error in line 361 corrected.
+
+2001-03-16 03:10 afan
+
+ * phplot.php: Major updates to DrawDots and DrawBars to make it
+ easy to put labels and dots overwriting bars. Code optimizations
+ and checks to make sure you don't need to set error_reporting(0).
+
+2001-03-09 19:58 afan
+
+ * phplot.php: Minor bug fixes
+
+2001-03-01 17:47 afan
+
+ * README.txt, phplot.php, rgb_small.inc.php, examples/example8.php:
+ Bug on line 164 corrected Removed rgb_small.inc.php
+
+2001-02-27 17:49 afan
+
+ * phplot.php: Added ability to use background Images with plots
+ Changed Image Color Allocation to work even with background
+ Images Note: this change requires usage of PHPLOT 3.0.2 or later.
+
+2001-02-23 21:22 afan
+
+ * phplot.php, phplot_data.php, examples/example3.php,
+ examples/example6.php, examples/example9.php: DrawText,
+ SetRGBColor, Sessions fixes
+
+2001-02-16 16:40 afan
+
+ * phplot.php, examples/example1.php: Added output_file and
+ input_file Added Constructor Added check to see if an image index
+ has already been added for smaller files
+
+2001-02-14 21:06 afan
+
+ * phplot.php, examples/example1.php: Added Function SetColorIndex
+ for operating on image color indexes directly Also checks to see
+ if the color has already been defined for image size
+ optimization.
+
+2001-02-13 20:50 afan
+
+ * phplot.php, examples/example1.php: Minor Bugfix
+
+2001-02-13 18:16 afan
+
+ * phplot.php, examples/data.php, examples/example2.php,
+ examples/example3.php, examples/example4.php: Title
+ modifications, added movable Y axis
+
+2001-02-12 14:54 afan
+
+ * examples/example8.php: Adding example8: two plots on one image
+
+2001-02-09 18:56 afan
+
+ * phplot.php: Added SetYAxisPosition and changed DrawYAxisCode
+
+2001-02-09 10:14 afan
+
+ * phplot.php: Added Title return lines
+
+2001-02-08 05:35 afan
+
+ * README.txt, phplot.php, doc/user_functions.html,
+ doc/user_internal_functions.html, examples/data.php,
+ examples/example1.php, examples/example4.php: Added Error Bar
+ Widths, Missing Data Handling, Minor bugfix, More docs
+
+2001-01-29 05:51 afan
+
+ * phplot.php, examples/create_chart.php, examples/example7.php:
+ Added NumHorizTicks, fixed bug in example 7
+
+2001-01-23 05:09 afan
+
+ * doc/user_functions.html: Doc Fix
+
+2001-01-23 05:04 afan
+
+ * phplot.php: Minor Changes
+
+2001-01-23 05:03 afan
+
+ * phplot.php, doc/internal_functions.html, doc/user_functions.html:
+ Updated Documentation
+
+2001-01-23 04:36 afan
+
+ * phplot.php, examples/example3.php: Minor bug fixes.
+
+2001-01-23 01:33 afan
+
+ * phplot.php: Minor fix to phplot after major update
+
+2001-01-23 01:06 afan
+
+ * README.txt, phplot.php, phplot_data.php,
+ examples/create_chart.php, examples/data.php,
+ examples/data_date.php, examples/data_date2.php,
+ examples/example2.php, examples/example4.php,
+ examples/example6.php, examples/example7.php, examples/test1.php:
+ Lots changed: easier to make multiple images, logs, etc.
+
+2001-01-17 04:05 afan
+
+ * phplot.php: [no log message]
+
+2001-01-17 03:42 afan
+
+ * phplot.php: Implemented Log Plots. Very little error checking
+
+2001-01-17 03:41 afan
+
+ * phplot.php: Log plots implemented. Very little data error
+ checking.
+
+2001-01-14 03:02 extensive
+
+ * phplot.php, phplot_data.php, doc/internal_functions.html,
+ doc/user_functions.html: Changed ReportError to DrawError
+ respectively PrintError, added new functionality to PHPlot_data
+ and added some documentation of PHPlot_data
+
+2001-01-11 18:43 afan
+
+ * phplot.php, doc/internal_functions.html: Added documentation.
+
+2001-01-11 17:07 afan
+
+ * create_chart.php, data_sample1.php, data_sample2.php,
+ data_sample3.php, data_sample4.php, doc.htm, format_chart.php,
+ phplot.php, doc/examples.html, doc/function_reference.html,
+ doc/index.html, doc/internal_functions.html, doc/quick_start.php,
+ doc/user_functions.html, doc/user_internal_functions.html,
+ examples/benjamingothic.ttf, examples/create_chart.php,
+ examples/data_sample1.php, examples/data_sample2.php,
+ examples/data_sample3.php, examples/data_sample4.php,
+ examples/format_chart.php, examples/inline_image.php,
+ examples/test_setup.php: Major change to structure of PHPLOT. Doc
+ directory, moved examples to examples directory.
+
+2001-01-11 16:25 extensive
+
+ * phplot.php: just added ReportError() and changed all DrawError()
+ calls to use ReportError(). phplot seems to be broken on my
+ system but I don't think it is my fault (this was the first time
+ I was testing a 3.7.x version), let's address that later. Is it
+ broken on your system, too, Afan?
+
+2001-01-11 02:14 extensive
+
+ * phplot.php, phplot_data.php: I just corrected some typos (mostly
+ my name being misspelled ;-)
+
+2001-01-08 00:53 afan
+
+ * doc.htm, phplot.php, phplot_data.php: Added Plot Border types
+
+2001-01-07 00:35 afan
+
+ * doc.htm, phplot_data.php: Adding phplot_data for release 3.7.0
+
+2001-01-07 00:30 afan
+
+ * examples/: data.php, example1.php, example2.php, example3.php,
+ example4.php, example5.php, rgb.inc.php, test1.php: Adding
+ PHPLOT_DATA routines. Defining the first sub-class. Added
+ examples: Afan
+
+2001-01-07 00:23 afan
+
+ * README.txt, create_chart.php, data_sample3.php, doc.htm,
+ phplot.php, stocks.php, stocks1.php, test1.php: 3.6.4 Committed
+
+2000-12-13 22:02 afan
+
+ * phplot.php: Allowing data in time_format but printed using
+ strftime
+
+2000-12-13 04:47 afan
+
+ * doc.htm, phplot.php, stocks.php: ver 3.2.1 and New Docs
+
+2000-12-11 18:03 afan
+
+ * create_chart.php, data_sample2.php, format_chart.php, phplot.php:
+ Release version 3.2.0
+
+2000-11-29 17:12 afan
+
+ * README.txt, benjamingothic.ttf, create_chart.php,
+ data_sample1.php, data_sample2.php, data_sample3.php,
+ data_sample4.php, doc.htm, format_chart.php, phplot.php,
+ rgb.inc.php, rgb_small.inc.php, stocks.php, stocks1.php,
+ test1.php: Initial revision
+
+2000-11-29 17:12 afan
+
+ * README.txt, benjamingothic.ttf, create_chart.php,
+ data_sample1.php, data_sample2.php, data_sample3.php,
+ data_sample4.php, doc.htm, format_chart.php, phplot.php,
+ rgb.inc.php, rgb_small.inc.php, stocks.php, stocks1.php,
+ test1.php: The first upload! Afan Ottenheimer
+
--- /dev/null
+ 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.
--- /dev/null
+--------------------------------------------------------------------
+ The PHP License, version 3.0
+Copyright (c) 1999 - 2003 The PHP Group. All rights reserved.
+--------------------------------------------------------------------
+
+Redistribution and use in source and binary forms, with or without
+modification, is permitted provided that the following conditions
+are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ 3. The name "PHP" must not be used to endorse or promote products
+ derived from this software without prior written permission. For
+ written permission, please contact group@php.net.
+
+ 4. Products derived from this software may not be called "PHP", nor
+ may "PHP" appear in their name, without prior written permission
+ from group@php.net. You may indicate that your software works in
+ conjunction with PHP by saying "Foo for PHP" instead of calling
+ it "PHP Foo" or "phpfoo"
+
+ 5. The PHP Group may publish revised and/or new versions of the
+ license from time to time. Each version will be given a
+ distinguishing version number.
+ Once covered code has been published under a particular version
+ of the license, you may always continue to use it under the terms
+ of that version. You may also choose to use such covered code
+ under the terms of any subsequent version of the license
+ published by the PHP Group. No one other than the PHP Group has
+ the right to modify the terms applicable to covered code created
+ under this License.
+
+ 6. Redistributions of any form whatsoever must retain the following
+ acknowledgment:
+ "This product includes PHP, freely available from
+ <http://www.php.net/>".
+
+THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
+ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
+DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+--------------------------------------------------------------------
+
+This software consists of voluntary contributions made by many
+individuals on behalf of the PHP Group.
+
+The PHP Group can be contacted via Email at group@php.net.
+
+For more information on the PHP Group and the PHP project,
+please see <http://www.php.net>.
+
+This product includes the Zend Engine, freely available at
+<http://www.zend.com>.
--- /dev/null
+This is a class for creating scientific and business charts.
+To start extract the files with
+
+ tar -zxvf phplot-5.0rc1.tar.gz
+
+and then point your browser to
+
+ doc/index.php.
+
+There are some configuration settings that you will need to make
+based on your setup.
+
+1. File Type: Depending on the version of GD you are using,
+ you may or may not have GIF or PNG file ability. That is
+ set with the function.
+
+ SetFileFormat("<filetype>") where <filetype> is png, gif, jpeg, ...
+
+ or edit the file phplot.php and change the line
+
+ var $file_format = "<filetype>";
+
+2. TTF: If you have TTF installed then use (and read the docs)
+
+ SetUseTTF(TRUE);
+
+ otherwise use
+
+ SetUseTTF(FALSE);
+
+Everything else should be independent of what version you are using.
+This has been tested with PHP3, PHP4, GD1.2 and GD 3.8.
+
+To start please see doc/index.php. There you'll find examples, tests and
+some introductory documents.
+
+--------------------------
+
+This is distributed with NO WARRANTY and under the terms of the GNU GPL
+and PHP licenses. If you use it - a cookie or some credit would be nice.
+
+You can get a copy of the GNU GPL at http://www.gnu.org/copyleft/gpl.html
+You can get a copy of the PHP License at http://www.php.net/license.html
+
+See http://www.sourceforge.net/projects/phplot/ for the latest changes.
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!-- $Id$ -->
+<html>
+<head>
+ <title>Welcome to PHPlot</title>
+ <link type="text/css" rel="stylesheet" href="style.css" />
+</head>
+<body>
+
+<h2>Welcome to PHPlot 5.0</h2>
+<table border="0">
+ <tr>
+ <td valign="top">
+ <p>
+ PHPlot is a <a href="http://www.php.net">PHP4</a> class for on the fly graphs
+ generation. It was started by
+ <a href="mailto:afan AT jeo DOT net">Afan Ottenheimer</a> in 2000 as an
+ opensource project, and is now co-developed with
+ <a href="mailto:nonick AT 8027 DOT org">Miguel de Benito</a> thanks to
+ <a href="http://sourceforge.net">sourceforge</a>. It is distributed under
+ the terms of the
+ <a href="http://www.gnu.org/copyleft/gpl.html"> GNU General Public License</a>,
+ and the <a href="http://www.php.net/license.html">PHP license</a>. You can always
+ obtain the latest source from the <a href="http://sourceforge.net/projects/phplot/">
+ sourceforge project page</a>, please do also check CVS, we try to have it always working
+ there.
+ </p>
+ <p>For further information, please check <a href="http://www.phplot.com">
+ our website</a>
+ </p>
+ </td>
+ <td>
+ <table border="0">
+ <tr><td><img src="imgs/graph1.png" /></td></tr>
+ <tr><td class="imgfoot">Example line graph with labels, legend
+ and left and lower axis titles.</td></tr>
+ </table>
+ </td>
+ </tr>
+</table>
+
+
+<h3>Features</h3>
+<table border="0">
+ <tr>
+ <td>
+ <table border="0">
+ <tr><td><img src="imgs/graph3.png" /></td></tr>
+ <tr><td class="imgfoot">Example 3d pie chart.</td></tr>
+ </table>
+ </td>
+ <td>
+ <p>
+ Here goes a (incomplete) list, in no particular order.:
+ <ul>
+ <li>Several different graph types: lines, bars, points, areas, pie, squared.</li>
+ <li>text-data, data only and data-error data types accepted.</li>
+ <li>3D shading for pie and bar graphs.</li>
+ <li>Different line types: solid and wholly customizable dashed ones.</li>
+ <li>Can draw error margins along y-axis when supplied in data. </li>
+ <li>Highly customizable canvas: titles, labels and ticks can be
+ placed anywhere, with any color and everything gets automagically placed without overlapping.</li>
+ <li>Vertical and horizontal grids.</li>
+ <li>Legend. Different types on the works. </li>
+ <li>TrueType font support.</li>
+ <li>Linear and logaritmic scales.</li>
+ <li>Several output formats: jpeg, png, gif, wbmp (those supported by your GD)</li>
+ </ul>
+ And here a short to-do/whishlist:
+ <ul>
+ <li>Horizontal bars.</li>
+ <li>Simple isometric 3D plots.</li>
+ <li>Automatic placement of several plots in one image.</li>
+ <li>Better or automatic management of many drawing options (ticks, labels, etc.)</li>
+ <li>Subclassing for optimisation: move features into subclasses for optional use
+ and leave a fast core.</li>
+ </ul>
+ </p>
+ </td>
+ </tr>
+</table>
+
+
+<h3>Requirements</h3>
+<p>
+We are not sure about exact requirements, but at least PHP 4.1.0 and
+GD Lib 2 are necessary. Feedback is welcome.
+</p>
+
+
+<h3>Quick start</h3>
+<p>You can rush for a quick start <a href="quickstart.html">here</a>.</p>
+
+
+<h3>Tests and examples</h3>
+<p>
+These examples make use of many, but not all, of the features present in PHPlot.
+The best one is the example-o-matic, where you can alter many parameters. Please proceed
+to any of them:
+<ul>
+ <li><a href="../examples/test_setup.php">GD setup test</a></li>
+ <li>Examples:</li>
+ <ul>
+ <li><a href="../examples/format_chart.php">Example-o-matic</a>.
+ Create most of the plot types with all data types and tweak most of the parameters.</li>
+ <li><a href="../examples/example1.php">Simple lines chart</a></li>
+ <li><a href="../examples/example2.php">Another one</a></li>
+ <li><a href="../examples/example3.php">Scaled data (with phplot_data)</a></li>
+ <li><a href="../examples/example4.php">Stock Chart (log scale)</a></li>
+ <li><a href="../examples/example6.php">Thin bar lines</a></li>
+ <li><a href="../examples/example7.php">Log chart with errors</a></li>
+ <li><a href="../examples/example8.php">Two plots in one image</a></li>
+ <li><a href="../examples/example9.php">Chart with some lines in it</a></li>
+ </ul>
+ <li><b>NOTE:</b>If the examples don't seem to work for you, it may be that you
+ don't have PHP set up correctly. If you do you should see some bold text here:
+ <?php echo "<b>OK!</b>\n"; ?> <br />
+ If you see no text then you should contact your system
+ administrator or your webserver documentation as to how to configure this.
+ </li>
+</ul>
+</p>
+
+
+<h3>Internals</h3>
+<p>
+Description of the use and inner workings of PHPlot:
+<ul>
+ <li><a href="schema.html">PHPlot canvas' elements drawing</a></li>
+ <li>Function reference: (<b>Very outdated</b>)
+ <ul>
+ <li><a href="user_functions.html">User functions</a></li>
+ <li><a href="user_internal_functions.html">User/Internal functions</a></li>
+ <li><a href="internal_functions.html">Internal functions (only of interest
+ for developers)</a></li>
+ </ul>
+ </li>
+</ul>
+</p>
+
+
+<h3>The Authors</h3>
+<p>
+<ul>
+ <li>Original work by <a href="mailto:afan AT jeo DOT net">Afan Ottenheimer</a>.</li>
+ <li>Recent work by <a href="mailto:nonick AT 8027 DOT org">Miguel de Benito</a>.</li>
+ <li>Contributions by Thiemo Nagel, Marlin Viss and Remi Ricard.</li>
+</ul>
+</p>
+
+<p class="foot">$Id$</p>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML><HEAD>
+<TITLE>PHPlot Internal Functions</TITLE>
+</HEAD>
+<BODY>
+
+<h2>PHPlot Internal Functions</h2>
+
+<p><DT><B>DrawArea()</B>
+<DD>Internal Function: Draw an Area Chart. $data[] must already be defined as data-data
+using $data[] = array("title",x,y1,y2,...) Points are placed at (x,y1), (x,y2), ...
+one x-point per $data[] element. <BR>Colors and border colors for each of the y1, y2, ... is set
+by <B>SetDataColors($which_data,$which_border)</B>
+This function is called if
+you use SetPlotType("area") and SetDataType("data-data")
+
+
+<p><DT><B>DrawAreaSeries()</B>
+<DD>Internal Function: Draw an Area Chart. $data[] must already be defined as $data[] =
+array("title",y1,y2,y3,...) The x axis is divided evenly, one x-point per
+$data[] element. <BR>Colors and border colors for each of the y1, y2, ... is set
+by <B>SetDataColors($which_data,$which_border)</B>
+This function is called if
+you use SetPlotType("area") and SetDataType("text-data")
+
+<p><DT><B>DrawBackground()</B>
+<DD>Internal Function: Draw the full background of the image on image pointer. Should be used
+BEFORE other Draw functions unless you really want to overwrite what you've done
+before. See <B>SetBackgroundColor</B> and <B>SetImageArea</B> for setting
+parameters.
+
+<p><DT><B>DrawBars()</B>
+<DD>Internal Function: Draw vertical bars. $data[] must already be defined as $data[] =
+array("title",y1,y2,y3,...) The x axis is divided evenly, one x-point per
+$data[] element. <BR>Colors and border colors for each of the y1, y2, ... is set
+by <B>SetDataColors($which_data,$which_border)</B>
+This function is called if
+you use SetPlotType("bars") and SetDataType("text-data")
+
+<p><DT><B>DrawDashedLine($x1,$y1,$x2,$y2,$dashed, $space, $color)</B>
+<DD>Internal Function: Called instead of ImageLine when line_style = 'dashed'
+line_style is set by <b>SetLineStyles</b> All variables passed to DrawDashedLine
+are in pixel coordinates.
+
+<p><DT><B>DrawDots()</B>
+<DD>Internal Function: Draw Dots as defined by <B>SetPointType</B> and data in x,y format. $data[]
+must already be defined as $data[] = array("title",x,y1,y2,...) Where the point
+occurs depends on both the X and Y values. <BR>Colors and border colors for each
+y1, y2, , ... is set by <B>SetDataColors($which_data,$which_border)</B>
+This function is called if
+you use SetPlotType("dots") and SetDataType("data-data")
+
+<p><DT><B>DrawDotSeries()</B>
+<DD>Internal Function: Draw Dots as defined by <B>SetPointType</B> and data in text-data format.
+$data[] must already be defined as $data[] = array("title",y1,y2,...)
+The x axis is divided evenly, one x-point per $data[] element. <BR>
+Colors and border colors
+for each y1, y2, , ... is set by <B>SetDataColors($which_data,$which_border)</B>
+This function is called if
+you use SetPlotType("dots") and SetDataType("text-data")
+
+<p><DT><B>DrawDotsError()</B>
+<DD>Internal Function: Draw Dots and Error Bars as defined by <B>SetPointType</B> and
+data in data-data-error format. $data[] must already be defined
+as $data[] = array("label",x,y,error+,error-)
+Colors and border colors
+for each y1, y2, , ... is set by <B>SetDataColors($which_data,$which_border)</B>
+The shape of the error bars is defined by <B>SetErrorBarShape($which_ebs)</B>
+and <B>SetErrorBarSize($which_ebs)</B> <br>
+This function is called if
+you use SetPlotType("dots") and SetDataType("data-data-error")
+
+<p><DT><B>DrawError($error_message)</B>
+<DD>Internal Function: Draw an internal error message printed on the Image directly.
+This way - if there is an error and the output is an image you
+don't get the PHP "Header already sent" messages.
+
+<p><DT><B>DrawGraph()</B>
+<DD>Internal Function: This is th last function called after you have set up
+all the parameters of the graph see <b>Set....</b> functions below.
+
+<p><DT><B>DrawHorizontalTicks()</B>
+<DD>Internal Function: Draw the ticks on the X axis.
+The distance between ticks can be defined in a number of ways. <i>Note:
+that for text-data data its best to let the program handle the
+distance between ticks - the default is 1.</i> (Text-data data is data where the data is evenly spaced over
+the x axis, no x-value is entered)
+
+<p><DT><B>DrawImageBorder()</B>
+<DD>Internal Function: Draw the border around the entire image. Currently this
+generates the raised border look around the image.
+
+<p><DT><B>DrawLabels()</B>
+<DD>Internal Function: Draw the Title, X-axis label, and the Y-axis label. This
+really just calls DrawTitle, DrawXLabel, and DrawYLabel.
+
+<p><DT><B>DrawLegend(x,y,type)</B>
+<DD>Internal Function: Draw the Legend. See <b>SetLegendPixels()</b>
+
+<p><DT><B>DrawLines()</B>
+<DD>Internal Function: Draw lines in data-data format.
+$data[] must already be defined
+as $data[] = array("label",x,y1,y2,....)
+Colors and border colors
+for each y1, y2, , ... is set by <B>SetDataColors($which_data,$which_border)</B>
+This function is called if
+you use SetPlotType("lines") and SetDataType("data-data")
+<br>
+
+<p><DT><B>DrawLineSeries()</B>
+<DD>Internal Function: Draw lines in text-data format.
+$data[] must already be defined
+as $data[] = array("label",y1,y2,y3,....)
+The x axis is divided evenly, one x-point per
+$data[] element. <BR>Colors and border colors for each of the y1, y2, ... is set
+by <B>SetDataColors($which_data,$which_border)</B>
+This function is called if
+you use SetPlotType("lines") and SetDataType("text-data")
+
+<p><DT><B>DrawLinesError()</B>
+<DD>Internal Function: Lines and Error Bars as defined by <B>SetPointType</B> and
+data in data-data-error format. $data[] must already be defined
+as $data[] = array("label",x,y,error+,error-)
+Colors and border colors
+for each y1, y2, , ... is set by <B>SetDataColors($which_data,$which_border)</B>
+The shape of the error bars is defined by <B>SetErrorBarShape($which_ebs)</B>
+and <B>SetErrorBarSize($which_ebs)</B>
+This function is called if
+you use SetPlotType("lines") and SetDataType("data-data-error")
+
+<p><DT><B>DrawPieChart()</B>
+<DD>Internal Function: Draw pie chart. Data is in text-data format. $data[] must
+already been defined as $data[] = array("label",y1,y2,y3,...)<BR>
+Colors and border colors for each of the y1, y2, ... is set
+by <B>SetDataColors($which_data,$which_border)</B>
+This function is called if
+you use SetPlotType("pie") and SetDataType("text-data")
+
+<p><DT><B>DrawPlotAreaBackground()</B>
+<DD>Internal Function: Draw the Background - in the color as defined by <b>X</b>
+and in an area as defined by <b>X</b>
+
+<p><DT><B>DrawPlotBorder()</B>
+<DD>Internal Function: Draw the border around the
+plot area - (Note: this is NOT the full image). This draws
+the rectangle as well as calling the functions
+<b>DrawVerticalTicks()</b> and <b>DrawXAxis()</b>
+
+<p><DT><B>DrawTitle()</B>
+<DD>Internal Function: This will draw the title as set by
+<b>SetTitle</b> and
+<b>SetTitleColor</b>. This is also affected by SetUseTTF
+to show how the title appears.
+
+
+<p><DT><B>DrawVerticalTicks()</B>
+<DD>Internal Function: Called by DrawPlotBorder. The spacing between the ticks
+is automatically set unless you have previously set the increment
+by
+ <B>SetNumVertTicks($which_nt)</B>
+or
+ <b>SetVertTickIncrements</b> but not both.
+
+<p><DT><B>DrawXAxis()</B>
+<DD>Internal Function: Draw the horizontal X axis at the world position X=0.
+
+<p><DT><B>DrawXLabel()</B>
+<DD>Internal Function: Called from DrawLabels. Draws the label of the X-Axis.
+
+<p><DT><B>DrawYErrorBar($x_world,$y_world,$error_height,$error_bar_type,$color)</B>
+<DD>Internal Function: This is similar to DrawDot, but it draws error bars.
+Draw one set of error bars at $x_world and $y_world where the
+data is defined in world coordinates (not pixel coordinates).
+
+<p><DT><B>DrawYLabel()</B>
+<DD>Internal Function: Called from DrawLabels. Draws the label of the Y-Axis. Its
+position is defined by the size of the font. Typically there is a
+two character height width around the plot area for drawing the
+labels.
+
+<p><DT><B>FindDataLimits()</B>
+<DD>Internal Function: This must be called AFTER SetDataType. It finds
+the maxima and minima for setting the scaling to be
+able to convert from world to pixel coordinates.
+
+<p><DT><B>InitImage()</B>
+<DD>Internal Function: An internal function called to set the
+image pointer for GD.
+
+<p><DT><B>PrintError($error_message)</B>
+<DD>Internal Function: Prints the given error message to stdout. The function
+is used for fatal errors that do not allow for creating an image.
+
+<p><DT><B>PrintImage()</B>
+<DD>Internal Function: An internal function which prints the image using the PHP
+functions Header("Content-type:...") and ImageGIF(), ImageJPEG(),
+or ImagePNG() depending on what the setting is of $this->file_format.
+This is set by <b>SetFileFormat()</b>
+
+<p><DT><B>SetColor($color_asked)</B>
+<DD>Internal Function: Translate from $color_asked to the index
+name color used in GD.
+$color_asked can be either a name like "black" or an rgb color array
+array(int,int,int). <br>
+
+<p><DT><B>SetDefaultColors()</B>
+<DD>Internal Function: Sets the default colors when first defining an image.
+Overridden by functions like <b>SetPlotBgColor</b>,
+ <b>SetBackgroundColor</b>,
+ <b>SetTextColor</b>,
+ <b>SetGridColor</b>,
+ <b>SetLightGridColor</b>,
+ <b>SetTickColor</b>, and
+ <b>SetTitleColor</b>
+
+<p><DT><B>SetDrawYGrid($which_dyg)</B>
+<DD>Internal Function: 1 = Draw the Y grid. Anything else, don't draw the Y grid.
+
+<p><DT><B>SetEqualXCoord()</B>
+<DD>Internal Function: For text-data graphs set the spacing between
+data points on the x-axis.
+
+<p><DT><B>SetMargins()</B>
+<DD>Internal Function: When the image is first created - set the margins
+ as the full area of the view surface (or panel),
+ less a margin of 4 character heights all round for labelling.
+ It thus depends on the current character size, set by SetCharacterHeight().
+
+<p><DT><B>SetTranslation()</B>
+<DD>Internal Function: Calculate the scale and origin for translating from
+world to pixel coordinates. This is an internal function,
+not one that you'd use normally, but if you are going to
+use it make sure you do it after SetDataType.
+
+<p><DT><B>SetXLabelHeight()</B>
+<DD>Internal Function: This is an internal function that sets the
+height of the X labels based on the maximum string
+length of the X data. It is used for positioning
+where the labels go relative to the x-axis.
+
+
+<p><DT><B>SetYLabelWidth()</B>
+<DD>Internal Function: Set the
+width of the Y Label based on the maximum string
+length of the Y data. It is used for positioning
+where the labels go relative to the y-axis.
+
+
+<p><DT><B>TTFBBoxSize($size, $angle, $font, $string)</B>
+<DD>Internal Function: Calculate the size of the box which encloses the
+text string <b>$string</b> using font <b>$font</b>,
+angle <b>$angle</b> and size <b>$size</b>. This is
+an internal function which is not called unless use_ttf is
+set to 1.
+
+<p><DT><B>xtr($x_world)</B>
+<DD>Internal Function: Translate into x-pixels coordinates from x world coordinates.
+
+<p><DT><B>ytr($y_world)</B>
+<DD>Internal Function: Translate into y-pixels coordinates from y world coordinates.
+
+
+
+
+
+</dl>
+
+</body>
+</html>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- $Id$ -->
+<html>
+<head>
+ <title>PHPLOT Quick Start and Examples</title>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+ <meta name="author" content="Afan Ottenheimer" />
+ <meta name="author" content="Miguel de Benito" />
+ <meta name="created" content="20010302;20371700" />
+ <meta name="changed" content="20040121;19341300" />
+ <meta name="description" content="phplot quick start and examples" />
+ <meta name="keywords" content="phplot, graphs, images, php" />
+ <meta name="robots" content="all" />
+ <meta name="locale" content="en-us" />
+ <link type="text/css" rel="stylesheet" href="style.css" />
+</head>
+
+<body lang="en-us" bgcolor="#ffffff">
+
+<h1>PHPlot Quick Start and Examples</h1>
+
+<p>Afan Ottenheimer, January 7, 2001</p>
+<p>Miguel de Benito, January 21, 2004</p>
+<p><b>Contents</b></p>
+<ul>
+ <li><a href="#intro">Introduction</a></li>
+ <li><a href="#first">First steps</a></li>
+ <li><a href="#lines">Multiples lines per graph</a></li>
+ <li><a href="#multiple">Multiple graphs per image</a></li>
+ <br />
+</ul>
+
+<h2><a name="intro"></a>Introduction</h2>
+
+<p>Many web sites need to create real-time or dynamic charts and graphs.
+from live data sets. Many users have found PHP a great way for this dynamic
+creation of images using the GD library and there have been several
+good articles describing this [] [] []. The advantage of using the server
+to create an image (server side scripting) is that one does not have to
+worry about browser compatibility or client operating system compatibility issues.
+The PHP image generating library uses the GD library to create elementary
+shapes (elipse, line, rectangle, ...).
+PHPlot is a graphics library which provides a means by which you can have your
+(PHP enabled) web server create and manipulate graphs as objects and
+display the completed graph as an image. Data sets passed to PHPlot use a very
+convenient way for database driven sites, in rows with y coordinate data.
+</p>
+
+<p>First, lets discuss how PHPlot works in general with some
+terminology. A PHPlot <i>image </i>can consist of several <i>graphs </i>,
+each graph consisting of several <i>elements</i>.
+You define an object (e.g. a variable like <code>$graph</code>),
+select the properties of the element that compose the graph and "<i>Draw</i>"
+what you want into the object. Tipically by selecting the plot type with
+<code>SetPlotType</code> and at the end calling <code>DrawGraph</code>. You
+can also directly invoke <code>PrintImage</code>, which either inserts the image
+into the data streaming to the client or writes it to disk.
+</p>
+<p>In PHPlot there are <em>World coordinates</em>, which are the XY coordinates
+relative to the axis origin, in the units of the data set; and
+<em>device (pixel)</em> coordinates which in GD are relative to the
+origin at the upper left side of the image.
+</p>
+<p>You can think of the "Draw" functions as shaping the
+image object and the "Print" function as the method of
+finally creating the digital image. PHPlot is smart enough that if
+you only have one graph on an image, then the "Print" is
+done for you automatically. If you do have multiple graphs per image
+then you'll need to use both the "Draw" and "Print"
+functions. We'll talk about that a bit later.
+</p>
+<p>Since PHP is a server scripted language you have several options
+for how you can "Print" the image. You can:</p>
+<ol>
+ <li>Write the image as a file on the server. (You specify a file
+ name and can specify caching as well)</li>
+ <li>Have the raw data stream out within an HTML file, as <IMG
+ SRC="my_PHPlot_code.php"></li>
+ <li>Precede the raw data with html image headers and call the
+ script directly (showing up as an image) e.g.
+ http://somewhere/my_PHPlot_code2.php .</li>
+</ol>
+<p>This document explains how to create plots using PHPlot from a
+PHP script. Information on PHP can be found at <a href="http://www.php.net/">www.php.net</a>.
+Information about the GD library which PHP uses to create images can
+be found at <a href="http://www.boutell.com/">www.boutell.com</a>.
+More information about PHPlot can be found at <a href="www.phplot.com">www.PHPlot.com</a>.</p>
+
+<h2>Creating the Object</h2>
+
+<p>You create a PHPlot object by first including the code to be used
+and then defining the variable:</p>
+<div class="box">
+<pre><?php
+include('./phplot.php'); // here we include the PHPlot code
+$graph = new PHPlot(); // here we define the variable graph
+
+//Rest of code goes below
+?></pre>
+</div>
+
+<p>The above code assigns the PHPlot object to the variable <code>$graph</code>.</p>
+
+<p>Now we have created a PHPlot graph object, we can access
+information about the object and manipulate the object. In these
+following examples, <code>$graph</code> is the variable/object we created
+above.</p>
+
+<p> <a href="#top">Back to top</a> </p>
+
+
+<h2>Real World Examples</h2>
+<h3><a name="first"></a>Case 1: A simple graph</h3>
+
+<p>We will start with a simple line graph. </p>
+<div class="box">
+<pre><?php
+//Include the code
+include('./PHPlot.php');
+
+//Define the object
+$graph = new PHPlot();
+
+//Define some data
+$example_data = array(
+ array('a',3),
+ array('b',5),
+ array('c',7),
+ array('d',8),
+ array('e',2),
+ array('f',6),
+ array('g',7)
+);
+$graph->SetDataValues($example_data);
+
+//Draw it
+$graph->DrawGraph(); // remember, since in this example we have one graph, PHPlot
+ // does the <i>PrintImage </i>part for you
+?></pre>
+</div>
+
+<p> And that's it! What we get is the following graph: </p>
+
+<div align=center>
+ <img src="imgs/qstart_fig1.png" name="fig1" alt="figure 1" align="bottom" border="0" />
+ <br />Figure 1
+</div>
+
+<p>That's a great start, but now we'd like to specify the width and height
+of the image.</p>
+
+
+<h3>Case 1a: Different Size Images and Titles</h3>
+<p>
+Lets say we want it to have a width of 300 and a height of 250 pixels.
+So instead of having the line <br /><br />
+ <code>$graph = new PHPlot();</code> <br /><br />
+we replace it with <br /><br />
+ <code>$graph = new PHPlot(300,250);</code><br /><br />
+and you have specified the size in pixels of the image to be created.
+A couple of things to note:
+</p>
+<ul>
+ <li>The default is <em>not</em> to use TTF fonts. </li>
+ <li>Since there was only one graph on the image we didn't have to
+ specify PrintImage, DrawGraph took care of it for us.
+ </li>
+ <li>
+ We did not specify the data type. If you do not specify the data
+ type PHPlot assumes <code>text-data</code>.
+ </li>
+ <li>
+ We did not specify the file type (gif, png, jpg, ...) .
+ PHPlot 5.0 assumes PNG image formats.
+ </li>
+ <li>
+ The data is passed in as an array of arrays. This may seem awkward
+ now, but as we add functionality this will be beneficial.
+ </li>
+</ul>
+<p>Ok, now we're ready to add some customization to the plot. Let's change
+the size, the title and the x/y axis labels. All we need to do is modify
+the variable <code>$graph</code> before printing the image. We achieve this with:
+</p>
+<div class="box">
+<pre><?php
+include ('./phplot.php');
+
+//create an graph object 300x250 pixels
+$graph = new PHPlot(300,250);
+//Set titles
+$graph->SetTitle("Title\n\rSubtitle");
+$graph->SetXTitle('X data');
+$graph->SetYTitle('Y data');
+
+//...rest of code
+
+
+?></pre>
+</div>
+<div align=center>
+ <img src="imgs/qstart_fig2.png" name="graphic1" align="bottom" border="0"><br />
+ Figure 2
+</div>
+
+<p>Note that in order for the "\n" and "\r " to be interpreted as
+new line/new return characters for <code>SetTitle </code>you have to
+enclose the string in <b>double </b>quotes.</p>
+
+<h3><a name="lines"></a>Case 2: Multiple Lines per Graph </h3>
+<p>Lets say we want to plot not just one
+dataset but several y values for each x position. With PHPlot it is
+easy to specify the multiple data lines by just passing in all the Y
+values for a given X value at once. So instead of array('label', y)
+we specify array('label', y<sub>1</sub>, y<sub>2</sub>, y<sub>3</sub>,
+...) This is very convenient when working with rows of data from databases.
+<br />
+Now our data will have three Y values for each position on the X axis
+</p>
+<div class="box">
+<pre><?php
+//Include the code
+include('./phplot.php');
+
+//Define the object
+$graph = new PHPlot(300,250);
+
+//Set titles
+$graph->SetTitle("Title\n\rSubtitle");
+$graph->SetXTitle('X data');
+$graph->SetYTitle('Y data');
+
+
+//Define some data
+$example_data = array(
+ array('a',3,4,2),
+ array('b',5,'',1), // here we have a missing data point, that's ok
+ array('c',7,2,6),
+ array('d',8,1,4),
+ array('e',2,4,6),
+ array('f',6,4,5),
+ array('g',7,2,3)
+);
+$graph->SetDataValues($example_data);
+
+//Draw it
+$graph->DrawGraph();
+?></pre>
+</div>
+<p>Which gives us: </p>
+<div align="center">
+ <img src="imgs/qstart_fig3.png" name="graphic2" align=bottom border="0" />
+ <br />Figure 3
+</div>
+
+<p>Notice that each set of Y data gets a different color.
+Also the missing data point is skipped, this behaviour can be adjusted with
+<code>SetDrawBrokenLines(TRUE);</code>
+</p>
+<p>
+This gives you the basics of how to create a graph in PHPlot.
+A nice start, but now we'd like to add some customization, namely different
+fonts, margins and types of graphs.
+</p>
+<p><a href="#top">Back to top</a> </p>
+
+
+<h3>Customization</h3>
+<p>Valid types of plots (as of PHPlot 5.0):
+<ul>
+ <li><code>bars</code> (with optional shadows)</li>
+ <li><code>lines</code></li>
+ <li><code>linepoints</code> (a faster way of plotting when
+ you want both points and lines)</li>
+ <li><code>area</code></li>
+ <li><code>points</code> (lots of point types here)</li>
+ <li><code>pie</code> (2D or 3D)</li>
+ <li><code>thinbarline</code> (sometimes also called impulse) </li>
+ <li><code>error bar</code> (which can also be used for stock market data graphs)</li>
+ <li><code>squared</code> (for binary data) </li>
+</ul>
+</p>
+<p>You specify which type with the <code>SetPlotType</code> function.
+We'll look at that function with bars and lines in the next example when we look at
+multiple graphs per image.
+</p>
+<p>As we discussed before, there are several ways we can manipulate
+the look/feel of the graph object. Almost every parameter of ticks, grids and data labels
+can be adjusted via (among many others):
+<ul>
+ <li><code>SetXTickPos()</code></li>
+ <li><code>SetYTickPos()</code></li>
+ <li><code>SetXTickLength()</code></li>
+ <li><code>SetYTickLength()</code></li>
+ <li><code>SetXTickCrossing()</code></li>
+ <li><code>SetYTickCrossing()</code></li>
+ <li><code>SetXTickIncrement()</code></li>
+ <li><code>SetYTickIncrement()</code></li>
+ <li><code>SetNumXTicks()</code></li>
+ <li><code>SetNumYticks()</code></li>
+ <li><code>SetSkipTopTick()</code></li>
+ <li><code>SetSkipBottomTick()</code></li>
+
+ <li><code>SetDrawXGrid()</code></li>
+ <li><code>SetDrawYGrid()</code></li>
+ <li><code>SetDrawDashedGrid()</code></li>
+ <li><code>SetDrawXDataLabelLines()</code></li>
+ <li><code>SetDrawYDataLabelLines()</code> (not yet implemented)</li>
+ <li><code>SetXDataLabelPos()</code></li>
+ <li><code>SetYDataLabelPos()</code></li>
+ <li><code>SetXLabelAngle()</code></li>
+ <li><code>SetYLabelAngle()</code></li>
+ <li><code>SetXLabelType()</code></li>
+ <li><code>SetYLabelType()</code></li>
+</ul>
+As we go further we will introduce some of these features of PHPlot.
+For more specialized examples, please go <a href="index.php">back to the index</a> and
+look in the examples section.
+</p>
+
+<p> <a href="#top">Back to top</a> </p>
+
+<h3><a name="multiple"></a> <b>Case 3: Multiple Graphs per Image </b></h3>
+
+<p>To create an image with several separate graphs
+on it is a straightforward process. As in the previous examples we
+first have to create an object (e.g. variable) but now we tell it to
+<i>not</i> print the image at the same time as the draw command. Now
+we want it to wait for the explicit <code>PrintImage</code> function call.
+To tell PHPlot this is the way we want to work, we use the
+<code>SetPrintImage</code> function.
+<code>SetPrintImage(TRUE)</code> is the default, and tells to draw the image
+when <code>DrawGraph</code> is called. To turn this
+off we use <code>SetPrintImage(FALSE)</code>.</p>
+<p>Now we will draw several images entirely within one object. That
+means that if we set a value for one graph, there will be a couple of
+other commands we will need.
+</p>
+<p>To specify in pixels the placement of each graph we use
+<code>SetNewPlotAreaPixels</code>. The format is
+<code>SetNewPlotAreaPixels(upper_left_x, upper_left_y, lower_right_x,
+lower_right_y)</code> . Again we are using the GD coordinates where 0,0
+is the upper left corner of the image.
+</p>
+<p>In more detail:</p>
+<div class="box">
+<pre><?php
+include('./PHPlot.php'); // here we include the PHPlot code
+$graph = new PHPlot(400,250); // here we define the variable $graph
+$graph->SetPrintImage(0); //Don't draw the image yet
+
+//....Data and Values for first graph here .....
+
+$graph->SetNewPlotAreaPixels(70,10,375,100); // where to place it
+
+$graph->DrawGraph(); //Draw the first graph to the image.
+
+//....Data and Values for second graph here .....
+
+$graph->SetNewPlotAreaPixels(70,120,375,220); //where to place graph 2
+$graph->DrawGraph(); //Draw the second graph to the image
+
+//Print the image with both graphs
+$graph->PrintImage();
+?></pre>
+</div>
+
+<p>Lets now create an image with 2 graphs on it with some example data. </p>
+
+<div class="box">
+<pre><?php
+//Include the code
+include('./phplot.php');
+
+//Define the object
+$graph = new PHPlot(400,250);
+
+$graph->SetPrintImage(0); //Don't draw the image until specified explicitly
+
+$example_data = array(
+ array('a',3),
+ array('b',5),
+ array('c',7),
+ array('d',8),
+ array('e',2),
+ array('f',6),
+ array('g',7)
+);
+
+$graph->SetDataType("text-data"); //Must be called before SetDataValues
+
+$graph->SetDataValues($example_data);
+$graph->SetYTickIncrement(2); //a smaller graph now - so we set a new tick increment
+
+$graph->SetXLabelAngle(90);
+$graph->SetXTitle("");
+$graph->SetYTitle("Price");
+$graph->SetPlotType("lines");
+$graph->SetLineWidth(1);
+
+$graph->SetNewPlotAreaPixels(70,10,375,100); // where do we want the graph to go
+$graph->DrawGraph(); // remember, since we said not to draw yet, PHPlot
+ // still needs a <i>PrintImage </i>command to write an image.
+
+
+//Now do the second chart on the same image
+unset($example_data); //we are re-using $example_data (to save memory), but you don't have to
+$example_data = array(
+ array('a',30,40,20),
+ array('b',50,'',10), // here we have a missing data point, that's ok
+ array('c',70,20,60),
+ array('d',80,10,40),
+ array('e',20,40,60),
+ array('f',60,40,50),
+ array('g',70,20,30)
+);
+
+$graph->SetDataType("text-data"); //Must be called before SetDataValues
+
+$graph->SetDataValues($example_data);
+
+$graph->SetXTitle("");
+$graph->SetYTitle("Verbal Cues");
+$graph->SetYTickIncrement(10);
+$graph->SetPlotType("bars");
+$graph->SetXLabelAngle(0); //have to re-set as defined above
+
+$graph->SetNewPlotAreaPixels(70,120,375,220);
+$graph->SetPlotAreaWorld(0,0,7,80);
+$graph->DrawGraph();
+
+//Print the image
+$graph->PrintImage();
+?></pre>
+</div>
+
+<p> <br /> <br /> Which gives us: </p>
+
+<div align="center">
+ <img src="imgs/qstart_fig4.png" name="graphic3" align="top" border="0" /> <br />
+ Figure 4 <br />
+</div>
+
+<p>
+You must remember that world Coordinates are the XY coordinates relative to the
+axis origin that can be drawn. Not the device (pixel) coordinates
+which in GD are relative to the origin at the upper left
+side of the image.
+</p>
+
+<div style="background:#6699cc; color:#ffffff;">
+ <a href="#top">Back to top</a> <br />
+ <a href="index.php">Back to the index</a> <br />
+</div>
+<div class="foot">$Id$</div>
+
+</body>
+</html>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+ <title>PHPlot schema</title>
+ <link type="text/css" rel="stylesheet" href="style.css" />
+</head>
+<body>
+
+<div class="nav"> [ <a href="../doc/index.html">Go to the index</a> ] </div>
+
+<h2>The Drawing</h2>
+<p>
+The drawing you can see here is an attempt to illustrate the positioning
+of elements on the canvas of PHPlot graphs. I'm not specially good at it
+so please don't complain. I (<a href="mailto:nonick AT 8027 DOT org">Miguel</a>)
+hope it will help somebody as it did with me when I first began browsing
+through the 3000 lines of code Afan had written.
+</p>
+<p>If you are curious, for the drawing I used
+<a href="http://www.lysator.liu.se/~alla/dia/">Dia</a> a gtk+ diagram creation
+sofware which I find easy and suited for my purposes.
+<center><img src="imgs/phplot-dia.png" alt="schema" /></center>
+</p>
+
+<h2>The words</h2>
+<p> Creating a graph with PHPlot is easy, you just create an instance of
+the class, set up a few options, push in the data and smile at your
+new cute graphic. However here we'll proceed a little more step by step so
+to show you how to get the most of PHPlot. Please go to <a href="quickstart.html">
+quickstart</a>.
+</p>
+
+<p class="foot">$Id$</p>
+</body>
+</html>
--- /dev/null
+/* $Id$
+ * Style sheet for PHPlot
+ */
+
+
+.foot {
+ text-align:right;
+ font-style:italic;
+ font-size:smaller;
+ width:100%;
+ background:#CCCCCC;
+ color:#000000;
+ }
+
+
+.nav {
+ text-align:center;
+ color:#DDDDDD;
+ background:#FFFFFF;
+ font-size:7px;
+ }
+
+.imgfoot { text-align:center; font-size:small; font-style:italic; }
+.hdr { text-align:center; background: #DDDDDD; color:#000000; }
+.bighdr { text-align:center; font-weight: bold; }
+
+h2 { border-bottom: 1px dashed; }
+h3 { border-bottom: 1px dotted; margin-left:1em;}
+
+img { padding: 0.5em; }
+
+.box {
+ background-color: #cccccc;
+ color: #000000;
+ border:1px solid;
+ width:75%;
+ margin:2em;
+ font-size:smaller;
+ }
+
+pre { font-family: monospace, "white-space" }
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML><HEAD>
+<TITLE>PHPlot User Functions</TITLE>
+</HEAD>
+<BODY>
+
+<h2>PHPlot User Functions</h2>
+
+<ul>
+<li><a href="#important">Important functions</a></li>
+<li><a href="#appearance">Appearance functions</a></li>
+<li><a href="#color">Color functions</a></li>
+<li><a href="#manipulation">Data manipulation functions</a></li>
+</ul>
+
+
+<hr>
+
+<h3><a name="important">Important functions</a></h3>
+
+<p><DT><B>SetDataType($which_dt)</B>
+<DD>User Function: PHPLOT can accept data in a number of different
+formats. One main difference between PHPLOT and PGPLOT
+is that the x-y or x-y-error data should be passed in
+with the data grouped together in an array.
+<p>
+Asside: Why the author chose this data format: In PGPLOT
+you would have the X-values in one array and the Y-values
+in a second. This would sometimes lead to really strange
+graphs if one array was accidentally one data element
+short. Plus most of the data the author was using came in
+from a database using a _get_row or _get_array (in php)
+and one can just pass it straight in to PHPLOT. <p>
+
+Colors and border colors are set by <b>SetDataColors</b>. Why
+not have colors as part of the same array? Because most
+data applications are used to putting out raw data and not
+raw data + color information. <p>
+
+So in PHPLOT the datalabel,x-value,y-value and error are
+grouped together as a <b>value array</b>. Then the
+entire set of points to be plotted is passed in as a <b>data array</b>
+E.g. Data_array = array(value_array_1,value_array_2,....) <p>
+See below for examples of the various data types: <br>
+
+<LI>text-data: Data is displayed at equal spacing along the x-axis. Data
+is passed in as a data array of value arrays. Each element of the data
+array is a position on the x-axis. The first element of the value array is
+the label for that x-axis position, every subsequent element of the value
+array is a y-value.
+Example data<br>
+<pre>
+$data = array(
+ array("label 1",1.1,2,3,4),
+ array("label 2",2,3,4,5),
+ array("label 3",5,6,7,8),
+ array("label 4",10,12,13,14)
+);
+</pre>
+Which will display data points at
+(1,1.1), (1,2), (1,3), (1,4), (2,2), (2,3)....<br>
+<IMG SRC="something.png">
+</LI>
+<LI>data-data:
+ X-Y data is passed in like text-data except
+that the second element of the value array is the position along the
+x axis of the data point(s). One data element would be $data[] = (title,x,y1,y2,y3,y4,...)
+or
+<pre>
+$data = array(
+ array("label 1",1.1,2,3,4),
+ array("label 2",2,3,4,5),
+ array("label 3",5,6,7,8),
+ array("label 4",10,12,13,14)
+);
+</pre>
+Notice that this is the same as in the previous example except that
+the x,y data points are at (1.1,2), (1.1,3), (1.1,4), (2,3)...
+</LI>
+<LI>data-data-error:
+Again X-Y data is passed in as an array with each value
+array being (data_label,x_position,y_position,error_plus,error_minus)
+</LI>
+
+<p><DT><B>SetDataValues($which_dv)</B>
+<DD>User Function: Passes the raw data values into the class variable
+$this->data_values. This function <b>needs</b> to be called before any
+image can be drawn.
+
+<p><DT><B>SetPlotType($which_pt)</B>
+<DD>User Function: Can be: bars, lines, linepoints, area, points, and pie
+
+<p><DT><B>SetErrorBarLineWidth($width)</B>
+<DD>Width of the Error Bars in Pixels. If not set then
+uses "line_width" to set the width of the error_bar lines.
+
+<p><DT><B>SetFileFormat($which_file_format)</B>
+<DD>User Function: Set the format of the output graph. Supported formats
+are GIF, JPEG, and PNG. You can only use those formats
+that are supported by your version of GD. For example,
+if you use GD-1.8.3 you can not use GIF images. If you
+use GD-1.2 you can not use PNG or JPEG images.
+
+<p><DT><B>SetUseTTF($which_ttf)</B>
+<DD>User Function: Call this as SetUseTTF(1) when you have TTF compiled into PHP
+otherwise call this as SetUseTTF(0)
+
+
+<hr>
+
+<h3><a name="appearance">Appearance functions</a></h3>
+
+
+<p><DT><B>SetErrorBarShape($which_ebs)</B>
+<DD>User Function: Can be "tee" or "line." If it is tee, then
+the half-width of the tee is set by <b>SetErrorBarSize</b>
+
+<p><DT><B>SetErrorBarSize($which_ebs)</B>
+<DD>User Function: Size in pixels of the Tee shape of the error bar.
+
+<p><DT><B>SetHorizTickIncrement($which_ti)</B>
+<DD>User Function: Set where to place the X-tick marks.
+
+<p><DT><B>SetNumHorizTicks($which_nt)</B>
+<DD>User Function: Use this or SetHorizTickIncrements but not both.
+
+<p><DT><B>SetNumVertTicks($which_nt)</B>
+<DD>User Function: Use this or SetVertTickIncrements but not both.
+
+<p><DT><B>SetPlotAreaPixels($x1,$y1,$x2,$y2)</B>
+<DD>User Function: You can use this to set the actual size in
+pixels of the plot area on the image.
+
+<p><DT><B>SetPointShape($which_pt)</B>
+<DD>User Function: Can be: rect,circle,diamond,triangle,dot,line,halfline
+
+<p><DT><B>SetPointSize($which_ps)</B>
+<DD>User Function: Set the width of the displayed data point for
+plot_type's that have data points. E.g. dots, linepoints
+This is an integer. For diamonds, values that are even
+make the diamond look better.
+
+<p><DT><B>SetPrecisionX($which_prec)</B>
+<DD>User Function: Set the precision of the data written to the X axis.
+$which_prec is an integer which represents the number of digits
+displayed to the right of the decimal. This uses the number_format
+command in PHP.
+
+<p><DT><B>SetPrecisionY($which_prec)</B>
+<DD>User Function: Set the precision of the data written to the Y axis.
+$which_prec is an integer which represents the number of digits
+displayed to the right of the decimal. This uses the number_format
+command in PHP.
+
+<p><DT><B>SetShading($which_s)</B>
+<DD>User Function: Set the length of the shadows for shading bar charts
+The color used is the LightGridColor See <b>SetLightGridColor</b>. <br>
+
+<p><DT><B>SetTickLength($which_tl)</B>
+<DD>User Function: Set the length of the tick in pixels for the x axis and y axis.
+$which_color can be either a name like "black" or an rgb color array
+array(int,int,int). <br>
+
+
+<p><DT><B>SetTitle($title)</B>
+<DD>User Function: Set the title of the graph. Printed at the top
+middle of the graph.
+
+<p><DT><B>SetHorizTickIncrement($which_ti)</B>
+<DD>User Function: Set the distance between tick marks on the X axis. $which_ti
+is in world coordinates.
+
+<p><DT><B>SetVertTickIncrement($which_ti)</B>
+<DD>User Function: Set the distance between tick marks on the Y axis. $which_ti
+is in world coordinates.
+
+<p><DT><b>SetXDatalabelMaxlength($which_xdlm)</b>
+<DD>User Function: Sets the maximum length of the datalabels on the x-axis.
+This adjusts the margins if the angle of the labels is not 0.
+
+<p>
+
+<p><DT><b>SetXGridLabelType($which_xtf)</b>
+<DD>User Function: Can be "time", "title", "none", "default" or "data". <br>
+time - label is set by the the php command strftime()<br>
+title - label is treated as text, the first element of the data array.<br>
+data - label is formateed using php command number_format<br>
+none - no labelss are printed.<br>
+default - prints as it is entered. <br>
+<p>
+
+
+<p><DT><b>SetXScaleType($which_xct)</b>
+<DD>Can be "log" or "linear".
+
+<p><DT><b>SetXTimeFormat($which_xtf)</b>
+<DD>User Function: Used for x_grid_label_type="time".
+For the format see the php manual for strftime(). It assumes the x-data values are unix timestamps, and displays them according to the passed format string.
+<p>Example: If x values are seconds offset from the beginning of the day. This coresponds to unix timestamps on January 1, 1970, so all I had to do was $graph->SetXGridLabelType("%H:%M") to display the time properly.
+ <p>
+The php strtotime() function also comes in handy turning dates into timestamps, especially for parameters to SetPlotAreaWorld().
+<p>
+Example:<br>
+$graph->SetPlotAreaWorld(strtotime("October 1"), 0,strtotime("December 15"),10);<br>
+$graph->SetXGridLabelType("time") ;<br>
+$graph->SetXTimeFormat("%b %d") ;<br>
+
+<p><DT><B>SetXLabel($xlbl)</B>
+<DD>User Function: Set the label for the X axis.
+
+<p><DT><B>SetYLabel($ylbl)</B>
+<DD>User Function: Set the label for the Y axis.
+
+<p><DT><b>SetYScaleType($which_xct)</b>
+<DD>Can be "log" or "linear".
+
+
+<hr>
+
+<h3><a name="color">Color functions</a></h3>
+
+<p><DT><B>SetBackgroundColor($which_color)</B>
+<DD>User Function: Set the color of the background of the entire image.
+$which_color can be either a name like "black" or an rgb color array
+array(int,int,int). <br> It defaults to array(222,222,222) if
+not defined.<br>
+
+<p><DT><B>SetGridColor ($which_color)</B>
+<DD>User Function: Set the color of the grid. Defaults to "black"
+$which_color can be either a name like "black" or an rgb color array
+array(int,int,int). <br>
+
+<p><DT><B>SetLegend($which_legend)</B>
+<DD>$which_legend is an array of text for display in a small box
+on the image. If you do not set the position with <b>SetLegendPixels()</b>
+then it puts it in the upper right hand side.
+
+<p><DT><b>SetLegendPixels($which_x,$which_y,$which_type)</b>
+<DD>Pick the upper left corner of the legend box with
+$which_x and $which_y in pixels. $which_type is reserved
+for future use.
+
+<p><DT><b>SetLegendWorld($which_x,$which_y,$which_type)</b>
+<DD>Untested and documentation not written. Have Fun!
+
+<p><DT><B>SetLightGridColor ($which_color)</B>
+<DD>User Function: There are two grid colors, this sets the
+light grid color.
+$which_color can be either a name like "black" or an rgb color array
+array(int,int,int). <br> It defaults to array(222,222,222) if
+not defined.<br>
+
+<p><DT><B>SetLineWidth($which_lt)</B>
+<DD>User Function: Set the width of lines in pixels for graphs that use
+lines (linepoints and lines). Affects the size of the
+error bar lines as well.
+
+<p><DT><B>SetLineStyles($which_sls)</B>
+<DD>User Function: Set style of the line to be printed.
+This is an array. Currently only 'dashed' and 'solid' are
+supported.
+
+<p><DT><B>SetPlotBgColor($which_color)</B>
+<DD>User Function: Set the Background color of the area on which
+the plot is defined. Called from <b>PlotAreaBackground</b><br>
+$which_color can be either a name like "black" or an rgb color array
+array(int,int,int). <br> It defaults to array(222,222,222) if
+not defined.
+
+<p><DT><B>SetTextColor ($which_color)</B>
+<DD>User Function: Set the color of text written. It defaults to black if not called.
+You can call this function multiple times - each time it changes the
+color of text written.
+$which_color can be either a name like "black" or an rgb color array
+array(int,int,int). <br>
+
+<p><DT><B>SetTickColor ($which_color)</B>
+<DD>User Function: Set the color of the ticks on the axes
+$which_color can be either a name like "black" or an rgb color array
+array(int,int,int). <br>
+
+<p><DT><B>SetTitleColor($which_color)</B>
+<DD>User Function: Set the color of the title.
+$which_color can be either a name like "black" or an rgb color array
+array(int,int,int). <br>
+
+<hr>
+
+<h3><a name="manipulation">Data manipulation functions</a></h3>
+
+<p>These functions only are availabe in the class PHPlot_data that extends PHPlot.
+Since all functions of that section do calculations on the data, it is neccessary
+that data is supplied to the class by the SetDataValues() function before calling
+any of the functions.</p>
+
+<p><DT><B>DoScaleData($even, $show_in_legend)</B>
+<DD>User Function: Scales the data so that graphs with widely different amplitudes
+can be plotted into one image. If $show_in_legend is true, the amplification factor
+that is applied to each for the datasets is appended to the legend of the graph. If
+$even is true, the function multiplies only by 10^x,2*10^x or 5*10^x.<br>
+
+<p><DT><B>DoMovingAverage($datarow, $interval, $show_in_legend)</B>
+<DD>User Function: Computes a moving average over an amount of $interval units
+on the data row that is indexed by $datarow. If $show_in_legend is true, a notice
+that a data row is averaged and the length of the interval are appended to the legend.
+<br>
+
+<hr>
+
+<h3>not implemented</h3>
+
+<p><DT><B>SetCharacterHeight()</B>
+<DD>User Function: Not yet implemented
+
+</body>
+</html>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML><HEAD>
+<TITLE>PHPlot User / Internal Functions</TITLE>
+</HEAD>
+<BODY>
+
+<h2>PHPlot User / Internal Functions</h2>
+
+
+<p><DT><B>DrawDataLabel($lab,$x_world,$y_world)</B>
+<DD>User Function and Internal Function: Draw a label at the world coordinates of x_world and y_world.
+
+
+<p><DT><B>DrawDot($x_world,$y_world,$dot_type,$color)</B>
+<DD>User Function and Internal Function: Draw one dot at $x_world and $y_world where the world
+coordinates (not pixel coordinates).
+
+
+<p><DT><B>DrawXDataLabel($xlab,$xpos)</B>
+<DD>User Function and Internal Function: Draw a data label on the x axis at world
+position $xpos. The position below
+the x axis is set based on the size of the font, and (if
+using TTF) the maximum string length of the labels, and
+the angle at which the labels are printed.
+
+
+<p><DT><B>SetDataColors($which_data,$which_border)</B>
+<DD> If called with $which_data="" it defaults to
+ $which_data = array("blue","bisque",array(0,176,0));
+ $which_border = array("black");
+
+
+<p><DT><B>SetErrorBarColors($which_data)</B>
+<DD> If not called then the colors are the same as the
+colors of the data as set by <b>SetDataColors()</b>
+otherwise it sets the colors of the error bars.
+
+<p><DT><B>SetLabels($xlbl,$ylbl,$title)</B>
+<DD>Internal Function and User Function: Set the text of the X, Y and Title labels.
+If you want to just set the X-axis label you can use <b>SetXLabel</b>.
+
+
+<p><DT><B>SetNewPlotAreaPixels($x1,$y1,$x2,$y2)</B>
+<DD>Reserved - not used yet.
+
+
+
+<p><DT><B>SetPlotAreaWorld($xmin,$ymin,$xmax,$ymax)</B>
+<DD>User Function and Internal Function: You do not have to call this function as the
+program will set the plot area automatically based on
+max values of X and Y. <br> You can call this function
+as SetPlotAreaWorld("","","","") and it will set the
+plot area based on max/min values of data.
+
+
+
+
+
+</dl>
+
+</body>
+</html>
--- /dev/null
+<?php
+/* $Id$ */
+
+error_reporting(E_ALL);
+
+/*
+// Check if we are processing the form
+if (! array_key_exists('submit', $_POST)) {
+ echo "<p>This file is intended to be called from format_chart.php, the example-o-matic.".
+ "Please <a href=\"format_chart.php\">click here</a> to try it.</p>";
+ exit;
+}
+*/
+
+extract ($_GET, EXTR_OVERWRITE);
+extract ($_POST, EXTR_OVERWRITE);
+
+
+//Sample functions
+
+// data-data as a function
+if ($which_data_type == 'function') {
+ //Put function here
+ $dx = ".3";
+ $max = 6.4;
+ $maxi = $max/$dx;
+ for ($i=0; $i<$maxi; $i++) {
+ $a = 4;
+ $x = $dx*$i;
+ $data[$i] = array("", $x, $a*sin($x),$a*cos($x),$a*cos($x+1));
+ }
+ $which_data_type = "data-data";
+}
+// data-data-error as a random function
+else if ($which_data_type == 'randfunction') {
+ srand ((double) microtime() * 1000000);
+ $a = 9.62;
+ $label[0] = "October"; $label[5] = "Day 5"; $label[10] = "Day 10";
+ $label[15] = "Day 15"; $label[20] = "Day 20"; $label[25] = "Day 25";
+
+ for ($i = 0; $i <= 30; $i++) {
+ $a += rand(-1, 2);
+ $b = rand(0,1);
+ $c = rand(0,1);
+ $data[] = @ array($label[$i],$i+1,$a,$b,$c);
+ }
+ $which_data_type = 'data-data-error';
+}
+// MBD, this is for data_sample3.php, $num_data_rows is set there
+else if ($which_data_type == 'data-data-error') {
+ for ($i = 0; $i < $num_data_rows; $i++) {
+ eval ("\$data[\$i] = \$data_row$i; ");
+ }
+} else {
+ foreach($data_row0 as $key=>$val) {
+ $data[$key] = array($data_row0[$key],$data_row1[$key],$data_row2[$key],$data_row3[$key],$data_row4[$key]);
+ }
+}
+
+
+////////////////////////////////////////////////
+
+//Required Settings
+ include("../phplot.php");
+ $graph = new PHPlot($xsize_in, $ysize_in);
+ $graph->SetDataType($which_data_type); // Must be first thing
+
+ $graph->SetDataValues($data);
+
+//Optional Settings (Don't need them)
+
+// $graph->SetTitle("This is a\n\rmultiple line title\n\rspanning three lines.");
+ $graph->SetTitle($title);
+ $graph->SetXTitle($xlbl, $which_xtitle_pos);
+ $graph->SetYTitle($ylbl, $which_ytitle_pos);
+ $graph->SetLegend(array("A","Bee","Cee","Dee"));
+
+ $graph->SetFileFormat($which_fileformat);
+ $graph->SetPlotType($which_plot_type);
+
+ $graph->SetUseTTF($which_use_ttf);
+
+ $graph->SetYTickIncrement($which_yti);
+ $graph->SetXTickIncrement($which_xti);
+ $graph->SetXTickLength($which_xtl);
+ $graph->SetYTickLength($which_ytl);
+ $graph->SetXTickCrossing($which_xtc);
+ $graph->SetYTickCrossing($which_ytc);
+ $graph->SetXTickPos($which_xtick_pos);
+ $graph->SetYTickPos($which_ytick_pos);
+
+
+ $graph->SetShading($which_shading);
+ $graph->SetLineWidth($which_line_width);
+ $graph->SetErrorBarLineWidth($which_errorbar_line_width);
+
+ $graph->SetDrawDashedGrid($which_dashed_grid);
+ switch($which_draw_grid) {
+ case 'x':
+ $graph->SetDrawXGrid(TRUE);
+ $graph->SetDrawYGrid(FALSE);
+ break;
+ case 'y':
+ $graph->SetDrawXGrid(FALSE);
+ $graph->SetDrawYGrid(TRUE);
+ break;
+ case 'both':
+ $graph->SetDrawXGrid(TRUE);
+ $graph->SetDrawYGrid(TRUE);
+ break;
+ case 'none':
+ $graph->SetDrawXGrid(FALSE);
+ $graph->SetDrawYGrid(FALSE);
+ }
+
+ $graph->SetXTickLabelPos($which_xtick_label_pos);
+ $graph->SetYTickLabelPos($which_ytick_label_pos);
+ $graph->SetXDataLabelPos($which_xdata_label_pos);
+ $graph->SetYDataLabelPos($which_ydata_label_pos);
+
+ // Please remember that angles other than 90 are taken as 0 when working fith fixed fonts.
+ $graph->SetXLabelAngle($which_xlabel_angle);
+ $graph->SetYLabelAngle($which_ylabel_angle);
+
+ //$graph->SetLineStyles(array("dashed","dashed","solid","solid"));
+ $graph->SetPointShape($which_point);
+ $graph->SetPointSize($which_point_size);
+ $graph->SetDrawBrokenLines($which_broken);
+
+ // Some forms in format_chart.php don't set this variable, suppress errors.
+ @ $graph->SetErrorBarShape($which_error_type);
+
+ $graph->SetXAxisPosition($which_xap);
+ $graph->SetYAxisPosition($which_yap);
+ $graph->SetPlotBorderType($which_btype);
+
+ if ($maxy_in) {
+ if ($which_data_type = "text-data") {
+ $graph->SetPlotAreaWorld(0,$miny_in,count($data),$maxy_in);
+ }
+ }
+
+/*
+//Even more settings
+
+ $graph->SetPlotAreaWorld(0,100,5.5,1000);
+ $graph->SetPlotAreaWorld(0,-10,6,35);
+ $graph->SetPlotAreaPixels(150,50,600,400);
+
+ $graph->SetDataColors(
+ array("blue","green","yellow","red"), //Data Colors
+ array("black") //Border Colors
+ );
+
+ $graph->SetPlotBgColor(array(222,222,222));
+ $graph->SetBackgroundColor(array(200,222,222)); //can use rgb values or "name" values
+ $graph->SetTextColor("black");
+ $graph->SetGridColor("black");
+ $graph->SetLightGridColor(array(175,175,175));
+ $graph->SetTickColor("black");
+ $graph->SetTitleColor(array(0,0,0)); // Can be array or name
+*/
+
+// $graph->SetPrintImage(false);
+ $graph->DrawGraph();
+// xdebug_dump_function_profile(XDEBUG_PROFILER_FS_SUM);
+?>
--- /dev/null
+<?php
+$example_data = array(
+ array("__A__",0.0,20,4,5,6),
+ array("__B__",2.0,30,5,6,7),
+ array("__C__",3.0,40,5,7,8),
+ array("__D__",4.0,50,3,6,3),
+ array("__E__",4.4,40,3,6,5),
+ array("__F__",5.4,40,5,6,5),
+ array("__G__",5.5,40,7,6,5),
+ array("__H__",7,35,0.0,0.0,""),
+ array("__I__",7.4,40,14,16,25),
+ array("__J__",7.6,40,6,6,5),
+ array("__K__",8.2,40,3,6,5),
+ array("__L__",8.5,40,8,6,9),
+ array("__M__",9.3,40,5,6,5),
+ array("__N__",9.6,40,9,6,7),
+ array("__O__",9.9,40,2,6,5),
+ array("__P__",10.0,40,3,6,8),
+ array("__Q__",10.4,40,3,6,5),
+ array("__R__",10.5,40,3,6,5),
+ array("__S__",10.8,40,3,6,5),
+ array("__T__",11.4,40,3,6,5),
+ array("__U__",12.0,40,3,7,5),
+ array("__V__",13.4,40,3,5,3),
+ array("__W__",14.0,30,3,5,6)
+);
+?>
--- /dev/null
+<?php
+//Title,unixtime_date,value
+
+$example_data = array(
+ array("Jan",883634400,10),
+ array("",883720800,20),
+ array("",883807200,20),
+ array("",883893600,22),
+ array("",883980000,33),
+ array("",884239200,30),
+ array("",884325600,20),
+ array("",884412000,10),
+ array("",884498400,11),
+ array("",884584800,42),
+ array("",884844000,21),
+ array("",884930400,42),
+ array("",885016800,43),
+ array("",885103200,24),
+ array("",885189600,55),
+ array("",885448800,28),
+ array("",885535200,39),
+ array("",885621600,20),
+ array("",885708000,41),
+ array("",885967200,34),
+ array("",886053600,45),
+ array("",886140000,56),
+ array("",886226400,27),
+ array("Feb",886312800,28),
+ array("",886572000,31),
+ array("",886658400,32),
+ array("",886744800,33),
+ array("",886831200,34),
+ array("",886917600,35),
+ array("",887176800,38),
+ array("",887263200,39),
+ array("",887349600,40),
+ array("",887436000,41),
+ array("",887522400,42),
+ array("",887781600,45),
+ array("",887868000,46),
+ array("",887954400,47),
+ array("",888040800,48),
+ array("",888127200,49),
+ array("",888386400,52),
+ array("",888472800,53),
+ array("",888559200,54),
+ array("",888645600,55),
+ array("Mar",888732000,56),
+ array("",888991200,59),
+ array("",889077600,60),
+ array("",889164000,61),
+ array("",889250400,62),
+ array("",889336800,63),
+ array("",889596000,66),
+ array("",889682400,67),
+ array("",889768800,68),
+ array("",889855200,69),
+ array("",889941600,70),
+ array("",890200800,33),
+ array("",890287200,34),
+ array("",890373600,35),
+ array("",890460000,36),
+ array("",890546400,37),
+ array("",890805600,30),
+ array("",890892000,31),
+ array("",890978400,32),
+ array("",891064800,33),
+ array("",891151200,34),
+ array("",891410400,37),
+ array("",891496800,38),
+ array("",891583200,10),
+ array("",891669600,12),
+ array("",891756000,14),
+ array("",892015200,20),
+ array("",892101600,22),
+ array("",892188000,24),
+ array("",892274400,26),
+ array("",892360800,28),
+ array("",892620000,34),
+ array("",892706400,36),
+ array("",892792800,38),
+ array("",892879200,40),
+ array("",892965600,42),
+ array("",893224800,48),
+ array("",893311200,50),
+ array("",893397600,52),
+ array("",893484000,54),
+ array("",893570400,56),
+ array("",893829600,62),
+ array("",893916000,64),
+ array("",894002400,66),
+ array("",894088800,68),
+ array("",894175200,60),
+ array("",894434400,66),
+ array("",894520800,68),
+ array("",894607200,60),
+ array("",894693600,62),
+ array("",894780000,64),
+ array("",895039200,60),
+ array("",895125600,62),
+ array("",895212000,64),
+ array("",895298400,66),
+ array("",895384800,68),
+ array("",895644000,10),
+ array("",895730400,06),
+ array("",895816800,08),
+ array("",895903200,11),
+ array("",895989600,11),
+ array("",896248800,18),
+ array("",896335200,20),
+ array("",896421600,12),
+ array("",896508000,12),
+ array("",896594400,10),
+ array("",896853600,13),
+ array("",896940000,14),
+ array("",897026400,15),
+ array("",897112800,16),
+ array("",897199200,17),
+ array("",897458400,20),
+ array("",897544800,21),
+ array("",897631200,22),
+ array("",897717600,23),
+ array("",897804000,24),
+ array("",898063200,27),
+ array("",898149600,28),
+ array("",898236000,29),
+ array("",898322400,30),
+ array("",898408800,31),
+ array("",898668000,34),
+ array("",898754400,35),
+ array("",898840800,36),
+ array("",898927200,37),
+ array("",899013600,38),
+ array("",899272800,41),
+ array("",899359200,42),
+ array("",899445600,43),
+ array("",899532000,44),
+ array("",899618400,45),
+ array("",899877600,48),
+ array("",899964000,49),
+ array("",900050400,50),
+ array("",900136800,21),
+ array("",900223200,62),
+ array("",900482400,35),
+ array("",900568800,76),
+ array("",900655200,37),
+ array("",900741600,78),
+ array("",900828000,49),
+ array("",901087200,82),
+ array("",901173600,23),
+ array("",901260000,44),
+ array("",901346400,55),
+ array("",901432800,26),
+ array("",901692000,49),
+ array("",901778400,10),
+ array("",901864800,51),
+ array("",901951200,52),
+ array("",902037600,53),
+ array("",902296800,46),
+ array("",902383200,47),
+ array("",902469600,68),
+ array("",902556000,69),
+ array("",902642400,40),
+ array("",902901600,73),
+ array("",902988000,84),
+ array("",903074400,85),
+ array("",903160800,86),
+ array("",903247200,87),
+ array("",903506400,40),
+ array("",903592800,21),
+ array("",903679200,52),
+ array("",903765600,83),
+ array("",903852000,24),
+ array("",904111200,27),
+ array("",904197600,68),
+ array("",904284000,49),
+ array("",904370400,10),
+ array("",904456800,01),
+ array("",904716000,14),
+ array("",904802400,10),
+ array("",904888800,16),
+ array("",904975200,07),
+ array("",905061600,18),
+ array("",905320800,12),
+ array("",905407200,14),
+ array("",905493600,16),
+ array("",905580000,18),
+ array("",905666400,20),
+ array("",905925600,26),
+ array("",906012000,28),
+ array("",906098400,30),
+ array("",906184800,32),
+ array("",906271200,34),
+ array("",906530400,40),
+ array("",906616800,42),
+ array("",906703200,44),
+ array("",906789600,46),
+ array("",906876000,48),
+ array("",907135200,54),
+ array("",907221600,56),
+ array("",907308000,58),
+ array("",907394400,60),
+ array("",907480800,62),
+ array("",907740000,68),
+ array("",907826400,70),
+ array("",907912800,72),
+ array("",907999200,74),
+ array("",908085600,76),
+ array("",908344800,32),
+ array("",908431200,44),
+ array("",908517600,46),
+ array("",908604000,28),
+ array("",908690400,60),
+ array("",908949600,36),
+ array("",909036000,58),
+ array("",909122400,70),
+ array("",909208800,22),
+ array("",909295200,54),
+ array("",909554400,30),
+ array("",909640800,52),
+ array("",909727200,34),
+ array("",909813600,56),
+ array("",909900000,38),
+ array("",909986400,60),
+ array("",910245600,42),
+ array("",910332000,53),
+ array("",910418400,54),
+ array("",910504800,35),
+ array("",910591200,46),
+ array("",910850400,49),
+ array("",910936800,40),
+ array("",911023200,32),
+ array("",911109600,22),
+ array("",911196000,23),
+ array("",911455200,26),
+ array("",911541600,27),
+ array("",911628000,28),
+ array("",911714400,29),
+ array("",911800800,30),
+ array("",912060000,33),
+ array("",912146400,34),
+ array("",912232800,35),
+ array("",912319200,36),
+ array("",912405600,37),
+ array("Dec",912664800,40),
+ array("",912751200,41),
+ array("",912837600,42),
+ array("",912924000,43),
+ array("",913010400,44),
+ array("",913269600,47),
+ array("",913356000,48),
+ array("",913442400,49),
+ array("",913528800,50),
+ array("",913615200,51),
+ array("",913874400,54),
+ array("",913960800,55),
+ array("",914047200,56),
+ array("",914133600,57),
+ array("",914220000,58),
+ array("",914479200,61),
+ array("",914565600,62),
+ array("",914652000,63),
+ array("",914738400,64),
+ array("",914824800,65),
+ array("",915084000,68)
+);
+?>
--- /dev/null
+<?php
+//Title,unixtime_date,value,+error,-error
+
+$example_data = array(
+ array("Jan",883634400,4.62,0.462,0.462),
+ array("",883720800,6.62,0.662,0),
+ array("",883807200,5.62,0,0.562),
+ array("",883893600,5.62,0.562,0),
+ array("",883980000,4.62,0.462,0.462),
+ array("",884239200,6.62,0.662,0),
+ array("",884325600,8.62,0,0.862),
+ array("",884412000,10.62,1.062,0),
+ array("",884498400,11.62,1.162,0),
+ array("",884584800,10.62,0,1.062),
+ array("",884844000,10.62,0,0),
+ array("",884930400,10.62,0,1.062),
+ array("",885016800,10.62,0,1.062),
+ array("",885103200,12.62,1.262,1.262),
+ array("",885189600,12.62,1.262,1.262),
+ array("",885448800,14.62,1.462,1.462),
+ array("",885535200,14.62,1.462,1.462),
+ array("",885621600,14.62,1.462,1.462),
+ array("",885708000,13.62,1.362,0),
+ array("",885967200,14.62,1.462,0),
+ array("",886053600,15.62,1.562,0),
+ array("",886140000,14.62,1.462,0),
+ array("",886226400,16.62,1.662,0),
+ array("Feb",886312800,15.62,1.562,0),
+ array("",886572000,14.62,0,1.462),
+ array("",886658400,13.62,1.362,0),
+ array("",886744800,14.62,1.462,1.462),
+ array("",886831200,13.62,1.362,0),
+ array("",886917600,13.62,1.362,1.362),
+ array("",887176800,14.62,0,1.462),
+ array("",887263200,13.62,1.362,1.362),
+ array("",887349600,13.62,0,1.362),
+ array("",887436000,12.62,1.262,0),
+ array("",887522400,12.62,1.262,1.262),
+ array("",887781600,12.62,0,0),
+ array("",887868000,11.62,1.162,1.162),
+ array("",887954400,11.62,1.162,0),
+ array("",888040800,12.62,0,1.262),
+ array("",888127200,13.62,1.362,1.362),
+ array("",888386400,15.62,1.562,1.562),
+ array("",888472800,17.62,0,1.762),
+ array("",888559200,18.62,0,1.862),
+ array("",888645600,19.62,0,0),
+ array("Mar",888732000,19.62,1.962,0),
+ array("",888991200,18.62,0,0),
+ array("",889077600,17.62,1.762,0),
+ array("",889164000,16.62,1.662,0),
+ array("",889250400,16.62,0,0),
+ array("",889336800,17.62,0,0),
+ array("",889596000,16.62,0,0),
+ array("",889682400,16.62,1.662,0),
+ array("",889768800,18.62,1.862,0),
+ array("",889855200,19.62,0,1.962),
+ array("",889941600,20.62,0,0),
+ array("",890200800,20.62,2.062,0),
+ array("",890287200,21.62,0,0),
+ array("",890373600,23.62,0,2.362),
+ array("",890460000,25.62,0,2.562),
+ array("",890546400,26.62,2.662,2.662),
+ array("",890805600,26.62,2.662,2.662),
+ array("",890892000,25.62,0,0),
+ array("",890978400,26.62,2.662,2.662),
+ array("",891064800,27.62,2.762,0),
+ array("",891151200,29.62,2.962,0),
+ array("",891410400,30.62,0,3.062),
+ array("",891496800,32.62,0,0),
+ array("",891583200,33.62,3.362,0),
+ array("",891669600,33.62,3.362,3.362),
+ array("",891756000,33.62,3.362,0),
+ array("",892015200,33.62,0,0),
+ array("",892101600,34.62,0,0),
+ array("",892188000,35.62,3.562,0),
+ array("",892274400,36.62,3.662,3.662),
+ array("",892360800,37.62,0,3.762),
+ array("",892620000,36.62,3.662,0),
+ array("",892706400,38.62,3.862,0),
+ array("",892792800,37.62,3.762,0),
+ array("",892879200,39.62,3.962,0),
+ array("",892965600,39.62,3.962,0),
+ array("",893224800,38.62,0,3.862),
+ array("",893311200,40.62,4.062,0),
+ array("",893397600,40.62,4.062,0),
+ array("",893484000,41.62,0,0),
+ array("",893570400,40.62,4.062,4.062),
+ array("",893829600,39.62,0,0),
+ array("",893916000,40.62,0,4.062),
+ array("",894002400,40.62,0,4.062),
+ array("",894088800,42.62,0,0),
+ array("",894175200,44.62,0,0),
+ array("",894434400,45.62,0,4.562),
+ array("",894520800,44.62,4.462,4.462),
+ array("",894607200,43.62,4.362,4.362),
+ array("",894693600,45.62,0,0),
+ array("",894780000,46.62,4.662,0),
+ array("",895039200,48.62,0,0),
+ array("",895125600,48.62,4.862,0),
+ array("",895212000,50.62,0,0),
+ array("",895298400,52.62,5.262,0),
+ array("",895384800,54.62,0,5.462),
+ array("",895644000,53.62,0,5.362),
+ array("",895730400,54.62,5.462,0),
+ array("",895816800,56.62,5.662,5.662),
+ array("",895903200,56.62,0,5.662),
+ array("",895989600,55.62,5.562,5.562),
+ array("",896248800,54.62,0,5.462),
+ array("",896335200,53.62,5.362,5.362),
+ array("",896421600,54.62,5.462,5.462),
+ array("",896508000,54.62,0,5.462),
+ array("",896594400,54.62,0,5.462),
+ array("",896853600,55.62,5.562,5.562),
+ array("",896940000,56.62,0,5.662),
+ array("",897026400,57.62,5.762,0),
+ array("",897112800,57.62,0,5.762),
+ array("",897199200,59.62,5.962,0),
+ array("",897458400,61.62,6.162,0),
+ array("",897544800,63.62,6.362,0),
+ array("",897631200,64.62,0,6.462),
+ array("",897717600,63.62,0,6.362),
+ array("",897804000,63.62,0,6.362),
+ array("",898063200,63.62,6.362,6.362),
+ array("",898149600,63.62,6.362,6.362),
+ array("",898236000,63.62,0,0),
+ array("",898322400,65.62,6.562,0),
+ array("",898408800,67.62,6.762,0),
+ array("",898668000,68.62,6.862,6.862),
+ array("",898754400,69.62,0,6.962),
+ array("",898840800,68.62,6.862,6.862),
+ array("",898927200,68.62,6.862,6.862),
+ array("",899013600,69.62,6.962,6.962),
+ array("",899272800,69.62,0,6.962),
+ array("",899359200,71.62,0,0),
+ array("",899445600,71.62,7.162,7.162),
+ array("",899532000,72.62,0,7.262),
+ array("",899618400,72.62,0,7.262),
+ array("",899877600,71.62,7.162,7.162),
+ array("",899964000,72.62,7.262,0),
+ array("",900050400,74.62,0,7.462),
+ array("",900136800,74.62,0,7.462),
+ array("",900223200,75.62,0,7.562),
+ array("",900482400,77.62,0,7.762),
+ array("",900568800,79.62,0,7.962),
+ array("",900655200,78.62,7.862,0),
+ array("",900741600,78.62,0,0),
+ array("",900828000,77.62,0,0),
+ array("",901087200,78.62,0,7.862),
+ array("",901173600,77.62,7.762,7.762),
+ array("",901260000,79.62,0,7.962),
+ array("",901346400,80.62,0,8.062),
+ array("",901432800,80.62,0,0),
+ array("",901692000,79.62,7.962,0),
+ array("",901778400,81.62,8.162,8.162),
+ array("",901864800,80.62,8.062,0),
+ array("",901951200,79.62,0,7.962),
+ array("",902037600,80.62,0,8.062),
+ array("",902296800,82.62,0,0),
+ array("",902383200,83.62,8.362,8.362),
+ array("",902469600,85.62,0,8.562),
+ array("",902556000,84.62,0,0),
+ array("",902642400,85.62,0,0),
+ array("",902901600,85.62,8.562,8.562),
+ array("",902988000,87.62,0,0),
+ array("",903074400,88.62,8.862,0),
+ array("",903160800,87.62,8.762,8.762),
+ array("",903247200,88.62,8.862,8.862),
+ array("",903506400,88.62,8.862,0),
+ array("",903592800,88.62,0,0),
+ array("",903679200,87.62,0,0),
+ array("",903765600,87.62,8.762,8.762),
+ array("",903852000,88.62,8.862,0),
+ array("",904111200,87.62,8.762,8.762),
+ array("",904197600,88.62,0,0),
+ array("",904284000,89.62,8.962,8.962),
+ array("",904370400,88.62,0,8.862),
+ array("",904456800,89.62,8.962,8.962),
+ array("",904716000,90.62,0,0),
+ array("",904802400,92.62,9.262,9.262),
+ array("",904888800,92.62,0,9.262),
+ array("",904975200,94.62,9.462,0),
+ array("",905061600,95.62,9.562,0),
+ array("",905320800,94.62,9.462,9.462),
+ array("",905407200,93.62,0,9.362),
+ array("",905493600,95.62,9.562,9.562),
+ array("",905580000,95.62,0,0),
+ array("",905666400,94.62,0,9.462),
+ array("",905925600,96.62,9.662,9.662),
+ array("",906012000,98.62,9.862,0),
+ array("",906098400,100.62,0,0),
+ array("",906184800,102.62,0,0),
+ array("",906271200,102.62,10.262,10.262),
+ array("",906530400,102.62,0,0),
+ array("",906616800,101.62,0,0),
+ array("",906703200,101.62,10.162,10.162),
+ array("",906789600,103.62,0,10.362),
+ array("",906876000,102.62,10.262,0),
+ array("",907135200,103.62,10.362,10.362),
+ array("",907221600,103.62,10.362,0),
+ array("",907308000,103.62,0,10.362),
+ array("",907394400,104.62,0,0),
+ array("",907480800,104.62,0,10.462),
+ array("",907740000,103.62,0,0),
+ array("",907826400,105.62,0,10.562),
+ array("",907912800,104.62,0,0),
+ array("",907999200,104.62,0,10.462),
+ array("",908085600,103.62,0,0),
+ array("",908344800,102.62,10.262,0),
+ array("",908431200,102.62,0,10.262),
+ array("",908517600,104.62,0,10.462),
+ array("",908604000,104.62,0,0),
+ array("",908690400,106.62,10.662,0),
+ array("",908949600,107.62,0,10.762),
+ array("",909036000,109.62,10.962,0),
+ array("",909122400,109.62,10.962,10.962),
+ array("",909208800,110.62,11.062,0),
+ array("",909295200,109.62,0,10.962),
+ array("",909554400,111.62,0,11.162),
+ array("",909640800,111.62,11.162,0),
+ array("",909727200,113.62,11.362,11.362),
+ array("",909813600,115.62,0,11.562),
+ array("",909900000,117.62,11.762,11.762),
+ array("",909986400,117.62,0,11.762),
+ array("",910245600,116.62,11.662,11.662),
+ array("",910332000,118.62,11.862,11.862),
+ array("",910418400,120.62,0,12.062),
+ array("",910504800,121.62,12.162,0),
+ array("",910591200,120.62,12.062,0),
+ array("",910850400,122.62,12.262,0),
+ array("",910936800,122.62,0,0),
+ array("",911023200,123.62,0,0),
+ array("",911109600,124.62,0,12.462),
+ array("",911196000,125.62,12.562,0),
+ array("",911455200,124.62,12.462,0),
+ array("",911541600,123.62,12.362,0),
+ array("",911628000,124.62,12.462,12.462),
+ array("",911714400,126.62,0,0),
+ array("",911800800,126.62,0,0),
+ array("",912060000,127.62,0,12.762),
+ array("",912146400,126.62,12.662,12.662),
+ array("",912232800,127.62,0,12.762),
+ array("",912319200,126.62,0,0),
+ array("",912405600,125.62,0,12.562),
+ array("Dec",912664800,126.62,0,0),
+ array("",912751200,108.62,0,12.862),
+ array("",912837600,108.62,0,12.862),
+ array("",912924000,109.62,12.962,12.962),
+ array("",913010400,100.62,0,0),
+ array("",913269600,109.62,0,0),
+ array("",913356000,108.62,0,0),
+ array("",913442400,108.62,0,0),
+ array("",913528800,108.62,0,12.862),
+ array("",913615200,100.62,13.062,0),
+ array("",913874400,109.62,12.962,0),
+ array("",913960800,108.62,12.862,0),
+ array("",914047200,108.62,12.862,12.862),
+ array("",914133600,107.62,0,12.762),
+ array("",914220000,108.62,0,12.862),
+ array("",914479200,107.62,0,0),
+ array("",914565600,107.62,12.762,12.762),
+ array("",914652000,109.62,12.962,12.962),
+ array("",914738400,101.62,0,0),
+ array("",914824800,100.62,0,0),
+ array("",915084000,109.62,0,12.962)
+);
+?>
--- /dev/null
+<p>
+Data type: (Text-data)<br />
+</p>
+<input type="hidden" name="which_data_type" value="text-data" />
+<table border=1>
+ <tr>
+ <td>Title (x axis)</td><td>Y data 1</td><td>Y data 2</td>
+ <td>Y data 3</td> <td>Y data 4</td>
+ </tr>
+
+<?php
+ srand ((double) microtime() * 12341234);
+ $a = 25;
+ $b = 10;
+ $c = -5;
+ for ($i=0; $i<5; $i++) {
+ $a += rand(-2, 2);
+ $b += rand(-5, 5);
+ $c += rand(-2, 2);
+
+?>
+ <tr>
+ <td>
+ <input type="text" name="data_row0[<?php echo $i?>]" value="Year <?php echo $i?>" />
+ </td><td>
+ <input type="text" name="data_row1[<?php echo $i?>]" value="<?php echo $a?>" size="3" />
+ </td><td>
+ <input type="text" name="data_row2[<?php echo $i?>]" value="<?php echo $b?>" size="3" />
+ </td><td>
+ <input type="text" name="data_row3[<?php echo $i?>]" value="<?php echo $c?>" size="3" />
+ </td><td>
+ <input type="text" name="data_row4[<?php echo $i?>]" value="<?php echo $c+1?>" size="3" />
+ </td>
+ </tr>
+<?php
+ }
+?>
+
+</table>
+
+<p>
+Graph type:
+<select name="which_plot_type">
+ <option value="bars">Bars (*)</option>
+ <option value="thinbarline">Thin bars</option>
+ <option value="lines">Lines</option>
+ <option value="squared">Squared lines</option>
+ <option value="pie">Pie (*)</option>
+ <option value="linepoints">Line and points</option>
+ <option value="points">Points</option>
+ <option value="area">Area</option>
+</select>
+</p>
+<div style="text-align:right; font-size: smaller;">
+Please note when writing your application that the graph <br />
+types marked with an asterisk only support the data <br />
+type for this form, "text-data".
+</div>
--- /dev/null
+<?php
+//data-data as just data
+ $data = array(
+ array("label 0", 0, 2, 5, 3 ),
+ array("label 1", 2, 3, 4, 2 ),
+ array("label 2", 3, 4, 3, 7 ),
+ array("label 3", 4.5, 5, 2, 4 ),
+ array("label 4", 5, 6, 1, 1 )
+ );
+?>
+<p>
+Data type: (data-data)<br />
+<input type="hidden" name="which_data_type" value="data-data" />
+<table border=1>
+ <tr>
+ <td>Title (data label)</td><td>X data</td><td>Y data 1</td>
+ <td>Y data 2</td><td>Y data 3</td>
+ </tr>
+
+ <?php
+ for ($i=0; $i<5; $i++) {
+ ?>
+ <tr>
+ <td>
+ <input type="text" name="data_row0[<?php echo $i?>]" value="<?php echo $data[$i][0]?>" />
+ </td><td>
+ <input type="text" name="data_row1[<?php echo $i?>]" value="<?php echo $data[$i][1]?>" size="3" />
+ </td><td>
+ <input type="text" name="data_row2[<?php echo $i?>]" value="<?php echo $data[$i][2]?>" size="3" />
+ </td><td>
+ <input type="text" name="data_row3[<?php echo $i?>]" value="<?php echo $data[$i][3]?>" size="3" />
+ </td><td>
+ <input type="text" name="data_row4[<?php echo $i?>]" value="<?php echo $data[$i][4]?>" size="3" />
+ </td>
+ </tr>
+
+ <?php
+ }
+ ?>
+
+</table>
+
+<p>
+Graph type:
+<select name="which_plot_type">
+ <option value="area">Area</option>
+ <option value="lines">Lines</option>
+ <option value="squared">Squared lines</option>
+ <option value="linepoints">Line and points</option>
+ <option value="points">Points</option>
+</select>
+</p>
--- /dev/null
+<p>
+Data set as X, Y, E+, E-, Y2, E2+, E2-,... <br />
+<?php
+//data-data-error
+ $num_rows = 6;
+ $data = array(
+ array("label 0", 0, 1, .5, .1, 1, .2, .1),
+ array("label 1", 2, 5, .5, .4, 2, .1, .3),
+ array("label 2", 3, 2, .1, .1, 3, .3, .1),
+ array("label 3", 4, 5, .5, .5, 3.5,.1, .2),
+ array("label 4", 5, 1, .1, .1, 5, .1, .1),
+ array("label 5", 6, 2, .1, .2, 0, .2, .3)
+ );
+?>
+Data type: (data-data-error)
+</p>
+<input type="hidden" name="which_data_type" value="data-data-error" />
+<table border=1>
+ <tr><td>Title (data label)</td><td>X data</td>
+ <td>Y data 1</td><td>Error +</td><td>Error -</td><td>Y data 2</td><td>Error +</td><td>Error -</td>
+ </tr>
+ <tr>
+ <td>
+
+ <?php
+ // MBD: All this is more complicated than before, but allows for easy adding of rows and columns
+ echo "<input type=\"hidden\" name=\"num_data_rows\" value=\"$num_rows\" />";
+
+ for ($i = 0; $i < $num_rows; $i++) {
+ // The label input element must be bigger.
+ $lines[0] = "<input type=\"text\" name=\"data_row".$i."[0]\" value=\"".$data[$i][0]."\" size=\"10\" />\n";
+
+ // Show <input>s for the rest of the columns
+ for ($j=1; $j<8; $j++)
+ $lines[$j] = "<input type=\"text\" name=\"data_row".$i."[$j]\" value=\"".$data[$i][$j]."\" size=\"3\" />\n";
+ $groups[$i] = join('</td><td>', $lines);
+ }
+ echo join("</tr><tr><td>\n", $groups);
+ ?>
+
+ </td>
+ </tr>
+</table>
+
+<p>
+Graph type:
+<select name="which_plot_type">
+ <option value="lines">lines</option>
+ <option value="linepoints">line and points</option>
+ <option value="points">points</option>
+</select>
+
+Error bar type:
+<select name="which_error_type">
+ <option value="tee">tee</option>
+ <option value="line">line</option>
+</select>
+</p>
--- /dev/null
+<p>
+Data type: <i>data-data</i> calculated from a function.
+</p>
+<pre>
+ $dx = ".3";
+ $max = 6.4;
+ $maxi = $max/$dx;
+ for ($i=0; $i<$maxi; $i++) {
+ $a = 4;
+ $x = $dx*$i;
+ $data[$i] = array("", $x, $a*sin($x),
+ $a*cos($x), $a*cos($x+1));
+ }
+</pre>
+<p>
+Chart type:
+<select name="which_plot_type">
+ <option value="lines">Lines</option>
+ <option value="linepoints">Lines and points</option>
+ <option value="points">Points</option>
+ <option value="thinbarline">Thin bars</option>
+</select>
+<input type="hidden" name="which_data_type" value="function" />
+</p>
--- /dev/null
+<p>
+Data type: <i>data-data-error</i> calculated from a function.
+</p>
+<pre>
+ srand ((double) microtime() * 1000000);
+ $a = 9.62;
+ $label[0] = "October"; $label[5] = "Day 5"; $label[10] = "Day 10";
+ $label[15] = "Day 15"; $label[20] = "Day 20"; $label[25] = "Day 25";
+
+ for ($i = 0; $i <= 30; $i++) {
+ $a += rand(-1, 2);
+ $b = rand(0,1);
+ $c = rand(0,1);
+ $data[] = @ array($label[$i],$i+1,$a,$b,$c);
+ }
+</pre>
+<p>
+Chart type:
+<select name="which_plot_type">
+ <option value="lines">Lines</option>
+ <option value="linepoints">Lines and points</option>
+ <option value="points">Points</option>
+</select>
+
+Error bar type:
+<select name="which_error_type">
+ <option value="tee">tee</option>
+ <option value="line">line</option>
+</select>
+<input type="hidden" name="which_data_type" value="randfunction" />
+</p>
--- /dev/null
+<?php
+//Include the code
+include("../phplot.php");
+
+//Define the object
+$graph = new PHPlot;
+
+//Set some data
+include("./data.php");
+$graph->SetDataValues($example_data);
+
+
+//Draw it
+$graph->DrawGraph();
+
+?>
--- /dev/null
+<?php
+//Include the code
+include("../phplot.php");
+
+//Define the Object
+$graph = new PHPlot;
+
+//Define some data
+include("./data.php");
+
+//Set the data type
+$graph->SetDataType("linear-linear");
+
+//Remove the X data labels
+//$graph->SetXGridLabelType("none");
+
+//Load the data into data array
+$graph->SetDataValues($example_data);
+
+//Draw the graph
+$graph->DrawGraph();
+?>
--- /dev/null
+<?php
+//Include the code
+include("../phplot.php");
+
+//Include the code for manipulating data (scaling, moving averages, etc.)
+include("../phplot_data.php");
+
+//Define the object
+$graph = new PHPlot_Data();
+
+//Define some data
+include("./data.php");
+
+//Set the data type
+$graph->SetDataType("data-data");
+
+//Load the data into the data array
+$graph->SetDataValues($example_data);
+$graph->DoMovingAverage(4,2,TRUE);
+
+//Call Scaling Function (in phplot_data.php)
+//$graph->DoScaleData(1,1);
+
+//Draw a Legend at pixel location 100,100
+$graph->SetLegendPixels(100,100,"");
+
+//have no labels on Y axis
+//$graph->SetYGridLabelType("none");
+
+//Print that puppy!
+$graph->DrawGraph();
+?>
--- /dev/null
+<?php
+
+//Include the code
+include("../phplot.php");
+
+//Define the object
+$graph = new PHPlot;
+
+//Create some random data as ("label",X-position, Y-position, error+, error-)
+//linear-linear-error data
+unset($data);
+$a = 4.62;
+srand ((double) microtime() * 1000);
+////////////////////////////////////////////////
+/////Note: for $label[5] to appear on the X axis,
+///// there must be a horizontal tick mark at x=5, etc.
+/////////////////////////////////////////////
+$label[0] = "October";
+$label[5] = "Day 5";
+$label[10] = "Day 10";
+$label[15] = "Day 15";
+$label[20] = "Day 20";
+$label[25] = "Day 25";
+$label[30] = "Day 30";
+Error_Reporting(0);
+for ($i=0; $i<=50; $i++){
+ $a += rand(-1, 2);
+ $b = $a*rand(0,1)/10;
+ $c = $a*rand(0,1)/10;
+ $data[] = array("$label[$i]",$i+1,$a,$b,$c);
+
+}
+
+
+//Define the data for error bars
+ $graph->SetDataType("linear-linear-error"); //Must be first thing
+
+//Set the Graph particulars
+ $graph->SetPrecisionX(0);
+ $graph->SetPrecisionY(0);
+ $graph->SetUseTTF("0");
+ $graph->SetDrawYGrid("1"); // 1 = true
+ $graph->SetDataValues($data);
+ $graph->SetImageArea(600, 400);
+ $graph->SetVertTickIncrement("");
+ $graph->SetHorizTickIncrement(1);
+ $graph->SetErrorBarLineWidth(1);
+ $graph->SetYScaleType("log");
+ $graph->SetPointShape("halfline");
+ $graph->SetErrorBarShape("line");
+ $graph->SetPlotType("points");
+ $graph->SetXGridLabelType("title");
+ $graph->SetXLabel("Day");
+ $graph->SetYLabel("Stock value");
+ $graph->SetTitle("Logarithmic scale\nexample 4");
+ //$graph->SetErrorBarColors(array("blue","red","green","black"));
+ $graph->SetDataColors(
+ array("blue","green","yellow","red"), //Data Colors
+ array("black") //Border Colors
+ );
+
+ $graph->SetPlotAreaWorld(0,0,32,50);
+ //$graph->SetPlotAreaPixels(150,50,600,400);
+
+/*
+//Other settings
+ $graph->SetPlotBgColor(array(222,222,222));
+ $graph->SetBackgroundColor(array(200,222,222)); //can use rgb values or "name" values
+ $graph->SetTextColor("black");
+ $graph->SetGridColor("black");
+ $graph->SetLightGridColor(array(175,175,175));
+ $graph->SetTickColor("black");
+ $graph->SetTitleColor(array(0,0,0)); // Can be array or name
+
+*/
+
+
+//Draw the graph
+ $graph->DrawGraph();
+?>
--- /dev/null
+<?php
+include("../phplot.php");
+$graph = new PHPlot(600,200);
+include("./data_date.php");
+$graph->SetDataType("data-data"); //Must be called before SetDataValues
+
+$graph->SetXGridLabelType("time");
+$graph->SetXDataLabelAngle(90);
+$graph->SetXLabel("");
+$graph->SetYLabel("Volume");
+$graph->SetVertTickIncrement(30);
+$graph->SetXTimeFormat("%b %y");
+$graph->SetDataValues($example_data);
+$graph->SetHorizTickIncrement(2679000);
+$graph->SetPlotType("thinbarline");
+$graph->SetDrawXDataLabels(false);
+$graph->SetPlotAreaWorld(883634400,0,915095000,90);
+$graph->DrawGraph();
+?>
--- /dev/null
+<?php
+include("./data_date2.php");
+include("../phplot.php");
+$graph = new PHPlot;
+$graph->SetDataType("data-data-error"); //Must be called before SetDataValues
+
+$graph->SetImageArea(600,400);
+$graph->SetPrecisionY(0);
+$graph->SetXLabel("");
+$graph->SetYLabel("Volume");
+$graph->SetVertTickIncrement(20);
+$graph->SetXAxisPosition(1);
+//$graph->SetSkipBottomTick(1);
+
+//Set Unixtime Increment and X Axis Settings
+$graph->SetHorizTickIncrement(2679000);
+$graph->SetXGridLabelType("time");
+$graph->SetXTimeFormat("%b %y");
+$graph->SetXDataLabelAngle(90);
+
+$graph->SetDataValues($example_data);
+$graph->SetPlotType("lines");
+$graph->SetErrorBarShape("line");
+$graph->SetPointShape("halfline");
+$graph->SetYScaleType("log");
+$graph->SetLineWidth(1);
+$graph->SetDrawXDataLabels(false);
+
+//Since X axis is in Unixtime format we set the limits accordingly
+$graph->SetPlotAreaWorld(883634400,1,915095000,140);
+
+$graph->DrawGraph();
+?>
--- /dev/null
+<?php
+include("./data_date2.php");
+include("../phplot.php");
+$graph = new PHPlot(600,400);
+$graph->SetPrintImage(0); //Don't draw the image yet
+
+$graph->SetDataType("data-data-error"); //Must be called before SetDataValues
+
+$graph->SetNewPlotAreaPixels(90,40,540,190);
+$graph->SetDataValues($example_data);
+
+$graph->SetXLabelType("time");
+$graph->SetXLabelAngle(90);
+$graph->SetXTitle("");
+$graph->SetYTitle("Price");
+$graph->SetYTickIncrement(20);
+$graph->SetXTickIncrement(2679000);
+$graph->SetXTimeFormat("%b %y");
+$graph->SetPlotType("lines");
+$graph->SetErrorBarShape("line");
+$graph->SetPointShape("halfline");
+$graph->SetYScaleType("log");
+$graph->SetLineWidths(array(1));
+$graph->SetPlotAreaWorld(883634400,1,915095000,140);
+$graph->SetXDataLabelPos('none');
+$graph->DrawGraph();
+
+//Now do the second chart on the image
+
+unset($example_data);
+
+$graph->SetYScaleType("linear");
+include("./data_date.php");
+
+$graph->SetDataType("data-data"); //Must be called before SetDataValues
+
+$graph->SetDataValues($example_data);
+$graph->SetNewPlotAreaPixels(90,260,540,350);
+$graph->SetDataValues($example_data);
+
+$graph->SetXLabelType("time");
+$graph->SetXLabelAngle(90);
+$graph->SetXTitle("");
+$graph->SetYTitle("Volume");
+$graph->SetYTickIncrement(30);
+$graph->SetPlotType("thinbarline");
+
+//Set how to display the x-axis ticks
+$graph->SetXTimeFormat("%b %y");
+$graph->SetXTickIncrement(2679000);
+$graph->SetXAxisPosition(0); //Have to reset it after log plots
+
+//Set Plot to go from x = Jan 1 1998, to x = Dec 31 1998
+// and from y = 0 to y = 90
+$graph->SetPlotAreaWorld(883634400,0,915095000,90);
+
+$graph->DrawGraph();
+
+//Print the image
+$graph->PrintImage();
+?>
--- /dev/null
+<?php
+//Include the code
+include("../phplot.php");
+
+//Define the object
+$graph = new PHPlot();
+
+//Define some data
+include("./data.php");
+$graph->SetDataValues($example_data);
+
+//Don't print until we say so
+$graph->SetPrintImage(0);
+
+//Draw it
+$graph->DrawGraph();
+
+//Define some colors
+$ndx_color = $graph->SetIndexColor("blue");
+$ndx_color1 = $graph->SetIndexColor("orange");
+
+//The image data colors are now ndx_data_color[]
+$graph->DrawDashedLine(250,$graph->plot_area[1],250,250,4,0,$graph->ndx_data_colors[0]);
+
+$graph->DrawDashedLine($graph->xtr(5),$graph->ytr(12),
+ $graph->xtr(20),$graph->ytr(42),5,3,$ndx_color);
+
+$graph->DrawDashedLine($graph->plot_area[0],250,$graph->plot_area[2],250,2,0,$ndx_color1);
+$graph->DrawDashedLine($graph->plot_area[0],251,$graph->plot_area[2],251,2,0,$ndx_color1);
+
+
+//Now print the image
+$graph->PrintImage();
+
+?>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <title>Example-o-matic</title>
+ <link type="text/css" rel="stylesheet" href="../doc/style.css" />
+</head>
+<body>
+
+<div class="nav"> [ <a href="../doc/index.php">Go to the index</a> ] </div>
+
+<h2>PHPlot test graph form</h2>
+
+<p>Use this form to test many different options of PHPlot. You can test
+every graph type supported for any of four different data types. You can
+tweak as you like or you can leave everything as is and press "Submit" for
+automatic values.
+</p>
+<form action="create_chart.php" method="post">
+<center>
+<table border="0">
+
+ <tr><td colspan="2" class="hdr">Data Settings</td></tr>
+
+<tr>
+ <td colspan="2">
+ <p>
+ Data type: [
+ <a href="format_chart.php?which_data_type=text-data">text-data</a> |
+ <a href="format_chart.php?which_data_type=data-data">data-data</a> |
+ <a href="format_chart.php?which_data_type=function">function</a> |
+ <a href="format_chart.php?which_data_type=data-data-error">data-data-error</a> |
+ <a href="format_chart.php?which_data_type=randfunction">randfunction</a> ]
+ </p>
+ <?php
+ if ($_GET['which_data_type'] == 'text-data')
+ include('data_sample1.php');
+ elseif ($_GET['which_data_type'] == 'data-data')
+ include('data_sample2.php');
+ elseif ($_GET['which_data_type'] == 'data-data-error')
+ include('data_sample3.php');
+ elseif ($_GET['which_data_type'] == 'function')
+ include('data_sample4.php');
+ elseif ($_GET['which_data_type'] == 'randfunction')
+ include('data_sample5.php');
+ else
+ include('data_sample1.php');
+ ?>
+ </td>
+</tr>
+ <tr><td colspan="2" class="hdr"><input name="submit" type="submit" /></td></tr>
+ <tr>
+ <td colspan="2">
+ <br />
+ <h3 style="text-align:center;margin:0;">Optional values</h3>
+ <br />
+ </td>
+ </tr>
+ <tr><td colspan="2" class="hdr">Sizes</td></tr>
+
+<tr>
+ <td>Width of graph in pixels:</td>
+ <td><input type="text" name="xsize_in" value="600" size="4" /></td>
+</tr>
+<tr>
+ <td> Height of graph in pixels:</td>
+ <td><input type="text" name="ysize_in" value="400" size="4" /></td>
+</tr>
+<tr>
+ <td>Maximum height of graph in y axis units:</td>
+ <td><input type="text" name="maxy_in" value="" size="4" /></td>
+</tr>
+<tr>
+ <td>Minimum height of graph in y axis units:</td>
+ <td><input type="text" name="miny_in" value="" size="4" /></td>
+</tr>
+
+ <tr><td colspan="2" class="hdr">Titles and data labels</td></tr>
+
+<tr>
+ <td>Title:</td>
+ <td><input type="text" name="title" value="This is a title" /></td>
+</tr>
+<tr>
+ <td>Y axis title:</td>
+ <td><input type="text" name="ylbl" value="Revenue in millions" /></td>
+</tr>
+<tr>
+ <td>Y axis title position:</td>
+ <td>
+ <select name="which_ytitle_pos">
+ <option value="plotleft">Left of plot</option>
+ <option value="plotright">Right of plot</option>
+ <option value="both" selected>Both right and left</option>
+ <option value="none">No Y axis title</option>
+ </select>
+ </td>
+</tr>
+<tr>
+ <td>Y axis data labels position:</td>
+ <td>
+ <select name="which_ydata_label_pos">
+ <option value="plotleft">Left of plot</option>
+ <option value="plotright">Right of plot</option>
+ <option value="both">Both right and left</option>
+ <option value="plotin">In the plot (To Do)</option>
+ <option value="none" selected>No data labels</option>
+ </select>
+ </td>
+</tr>
+<tr>
+ <td>Y axis labels angle:</td>
+ <td><input name="which_ylabel_angle" value="0" size="3" /></td>
+</tr>
+
+
+<tr>
+ <td>X axis title:</td>
+ <td><input type="text" name="xlbl" value="years" /></td>
+</tr>
+<tr>
+ <td>X axis title position:</td>
+ <td>
+ <select name="which_xtitle_pos">
+ <option value="plotup">Up of plot</option>
+ <option value="plotdown">Down of plot</option>
+ <option value="both" selected>Both up and down</option>
+ <option value="none">No X axis title</option>
+ </select>
+ </td>
+</tr>
+<tr>
+ <td>X axis data labels position:</td>
+ <td>
+ <select name="which_xdata_label_pos">
+ <option value="plotup">Up of plot</option>
+ <option value="plotdown">Down of plot</option>
+ <option value="both" selected>Both up and down</option>
+ <option value="plotin">In the plot (To Do)</option>
+ <option value="none" selected>No data labels</option>
+ </select>
+ </td>
+</tr>
+<tr>
+ <td>X axis labels angle:</td>
+ <td><input name="which_xlabel_angle" value="0" size="3" /></td>
+</tr>
+
+ <tr><td colspan="2" class="hdr">Grid and ticks</td></tr>
+
+
+<tr>
+ <td>Grid drawn:</td>
+ <td>
+ <select name="which_draw_grid">
+ <option value="x">Vertical grid</option>
+ <option value="y">Horizontal grid</option>
+ <option value="both" selected>Both grids</option>
+ <option value="none">No grid</option>
+ </select>
+ </td>
+</tr>
+<tr>
+ <td>Dashed grid?</td>
+ <td>
+ <select name="which_dashed_grid">
+ <option value="1" selected>Yes</option>
+ <option value="0">No</option>
+ </select>
+ </td>
+</tr>
+<tr>
+ <td>X axis ticks length:</td>
+ <td><input type="text" name="which_xtl" value="5" size="3"/></td>
+</tr>
+<tr>
+ <td>X axis ticks crossing:</td>
+ <td><input type="text" name="which_xtc" value="3" size="3"/></td>
+</tr>
+<tr>
+ <td>X axis ticks position:</td>
+ <td>
+ <select name="which_xtick_pos">
+ <option value="plotup">Up of plot</option>
+ <option value="plotdown">Down of plot</option>
+ <option value="both" selected>Both up and down</option>
+ <option value="xaxis">At X axis</option>
+ <option value="none">No ticks</option>
+ </select>
+ </td>
+</tr>
+<tr>
+ <td>X axis tick labels position:</td>
+ <td>
+ <select name="which_xtick_label_pos">
+ <option value="plotup">Up of plot</option>
+ <option value="plotdown">Down of plot</option>
+ <option value="both" selected>Both up and down</option>
+ <option value="xaxis">Below X axis</option>
+ <option value="none">No tick labels</option>
+ </select>
+ </td>
+</tr>
+<tr>
+ <td>Y axis ticks length:</td>
+ <td><input type="text" name="which_ytl" value="5" size="3"/></td>
+</tr>
+<tr>
+ <td>Y axis ticks crossing:</td>
+ <td><input type="text" name="which_ytc" value="3" size="3"/></td>
+</tr>
+<tr>
+ <td>Y axis ticks position:</td>
+ <td>
+ <select name="which_ytick_pos">
+ <option value="plotleft">Left of plot</option>
+ <option value="plotright">Right of plot</option>
+ <option value="both" selected>Both right and left</option>
+ <option value="yaxis">At Y axis</option>
+ <option value="none">No ticks</option>
+ </select>
+ </td>
+</tr>
+<tr>
+ <td>Y axis tick labels position:</td>
+ <td>
+ <select name="which_ytick_label_pos">
+ <option value="plotleft">Left of plot</option>
+ <option value="plotright">Right of plot</option>
+ <option value="both" selected>Both right and left</option>
+ <option value="yaxis">Left of Y axis</option>
+ <option value="none">No tick labels</option>
+ </select>
+ </td>
+</tr>
+<tr>
+ <td>X tick increment:</td>
+ <td><input type="text" name="which_xti" value="1" /></td>
+</tr>
+<tr>
+ <td>Y tick increment:</td>
+ <td><input type="text" name="which_yti" value="" /></td>
+</tr>
+
+
+ <tr><td colspan="2" class="hdr">Other</td></tr>
+
+
+<tr>
+ <td>X axis position:</td>
+ <td><input type="text" name="which_xap" value="0" size="5"/></td>
+</tr>
+<tr>
+ <td>Y axis position:</td>
+ <td><input type="text" name="which_yap" value="0" size="5"/></td>
+</tr>
+<tr>
+ <td>Plot Border:</td>
+ <td>
+ <select name="which_btype">
+ <option value="plotleft">Left of plot</option>
+ <option value="plotright">Right of plot</option>
+ <option value="both">Both sides of plot</option>
+ <option value="full" selected>All four sides</option>
+ <option value="none">None</option>
+ </select>
+ </td>
+</tr>
+
+
+<tr>
+ <td>Shade height (0 for none):</td>
+ <td><input type="text" name="which_shading" value="5" size="3"/></td>
+</tr>
+<tr>
+ <td>Plot line width:</td>
+ <td><input name="which_line_width" value="1" size="3" /></td>
+</tr>
+<tr>
+ <td>Error bar line width:</td>
+ <td><input name="which_errorbar_line_width" value="1" size="3" /></td>
+</tr>
+<tr>
+ <td>Point Type:</td>
+ <td>
+ <select name="which_point">
+ <option value="diamond">Diamond</option>
+ <option value="rect">Square</option>
+ <option value="circle">Circle</option>
+ <option value="triangle">Triangle</option>
+ <option value="trianglemid">Centered triangle</option>
+ <option value="dot">Filled dot</option>
+ <option value="line">Line</option>
+ <option value="halfline">Half line</option>
+ <option value="cross" selected>Cross</option>
+ <option value="plus" selected>Plus sign</option>
+ </select>
+ </td>
+</tr>
+<tr>
+ <td>Point Size:</td>
+ <td><input name="which_point_size" value="4" size="3" /></td>
+</tr>
+<tr>
+ <td>Draw broken lines with missing Y data:</td>
+ <td>
+ <select name="which_broken">
+ <option value="0" selected>No</option>
+ <option value="1">Yes</option>
+ </select>
+<tr>
+ <td>Use TrueType font:</td>
+ <td>
+ <select name="which_use_ttf">
+ <option value="0" selected>No</option>
+ <option value="1">Yes</option>
+ </select>
+ </td>
+</tr>
+<tr>
+ <td>File format:</td>
+ <td>
+ <select name="which_fileformat">
+ <option value="png">png</option>
+ <option value="jpg">jpeg</option>
+ <option value="gif">gif</option>
+ <option value="wbmp">bmp</option>
+ </select>
+ </td>
+</tr>
+ <tr><td colspan="2" class="hdr"><input name="submit" type="submit" /></td></tr>
+
+</table>
+</center>
+</form>
+
+<p>
+Please visit <a href="http://phplot.sourceforge.net">PHPlot's site</a>, the
+<a href="http://sourceforge.net/projects/phplot/">sourceforge project page</a>,
+or see <a href="http://www.jeo.net/php/">more php code and examples</a>
+by Afan Ottenheimer of jeonet.
+</p>
+
+<p class="foot">$Id$</p>
+</body>
+</html>
--- /dev/null
+<?php
+/* $Id$ */
+
+if (! isset($_GET['which_title'])) {
+echo <<<EOF
+<pre>
+ *************************************************
+ * This file is meant to be called only from the *
+ * <a href="test_setup.php">test page</a> *
+ * It will fail if called by itself. *
+ *************************************************
+</pre>
+EOF
+;
+exit;
+}
+
+// From PHP 4.?, register_globals is off, take it into account (MBD)
+
+include('../phplot.php');
+$graph = new PHPlot;
+include('./data.php');
+$graph->SetTitle("$_GET[which_title]");
+$graph->SetDataValues($example_data);
+$graph->SetIsInline('1');
+$graph->SetFileFormat("$_GET[which_format]");
+$graph->DrawGraph();
+?>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!-- $Id$ -->
+<html>
+<head>
+ <title>PHPlot graphic formats test</title>
+ <link type="text/css" rel="stylesheet" href="../doc/style.css" />
+</head>
+<body>
+
+<div class="nav"> [ <a href="../doc/index.html">Go to the index</a> ] </div>
+
+<h2>PHPlot test graph form</h2>
+
+<p>Use this form to test many different options of PHPlot. You can test
+every graph type supported for any of four different data types. You can
+tweak as you like or you can leave everything as is and press "Submit" for
+<h2>PHPlot graphic formats test</h2>
+
+<p>
+This page will test which graphic formats are supported by the version of GD
+linked into PHP. You should see at least one of the four images below.
+</p>
+
+<center>
+<table>
+<tr><td class="hdr">PNG graphics</td></tr>
+<tr><td>
+<?php
+ if (! imagetypes() & IMG_PNG )
+ echo "PNG NOT ENABLED";
+ else
+ echo "<img src=\"inline_image.php?which_format=png&which_title=YES_PNG_IS_ENABLED\" />";
+
+?>
+</td></tr>
+<tr><td class="hdr">JPEG graphics</td></tr>
+<tr><td>
+<?php
+ if (! imagetypes() & IMG_JPG )
+ echo "JPEG NOT ENABLED";
+ else
+ echo "<img src=\"inline_image.php?which_format=jpg&which_title=YES_JPG_IS_ENABLED\" />";
+?>
+</td></tr>
+<tr><td class="hdr">GIF graphics</td></tr>
+<tr><td>
+<?php
+ if (! imagetypes() & IMG_GIF)
+ echo "GIF NOT ENABLED";
+ else
+ echo "<img src=\"inline_image.php?which_format=gif&which_title=YES_GIF_IS_ENABLED\" />";
+?>
+</td></tr>
+<tr><td class="hdr">BMP graphics</td></tr>
+<tr><td>
+<?php
+ if (! imagetypes() & IMG_WBMP)
+ echo "BMP NOT ENABLED";
+ else
+ echo "<img src=\"inline_image.php?which_format=wbmp&which_title=YES_WBMP_IS_ENABLED\" />";
+?>
+</td></tr>
+</table>
+</center>
+
+</body>
+</html>
--- /dev/null
+<?php
+
+/* $Id$ */
+
+/*
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Afan Ottenheimer. Released under
+ * the GPL and PHP licenses as stated in the the README file which
+ * should have been included with this document.
+ *
+ * Recent (2003-2004) work by Miguel de Benito Delgado <nonick AT 8027 DOT org>
+ *
+ */
+
+
+// PHPLOT Version 5.0.rc1
+// Requires PHP 4.1.0 or later (CHECK THIS)
+
+if (! defined(__FUNCTION__))
+ define(__FUNCTION__, '__FUNCTION__ Requires at least PHP 4.3.0.');
+
+define ('MINY', -1); // Indexes in $data (for DrawXDataLine())
+define ('MAXY', -2);
+
+error_reporting(E_ALL);
+
+
+class PHPlot {
+
+ /* I have removed internal variable declarations, some isset() checking was required,
+ * but now the variables left are those which can be tweaked by the user. This is intended to
+ * be the first step towards moving most of the Set...() methods into a subclass which will be
+ * used only when strictly necessary. Many users will be able to put default values here in the
+ * class and thus avoid memory overhead and reduce parsing times.
+ */
+ //////////////// CONFIG PARAMETERS //////////////////////
+ var $reduction = 8; // BW Patch
+ var $is_inline = FALSE; // FALSE = Sends headers, TRUE = sends just raw image data
+ var $browser_cache = FALSE; // FALSE = Sends headers for browser to not cache the image,
+ // (only if is_inline = FALSE also)
+
+ var $safe_margin = 5; // Extra margin used in several places. In pixels
+
+ var $x_axis_position = ''; // Where to draw both axis (world coordinates),
+ var $y_axis_position = ''; // leave blank for X axis at 0 and Y axis at left of plot.
+
+ var $xscale_type = 'linear'; // linear, log
+ var $yscale_type = 'linear';
+
+//Fonts
+ var $use_ttf = FALSE; // Use True Type Fonts?
+ var $ttf_path = '.'; // Default path to look in for TT Fonts.
+ var $default_ttfont = 'benjamingothic.ttf';
+ var $line_spacing = 4; // Pixels between lines.
+
+ // Font angles: 0 or 90 degrees for fixed fonts, any for TTF
+ var $x_label_angle = 0; // For labels on X axis (tick and data)
+ var $y_label_angle = 0; // For labels on Y axis (tick and data)
+ var $x_title_angle = 0; // Don't change this if you don't want to screw things up!
+ var $y_title_angle = 90; // Nor this.
+ var $title_angle = 0; // Or this.
+
+//Formats
+ var $file_format = 'png';
+ var $output_file = ''; // For output to a file instead of stdout
+
+//Data
+ var $data_type = 'text-data'; // text-data, data-data-error, data-data, text-data-pie
+ var $plot_type= 'linepoints'; // bars, lines, linepoints, area, points, pie, thinbarline, squared
+
+ var $label_scale_position = 0.5; // Shifts data labes in pie charts. 1 = top, 0 = bottom
+ var $group_frac_width = 0.7; // value from 0 to 1 = width of bar groups
+ var $bar_width_adjust = 1; // 1 = bars of normal width, must be > 0
+
+ var $y_precision = 1;
+ var $x_precision = 1;
+
+ var $data_units_text = ''; // Units text for 'data' labels (i.e: '¤', '$', etc.)
+
+// Titles
+ var $title_txt = '';
+
+ var $x_title_txt = '';
+ var $x_title_pos = 'plotdown'; // plotdown, plotup, both, none
+
+ var $y_title_txt = '';
+ var $y_title_pos = 'plotleft'; // plotleft, plotright, both, none
+
+
+//Labels
+ // There are two types of labels in PHPlot:
+ // Tick labels: they follow the grid, next to ticks in axis. (DONE)
+ // they are drawn at grid drawing time, by _DrawXTicks() and _DrawYTicks()
+ // Data labels: they follow the data points, and can be placed on the axis or the plot (x/y) (TODO)
+ // they are drawn at graph plotting time, by DrawDataLabel(), called by DrawLines(), etc.
+ // Draw*DataLabel() also draws H/V lines to datapoints depending on draw_*_data_label_line
+
+ // Tick Labels
+ var $x_tick_label_pos = 'plotdown'; // plotdown, plotup, both, xaxis, none
+ var $y_tick_label_pos = 'plotleft'; // plotleft, plotright, both, yaxis, none
+
+ // Data Labels:
+ var $x_data_label_pos = 'plotdown'; // plotdown, plotup, both, plot, all, none
+ var $y_data_label_pos = 'plotleft'; // plotleft, plotright, both, plot, all, none
+
+ var $draw_x_data_label_lines = FALSE; // Draw a line from the data point to the axis?
+ var $draw_y_data_label_lines = FALSE; // TODO
+
+ // Label types: (for tick, data and plot labels)
+ var $x_label_type = ''; // data, time. Leave blank for no formatting.
+ var $y_label_type = ''; // data, time. Leave blank for no formatting.
+ var $x_time_format = '%H:%m:%s'; // See http://www.php.net/manual/html/function.strftime.html
+ var $y_time_format = '%H:%m:%s'; // SetYTimeFormat() too...
+
+ // Skipping labels
+ var $x_label_inc = 1; // Draw a label every this many (1 = all) (TODO)
+ var $y_label_inc = 1;
+
+ // Legend
+ var $legend = ''; // An array with legend titles
+ var $legend_x_pos = '';
+ var $legend_y_pos = '';
+
+
+//Ticks
+ var $x_tick_length = 5; // tick length in pixels for upper/lower axis
+ var $y_tick_length = 5; // tick length in pixels for left/right axis
+
+ var $x_tick_cross = 3; // ticks cross x axis this many pixels
+ var $y_tick_cross = 3; // ticks cross y axis this many pixels
+
+ var $x_tick_pos = 'plotdown'; // plotdown, plotup, both, xaxis, none
+ var $y_tick_pos = 'plotleft'; // plotright, plotleft, both, yaxis, none
+
+ var $num_x_ticks = '';
+ var $num_y_ticks = '';
+
+ var $x_tick_increment = ''; // Set num_x_ticks or x_tick_increment, not both.
+ var $y_tick_increment = ''; // Set num_y_ticks or y_tick_increment, not both.
+
+ var $skip_top_tick = FALSE;
+ var $skip_bottom_tick = FALSE;
+ var $skip_left_tick = FALSE;
+ var $skip_right_tick = FALSE;
+
+//Grid Formatting
+ var $draw_x_grid = FALSE;
+ var $draw_y_grid = TRUE;
+
+ var $dashed_grid = TRUE;
+
+//Colors and styles (all colors can be array (R,G,B) or named color)
+ var $color_array = 'small'; // 'small', 'large' or array (define your own colors)
+ // See rgb.inc.php and SetRGBArray()
+ var $i_border = array(194, 194, 194);
+ var $plot_bg_color = 'white';
+ var $bg_color = 'white';
+ var $label_color = 'black';
+ var $text_color = 'black';
+ var $grid_color = 'black';
+ var $light_grid_color = 'gray';
+ var $tick_color = 'black';
+ var $title_color = 'black';
+ var $data_colors = array('SkyBlue', 'green', 'orange', 'blue', 'orange', 'red', 'violet', 'azure1');
+ var $error_bar_colors = array('SkyBlue', 'green', 'orange', 'blue', 'orange', 'red', 'violet', 'azure1');
+ var $data_border_colors = array('black');
+
+ var $line_widths = 1; // single value or array
+ var $line_styles = array('solid', 'solid', 'dashed'); // single value or array
+ var $dashed_style = '2-4'; // colored dots-transparent dots
+
+ var $point_size = 5;
+ var $point_shape = 'diamond'; // rect, circle, diamond, triangle, dot, line, halfline, cross
+
+ var $error_bar_size = 5; // right and left size of tee
+ var $error_bar_shape = 'tee'; // 'tee' or 'line'
+ var $error_bar_line_width = 1; // single value (or array TODO)
+
+ var $plot_border_type = 'sides'; // left, sides, none, full
+ var $image_border_type = 'none'; // 'raised', 'plain', 'none'
+
+ var $shading = 5; // 0 for no shading, > 0 is size of shadows in pixels
+
+ var $draw_plot_area_background = FALSE;
+ var $draw_broken_lines = FALSE; // Tells not to draw lines for missing Y data.
+
+
+//////////////////////////////////////////////////////
+//BEGIN CODE
+//////////////////////////////////////////////////////
+
+ /*!
+ * Constructor: Setup img resource, colors and size of the image, and font sizes.
+ *
+ * \param which_width int Image width in pixels.
+ * \param which_height int Image height in pixels.
+ * \param which_output_file string Filename for output.
+ * \param which_input_fule string Path to a file to be used as background.
+ */
+ function PHPlot($which_width=600, $which_height=400, $which_output_file=NULL, $which_input_file=NULL)
+ {
+ /*
+ * Please see http://www.php.net/register_shutdown_function
+ * PLEASE NOTE: register_shutdown_function() will take a copy of the object rather than a reference
+ * so we put an ampersand. However, the function registered will work on the object as it
+ * was upon registration. To solve this, one of two methods can be used:
+ * $obj = new object();
+ * register_shutdown_function(array(&$obj,'shutdown'));
+ * OR
+ * $obj = &new object();
+ * HOWEVER, as the second statement assigns $obj a reference to the current object, it might be that
+ * several instances mess things up... (CHECK THIS)
+ *
+ * AND
+ * as $this->img is set upon construction of the object, problems will not arise for us (for the
+ * moment maybe, so I put all this here just in case)
+ */
+ register_shutdown_function(array(&$this, '_PHPlot'));
+
+ $this->SetRGBArray($this->color_array);
+
+ $this->background_done = FALSE; // Set to TRUE after background image first drawn
+
+ if ($which_output_file)
+ $this->SetOutputFile($which_output_file);
+
+ if ($which_input_file)
+ $this->SetInputFile($which_input_file);
+ else {
+ $this->image_width = $which_width;
+ $this->image_height = $which_height;
+
+ $this->img = ImageCreate($this->image_width, $this->image_height);
+ if (! $this->img)
+ $this->PrintError('PHPlot(): Could not create image resource.');
+
+ }
+
+ $this->SetDefaultStyles();
+ $this->SetDefaultFonts();
+
+ $this->SetTitle('');
+ $this->SetXTitle('');
+ $this->SetYTitle('');
+
+ $this->print_image = TRUE; // Use for multiple plots per image (TODO: automatic)
+ }
+
+ /*!
+ * Destructor. Image resources not deallocated can be memory hogs, I think
+ * it is safer to automatically call imagedestroy upon script termination than
+ * do it ourselves.
+ * See notes in the constructor code.
+ */
+ function _PHPlot ()
+ {
+ ImageDestroy($this->img);
+ return;
+ }
+
+
+/////////////////////////////////////////////
+////////////// COLORS
+/////////////////////////////////////////////
+
+ /*!
+ * Returns an index to a color passed in as anything (string, hex, rgb)
+ *
+ * \param which_color * Color (can be '#AABBCC', 'Colorname', or array(r,g,b))
+ */
+ function SetIndexColor($which_color)
+ {
+ list ($r, $g, $b) = $this->SetRGBColor($which_color); //Translate to RGB
+ $index = ImageColorExact($this->img, $r, $g, $b);
+ if ($index == -1) {
+ return ImageColorResolve($this->img, $r, $g, $b);
+ } else {
+ return $index;
+ }
+ }
+
+
+ /*!
+ * Returns an index to a slightly darker color than the one requested.
+ */
+ function SetIndexDarkColor($which_color)
+ {
+ list ($r, $g, $b) = $this->SetRGBColor($which_color);
+
+ $r -= 0x30; $r = ($r < 0) ? 0 : $r;
+ $g -= 0x30; $g = ($g < 0) ? 0 : $g;
+ $b -= 0x30; $b = ($b < 0) ? 0 : $b;
+
+ $index = ImageColorExact($this->img, $r, $g, $b);
+ if ($index == -1) {
+ return ImageColorResolve($this->img, $r, $g, $b);
+ } else {
+ return $index;
+ }
+ }
+
+ /*!
+ * Sets/reverts all colors and styles to their defaults. If session is set, then only updates indices,
+ * as they are lost with every script execution, else, sets the default colors by name or value and
+ * then updates indices too.
+ *
+ * FIXME Isn't this too slow?
+ *
+ */
+ function SetDefaultStyles()
+ {
+ /* Some of the Set*() functions use default values when they get no parameters. */
+
+ if (! isset($this->session_set)) {
+ // If sessions are enabled, this variable will be preserved, so upon future executions, we
+ // will have it set, as well as color names (though not color indices, that's why we
+ // need to rebuild them)
+ $this->session_set = TRUE;
+
+ // These only need to be set once
+ $this->SetLineWidths();
+ $this->SetLineStyles();
+ $this->SetDefaultDashedStyle($this->dashed_style);
+ $this->SetPointSize($this->point_size);
+ }
+
+ $this->SetImageBorderColor($this->i_border);
+ $this->SetPlotBgColor($this->plot_bg_color);
+ $this->SetBackgroundColor($this->bg_color);
+ $this->SetLabelColor($this->label_color);
+ $this->SetTextColor($this->text_color);
+ $this->SetGridColor($this->grid_color);
+ $this->SetLightGridColor($this->light_grid_color);
+ $this->SetTickColor($this->tick_color);
+ $this->SetTitleColor($this->title_color);
+ $this->SetDataColors();
+ $this->SetErrorBarColors();
+ $this->SetDataBorderColors();
+ }
+
+
+ /*
+ *
+ */
+ function SetBackgroundColor($which_color)
+ {
+ $this->bg_color= $which_color;
+ $this->ndx_bg_color= $this->SetIndexColor($this->bg_color);
+ return TRUE;
+ }
+
+ /*
+ *
+ */
+ function SetPlotBgColor($which_color)
+ {
+ $this->plot_bg_color= $which_color;
+ $this->ndx_plot_bg_color= $this->SetIndexColor($this->plot_bg_color);
+ return TRUE;
+ }
+
+ /*
+ *
+ */
+ function SetTitleColor($which_color)
+ {
+ $this->title_color= $which_color;
+ $this->ndx_title_color= $this->SetIndexColor($this->title_color);
+ return TRUE;
+ }
+
+ /*
+ *
+ */
+ function SetTickColor ($which_color)
+ {
+ $this->tick_color= $which_color;
+ $this->ndx_tick_color= $this->SetIndexColor($this->tick_color);
+ return TRUE;
+ }
+
+
+ /*
+ *
+ */
+ function SetLabelColor ($which_color)
+ {
+ $this->label_color = $which_color;
+ $this->ndx_title_color= $this->SetIndexColor($this->label_color);
+ return TRUE;
+ }
+
+
+ /*
+ *
+ */
+ function SetTextColor ($which_color)
+ {
+ $this->text_color= $which_color;
+ $this->ndx_text_color= $this->SetIndexColor($this->text_color);
+ return TRUE;
+ }
+
+
+ /*
+ *
+ */
+ function SetLightGridColor ($which_color)
+ {
+ $this->light_grid_color= $which_color;
+ $this->ndx_light_grid_color= $this->SetIndexColor($this->light_grid_color);
+ return TRUE;
+ }
+
+
+ /*
+ *
+ */
+ function SetGridColor ($which_color)
+ {
+ $this->grid_color = $which_color;
+ $this->ndx_grid_color= $this->SetIndexColor($this->grid_color);
+ return TRUE;
+ }
+
+
+ /*
+ *
+ */
+ function SetImageBorderColor($which_color)
+ {
+ $this->i_border = $which_color;
+ $this->ndx_i_border = $this->SetIndexColor($this->i_border);
+ $this->ndx_i_border_dark = $this->SetIndexDarkColor($this->i_border);
+ return TRUE;
+ }
+
+
+ /*
+ *
+ */
+ function SetTransparentColor($which_color)
+ {
+ ImageColorTransparent($this->img, $this->SetIndexColor($which_color));
+ return TRUE;
+ }
+
+
+ /*!
+ * Sets the array of colors to be used. It can be user defined, a small predefined one
+ * or a large one included from 'rgb.inc.php'.
+ *
+ * \param which_color_array If an array, the used as color array. If a string can
+ * be one of 'small' or 'large'.
+ */
+ function SetRGBArray ($which_color_array)
+ {
+ if ( is_array($which_color_array) ) { // User defined array
+ $this->rgb_array = $which_color_array;
+ return TRUE;
+ } elseif ($which_color_array == 'small') { // Small predefined color array
+ $this->rgb_array = array(
+ 'white' => array(255, 255, 255),
+ 'snow' => array(255, 250, 250),
+ 'PeachPuff' => array(255, 218, 185),
+ 'ivory' => array(255, 255, 240),
+ 'lavender' => array(230, 230, 250),
+ 'black' => array( 0, 0, 0),
+ 'DimGrey' => array(105, 105, 105),
+ 'gray' => array(190, 190, 190),
+ 'grey' => array(190, 190, 190),
+ 'navy' => array( 0, 0, 128),
+ 'SlateBlue' => array(106, 90, 205),
+ 'blue' => array( 0, 0, 255),
+ 'SkyBlue' => array(135, 206, 235),
+ 'cyan' => array( 0, 255, 255),
+ 'DarkGreen' => array( 0, 100, 0),
+ 'green' => array( 0, 255, 0),
+ 'YellowGreen' => array(154, 205, 50),
+ 'yellow' => array(255, 255, 0),
+ 'orange' => array(255, 165, 0),
+ 'gold' => array(255, 215, 0),
+ 'peru' => array(205, 133, 63),
+ 'beige' => array(245, 245, 220),
+ 'wheat' => array(245, 222, 179),
+ 'tan' => array(210, 180, 140),
+ 'brown' => array(165, 42, 42),
+ 'salmon' => array(250, 128, 114),
+ 'red' => array(255, 0, 0),
+ 'pink' => array(255, 192, 203),
+ 'maroon' => array(176, 48, 96),
+ 'magenta' => array(255, 0, 255),
+ 'violet' => array(238, 130, 238),
+ 'plum' => array(221, 160, 221),
+ 'orchid' => array(218, 112, 214),
+ 'purple' => array(160, 32, 240),
+ 'azure1' => array(240, 255, 255),
+ 'aquamarine1' => array(127, 255, 212)
+ );
+ return TRUE;
+ } elseif ($which_color_array === 'large') { // Large color array
+ include("./rgb.inc.php");
+ $this->rgb_array = $RGBArray;
+ } else { // Default to black and white only.
+ $this->rgb_array = array('white' => array(255, 255, 255), 'black' => array(0, 0, 0));
+ }
+
+ return TRUE;
+ }
+
+ /*!
+ * Returns an array in R, G, B format 0-255
+ *
+ * \param color_asked array(R,G,B) or string (named color or '#AABBCC')
+ */
+ function SetRGBColor($color_asked)
+ {
+ if ($color_asked == '') { $color_asked = array(0, 0, 0); };
+
+ if ( count($color_asked) == 3 ) { // already array of 3 rgb
+ $ret_val = $color_asked;
+ } else { // asking for a color by string
+ if(substr($color_asked, 0, 1) == '#') { // asking in #FFFFFF format.
+ $ret_val = array(hexdec(substr($color_asked, 1, 2)), hexdec(substr($color_asked, 3, 2)),
+ hexdec(substr($color_asked, 5, 2)));
+ } else { // asking by color name
+ $ret_val = $this->rgb_array[$color_asked];
+ }
+ }
+ return $ret_val;
+ }
+
+
+ /*!
+ * Sets the colors for the data.
+ */
+ function SetDataColors($which_data = NULL, $which_border = NULL)
+ {
+ if (is_null($which_data) && is_array($this->data_colors)) {
+ // use already set data_colors
+ } else if (! is_array($which_data)) {
+ $this->data_colors = ($which_data) ? array($which_data) : array('blue', 'red', 'green', 'orange');
+ } else {
+ $this->data_colors = $which_data;
+ }
+
+ $i = 0;
+ foreach ($this->data_colors as $col) {
+ $this->ndx_data_colors[$i] = $this->SetIndexColor($col);
+ $this->ndx_data_dark_colors[$i] = $this->SetIndexDarkColor($col);
+ $i++;
+ }
+
+ // For past compatibility:
+ $this->SetDataBorderColors($which_border);
+ } // function SetDataColors()
+
+
+ /*!
+ *
+ */
+ function SetDataBorderColors($which_br = NULL)
+ {
+ if (is_null($which_br) && is_array($this->data_border_colors)) {
+ // use already set data_border_colors
+ } else if (! is_array($which_br)) {
+ // Create new array with specified color
+ $this->data_border_colors = ($which_br) ? array($which_br) : array('black');
+ } else {
+ $this->data_border_colors = $which_br;
+ }
+
+ $i = 0;
+ foreach($this->data_border_colors as $col) {
+ $this->ndx_data_border_colors[$i] = $this->SetIndexColor($col);
+ $i++;
+ }
+ } // function SetDataBorderColors()
+
+
+ /*!
+ * Sets the colors for the data error bars.
+ */
+ function SetErrorBarColors($which_err = NULL)
+ {
+ if (is_null($which_err) && is_array($this->error_bar_colors)) {
+ // use already set error_bar_colors
+ } else if (! is_array($which_err)) {
+ $this->error_bar_colors = ($which_err) ? array($which_err) : array('black');
+ } else {
+ $this->error_bar_colors = $which_err;
+ }
+
+ $i = 0;
+ foreach($this->error_bar_colors as $col) {
+ $this->ndx_error_bar_colors[$i] = $this->SetIndexColor($col);
+ $i++;
+ }
+ return TRUE;
+
+ } // function SetErrorBarColors()
+
+
+ /*!
+ * Sets the default dashed style.
+ * \param which_style A string specifying order of colored and transparent dots,
+ * i.e: '4-3' means 4 colored, 3 transparent;
+ * '2-3-1-2' means 2 colored, 3 transparent, 1 colored, 2 transparent.
+ */
+ function SetDefaultDashedStyle($which_style)
+ {
+ // String: "numcol-numtrans-numcol-numtrans..."
+ $asked = explode('-', $which_style);
+
+ if (count($asked) < 2) {
+ $this->DrawError("SetDefaultDashedStyle(): Wrong parameter '$which_style'.");
+ return FALSE;
+ }
+
+ // Build the string to be eval()uated later by SetDashedStyle()
+ $this->default_dashed_style = 'array( ';
+
+ $t = 0;
+ foreach($asked as $s) {
+ if ($t % 2 == 0) {
+ $this->default_dashed_style .= str_repeat('$which_ndxcol,', $s);
+ } else {
+ $this->default_dashed_style .= str_repeat('IMG_COLOR_TRANSPARENT,', $s);
+ }
+ $t++;
+ }
+ // Remove trailing comma and add closing parenthesis
+ $this->default_dashed_style = substr($this->default_dashed_style, 0, -1);
+ $this->default_dashed_style .= ')';
+
+ return TRUE;
+ }
+
+
+ /*!
+ * Sets the style before drawing a dashed line. Defaults to $this->default_dashed_style
+ * \param which_ndxcol Color index to be used.
+ */
+ function SetDashedStyle($which_ndxcol)
+ {
+ // See SetDefaultDashedStyle() to understand this.
+ eval ("\$style = $this->default_dashed_style;");
+ return imagesetstyle($this->img, $style);
+ }
+
+
+ /*!
+ * Sets line widths on a per-line basis.
+ */
+ function SetLineWidths($which_lw=NULL)
+ {
+ if (is_null($which_lw)) {
+ // Do nothing, use default value.
+ } else if (is_array($which_lw)) {
+ // Did we get an array with line widths?
+ $this->line_widths = $which_lw;
+ } else {
+ $this->line_widths = array($which_lw);
+ }
+ return TRUE;
+ }
+
+ /*!
+ *
+ */
+ function SetLineStyles($which_ls=NULL)
+ {
+ if (is_null($which_ls)) {
+ // Do nothing, use default value.
+ } else if (! is_array($which_ls)) {
+ // Did we get an array with line styles?
+ $this->line_styles = $which_ls;
+ } else {
+ $this->line_styles = ($which_ls) ? array($which_ls) : array('solid');
+ }
+ return TRUE;
+ }
+
+
+/////////////////////////////////////////////
+////////////// FONTS
+/////////////////////////////////////////////
+
+
+ /*!
+ * Sets number of pixels between lines of the same text.
+ */
+ function SetLineSpacing($which_spc)
+ {
+ $this->line_spacing = $which_spc;
+ }
+
+
+ /*!
+ * Enables use of TrueType fonts in the graph. Font initialisation methods
+ * depend on this setting, so when called, SetUseTTF() resets the font
+ * settings
+ */
+ function SetUseTTF($which_ttf)
+ {
+ $this->use_ttf = $which_ttf;
+ if ($which_ttf)
+ $this->SetDefaultFonts();
+ return TRUE;
+ }
+
+ /*!
+ * Sets the directory name to look into for TrueType fonts.
+ */
+ function SetTTFPath($which_path)
+ {
+ // Maybe someone needs really dynamic config. He'll need this:
+ // clearstatcache();
+
+ if (is_dir($which_path) && is_readable($which_path)) {
+ $this->ttf_path = $which_path;
+ return TRUE;
+ } else {
+ $this->PrintError("SetTTFPath(): $which_path is not a valid path.");
+ return FALSE;
+ }
+ }
+
+ /*!
+ * Sets the default TrueType font and updates all fonts to that.
+ */
+ function SetDefaultTTFont($which_font)
+ {
+ if (is_file($which_font) && is_readable($which_font)) {
+ $this->default_ttfont = $which_font;
+ return $this->SetDefaultFonts();
+ } else {
+ $this->PrintError("SetDefaultTTFont(): $which_font is not a valid font file.");
+ return FALSE;
+ }
+ }
+
+ /*!
+ * Sets fonts to their defaults
+ */
+ function SetDefaultFonts()
+ {
+ // TTF:
+ if ($this->use_ttf) {
+ //$this->SetTTFPath(dirname($_SERVER['PHP_SELF']));
+ $this->SetTTFPath(getcwd());
+ $this->SetFont('generic', $this->default_ttfont, 8);
+ $this->SetFont('title', $this->default_ttfont, 14);
+ $this->SetFont('legend', $this->default_ttfont, 8);
+ $this->SetFont('x_label', $this->default_ttfont, 6);
+ $this->SetFont('y_label', $this->default_ttfont, 6);
+ $this->SetFont('x_title', $this->default_ttfont, 10);
+ $this->SetFont('y_title', $this->default_ttfont, 10);
+ }
+ // Fixed:
+ else {
+ $this->SetFont('generic', 2);
+ $this->SetFont('title', 5);
+ $this->SetFont('legend', 2);
+ $this->SetFont('x_label', 1);
+ $this->SetFont('y_label', 1);
+ $this->SetFont('x_title', 3);
+ $this->SetFont('y_title', 3);
+ }
+
+ return TRUE;
+ }
+
+ /*!
+ * Sets Fixed/Truetype font parameters.
+ * \param $which_elem Is the element whose font is to be changed.
+ * It can be one of 'title', 'legend', 'generic',
+ * 'x_label', 'y_label', x_title' or 'y_title'
+ * \param $which_font Can be a number (for fixed font sizes) or
+ * a string with the filename when using TTFonts.
+ * \param $which_size Point size (TTF only)
+ * Calculates and updates internal height and width variables.
+ */
+ function SetFont($which_elem, $which_font, $which_size = 12)
+ {
+ // TTF:
+ if ($this->use_ttf) {
+ $path = $this->ttf_path.'/'.$which_font;
+
+ if (! is_file($path) || ! is_readable($path) ) {
+ $this->DrawError("SetFont(): True Type font $path doesn't exist");
+ return FALSE;
+ }
+
+ switch ($which_elem) {
+ case 'generic':
+ $this->generic_font['font'] = $path;
+ $this->generic_font['size'] = $which_size;
+ break;
+ case 'title':
+ $this->title_font['font'] = $path;
+ $this->title_font['size'] = $which_size;
+ break;
+ case 'legend':
+ $this->legend_font['font'] = $path;
+ $this->legend_font['size'] = $which_size;
+ break;
+ case 'x_label':
+ $this->x_label_font['font'] = $path;
+ $this->x_label_font['size'] = $which_size;
+ break;
+ case 'y_label':
+ $this->y_label_font['font'] = $path;
+ $this->y_label_font['size'] = $which_size;
+ break;
+ case 'x_title':
+ $this->x_title_font['font'] = $path;
+ $this->x_title_font['size'] = $which_size;
+ break;
+ case 'y_title':
+ $this->y_title_font['font'] = $path;
+ $this->y_title_font['size'] = $which_size;
+ break;
+ default:
+ $this->DrawError("SetFont(): Unknown element '$which_elem' specified.");
+ return FALSE;
+ }
+ return TRUE;
+
+ }
+
+ // Fixed fonts:
+ if ($which_font > 5 || $which_font < 0) {
+ $this->DrawError('SetFont(): Non-TTF font size must be 1, 2, 3, 4 or 5');
+ return FALSE;
+ }
+
+ switch ($which_elem) {
+ case 'generic':
+ $this->generic_font['font'] = $which_font;
+ $this->generic_font['height'] = ImageFontHeight($which_font);
+ $this->generic_font['width'] = ImageFontWidth($which_font);
+ break;
+ case 'title':
+ $this->title_font['font'] = $which_font;
+ $this->title_font['height'] = ImageFontHeight($which_font);
+ $this->title_font['width'] = ImageFontWidth($which_font);
+ break;
+ case 'legend':
+ $this->legend_font['font'] = $which_font;
+ $this->legend_font['height'] = ImageFontHeight($which_font)-$this->reduction; // BW Patch
+ $this->legend_font['width'] = ImageFontWidth($which_font);
+ break;
+ case 'x_label':
+ $this->x_label_font['font'] = $which_font;
+ $this->x_label_font['height'] = ImageFontHeight($which_font);
+ $this->x_label_font['width'] = ImageFontWidth($which_font);
+ break;
+ case 'y_label':
+ $this->y_label_font['font'] = $which_font;
+ $this->y_label_font['height'] = ImageFontHeight($which_font);
+ $this->y_label_font['width'] = ImageFontWidth($which_font);
+ break;
+ case 'x_title':
+ $this->x_title_font['font'] = $which_font;
+ $this->x_title_font['height'] = ImageFontHeight($which_font);
+ $this->x_title_font['width'] = ImageFontWidth($which_font);
+ break;
+ case 'y_title':
+ $this->y_title_font['font'] = $which_font;
+ $this->y_title_font['height'] = ImageFontHeight($which_font);
+ $this->y_title_font['width'] = ImageFontWidth($which_font);
+ break;
+ default:
+ $this->DrawError("SetFont(): Unknown element '$which_elem' specified.");
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+
+ /*!
+ * Returns an array with the size of the bounding box of an
+ * arbitrarily placed (rotated) TrueType text string.
+ */
+ function TTFBBoxSize($size, $angle, $font, $string)
+ {
+ // First, assume angle < 90
+ $arr = ImageTTFBBox($size, 0, $font, $string);
+ $flat_width = $arr[2] - $arr[0];
+ $flat_height = abs($arr[3] - $arr[5]);
+
+ // Now the bounding box
+ $angle = deg2rad($angle);
+ $width = ceil(abs($flat_width*cos($angle) + $flat_height*sin($angle))); //Must be integer
+ $height = ceil(abs($flat_width*sin($angle) + $flat_height*cos($angle))); //Must be integer
+
+ return array($width, $height);
+ }
+
+
+ /*!
+ * Draws a string of text. Horizontal and vertical alignment are relative to
+ * to the drawing. That is: vertical text (90 deg) gets centered along y-axis
+ * with v_align = 'center', and adjusted to the left of x-axis with h_align = 'right',
+ *
+ * \note Original multiple lines code submitted by Remi Ricard.
+ * \note Original vertical code submitted by Marlin Viss.
+ */
+ function DrawText($which_font, $which_angle, $which_xpos, $which_ypos, $which_color, $which_text,
+ $which_halign = 'left', $which_valign = 'bottom')
+ {
+ // TTF:
+ if ($this->use_ttf) {
+ $size = $this->TTFBBoxSize($which_font['size'], $which_angle, $which_font['font'], $which_text);
+ $rads = deg2rad($which_angle);
+
+ if ($which_valign == 'center')
+ $which_ypos += $size[1]/2;
+
+ if ($which_valign == 'bottom')
+ $which_ypos += $size[1];
+
+ if ($which_halign == 'center')
+ $which_xpos -= ($size[0]/2) * cos($rads);
+
+ if ($which_halign == 'left')
+ $which_xpos += $size[0] * sin($rads);
+
+ if ($which_halign == 'right')
+ $which_xpos -= $size[0] * cos($rads);
+
+ ImageTTFText($this->img, $which_font['size'], $which_angle,
+ $which_xpos, $which_ypos, $which_color, $which_font['font'], $which_text);
+ }
+ // Fixed fonts:
+ else {
+ // Split the text by its lines, and count them
+ $which_text = ereg_replace("\r", "", $which_text);
+ $str = split("\n", $which_text);
+ $nlines = count($str);
+ $spacing = $this->line_spacing * ($nlines - 1);
+
+ // Vertical text:
+ // (Remember the alignment convention with vertical text)
+ if ($which_angle == 90) {
+ // The text goes around $which_xpos.
+ if ($which_halign == 'center')
+ $which_xpos -= ($nlines * ($which_font['height'] + $spacing))/2;
+
+ // Left alignment requires no modification to $xpos...
+ // Right-align it. $which_xpos designated the rightmost x coordinate.
+ else if ($which_halign == 'right')
+ $which_xpos += ($nlines * ($which_font['height'] + $spacing));
+
+ $ypos = $which_ypos;
+ for($i = 0; $i < $nlines; $i++) {
+ // Center the text vertically around $which_ypos (each line)
+ if ($which_valign == 'center')
+ $ypos = $which_ypos + (strlen($str[$i]) * $which_font['width']) / 2;
+ // Make the text finish (vertically) at $which_ypos
+ if ($which_valign == 'bottom')
+ $ypos = $which_ypos + strlen($str[$i]) * $which_font['width'];
+
+ ImageStringUp($this->img, $which_font['font'],
+ $i * ($which_font['height'] + $spacing) + $which_xpos,
+ $ypos, $str[$i], $which_color);
+ }
+ }
+ // Horizontal text:
+ else {
+ // The text goes above $which_ypos
+ if ($which_valign == 'top')
+ $which_ypos -= $nlines * ($which_font['height'] + $spacing);
+ // The text is centered around $which_ypos
+ if ($which_valign == 'center')
+ $which_ypos -= ($nlines * ($which_font['height'] + $spacing))/2;
+ // valign = 'bottom' requires no modification
+
+ $xpos = $which_xpos;
+ for($i = 0; $i < $nlines; $i++) {
+ // center the text around $which_xpos
+ if ($which_halign == 'center')
+ $xpos = $which_xpos - (strlen($str[$i]) * $which_font['width'])/2;
+ // make the text finish at $which_xpos
+ if ($which_halign == 'right')
+ $xpos = $which_xpos - strlen($str[$i]) * $which_font['width'];
+
+ ImageString($this->img, $which_font['font'], $xpos,
+ $i * ($which_font['height'] + $spacing) + $which_ypos,
+ $str[$i], $which_color);
+ }
+ }
+ }
+ return TRUE;
+ } // function DrawText()
+
+
+/////////////////////////////////////////////
+/////////// INPUT / OUTPUT CONTROL
+/////////////////////////////////////////////
+
+ /*!
+ * Sets output format.
+ * inline condition, cacheable, etc.
+ */
+ function SetFileFormat($which_file_format)
+ {
+ // I know rewriting this was unnecessary, but it didn't work for me, I don't
+ // understand why.
+ $asked = strtolower($which_file_format);
+ switch ($asked) {
+ case 'jpg':
+ if (imagetypes() & IMG_JPG)
+ return TRUE;
+ break;
+ case 'png':
+ if (imagetypes() & IMG_PNG)
+ return TRUE;
+ break;
+ case 'gif':
+ if (imagetypes() & IMG_GIF)
+ return TRUE;
+ break;
+ case 'wbmp':
+ if (imagetypes() & IMG_WBMP)
+ return TRUE;
+ break;
+ default:
+ $this->PrintError("SetFileFormat(): Unrecognized option '$which_file_format'");
+ return FALSE;
+ }
+ $this->PrintError("SetFileFormat():File format '$which_file_format' not supported");
+ return FALSE;
+ }
+
+
+ /*!
+ * Selects an input file to be used as background for the whole graph.
+ */
+ function SetInputFile($which_input_file)
+ {
+ $size = GetImageSize($which_input_file);
+ $input_type = $size[2];
+
+ switch($input_type) {
+ case 1:
+ $im = @ImageCreateFromGIF ($which_input_file);
+ if (!$im) { // See if it failed
+ $this->PrintError("Unable to open $which_input_file as a GIF");
+ return FALSE;
+ }
+ break;
+ case 3:
+ $im = @ImageCreateFromPNG ($which_input_file);
+ if (!$im) { // See if it failed
+ $this->PrintError("Unable to open $which_input_file as a PNG");
+ return FALSE;
+ }
+ break;
+ case 2:
+ $im = @ImageCreateFromJPEG ($which_input_file);
+ if (!$im) { // See if it failed
+ $this->PrintError("Unable to open $which_input_file as a JPG");
+ return FALSE;
+ }
+ break;
+ default:
+ $this->PrintError('SetInputFile(): Please select gif, jpg, or png for image type!');
+ return FALSE;
+ break;
+ }
+
+ // Set Width and Height of Image
+ $this->image_width = $size[0];
+ $this->image_height = $size[1];
+
+ // Deallocate any resources previously allocated
+ if ($this->img)
+ imagedestroy($this->img);
+
+ $this->img = $im;
+
+ return TRUE;
+
+ }
+
+ function SetOutputFile($which_output_file)
+ {
+ $this->output_file = $which_output_file;
+ return TRUE;
+ }
+
+ /*!
+ * Sets the output image as 'inline', ie. no Content-Type headers are sent
+ * to the browser. Very useful if you want to embed the images.
+ */
+ function SetIsInline($which_ii)
+ {
+ $this->is_inline = $which_ii;
+ return TRUE;
+ }
+
+
+ /*!
+ * Performs the actual outputting of the generated graph, and
+ * destroys the image resource.
+ */
+ function PrintImage()
+ {
+ // Browser cache stuff submitted by Thiemo Nagel
+ if ( (! $this->browser_cache) && (! $this->is_inline)) {
+ header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
+ header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT');
+ header('Cache-Control: no-cache, must-revalidate');
+ header('Pragma: no-cache');
+ }
+
+ switch($this->file_format) {
+ case 'png':
+ if (! $this->is_inline) {
+ Header('Content-type: image/png');
+ }
+ if ($this->is_inline && $this->output_file != '') {
+ ImagePng($this->img, $this->output_file);
+ } else {
+ ImagePng($this->img);
+ }
+ break;
+ case 'jpg':
+ if (! $this->is_inline) {
+ Header('Content-type: image/jpeg');
+ }
+ if ($this->is_inline && $this->output_file != '') {
+ ImageJPEG($this->img, $this->output_file);
+ } else {
+ ImageJPEG($this->img);
+ }
+ break;
+ case 'gif':
+ if (! $this->is_inline) {
+ Header('Content-type: image/gif');
+ }
+ if ($this->is_inline && $this->output_file != '') {
+ ImageGIF($this->img, $this->output_file);
+ } else {
+ ImageGIF($this->img);
+ }
+
+ break;
+ case 'wbmp': // wireless bitmap, 2 bit.
+ if (! $this->is_inline) {
+ Header('Content-type: image/wbmp');
+ }
+ if ($this->is_inline && $this->output_file != '') {
+ ImageWBMP($this->img, $this->output_file);
+ } else {
+ ImageWBMP($this->img);
+ }
+
+ break;
+ default:
+ $this->PrintError('PrintImage(): Please select an image type!');
+ break;
+ }
+ return TRUE;
+ }
+
+ /*!
+ * Prints an error message to stdout and dies
+ */
+ function PrintError($error_message)
+ {
+ echo "<p><b>Fatal error</b>: $error_message<p>";
+ die;
+ }
+
+ /*!
+ * Prints an error message inline into the generated image and draws it centered
+ * around the given coordinates (defaults to center of the image)
+ * \param error_message Message to be drawn
+ * \param where_x X coordinate
+ * \param where_y Y coordinate
+ */
+ function DrawError($error_message, $where_x = NULL, $where_y = NULL)
+ {
+ if (! $this->img)
+ $this->PrintError('_DrawError(): Warning, no image resource allocated. '.
+ 'The message to be written was: '.$error_message);
+
+ $ypos = (! $where_y) ? $this->image_height/2 : $where_y;
+ $xpos = (! $where_x) ? $this->image_width/2 : $where_x;
+ ImageRectangle($this->img, 0, 0, $this->image_width, $this->image_height,
+ ImageColorAllocate($this->img, 255, 255, 255));
+
+ $this->DrawText($this->generic_font, 0, $xpos, $ypos, ImageColorAllocate($this->img, 0, 0, 0),
+ $error_message, 'center', 'center');
+
+ $this->PrintImage();
+ exit;
+// return TRUE;
+ }
+
+/////////////////////////////////////////////
+/////////// LABELS
+/////////////////////////////////////////////
+
+
+ /*!
+ * Sets position for X labels following data points.
+ */
+ function SetXDataLabelPos($which_xdlp)
+ {
+ $this->x_data_label_pos = $this->CheckOption($which_xdlp, 'plotdown, plotup, both, xaxis, all, none',
+ __FUNCTION__);
+ if ($which_xdlp != 'none')
+ $this->x_tick_label_pos == 'none';
+
+ return TRUE;
+ }
+
+ /*!
+ * Sets position for Y labels following data points.
+ */
+ function SetYDataLabelPos($which_ydlp)
+ {
+ $this->y_data_label_pos = $this->CheckOption($which_ydlp, 'plotleft, plotright, both, yaxis, all, none',
+ __FUNCTION__);
+ if ($which_ydlp != 'none')
+ $this->y_tick_label_pos == 'none';
+
+ return TRUE;
+ }
+
+
+ /*!
+ * Sets position for X labels following ticks (hence grid lines)
+ */
+ function SetXTickLabelPos($which_xtlp)
+ {
+ $this->x_tick_label_pos = $this->CheckOption($which_xtlp, 'plotdown, plotup, both, xaxis, all, none',
+ __FUNCTION__);
+ if ($which_xtlp != 'none')
+ $this->x_data_label_pos == 'none';
+
+ return TRUE;
+ }
+
+ /*!
+ * Sets position for Y labels following ticks (hence grid lines)
+ */
+ function SetYTickLabelPos($which_ytlp)
+ {
+ $this->y_tick_label_pos = $this->CheckOption($which_ytlp, 'plotleft, plotright, both, yaxis, all, none',
+ __FUNCTION__);
+ if ($which_ytlp != 'none')
+ $this->y_data_label_pos == 'none';
+
+ return TRUE;
+ }
+
+ /*!
+ * Sets type for tick and data labels on X axis.
+ * \note 'title' type left for backwards compatibility.
+ */
+ function SetXLabelType($which_xlt)
+ {
+ $this->x_label_type = $this->CheckOption($which_xlt, 'data, time, title', __FUNCTION__);
+ return TRUE;
+ }
+
+ /*!
+ * Sets type for tick and data labels on Y axis.
+ */
+ function SetYLabelType($which_ylt)
+ {
+ $this->y_label_type = $this->CheckOption($which_ylt, 'data, time', __FUNCTION__);
+ return TRUE;
+ }
+
+ function SetXTimeFormat($which_xtf)
+ {
+ $this->x_time_format = $which_xtf;
+ return TRUE;
+ }
+ function SetYTimeFormat($which_ytf)
+ {
+ $this->y_time_format = $which_ytf;
+ return TRUE;
+ }
+
+ function SetXLabelAngle($which_xla)
+ {
+ $this->x_label_angle = $which_xla;
+ return TRUE;
+ }
+
+ function SetYLabelAngle($which_yla)
+ {
+ $this->y_label_angle = $which_yla;
+ return TRUE;
+ }
+
+/////////////////////////////////////////////
+/////////// MISC
+/////////////////////////////////////////////
+
+ /*!
+ * ON THE WORKS: XXX XXX XXX XXX
+ *
+ ***************** __FUNCTION__ needs PHP 4.3.0
+ *
+ * Checks the valididy of an option.
+ * \param which_opt String to check.
+ * \param which_acc String of accepted choices.
+ * \param which_func Name of the calling function, for error messages.
+ * \note If checking everywhere for correctness slows things down, we could provide a
+ * child class overriding every Set...() method which uses CheckOption(). Those new
+ * methods could proceed in the unsafe but faster way.
+ */
+ function CheckOption($which_opt, $which_acc, $which_func)
+ {
+ $asked = trim($which_opt);
+
+ // FIXME: this for backward compatibility, as eregi() fails with empty strings.
+ if ($asked == '')
+ return '';
+
+ if (@ eregi($asked, $which_acc)) {
+ return $asked;
+ } else {
+ $this->DrawError("$which_func(): '$which_opt' not in available choices: '$which_acc'.");
+ return NULL;
+ }
+ }
+
+
+ /*!
+ * \note Submitted by Thiemo Nagel
+ */
+ function SetBrowserCache($which_browser_cache)
+ {
+ $this->browser_cache = $which_browser_cache;
+ return TRUE;
+ }
+
+ /*!
+ * Whether to show the final image or not
+ */
+ function SetPrintImage($which_pi)
+ {
+ $this->print_image = $which_pi;
+ return TRUE;
+ }
+
+ /*!
+ * Sets the graph's legend. If argument is not an array, appends it to the legend.
+ */
+ function SetLegend($which_leg)
+ {
+ if (is_array($which_leg)) { // use array
+ $this->legend = $which_leg;
+ return TRUE;
+ } else if (! is_null($which_leg)) { // append string
+ $this->legend[] = $which_leg;
+ return TRUE;
+ } else {
+ $this->DrawError("SetLegend(): argument must not be null.");
+ return FALSE;
+ }
+ }
+
+ /*!
+ * Specifies the absolute (relative to image's up/left corner) position
+ * of the legend's upper/leftmost corner.
+ * $which_type not yet used (TODO)
+ */
+ function SetLegendPixels($which_x, $which_y, $which_type=NULL)
+ {
+ $this->legend_x_pos = $which_x;
+ $this->legend_y_pos = $which_y;
+
+ return TRUE;
+ }
+
+ /*!
+ * Specifies the relative (to graph's origin) position of the legend's
+ * upper/leftmost corner. MUST be called after scales are set up.
+ * $which_type not yet used (TODO)
+ */
+ function SetLegendWorld($which_x, $which_y, $which_type=NULL)
+ {
+ if (! $this->scale_is_set)
+ $this->CalcTranslation();
+
+ $this->legend_x_pos = $this->xtr($which_x);
+ $this->legend_y_pos = $this->ytr($which_y);
+
+ return TRUE;
+ }
+
+ /*!
+ * Accepted values are: left, sides, none, full
+ */
+ function SetPlotBorderType($pbt)
+ {
+ $this->plot_border_type = $this->CheckOption($pbt, 'left, sides, none, full', __FUNCTION__);
+ }
+
+ /*!
+ * Accepted values are: raised, plain
+ */
+ function SetImageBorderType($sibt)
+ {
+ $this->image_border_type = $this->CheckOption($sibt, 'raised, plain', __FUNCTION__);
+ }
+
+
+ /*!
+ * \param dpab bool
+ */
+ function SetDrawPlotAreaBackground($dpab)
+ {
+ $this->draw_plot_area_background = (bool)$dpab;
+ }
+
+
+ /*!
+ * \param dyg bool
+ */
+ function SetDrawYGrid($dyg)
+ {
+ $this->draw_y_grid = (bool)$dyg;
+ return TRUE;
+ }
+
+
+ /*!
+ * \param dxg bool
+ */
+ function SetDrawXGrid($dxg)
+ {
+ $this->draw_x_grid = (bool)$dxg;
+ return TRUE;
+ }
+
+
+ /*!
+ * \param ddg bool
+ */
+ function SetDrawDashedGrid($ddg)
+ {
+ $this->dashed_grid = (bool)$ddg;
+ return TRUE;
+ }
+
+
+ /*!
+ * \param dxdl bool
+ */
+ function SetDrawXDataLabelLines($dxdl)
+ {
+ $this->draw_x_data_label_lines = (bool)$dxdl;
+ return TRUE;
+ }
+
+
+ /*!
+ * TODO: draw_y_data_label_lines not implemented.
+ * \param dydl bool
+ */
+ function SetDrawYDataLabelLines($dydl)
+ {
+ $this->draw_y_data_label_lines = $dydl;
+ return TRUE;
+ }
+ /*!
+ * Sets the graph's title.
+ */
+ function SetTitle($which_title)
+ {
+ $this->title_txt = $which_title;
+
+ if ($which_title == '') {
+ $this->title_height = 0;
+ return TRUE;
+ }
+
+ $str = split("\n", $which_title);
+ $lines = count($str);
+ $spacing = $this->line_spacing * ($lines - 1);
+
+ if ($this->use_ttf) {
+ $size = $this->TTFBBoxSize($this->title_font['size'], 0, $this->title_font['font'], $which_title);
+ $this->title_height = $size[1] * $lines;
+ } else {
+ $this->title_height = ($this->title_font['height'] + $spacing) * $lines;
+ }
+ return TRUE;
+ }
+
+ /*!
+ * Sets the X axis title and position.
+ */
+ function SetXTitle($which_xtitle, $which_xpos = 'plotdown')
+ {
+ if ($which_xtitle == '')
+ $which_xpos = 'none';
+
+ $this->x_title_pos = $this->CheckOption($which_xpos, 'plotdown, plotup, both, none', __FUNCTION__);
+
+ $this->x_title_txt = $which_xtitle;
+
+ $str = split("\n", $which_xtitle);
+ $lines = count($str);
+ $spacing = $this->line_spacing * ($lines - 1);
+
+ if ($this->use_ttf) {
+ $size = $this->TTFBBoxSize($this->x_title_font['size'], 0, $this->x_title_font['font'], $which_xtitle);
+ $this->x_title_height = $size[1] * $lines;
+ } else {
+ $this->x_title_height = ($this->y_title_font['height'] + $spacing) * $lines;
+ }
+
+ return TRUE;
+ }
+
+
+ /*!
+ * Sets the Y axis title and position.
+ */
+ function SetYTitle($which_ytitle, $which_ypos = 'plotleft')
+ {
+ if ($which_ytitle == '')
+ $which_ypos = 'none';
+
+ $this->y_title_pos = $this->CheckOption($which_ypos, 'plotleft, plotright, both, none', __FUNCTION__);
+
+ $this->y_title_txt = $which_ytitle;
+
+ $str = split("\n", $which_ytitle);
+ $lines = count($str);
+ $spacing = $this->line_spacing * ($lines - 1);
+
+ if ($this->use_ttf) {
+ $size = $this->TTFBBoxSize($this->y_title_font['size'], 90, $this->y_title_font['font'],
+ $which_ytitle);
+ $this->y_title_width = $size[0] * $lines;
+ } else {
+ $this->y_title_width = ($this->y_title_font['height'] + $spacing) * $lines;
+ }
+
+ return TRUE;
+ }
+
+ /*!
+ * Sets the size of the drop shadow for bar and pie charts.
+ * \param which_s int Size in pixels.
+ */
+ function SetShading($which_s)
+ {
+ $this->shading = (int)$which_s;
+ return TRUE;
+ }
+
+ function SetPlotType($which_pt)
+ {
+ $this->plot_type = $this->CheckOption($which_pt,
+ 'bars, lines, linepoints, area, points, pie, thinbarline, squared',
+ __FUNCTION__);
+ }
+
+ /*!
+ * Sets the position of Y axis.
+ * \param pos int Position in world coordinates.
+ */
+ function SetYAxisPosition($pos)
+ {
+ $this->y_axis_position = (int)$pos;
+ if (isset($this->scale_is_set)) {
+ $this->CalcTranslation();
+ }
+ return TRUE;
+ }
+
+ /*!
+ * Sets the position of X axis.
+ * \param pos int Position in world coordinates.
+ */
+ function SetXAxisPosition($pos)
+ {
+ $this->x_axis_position = (int)$pos;
+ if (isset($this->scale_is_set)) {
+ $this->CalcTranslation();
+ }
+ return TRUE;
+ }
+
+
+ function SetXScaleType($which_xst)
+ {
+ $this->xscale_type = $this->CheckOption($which_xst, 'linear, log', __FUNCTION__);
+ return TRUE;
+ }
+
+ function SetYScaleType($which_yst)
+ {
+ $this->yscale_type = $this->CheckOption($which_yst, 'linear, log', __FUNCTION__);
+ return TRUE;
+ }
+
+ function SetPrecisionX($which_prec)
+ {
+ $this->x_precision = $which_prec;
+ return TRUE;
+ }
+ function SetPrecisionY($which_prec)
+ {
+ $this->y_precision = $which_prec;
+ return TRUE;
+ }
+
+ function SetErrorBarLineWidth($which_seblw)
+ {
+ $this->error_bar_line_width = $which_seblw;
+ return TRUE;
+ }
+
+ function SetLabelScalePosition($which_blp)
+ {
+ //0 to 1
+ $this->label_scale_position = $which_blp;
+ return TRUE;
+ }
+
+ function SetErrorBarSize($which_ebs)
+ {
+ //in pixels
+ $this->error_bar_size = $which_ebs;
+ return TRUE;
+ }
+
+ /*!
+ * Can be one of: 'tee', 'line'
+ */
+ function SetErrorBarShape($which_ebs)
+ {
+ $this->error_bar_shape = $this->CheckOption($which_ebs, 'tee, line', __FUNCTION__);
+ }
+
+ /*!
+ * Can be one of: 'halfline', 'line', 'plus', 'cross', 'rect', 'circle', 'dot',
+ * 'diamond', 'triangle', 'trianglemid'
+ */
+ function SetPointShape($which_pt)
+ {
+ $this->point_shape = $this->CheckOption($which_pt,
+ 'halfline, line, plus, cross, rect, circle, dot, diamond, triangle, trianglemid',
+ __FUNCTION__);
+ }
+
+ /*!
+ * Sets the point size for point plots.
+ * \param ps int Size in pixels.
+ */
+ function SetPointSize($ps)
+ {
+ $this->point_size = (int)$ps;
+
+ if ($this->point_shape == 'diamond' or $this->point_shape == 'triangle') {
+ if ($this->point_size % 2 != 0) {
+ $this->point_size++;
+ }
+ }
+ return TRUE;
+ }
+
+
+ /*!
+ * Tells not to draw lines for missing Y data. Only works with 'lines' and 'squared' plots.
+ * \param bl bool
+ */
+ function SetDrawBrokenLines($bl)
+ {
+ $this->draw_broken_lines = (bool)$bl;
+ }
+
+
+ /*!
+ * text-data: ('label', y1, y2, y3, ...)
+ * text-data-pie: ('label', y1), for pie charts. See DrawPieChart()
+ * data-data: ('label', x, y1, y2, y3, ...)
+ * data-data-error: ('label', x1, y1, e1+, e2-, y2, e2+, e2-, y3, e3+, e3-, ...)
+ */
+ function SetDataType($which_dt)
+ {
+ //The next three lines are for past compatibility.
+ if ($which_dt == 'text-linear') { $which_dt = 'text-data'; };
+ if ($which_dt == 'linear-linear') { $which_dt = 'data-data'; };
+ if ($which_dt == 'linear-linear-error') { $which_dt = 'data-data-error'; };
+
+ $this->data_type = $this->CheckOption($which_dt, 'text-data, text-data-pie, data-data, data-data-error',
+ __FUNCTION__);
+ return TRUE;
+ }
+
+ /*!
+ * Copy the array passed as data values. We convert to numerical indexes, for its
+ * use for (or while) loops, which sometimes are faster. Performance improvements
+ * vary from 28% in DrawLines() to 49% in DrawArea() for plot drawing functions.
+ */
+ function SetDataValues(&$which_dv)
+ {
+ $this->num_data_rows = count($which_dv);
+ $this->total_records = 0; // Perform some useful calculations.
+ $this->records_per_group = 1;
+ for ($i = 0, $recs = 0; $i < $this->num_data_rows; $i++) {
+ // Copy
+ $this->data[$i] = array_values($which_dv[$i]); // convert to numerical indices.
+
+ // Compute some values
+ $recs = count($this->data[$i]);
+ $this->total_records += $recs;
+
+ if ($recs > $this->records_per_group)
+ $this->records_per_group = $recs;
+
+ $this->num_recs[$i] = $recs;
+ }
+ }
+
+ /*!
+ * Pad styles arrays for later use by plot drawing functions:
+ * This removes the need for $max_data_colors, etc. and $color_index = $color_index % $max_data_colors
+ * in DrawBars(), DrawLines(), etc.
+ */
+ function PadArrays()
+ {
+ array_pad_array($this->line_widths, $this->records_per_group);
+ array_pad_array($this->line_styles, $this->records_per_group);
+
+ array_pad_array($this->data_colors, $this->records_per_group);
+ array_pad_array($this->data_border_colors, $this->records_per_group);
+ array_pad_array($this->error_bar_colors, $this->records_per_group);
+
+ $this->SetDataColors();
+ $this->SetDataBorderColors();
+ $this->SetErrorBarColors();
+
+ return TRUE;
+ }
+
+
+//////////////////////////////////////////////////////////
+/////////// DATA ANALYSIS, SCALING AND TRANSLATION
+//////////////////////////////////////////////////////////
+
+ /*!
+ * Analizes data and sets up internal maxima and minima
+ * Needed by: CalcMargins(), ...
+ * Text-Data is different than data-data graphs. For them what
+ * we have, instead of X values, is # of records equally spaced on data.
+ * text-data is passed in as $data[] = (title, y1, y2, y3, y4, ...)
+ * data-data is passed in as $data[] = (title, x, y1, y2, y3, y4, ...)
+ */
+ function FindDataLimits()
+ {
+ // Set some default min and max values before running through the data
+ switch ($this->data_type) {
+ case 'text-data':
+ $minx = 0;
+ $maxx = $this->num_data_rows - 1 ;
+ $miny = $this->data[0][1];
+ $maxy = $miny;
+ break;
+ default: //Everything else: data-data, etc, take first value
+ $minx = $this->data[0][1];
+ $maxx = $minx;
+ $miny = $this->data[0][2];
+ $maxy = $miny;
+ break;
+ }
+
+ $mine = 0; // Maximum value for the -error bar (assume error bars always > 0)
+ $maxe = 0; // Maximum value for the +error bar (assume error bars always > 0)
+ $maxt = 0; // Maximum number of characters in text labels
+
+ $minminy = $miny;
+ $maxmaxy = $maxy;
+ // Process each row of data
+ for ($i=0; $i < $this->num_data_rows; $i++) {
+ $j=0;
+ // Extract maximum text label length
+ $val = @ strlen($this->data[$i][$j++]);
+ $maxt = ($val > $maxt) ? $val : $maxt;
+
+ switch ($this->data_type) {
+ case 'text-data': // Data is passed in as (title, y1, y2, y3, ...)
+ case 'text-data-pie': // This one is for some pie charts, see DrawPieChart()
+ // $numrecs = @ count($this->data[$i]);
+ $miny = $maxy = (double)$this->data[$i][$j];
+ for (; $j < $this->num_recs[$i]; $j++) {
+ $val = (double)$this->data[$i][$j];
+ $maxy = ($val > $maxy) ? $val : $maxy;
+ $miny = ($val < $miny) ? $val : $miny;
+ }
+ break;
+ case 'data-data': // Data is passed in as (title, x, y, y2, y3, ...)
+ // X value:
+ $val = (double)$this->data[$i][$j++];
+ $maxx = ($val > $maxx) ? $val : $maxx;
+ $minx = ($val < $minx) ? $val : $minx;
+
+ $miny = $maxy = (double)$this->data[$i][$j];
+ // $numrecs = @ count($this->data[$i]);
+ for (; $j < $this->num_recs[$i]; $j++) {
+ $val = (double)$this->data[$i][$j];
+ $maxy = ($val > $maxy) ? $val : $maxy;
+ $miny = ($val < $miny) ? $val : $miny;
+ }
+ break;
+ case 'data-data-error': // Data is passed in as (title, x, y, err+, err-, y2, err2+, err2-,...)
+ // X value:
+ $val = (double)$this->data[$i][$j++];
+ $maxx = ($val > $maxx) ? $val : $maxx;
+ $minx = ($val < $minx) ? $val : $minx;
+
+ $miny = $maxy = (double)$this->data[$i][$j];
+ // $numrecs = @ count($this->data[$i]);
+ for (; $j < $this->num_recs[$i];) {
+ // Y value:
+ $val = (double)$this->data[$i][$j++];
+ $maxy = ($val > $maxy) ? $val : $maxy;
+ $miny = ($val < $miny) ? $val : $miny;
+ // Error +:
+ $val = (double)$this->data[$i][$j++];
+ $maxe = ($val > $maxe) ? $val : $maxe;
+ // Error -:
+ $val = (double)$this->data[$i][$j++];
+ $mine = ($val > $mine) ? $val : $mine;
+ }
+ $maxy = $maxy + $maxe;
+ $miny = $miny - $mine; // assume error bars are always > 0
+ break;
+ default:
+ $this->PrintError("FindDataLimits(): Unknown data type '$data_type'.");
+ break;
+ }
+ $this->data[$i][MINY] = $miny; // This row's min Y, for DrawXDataLine()
+ $this->data[$i][MAXY] = $maxy; // This row's max Y, for DrawXDataLine()
+ $minminy = ($miny < $minminy) ? $miny : $minminy; // global min
+ $maxmaxy = ($maxy > $maxmaxy) ? $maxy : $maxmaxy; // global max
+ }
+
+ $this->min_x = $minx;
+ $this->max_x = $maxx;
+ $this->min_y = $minminy;
+ $this->max_y = $maxmaxy;
+ $this->max_t = $maxt;
+
+ $this->data_limits_done = TRUE;
+
+ return TRUE;
+ }
+
+
+ /*!
+ * Calculates image margins on the fly from title positions and sizes,
+ * and tick labels positions and sizes.
+ *
+ * FIXME: fix x_data_label_pos behaviour. Now we are leaving room for it AND x_tick_label_pos
+ * maybe it shouldn't be so...
+ *
+ * TODO: add x_tick_label_width and y_tick_label_height and use them to calculate
+ * max_x_labels and max_y_labels, to be used by drawing functions t avoid overlapping.
+ */
+ function CalcMargins()
+ {
+ // Temporary variables for label size calculation
+ $xlab = $this->FormatLabel('x', $this->max_x);
+ $ylab = $this->FormatLabel('y', $this->max_y);
+
+ //////// Calculate maximum X/Y axis label height and width:
+
+ // TTFonts:
+ if ($this->use_ttf) {
+ // Maximum X axis label height
+ $size = $this->TTFBBoxSize($this->x_label_font['size'], $this->x_label_angle,
+ $this->x_label_font['font'], $xlab);
+ $this->x_tick_label_height = $size[1];
+
+ // Maximum Y axis label width
+ $size = $this->TTFBBoxSize($this->y_label_font['size'], $this->y_label_angle,
+ $this->y_label_font['font'], $ylab);
+ $this->y_tick_label_width = $size[0];
+ }
+ // Fixed fonts:
+ else {
+ // Maximum X axis label height
+ if ($this->x_label_angle == 90)
+ $this->x_tick_label_height = strlen($xlab) * $this->x_label_font['width'];
+ else
+ $this->x_tick_label_height = $this->x_label_font['height'];
+
+ // Maximum Y axis label width
+ $this->y_tick_label_width = strlen($ylab) * $this->y_label_font['width'];
+ }
+
+
+ ///////// Calculate margins:
+
+ // Upper title, ticks and tick labels, and data labels:
+ $this->y_top_margin = $this->title_height + $this->safe_margin * 2;
+
+ if ($this->x_title_pos == 'plotup' || $this->x_title_pos == 'both')
+ $this->y_top_margin += $this->x_title_height + $this->safe_margin;
+
+ if ($this->x_tick_label_pos == 'plotup' || $this->x_tick_label_pos == 'both')
+ $this->y_top_margin += $this->x_tick_label_height;
+
+ if ($this->x_tick_pos == 'plotup' || $this->x_tick_pos == 'both')
+ $this->y_top_margin += $this->x_tick_length * 2;
+
+ if ($this->x_data_label_pos == 'plotup' || $this->x_data_label_pos == 'both')
+ $this->y_top_margin += $this->x_tick_label_height;
+
+ // Lower title, ticks and tick labels, and data labels:
+ $this->y_bot_margin = $this->safe_margin * 2;
+
+ if ($this->x_title_pos == 'plotdown' || $this->x_title_pos == 'both')
+ $this->y_bot_margin += $this->x_title_height;
+
+ if ($this->x_tick_pos == 'plotdown' || $this->x_tick_pos == 'both')
+ $this->y_bot_margin += $this->x_tick_length * 2;
+
+ if ($this->x_tick_pos == 'xaxis' && ($this->x_axis_position == '' || $this->x_axis_position == 0))
+ $this->y_bot_margin += $this->x_tick_length * 2;
+
+ if ($this->x_tick_label_pos == 'plotdown' || $this->x_tick_label_pos == 'both')
+ $this->y_bot_margin += $this->x_tick_label_height;
+
+ if ($this->x_tick_label_pos == 'xaxis' && ($this->x_axis_position == '' || $this->x_axis_position == 0))
+ $this->y_bot_margin += $this->x_tick_label_height;
+
+ if ($this->x_data_label_pos == 'plotdown' || $this->x_data_label_pos == 'both')
+ $this->y_bot_margin += $this->x_tick_label_height;
+
+ // Left title, ticks and tick labels:
+ $this->x_left_margin = $this->safe_margin * 2;
+
+ if ($this->y_title_pos == 'plotleft' || $this->y_title_pos == 'both')
+ $this->x_left_margin += $this->y_title_width + $this->safe_margin;
+
+ if ($this->y_tick_label_pos == 'plotleft' || $this->y_tick_label_pos == 'both')
+ $this->x_left_margin += $this->y_tick_label_width;
+
+ if ($this->y_tick_pos == 'plotleft' || $this->y_tick_pos == 'both')
+ $this->x_left_margin += $this->y_tick_length * 2 ;
+
+ // Right title, ticks and tick labels:
+ $this->x_right_margin = $this->safe_margin * 2;
+
+ if ($this->y_title_pos == 'plotright' || $this->y_title_pos == 'both')
+ $this->x_right_margin += $this->y_title_width + $this->safe_margin;
+
+ if ($this->y_tick_label_pos == 'plotright' || $this->y_tick_label_pos == 'both')
+ $this->x_right_margin += $this->y_tick_label_width;
+
+ if ($this->y_tick_pos == 'plotright' || $this->y_tick_pos == 'both')
+ $this->x_right_margin += $this->y_tick_length * 2;
+
+
+ $this->x_tot_margin = $this->x_left_margin + $this->x_right_margin;
+ $this->y_tot_margin = $this->y_top_margin + $this->y_bot_margin;
+
+ return;
+ }
+
+
+ /*!
+ * Set the margins in pixels (left, right, top, bottom)
+ */
+ function SetMarginsPixels($which_lm, $which_rm, $which_tm, $which_bm)
+ {
+
+ $this->x_left_margin = $which_lm;
+ $this->x_right_margin = $which_rm;
+ $this->x_tot_margin = $which_lm + $which_rm;
+
+ $this->y_top_margin = $which_tm;
+ $this->y_bot_margin = $which_bm;
+ $this->y_tot_margin = $which_tm + $which_bm;
+
+ $this->SetPlotAreaPixels();
+
+ return;
+ }
+
+
+ /*!
+ * Sets the limits for the plot area. If no arguments are supplied, uses
+ * values calculated from _CalcMargins();
+ * Like in GD, (0,0) is upper left
+ *
+ * This resets the scale if SetPlotAreaWorld() was already called
+ */
+ function SetPlotAreaPixels($x1=NULL, $y1=NULL, $x2=NULL, $y2=NULL)
+ {
+ if ($x2 && $y2) {
+ $this->plot_area = array($x1, $y1, $x2, $y2);
+ } else {
+ if (! isset($this->x_tot_margin))
+ $this->CalcMargins();
+
+ $this->plot_area = array($this->x_left_margin, $this->y_top_margin,
+ $this->image_width - $this->x_right_margin,
+ $this->image_height - $this->y_bot_margin);
+ }
+ $this->plot_area_width = $this->plot_area[2] - $this->plot_area[0];
+ $this->plot_area_height = $this->plot_area[3] - $this->plot_area[1];
+
+ // Reset the scale with the new plot area.
+ if (isset($this->plot_max_x))
+ $this->CalcTranslation();
+
+ return TRUE;
+
+ }
+
+
+ /*!
+ * Sets minimum and maximum x and y values in the plot using FindDataLimits()
+ * or from the supplied parameters, if any.
+ *
+ * This resets the scale if SetPlotAreaPixels() was already called
+ */
+ function SetPlotAreaWorld($xmin=NULL, $ymin=NULL, $xmax=NULL, $ymax=NULL)
+ {
+ if ((! $xmin) && (! $xmax) ) {
+ // For automatic setting of data we need data limits
+ if (! isset($this->data_limits_done)) {
+ $this->FindDataLimits() ;
+ }
+ if ($this->data_type == 'text-data') {
+ $xmax = $this->max_x + 1 ; // valid for BAR CHART TYPE GRAPHS ONLY
+ $xmin = 0 ; // valid for BAR CHART TYPE GRAPHS ONLY
+ } else {
+ $xmax = $this->max_x;
+ $xmin = $this->min_x;
+ }
+
+ $ymax = ceil($this->max_y * 1.1);
+ if ($this->min_y < 0) {
+ $ymin = floor($this->min_y * 1.1);
+ } else {
+ $ymin = 0;
+ }
+ }
+
+ $this->plot_min_x = $xmin;
+ $this->plot_max_x = $xmax;
+
+ if ($ymin == $ymax) {
+ $ymax += 1;
+ }
+ if ($this->yscale_type == 'log') {
+ //extra error checking
+ if ($ymin <= 0) {
+ $ymin = 1;
+ }
+ if ($ymax <= 0) {
+ $this->PrintError('SetPlotAreaWorld(): Log plots need data greater than 0');
+ return FALSE;
+ }
+ }
+
+ $this->plot_min_y = $ymin;
+ $this->plot_max_y = $ymax;
+
+ if ($ymax <= $ymin) {
+ $this->DrawError('SetPlotAreaWorld(): Error in data - max not greater than min');
+ return FALSE;
+ }
+
+ // Reset the scale with the new maxs and mins
+ if (isset($this->plot_area_width)) {
+ $this->CalcTranslation();
+ }
+
+ return TRUE;
+ } //function SetPlotAreaWorld
+
+
+ /*!
+ * For plots that have equally spaced x variables and multiple bars per x-point.
+ */
+ function SetEqualXCoord()
+ {
+ $space = ($this->plot_area[2] - $this->plot_area[0]) /
+ ($this->num_data_rows * 2) * $this->group_frac_width;
+ $group_width = $space * 2;
+ $bar_width = $group_width / $this->records_per_group;
+ //I think that eventually this space variable will be replaced by just graphing x.
+ $this->data_group_space = $space;
+ $this->record_bar_width = $bar_width;
+ return TRUE;
+ }
+
+ /*!
+ * Calculates scaling stuff...
+ */
+ function CalcTranslation()
+ {
+ if ($this->xscale_type == 'log') {
+ $this->xscale = ($this->plot_area_width)/(log10($this->plot_max_x) - log10($this->plot_min_x));
+ } else {
+ $this->xscale = ($this->plot_area_width)/($this->plot_max_x - $this->plot_min_x);
+ }
+ if ($this->yscale_type == 'log') {
+ $this->yscale = ($this->plot_area_height)/(log10($this->plot_max_y) - log10($this->plot_min_y));
+ } else {
+ $this->yscale = ($this->plot_area_height)/($this->plot_max_y - $this->plot_min_y);
+ }
+
+ // GD defines x = 0 at left and y = 0 at TOP so -/+ respectively
+ if ($this->xscale_type == 'log') {
+ $this->plot_origin_x = $this->plot_area[0] - ($this->xscale * log10($this->plot_min_x) );
+ } else {
+ $this->plot_origin_x = $this->plot_area[0] - ($this->xscale * $this->plot_min_x);
+ }
+ if ($this->yscale_type == 'log') {
+ $this->plot_origin_y = $this->plot_area[3] + ($this->yscale * log10($this->plot_min_y));
+ } else {
+ $this->plot_origin_y = $this->plot_area[3] + ($this->yscale * $this->plot_min_y);
+ }
+
+ $this->scale_is_set = TRUE;
+
+ /************** FIXME?? *************/
+ // There should be a better place for this.
+
+ // User provided y axis position?
+ if ($this->y_axis_position != '') {
+ // Make sure we draw our axis inside the plot
+ $this->y_axis_position = ($this->y_axis_position < $this->plot_min_x)
+ ? $this->plot_min_x : $this->y_axis_position;
+ $this->y_axis_position = ($this->y_axis_position > $this->plot_max_x)
+ ? $this->plot_max_x : $this->y_axis_position;
+ $this->y_axis_x_pixels = $this->xtr($this->y_axis_position);
+ } else {
+ // Default to left axis
+ $this->y_axis_x_pixels = $this->xtr($this->plot_min_x);
+ }
+ // User provided x axis position?
+ if ($this->x_axis_position != '') {
+ // Make sure we draw our axis inside the plot
+ $this->x_axis_position = ($this->x_axis_position < $this->plot_min_y)
+ ? $this->plot_min_y : $this->x_axis_position;
+ $this->x_axis_position = ($this->x_axis_position > $this->plot_max_y)
+ ? $this->plot_max_y : $this->x_axis_position;
+ $this->x_axis_y_pixels = $this->ytr($this->x_axis_position);
+ } else {
+ if ($this->yscale_type == 'log')
+ $this->x_axis_y_pixels = $this->ytr(1);
+ else
+ // Default to axis at 0 or plot_min_y (should be 0 anyway, from SetPlotAreaWorld())
+ $this->x_axis_y_pixels = ($this->plot_min_y <= 0) && (0 <= $this->plot_max_y)
+ ? $this->ytr(0) : $this->ytr($this->plot_min_y);
+ }
+
+ } // function CalcTranslation()
+
+
+ /*!
+ * Translate X world coordinate into pixel coordinate
+ * Needs values calculated by _CalcTranslation()
+ */
+ function xtr($x_world)
+ {
+ //$x_pixels = $this->x_left_margin + ($this->image_width - $this->x_tot_margin)*
+ // (($x_world - $this->plot_min_x) / ($this->plot_max_x - $this->plot_min_x)) ;
+ //which with a little bit of math reduces to ...
+ if ($this->xscale_type == 'log') {
+ $x_pixels = $this->plot_origin_x + log10($x_world) * $this->xscale ;
+ } else {
+ $x_pixels = $this->plot_origin_x + $x_world * $this->xscale ;
+ }
+ return round($x_pixels);
+ }
+
+
+ /*!
+ * Translate Y world coordinate into pixel coordinate.
+ * Needs values calculated by _CalcTranslation()
+ */
+ function ytr($y_world)
+ {
+ if ($this->yscale_type == 'log') {
+ //minus because GD defines y = 0 at top. doh!
+ $y_pixels = $this->plot_origin_y - log10($y_world) * $this->yscale ;
+ } else {
+ $y_pixels = $this->plot_origin_y - $y_world * $this->yscale ;
+ }
+ return round($y_pixels);
+ }
+
+ /*!
+ * Formats a tick or data label.
+ *
+ * \note Time formatting suggested by Marlin Viss
+ */
+ function FormatLabel($which_pos, $which_lab)
+ {
+ switch ($which_pos) {
+ case 'x':
+ case 'plotx':
+ switch ($this->x_label_type) {
+ case 'title':
+ $lab = $this->data[$which_lab][0];
+ break;
+ case 'data':
+ $lab = number_format($which_lab, $this->x_precision, '.', ', ').$this->data_units_text;
+ break;
+ case 'time':
+ $lab = strftime($this->x_time_format, $which_lab);
+ break;
+ default:
+ // Unchanged from whatever format it is passed in
+ $lab = $which_lab;
+ break;
+ }
+ break;
+ case 'y':
+ case 'ploty':
+ switch ($this->y_label_type) {
+ case 'data':
+ $lab = number_format($which_lab, $this->y_precision, '.', ', ').$this->data_units_text;
+ break;
+ case 'time':
+ $lab = strftime($this->y_time_format, $which_lab);
+ break;
+ default:
+ // Unchanged from whatever format it is passed in
+ $lab = $which_lab;
+ break;
+ }
+ break;
+ default:
+ $this->PrintError("FormatLabel(): Unknown label type $which_type");
+ return NULL;
+ }
+
+ return $lab;
+ } //function FormatLabel
+
+
+
+/////////////////////////////////////////////
+/////////////// TICKS
+/////////////////////////////////////////////
+
+ /*!
+ * Use either this or SetNumXTicks() to set where to place x tick marks
+ */
+ function SetXTickIncrement($which_ti=NULL)
+ {
+ if ($which_ti) {
+ $this->x_tick_increment = $which_ti; //world coordinates
+ } else {
+ if (! isset($this->data_limits_done)) {
+ $this->FindDataLimits(); //Get maxima and minima for scaling
+ }
+ //$this->x_tick_increment = ( ceil($this->max_x * 1.2) - floor($this->min_x * 1.2) )/10;
+ $this->x_tick_increment = ($this->plot_max_x - $this->plot_min_x )/10;
+ }
+ $this->num_x_ticks = ''; //either use num_y_ticks or y_tick_increment, not both
+ return TRUE;
+ }
+
+ /*!
+ * Use either this or SetNumYTicks() to set where to place y tick marks
+ */
+ function SetYTickIncrement($which_ti=NULL)
+ {
+ if ($which_ti) {
+ $this->y_tick_increment = $which_ti; //world coordinates
+ } else {
+ if (! isset($this->data_limits_done)) {
+ $this->FindDataLimits(); //Get maxima and minima for scaling
+ }
+ if (! isset($this->plot_max_y))
+ $this->SetPlotAreaWorld();
+
+ //$this->y_tick_increment = ( ceil($this->max_y * 1.2) - floor($this->min_y * 1.2) )/10;
+ $this->y_tick_increment = ($this->plot_max_y - $this->plot_min_y )/10;
+ }
+ $this->num_y_ticks = ''; //either use num_y_ticks or y_tick_increment, not both
+ return TRUE;
+ }
+
+
+ function SetNumXTicks($which_nt)
+ {
+ $this->num_x_ticks = $which_nt;
+ $this->x_tick_increment = ''; //either use num_x_ticks or x_tick_increment, not both
+ return TRUE;
+ }
+
+ function SetNumYTicks($which_nt)
+ {
+ $this->num_y_ticks = $which_nt;
+ $this->y_tick_increment = ''; //either use num_y_ticks or y_tick_increment, not both
+ return TRUE;
+ }
+
+ /*!
+ *
+ */
+ function SetYTickPos($which_tp)
+ {
+ $this->y_tick_pos = $this->CheckOption($which_tp, 'plotleft, plotright, both, yaxis, none', __FUNCTION__);
+ return TRUE;
+ }
+ /*!
+ *
+ */
+ function SetXTickPos($which_tp)
+ {
+ $this->x_tick_pos = $this->CheckOption($which_tp, 'plotdown, plotup, both, xaxis, none', __FUNCTION__);
+ return TRUE;
+ }
+
+ /*!
+ * \param skip bool
+ */
+ function SetSkipTopTick($skip)
+ {
+ $this->skip_top_tick = (bool)$skip;
+ return TRUE;
+ }
+
+ /*!
+ * \param skip bool
+ */
+ function SetSkipBottomTick($skip)
+ {
+ $this->skip_bottom_tick = (bool)$skip;
+ return TRUE;
+ }
+
+ function SetXTickLength($which_xln)
+ {
+ $this->x_tick_length = $which_xln;
+ return TRUE;
+ }
+
+ function SetYTickLength($which_yln)
+ {
+ $this->y_tick_length = $which_yln;
+ return TRUE;
+ }
+
+ function SetXTickCrossing($which_xc)
+ {
+ $this->x_tick_cross = $which_xc;
+ return TRUE;
+ }
+
+ function SetYTickCrossing($which_yc)
+ {
+ $this->y_tick_cross = $which_yc;
+ return TRUE;
+ }
+
+
+/////////////////////////////////////////////
+//////////////////// GENERIC DRAWING
+/////////////////////////////////////////////
+
+ /*!
+ * Fills the background of the image with a solid color
+ */
+ function DrawBackground()
+ {
+ if (! $this->background_done) { //Don't draw it twice if drawing two plots on one image
+ ImageFilledRectangle($this->img, 0, 0, $this->image_width, $this->image_height,
+ $this->ndx_bg_color);
+ $this->background_done = TRUE;
+ }
+ return TRUE;
+ }
+
+ /*!
+ * Draws a border around the final image.
+ */
+ function DrawImageBorder()
+ {
+ switch ($this->image_border_type) {
+ case 'raised':
+ ImageLine($this->img, 0, 0, $this->image_width-1, 0, $this->ndx_i_border);
+ ImageLine($this->img, 1, 1, $this->image_width-2, 1, $this->ndx_i_border);
+ ImageLine($this->img, 0, 0, 0, $this->image_height-1, $this->ndx_i_border);
+ ImageLine($this->img, 1, 1, 1, $this->image_height-2, $this->ndx_i_border);
+ ImageLine($this->img, $this->image_width-1, 0, $this->image_width-1,
+ $this->image_height-1, $this->ndx_i_border_dark);
+ ImageLine($this->img, 0, $this->image_height-1, $this->image_width-1,
+ $this->image_height-1, $this->ndx_i_border_dark);
+ ImageLine($this->img, $this->image_width-2, 1, $this->image_width-2,
+ $this->image_height-2, $this->ndx_i_border_dark);
+ ImageLine($this->img, 1, $this->image_height-2, $this->image_width-2,
+ $this->image_height-2, $this->ndx_i_border_dark);
+ break;
+ case 'plain':
+ ImageLine($this->img, 0, 0, $this->image_width, 0, $this->ndx_i_border_dark);
+ ImageLine($this->img, $this->image_width-1, 0, $this->image_width-1,
+ $this->image_height, $this->ndx_i_border_dark);
+ ImageLine($this->img, $this->image_width-1, $this->image_height-1, 0, $this->image_height-1,
+ $this->ndx_i_border_dark);
+ ImageLine($this->img, 0, 0, 0, $this->image_height, $this->ndx_i_border_dark);
+ break;
+ case 'none':
+ break;
+ default:
+ $this->DrawError("DrawImageBorder(): unknown image_border_type: '$this->image_border_type'");
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+
+ /*!
+ * Adds the title to the graph.
+ */
+ function DrawTitle()
+ {
+ // Center of the plot area
+ //$xpos = ($this->plot_area[0] + $this->plot_area_width )/ 2;
+
+ // Center of the image:
+ $xpos = $this->image_width / 2;
+
+ // Place it at almost at the top
+ $ypos = $this->safe_margin;
+
+ $this->DrawText($this->title_font, $this->title_angle, $xpos, $ypos,
+ $this->ndx_title_color, $this->title_txt, 'center', 'bottom');
+
+ return TRUE;
+
+ }
+
+
+ /*!
+ * Draws the X-Axis Title
+ */
+ function DrawXTitle()
+ {
+ if ($this->x_title_pos == 'none')
+ return;
+
+ // Center of the plot
+ $xpos = ($this->plot_area[2] + $this->plot_area[0]) / 2;
+
+ // Upper title
+ if ($this->x_title_pos == 'plotup' || $this->x_title_pos == 'both') {
+ $ypos = $this->safe_margin + $this->title_height + $this->safe_margin;
+ $this->DrawText($this->x_title_font, $this->x_title_angle,
+ $xpos, $ypos, $this->ndx_title_color, $this->x_title_txt, 'center');
+ }
+ // Lower title
+ if ($this->x_title_pos == 'plotdown' || $this->x_title_pos == 'both') {
+ $ypos = $this->image_height - $this->x_title_height - $this->safe_margin;
+ $this->DrawText($this->x_title_font, $this->x_title_angle,
+ $xpos, $ypos, $this->ndx_title_color, $this->x_title_txt, 'center');
+ }
+ return TRUE;
+ }
+
+ /*!
+ * Draws the Y-Axis Title
+ */
+ function DrawYTitle()
+ {
+ if ($this->y_title_pos == 'none')
+ return;
+
+ // Center the title vertically to the plot
+ $ypos = ($this->plot_area[3] + $this->plot_area[1]) / 2;
+
+ if ($this->y_title_pos == 'plotleft' || $this->y_title_pos == 'both') {
+ $xpos = $this->safe_margin;
+ $this->DrawText($this->y_title_font, 90, $xpos, $ypos, $this->ndx_title_color,
+ $this->y_title_txt, 'left', 'center');
+ }
+ if ($this->y_title_pos == 'plotright' || $this->y_title_pos == 'both') {
+ $xpos = $this->image_width - $this->safe_margin - $this->y_title_width - $this->safe_margin;
+ $this->DrawText($this->y_title_font, 90, $xpos, $ypos, $this->ndx_title_color,
+ $this->y_title_txt, 'left', 'center');
+ }
+
+ return TRUE;
+ }
+
+
+ /*!
+ * Fills the plot area with a solid color
+ */
+ function DrawPlotAreaBackground()
+ {
+ ImageFilledRectangle($this->img, $this->plot_area[0], $this->plot_area[1],
+ $this->plot_area[2], $this->plot_area[3],
+ $this->ndx_plot_bg_color);
+ return TRUE;
+ }
+
+ /*
+ * \note Horizontal grid lines overwrite horizontal axis with y=0, so call this first, then DrawXAxis()
+ */
+ function DrawYAxis()
+ {
+ // Draw ticks, labels and grid, if any
+ $this->DrawYTicks();
+
+ // Draw Y axis at X = y_axis_x_pixels
+ ImageLine($this->img, $this->y_axis_x_pixels, $this->plot_area[1],
+ $this->y_axis_x_pixels, $this->plot_area[3], $this->ndx_grid_color);
+
+ return TRUE;
+ }
+
+ /*
+ *
+ */
+ function DrawXAxis()
+ {
+ // Draw ticks, labels and grid
+ $this->DrawXTicks();
+
+ //Draw Tick and Label for Y axis
+ if (! $this->skip_bottom_tick) {
+ $ylab =$this->FormatLabel('y', $this->x_axis_position);
+ $this->DrawYTick($ylab, $this->x_axis_y_pixels);
+ }
+
+ //Draw X Axis at Y = x_axis_y_pixels
+ ImageLine($this->img, $this->plot_area[0]+1, $this->x_axis_y_pixels,
+ $this->plot_area[2]-1, $this->x_axis_y_pixels, $this->ndx_grid_color);
+
+ return TRUE;
+ }
+
+ /*!
+ * Draw Just one Tick, called from DrawYTicks() and DrawXAxis()
+ * TODO? Move this inside DrawYTicks() and Modify DrawXAxis() ?
+ */
+ function DrawYTick($which_ylab, $which_ypix)
+ {
+ // Ticks on Y axis
+ if ($this->y_tick_pos == 'yaxis') {
+ ImageLine($this->img, $this->y_axis_x_pixels - $this->y_tick_length, $which_ypix,
+ $this->y_axis_x_pixels + $this->y_tick_cross, $which_ypix,
+ $this->ndx_tick_color);
+ }
+
+ // Labels on Y axis
+ if ($this->y_tick_label_pos == 'yaxis') {
+ $this->DrawText($this->y_label_font, $this->y_label_angle,
+ $this->y_axis_x_pixels - $this->y_tick_length * 1.5, $which_ypix,
+ $this->ndx_text_color, $which_ylab, 'right', 'center');
+ }
+
+ // Ticks to the left of the Plot Area
+ if (($this->y_tick_pos == 'plotleft') || ($this->y_tick_pos == 'both') ) {
+ ImageLine($this->img, $this->plot_area[0] - $this->y_tick_length,
+ $which_ypix, $this->plot_area[0] + $this->y_tick_cross,
+ $which_ypix, $this->ndx_tick_color);
+ }
+
+ // Ticks to the right of the Plot Area
+ if (($this->y_tick_pos == 'plotright') || ($this->y_tick_pos == 'both') ) {
+ ImageLine($this->img, ($this->plot_area[2] + $this->y_tick_length),
+ $which_ypix, $this->plot_area[2] - $this->y_tick_cross,
+ $which_ypix, $this->ndx_tick_color);
+ }
+
+ // Labels to the left of the plot area
+ if ($this->y_tick_label_pos == 'plotleft' || $this->y_tick_label_pos == 'both') {
+ $this->DrawText($this->y_label_font, $this->y_label_angle,
+ $this->plot_area[0] - $this->y_tick_length * 1.5, $which_ypix,
+ $this->ndx_text_color, $which_ylab, 'right', 'center');
+ }
+ // Labels to the right of the plot area
+ if ($this->y_tick_label_pos == 'plotright' || $this->y_tick_label_pos == 'both') {
+ $this->DrawText($this->y_label_font, $this->y_label_angle,
+ $this->plot_area[2] + $this->y_tick_length * 1.5, $which_ypix,
+ $this->ndx_text_color, $which_ylab, 'left', 'center');
+ }
+ } // Function DrawYTick()
+
+
+ /*!
+ * Draws Grid, Ticks and Tick Labels along Y-Axis
+ * Ticks and ticklabels can be left of plot only, right of plot only,
+ * both on the left and right of plot, or crossing a user defined Y-axis
+ */
+ function DrawYTicks()
+ {
+ // Sets the line style for IMG_COLOR_STYLED lines (grid)
+ if ($this->dashed_grid) {
+ $this->SetDashedStyle($this->ndx_light_grid_color);
+ $style = IMG_COLOR_STYLED;
+ } else {
+ $style = $this->ndx_light_grid_color;
+ }
+
+ // maxy is always > miny so delta_y is always positive
+ if ($this->y_tick_increment) {
+ $delta_y = $this->y_tick_increment;
+ } elseif ($this->num_y_ticks) {
+ $delta_y = ($this->plot_max_y - $this->plot_min_y) / $this->num_y_ticks;
+ } else {
+ $delta_y = ($this->plot_max_y - $this->plot_min_y) / 10 ;
+ }
+
+ // NOTE: When working with floats, because of approximations when adding $delta_y,
+ // $y_tmp never equals $y_end at the for loop, so one spurious line would get drawn where
+ // not for the substraction to $y_end here.
+ $y_tmp = (double)$this->plot_min_y;
+ $y_end = (double)$this->plot_max_y - ($delta_y/2);
+
+ if ($this->skip_bottom_tick)
+ $y_tmp += $delta_y;
+
+ if ($this->skip_top_tick)
+ $y_end -= $delta_y;
+
+ for (;$y_tmp < $y_end; $y_tmp += $delta_y) {
+ $ylab = $this->FormatLabel('y', $y_tmp);
+ $y_pixels = $this->ytr($y_tmp);
+
+ // Horizontal grid line
+ if ($this->draw_y_grid) {
+ ImageLine($this->img, $this->plot_area[0]+1, $y_pixels, $this->plot_area[2]-1, $y_pixels, $style);
+ }
+
+ // Draw ticks
+ $this->DrawYTick($ylab, $y_pixels);
+ }
+ return TRUE;
+ } // function DrawYTicks
+
+
+ /*!
+ * Draws Grid, Ticks and Tick Labels along X-Axis
+ * Ticks and tick labels can be down of plot only, up of plot only,
+ * both on up and down of plot, or crossing a user defined X-axis
+ *
+ * \note Original vertical code submitted by Marlin Viss
+ */
+ function DrawXTicks()
+ {
+ // Sets the line style for IMG_COLOR_STYLED lines (grid)
+ if ($this->dashed_grid) {
+ $this->SetDashedStyle($this->ndx_light_grid_color);
+ $style = IMG_COLOR_STYLED;
+ } else {
+ $style = $this->ndx_light_grid_color;
+ }
+
+ // Calculate x increment between ticks
+ if ($this->x_tick_increment) {
+ $delta_x = $this->x_tick_increment;
+ } elseif ($this->num_x_ticks) {
+ $delta_x = ($this->plot_max_x - $this->plot_min_x) / $this->num_x_ticks;
+ } else {
+ $delta_x =($this->plot_max_x - $this->plot_min_x) / 10 ;
+ }
+
+ // NOTE: When working with decimals, because of approximations when adding $delta_x,
+ // $x_tmp never equals $x_end at the for loop, so one spurious line would get drawn where
+ // not for the substraction to $x_end here.
+ $x_tmp = (double)$this->plot_min_x;
+ $x_end = (double)$this->plot_max_x - ($delta_x/2);
+
+ // Should the leftmost tick be drawn?
+ if ($this->skip_left_tick)
+ $x_tmp += $delta_x;
+
+ // And the rightmost?
+ if (! $this->skip_right_tick)
+ $x_end += $delta_x;
+
+ for (;$x_tmp < $x_end; $x_tmp += $delta_x) {
+ $xlab = $this->FormatLabel('x', $x_tmp);
+ $x_pixels = $this->xtr($x_tmp);
+
+ // Vertical grid lines
+ if ($this->draw_x_grid) {
+ ImageLine($this->img, $x_pixels, $this->plot_area[1], $x_pixels, $this->plot_area[3], $style);
+ }
+
+ // Tick on X Axis
+ if ($this->x_tick_pos == 'xaxis') {
+ ImageLine($this->img, $x_pixels, $this->x_axis_y_pixels - $this->x_tick_cross,
+ $x_pixels, $this->x_axis_y_pixels + $this->x_tick_length, $this->ndx_tick_color);
+ }
+
+ // Label on X axis
+ if ($this->x_tick_label_pos == 'xaxis') {
+ $this->DrawText($this->x_label_font, $this->x_label_angle, $x_pixels,
+ $this->x_axis_y_pixels + $this->x_tick_length*1.5, $this->ndx_text_color,
+ $xlab, 'center', 'bottom');
+ }
+
+ // Top of the plot area tick
+ if ($this->x_tick_pos == 'plotup' || $this->x_tick_pos == 'both') {
+ ImageLine($this->img, $x_pixels, $this->plot_area[1] - $this->x_tick_length,
+ $x_pixels, $this->plot_area[1] + $this->x_tick_cross, $this->ndx_tick_color);
+ }
+ // Bottom of the plot area tick
+ if ($this->x_tick_pos == 'plotdown' || $this->x_tick_pos == 'both') {
+ ImageLine($this->img, $x_pixels, $this->plot_area[3] + $this->x_tick_length,
+ $x_pixels, $this->plot_area[3] - $this->x_tick_cross, $this->ndx_tick_color);
+ }
+
+ // Top of the plot area tick label
+ if ($this->x_tick_label_pos == 'plotup' || $this->x_tick_label_pos == 'both') {
+ $this->DrawText($this->x_label_font, $this->x_label_angle, $x_pixels,
+ $this->plot_area[1] - $this->x_tick_length*1.5, $this->ndx_text_color,
+ $xlab, 'center', 'top');
+ }
+
+ // Bottom of the plot area tick label
+ if ($this->x_tick_label_pos == 'plotdown' || $this->x_tick_label_pos == 'both') {
+ $this->DrawText($this->x_label_font, $this->x_label_angle, $x_pixels,
+ $this->plot_area[3] + $this->x_tick_length*1.5, $this->ndx_text_color,
+ $xlab, 'center', 'bottom');
+ }
+ }
+ return;
+ } // function DrawXTicks
+
+
+ /*!
+ *
+ */
+ function DrawPlotBorder()
+ {
+ switch ($this->plot_border_type) {
+ case 'left': // for past compatibility
+ case 'plotleft':
+ ImageLine($this->img, $this->plot_area[0], $this->ytr($this->plot_min_y),
+ $this->plot_area[0], $this->ytr($this->plot_max_y), $this->ndx_grid_color);
+ break;
+ case 'right':
+ case 'plotright':
+ ImageLine($this->img, $this->plot_area[2], $this->ytr($this->plot_min_y),
+ $this->plot_area[2], $this->ytr($this->plot_max_y), $this->ndx_grid_color);
+ break;
+ case 'both':
+ case 'sides':
+ ImageLine($this->img, $this->plot_area[0], $this->ytr($this->plot_min_y),
+ $this->plot_area[0], $this->ytr($this->plot_max_y), $this->ndx_grid_color);
+ ImageLine($this->img, $this->plot_area[2], $this->ytr($this->plot_min_y),
+ $this->plot_area[2], $this->ytr($this->plot_max_y), $this->ndx_grid_color);
+ break;
+ case 'none':
+ //Draw No Border
+ break;
+ case 'full':
+ default:
+ ImageRectangle($this->img, $this->plot_area[0], $this->ytr($this->plot_min_y),
+ $this->plot_area[2], $this->ytr($this->plot_max_y), $this->ndx_grid_color);
+ break;
+ }
+ return TRUE;
+ }
+
+
+ /*!
+ * Draws the data label associated with a point in the plot.
+ * This is different from x_labels drawn by DrawXTicks() and care
+ * should be taken not to draw both, as they'd probably overlap.
+ * Calling of this function in DrawLines(), etc is decided after x_data_label_pos value.
+ * Leave the last parameter out, to avoid the drawing of vertical lines, no matter
+ * what the setting is (for plots that need it, like DrawSquared())
+ */
+ function DrawXDataLabel($xlab, $xpos, $row=FALSE)
+ {
+ $xlab = $this->FormatLabel('x', $xlab);
+
+ // Labels below the plot area
+ if ($this->x_data_label_pos == 'plotdown' || $this->x_data_label_pos == 'both')
+ $this->DrawText($this->x_label_font, $this->x_label_angle, $xpos,
+ $this->plot_area[3] + $this->x_tick_length,
+ $this->ndx_text_color, $xlab, 'center', 'bottom');
+
+ // Labels above the plot area
+ if ($this->x_data_label_pos == 'plotup' || $this->x_data_label_pos == 'both')
+ $this->DrawText($this->x_label_font, $this->x_label_angle, $xpos,
+ $this->plot_area[1] - $this->x_tick_length ,
+ $this->ndx_text_color, $xlab, 'center', 'top');
+
+ if ($row && $this->draw_x_data_label_lines)
+ $this->DrawXDataLine($xpos, $row);
+ }
+
+ /*!
+ * Draws Vertical lines from data points up and down.
+ * Which lines are drawn depends on the value of x_data_label_pos,
+ * and whether this is at all done or not, on draw_x_data_label_lines
+ *
+ * \param xpos int position in pixels of the line.
+ * \param row int index of the data row being drawn.
+ */
+ function DrawXDataLine($xpos, $row)
+ {
+ // Sets the line style for IMG_COLOR_STYLED lines (grid)
+ if($this->dashed_grid) {
+ $this->SetDashedStyle($this->ndx_light_grid_color);
+ $style = IMG_COLOR_STYLED;
+ } else {
+ $style = $this->ndx_light_grid_color;
+ }
+
+ // Lines from the bottom up
+ if ($this->x_data_label_pos == 'both') {
+ ImageLine($this->img, $xpos, $this->plot_area[3], $xpos, $this->plot_area[1], $style);
+ }
+ // Lines coming from the bottom of the plot
+ else if ($this->x_data_label_pos == 'plotdown') {
+ // See FindDataLimits() to see why 'MAXY' index.
+ $ypos = $this->ytr($this->data[$row][MAXY]);
+ ImageLine($this->img, $xpos, $ypos, $xpos, $this->plot_area[3], $style);
+ }
+ // Lines coming from the top of the plot
+ else if ($this->x_data_label_pos == 'plotup') {
+ // See FindDataLimits() to see why 'MINY' index.
+ $ypos = $this->ytr($this->data[$row][MINY]);
+ ImageLine($this->img, $xpos, $this->plot_area[1], $xpos, $ypos, $style);
+ }
+ }
+
+/*
+ function DrawPlotLabel($xlab, $xpos, $ypos)
+ {
+ $this->DrawText($this->x_label_font, $this->x_label_angle, $xpos, $this
+*/
+
+ /*!
+ * Draws the graph legend
+ *
+ * \note Base code submitted by Marlin Viss
+ * FIXME: maximum label length should be calculated more accurately for TT fonts
+ * Performing a BBox calculation for every legend element, for example.
+ */
+ function DrawLegend($which_x1, $which_y1, $which_boxtype)
+ {
+ // Find maximum legend label length
+ $max_len = 0;
+ foreach ($this->legend as $leg) {
+ $len = strlen($leg);
+ $max_len = ($len > $max_len) ? $len : $max_len;
+ }
+ $max_len += 5; // Leave room for the boxes and margins
+
+ /////// Calculate legend labels sizes: FIXME - dirty hack - FIXME
+ // TTF:
+ if ($this->use_ttf) {
+ $size = $this->TTFBBoxSize($this->legend_font['size'], 0,
+ $this->legend_font['font'], '_');
+ $char_w = $size[0];
+
+ $size = $this->TTFBBoxSize($this->legend_font['size'], 0,
+ $this->legend_font['font'], '|');
+ $char_h = $size[1];
+ }
+ // Fixed fonts:
+ else {
+ $char_w = $this->legend_font['width'];
+ $char_h = $this->legend_font['height'];
+ }
+
+ $v_margin = $char_h/2; // Between vertical borders and labels
+ $dot_height = $char_h + $this->line_spacing; // Height of the small colored boxes
+ $width = $char_w * $max_len;
+
+ //////// Calculate box size
+ // upper Left
+ if ( (! $which_x1) || (! $which_y1) ) {
+ $box_start_x = $this->plot_area[2] - $width;
+ $box_start_y = $this->plot_area[1] + 5;
+ } else {
+ $box_start_x = $which_x1;
+ $box_start_y = $which_y1;
+ }
+
+ // Lower right corner
+ $box_end_y = $box_start_y + $dot_height*(count($this->legend)) + 2*$v_margin;
+ $box_end_x = $box_start_x + $width - 5;
+
+
+ // Draw outer box
+ ImageFilledRectangle($this->img, $box_start_x, $box_start_y, $box_end_x, $box_end_y, $this->ndx_bg_color);
+ ImageRectangle($this->img, $box_start_x, $box_start_y, $box_end_x, $box_end_y, $this->ndx_grid_color);
+
+ $color_index = 0;
+ $max_color_index = count($this->ndx_data_colors) - 1;
+
+ $dot_left_x = $box_end_x - $char_w * 2;
+ $dot_right_x = $box_end_x - $char_w;
+ $y_pos = $box_start_y + $v_margin;
+
+ foreach ($this->legend as $leg) {
+ // Text right aligned to the little box
+ $this->DrawText($this->legend_font, 0, $dot_left_x - $char_w, $y_pos,
+ $this->ndx_text_color, $leg, 'right');
+ // Draw a box in the data color
+ ImageFilledRectangle($this->img, $dot_left_x, $y_pos + 1, $dot_right_x,
+ $y_pos + $dot_height-1, $this->ndx_data_colors[$color_index]);
+ // Draw a rectangle around the box
+ ImageRectangle($this->img, $dot_left_x, $y_pos + 1, $dot_right_x,
+ $y_pos + $dot_height-1, $this->ndx_text_color);
+
+ $y_pos += $char_h + $this->line_spacing;
+
+ $color_index++;
+ if ($color_index > $max_color_index)
+ $color_index = 0;
+ }
+ } // Function DrawLegend()
+
+
+ /*!
+ * TODO Draws a legend over (or below) an axis of the plot.
+ */
+ function DrawAxisLegend()
+ {
+ // Calculate available room
+ // Calculate length of all items (boxes included)
+ // Calculate number of lines and room it would take. FIXME: this should be known in CalcMargins()
+ // Draw.
+ }
+
+/////////////////////////////////////////////
+//////////////////// PLOT DRAWING
+/////////////////////////////////////////////
+
+
+ /*!
+ * Draws a pie chart. Data has to be 'text-data' type.
+ *
+ * This can work in two ways: the classical, with a column for each sector
+ * (computes the column totals and draws the pie with that)
+ * OR
+ * Takes each row as a sector and uses it's first value. This has the added
+ * advantage of using the labels provided, which is not the case with the
+ * former method. This might prove useful for pie charts from GROUP BY sql queries
+ */
+ function DrawPieChart()
+ {
+ $xpos = $this->plot_area[0] + $this->plot_area_width/2;
+ $ypos = $this->plot_area[1] + $this->plot_area_height/2;
+ $diameter = min($this->plot_area_width, $this->plot_area_height);
+ $radius = $diameter/2;
+
+ // Get sum of each column? One pie slice per column
+ if ($this->data_type === 'text-data') {
+ for ($i = 0; $i < $this->num_data_rows; $i++) {
+ for ($j = 1; $j < $this->num_recs[$i]; $j++) { // Label ($row[0]) unused in these pie charts
+ @ $sumarr[$j] += abs($this->data[$i][$j]); // NOTE! sum > 0 to make pie charts
+ }
+ }
+ }
+ // Or only one column per row, one pie slice per row?
+ else if ($this->data_type == 'text-data-pie') {
+ for ($i = 0; $i < $this->num_data_rows; $i++) {
+ $legend[$i] = $this->data[$i][0]; // Set the legend to column labels
+ $sumarr[$i] = $this->data[$i][1];
+ }
+ }
+ else if ($this->data_type == 'data-data') {
+ for ($i = 0; $i < $this->num_data_rows; $i++) {
+ for ($j = 2; $j < $this->num_recs[$i]; $j++) {
+ @ $sumarr[$j] += abs($this->data[$i][$j]);
+ }
+ }
+ }
+ else {
+ $this->DrawError("DrawPieChart(): Data type '$this->data_type' not supported.");
+ return FALSE;
+ }
+
+ $total = array_sum($sumarr);
+
+ if ($total == 0) {
+ $this->DrawError('DrawPieChart(): Empty data set');
+ return FALSE;
+ }
+
+ if ($this->shading) {
+ $diam2 = $diameter / 2;
+ } else {
+ $diam2 = $diameter;
+ }
+ $max_data_colors = count ($this->data_colors);
+
+ for ($h = $this->shading; $h >= 0; $h--) {
+ $color_index = 0;
+ $start_angle = 0;
+ $end_angle = 0;
+ foreach ($sumarr as $val) {
+ // For shaded pies: the last one (at the top of the "stack") has a brighter color:
+ if ($h == 0)
+ $slicecol = $this->ndx_data_colors[$color_index];
+ else
+ $slicecol = $this->ndx_data_dark_colors[$color_index];
+
+ $label_txt = number_format(($val / $total * 100), $this->y_precision, '.', ', ') . '%';
+ $val = 360 * ($val / $total);
+
+ // NOTE that imagefilledarc measures angles CLOCKWISE (go figure why),
+ // so the pie chart would start clockwise from 3 o'clock, would it not be
+ // for the reversal of start and end angles in imagefilledarc()
+ $start_angle = $end_angle;
+ $end_angle += $val;
+ $mid_angle = deg2rad($end_angle - ($val / 2));
+
+ // Draw the slice
+ ImageFilledArc($this->img, $xpos, $ypos+$h, $diameter, $diam2,
+ 360-$end_angle, 360-$start_angle,
+ $slicecol, IMG_ARC_PIE);
+
+ // Draw the labels only once
+ if ($h == 0) {
+ // Draw the outline
+ if (! $this->shading)
+ ImageFilledArc($this->img, $xpos, $ypos+$h, $diameter, $diam2,
+ 360-$end_angle, 360-$start_angle,
+ $this->ndx_grid_color, IMG_ARC_PIE | IMG_ARC_EDGED |IMG_ARC_NOFILL);
+
+
+ // The '* 1.2' trick is to get labels out of the pie chart so there are more
+ // chances they can be seen in small sectors.
+ $label_x = $xpos + ($diameter * 1.2 * cos($mid_angle)) * $this->label_scale_position;
+ $label_y = $ypos+$h - ($diam2 * 1.2 * sin($mid_angle)) * $this->label_scale_position;
+
+ $this->DrawText($this->generic_font, 0, $label_x, $label_y, $this->ndx_grid_color,
+ $label_txt, 'center', 'center');
+ }
+ $color_index++;
+ $color_index = $color_index % $max_data_colors;
+ } // end for
+ } // end for
+ }
+
+
+ /*!
+ * Supported data formats: data-data-error, text-data-error (doesn't exist yet)
+ * ( data comes in as array("title", x, y, error+, error-, y2, error2+, error2-, ...) )
+ */
+ function DrawDotsError()
+ {
+ $this->CheckOption($this->data_type, 'data-data-error', __FUNCTION__);
+
+ for($row = 0, $cnt = 0; $row < $this->num_data_rows; $row++) {
+ $record = 1; // Skip record #0 (title)
+
+ // Do we have a value for X?
+ if ($this->data_type == 'data-data-error')
+ $x_now = $this->data[$row][$record++]; // Read it, advance record index
+ else
+ $x_now = 0.5 + $cnt++; // Place text-data at X = 0.5, 1.5, 2.5, etc...
+
+ // Draw X Data labels?
+ if ($this->x_data_label_pos != 'none')
+ $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels, $row);
+
+ while ($record < $this->num_recs[$row]) {
+ // Y:
+ $y_now = $this->data[$row][$record++];
+ $this->DrawDot($x_now, $y_now, $this->point_shape, $this->ndx_data_colors[$record]);
+
+ // Error +
+ $val = $this->data[$row][$record++];
+ $this->DrawYErrorBar($x_now, $y_now, $val, $this->error_bar_shape,
+ $this->ndx_error_bar_colors[$record]);
+ // Error -
+ $val = $this->data[$row][$record];
+ $this->DrawYErrorBar($x_now, $y_now, -$val, $this->error_bar_shape,
+ $this->ndx_error_bar_colors[$record++]);
+ }
+ }
+ } // function DrawDotsError()
+
+
+ /*
+ * Supported data types:
+ * - data-data ("title", x, y1, y2, y3, ...)
+ * - text-data ("title", y1, y2, y3, ...)
+ */
+ function DrawDots()
+ {
+ $this->CheckOption($this->data_type, 'text-data, data-data', __FUNCTION__);
+
+ for ($row = 0, $cnt = 0; $row < $this->num_data_rows; $row++) {
+ $rec = 1; // Skip record #0 (data label)
+
+ // Do we have a value for X?
+ if ($this->data_type == 'data-data')
+ $x_now = $this->data[$row][$rec++]; // Read it, advance record index
+ else
+ $x_now = 0.5 + $cnt++; // Place text-data at X = 0.5, 1.5, 2.5, etc...
+
+ $x_now_pixels = $this->xtr($x_now);
+
+ // Draw X Data labels?
+ if ($this->x_data_label_pos != 'none')
+ $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels, $row);
+
+ // Proceed with Y values
+ for($idx = 0;$rec < $this->num_recs[$row]; $rec++, $idx++) {
+ if (is_numeric($this->data[$row][$rec])) { // Allow for missing Y data
+ $this->DrawDot($x_now, $this->data[$row][$rec],
+ $this->point_shape, $this->ndx_data_colors[$idx]);
+ }
+ }
+ }
+ } //function DrawDots
+
+
+ /*!
+ * A clean, fast routine for when you just want charts like stock volume charts
+ */
+ function DrawThinBarLines()
+ {
+ $this->CheckOption($this->data_type, 'text-data, data-data', __FUNCTION__);
+
+ for ($row = 0, $cnt = 0; $row < $this->num_data_rows; $row++) {
+ $rec = 1; // Skip record #0 (data label)
+
+ // Do we have a value for X?
+ if ($this->data_type == 'data-data')
+ $x_now = $this->data[$row][$rec++]; // Read it, advance record index
+ else
+ $x_now = 0.5 + $cnt++; // Place text-data at X = 0.5, 1.5, 2.5, etc...
+
+ $x_now_pixels = $this->xtr($x_now);
+
+ // Draw X Data labels?
+ if ($this->x_data_label_pos != 'none')
+ $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels);
+
+ // Proceed with Y values
+ for($idx = 0;$rec < $this->num_recs[$row]; $rec++, $idx++) {
+ if (is_numeric($this->data[$row][$rec])) { // Allow for missing Y data
+ ImageSetThickness($this->img, $this->line_widths[$idx]);
+ // Draws a line from user defined x axis position up to ytr($val)
+ ImageLine($this->img, $x_now_pixels, $this->x_axis_y_pixels, $x_now_pixels,
+ $this->ytr($this->data[$row][$rec]), $this->ndx_data_colors[$idx]);
+ }
+ }
+ }
+
+ ImageSetThickness($this->img, 1);
+ } //function DrawThinBarLines
+
+ /*!
+ *
+ */
+ function DrawYErrorBar($x_world, $y_world, $error_height, $error_bar_type, $color)
+ {
+ /*
+ // TODO: add a parameter to show datalabels next to error bars?
+ // something like this:
+ if ($this->x_data_label_pos == 'plot') {
+ $this->DrawText($this->error_font, 90, $x1, $y2,
+ $color, $label, 'center', 'top');
+ */
+
+ $x1 = $this->xtr($x_world);
+ $y1 = $this->ytr($y_world);
+ $y2 = $this->ytr($y_world+$error_height) ;
+
+ ImageSetThickness($this->img, $this->error_bar_line_width);
+ ImageLine($this->img, $x1, $y1 , $x1, $y2, $color);
+
+ switch ($error_bar_type) {
+ case 'line':
+ break;
+ case 'tee':
+ ImageLine($this->img, $x1-$this->error_bar_size, $y2, $x1+$this->error_bar_size, $y2, $color);
+ break;
+ default:
+ ImageLine($this->img, $x1-$this->error_bar_size, $y2, $x1+$this->error_bar_size, $y2, $color);
+ break;
+ }
+
+ ImageSetThickness($this->img, 1);
+ return TRUE;
+ }
+
+ /*!
+ * Draws a styled dot. Uses world coordinates.
+ * Supported types: 'halfline', 'line', 'plus', 'cross', 'rect', 'circle', 'dot',
+ * 'diamond', 'triangle', 'trianglemid'
+ */
+ function DrawDot($x_world, $y_world, $dot_type, $color)
+ {
+ $half_point = $this->point_size / 2;
+
+ $x_mid = $this->xtr($x_world);
+ $y_mid = $this->ytr($y_world);
+
+ $x1 = $x_mid - $half_point;
+ $x2 = $x_mid + $half_point;
+ $y1 = $y_mid - $half_point;
+ $y2 = $y_mid + $half_point;
+
+ switch ($dot_type) {
+ case 'halfline':
+ ImageLine($this->img, $x1, $y_mid, $x_mid, $y_mid, $color);
+ break;
+ case 'line':
+ ImageLine($this->img, $x1, $y_mid, $x2, $y_mid, $color);
+ break;
+ case 'plus':
+ ImageLine($this->img, $x1, $y_mid, $x2, $y_mid, $color);
+ ImageLine($this->img, $x_mid, $y1, $x_mid, $y2, $color);
+ break;
+ case 'cross':
+ ImageLine($this->img, $x1, $y1, $x2, $y2, $color);
+ ImageLine($this->img, $x1, $y2, $x2, $y1, $color);
+ break;
+ case 'rect':
+ ImageFilledRectangle($this->img, $x1, $y1, $x2, $y2, $color);
+ break;
+ case 'circle':
+ ImageArc($this->img, $x_mid, $y_mid, $this->point_size, $this->point_size, 0, 360, $color);
+ break;
+ case 'dot':
+ ImageFilledArc($this->img, $x_mid, $y_mid, $this->point_size, $this->point_size, 0, 360,
+ $color, IMG_ARC_PIE);
+ break;
+ case 'diamond':
+ $arrpoints = array( $x1, $y_mid, $x_mid, $y1, $x2, $y_mid, $x_mid, $y2);
+ ImageFilledPolygon($this->img, $arrpoints, 4, $color);
+ break;
+ case 'triangle':
+ $arrpoints = array( $x1, $y_mid, $x2, $y_mid, $x_mid, $y2);
+ ImageFilledPolygon($this->img, $arrpoints, 3, $color);
+ break;
+ case 'trianglemid':
+ $arrpoints = array( $x1, $y1, $x2, $y1, $x_mid, $y_mid);
+ ImageFilledPolygon($this->img, $arrpoints, 3, $color);
+ break;
+ default:
+ ImageFilledRectangle($this->img, $x1, $y1, $x2, $y2, $color);
+ break;
+ }
+ return TRUE;
+ }
+
+ /*!
+ * Draw an area plot. Supported data types:
+ * 'text-data'
+ * 'data-data'
+ * NOTE: This function used to add first and last data values even on incomplete
+ * sets. That is not the behaviour now. As for missing data in between,
+ * there are two posibilities: replace the point with one on the X axis (previous
+ * way), or forget about it and use the preceding and following ones to draw the polygon.
+ * There is the possibility to use both, we just need to add the method to set
+ * it. Something like SetMissingDataBehaviour(), for example.
+ */
+ function DrawArea()
+ {
+ $incomplete_data_defaults_to_x_axis = FALSE; // TODO: make this configurable
+
+ for ($row = 0, $cnt = 0; $row < $this->num_data_rows; $row++) {
+ $rec = 1; // Skip record #0 (data label)
+
+ if ($this->data_type == 'data-data') // Do we have a value for X?
+ $x_now = $this->data[$row][$rec++]; // Read it, advance record index
+ else
+ $x_now = 0.5 + $cnt++; // Place text-data at X = 0.5, 1.5, 2.5, etc...
+
+ $x_now_pixels = $this->xtr($x_now); // Absolute coordinates
+
+
+ if ($this->x_data_label_pos != 'none') // Draw X Data labels?
+ $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels);
+
+ // Proceed with Y values
+ // Create array of points for imagefilledpolygon()
+ for($idx = 0; $rec < $this->num_recs[$row]; $rec++, $idx++) {
+ if (is_numeric($this->data[$row][$rec])) { // Allow for missing Y data
+ $y_now_pixels = $this->ytr($this->data[$row][$rec]);
+
+ $posarr[$idx][] = $x_now_pixels;
+ $posarr[$idx][] = $y_now_pixels;
+
+ $num_points[$idx] = isset($num_points[$idx]) ? $num_points[$idx]+1 : 1;
+ }
+ // If there's missing data...
+ else {
+ if (isset ($incomplete_data_defaults_to_x_axis)) {
+ $posarr[$idx][] = $x_now_pixels;
+ $posarr[$idx][] = $this->x_axis_y_pixels;
+ $num_points[$idx] = isset($num_points[$idx]) ? $num_points[$idx]+1 : 1;
+ }
+ }
+ }
+ } // end for
+
+ $end = count($posarr);
+ for ($i = 0; $i < $end; $i++) {
+ // Prepend initial points. X = first point's X, Y = x_axis_y_pixels
+ $x = $posarr[$i][0];
+ array_unshift($posarr[$i], $x, $this->x_axis_y_pixels);
+
+ // Append final points. X = last point's X, Y = x_axis_y_pixels
+ $x = $posarr[$i][count($posarr[$i])-2];
+ array_push($posarr[$i], $x, $this->x_axis_y_pixels);
+
+ $num_points[$i] += 2;
+
+ // Draw the poligon
+ ImageFilledPolygon($this->img, $posarr[$i], $num_points[$i], $this->ndx_data_colors[$i]);
+ }
+
+ } // function DrawArea()
+
+
+ /*!
+ * Draw Lines. Supported data-types:
+ * 'data-data',
+ * 'text-data'
+ * NOTE: Please see the note regarding incomplete data sets on DrawArea()
+ */
+ function DrawLines()
+ {
+ // This will tell us if lines have already begun to be drawn.
+ // It is an array to keep separate information for every line, with a single
+ // variable we would sometimes get "undefined offset" errors and no plot...
+ $start_lines = array_fill(0, $this->records_per_group, FALSE);
+
+ if ($this->data_type == 'text-data') {
+ $lastx[0] = $this->xtr(0);
+ $lasty[0] = $this->xtr(0);
+ }
+
+ for ($row = 0, $cnt = 0; $row < $this->num_data_rows; $row++) {
+ $record = 1; // Skip record #0 (data label)
+
+ if ($this->data_type == 'data-data') // Do we have a value for X?
+ $x_now = $this->data[$row][$record++]; // Read it, advance record index
+ else
+ $x_now = 0.5 + $cnt++; // Place text-data at X = 0.5, 1.5, 2.5, etc...
+
+ $x_now_pixels = $this->xtr($x_now); // Absolute coordinates
+
+ if ($this->x_data_label_pos != 'none') // Draw X Data labels?
+ $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels, $row);
+
+ for ($idx = 0; $record < $this->num_recs[$row]; $record++, $idx++) {
+ if (is_numeric($this->data[$row][$record])) { //Allow for missing Y data
+ $y_now_pixels = $this->ytr($this->data[$row][$record]);
+
+ if ($start_lines[$idx] == TRUE) {
+ // Set line width, revert it to normal at the end
+ ImageSetThickness($this->img, $this->line_widths[$idx]);
+
+ if ($this->line_styles[$idx] == 'dashed') {
+ $this->SetDashedStyle($this->ndx_data_colors[$idx]);
+ ImageLine($this->img, $x_now_pixels, $y_now_pixels, $lastx[$idx], $lasty[$idx],
+ IMG_COLOR_STYLED);
+ } else {
+ ImageLine($this->img, $x_now_pixels, $y_now_pixels, $lastx[$idx], $lasty[$idx],
+ $this->ndx_data_colors[$idx]);
+ }
+
+ }
+ $lasty[$idx] = $y_now_pixels;
+ $lastx[$idx] = $x_now_pixels;
+ $start_lines[$idx] = TRUE;
+ }
+ // Y data missing... should we leave a blank or not?
+ else if ($this->draw_broken_lines) {
+ $start_lines[$idx] = FALSE;
+ }
+ } // end for
+ } // end for
+
+ ImageSetThickness($this->img, 1); // Revert to original state for lines to be drawn later.
+ } // function DrawLines()
+
+
+ /*!
+ * Draw lines with error bars - data comes in as
+ * array("label", x, y, error+, error-, y2, error2+, error2-, ...);
+ */
+ function DrawLinesError()
+ {
+ if ($this->data_type != 'data-data-error') {
+ $this->DrawError("DrawLinesError(): Data type '$this->data_type' not supported.");
+ return FALSE;
+ }
+
+ $start_lines = array_fill(0, $this->records_per_group, FALSE);
+
+ for ($row = 0, $cnt = 0; $row < $this->num_data_rows; $row++) {
+ $record = 1; // Skip record #0 (data label)
+
+ $x_now = $this->data[$row][$record++]; // Read X value, advance record index
+
+ $x_now_pixels = $this->xtr($x_now); // Absolute coordinates.
+
+
+ if ($this->x_data_label_pos != 'none') // Draw X Data labels?
+ $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels, $row);
+
+ // Now go for Y, E+, E-
+ for ($idx = 0; $record < $this->num_recs[$row]; $idx++) {
+ // Y
+ $y_now = $this->data[$row][$record++];
+ $y_now_pixels = $this->ytr($y_now);
+
+ if ($start_lines[$idx] == TRUE) {
+ ImageSetThickness($this->img, $this->line_widths[$idx]);
+
+ if ($this->line_styles[$idx] == 'dashed') {
+ $this->SetDashedStyle($this->ndx_data_colors[$idx]);
+ ImageLine($this->img, $x_now_pixels, $y_now_pixels, $lastx[$idx], $lasty[$idx],
+ IMG_COLOR_STYLED);
+ } else {
+ ImageLine($this->img, $x_now_pixels, $y_now_pixels, $lastx[$idx], $lasty[$idx],
+ $this->ndx_data_colors[$idx]);
+ }
+ }
+
+ // Error+
+ $val = $this->data[$row][$record++];
+ $this->DrawYErrorBar($x_now, $y_now, $val, $this->error_bar_shape,
+ $this->ndx_error_bar_colors[$idx]);
+
+ // Error-
+ $val = $this->data[$row][$record++];
+ $this->DrawYErrorBar($x_now, $y_now, -$val, $this->error_bar_shape,
+ $this->ndx_error_bar_colors[$idx]);
+
+ // Update indices:
+ $start_lines[$idx] = TRUE; // Tells us if we already drew the first column of points,
+ // thus having $lastx and $lasty ready for the next column.
+ $lastx[$idx] = $x_now_pixels;
+ $lasty[$idx] = $y_now_pixels;
+ } // end while
+ } // end for
+
+ ImageSetThickness($this->img, 1); // Revert to original state for lines to be drawn later.
+ } // function DrawErrorLines()
+
+
+
+ /*!
+ * This is a mere copy of DrawLines() with one more line drawn for each point
+ */
+ function DrawSquared()
+ {
+ // This will tell us if lines have already begun to be drawn.
+ // It is an array to keep separate information for every line, for with a single
+ // variable we could sometimes get "undefined offset" errors and no plot...
+ $start_lines = array_fill(0, $this->records_per_group, FALSE);
+
+ if ($this->data_type == 'text-data') {
+ $lastx[0] = $this->xtr(0);
+ $lasty[0] = $this->xtr(0);
+ }
+
+ for ($row = 0, $cnt = 0; $row < $this->num_data_rows; $row++) {
+ $record = 1; // Skip record #0 (data label)
+
+ if ($this->data_type == 'data-data') // Do we have a value for X?
+ $x_now = $this->data[$row][$record++]; // Read it, advance record index
+ else
+ $x_now = 0.5 + $cnt++; // Place text-data at X = 0.5, 1.5, 2.5, etc...
+
+ $x_now_pixels = $this->xtr($x_now); // Absolute coordinates
+
+ if ($this->x_data_label_pos != 'none') // Draw X Data labels?
+ $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels); // notice there is no last param.
+
+ // Draw Lines
+ for ($idx = 0; $record < $this->num_recs[$row]; $record++, $idx++) {
+ if (is_numeric($this->data[$row][$record])) { // Allow for missing Y data
+ $y_now_pixels = $this->ytr($this->data[$row][$record]);
+
+ if ($start_lines[$idx] == TRUE) {
+ // Set line width, revert it to normal at the end
+ ImageSetThickness($this->img, $this->line_widths[$idx]);
+
+ if ($this->line_styles[$idx] == 'dashed') {
+ $this->SetDashedStyle($this->ndx_data_colors[$idx]);
+ ImageLine($this->img, $lastx[$idx], $lasty[$idx], $x_now_pixels, $lasty[$idx],
+ IMG_COLOR_STYLED);
+ ImageLine($this->img, $x_now_pixels, $lasty[$idx], $x_now_pixels, $y_now_pixels,
+ IMG_COLOR_STYLED);
+ } else {
+ ImageLine($this->img, $lastx[$idx], $lasty[$idx], $x_now_pixels, $lasty[$idx],
+ $this->ndx_data_colors[$idx]);
+ ImageLine($this->img, $x_now_pixels, $lasty[$idx], $x_now_pixels, $y_now_pixels,
+ $this->ndx_data_colors[$idx]);
+ }
+ }
+ $lastx[$idx] = $x_now_pixels;
+ $lasty[$idx] = $y_now_pixels;
+ $start_lines[$idx] = TRUE;
+ }
+ // Y data missing... should we leave a blank or not?
+ else if ($this->draw_broken_lines) {
+ $start_lines[$idx] = FALSE;
+ }
+ }
+ } // end while
+
+ ImageSetThickness($this->img, 1);
+ } // function DrawSquared()
+
+
+ /*!
+ * Data comes in as array("title", x, y, y2, y3, ...)
+ */
+ function DrawBars()
+ {
+ if ($this->data_type != 'text-data') {
+ $this->DrawError('DrawBars(): Bar plots must be text-data: use function SetDataType("text-data")');
+ return FALSE;
+ }
+
+ for ($row = 0; $row < $this->num_data_rows; $row++) {
+ $record = 1; // Skip record #0 (data label)
+
+ $x_now_pixels = $this->xtr(0.5 + $row); // Place text-data at X = 0.5, 1.5, 2.5, etc...
+
+ if ($this->x_data_label_pos != 'none') // Draw X Data labels?
+ $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels);
+
+ // Draw the bar
+ for ($idx = 0; $record < $this->num_recs[$row]; $record++, $idx++) {
+ if (is_numeric($this->data[$row][$record])) { // Allow for missing Y data
+ $x1 = $x_now_pixels - $this->data_group_space + ($idx * $this->record_bar_width);
+ $x2 = $x1 + ($this->bar_width_adjust * $this->record_bar_width);
+
+ if ($this->data[$row][$record] < $this->x_axis_position) {
+ $y1 = $this->x_axis_y_pixels;
+ $y2 = $this->ytr($this->data[$row][$record]);
+ } else {
+ $y1 = $this->ytr($this->data[$row][$record]);
+ $y2 = $this->x_axis_y_pixels;
+ }
+
+ if ($this->shading) { // Draw the shade?
+ ImageFilledPolygon($this->img, array($x1, $y1,
+ $x1 + $this->shading, $y1 - $this->shading,
+ $x2 + $this->shading, $y1 - $this->shading,
+ $x2 + $this->shading, $y2 - $this->shading,
+ $x2, $y2,
+ $x2, $y1),
+ 6, $this->ndx_data_dark_colors[$idx]);
+ }
+ // Or draw a border?
+ else {
+ ImageRectangle($this->img, $x1, $y1, $x2,$y2, $this->ndx_data_border_colors[$idx]);
+ }
+ // Draw the bar
+ ImageFilledRectangle($this->img, $x1, $y1, $x2, $y2, $this->ndx_data_colors[$idx]);
+ }
+ } // end for
+ } // end for
+ } //function DrawBars
+
+
+ /*!
+ *
+ */
+ function DrawGraph()
+ {
+ if (! $this->img) {
+ $this->DrawError('DrawGraph(): No image resource allocated');
+ return FALSE;
+ }
+
+ if (! is_array($this->data)) {
+ $this->DrawError("DrawGraph(): No array of data in \$data");
+ return FALSE;
+ }
+
+ if (! isset($this->data_limits_done))
+ $this->FindDataLimits(); // Get maxima and minima for scaling
+
+ if ($this->total_records == 0) { // Check for empty data sets
+ $this->DrawError('Empty data set');
+ return FALSE;
+ }
+
+ $this->CalcMargins(); // Calculate margins
+
+ if (! isset($this->plot_area_width)) // Set plot area pixel values (plot_area[])
+ $this->SetPlotAreaPixels();
+
+ if (! isset($this->plot_max_y)) // Set plot area world values (plot_max_x, etc.)
+ $this->SetPlotAreaWorld();
+
+ if ($this->data_type == 'text-data')
+ $this->SetEqualXCoord();
+
+ if ($this->x_data_label_pos != 'none') { // Default: do not draw tick stuff if
+ $this->x_tick_label_pos = 'none'; // there are data labels.
+ $this->x_tick_pos = 'none';
+ }
+
+ $this->PadArrays(); // Pad color and style arrays to fit records per group.
+
+ $this->DrawBackground();
+
+ $this->DrawImageBorder();
+
+ if ($this->draw_plot_area_background)
+ $this->DrawPlotAreaBackground();
+
+ $this->DrawTitle();
+ $this->DrawXTitle();
+ $this->DrawYTitle();
+
+ switch ($this->plot_type) {
+ case 'thinbarline':
+ $this->DrawThinBarLines();
+ break;
+ case 'area':
+ $this->DrawArea();
+ break;
+ case 'squared':
+ $this->DrawSquared();
+ break;
+ case 'lines':
+ if ( $this->data_type == 'data-data-error') {
+ $this->DrawLinesError();
+ } else {
+ $this->DrawLines();
+ }
+ break;
+ case 'linepoints': // FIXME !!! DrawXDataLabel gets called in DrawLines() and DrawDots()
+ if ( $this->data_type == 'data-data-error') {
+ $this->DrawLinesError();
+ $this->DrawDotsError();
+ } else {
+ $this->DrawLines();
+ $this->DrawDots();
+ }
+ break;
+ case 'points';
+ if ( $this->data_type == 'data-data-error') {
+ $this->DrawDotsError();
+ } else {
+ $this->DrawDots();
+ }
+ break;
+ case 'pie':
+ // Pie charts can maximize image space usage.
+ $this->SetPlotAreaPixels($this->safe_margin, $this->title_height,
+ $this->image_width - $this->safe_margin,
+ $this->image_height - $this->safe_margin);
+ $this->DrawPieChart();
+ break;
+ case 'bars':
+ default:
+ $this->plot_type = 'bars'; // Set it if it wasn't already set.
+ $this->DrawYAxis(); // We don't want the grid to overwrite bar charts
+ $this->DrawXAxis(); // so we draw it first. Also, Y must be drawn before X (see DrawYAxis())
+ $this->DrawBars();
+ $this->DrawPlotBorder();
+ break;
+ } // end switch
+
+ if ($this->plot_type != 'pie' && $this->plot_type != 'bars') {
+ $this->DrawYAxis();
+ $this->DrawXAxis();
+ $this->DrawPlotBorder();
+ }
+ if ($this->legend)
+ $this->DrawLegend($this->legend_x_pos, $this->legend_y_pos, '');
+
+ if ($this->print_image)
+ $this->PrintImage();
+
+ } //function DrawGraph()
+
+/////////////////////////////////////////////
+////////////////// DEPRECATED METHODS
+/////////////////////////////////////////////
+
+ /*!
+ * Deprecated, use SetYTickPos()
+ */
+ function SetDrawVertTicks($which_dvt)
+ {
+ if ($which_dvt != 1)
+ $this->SetYTickPos('none');
+ return TRUE;
+ }
+
+ /*!
+ * Deprecated, use SetXTickPos()
+ */
+ function SetDrawHorizTicks($which_dht)
+ {
+ if ($which_dht != 1)
+ $this->SetXTickPos('none');
+ return TRUE;
+ }
+
+ /*!
+ * \deprecated Use SetNumXTicks()
+ */
+ function SetNumHorizTicks($n)
+ {
+ return $this->SetNumXTicks($n);
+ }
+
+ /*!
+ * \deprecated Use SetNumYTicks()
+ */
+ function SetNumVertTicks($n)
+ {
+ return $this->SetNumYTicks($n);
+ }
+
+ /*!
+ * \deprecated Use SetXTickIncrement()
+ */
+ function SetHorizTickIncrement($inc)
+ {
+ return $this->SetXTickIncrement($inc);
+ }
+
+
+ /*!
+ * \deprecated Use SetYTickIncrement()
+ */
+ function SetVertTickIncrement($inc)
+ {
+ return $this->SetYTickIncrement($inc);
+ }
+
+ /*!
+ * \deprecated Use SetYTickPos()
+ */
+ function SetVertTickPosition($which_tp)
+ {
+ return $this->SetYTickPos($which_tp);
+ }
+
+ /*!
+ * \deprecated Use SetXTickPos()
+ */
+ function SetHorizTickPosition($which_tp)
+ {
+ return $this->SetXTickPos($which_tp);
+ }
+
+ /*!
+ * \deprecated Use SetFont()
+ */
+ function SetTitleFontSize($which_size)
+ {
+ return $this->SetFont('title', $which_size);
+ }
+
+ /*!
+ * \deprecated Use SetFont()
+ */
+ function SetAxisFontSize($which_size)
+ {
+ $this->SetFont('x_label', $which_size);
+ $this->SetFont('y_label', $whic_size);
+ }
+
+ /*!
+ * \deprecated Use SetFont()
+ */
+ function SetSmallFontSize($which_size)
+ {
+ return $this->SetFont('generic', $which_size);
+ }
+
+ /*!
+ * \deprecated Use SetFont()
+ */
+ function SetXLabelFontSize($which_size)
+ {
+ return $this->SetFont('x_title', $which_size);
+ }
+
+ /*!
+ * \deprecated Use SetFont()
+ */
+ function SetYLabelFontSize($which_size)
+ {
+ return $this->SetFont('y_title', $which_size);
+ }
+
+ /*!
+ * \deprecated Use SetXTitle()
+ */
+ function SetXLabel($which_xlab)
+ {
+ return $this->SetXTitle($which_xlab);
+ }
+
+ /*!
+ * \deprecated Use SetYTitle()
+ */
+ function SetYLabel($which_ylab)
+ {
+ return $this->SetYTitle($which_ylab);
+ }
+
+ /*!
+ * \deprecated This is now an Internal function - please set width and
+ * height via PHPlot() upon object construction
+ */
+ function SetImageArea($which_iw, $which_ih)
+ {
+ $this->image_width = $which_iw;
+ $this->image_height = $which_ih;
+
+ return TRUE;
+ }
+
+ /*!
+ * \deprecated Use SetXTickLength() and SetYTickLength() instead.
+ */
+ function SetTickLength($which_tl)
+ {
+ $this->SetXTickLength($which_tl);
+ $this->SetYTickLength($which_tl);
+ return TRUE;
+ }
+
+ /*!
+ * \deprecated Use SetYLabelType()
+ */
+ function SetYGridLabelType($which_yglt)
+ {
+ return $this->SetYLabelType($which_yglt);
+ }
+
+ /*!
+ * \deprecated Use SetXLabelType()
+ */
+ function SetXGridLabelType($which_xglt)
+ {
+ return $this->SetXLabelType($which_xglt);
+ }
+ /*!
+ * \deprecated Use SetYTickLabelPos()
+ */
+ function SetYGridLabelPos($which_yglp)
+ {
+ return $this->SetYTickLabelPos($which_yglp);
+ }
+ /*!
+ * \deprecated Use SetXTickLabelPos()
+ */
+ function SetXGridLabelPos($which_xglp)
+ {
+ return $this->SetXTickLabelPos($which_xglp);
+ }
+
+
+ /*!
+ * \deprecated Use SetXtitle()
+ */
+ function SetXTitlePos($xpos)
+ {
+ $this->x_title_pos = $xpos;
+ return TRUE;
+ }
+
+ /*!
+ * \deprecated Use SetYTitle()
+ */
+ function SetYTitlePos($xpos)
+ {
+ $this->y_title_pos = $xpos;
+ return TRUE;
+ }
+
+ /*!
+ * \deprecated Use DrawDots()
+ */
+ function DrawDotSeries()
+ {
+ $this->DrawDots();
+ }
+
+ /*!
+ * \deprecated Use SetXLabelAngle()
+ */
+ function SetXDataLabelAngle($which_xdla)
+ {
+ return $this->SetXLabelAngle($which_xdla);
+ }
+
+ /*!
+ * Draw Labels (not grid labels) on X Axis, following data points. Default position is
+ * down of plot. Care must be taken not to draw these and x_tick_labels as they'd probably overlap.
+ *
+ * \deprecated Use SetXDataLabelPos()
+ */
+ function SetDrawXDataLabels($which_dxdl)
+ {
+ if ($which_dxdl == '1' )
+ $this->SetXDataLabelPos('plotdown');
+ else
+ $this->SetXDataLabelPos('none');
+ }
+
+ /*!
+ * \deprecated This method was intended to improve performance by being specially
+ * written for 'data-data'. However, the improvement didn't pay. Use DrawLines() instead
+ */
+ function DrawLineSeries()
+ {
+ return $this->DrawLines();
+ }
+
+ /*!
+ * \deprecated Calculates maximum X-Axis label height. Now inside _CalcMargins()
+ */
+ function CalcXHeights()
+ {
+ // TTF
+ if ($this->use_ttf) {
+ $xstr = str_repeat('.', $this->max_t);
+ $size = $this->TTFBBoxSize($this->x_label_font['size'], $this->x_label_angle,
+ $this->x_label_font['font'], $xstr);
+ $this->x_tick_label_height = $size[1];
+ }
+ // Fixed font
+ else { // For Non-TTF fonts we can have only angles 0 or 90
+ if ($this->x_label_angle == 90)
+ $this->x_tick_label_height = $this->max_t * $this->x_label_font['width'];
+ else
+ $this->x_tick_label_height = $this->x_label_font['height'];
+ }
+
+ return TRUE;
+ }
+
+
+ /*!
+ * \deprecated Calculates Maximum Y-Axis tick label width. Now inside CalcMargins()
+ */
+ function CalcYWidths()
+ {
+ //the "." is for space. It isn't actually printed
+ $ylab = number_format($this->max_y, $this->y_precision, '.', ', ') . $this->data_units_text . '.';
+
+ // TTF
+ if ($this->use_ttf) {
+ // Maximum Y tick label width
+ $size = $this->TTFBBoxSize($this->y_label_font['size'], 0, $this->y_label_font['font'], $ylab);
+ $this->y_tick_label_width = $size[0];
+
+ }
+ // Fixed font
+ else {
+ // Y axis title width
+ $this->y_tick_label_width = strlen($ylab) * $this->y_label_font['width'];
+ }
+
+ return TRUE;
+ }
+
+ /*!
+ * \deprecated Superfluous.
+ */
+ function DrawLabels()
+ {
+ $this->DrawTitle();
+ $this->DrawXTitle();
+ $this->DrawYTitle();
+ }
+
+ /*!
+ * Set up the image resource 'img'
+ * \deprecated The constructor should init 'img'
+ */
+ function InitImage()
+ {
+ $this->img = ImageCreate($this->image_width, $this->image_height);
+
+ if (! $this->img)
+ $this->PrintError('InitImage(): Could not create image resource');
+ return TRUE;
+ }
+
+ /*!
+ * \deprecated
+ */
+ function SetNewPlotAreaPixels($x1, $y1, $x2, $y2)
+ {
+ //Like in GD 0, 0 is upper left set via pixel Coordinates
+ $this->plot_area = array($x1, $y1, $x2, $y2);
+ $this->plot_area_width = $this->plot_area[2] - $this->plot_area[0];
+ $this->plot_area_height = $this->plot_area[3] - $this->plot_area[1];
+ $this->y_top_margin = $this->plot_area[1];
+
+ if (isset($this->plot_max_x))
+ $this->CalcTranslation();
+
+ return TRUE;
+ }
+
+ /*!
+ * \deprecated Use _SetRGBColor()
+ */
+ function SetColor($which_color)
+ {
+ $this->SetRGBColor($which_color);
+ return TRUE;
+ }
+
+ /*
+ * \deprecated Use SetLineWidths().
+ */
+ function SetLineWidth($which_lw)
+ {
+
+ $this->SetLineWidths($which_lw);
+
+ if (!$this->error_bar_line_width) {
+ $this->SetErrorBarLineWidth($which_lw);
+ }
+ return TRUE;
+ }
+
+ /*!
+ * \deprecated
+ */
+ function DrawDashedLine($x1, $y1, $x2, $y2 , $dash_length, $dash_space, $color)
+ {
+ if ($dash_length)
+ $dashes = array_fill(0, $dash_length, $color);
+ else
+ $dashes = array();
+ if ($dash_space)
+ $spaces = array_fill(0, $dash_space, IMG_COLOR_TRANSPARENT);
+ else
+ $spaces = array();
+
+ $style = array_merge($dashes, $spaces);
+ ImageSetStyle($this->img, $style);
+ ImageLine($this->img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
+ }
+} // class PHPlot
+
+
+
+////////////////////////
+
+
+/*!
+ * Pads an array with another or with itself.
+ * \param arr array Original array (reference)
+ * \param size int Size of the resulting array.
+ * \param arr2 array If specified, array to use for padding. If unspecified, pad with $arr.
+ */
+function array_pad_array(&$arr, $size, $arr2=NULL)
+{
+ if (! is_array($arr2)) {
+ $arr2 = $arr; // copy the original array
+ }
+ while (count($arr) < $size)
+ $arr = array_merge($arr, $arr2); // append until done
+}
+?>
--- /dev/null
+<?php
+/* $Id$
+ *
+ * Copyright (C) 2000 Afan Ottenheimer. Released under
+ * the GPL and PHP licenses as stated in the the README file which
+ * should have been included with this document.
+
+ * This is an subclass for phplot.php and should only be
+ * called after phplot.ini has been called. This extends
+ * phplot by adding additional routines that can be used
+ * to modify the data arrays.
+ *
+ * Data must be a *numerical* array, this is enforced in SetDataValues()
+ */
+
+require_once("phplot.php");
+
+class PHPlot_Data extends PHPlot
+{
+ /*!
+ * Constructor
+ */
+ function PHPlot_Data($which_width=600, $which_height=400, $which_output_file=NULL, $which_input_file=NULL)
+ {
+ if (! isset($this->img)) {
+ $this->PHPlot($which_width, $which_height, $which_output_file, $which_input_file);
+ }
+ }
+
+ /*!
+ * Will scale all data rows
+ * Maybe later I will do a function that only scales some rows
+ * if $even is TRUE, data will be scaled with "even" factors.
+ * \note Original code by Thiemo Nagel
+ */
+ function DoScaleData($even, $show_in_legend)
+ {
+ $offset = 0; // We use this not to read labels in text-data
+
+ if ($this->data_type == 'text-data') {
+ $offset = 1;
+ } elseif ($this->data_type != 'data-data') {
+ $this->DrawError('wrong data type!!');
+ return FALSE;
+ }
+
+ // Determine maxima for each data row in array $max
+ // Put maximum of the maxima in $maxmax
+ $maxmax = 0;
+ for($i=0; $i < $this->num_data_rows; $i++) {
+ $rowsize = count($this->data[$i]);
+ for ($j=$offset; $j < $rowsize; $j++) {
+ if ($this->data[$i][$j] > @ $max[$j])
+ $max[$j] = $this->data[$i][$j];
+ if (@ $max[$j] > $maxmax)
+ $maxmax = $max[$j];
+ }
+ }
+
+ // determine amplification factor $amplify
+ $end = count($max) + $offset;
+ for ($i=$offset; $i < $end; $i++) {
+ if ($max[$i] == 0 || $max[$i] == $maxmax) {
+ $amplify[$i] = 1; // no divide by zero
+ } else {
+ if ($even) {
+ $amp = pow(10,round(log10($maxmax / $max[$i]))-1);
+ if ($amp * $max[$i] * 5 < $maxmax) {
+ $amp *= 5;
+ } elseif ($amp * $max[$i] * 2 < $maxmax) {
+ $amp *= 2;
+ }
+ } else {
+ $amp = $maxmax / $max[$i];
+ $digits = floor(log10($amp));
+ $amp = round($amp/pow(10,$digits-1))*pow(10,$digits-1);
+ }
+ $amplify[$i] = $amp;
+ }
+ if ($amplify[$i] != 1 && $show_in_legend)
+ @ $this->legend[$i] .= "*$amplify[$i]";
+ }
+
+ // Amplify data
+ // On my machine, running 1000 iterations over 1000 rows of 12 elements each,
+ // the for loops were 43.2% faster (MBD)
+ for ($i = 0; $i < $this->num_data_rows; $i++) {
+ $rowsize = count($this->data[$i]);
+ for ($j=$offset; $j < $rowsize; $j++) {
+ $this->data[$i][$j] *= $amplify[$j];
+ }
+ }
+
+ //Re-Scale Vertical Ticks if not already set
+ if ( ! $this->y_tick_increment) {
+ $this->SetYTickIncrement() ;
+ }
+
+ return TRUE;
+ } //function DoScaleData
+
+
+ /*!
+ * Computes a moving average of strength $interval for
+ * data row number $datarow, where 0 denotes the first
+ * row of y-data.
+ *
+ * \param int datarow Index of the row whereupon to make calculations
+ * \param int interval Number of elements to use in average ("strength")
+ * \param bool show Whether to tell about the moving average in the legend.
+ * \param string color Color for the line to be drawn. This color is darkened.
+ * Can be named or #RRGGBB.
+ * \param int width Width of the line to be drawn.
+ *
+ * \note Original idea by Theimo Nagel
+ */
+ function DoMovingAverage($datarow, $interval, $show=TRUE, $color=NULL, $width=NULL)
+ {
+ $off = 1; // Skip record #0 (data label)
+
+ $this->PadArrays();
+
+ if ($interval == 0) {
+ $this->DrawError('DoMovingAverage(): interval can\'t be 0');
+ return FALSE;
+ }
+
+ if ($datarow >= $this->records_per_group) {
+ $this->DrawError("DoMovingAverage(): Data row out of bounds ($datarow >= $this->records_per_group)");
+ return FALSE;
+ }
+
+ if ($this->data_type == 'text-data') {
+ // Ok. No need to set the offset to skip more records.
+ } elseif ($this->data_type == 'data-data') {
+ $off++; // first Y value at $data[][2]
+ } else {
+ $this->DrawError('DoMovingAverage(): wrong data type!!');
+ return FALSE;
+ }
+
+ // Set color:
+ if ($color) {
+ array_push($this->ndx_data_colors, $this->SetIndexDarkColor($color));
+ } else {
+ array_push($this->ndx_data_colors, $this->SetIndexDarkColor($this->data_colors[$datarow]));
+ }
+ // Set line width:
+ if ($width) {
+ array_push($this->line_widths, $width);
+ } else {
+ array_push($this->line_widths, $this->line_widths[$datarow] * 2);
+ }
+ // Show in legend?
+ if ($show) {
+ $this->legend[$this->records_per_group-1] = "(MA[$datarow]:$interval)";
+ }
+
+ $datarow += $off;
+ for ($i = 0; $i < $this->num_data_rows; $i++) {
+ $storage[$i % $interval] = @ $this->data[$i][$datarow];
+ $ma = array_sum($storage);
+ $ma /= count($storage);
+ array_push($this->data[$i], $ma); // Push the data onto the array
+ $this->num_recs[$i]++; // Tell the drawing functions it is there
+ }
+ $this->records_per_group++;
+// $this->FindDataLimits();
+ return TRUE;
+ } //function DoMovingAverage()
+
+
+ /**
+ * Computes an exponentially smoothed moving average.
+ * @param int perc "smoothing percentage"
+ * FIXME!!! I haven't checked this.
+ */
+ function DoExponentialMovingAverage($datarow, $perc, $show_in_legend)
+ {
+ if ($this->data_type == 'text-data') {
+ $datarow++;
+ } elseif ($this->data_type != 'data-data') {
+ $this->DrawError('DoWeightedMovingAverage(): wrong data type!!');
+ return FALSE;
+ }
+
+ if ($show_in_legend) {
+ $this->legend[$datarow] .= " (MA: $interval)";
+ }
+
+ $storage[0] = $this->data[0][$datarow];
+ for ($i=1;$i < $this->num_data_rows; $i++) {
+ $storage[$i] = @ $storage[$i-1] + $perc * ($this->data[$i][$datarow] - $storage[$i-1]);
+ $ma = array_sum($storage);
+ $ma /= count($storage);
+ $this->data[$i][$datarow] = $ma;
+ }
+ return TRUE;
+ } // function DoExponentialMovingAverage()
+
+
+ /*!
+ * Removes the DataSet of number $index
+ */
+ function DoRemoveDataSet($index)
+ {
+ $offset = 1;
+ if ($this->data_type == 'data-data') {
+ $offset++;
+ } elseif ($this->data_type != 'text-data') {
+ $this->DrawError('wrong data type!!');
+ return FALSE;
+ }
+
+ $index += $offset;
+ foreach ($this->data as $key=>$val) {
+ foreach ($val as $key2=>$val2) {
+ if ($key2 >= $index) {
+ if (isset($this->data[$key][$key2+1])) {
+ $this->data[$key][$key2] = $this->data[$key][$key2+1];
+ } else {
+ unset($this->data[$key][$key2]);
+ }
+ }
+ }
+ }
+ } // function DoRemoveDataSet
+
+
+ /*!
+ * Computes row x divided by row y, stores the result in row x
+ * and deletes row y
+ */
+ function DoDivision($x,$y)
+ {
+ $offset = 1;
+ if ($this->data_type == 'data-data') {
+ $offset++;
+ } elseif ($this->data_type != 'text-data') {
+ $this->DrawError('wrong data type!!');
+ return FALSE;
+ }
+
+ $x += $offset; $y += $offset;
+ reset($this->data);
+ while (list($key, $val) = each($this->data)) {
+ if ($this->data[$key][$y] == 0) {
+ $this->data[$key][$x] = 0;
+ } else {
+ $this->data[$key][$x] /= $this->data[$key][$y];
+ }
+ }
+
+ $this->DoRemoveDataSet($y-$offset);
+ } // function DoDivision
+
+} // class PHPlot_Data extends PHPlot
+?>
--- /dev/null
+<?php
+//Looking forward to the day when memory is so
+//plentiful to be able to set gigantic arrays,
+//we offer this taken from PHPLOT.
+$ColorArray = array(
+ "snow" => array(255, 250, 250),
+ "ghost white" => array(248, 248, 255),
+ "GhostWhite" => array(248, 248, 255),
+ "white smoke" => array(245, 245, 245),
+ "WhiteSmoke" => array(245, 245, 245),
+ "gainsboro" => array(220, 220, 220),
+ "floral white" => array(255, 250, 240),
+ "FloralWhite" => array(255, 250, 240),
+ "old lace" => array(253, 245, 230),
+ "OldLace" => array(253, 245, 230),
+ "linen" => array(250, 240, 230),
+ "antique white" => array(250, 235, 215),
+ "AntiqueWhite" => array(250, 235, 215),
+ "papaya whip" => array(255, 239, 213),
+ "PapayaWhip" => array(255, 239, 213),
+ "blanched almond" => array(255, 235, 205),
+ "BlanchedAlmond" => array(255, 235, 205),
+ "bisque" => array(255, 228, 196),
+ "peach puff" => array(255, 218, 185),
+ "PeachPuff" => array(255, 218, 185),
+ "navajo white" => array(255, 222, 173),
+ "NavajoWhite" => array(255, 222, 173),
+ "moccasin" => array(255, 228, 181),
+ "cornsilk" => array(255, 248, 220),
+ "ivory" => array(255, 255, 240),
+ "lemon chiffon" => array(255, 250, 205),
+ "LemonChiffon" => array(255, 250, 205),
+ "seashell" => array(255, 245, 238),
+ "honeydew" => array(240, 255, 240),
+ "mint cream" => array(245, 255, 250),
+ "MintCream" => array(245, 255, 250),
+ "azure" => array(240, 255, 255),
+ "alice blue" => array(240, 248, 255),
+ "AliceBlue" => array(240, 248, 255),
+ "lavender" => array(230, 230, 250),
+ "lavender blush" => array(255, 240, 245),
+ "LavenderBlush" => array(255, 240, 245),
+ "misty rose" => array(255, 228, 225),
+ "MistyRose" => array(255, 228, 225),
+ "white" => array(255, 255, 255),
+ "black" => array( 0, 0, 0),
+ "dark slate gray" => array( 47, 79, 79),
+ "DarkSlateGray" => array( 47, 79, 79),
+ "dark slate grey" => array( 47, 79, 79),
+ "DarkSlateGrey" => array( 47, 79, 79),
+ "dim gray" => array(105, 105, 105),
+ "DimGray" => array(105, 105, 105),
+ "dim grey" => array(105, 105, 105),
+ "DimGrey" => array(105, 105, 105),
+ "slate gray" => array(112, 128, 144),
+ "SlateGray" => array(112, 128, 144),
+ "slate grey" => array(112, 128, 144),
+ "SlateGrey" => array(112, 128, 144),
+ "light slate gray" => array(119, 136, 153),
+ "LightSlateGray" => array(119, 136, 153),
+ "light slate grey" => array(119, 136, 153),
+ "LightSlateGrey" => array(119, 136, 153),
+ "gray" => array(190, 190, 190),
+ "grey" => array(190, 190, 190),
+ "light grey" => array(211, 211, 211),
+ "LightGrey" => array(211, 211, 211),
+ "light gray" => array(211, 211, 211),
+ "LightGray" => array(211, 211, 211),
+ "midnight blue" => array( 25, 25, 112),
+ "MidnightBlue" => array( 25, 25, 112),
+ "navy" => array( 0, 0, 128),
+ "navy blue" => array( 0, 0, 128),
+ "NavyBlue" => array( 0, 0, 128),
+ "cornflower blue" => array(100, 149, 237),
+ "CornflowerBlue" => array(100, 149, 237),
+ "dark slate blue" => array( 72, 61, 139),
+ "DarkSlateBlue" => array( 72, 61, 139),
+ "slate blue" => array(106, 90, 205),
+ "SlateBlue" => array(106, 90, 205),
+ "medium slate blue" => array(123, 104, 238),
+ "MediumSlateBlue" => array(123, 104, 238),
+ "light slate blue" => array(132, 112, 255),
+ "LightSlateBlue" => array(132, 112, 255),
+ "medium blue" => array( 0, 0, 205),
+ "MediumBlue" => array( 0, 0, 205),
+ "royal blue" => array( 65, 105, 225),
+ "RoyalBlue" => array( 65, 105, 225),
+ "blue" => array( 0, 0, 255),
+ "dodger blue" => array( 30, 144, 255),
+ "DodgerBlue" => array( 30, 144, 255),
+ "deep sky blue" => array( 0, 191, 255),
+ "DeepSkyBlue" => array( 0, 191, 255),
+ "sky blue" => array(135, 206, 235),
+ "SkyBlue" => array(135, 206, 235),
+ "light sky blue" => array(135, 206, 250),
+ "LightSkyBlue" => array(135, 206, 250),
+ "steel blue" => array( 70, 130, 180),
+ "SteelBlue" => array( 70, 130, 180),
+ "light steel blue" => array(176, 196, 222),
+ "LightSteelBlue" => array(176, 196, 222),
+ "light blue" => array(173, 216, 230),
+ "LightBlue" => array(173, 216, 230),
+ "powder blue" => array(176, 224, 230),
+ "PowderBlue" => array(176, 224, 230),
+ "pale turquoise" => array(175, 238, 238),
+ "PaleTurquoise" => array(175, 238, 238),
+ "dark turquoise" => array( 0, 206, 209),
+ "DarkTurquoise" => array( 0, 206, 209),
+ "medium turquoise" => array( 72, 209, 204),
+ "MediumTurquoise" => array( 72, 209, 204),
+ "turquoise" => array( 64, 224, 208),
+ "cyan" => array( 0, 255, 255),
+ "light cyan" => array(224, 255, 255),
+ "LightCyan" => array(224, 255, 255),
+ "cadet blue" => array( 95, 158, 160),
+ "CadetBlue" => array( 95, 158, 160),
+ "medium aquamarine" => array(102, 205, 170),
+ "MediumAquamarine" => array(102, 205, 170),
+ "aquamarine" => array(127, 255, 212),
+ "dark green" => array( 0, 100, 0),
+ "DarkGreen" => array( 0, 100, 0),
+ "dark olive green" => array( 85, 107, 47),
+ "DarkOliveGreen" => array( 85, 107, 47),
+ "dark sea green" => array(143, 188, 143),
+ "DarkSeaGreen" => array(143, 188, 143),
+ "sea green" => array( 46, 139, 87),
+ "SeaGreen" => array( 46, 139, 87),
+ "medium sea green" => array( 60, 179, 113),
+ "MediumSeaGreen" => array( 60, 179, 113),
+ "light sea green" => array( 32, 178, 170),
+ "LightSeaGreen" => array( 32, 178, 170),
+ "pale green" => array(152, 251, 152),
+ "PaleGreen" => array(152, 251, 152),
+ "spring green" => array( 0, 255, 127),
+ "SpringGreen" => array( 0, 255, 127),
+ "lawn green" => array(124, 252, 0),
+ "LawnGreen" => array(124, 252, 0),
+ "green" => array( 0, 255, 0),
+ "chartreuse" => array(127, 255, 0),
+ "medium spring green" => array( 0, 250, 154),
+ "MediumSpringGreen" => array( 0, 250, 154),
+ "green yellow" => array(173, 255, 47),
+ "GreenYellow" => array(173, 255, 47),
+ "lime green" => array( 50, 205, 50),
+ "LimeGreen" => array( 50, 205, 50),
+ "yellow green" => array(154, 205, 50),
+ "YellowGreen" => array(154, 205, 50),
+ "forest green" => array( 34, 139, 34),
+ "ForestGreen" => array( 34, 139, 34),
+ "olive drab" => array(107, 142, 35),
+ "OliveDrab" => array(107, 142, 35),
+ "dark khaki" => array(189, 183, 107),
+ "DarkKhaki" => array(189, 183, 107),
+ "khaki" => array(240, 230, 140),
+ "pale goldenrod" => array(238, 232, 170),
+ "PaleGoldenrod" => array(238, 232, 170),
+ "light goldenrod yellow" => array(250, 250, 210),
+ "LightGoldenrodYellow" => array(250, 250, 210),
+ "light yellow" => array(255, 255, 224),
+ "LightYellow" => array(255, 255, 224),
+ "yellow" => array(255, 255, 0),
+ "gold" => array(255, 215, 0),
+ "light goldenrod" => array(238, 221, 130),
+ "LightGoldenrod" => array(238, 221, 130),
+ "goldenrod" => array(218, 165, 32),
+ "dark goldenrod" => array(184, 134, 11),
+ "DarkGoldenrod" => array(184, 134, 11),
+ "rosy brown" => array(188, 143, 143),
+ "RosyBrown" => array(188, 143, 143),
+ "indian red" => array(205, 92, 92),
+ "IndianRed" => array(205, 92, 92),
+ "saddle brown" => array(139, 69, 19),
+ "SaddleBrown" => array(139, 69, 19),
+ "sienna" => array(160, 82, 45),
+ "peru" => array(205, 133, 63),
+ "burlywood" => array(222, 184, 135),
+ "beige" => array(245, 245, 220),
+ "wheat" => array(245, 222, 179),
+ "sandy brown" => array(244, 164, 96),
+ "SandyBrown" => array(244, 164, 96),
+ "tan" => array(210, 180, 140),
+ "chocolate" => array(210, 105, 30),
+ "firebrick" => array(178, 34, 34),
+ "brown" => array(165, 42, 42),
+ "dark salmon" => array(233, 150, 122),
+ "DarkSalmon" => array(233, 150, 122),
+ "salmon" => array(250, 128, 114),
+ "light salmon" => array(255, 160, 122),
+ "LightSalmon" => array(255, 160, 122),
+ "orange" => array(255, 165, 0),
+ "dark orange" => array(255, 140, 0),
+ "DarkOrange" => array(255, 140, 0),
+ "coral" => array(255, 127, 80),
+ "light coral" => array(240, 128, 128),
+ "LightCoral" => array(240, 128, 128),
+ "tomato" => array(255, 99, 71),
+ "orange red" => array(255, 69, 0),
+ "OrangeRed" => array(255, 69, 0),
+ "red" => array(255, 0, 0),
+ "hot pink" => array(255, 105, 180),
+ "HotPink" => array(255, 105, 180),
+ "deep pink" => array(255, 20, 147),
+ "DeepPink" => array(255, 20, 147),
+ "pink" => array(255, 192, 203),
+ "light pink" => array(255, 182, 193),
+ "LightPink" => array(255, 182, 193),
+ "pale violet red" => array(219, 112, 147),
+ "PaleVioletRed" => array(219, 112, 147),
+ "maroon" => array(176, 48, 96),
+ "medium violet red" => array(199, 21, 133),
+ "MediumVioletRed" => array(199, 21, 133),
+ "violet red" => array(208, 32, 144),
+ "VioletRed" => array(208, 32, 144),
+ "magenta" => array(255, 0, 255),
+ "violet" => array(238, 130, 238),
+ "plum" => array(221, 160, 221),
+ "orchid" => array(218, 112, 214),
+ "medium orchid" => array(186, 85, 211),
+ "MediumOrchid" => array(186, 85, 211),
+ "dark orchid" => array(153, 50, 204),
+ "DarkOrchid" => array(153, 50, 204),
+ "dark violet" => array(148, 0, 211),
+ "DarkViolet" => array(148, 0, 211),
+ "blue violet" => array(138, 43, 226),
+ "BlueViolet" => array(138, 43, 226),
+ "purple" => array(160, 32, 240),
+ "medium purple" => array(147, 112, 219),
+ "MediumPurple" => array(147, 112, 219),
+ "thistle" => array(216, 191, 216),
+ "snow1" => array(255, 250, 250),
+ "snow2" => array(238, 233, 233),
+ "snow3" => array(205, 201, 201),
+ "snow4" => array(139, 137, 137),
+ "seashell1" => array(255, 245, 238),
+ "seashell2" => array(238, 229, 222),
+ "seashell3" => array(205, 197, 191),
+ "seashell4" => array(139, 134, 130),
+ "AntiqueWhite1" => array(255, 239, 219),
+ "AntiqueWhite2" => array(238, 223, 204),
+ "AntiqueWhite3" => array(205, 192, 176),
+ "AntiqueWhite4" => array(139, 131, 120),
+ "bisque1" => array(255, 228, 196),
+ "bisque2" => array(238, 213, 183),
+ "bisque3" => array(205, 183, 158),
+ "bisque4" => array(139, 125, 107),
+ "PeachPuff1" => array(255, 218, 185),
+ "PeachPuff2" => array(238, 203, 173),
+ "PeachPuff3" => array(205, 175, 149),
+ "PeachPuff4" => array(139, 119, 101),
+ "NavajoWhite1" => array(255, 222, 173),
+ "NavajoWhite2" => array(238, 207, 161),
+ "NavajoWhite3" => array(205, 179, 139),
+ "NavajoWhite4" => array(139, 121, 94),
+ "LemonChiffon1" => array(255, 250, 205),
+ "LemonChiffon2" => array(238, 233, 191),
+ "LemonChiffon3" => array(205, 201, 165),
+ "LemonChiffon4" => array(139, 137, 112),
+ "cornsilk1" => array(255, 248, 220),
+ "cornsilk2" => array(238, 232, 205),
+ "cornsilk3" => array(205, 200, 177),
+ "cornsilk4" => array(139, 136, 120),
+ "ivory1" => array(255, 255, 240),
+ "ivory2" => array(238, 238, 224),
+ "ivory3" => array(205, 205, 193),
+ "ivory4" => array(139, 139, 131),
+ "honeydew1" => array(240, 255, 240),
+ "honeydew2" => array(224, 238, 224),
+ "honeydew3" => array(193, 205, 193),
+ "honeydew4" => array(131, 139, 131),
+ "LavenderBlush1" => array(255, 240, 245),
+ "LavenderBlush2" => array(238, 224, 229),
+ "LavenderBlush3" => array(205, 193, 197),
+ "LavenderBlush4" => array(139, 131, 134),
+ "MistyRose1" => array(255, 228, 225),
+ "MistyRose2" => array(238, 213, 210),
+ "MistyRose3" => array(205, 183, 181),
+ "MistyRose4" => array(139, 125, 123),
+ "azure1" => array(240, 255, 255),
+ "azure2" => array(224, 238, 238),
+ "azure3" => array(193, 205, 205),
+ "azure4" => array(131, 139, 139),
+ "SlateBlue1" => array(131, 111, 255),
+ "SlateBlue2" => array(122, 103, 238),
+ "SlateBlue3" => array(105, 89, 205),
+ "SlateBlue4" => array( 71, 60, 139),
+ "RoyalBlue1" => array( 72, 118, 255),
+ "RoyalBlue2" => array( 67, 110, 238),
+ "RoyalBlue3" => array( 58, 95, 205),
+ "RoyalBlue4" => array( 39, 64, 139),
+ "blue1" => array( 0, 0, 255),
+ "blue2" => array( 0, 0, 238),
+ "blue3" => array( 0, 0, 205),
+ "blue4" => array( 0, 0, 139),
+ "DodgerBlue1" => array( 30, 144, 255),
+ "DodgerBlue2" => array( 28, 134, 238),
+ "DodgerBlue3" => array( 24, 116, 205),
+ "DodgerBlue4" => array( 16, 78, 139),
+ "SteelBlue1" => array( 99, 184, 255),
+ "SteelBlue2" => array( 92, 172, 238),
+ "SteelBlue3" => array( 79, 148, 205),
+ "SteelBlue4" => array( 54, 100, 139),
+ "DeepSkyBlue1" => array( 0, 191, 255),
+ "DeepSkyBlue2" => array( 0, 178, 238),
+ "DeepSkyBlue3" => array( 0, 154, 205),
+ "DeepSkyBlue4" => array( 0, 104, 139),
+ "SkyBlue1" => array(135, 206, 255),
+ "SkyBlue2" => array(126, 192, 238),
+ "SkyBlue3" => array(108, 166, 205),
+ "SkyBlue4" => array( 74, 112, 139),
+ "LightSkyBlue1" => array(176, 226, 255),
+ "LightSkyBlue2" => array(164, 211, 238),
+ "LightSkyBlue3" => array(141, 182, 205),
+ "LightSkyBlue4" => array( 96, 123, 139),
+ "SlateGray1" => array(198, 226, 255),
+ "SlateGray2" => array(185, 211, 238),
+ "SlateGray3" => array(159, 182, 205),
+ "SlateGray4" => array(108, 123, 139),
+ "LightSteelBlue1" => array(202, 225, 255),
+ "LightSteelBlue2" => array(188, 210, 238),
+ "LightSteelBlue3" => array(162, 181, 205),
+ "LightSteelBlue4" => array(110, 123, 139),
+ "LightBlue1" => array(191, 239, 255),
+ "LightBlue2" => array(178, 223, 238),
+ "LightBlue3" => array(154, 192, 205),
+ "LightBlue4" => array(104, 131, 139),
+ "LightCyan1" => array(224, 255, 255),
+ "LightCyan2" => array(209, 238, 238),
+ "LightCyan3" => array(180, 205, 205),
+ "LightCyan4" => array(122, 139, 139),
+ "PaleTurquoise1" => array(187, 255, 255),
+ "PaleTurquoise2" => array(174, 238, 238),
+ "PaleTurquoise3" => array(150, 205, 205),
+ "PaleTurquoise4" => array(102, 139, 139),
+ "CadetBlue1" => array(152, 245, 255),
+ "CadetBlue2" => array(142, 229, 238),
+ "CadetBlue3" => array(122, 197, 205),
+ "CadetBlue4" => array( 83, 134, 139),
+ "turquoise1" => array( 0, 245, 255),
+ "turquoise2" => array( 0, 229, 238),
+ "turquoise3" => array( 0, 197, 205),
+ "turquoise4" => array( 0, 134, 139),
+ "cyan1" => array( 0, 255, 255),
+ "cyan2" => array( 0, 238, 238),
+ "cyan3" => array( 0, 205, 205),
+ "cyan4" => array( 0, 139, 139),
+ "DarkSlateGray1" => array(151, 255, 255),
+ "DarkSlateGray2" => array(141, 238, 238),
+ "DarkSlateGray3" => array(121, 205, 205),
+ "DarkSlateGray4" => array( 82, 139, 139),
+ "aquamarine1" => array(127, 255, 212),
+ "aquamarine2" => array(118, 238, 198),
+ "aquamarine3" => array(102, 205, 170),
+ "aquamarine4" => array( 69, 139, 116),
+ "DarkSeaGreen1" => array(193, 255, 193),
+ "DarkSeaGreen2" => array(180, 238, 180),
+ "DarkSeaGreen3" => array(155, 205, 155),
+ "DarkSeaGreen4" => array(105, 139, 105),
+ "SeaGreen1" => array( 84, 255, 159),
+ "SeaGreen2" => array( 78, 238, 148),
+ "SeaGreen3" => array( 67, 205, 128),
+ "SeaGreen4" => array( 46, 139, 87),
+ "PaleGreen1" => array(154, 255, 154),
+ "PaleGreen2" => array(144, 238, 144),
+ "PaleGreen3" => array(124, 205, 124),
+ "PaleGreen4" => array( 84, 139, 84),
+ "SpringGreen1" => array( 0, 255, 127),
+ "SpringGreen2" => array( 0, 238, 118),
+ "SpringGreen3" => array( 0, 205, 102),
+ "SpringGreen4" => array( 0, 139, 69),
+ "green1" => array( 0, 255, 0),
+ "green2" => array( 0, 238, 0),
+ "green3" => array( 0, 205, 0),
+ "green4" => array( 0, 139, 0),
+ "chartreuse1" => array(127, 255, 0),
+ "chartreuse2" => array(118, 238, 0),
+ "chartreuse3" => array(102, 205, 0),
+ "chartreuse4" => array( 69, 139, 0),
+ "OliveDrab1" => array(192, 255, 62),
+ "OliveDrab2" => array(179, 238, 58),
+ "OliveDrab3" => array(154, 205, 50),
+ "OliveDrab4" => array(105, 139, 34),
+ "DarkOliveGreen1" => array(202, 255, 112),
+ "DarkOliveGreen2" => array(188, 238, 104),
+ "DarkOliveGreen3" => array(162, 205, 90),
+ "DarkOliveGreen4" => array(110, 139, 61),
+ "khaki1" => array(255, 246, 143),
+ "khaki2" => array(238, 230, 133),
+ "khaki3" => array(205, 198, 115),
+ "khaki4" => array(139, 134, 78),
+ "LightGoldenrod1" => array(255, 236, 139),
+ "LightGoldenrod2" => array(238, 220, 130),
+ "LightGoldenrod3" => array(205, 190, 112),
+ "LightGoldenrod4" => array(139, 129, 76),
+ "LightYellow1" => array(255, 255, 224),
+ "LightYellow2" => array(238, 238, 209),
+ "LightYellow3" => array(205, 205, 180),
+ "LightYellow4" => array(139, 139, 122),
+ "yellow1" => array(255, 255, 0),
+ "yellow2" => array(238, 238, 0),
+ "yellow3" => array(205, 205, 0),
+ "yellow4" => array(139, 139, 0),
+ "gold1" => array(255, 215, 0),
+ "gold2" => array(238, 201, 0),
+ "gold3" => array(205, 173, 0),
+ "gold4" => array(139, 117, 0),
+ "goldenrod1" => array(255, 193, 37),
+ "goldenrod2" => array(238, 180, 34),
+ "goldenrod3" => array(205, 155, 29),
+ "goldenrod4" => array(139, 105, 20),
+ "DarkGoldenrod1" => array(255, 185, 15),
+ "DarkGoldenrod2" => array(238, 173, 14),
+ "DarkGoldenrod3" => array(205, 149, 12),
+ "DarkGoldenrod4" => array(139, 101, 8),
+ "RosyBrown1" => array(255, 193, 193),
+ "RosyBrown2" => array(238, 180, 180),
+ "RosyBrown3" => array(205, 155, 155),
+ "RosyBrown4" => array(139, 105, 105),
+ "IndianRed1" => array(255, 106, 106),
+ "IndianRed2" => array(238, 99, 99),
+ "IndianRed3" => array(205, 85, 85),
+ "IndianRed4" => array(139, 58, 58),
+ "sienna1" => array(255, 130, 71),
+ "sienna2" => array(238, 121, 66),
+ "sienna3" => array(205, 104, 57),
+ "sienna4" => array(139, 71, 38),
+ "burlywood1" => array(255, 211, 155),
+ "burlywood2" => array(238, 197, 145),
+ "burlywood3" => array(205, 170, 125),
+ "burlywood4" => array(139, 115, 85),
+ "wheat1" => array(255, 231, 186),
+ "wheat2" => array(238, 216, 174),
+ "wheat3" => array(205, 186, 150),
+ "wheat4" => array(139, 126, 102),
+ "tan1" => array(255, 165, 79),
+ "tan2" => array(238, 154, 73),
+ "tan3" => array(205, 133, 63),
+ "tan4" => array(139, 90, 43),
+ "chocolate1" => array(255, 127, 36),
+ "chocolate2" => array(238, 118, 33),
+ "chocolate3" => array(205, 102, 29),
+ "chocolate4" => array(139, 69, 19),
+ "firebrick1" => array(255, 48, 48),
+ "firebrick2" => array(238, 44, 44),
+ "firebrick3" => array(205, 38, 38),
+ "firebrick4" => array(139, 26, 26),
+ "brown1" => array(255, 64, 64),
+ "brown2" => array(238, 59, 59),
+ "brown3" => array(205, 51, 51),
+ "brown4" => array(139, 35, 35),
+ "salmon1" => array(255, 140, 105),
+ "salmon2" => array(238, 130, 98),
+ "salmon3" => array(205, 112, 84),
+ "salmon4" => array(139, 76, 57),
+ "LightSalmon1" => array(255, 160, 122),
+ "LightSalmon2" => array(238, 149, 114),
+ "LightSalmon3" => array(205, 129, 98),
+ "LightSalmon4" => array(139, 87, 66),
+ "orange1" => array(255, 165, 0),
+ "orange2" => array(238, 154, 0),
+ "orange3" => array(205, 133, 0),
+ "orange4" => array(139, 90, 0),
+ "DarkOrange1" => array(255, 127, 0),
+ "DarkOrange2" => array(238, 118, 0),
+ "DarkOrange3" => array(205, 102, 0),
+ "DarkOrange4" => array(139, 69, 0),
+ "coral1" => array(255, 114, 86),
+ "coral2" => array(238, 106, 80),
+ "coral3" => array(205, 91, 69),
+ "coral4" => array(139, 62, 47),
+ "tomato1" => array(255, 99, 71),
+ "tomato2" => array(238, 92, 66),
+ "tomato3" => array(205, 79, 57),
+ "tomato4" => array(139, 54, 38),
+ "OrangeRed1" => array(255, 69, 0),
+ "OrangeRed2" => array(238, 64, 0),
+ "OrangeRed3" => array(205, 55, 0),
+ "OrangeRed4" => array(139, 37, 0),
+ "red1" => array(255, 0, 0),
+ "red2" => array(238, 0, 0),
+ "red3" => array(205, 0, 0),
+ "red4" => array(139, 0, 0),
+ "DeepPink1" => array(255, 20, 147),
+ "DeepPink2" => array(238, 18, 137),
+ "DeepPink3" => array(205, 16, 118),
+ "DeepPink4" => array(139, 10, 80),
+ "HotPink1" => array(255, 110, 180),
+ "HotPink2" => array(238, 106, 167),
+ "HotPink3" => array(205, 96, 144),
+ "HotPink4" => array(139, 58, 98),
+ "pink1" => array(255, 181, 197),
+ "pink2" => array(238, 169, 184),
+ "pink3" => array(205, 145, 158),
+ "pink4" => array(139, 99, 108),
+ "LightPink1" => array(255, 174, 185),
+ "LightPink2" => array(238, 162, 173),
+ "LightPink3" => array(205, 140, 149),
+ "LightPink4" => array(139, 95, 101),
+ "PaleVioletRed1" => array(255, 130, 171),
+ "PaleVioletRed2" => array(238, 121, 159),
+ "PaleVioletRed3" => array(205, 104, 137),
+ "PaleVioletRed4" => array(139, 71, 93),
+ "maroon1" => array(255, 52, 179),
+ "maroon2" => array(238, 48, 167),
+ "maroon3" => array(205, 41, 144),
+ "maroon4" => array(139, 28, 98),
+ "VioletRed1" => array(255, 62, 150),
+ "VioletRed2" => array(238, 58, 140),
+ "VioletRed3" => array(205, 50, 120),
+ "VioletRed4" => array(139, 34, 82),
+ "magenta1" => array(255, 0, 255),
+ "magenta2" => array(238, 0, 238),
+ "magenta3" => array(205, 0, 205),
+ "magenta4" => array(139, 0, 139),
+ "orchid1" => array(255, 131, 250),
+ "orchid2" => array(238, 122, 233),
+ "orchid3" => array(205, 105, 201),
+ "orchid4" => array(139, 71, 137),
+ "plum1" => array(255, 187, 255),
+ "plum2" => array(238, 174, 238),
+ "plum3" => array(205, 150, 205),
+ "plum4" => array(139, 102, 139),
+ "MediumOrchid1" => array(224, 102, 255),
+ "MediumOrchid2" => array(209, 95, 238),
+ "MediumOrchid3" => array(180, 82, 205),
+ "MediumOrchid4" => array(122, 55, 139),
+ "DarkOrchid1" => array(191, 62, 255),
+ "DarkOrchid2" => array(178, 58, 238),
+ "DarkOrchid3" => array(154, 50, 205),
+ "DarkOrchid4" => array(104, 34, 139),
+ "purple1" => array(155, 48, 255),
+ "purple2" => array(145, 44, 238),
+ "purple3" => array(125, 38, 205),
+ "purple4" => array( 85, 26, 139),
+ "MediumPurple1" => array(171, 130, 255),
+ "MediumPurple2" => array(159, 121, 238),
+ "MediumPurple3" => array(137, 104, 205),
+ "MediumPurple4" => array( 93, 71, 139),
+ "thistle1" => array(255, 225, 255),
+ "thistle2" => array(238, 210, 238),
+ "thistle3" => array(205, 181, 205),
+ "thistle4" => array(139, 123, 139),
+ "gray0" => array( 0, 0, 0),
+ "grey0" => array( 0, 0, 0),
+ "gray1" => array( 3, 3, 3),
+ "grey1" => array( 3, 3, 3),
+ "gray2" => array( 5, 5, 5),
+ "grey2" => array( 5, 5, 5),
+ "gray3" => array( 8, 8, 8),
+ "grey3" => array( 8, 8, 8),
+ "gray4" => array( 10, 10, 10),
+ "grey4" => array( 10, 10, 10),
+ "gray5" => array( 13, 13, 13),
+ "grey5" => array( 13, 13, 13),
+ "gray6" => array( 15, 15, 15),
+ "grey6" => array( 15, 15, 15),
+ "gray7" => array( 18, 18, 18),
+ "grey7" => array( 18, 18, 18),
+ "gray8" => array( 20, 20, 20),
+ "grey8" => array( 20, 20, 20),
+ "gray9" => array( 23, 23, 23),
+ "grey9" => array( 23, 23, 23),
+ "gray10" => array( 26, 26, 26),
+ "grey10" => array( 26, 26, 26),
+ "gray11" => array( 28, 28, 28),
+ "grey11" => array( 28, 28, 28),
+ "gray12" => array( 31, 31, 31),
+ "grey12" => array( 31, 31, 31),
+ "gray13" => array( 33, 33, 33),
+ "grey13" => array( 33, 33, 33),
+ "gray14" => array( 36, 36, 36),
+ "grey14" => array( 36, 36, 36),
+ "gray15" => array( 38, 38, 38),
+ "grey15" => array( 38, 38, 38),
+ "gray16" => array( 41, 41, 41),
+ "grey16" => array( 41, 41, 41),
+ "gray17" => array( 43, 43, 43),
+ "grey17" => array( 43, 43, 43),
+ "gray18" => array( 46, 46, 46),
+ "grey18" => array( 46, 46, 46),
+ "gray19" => array( 48, 48, 48),
+ "grey19" => array( 48, 48, 48),
+ "gray20" => array( 51, 51, 51),
+ "grey20" => array( 51, 51, 51),
+ "gray21" => array( 54, 54, 54),
+ "grey21" => array( 54, 54, 54),
+ "gray22" => array( 56, 56, 56),
+ "grey22" => array( 56, 56, 56),
+ "gray23" => array( 59, 59, 59),
+ "grey23" => array( 59, 59, 59),
+ "gray24" => array( 61, 61, 61),
+ "grey24" => array( 61, 61, 61),
+ "gray25" => array( 64, 64, 64),
+ "grey25" => array( 64, 64, 64),
+ "gray26" => array( 66, 66, 66),
+ "grey26" => array( 66, 66, 66),
+ "gray27" => array( 69, 69, 69),
+ "grey27" => array( 69, 69, 69),
+ "gray28" => array( 71, 71, 71),
+ "grey28" => array( 71, 71, 71),
+ "gray29" => array( 74, 74, 74),
+ "grey29" => array( 74, 74, 74),
+ "gray30" => array( 77, 77, 77),
+ "grey30" => array( 77, 77, 77),
+ "gray31" => array( 79, 79, 79),
+ "grey31" => array( 79, 79, 79),
+ "gray32" => array( 82, 82, 82),
+ "grey32" => array( 82, 82, 82),
+ "gray33" => array( 84, 84, 84),
+ "grey33" => array( 84, 84, 84),
+ "gray34" => array( 87, 87, 87),
+ "grey34" => array( 87, 87, 87),
+ "gray35" => array( 89, 89, 89),
+ "grey35" => array( 89, 89, 89),
+ "gray36" => array( 92, 92, 92),
+ "grey36" => array( 92, 92, 92),
+ "gray37" => array( 94, 94, 94),
+ "grey37" => array( 94, 94, 94),
+ "gray38" => array( 97, 97, 97),
+ "grey38" => array( 97, 97, 97),
+ "gray39" => array( 99, 99, 99),
+ "grey39" => array( 99, 99, 99),
+ "gray40" => array(102, 102, 102),
+ "grey40" => array(102, 102, 102),
+ "gray41" => array(105, 105, 105),
+ "grey41" => array(105, 105, 105),
+ "gray42" => array(107, 107, 107),
+ "grey42" => array(107, 107, 107),
+ "gray43" => array(110, 110, 110),
+ "grey43" => array(110, 110, 110),
+ "gray44" => array(112, 112, 112),
+ "grey44" => array(112, 112, 112),
+ "gray45" => array(115, 115, 115),
+ "grey45" => array(115, 115, 115),
+ "gray46" => array(117, 117, 117),
+ "grey46" => array(117, 117, 117),
+ "gray47" => array(120, 120, 120),
+ "grey47" => array(120, 120, 120),
+ "gray48" => array(122, 122, 122),
+ "grey48" => array(122, 122, 122),
+ "gray49" => array(125, 125, 125),
+ "grey49" => array(125, 125, 125),
+ "gray50" => array(127, 127, 127),
+ "grey50" => array(127, 127, 127),
+ "gray51" => array(130, 130, 130),
+ "grey51" => array(130, 130, 130),
+ "gray52" => array(133, 133, 133),
+ "grey52" => array(133, 133, 133),
+ "gray53" => array(135, 135, 135),
+ "grey53" => array(135, 135, 135),
+ "gray54" => array(138, 138, 138),
+ "grey54" => array(138, 138, 138),
+ "gray55" => array(140, 140, 140),
+ "grey55" => array(140, 140, 140),
+ "gray56" => array(143, 143, 143),
+ "grey56" => array(143, 143, 143),
+ "gray57" => array(145, 145, 145),
+ "grey57" => array(145, 145, 145),
+ "gray58" => array(148, 148, 148),
+ "grey58" => array(148, 148, 148),
+ "gray59" => array(150, 150, 150),
+ "grey59" => array(150, 150, 150),
+ "gray60" => array(153, 153, 153),
+ "grey60" => array(153, 153, 153),
+ "gray61" => array(156, 156, 156),
+ "grey61" => array(156, 156, 156),
+ "gray62" => array(158, 158, 158),
+ "grey62" => array(158, 158, 158),
+ "gray63" => array(161, 161, 161),
+ "grey63" => array(161, 161, 161),
+ "gray64" => array(163, 163, 163),
+ "grey64" => array(163, 163, 163),
+ "gray65" => array(166, 166, 166),
+ "grey65" => array(166, 166, 166),
+ "gray66" => array(168, 168, 168),
+ "grey66" => array(168, 168, 168),
+ "gray67" => array(171, 171, 171),
+ "grey67" => array(171, 171, 171),
+ "gray68" => array(173, 173, 173),
+ "grey68" => array(173, 173, 173),
+ "gray69" => array(176, 176, 176),
+ "grey69" => array(176, 176, 176),
+ "gray70" => array(179, 179, 179),
+ "grey70" => array(179, 179, 179),
+ "gray71" => array(181, 181, 181),
+ "grey71" => array(181, 181, 181),
+ "gray72" => array(184, 184, 184),
+ "grey72" => array(184, 184, 184),
+ "gray73" => array(186, 186, 186),
+ "grey73" => array(186, 186, 186),
+ "gray74" => array(189, 189, 189),
+ "grey74" => array(189, 189, 189),
+ "gray75" => array(191, 191, 191),
+ "grey75" => array(191, 191, 191),
+ "gray76" => array(194, 194, 194),
+ "grey76" => array(194, 194, 194),
+ "gray77" => array(196, 196, 196),
+ "grey77" => array(196, 196, 196),
+ "gray78" => array(199, 199, 199),
+ "grey78" => array(199, 199, 199),
+ "gray79" => array(201, 201, 201),
+ "grey79" => array(201, 201, 201),
+ "gray80" => array(204, 204, 204),
+ "grey80" => array(204, 204, 204),
+ "gray81" => array(207, 207, 207),
+ "grey81" => array(207, 207, 207),
+ "gray82" => array(209, 209, 209),
+ "grey82" => array(209, 209, 209),
+ "gray83" => array(212, 212, 212),
+ "grey83" => array(212, 212, 212),
+ "gray84" => array(214, 214, 214),
+ "grey84" => array(214, 214, 214),
+ "gray85" => array(217, 217, 217),
+ "grey85" => array(217, 217, 217),
+ "gray86" => array(219, 219, 219),
+ "grey86" => array(219, 219, 219),
+ "gray87" => array(222, 222, 222),
+ "grey87" => array(222, 222, 222),
+ "gray88" => array(224, 224, 224),
+ "grey88" => array(224, 224, 224),
+ "gray89" => array(227, 227, 227),
+ "grey89" => array(227, 227, 227),
+ "gray90" => array(229, 229, 229),
+ "grey90" => array(229, 229, 229),
+ "gray91" => array(232, 232, 232),
+ "grey91" => array(232, 232, 232),
+ "gray92" => array(235, 235, 235),
+ "grey92" => array(235, 235, 235),
+ "gray93" => array(237, 237, 237),
+ "grey93" => array(237, 237, 237),
+ "gray94" => array(240, 240, 240),
+ "grey94" => array(240, 240, 240),
+ "gray95" => array(242, 242, 242),
+ "grey95" => array(242, 242, 242),
+ "gray96" => array(245, 245, 245),
+ "grey96" => array(245, 245, 245),
+ "gray97" => array(247, 247, 247),
+ "grey97" => array(247, 247, 247),
+ "gray98" => array(250, 250, 250),
+ "grey98" => array(250, 250, 250),
+ "gray99" => array(252, 252, 252),
+ "grey99" => array(252, 252, 252),
+ "gray100" => array(255, 255, 255)
+);
+?>
--- /dev/null
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
--- /dev/null
+<?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.6
+ * @copyright Copyright: 2001-2004 ispi of Lincoln, Inc.
+ * @author Andrei Zmievski <andrei@php.net>
+ * @access public
+ * @package Smarty
+ */
+
+/* $Id$ */
+
+/**
+ * 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 ( $line{0} == '[' && preg_match('!^\[(.*?)\]!', $line, $match) ) {
+ /* section found */
+ if ($match[1]{0} == '.') {
+ /* 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 ($var_name{0} == '.') {
+ 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);
+ }
+ /**#@-*/
+}
+
+?>
--- /dev/null
+<?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-2004 ispi of Lincoln, Inc.
+ * @author Monte Ohrt <monte@ispi.net>
+ * @author Andrei Zmievski <andrei@php.net>
+ * @package Smarty
+ * @version 2.6.6
+ */
+
+/* $Id$ */
+
+/**
+ * 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'),
+ '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.6';
+
+ /**
+ * 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;
+ }
+ if(isset($this->_tpl_vars[$name])) {
+ return $this->_tpl_vars[$name];
+ }
+ }
+
+ /**
+ * 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];
+ }
+ }
+
+ /**
+ * 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 {
+ $_cookie_var = $this->request_use_auto_globals ? $_COOKIE['SMARTY_DEBUG'] : $GLOBALS['HTTP_COOKIE_VARS']['SMARTY_DEBUG'];
+ $this->debugging = $_cookie_var ? true : false;
+ }
+ }
+
+ 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 (($string{0} == "'" || $string{0} == '"') &&
+ $string{strlen($string)-1} == $string{0})
+ return substr($string, 1, -1);
+ else
+ return $string;
+ }
+
+
+ /**
+ * read in a file from line $start for $lines.
+ * read the entire file if $start and $lines are null.
+ *
+ * @param string $filename
+ * @param integer $start
+ * @param integer $lines
+ * @return string
+ */
+ function _read_file($filename)
+ {
+ if ( file_exists($filename) && ($fd = @fopen($filename, 'rb')) ) {
+ $contents = ($size = filesize($filename)) ? fread($fd, $size) : '';
+ 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: */
+
+?>
--- /dev/null
+<?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@ispi.net>
+ * @author Andrei Zmievski <andrei@php.net>
+ * @version 2.6.6
+ * @copyright 2001-2004 ispi of Lincoln, Inc.
+ * @package Smarty
+ */
+
+/* $Id$ */
+
+/**
+ * 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*[\"\']?php[\"\']?)~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;
+ }
+
+ $compiled_content = '';
+
+ /* 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]);
+ }
+ $compiled_content .= $text_blocks[$i].$compiled_tags[$i];
+ }
+ $compiled_content .= $text_blocks[$i];
+
+ /* Reformat data between 'strip' and '/strip' tags, removing spaces, tabs and newlines. */
+ if (preg_match_all("~{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}~s", $compiled_content, $_match)) {
+ $strip_tags = $_match[0];
+ $strip_tags_modified = preg_replace("~{$ldq}/?strip{$rdq}|[\t ]+$|^[\t ]+~m", '', $strip_tags);
+ $strip_tags_modified = preg_replace('~[\r\n]+~m', '', $strip_tags_modified);
+ for ($i = 0, $for_max = count($strip_tags); $i < $for_max; $i++)
+ $compiled_content = preg_replace("~{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}~s",
+ $this->_quote_replace($strip_tags_modified[$i]),
+ $compiled_content, 1);
+ }
+
+ // remove \n from the end of the file, if any
+ if (($_len=strlen($compiled_content)) && ($compiled_content{$_len - 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;
+ }
+
+ // remove unnecessary close/open tags
+ $compiled_content = preg_replace('~\?>\n?<\?php~', '', $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', '$plugin_info[0]', $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 ($template_tag{0} == '*' && $template_tag{strlen($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, $this->_parse_attrs($tag_args));
+ if(isset($_tag_attrs['assign'])) {
+ return "<?php \$this->assign('" . $this->_dequote($_tag_attrs['assign']) . "', $_return ); ?>\n";
+ } else {
+ 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; unset(\$_from); else: ?>";
+
+ case '/foreach':
+ $_open_tag = $this->_pop_tag('foreach');
+ if ($_open_tag == 'foreachelse')
+ return "<?php endif; ?>";
+ else
+ return "<?php endforeach; unset(\$_from); endif; ?>";
+ break;
+
+ case 'strip':
+ case '/strip':
+ if ($tag_command{0}=='/') {
+ $this->_pop_tag('strip');
+ if (--$this->_strip_depth==0) { /* outermost closing {/strip} */
+ $this->_additional_newline = "\n";
+ return $this->left_delimiter.$tag_command.$this->right_delimiter;
+ }
+ } else {
+ $this->_push_tag('strip');
+ if ($this->_strip_depth++==0) { /* outermost opening {strip} */
+ $this->_additional_newline = "";
+ return $this->left_delimiter.$tag_command.$this->right_delimiter;
+ }
+ }
+ 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 ($tag_command{0} == '/') {
+ $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);
+ $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 .= $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], null, $this, $_block_repeat=true);';
+ $output .= 'while ($_block_repeat) { ob_start(); ?>';
+ } else {
+ $output = '<?php $this->_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], $this->_block_content, $this, $_block_repeat=false)';
+ if ($tag_modifier != '') {
+ $this->_parse_modifiers($_out_tag_text, $tag_modifier);
+ }
+ $output .= '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);
+ $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 ($tag_command{0} == '/') {
+ $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 .= "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], null, \$this, \$_block_repeat=true); ";
+ $prefix .= "while (\$_block_repeat) { ob_start();";
+ $return = null;
+ $postfix = '';
+ } else {
+ $prefix = "\$this->_obj_block_content = ob_get_contents(); ob_end_clean(); ";
+ $return = "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], \$this->_obj_block_content, \$this, \$_block_repeat=false)";
+ $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)) {
+ $this->_syntax_error("missing insert 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 ';
+ if (isset($name)) {
+ $foreach_props = "\$this->_foreach[$name]";
+ $output .= "if (isset(\$this->_foreach[$name])) unset(\$this->_foreach[$name]);\n";
+ $output .= "{$foreach_props}['total'] = count(\$_from = (array)$from);\n";
+ $output .= "{$foreach_props}['show'] = {$foreach_props}['total'] > 0;\n";
+ $output .= "if ({$foreach_props}['show']):\n";
+ $output .= "{$foreach_props}['iteration'] = 0;\n";
+ $output .= " foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
+ $output .= " {$foreach_props}['iteration']++;\n";
+ $output .= " {$foreach_props}['first'] = ({$foreach_props}['iteration'] == 1);\n";
+ $output .= " {$foreach_props}['last'] = ({$foreach_props}['iteration'] == {$foreach_props}['total']);\n";
+ } else {
+ $output .= "if (count(\$_from = (array)$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];
+
+ // 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->_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('"' . $val .'"');
+ }
+ 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];
+ rsort($_match);
+ reset($_match);
+ foreach($_match as $_var) {
+ $var_expr = str_replace ($_var, '".(' . $this->_parse_var(str_replace('`','',$_var)) . ')."', $var_expr);
+ }
+ $_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($var_expr{0}))
+ $_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($var_expr{0})) {
+ // 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 ($_index{0} == '[') {
+ $_index = substr($_index, 1, -1);
+ if (is_numeric($_index)) {
+ $_output .= "[$_index]";
+ } elseif ($_index{0} == '$') {
+ 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 ($_index{0} == '.') {
+ if ($_index{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 ($_index{2} == '$') {
+ 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 ($_index{0} == '(') {
+ $_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 ($_modifier_name{0} == '@') {
+ $_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($output{0} == '$') {
+ $output = '@' . $output;
+ }
+ if(isset($_modifier_args[0]) && $_modifier_args[0]{0} == '$') {
+ $_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 ($_index{0} != '.' && $_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':
+ case 'section':
+ array_shift($indexes);
+ $_var = $this->_parse_var_props(substr($indexes[0], 1));
+ if ($_ref == 'foreach')
+ $compiled_ref = "\$this->_foreach[$_var]";
+ else
+ $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);
+ $_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
+ . '}\';}';
+ 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++)
+ . '}\';}';
+ }
+
+
+ /**
+ * 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: */
+
+?>
--- /dev/null
+{* Smarty *}
+
+{* debug.tpl, last updated version 2.0.1 *}
+
+{assign_debug_info}
+
+{if isset($_smarty_debug_output) and $_smarty_debug_output eq "html"}
+ <table border=0 width=100%>
+ <tr bgcolor=#cccccc><th colspan=2>Smarty Debug Console</th></tr>
+ <tr bgcolor=#cccccc><td colspan=2><b>included templates & config files (load time in seconds):</b></td></tr>
+ {section name=templates loop=$_debug_tpls}
+ <tr bgcolor={if %templates.index% is even}#eeeeee{else}#fafafa{/if}><td colspan=2><tt>{section name=indent loop=$_debug_tpls[templates].depth} {/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)} <font size=-1><i>({$_debug_tpls[templates].exec_time|string_format:"%.5f"}){if %templates.index% eq 0} (total){/if}</i></font>{/if}</tt></td></tr>
+ {sectionelse}
+ <tr bgcolor=#eeeeee><td colspan=2><tt><i>no templates included</i></tt></td></tr>
+ {/section}
+ <tr bgcolor=#cccccc><td colspan=2><b>assigned template variables:</b></td></tr>
+ {section name=vars loop=$_debug_keys}
+ <tr bgcolor={if %vars.index% is even}#eeeeee{else}#fafafa{/if}><td valign=top><tt><font color=blue>{ldelim}${$_debug_keys[vars]}{rdelim}</font></tt></td><td nowrap><tt><font color=green>{$_debug_vals[vars]|@debug_print_var}</font></tt></td></tr>
+ {sectionelse}
+ <tr bgcolor=#eeeeee><td colspan=2><tt><i>no template variables assigned</i></tt></td></tr>
+ {/section}
+ <tr bgcolor=#cccccc><td colspan=2><b>assigned config file variables (outer template scope):</b></td></tr>
+ {section name=config_vars loop=$_debug_config_keys}
+ <tr bgcolor={if %config_vars.index% is even}#eeeeee{else}#fafafa{/if}><td valign=top><tt><font color=maroon>{ldelim}#{$_debug_config_keys[config_vars]}#{rdelim}</font></tt></td><td><tt><font color=green>{$_debug_config_vals[config_vars]|@debug_print_var}</font></tt></td></tr>
+ {sectionelse}
+ <tr bgcolor=#eeeeee><td colspan=2><tt><i>no config vars assigned</i></tt></td></tr>
+ {/section}
+ </table>
+</BODY></HTML>
+{else}
+<SCRIPT language=javascript>
+ 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("<HTML><HEAD><TITLE>Smarty Debug Console_"+self.name+"</TITLE></HEAD><BODY bgcolor=#ffffff>");
+ _smarty_console.document.write("<table border=0 width=100%>");
+ _smarty_console.document.write("<tr bgcolor=#cccccc><th colspan=2>Smarty Debug Console</th></tr>");
+ _smarty_console.document.write("<tr bgcolor=#cccccc><td colspan=2><b>included templates & config files (load time in seconds):</b></td></tr>");
+ {section name=templates loop=$_debug_tpls}
+ _smarty_console.document.write("<tr bgcolor={if %templates.index% is even}#eeeeee{else}#fafafa{/if}><td colspan=2><tt>{section name=indent loop=$_debug_tpls[templates].depth} {/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|escape:javascript}</font>{if isset($_debug_tpls[templates].exec_time)} <font size=-1><i>({$_debug_tpls[templates].exec_time|string_format:"%.5f"}){if %templates.index% eq 0} (total){/if}</i></font>{/if}</tt></td></tr>");
+ {sectionelse}
+ _smarty_console.document.write("<tr bgcolor=#eeeeee><td colspan=2><tt><i>no templates included</i></tt></td></tr>");
+ {/section}
+ _smarty_console.document.write("<tr bgcolor=#cccccc><td colspan=2><b>assigned template variables:</b></td></tr>");
+ {section name=vars loop=$_debug_keys}
+ _smarty_console.document.write("<tr bgcolor={if %vars.index% is even}#eeeeee{else}#fafafa{/if}><td valign=top><tt><font color=blue>{ldelim}${$_debug_keys[vars]}{rdelim}</font></tt></td><td nowrap><tt><font color=green>{$_debug_vals[vars]|@debug_print_var|escape:javascript}</font></tt></td></tr>");
+ {sectionelse}
+ _smarty_console.document.write("<tr bgcolor=#eeeeee><td colspan=2><tt><i>no template variables assigned</i></tt></td></tr>");
+ {/section}
+ _smarty_console.document.write("<tr bgcolor=#cccccc><td colspan=2><b>assigned config file variables (outer template scope):</b></td></tr>");
+ {section name=config_vars loop=$_debug_config_keys}
+ _smarty_console.document.write("<tr bgcolor={if %config_vars.index% is even}#eeeeee{else}#fafafa{/if}><td valign=top><tt><font color=maroon>{ldelim}#{$_debug_config_keys[config_vars]}#{rdelim}</font></tt></td><td><tt><font color=green>{$_debug_config_vals[config_vars]|@debug_print_var|escape:javascript}</font></tt></td></tr>");
+ {sectionelse}
+ _smarty_console.document.write("<tr bgcolor=#eeeeee><td colspan=2><tt><i>no config vars assigned</i></tt></td></tr>");
+ {/section}
+ _smarty_console.document.write("</table>");
+ _smarty_console.document.write("</BODY></HTML>");
+ _smarty_console.document.close();
+</SCRIPT>
+{/if}
--- /dev/null
+<?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: */
+
+?>
--- /dev/null
+<?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: */
+
+?>
--- /dev/null
+<?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 = ($_dir{0}=='/') ? '/' : 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: */
+
+?>
--- /dev/null
+<?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[] = dirname(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: */
+
+?>
--- /dev/null
+<?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: */
+
+?>
--- /dev/null
+<?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: */
+
+?>
--- /dev/null
+<?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: */
+
+?>
--- /dev/null
+<?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 &&
+ $_rp{strlen($_cd)} == DIRECTORY_SEPARATOR ) {
+ return true;
+ }
+ }
+ }
+ if (!empty($smarty->secure_dir)) {
+ foreach ((array)$smarty->secure_dir as $curr_dir) {
+ if ( ($_cd = realpath($curr_dir)) !== false &&
+ strncmp($_rp, $_cd, strlen($_cd)) == 0 &&
+ $_rp{strlen($_cd)} == 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: */
+
+?>
--- /dev/null
+<?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
+ && $_rp{strlen($_cd)} == 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: */
+
+?>
--- /dev/null
+<?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: */
+
+?>
--- /dev/null
+<?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: */
+
+?>
--- /dev/null
+<?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'] = str_replace($cached_inserts[$i], $replace, $params['results']);
+ 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: */
+
+?>
--- /dev/null
+<?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_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;
+}
+
+?>
--- /dev/null
+<?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;
+ }
+
+ $cache_split = explode("\n", $params['results'], 2);
+ $cache_header = $cache_split[0];
+
+ $_cache_info = unserialize($cache_header);
+
+ 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;
+ }
+ }
+ }
+ }
+
+ foreach ($_cache_info['cache_serials'] as $_include_file_path=>$_cache_serial) {
+ if (empty($smarty->_cache_serials[$_include_file_path])) {
+ $smarty->_include($_include_file_path, true);
+ }
+
+ if ($smarty->_cache_serials[$_include_file_path] != $_cache_serial) {
+ /* regenerate */
+ return false;
+ }
+ }
+ $params['results'] = $cache_split[1];
+ $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: */
+
+?>
--- /dev/null
+<?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: */
+
+?>
--- /dev/null
+<?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']
+ );
+ require_once(SMARTY_CORE_DIR . 'core.rmdir.php');
+ 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: */
+
+?>
--- /dev/null
+<?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: */
+
+?>
--- /dev/null
+<?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: */
+
+?>
--- /dev/null
+<?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
+ $params['results'] = serialize($smarty->_cache_info)."\n".$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: */
+
+?>
--- /dev/null
+<?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+)\}\';\}';
+ $_tag_end = 'if \(\$this->caching && \!\$this->_cache_including\) \{ echo \'\{/nocache\:(\\2)#(\\3)\}\';\}';
+
+ 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]);
+ array_shift($tokens); /* remove the opening <.?.php */
+ 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;
+}
+
+
+?>
--- /dev/null
+<?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: */
+
+?>
--- /dev/null
+<?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);
+
+ // Delete the file if it allready exists (this is needed on Win,
+ // because it cannot overwrite files with rename()
+ if (file_exists($params['filename'])) {
+ @unlink($params['filename']);
+ }
+ @rename($_tmp_file, $params['filename']);
+ @chmod($params['filename'], $smarty->_file_perms);
+
+ return true;
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+<?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>
+ * @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: */
+
+?>
--- /dev/null
+<?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)
+ * @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: */
+
+?>
--- /dev/null
+<?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>
+ * @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: */
+
+?>
--- /dev/null
+<?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)
+ * @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: */
+
+?>
--- /dev/null
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {counter} function plugin
+ *
+ * Type: function<br>
+ * Name: counter<br>
+ * Purpose: print out a counter value
+ * @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: */
+
+?>
--- /dev/null
+<?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@ispi.net>
+ * @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: */
+
+?>
--- /dev/null
+<?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@ispi.net>
+ * @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: */
+
+?>
--- /dev/null
+<?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)
+ * @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: */
+
+?>
--- /dev/null
+<?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)
+ * @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: */
+
+?>
--- /dev/null
+<?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
+ * - 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@ispi.net>
+ * @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 (is_array($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;
+}
+
+?>
--- /dev/null
+<?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)
+ * - border = border width (optional, default 0)
+ * - height = image height (optional, default actual height)
+ * - image =image width (optional, default actual width)
+ * - basedir = base directory for absolute paths, default
+ * is environment variable DOCUMENT_ROOT
+ *
+ * Examples: {html_image file="images/masthead.gif"}
+ * Output: <img src="images/masthead.gif" border=0 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@ispi.net>
+ * @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 = '';
+ $border = 0;
+ $height = '';
+ $width = '';
+ $extra = '';
+ $prefix = '';
+ $suffix = '';
+ $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 'border':
+ case 'height':
+ case 'width':
+ case 'dpi':
+ 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 ($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);
+
+ } elseif (!$_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(!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="'.$file.'" alt="'.$alt.'" border="'.$border.'" width="'.$width.'" height="'.$height.'"'.$extra.' />' . $suffix;
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+<?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)
+ * @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 (is_array($options)) {
+
+ foreach ($options as $_key=>$_val)
+ $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected);
+
+ } else {
+
+ foreach ((array)$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: */
+
+?>
--- /dev/null
+<?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
+ * - 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@ispi.net>
+ * @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;
+ $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':
+ $$_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) && is_array($options)) {
+
+ foreach ((array)$options as $_key=>$_val)
+ $_html_result[] = smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
+
+ } else {
+
+ foreach ((array)$values as $_i=>$_key) {
+ $_val = isset($output[$_i]) ? $output[$_i] : '';
+ $_html_result[] = smarty_function_html_radios_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_radios_output($name, $value, $output, $selected, $extra, $separator, $labels) {
+ $_output = '';
+ if ($labels) $_output .= '<label>';
+ $_output .= '<input type="radio" name="'
+ . smarty_function_escape_special_chars($name) . '" value="'
+ . smarty_function_escape_special_chars($value) . '"';
+
+ if ($value==$selected) {
+ $_output .= ' checked="checked"';
+ }
+ $_output .= $extra . ' />' . $output;
+ if ($labels) $_output .= '</label>';
+ $_output .= $separator;
+
+ return $_output;
+}
+
+?>
--- /dev/null
+<?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 suppport negative timestamps, force year
+ * dropdown to include given date unless explicitly set (Monte)
+ * @link http://smarty.php.net/manual/en/language.function.html.select.date.php {html_select_date}
+ * (Smarty online manual)
+ * @version 1.3.2
+ * @author Andrei Zmievski
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_html_select_date($params, &$smarty)
+{
+ 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;
+
+ 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:
+ $smarty->trigger_error("[html_select_date] unknown parameter $_key", E_USER_WARNING);
+
+ }
+ }
+
+ 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)) {
+ // 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 = "";
+
+ if ($display_months) {
+ $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 .= '>'."\n";
+
+ $month_result .= smarty_function_html_options(array('output' => $month_names,
+ 'values' => $month_values,
+ 'selected' => $a=$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) {
+ $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 .= '>'."\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) {
+ 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 .= '>'."\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 != 2) {
+ $html_result .= $field_separator;
+ }
+ }
+
+ return $html_result;
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+<?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)
+ * @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: */
+
+?>
--- /dev/null
+<?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
+ * - rows = number of rows
+ * - table_attr = table attributes
+ * - tr_attr = table row attributes (arrays are cycled)
+ * - td_attr = table cell attributes (arrays are cycled)
+ * - trailpad = value to pad trailing cells with
+ * - 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=4 tr_attr=$colors}
+ * </pre>
+ * @author Monte Ohrt <monte@ispi.net>
+ * @version 1.0
+ * @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 = '';
+ $td_attr = '';
+ $cols = 3;
+ $rows = 3;
+ $trailpad = ' ';
+ $vdir = 'down';
+ $hdir = 'right';
+ $inner = 'cols';
+
+ 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':
+ case 'rows':
+ $$_key = (int)$_value;
+ break;
+
+ case 'table_attr':
+ case 'trailpad':
+ case 'hdir':
+ case 'vdir':
+ case 'inner':
+ $$_key = (string)$_value;
+ break;
+
+ case 'tr_attr':
+ case 'td_attr':
+ $$_key = $_value;
+ break;
+ }
+ }
+
+ $loop_count = count($loop);
+ if (empty($params['rows'])) {
+ /* no rows specified */
+ $rows = ceil($loop_count/$cols);
+ } elseif (empty($params['cols'])) {
+ if (!empty($params['rows'])) {
+ /* no cols specified, but rows */
+ $cols = ceil($loop_count/$rows);
+ }
+ }
+
+ $output = "<table $table_attr>\n";
+
+ for ($r=0; $r<$rows; $r++) {
+ $output .= "<tr" . smarty_function_html_table_cycle('tr', $tr_attr, $r) . ">\n";
+ $rx = ($vdir == 'down') ? $r*$cols : ($rows-1-$r)*$cols;
+
+ for ($c=0; $c<$cols; $c++) {
+ $x = ($hdir == 'right') ? $rx+$c : $rx+$cols-1-$c;
+ if ($inner!='cols') {
+ /* shuffle x to loop over rows*/
+ $x = floor($x/$cols) + ($x%$cols)*$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 .= "</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: */
+
+?>
--- /dev/null
+<?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
+ * * 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@ispi.net>
+ * @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.
+ $mail_parms = array();
+ foreach ($params as $var=>$value) {
+ switch ($var) {
+ case 'cc':
+ case 'bcc':
+ case 'followupto':
+ if (!empty($value))
+ $mail_parms[] = $var.'='.str_replace('%40','@',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','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 == '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 = "mailto:";
+ return '<a href="'.$mailto.$address_encode.'" '.$extra.'>'.$text_encode.'</a>';
+
+ } else {
+ // no encoding
+ return '<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>';
+
+ }
+
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+<?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)
+ * @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-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[2] as $curr_var) {
+ if (!in_array($curr_var,array_keys($params)) && !in_array($curr_var, $allowed_funcs)) {
+ $smarty->trigger_error("math: parameter $curr_var not passed as argument");
+ 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/",$val, $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: */
+
+?>
--- /dev/null
+<?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)
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_popup($params, &$smarty)
+{
+ $append = '';
+ foreach ($params as $_key=>$_value) {
+ switch ($_key) {
+ case 'text':
+ case 'trigger':
+ $$_key = (string)$_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 'inarray':
+ case 'caparray':
+ case 'capicon':
+ case 'background':
+ case 'frame':
+ case 'function':
+ $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':
+ 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 . ');" onmouseout="nd();"';
+
+ return $retval;
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+<?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)
+ * @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: */
+
+?>
--- /dev/null
+<?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)
+ * @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+\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(!preg_match('!\d!',$string[0]) || $_uc_digits)
+ return ucfirst($string[0]);
+ else
+ return $string[0];
+}
+
+
+?>
--- /dev/null
+<?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@ispi.net>
+ * @version 1.0
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_cat($string, $cat)
+{
+ return $string . $cat;
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+<?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)
+ * @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: */
+
+?>
--- /dev/null
+<?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)
+ * @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: */
+
+?>
--- /dev/null
+<?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)
+ * @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: */
+
+?>
--- /dev/null
+<?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)
+ * @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: */
+
+?>
--- /dev/null
+<?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)
+ * @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=null)
+{
+ if (substr(PHP_OS,0,3) == 'WIN') {
+ $_win_from = array ('%e', '%T', '%D');
+ $_win_to = array ('%#d', '%H:%M:%S', '%m/%d/%y');
+ $format = str_replace($_win_from, $_win_to, $format);
+ }
+ if($string != '') {
+ return strftime($format, smarty_make_timestamp($string));
+ } elseif (isset($default_date) && $default_date != '') {
+ return strftime($format, smarty_make_timestamp($default_date));
+ } else {
+ return;
+ }
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+<?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)
+ * @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>');
+ if (is_array($var)) {
+ $results = "<b>Array (".count($var).")</b>";
+ foreach ($var as $curr_key => $curr_val) {
+ $return = smarty_modifier_debug_print_var($curr_val, $depth+1, $length);
+ $results .= "<br>".str_repeat(' ', $depth*2)."<b>".strtr($curr_key, $_replace)."</b> => $return";
+ }
+ } else if (is_object($var)) {
+ $object_vars = get_object_vars($var);
+ $results = "<b>".get_class($var)." Object (".count($object_vars).")</b>";
+ foreach ($object_vars as $curr_key => $curr_val) {
+ $return = smarty_modifier_debug_print_var($curr_val, $depth+1, $length);
+ $results .= "<br>".str_repeat(' ', $depth*2)."<b>$curr_key</b> => $return";
+ }
+ } else if (is_resource($var)) {
+ $results = '<i>'.(string)$var.'</i>';
+ } else if (empty($var) && $var != "0") {
+ $results = '<i>empty</i>';
+ } else {
+ if (strlen($var) > $length ) {
+ $results = substr($var, 0, $length-3).'...';
+ } else {
+ $results = $var;
+ }
+ $results = htmlspecialchars($results);
+ $results = strtr($results, $_replace);
+ }
+ return $results;
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+<?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)
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_default($string, $default = '')
+{
+ if (!isset($string) || $string === '')
+ return $default;
+ else
+ return $string;
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+<?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)
+ * @param string
+ * @param html|htmlall|url|quotes|hex|hexentity|javascript
+ * @return string
+ */
+function smarty_modifier_escape($string, $esc_type = 'html')
+{
+ switch ($esc_type) {
+ case 'html':
+ return htmlspecialchars($string, ENT_QUOTES);
+
+ case 'htmlall':
+ return htmlentities($string, ENT_QUOTES);
+
+ case 'url':
+ return urlencode($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($string{$_i});
+ // non-standard char, escape it
+ if($_ord >= 126){
+ $_res .= '&#' . $_ord . ';';
+ }
+ else {
+ $_res .= $string{$_i};
+ }
+ }
+ return $_res;
+
+ default:
+ return $string;
+ }
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+<?php
+/*
+* Smarty plugin
+* -------------------------------------------------------------
+* Type: modifier
+* Name: fsize_format
+* Version: 0.2
+* Date: 2003-05-15
+* Author: Joscha Feth, joscha@feth.com
+* Purpose: formats a filesize (in bytes) to human-readable format
+* Usage: In the template, use
+ {$filesize|fsize_format} => 123.45 B|KB|MB|GB|TB
+ or
+ {$filesize|fsize_format:"MB"} => 123.45 MB
+ or
+ {$filesize|fsize_format:"TB":4} => 0.0012 TB
+* Params:
+ int size the filesize in bytes
+ string format the format, the output shall be: B, KB, MB, GB or TB
+ int precision the rounding precision
+ string dec_point the decimal separator
+ string thousands_sep the thousands separator
+* Install: Drop into the plugin directory
+* Version:
+* 2003-05-15 Version 0.2 - added dec_point and thousands_sep thanks to Thomas Brandl, tbrandl@barff.de
+* - made format always uppercase
+* - count sizes "on-the-fly"
+* 2003-02-21 Version 0.1 - initial release
+* -------------------------------------------------------------
+*/
+function smarty_modifier_fsize_format($size,$format = '',$precision = 2, $dec_point = ".", $thousands_sep = ",")
+{
+
+ $format = strtoupper($format);
+
+ static $sizes = array();
+
+ if(!count($sizes)) {
+ $b = 1024;
+ $sizes["B"] = 1;
+ $sizes["KB"] = $sizes["B"] * $b;
+ $sizes["MB"] = $sizes["KB"] * $b;
+ $sizes["GB"] = $sizes["MB"] * $b;
+ $sizes["TB"] = $sizes["GB"] * $b;
+
+ $sizes = array_reverse($sizes,true);
+ }
+
+ //~ get "human" filesize
+ foreach($sizes AS $unit => $bytes) {
+ if($size > $bytes || $unit == $format) {
+ //~ return formatted size
+ return number_format($size / $bytes,$precision,$dec_point,$thousands_sep)." ".$unit;
+ } //~ end if
+ } //~ end foreach
+} //~ end function
+?>
+
\ No newline at end of file
--- /dev/null
+<?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)
+ * @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);
+}
+
+?>
--- /dev/null
+<?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)
+ * @param string
+ * @return string
+ */
+function smarty_modifier_lower($string)
+{
+ return strtolower($string);
+}
+
+?>
--- /dev/null
+<?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@ispi.net>
+ * @param string
+ * @return string
+ */
+function smarty_modifier_nl2br($string)
+{
+ return nl2br($string);
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty regex_replace modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: regex_replace<br>
+ * Purpose: regular epxression search/replace
+ * @link http://smarty.php.net/manual/en/language.modifier.regex.replace.php
+ * regex_replace (Smarty online manual)
+ * @param string
+ * @param string|array
+ * @param string|array
+ * @return string
+ */
+function smarty_modifier_regex_replace($string, $search, $replace)
+{
+ return preg_replace($search, $replace, $string);
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+<?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)
+ * @param string
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_replace($string, $search, $replace)
+{
+ return str_replace($search, $replace, $string);
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+<?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)
+ * @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: */
+
+?>
--- /dev/null
+<?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)
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_string_format($string, $format)
+{
+ return sprintf($format, $string);
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+<?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:" "}
+ * Date: September 25th, 2002
+ * @link http://smarty.php.net/manual/en/language.modifier.strip.php
+ * strip (Smarty online manual)
+ * @author Monte Ohrt <monte@ispi.net>
+ * @version 1.0
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_strip($text, $replace = ' ')
+{
+ return preg_replace('!\s+!', $replace, $text);
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+<?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)
+ * @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: */
+
+?>
--- /dev/null
+<?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.
+ * @link http://smarty.php.net/manual/en/language.modifier.truncate.php
+ * truncate (Smarty online manual)
+ * @param string
+ * @param integer
+ * @param string
+ * @param boolean
+ * @return string
+ */
+function smarty_modifier_truncate($string, $length = 80, $etc = '...',
+ $break_words = false)
+{
+ if ($length == 0)
+ return '';
+
+ if (strlen($string) > $length) {
+ $length -= strlen($etc);
+ if (!$break_words)
+ $string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length+1));
+
+ return substr($string, 0, $length).$etc;
+ } else
+ return $string;
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+<?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)
+ * @param string
+ * @return string
+ */
+function smarty_modifier_upper($string)
+{
+ return strtoupper($string);
+}
+
+?>
--- /dev/null
+<?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)
+ * @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);
+}
+
+?>
--- /dev/null
+<?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@ispi.net>
+ * @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 script blocks
+ smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:SCRIPT@@@",$_script_blocks, $source);
+
+ // replace pre blocks
+ smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:PRE@@@",$_pre_blocks, $source);
+
+ // replace textarea blocks
+ smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:TEXTAREA@@@",$_textarea_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;
+
+}
+
+?>
--- /dev/null
+<?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
+ * @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: */
+
+?>
--- /dev/null
+<?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.
+ * @param string
+ * @return string
+ */
+function smarty_make_timestamp($string)
+{
+ if(empty($string)) {
+ $string = "now";
+ }
+ $time = strtotime($string);
+ if (is_numeric($time) && $time != -1)
+ return $time;
+
+ // is mysql timestamp format of YYYYMMDDHHMMSS?
+ if (preg_match('/^\d{14}$/', $string)) {
+ $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));
+
+ return $time;
+ }
+
+ // couldn't recognize it, try to return a time
+ $time = (int) $string;
+ if ($time > 0)
+ return $time;
+ else
+ return time();
+}
+
+/* vim: set expandtab: */
+
+?>
--- /dev/null
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
--- /dev/null
+2004-03-01 Sagi Bashari <sagi@boom.org.il>
+
+ * tsmarty2c.php:
+ - added support for directories (originally by Uros Gruber <uros.gruber@vizija.si>)
+ - fixed bug that prevented more than 1 block per line (reported by Eneko Lacunza <enlar@euskal.org>)
+ - convert new line to \n in output string
+
+ * smarty_gettext.php:
+ - run nl2br() when escaping html
--- /dev/null
+Gettext support for Smarty
+--------------------------
+
+Author: Sagi Bashari <sagi@boom.org.il>
+URL: http://www.boom.org.il/smarty/gettext/
+Support URL: http://www.phpinsider.com/smarty-forum/viewtopic.php?t=84
+
+This file assumes that you already know what is gettext and how to use it with PHP.
+If you don't, please visit the following websites before trying to use this package:
+ - http://www.php.net/gettext
+ - http://www.onlamp.com/pub/a/php/2002/06/13/php.html
+
+This package has two parts:
+ 1. smarty_gettext.php - The smarty plugin
+ 2. tsmarty2c.php - command line utility that rips gettext strings from smarty source files and converts them to C format
+
+The Smarty plugin
+-----------------
+
+Installation:
+
+1. Copy the smarty_gettext.php file to your include directory.
+2. After initializing the smarty object in your script, register the plugin as a block function.
+
+Example:
+$smarty = new Smarty [...];
+require('smarty_gettext.php');
+$smarty->register_block('t', 'smarty_translate');
+
+This example will register the function as a block function named 't'.
+
+Usage:
+
+The content of the block function is the string that you want to translate. For example, for translating 'Hello World', use: {t}Hello World{/t}.
+
+If you have dynamic parameters that should be set inside the string, pass them to the block function, and they will be replaced with %n, where n is 1 for the 1st parameter and so on. For example, {t name="sagi"}my name is %1{/t} will replace %1 with name.
+
+The parameter name is ignored, unless it is one of the reserved names (see below). Only the parameters order matters.
+
+Example for using multiple parameters:
+{t 1='one' 2='two' 3='three'}The 1st parameter is %1, the 2nd is %2 and the 3nd %3.{/t}
+
+NOTE: I decided to use numeric arguments instead of sprintf(), because it offers greater control over the parameter placement in the translated text. You can also use this in your PHP code, by using the strarg() function, like this: strarg(_('hi %1'), $name [,..]).
+
+By default all the translated strings will be automatically HTML escaped. You may control this by setting the 'escape' parameter. Possible values:
+ - 'html' for HTML escaping, this is the default.
+ - 'js' for javascript escaping.
+ - 'no'/'off'/0 - turns off escaping
+
+ Example: {t escape=no url="http://www.php.net/" name="PHP website"}<a href="%1">%2</a>{/t}
+
+Plural support:
+
+The package also provides support for plural forms (see ngettext).
+
+To provide a plural form:
+ 1. Set a parameter named 'plural' with the plural version of the string.
+ 2. Set a parameter named 'count' with the variable count.
+
+Example:
+{t count=$files|@count plural="%1 files"}%1 file{/t}
+
+
+tsmarty2c.php - the command line utility
+----------------------------------------
+
+This utility will rip the translation strings from the smarty files, and convert them to gettext calls in C, that can later be used with the standard gettext tools.
+
+Usage:
+./tsmarty2c.php <filename or directory> <file2> <..> > smarty.c
+
+If a parameter is a directory, the template files within will be parsed.
+
+Copyright
+---------
+
+Copyright (c) 2004 Sagi Bashari
+
+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
--- /dev/null
+<?php
+/**
+ * smarty_gettext.php - Gettext support for smarty
+ *
+ * ------------------------------------------------------------------------- *
+ * 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 *
+ * ------------------------------------------------------------------------- *
+ *
+ * To register as a smarty block function named 't', use:
+ * $smarty->register_block('t', 'smarty_translate');
+ *
+ * @package smarty_gettext
+ * @version 0.9
+ * @link http://www.boom.org.il/smarty/gettext/
+ * @author Sagi Bashari <sagi@boom.org.il>
+ * @copyright 2004 Sagi Bashari
+ */
+
+/**
+ * Replace arguments in a string with their values. Arguments are represented by % followed by their number.
+ *
+ * @param string Source string
+ * @param mixed Arguments, can be passed in an array or through single variables.
+ * @returns string Modified string
+ */
+function strarg($str)
+{
+ $tr = array();
+ $p = 0;
+
+ for ($i=1; $i < func_num_args(); $i++) {
+ $arg = func_get_arg($i);
+
+ if (is_array($arg)) {
+ foreach ($arg as $aarg) {
+ $tr['%'.++$p] = $aarg;
+ }
+ } else {
+ $tr['%'.++$p] = $arg;
+ }
+ }
+
+ return strtr($str, $tr);
+}
+
+/**
+ * Smarty block function, provides gettext support for smarty.
+ *
+ * The block content is the text that should be translated.
+ *
+ * Any parameter that is sent to the function will be represented as %n in the translation text,
+ * where n is 1 for the first parameter. The following parameters are reserved:
+ * - escape - sets escape mode:
+ * - 'html' for HTML escaping, this is the default.
+ * - 'js' for javascript escaping.
+ * - 'no'/'off'/0 - turns off escaping
+ * - plural - The plural version of the text (2nd parameter of ngettext())
+ * - count - The item count for plural mode (3rd parameter of ngettext())
+ */
+function smarty_translate($params, $text, &$smarty)
+{
+ $text = stripslashes($text);
+
+ // set escape mode
+ if (isset($params['escape'])) {
+ $escape = $params['escape'];
+ unset($params['escape']);
+ }
+
+ // set plural version
+ if (isset($params['plural'])) {
+ $plural = $params['plural'];
+ unset($params['plural']);
+
+ // set count
+ if (isset($params['count'])) {
+ $count = $params['count'];
+ unset($params['count']);
+ }
+ }
+
+ // use plural if required parameters are set
+ if (isset($count) && isset($plural)) {
+ $text = ngettext($text, $plural, $count);
+ } else { // use normal
+ $text = gettext($text);
+ }
+
+ // run strarg if there are parameters
+ if (count($params)) {
+ $text = strarg($text, $params);
+ }
+
+ if (!isset($escape) || $escape == 'html') { // html escape, default
+ $text = nl2br(htmlspecialchars($text));
+ } elseif (isset($escape) && ($escape == 'javascript' || $escape == 'js')) { // javascript escape
+ $text = str_replace('\'','\\\'',stripslashes($text));
+ }
+
+ return $text;
+}
+
+?>
--- /dev/null
+#!/usr/local/bin/php -qn
+<?php
+/**
+ * tsmarty2c.php - rips gettext strings from smarty template
+ *
+ * ------------------------------------------------------------------------- *
+ * 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 *
+ * ------------------------------------------------------------------------- *
+ *
+ * This command line script rips gettext strings from smarty file, and prints them to stdout in C format,
+ * that can later be used with the standard gettext tools.
+ *
+ * Usage:
+ * ./tsmarty2c.php <filename or directory> <file2> <..> > smarty.c
+ *
+ * If a parameter is a directory, the template files within will be parsed.
+ *
+ * @package smarty_gettext
+ * @version 0.9
+ * @link http://www.boom.org.il/smarty/gettext/
+ * @author Sagi Bashari <sagi@boom.org.il>
+ * @copyright 2004 Sagi Bashari
+ */
+
+// smarty open tag
+$ldq = preg_quote('{');
+
+// smarty close tag
+$rdq = preg_quote('}');
+
+// smarty command
+$cmd = preg_quote('t');
+
+// extensions of smarty files, used when going through a directory
+$extensions = array('tpl');
+
+// "fix" string - strip slashes, escape and convert new lines to \n
+function fs($str)
+{
+ $str = stripslashes($str);
+ $str = str_replace('"', '\"', $str);
+ $str = str_replace("\n", '\n', $str);
+ return $str;
+}
+
+// rips gettext strings from $file and prints them in C format
+function do_file($file)
+{
+ $content = @file_get_contents($file);
+
+ if (empty($content)) {
+ return;
+ }
+
+ global $ldq, $rdq, $cmd;
+
+ preg_match_all("/{$ldq}\s*({$cmd})\s*([^{$rdq}]*){$rdq}([^{$ldq}]*){$ldq}\/\\1{$rdq}/", $content, $matches);
+
+ for ($i=0; $i < count($matches[0]); $i++) {
+ if (preg_match('/plural\s*=\s*["\']?\s*(.[^\"\']*)\s*["\']?/', $matches[2][$i], $match)) {
+ print 'ngettext("'.fs($matches[3][$i]).'","'.fs($match[1]).'",x);'."\n";
+ } else {
+ print 'gettext("'.fs($matches[3][$i]).'");'."\n";
+ }
+ }
+}
+
+// go through a directory
+function do_dir($dir)
+{
+ $d = dir($dir);
+
+ while (false !== ($entry = $d->read())) {
+ if ($entry == '.' || $entry == '..') {
+ continue;
+ }
+
+ $entry = $dir.'/'.$entry;
+
+ if (is_dir($entry)) { // if a directory, go through it
+ do_dir($entry);
+ } else { // if file, parse only if extension is matched
+ $pi = pathinfo($entry);
+
+ if (in_array($pi['extension'], $GLOBALS['extensions'])) {
+ do_file($entry);
+ }
+ }
+ }
+
+ $d->close();
+}
+
+for ($ac=1; $ac < $_SERVER['argc']; $ac++) {
+ if (is_dir($_SERVER['argv'][$ac])) { // go through directory
+ do_dir($_SERVER['argv'][$ac]);
+ } else { // do file
+ do_file($_SERVER['argv'][$ac]);
+ }
+}
+
+?>
--- /dev/null
+<?
+/*
++-------------------------------------------------------------------------+
+| Copyright (C) 2004 Juan Luis Francés Jiménez |
+| |
+| 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. |
++-------------------------------------------------------------------------+
+*/
+require ("paths.php");
+require($smarty_path."Smarty.class.php");
+include "classes.inc";
+
+$smarty = new Smarty; // Template engine
+$dbSql = new Bweb();
+
+//$smarty->compile_check = true;
+//$smarty->debugging = true;
+$smarty->template_dir = "./templates";
+$smarty->compile_dir = "./templates_c";
+$smarty->config_dir = "./configs";
+$smarty->config_load("bacula.conf"); // Load config file
+$mode = $smarty->get_config_vars("mode"); // Lite o Extend?
+
+require("lang.php");
+
+
+// generaldata.tpl & last_run_report.tpl (last24bytes)
+$client = $dbSql->link->query("select count(*) from Client")
+ or die ("Error query at row 37");
+$totalfiles = $dbSql->link->query("select count(FilenameId) from Filename")
+ or die ("Error query at row 39");
+$last24bytes = $dbSql->link->query("select sum(JobBytes),count(*) from Job where Endtime <= NOW() and UNIX_TIMESTAMP(EndTime) > UNIX_TIMESTAMP(NOW())-86400")
+ or die ("Error query at row 41");
+$bytes_stored =& $dbSql->link->getOne("select SUM(VolBytes) from Media")
+ or die ("Error query at row 43");
+
+$smarty->assign('bytes_stored',$bytes_stored);
+
+$tmp = $client->fetchRow();
+$smarty->assign('clientes_totales',$tmp[0]);
+
+$tmp = $last24bytes->fetchRow();
+if ( empty($tmp[0]) ) { // No data for last 24, search last 48
+ $last24bytes = $dbSql->link->query("select sum(JobBytes) from Job where Endtime <= NOW() and UNIX_TIMESTAMP(EndTime) > UNIX_TIMESTAMP(NOW())-172800" );
+ $smarty->assign('when',"yesterday");
+}
+$smarty->assign('bytes_totales',$tmp[0]);
+$smarty->assign('total_jobs', $tmp[1]);
+
+$tmp = $totalfiles->fetchRow();
+$smarty->assign('files_totales',$tmp[0]);
+
+$client->free();
+$totalfiles->free();
+$last24bytes->free();
+
+
+// report_select.tpl & last_run_report.tpl
+$res = $dbSql->link->query("select Name from Job group by Name");
+$a_jobs = array();
+while ( $tmp = $res->fetchRow() )
+ array_push($a_jobs, $tmp[0]);
+$smarty->assign('total_name_jobs',$a_jobs);
+$smarty->assign('time2',( (time())-2678400) ); // Current time - 1 month. <select> date
+$res->free();
+
+// volumes.tpl
+$volumes = $dbSql->GetDataVolumes(); // Obtain array with info
+$pools = array_keys($volumes); // Extract Pools
+$smarty->assign('pools',$pools);
+$smarty->assign('volumes',$volumes);
+
+// last_run_report.tpl
+if ($mode == "Lite" && $_GET['Full_popup'] != "yes") {
+ $tmp = array();
+ $status = $dbSql->link->query("select JobId,Name,EndTime,JobStatus from Job where EndTime <= NOW() and UNIX_TIMESTAMP(EndTime) >UNIX_TIMESTAMP(NOW())-86400 and JobStatus!=\"T\"" )
+ or die ("Error: query at row 85");
+ $smarty->assign('status', $status->numRows());
+ if ( $status->numRows() ) {
+ while ( $res = $status->fetchRow() )
+ array_push($tmp, $res);
+ $smarty->assign('errors_array',$tmp);
+ }
+ $status->free();
+
+ // Total Elapsed Time. Only for single Job.
+ $ret = $dbSql->link->query("select UNIX_TIMESTAMP(EndTime)-UNIX_TIMESTAMP(StartTime) as elapsed from Job where EndTime <= NOW() and UNIX_TIMESTAMP(EndTime) > UNIX_TIMESTAMP(NOW())-84600")
+ or die ("Error at row 96");
+ while ( $res = $ret->fetchRow() ) {
+ if ( $TotalElapsed < 1000000000 ) // Temporal "workaround" ;) Fix later
+ $TotalElapsed += $res[0];
+ }
+ if ($TotalElapsed > 86400) // More than 1 day!
+ $TotalElapsed = gmstrftime("%d days %H:%M:%S", $TotalElapsed);
+ else
+ $TotalElapsed = gmstrftime("%H:%M:%S", $TotalElapsed);
+ $smarty->assign('TotalElapsed',$TotalElapsed);
+ $ret->free();
+}
+else if ($mode == "Full" || $_GET['Full_popup'] == "yes" ){
+ $tmp1 = array();
+ $query = "select SEC_TO_TIME( UNIX_TIMESTAMP(Job.EndTime)-UNIX_TIMESTAMP(Job.StartTime) )
+ as elapsed,Job.Name,Job.StartTime,Job.EndTime,Job.Level,Pool.Name,Job.JobStatus from Job
+ LEFT JOIN Pool ON Job.PoolId=Pool.PoolId where EndTime <= NOW() and UNIX_TIMESTAMP(EndTime) >UNIX_TIMESTAMP(NOW())-86400
+ order by elapsed "; // Full report array
+ $status = $dbSql->link->query($query)
+ or die ("Error: query at row 115");
+ while ( $tmp = $status->fetchRow() ) {
+ $tdate = explode (":",$tmp[0]);
+ if ( $tdate[0] > 300000 ) // Temporal "workaround" ;) Fix later
+ $tmp[0] = "00:00:00";
+ array_push($tmp1,$tmp);
+ }
+
+ $smarty->assign('clients',$tmp1);
+}
+
+
+if ($_GET['Full_popup'] == "yes" || $_GET['pop_graph1'] == "yes" || $_GET['pop_graph2'] == "yes")
+ $smarty->display('full_popup.tpl');
+else
+ $smarty->display('index.tpl');
+?>
\ No newline at end of file
--- /dev/null
+//\/////
+//\ overLIB Anchor Plugin
+//\ This file requires overLIB 4.00 or later.
+//\
+//\ overLIB 4.00 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\ Contributors are listed on the homepage.
+//\ See http://www.bosrup.com/web/overlib/ for details.
+//\/////
+if (typeof olInfo=='undefined'||olInfo.simpleversion<400) alert('overLIB 4.00 or later is required for the Anchor Plugin.');registerCommands('anchor,anchorx,anchory,noanchorwarn,anchoralign');
+if (typeof ol_anchor=='undefined') var ol_anchor='';if (typeof ol_anchorx=='undefined') var ol_anchorx=0;if (typeof ol_anchory=='undefined') var ol_anchory=0;if (typeof ol_noanchorwarn=='undefined') var ol_noanchorwarn=1;if (typeof ol_anchoralign=='undefined') var ol_anchoralign='UL';
+var o3_anchor="";var o3_anchorx=0;var o3_anchory=0;var o3_noanchorwarn=1;var o3_anchoralign='UL';var mrkObj, rmrkPosition;
+function setAnchorVariables() {o3_anchor=ol_anchor;o3_anchorx=ol_anchorx;o3_anchory=ol_anchory;o3_noanchorwarn=ol_noanchorwarn;o3_anchoralign=ol_anchoralign;mrkObj=null;}
+function parseAnchorExtras(pf,i,ar) {var v, k=i;
+if (k<ar.length) {if (ar[k]==ANCHOR) { eval(pf+"anchor='"+escSglQuote(ar[++k])+"'"); return k; }
+if (ar[k]==ANCHORX) { eval(pf+'anchorx='+ar[++k]); return k; }
+if (ar[k]==ANCHORY) { eval(pf+'anchory='+ar[++k]); return k; }
+if (ar[k]==NOANCHORWARN) { eval(pf+'noanchorwarn=('+pf+'noanchorwarn==1)?0:1'); return k; }
+if (ar[k]==ANCHORALIGN) { k=opt_MULTIPLEARGS(++k, ar, (pf+'anchoralign')); return k; }
+}
+return-1;}
+function checkAnchorObject() {var w=o3_anchor;
+if (w) {if (!(mrkObj=getAnchorObjectRef(w))) {if (o3_noanchorwarn) {alert('WARNING! Reference mark "'+w+'" not found.');return false;} else w='';}
+}
+return true;}
+function anchorPlaceLayer() {var placeX, placeY, widthFix=0;
+if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientWidth=='number'")&&eval('o3_frame.'+docRoot+'.clientWidth')) {iwidth=eval('o3_frame.'+docRoot+'.clientWidth');} else if (typeof(o3_frame.innerWidth)=='number') {widthFix=Math.ceil(1.2*(o3_frame.outerWidth-o3_frame.innerWidth));iwidth=o3_frame.innerWidth;}
+if (o3_anchor) {placeX=rmrkPosition[0];placeY=rmrkPosition[1];} else {
+winoffset=(olIe4)?eval('o3_frame.'+docRoot+'.scrollLeft'):o3_frame.pageXOffset;var parsedWidth=parseInt(o3_width);
+if (o3_fixx>-1||o3_relx!=null) {
+placeX=(o3_relx!=null?( o3_relx<0?winoffset+o3_relx+iwidth-parsedWidth-widthFix:winoffset+o3_relx):o3_fixx);} else {
+if (o3_hauto==1) {if ((o3_x-winoffset)>(iwidth/2)) {o3_hpos=LEFT;} else {o3_hpos=RIGHT;}
+}
+if (o3_hpos==CENTER) {placeX=o3_x+o3_offsetx-(parsedWidth/2);
+if (placeX<winoffset) placeX=winoffset;}
+if (o3_hpos==RIGHT) {placeX=o3_x+o3_offsetx;
+if ((placeX+parsedWidth)>(winoffset+iwidth-widthFix)) {placeX=iwidth+winoffset-parsedWidth-widthFix;if (placeX<0) placeX=0;}
+}
+if (o3_hpos==LEFT) {placeX=o3_x-o3_offsetx-parsedWidth;if (placeX<winoffset) placeX=winoffset;}
+if (o3_snapx>1) {var snapping=placeX % o3_snapx;
+if (o3_hpos==LEFT) {placeX=placeX-(o3_snapx+snapping);} else {
+placeX=placeX+(o3_snapx-snapping);}
+if (placeX<winoffset) placeX=winoffset;}
+}
+if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientHeight=='number'")&&eval('o3_frame.'+docRoot+'.clientHeight')) {iheight=eval('o3_frame.'+docRoot+'.clientHeight');} else if (typeof(o3_frame.innerHeight)=='number') {iheight=o3_frame.innerHeight;}
+scrolloffset=(olIe4)?eval('o3_frame.'+docRoot+'.scrollTop'):o3_frame.pageYOffset;var parsedHeight=(o3_aboveheight?parseInt(o3_aboveheight):(olNs4?over.clip.height:over.offsetHeight));
+if (o3_fixy>-1||o3_rely!=null) {
+placeY=(o3_rely!=null?(o3_rely<0?scrolloffset+o3_rely+iheight-parsedHeight:scrolloffset+o3_rely):o3_fixy);} else {
+if (o3_vauto==1) {if ((o3_y-scrolloffset)>(iheight/2)) {o3_vpos=ABOVE;} else {o3_vpos=BELOW;}
+}
+if (o3_vpos==ABOVE) {if (o3_aboveheight==0) o3_aboveheight=parsedHeight;
+placeY=o3_y-(o3_aboveheight+o3_offsety);if (placeY<scrolloffset) placeY=scrolloffset;} else {
+placeY=o3_y+o3_offsety;}
+if (o3_snapy>1) {var snapping=placeY % o3_snapy;
+if (o3_aboveheight>0&&o3_vpos==ABOVE) {placeY=placeY-(o3_snapy+snapping);} else {placeY=placeY+(o3_snapy-snapping);}
+if (placeY<scrolloffset) placeY=scrolloffset;}
+}
+}
+repositionTo(over, placeX, placeY);if (typeof o3_scroll!='undefined'&& o3_scroll&& o3_sticky&& (o3_relx||o3_rely)&& (typeof o3_draggable=='undefined'||!o3_draggable)) {if (typeof over.scroller=='undefined'||over.scroller.canScroll) over.scroller=new scroller(placeX-winoffset, placeY-scrolloffset, setTimeout("repositionOver()", 20));}
+}
+function anchorPreface() {if (!mrkObj) return;rmrkPosition=getAnchorLocation(mrkObj);}
+function getAnchorObjectRef(aObj) {return getRefById(aObj, o3_frame.document)||getRefByName(aObj, o3_frame.document)
+}
+function getAnchorLocation(objRef){var mkObj, of, offsets, mlyr
+mkObj=mlyr=objRef
+offsets=[o3_anchorx, o3_anchory]
+if (document.layers){if (typeof mlyr.length!='undefined'&& mlyr.length>1) {mkObj=mlyr[0]
+offsets[0]+=mlyr[0].x+mlyr[1].pageX
+offsets[1]+=mlyr[0].y+mlyr[1].pageY
+} else {if(mlyr.toString().indexOf('Image')!=-1||mlyr.toString().indexOf('Anchor')!=-1){offsets[0]+=mlyr.x
+offsets[1]+=mlyr.y
+} else {offsets[0]+=mlyr.pageX
+offsets[1]+=mlyr.pageY
+}
+}
+} else {offsets[0]+=pageLocation(mlyr, 'Left')
+offsets[1]+=pageLocation(mlyr, 'Top')
+}
+of=getAnchorOffsets(mkObj)
+if (typeof o3_dragimg!='undefined'&& o3_dragimg) {olImgLeft=offsets[0];olImgTop=offsets[1];}
+offsets[0]+=of[0]
+offsets[1]+=of[1]
+if (typeof o3_dragimg!='undefined'&& o3_dragimg) {olImgRight=offsets[0];olImgBottom=offsets[1];return;}
+return offsets;}
+function getAnchorOffsets(mkObj){var fx=fy=0, mp, puc, mkAry, sx=sy=0, w=o3_anchoralign
+var mW=mH=pW=pH=0
+var off=[0, 0]
+mkAry=w.split(',');
+if (mkAry.length<3) {mp=mkAry[0].toUpperCase();puc=(mkAry.length==1)?mp:mkAry[1].toUpperCase();} else if (mkAry.length==3) {if (!isNaN(mkAry[0])) {mp=mkAry.slice(0, 2);puc=mkAry[2].toUpperCase();} else {mp=mkAry[0].toUpperCase();puc=mkAry.slice(1);}
+} else {mp=mkAry.slice(0, 2);puc=mkAry.slice(2);}
+var shdwPresent=typeof o3_shadow!='undefined'&& o3_shadow
+if (shdwPresent) {sx=Math.abs(o3_shadowx);sy=Math.abs(o3_shadowy);}
+pW=(shdwPresent?parseInt(o3_width):(olNs4?over.clip.width:over.offsetWidth))
+pH=(shdwPresent?parseInt(o3_aboveheight):(olNs4?over.clip.height:over.offsetHeight))
+if (olOp&& o3_wrap) {pW=(shdwPresent?parseInt(o3_width):(olNs4?over.clip.width:over.offsetWidth))
+pH=(shdwPresent?parseInt(o3_aboveheight):(olNs4?over.clip.height:over.offsetHeight))
+}
+if (!olOp&& mkObj.toString().indexOf('Image')!=-1){mW=mkObj.width
+mH=mkObj.height
+} else if (!olOp&& mkObj.toString().indexOf('Anchor')!=-1) {mp='UL'
+} else {mW=(olNs4)?mkObj.clip.width:mkObj.offsetWidth
+mH=(olNs4)?mkObj.clip.height:mkObj.offsetHeight
+}
+if (!isNaN(mp)||typeof mp=='object') {if (typeof mp=='object') {fx=parseFloat(mp[0]);fy=parseFloat(mp[1]);} else
+fx=fy=parseFloat(mp);off=[Math.round(fx*mW), Math.round(fy*mH)];} else {if (mp=='UR') off=[mW, 0]
+else if (mp=='LL') off=[0, mH]
+else if (mp=='LR') off=[mW, mH]
+}
+if (typeof o3_dragimg!='undefined'&& o3_dragimg) return off;else {if (!isNaN(puc)||typeof puc=='object' ) {if (typeof puc=='object') {fx=parseFloat(puc[0]);fy=parseFloat(puc[1]);} else
+fx=fy=parseFloat(puc);off[0]-=Math.round(fx*(pW-sx));off[1]-=Math.round(fy*(pH-sy));} else {if (puc=='UR') {off[0]-=(pW-sx);off[1]-=sy
+} else if (puc=='LL') {off[0]-=sx;off[1]-=(pH-sy)
+} else if (puc=='LR') {off[0]-=(pW-sx);off[1]-=(pH-sy)
+}
+}
+return off
+}
+}
+function pageLocation(o, t){var x=0
+while(o.offsetParent){x+=o['offset'+t]
+o=o.offsetParent
+}
+x+=o['offset'+t]
+return x
+}
+function getRefById(l, d){var r="", j
+d=(d||document)
+if (d.all) return d.all[l]
+else if (d.getElementById) return d.getElementById(l)
+else if (d.layers&& d.layers.length>0) {if (d.layers[l]) return d.layers[l]
+for (j=0; j<d.layers.length; j++) {r=getRefById(l, d.layers[j].document)
+if(r) return r
+}
+}
+return false
+}
+function getRefByName(l, d) {var r=null, j
+d=(d||document)
+if (d.images[l]) return d.images[l]
+else if (d.anchors[l]) return d.anchors[l];else if (d.layers&& d.layers.length>0) {for (j=0; j<d.layers.length; j++) {r=getRefByName(l, d.layers[j].document)
+if (r&& r.length>0) return r
+else if (r) return [r, d.layers[j]]
+}
+}
+return null
+}
+registerHook("placeLayer", anchorPlaceLayer, FREPLACE);registerRunTimeFunction(setAnchorVariables);registerCmdLineFunction(parseAnchorExtras);registerPostParseFunction(checkAnchorObject);registerHook("createPopup", anchorPreface, FAFTER);
--- /dev/null
+//\/////
+//\ overLIB Crossframe Support Plugin
+//\ This file requires overLIB 4.00 or later.
+//\
+//\ overLIB 4.00 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\ Contributors are listed on the homepage.
+//\ See http://www.bosrup.com/web/overlib/ for details.
+//\/////
+if (typeof olInfo=='undefined'||olInfo.simpleversion<400) alert('overLIB 4.00 or later is required for the Cross Frame Support Plugin.');registerCommands('frame');
+function parseFrameExtras(pf,i,ar) {var k=i,v;
+if (k<ar.length) {if (ar[k]==FRAME) { v=ar[++k]; if(pf=='ol_'&&compatibleframe(v)) ol_frame=v; else opt_FRAME(v); return k; }
+}
+return-1;}
+function opt_FRAME(frm) {o3_frame=compatibleFrame(frm)?frm:ol_frame;
+if (olNs4) {over=o3_frame.document.layers['overDiv'];} else if (document.all) {over=o3_frame.document.all['overDiv'];} else if (document.getElementById) {over=o3_frame.document.getElementById("overDiv");}
+return 0;}
+function compatibleFrame(frameid) {if (olNs4&&typeof frameid.document.overDiv=='undefined') {return false;} else if (document.all&&typeof frameid.document.all["overDiv"]=='undefined') {return false;} else if (document.getElementById&&frameid.document.getElementById('overDiv')==null) {return false;}
+return true;}
+function frmDepth(thisFrame,ofrm) {var retVal='';
+for (var i=0; i<thisFrame.length; i++) {if (thisFrame[i].length>0) {retVal=frmDepth(thisFrame[i],ofrm);if (retVal=='') continue;} else if (thisFrame[i]!=ofrm) continue;retVal='['+i+']'+retVal;break;}
+return retVal;}
+function getFrmRef(srcFrm,tgetFrm) {var rtnVal=''
+if (tgetFrm!=srcFrm) {var tFrm=frmDepth(top.frames,tgetFrm)
+var sFrm=frmDepth(top.frames,srcFrm)
+if (sFrm.length==tFrm.length) {l=tFrm.lastIndexOf('[')
+if (l) {while ( sFrm.substring(0,l)!=tFrm.substring(0,l) )
+l=tFrm.lastIndexOf('[',l-1)
+tFrm=tFrm.substr(l)
+sFrm=sFrm.substr(l)
+}
+}
+var cnt=0, p='',str=tFrm
+while ((k=str.lastIndexOf('['))!=-1) {cnt++
+str=str.substring(0,k)
+}
+for (var i=0; i<cnt; i++) p=p+'parent.'
+rtnVal=p+'frames'+sFrm+'.'
+}
+return rtnVal
+}
+function chkForFrmRef() {if(o3_frame!=ol_frame) fnRef=getFrmRef(ol_frame,o3_frame)
+return true;}
+registerCmdLineFunction(parseFrameExtras);registerPostParseFunction(chkForFrmRef);
--- /dev/null
+//\/////
+//\ overLIB CSS Style Plugin
+//\ This file requires overLIB 4.00 or later.
+//\
+//\ overLIB 4.00 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\ Contributors are listed on the homepage.
+//\ See http://www.bosrup.com/web/overlib/ for details.
+//\/////
+if (typeof olInfo=='undefined'||olInfo.simpleversion<400) alert('overLIB 4.00 or later is required for the CSS Style Plugin.');registerCommands('cssstyle,padunit,heightunit,widthunit,textsizeunit,textdecoration,textstyle,textweight,captionsizeunit,captiondecoration,captionstyle,captionweight,closesizeunit,closedecoration,closestyle,closeweight');
+if (typeof ol_padunit=='undefined') var ol_padunit="px";if (typeof ol_heightunit=='undefined') var ol_heightunit="px";if (typeof ol_widthunit=='undefined') var ol_widthunit="px";if (typeof ol_textsizeunit=='undefined') var ol_textsizeunit="px";if (typeof ol_textdecoration=='undefined') var ol_textdecoration="none";if (typeof ol_textstyle=='undefined') var ol_textstyle="normal";if (typeof ol_textweight=='undefined') var ol_textweight="normal";if (typeof ol_captionsizeunit=='undefined') var ol_captionsizeunit="px";if (typeof ol_captiondecoration=='undefined') var ol_captiondecoration="none";if (typeof ol_captionstyle=='undefined') var ol_captionstyle="normal";if (typeof ol_captionweight=='undefined') var ol_captionweight="bold";if (typeof ol_closesizeunit=='undefined') var ol_closesizeunit="px";if (typeof ol_closedecoration=='undefined') var ol_closedecoration="none";if (typeof ol_closestyle=='undefined') var ol_closestyle="normal";if (typeof ol_closeweight=='undefined') var ol_closeweight="normal";
+var o3_padunit="px";var o3_heightunit="px";var o3_widthunit="px";var o3_textsizeunit="px";var o3_textdecoration="";var o3_textstyle="";var o3_textweight="";var o3_captionsizeunit="px";var o3_captiondecoration="";var o3_captionstyle="";var o3_captionweight="";var o3_closesizeunit="px";var o3_closedecoration="";var o3_closestyle="";var o3_closeweight="";
+function setCSSStyleVariables() {o3_padunit=ol_padunit;o3_heightunit=ol_heightunit;o3_widthunit=ol_widthunit;o3_textsizeunit=ol_textsizeunit;o3_textdecoration=ol_textdecoration;o3_textstyle=ol_textstyle;o3_textweight=ol_textweight;o3_captionsizeunit=ol_captionsizeunit;o3_captiondecoration=ol_captiondecoration;o3_captionstyle=ol_captionstyle;o3_captionweight=ol_captionweight;o3_closesizeunit=ol_closesizeunit;o3_closedecoration=ol_closedecoration;o3_closestyle=ol_closestyle;o3_closeweight=ol_closeweight;}
+function parseCSSStyleExtras(pf, i, ar) {var k=i;
+if (k<ar.length) {if (ar[k]==CSSSTYLE) { eval(pf+'css='+ar[k]); return k; }
+if (ar[k]==PADUNIT) { eval(pf+'padunit="'+ar[++k]+'"'); return k; }
+if (ar[k]==HEIGHTUNIT) { eval(pf+'heightunit="'+ar[++k]+'"'); return k; }
+if (ar[k]==WIDTHUNIT) { eval(pf+'widthunit="'+ar[++k]+'"'); return k; }
+if (ar[k]==TEXTSIZEUNIT) { eval(pf+'textsizeunit="'+ar[++k]+'"'); return k; }
+if (ar[k]==TEXTDECORATION) { eval(pf+'textdecoration="'+ar[++k]+'"'); return k; }
+if (ar[k]==TEXTSTYLE) { eval(pf+'textstyle="'+ar[++k]+'"'); return k; }
+if (ar[k]==TEXTWEIGHT) { eval(pf+'textweight="'+ar[++k]+'"'); return k; }
+if (ar[k]==CAPTIONSIZEUNIT) { eval(pf+'captionsizeunit="'+ar[++k]+'"'); return k; }
+if (ar[k]==CAPTIONDECORATION) { eval(pf+'captiondecoration="'+ar[++k]+'"'); return k; }
+if (ar[k]==CAPTIONSTYLE) { eval(pf+'captionstyle="'+ar[++k]+'"'); return k; }
+if (ar[k]==CAPTIONWEIGHT) { eval(pf+'captionweight="'+ar[++k]+'"'); return k; }
+if (ar[k]==CLOSESIZEUNIT) { eval(pf+'closesizeunit="'+ar[++k]+'"'); return k; }
+if (ar[k]==CLOSEDECORATION) { eval(pf+'closedecoration="'+ar[++k]+'"'); return k; }
+if (ar[k]==CLOSESTYLE) { eval(pf+'closestyle="'+ar[++k]+'"'); return k; }
+if (ar[k]==CLOSEWEIGHT) { eval(pf+'closeweight="'+ar[++k]+'"'); return k; }
+}
+return-1;}
+function ol_content_simple_cssstyle(text) {txt='<table width="'+o3_width+'" border="0" cellpadding="'+o3_border+'" cellspacing="0" style="background-color: '+o3_bgcolor+'; height: '+o3_height+o3_heightunit+';"><tr><td><table width="100%" border="0" cellpadding="'+o3_cellpad+'" cellspacing="0" style="color: '+o3_fgcolor+'; background-color: '+o3_fgcolor+'; height: '+o3_height+o3_heightunit+';"><tr><td valign="TOP"><font style="font-family: '+o3_textfont+'; color: '+o3_textcolor+'; font-size: '+o3_textsize+o3_textsizeunit+'; text-decoration: '+o3_textdecoration+'; font-weight: '+o3_textweight+'; font-style:'+o3_textstyle+'">'+text+'</font></td></tr></table></td></tr></table>';set_background("");
+return txt;}
+function ol_content_caption_cssstyle(text, title, close) {var nameId;closing="";closeevent="onMouseOver";
+if (o3_closeclick==1) closeevent=(o3_closetitle?"title='"+o3_closetitle+"'":"")+" onClick";
+if (o3_capicon!="") {nameId=' hspace=\"5\"'+' align=\"middle\" alt=\"\"';if (typeof o3_dragimg!='undefined'&&o3_dragimg) nameId=' hspace=\"5\"'+' name=\"'+o3_dragimg+'\" id=\"'+o3_dragimg+'\" align=\"middle\" alt=\"Drag Enabled\" title=\"Drag Enabled\"';o3_capicon='<img src=\"'+o3_capicon+'\"'+nameId+' />';}
+if (close!="") {closing='<td align="RIGHT"><a href="javascript:return '+fnRef+'cClick();" '+closeevent+'="return '+fnRef+'cClick();" style="color: '+o3_closecolor+'; font-family: '+o3_closefont+'; font-size: '+o3_closesize+o3_closesizeunit+'; text-decoration: '+o3_closedecoration+'; font-weight: '+o3_closeweight+'; font-style:'+o3_closestyle+';">'+close+'</a></td>';}
+txt='<table width="'+o3_width+'" border="0" cellpadding="'+o3_border+'" cellspacing="0" style="background-color: '+o3_bgcolor+'; background-image: url('+o3_bgbackground+'); height: '+o3_height+o3_heightunit+';"><tr><td><table width="100%" border="0" cellpadding="0" cellspacing="0"><tr><td><font style="font-family: '+o3_captionfont+'; color: '+o3_capcolor+'; font-size: '+o3_captionsize+o3_captionsizeunit+'; font-weight: '+o3_captionweight+'; font-style: '+o3_captionstyle+'; text-decoration: '+o3_captiondecoration+';">'+o3_capicon+title+'</font></td>'+closing+'</tr></table><table width="100%" border="0" cellpadding="'+o3_cellpad+'" cellspacing="0" style="color: '+o3_fgcolor+'; background-color: '+o3_fgcolor+'; height: '+o3_height+o3_heightunit+';"><tr><td valign="TOP"><font style="font-family: '+o3_textfont+'; color: '+o3_textcolor+'; font-size: '+o3_textsize+o3_textsizeunit+'; text-decoration: '+o3_textdecoration+'; font-weight: '+o3_textweight+'; font-style:'+o3_textstyle+'">'+text+'</font></td></tr></table></td></tr></table>';set_background("");
+return txt;}
+function ol_content_background_cssstyle(text, picture, hasfullhtml) {if (hasfullhtml) {txt=text;} else {var pU, hU, wU;pU=(o3_padunit=='%'?'%':'');hU=(o3_heightunit=='%'?'%':'');wU=(o3_widthunit=='%'?'%':'');txt='<table width="'+o3_width+wu+'" border="0" cellpadding="0" cellspacing="0" height="'+o3_height+hu+'"><tr><td colspan="3" height="'+o3_padyt+pu+'"></td></tr><tr><td width="'+o3_padxl+pu+'"></td><td valign="TOP" width="'+(o3_width-o3_padxl-o3_padxr)+pu+'"><font style="font-family: '+o3_textfont+'; color: '+o3_textcolor+'; font-size: '+o3_textsize+o3_textsizeunit+';">'+text+'</font></td><td width="'+o3_padxr+pu+'"></td></tr><tr><td colspan="3" height="'+o3_padyb+pu+'"></td></tr></table>';}
+set_background(picture);
+return txt;}
+registerRunTimeFunction(setCSSStyleVariables);registerCmdLineFunction(parseCSSStyleExtras);registerHook("ol_content_simple", ol_content_simple_cssstyle, FALTERNATE, CSSSTYLE);registerHook("ol_content_caption", ol_content_caption_cssstyle, FALTERNATE, CSSSTYLE);registerHook("ol_content_background", ol_content_background_cssstyle, FALTERNATE, CSSSTYLE);
\ No newline at end of file
--- /dev/null
+//\/////
+//\ overLIB Exclusive Plugin
+//\ This file requires overLIB 4.00 or later.
+//\
+//\ overLIB 4.00 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\ Contributors are listed on the homepage.
+//\ See http://www.bosrup.com/web/overlib/ for details.
+//\/////
+if (typeof olInfo=='undefined'||olInfo.simpleversion<400) alert('overLIB 4.00 or later is required for the Debug Plugin.');registerCommands('exclusive,exclusivestatus,exclusiveoverride');var olOverrideIsSet;
+if (typeof ol_exclusive=='undefined') var ol_exclusive=0;if (typeof ol_exclusivestatus=='undefined') var ol_exclusivestatus='Please close open popup first.';
+var o3_exclusive=0;var o3_exclusivestatus='';
+function setExclusiveVariables() {o3_exclusive=ol_exclusive;o3_exclusivestatus=ol_exclusivestatus;}
+function parseExclusiveExtras(pf,i,ar) {var k=i,v;
+olOverrideIsSet=false;
+if (k<ar.length) {if (ar[k]==EXCLUSIVEOVERRIDE) { if(pf!='ol_') olOverrideIsSet=true; return k; }
+if (ar[k]==EXCLUSIVE) { eval(pf+'exclusive=('+pf+'exclusive==0)?1:0'); return k; }
+if (ar[k]==EXCLUSIVESTATUS) { eval(pf+"exclusivestatus='"+escSglQuote(ar[++k])+"'"); return k; }
+}
+return-1;}
+function isExclusive(args) {var rtnVal=false;
+if(args!=null) rtnVal=hasCommand(args, EXCLUSIVEOVERRIDE);
+if(rtnVal) return false;else {self.status=(o3_exclusive)?o3_exclusivestatus:'';return o3_exclusive;}
+}
+function hasCommand(args, COMMAND) {var rtnFlag=false;
+for (var i=0; i<args.length; i++) {if (typeof args[i]=='number'&& args[i]==COMMAND) {rtnFlag=true;break;}
+}
+return rtnFlag;}
+function clearExclusive() {o3_exclusive=0;}
+function setExclusive() {o3_exclusive=(o3_showingsticky&& o3_exclusive);}
+function chkForExclusive() {if (olOverrideIsSet) o3_exclusive=0;
+return true;}
+registerRunTimeFunction(setExclusiveVariables);registerCmdLineFunction(parseExclusiveExtras);registerPostParseFunction(chkForExclusive);registerHook("createPopup",setExclusive,FBEFORE);registerHook("hideObject",clearExclusive,FAFTER);
--- /dev/null
+//\/////
+//\ overLIB Follow Scroll Plugin
+//\ This file requires overLIB 4.00 or later.
+//\
+//\ overLIB 4.00 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\ Contributors are listed on the homepage.
+//\ See http://www.bosrup.com/web/overlib/ for details.
+//\/////
+if (typeof olInfo=='undefined'||olInfo.simpleversion<400) alert('overLIB 4.00 or later is required for the Follow Scroll Plugin.');registerCommands('followscroll,followscrollrefresh');
+if (typeof ol_followscroll=='undefined') var ol_followscroll=0;if (typeof ol_followscrollrefresh=='undefined') var ol_followscrollrefresh=100;
+var o3_followscroll=0;var o3_followscrollrefresh=100;
+function setScrollVariables() {o3_followscroll=ol_followscroll;o3_followscrollrefresh=ol_followscrollrefresh;}
+function parseScrollExtras(pf,i,ar) {var k=i,v;if (k<ar.length) {if (ar[k]==FOLLOWSCROLL) { eval(pf+'followscroll=('+pf+'followscroll==0)?1:0'); return k; }
+if (ar[k]==FOLLOWSCROLLREFRESH) { eval(pf+'followscrollrefresh='+ar[++k]); return k; }
+}
+return-1;}
+function scroll_placeLayer() {var placeX, placeY, widthFix=0;var hasAnchor=(typeof o3_anchor!='undefined'&&o3_anchor);
+if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientWidth=='number'")&&eval('o3_frame.'+docRoot+'.clientWidth')) {iwidth=eval('o3_frame.'+docRoot+'.clientWidth');} else if (typeof(o3_frame.innerWidth)=='number') {widthFix=Math.ceil(1.2*(o3_frame.outerWidth-o3_frame.innerWidth));iwidth=o3_frame.innerWidth;}
+if (hasAnchor) {placeX=rmrkPosition[0];placeY=rmrkPosition[1];} else {
+winoffset=(olIe4)?eval('o3_frame.'+docRoot+'.scrollLeft'):o3_frame.pageXOffset;var parsedWidth=parseInt(o3_width);
+if (o3_fixx>-1||o3_relx!=null) {
+placeX=(o3_relx!=null?( o3_relx<0?winoffset+o3_relx+iwidth-parsedWidth-widthFix:winoffset+o3_relx):o3_fixx);} else {
+if (o3_hauto==1) {if ((o3_x-winoffset)>(iwidth/2)) {o3_hpos=LEFT;} else {o3_hpos=RIGHT;}
+}
+if (o3_hpos==CENTER) {placeX=o3_x+o3_offsetx-(parsedWidth/2);
+if (placeX<winoffset) placeX=winoffset;}
+if (o3_hpos==RIGHT) {placeX=o3_x+o3_offsetx;
+if ((placeX+parsedWidth)>(winoffset+iwidth-widthFix)) {placeX=iwidth+winoffset-parsedWidth-widthFix;if (placeX<0) placeX=0;}
+}
+if (o3_hpos==LEFT) {placeX=o3_x-o3_offsetx-parsedWidth;if (placeX<winoffset) placeX=winoffset;}
+if (o3_snapx>1) {var snapping=placeX % o3_snapx;
+if (o3_hpos==LEFT) {placeX=placeX-(o3_snapx+snapping);} else {
+placeX=placeX+(o3_snapx-snapping);}
+if (placeX<winoffset) placeX=winoffset;}
+}
+if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientHeight=='number'")&&eval('o3_frame.'+docRoot+'.clientHeight')) {iheight=eval('o3_frame.'+docRoot+'.clientHeight');} else if (typeof(o3_frame.innerHeight)=='number') {iheight=o3_frame.innerHeight;}
+scrolloffset=(olIe4)?eval('o3_frame.'+docRoot+'.scrollTop'):o3_frame.pageYOffset;var parsedHeight=(o3_aboveheight?parseInt(o3_aboveheight):(olNs4?over.clip.height:over.offsetHeight));
+if (o3_fixy>-1||o3_rely!=null) {
+placeY=(o3_rely!=null?(o3_rely<0?scrolloffset+o3_rely+iheight-parsedHeight:scrolloffset+o3_rely):o3_fixy);} else {
+if (o3_vauto==1) {if ((o3_y-scrolloffset)>(iheight/2)) {o3_vpos=ABOVE;} else {o3_vpos=BELOW;}
+}
+if (o3_vpos==ABOVE) {if (o3_aboveheight==0) o3_aboveheight=parsedHeight;
+placeY=o3_y-(o3_aboveheight+o3_offsety);if (placeY<scrolloffset) placeY=scrolloffset;} else {
+placeY=o3_y+o3_offsety;}
+if (o3_snapy>1) {var snapping=placeY % o3_snapy;
+if (o3_aboveheight>0&&o3_vpos==ABOVE) {placeY=placeY-(o3_snapy+snapping);} else {placeY=placeY+(o3_snapy-snapping);}
+if (placeY<scrolloffset) placeY=scrolloffset;}
+}
+}
+repositionTo(over,placeX,placeY);
+if (o3_followscroll&&o3_sticky&&(o3_relx||o3_rely)&&(typeof o3_draggable=='undefined'||!o3_draggable)) {if (typeof over.scroller=='undefined'||over.scroller.canScroll) over.scroller=new Scroller(placeX-winoffset,placeY-scrolloffset,o3_followscrollrefresh);}
+}
+function Scroller(X,Y,refresh) {this.canScroll=0;this.refresh=refresh;this.x=X;this.y=Y;this.timer=setTimeout("repositionOver()",this.refresh);}
+function cancelScroll() {if (!o3_followscroll||typeof over.scroller=='undefined') return;over.scroller.canScroll=1;
+if (over.scroller.timer) {clearTimeout(over.scroller.timer);over.scroller.timer=null;}
+}
+function getPageScrollY() {if (o3_frame.pageYOffset) return o3_frame.pageYOffset;if (eval(docRoot)) return eval('o3_frame.'+docRoot+'.scrollTop');return-1;}
+function getPageScrollX() {if (o3_frame.pageXOffset) return o3_frame.pageXOffset;if (eval(docRoot)) return eval('o3_frame.'+docRoot+'.scrollLeft');return-1;}
+function getLayerTop(layer) {if (layer.pageY) return layer.pageY;if (layer.style.top) return parseInt(layer.style.top);return-1;}
+function getLayerLeft(layer) {if (layer.pageX) return layer.pageX;if (layer.style.left) return parseInt(layer.style.left);return-1;}
+function repositionOver() {var X, Y, pgLeft, pgTop;pgTop=getPageScrollY();pgLeft=getPageScrollX();X=getLayerLeft(over)-pgLeft;Y=getLayerTop(over)-pgTop;
+if (X!=over.scroller.x||Y!=over.scroller.y) repositionTo(over, pgLeft+over.scroller.x, pgTop+over.scroller.y);over.scroller.timer=setTimeout("repositionOver()", over.scroller.refresh);}
+registerRunTimeFunction(setScrollVariables);registerCmdLineFunction(parseScrollExtras);registerHook("hideObject",cancelScroll,FAFTER);registerHook("placeLayer",scroll_placeLayer,FREPLACE);
--- /dev/null
+//\/////
+//\ overLIB Hide Form Plugin
+//\ This file requires overLIB 4.00 or later.
+//\
+//\ Uses an iframe shim to mask system controls for IE v5.5 or higher as suggested in
+//\ http://dotnetjunkies.com/weblog/jking/posts/488.aspx
+//\
+//\ overLIB 4.00 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\ Contributors are listed on the homepage.
+//\ See http://www.bosrup.com/web/overlib/ for details.
+//\/////
+if (typeof olInfo=='undefined'||olInfo.simpleversion<400) alert('overLIB 4.00 or later is required for the HideForm Plugin.');
+function generatePopUp(content) {if(!olIe4||olOp||!olIe55||(typeof o3_shadow!='undefined'&&o3_shadow)||(typeof o3_bubble!='undefined'&&o3_bubble)) return;
+var wd,ht,txt, zIdx=0;
+wd=parseInt(o3_width);ht=over.offsetHeight;txt=bckDropSrc(wd,ht,zIdx++);txt+='<div style="position: absolute; top: 0; left: 0; width: '+wd+'px; z-index: '+zIdx+';">'+content+'</div>';layerWrite(txt);}
+function bckDropSrc(width, height, Z) {return '<iframe frameborder="0" scrolling="no" src="" width="'+width+'" height="'+height+'" style="z-index: '+Z+'; filter: Beta(Style=0,Opacity=0);"></iframe>';}
+function hideSelectBox() {if(olNs4||olOp||olIe55) return;var px, py, pw, ph, sx, sw, sy, sh, selEl, v;
+if(olIe4) v=0;else {v=navigator.userAgent.match(/Gecko\/(\d{8})/i);if(!v) return;v=parseInt(v[1]);}
+if (v<20030624) {px=parseInt(over.style.left);py=parseInt(over.style.top);pw=o3_width;ph=(o3_aboveheight?parseInt(o3_aboveheight):over.offsetHeight);selEl=(olIe4)?o3_frame.document.all.tags("SELECT"):o3_frame.document.getElementsByTagName("SELECT");for (var i=0; i<selEl.length; i++) {if(!olIe4&&selEl[i].size<2) continue;sx=pageLocation(selEl[i],'Left');sy=pageLocation(selEl[i],'Top');sw=selEl[i].offsetWidth;sh=selEl[i].offsetHeight;if((px+pw)<sx||px>(sx+sw)||(py+ph)<sy||py>(sy+sh)) continue;selEl[i].isHidden=1;selEl[i].style.visibility='hidden';}
+}
+}
+function showSelectBox() {if(olNs4||olOp||olIe55) return;var selEl, v;
+if(olIe4) v=0;else {v=navigator.userAgent.match(/Gecko\/(\d{8})/i);if(!v) return;v=parseInt(v[1]);}
+if(v<20030624) {selEl=(olIe4)?o3_frame.document.all.tags("SELECT"):o3_frame.document.getElementsByTagName("SELECT");for (var i=0; i<selEl.length; i++) {if(typeof selEl[i].isHidden!='undefined'&&selEl[i].isHidden) {selEl[i].isHidden=0;selEl[i].style.visibility='visible';}
+}
+}
+}
+function pageLocation(o,t){var x=0
+while(o.offsetParent){x+=o['offset'+t]
+o=o.offsetParent
+}
+x+=o['offset'+t]
+return x
+}
+if (!(olNs4||olOp||olIe55||navigator.userAgent.indexOf('Netscape6')!=-1)) {var MMStr=olMouseMove.toString();var strRe=/(if\s*\(o3_allowmove\s*==\s*1.*\)\s*)/;var f=MMStr.match(strRe);
+if (f) {var ls=MMStr.search(strRe);ls+=f[1].length;var le=MMStr.substring(ls).search(/[;|}]\n/);MMStr=MMStr.substring(0,ls)+' { runHook("placeLayer",FREPLACE); if(olHideForm) hideSelectBox(); '+MMStr.substring(ls+(le!=-1?le+3:0));document.writeln('<script type="text/javascript">\n<!--\n'+MMStr+'\n
+}
+f=capExtent.onmousemove.toString().match(/function[ ]+(\w*)\(/);if (f&&f[1]!='annoymous') capExtent.onmousemove=olMouseMove;}
+registerHook("createPopup",generatePopUp,FAFTER);registerHook("hideObject",showSelectBox,FAFTER);olHideForm=1;
\ No newline at end of file
--- /dev/null
+//\/////
+//\ overLIB 4.00 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\
+//\ Contributors are listed on the homepage.
+//\ This file might be old, always check for the latest version at:
+//\ http://www.bosrup.com/web/overlib/
+//\
+//\ Please read the license agreement (available through the link above)
+//\ before using overLIB. Direct any licensing questions to erik@bosrup.com.
+//\
+//\ Do not sell this as your own work or remove this copyright notice.
+//\ For full details on copying or changing this script please read the
+//\ license agreement at the link above. Please give credit on sites that
+//\ use overLIB and submit changes of the script so other people can use
+//\ them as well.
+//\/////
+//\ THIS IS A VERY MODIFIED VERSION. DO NOT EDIT OR PUBLISH. GET THE ORIGINAL!
+var olLoaded=0;var pmStart=10000000; var pmUpper=10001000; var pmCount=pmStart+1; var pms=new Array(); var olInfo=new Info('4.00', 1);var FREPLACE=0; var FBEFORE=1; var FAFTER=2; var FALTERNATE=3;var olHideForm=0;registerCommands('donothing,inarray,caparray,sticky,background,noclose,caption,left,right,center,offsetx,offsety,fgcolor,bgcolor,textcolor,capcolor,closecolor,width,border,cellpad,status,autostatus,autostatuscap,height,closetext,snapx,snapy,fixx,fixy,relx,rely,fgbackground,bgbackground,padx,pady,fullhtml,above,below,capicon,textfont,captionfont,closefont,textsize,captionsize,closesize,timeout,function,delay,hauto,vauto,closeclick,wrap,followmouse,mouseoff,closetitle,cssoff,cssclass,fgclass,bgclass,textfontclass,captionfontclass,closefontclass');
+if (typeof ol_fgcolor=='undefined') var ol_fgcolor="#CCCCFF";if (typeof ol_bgcolor=='undefined') var ol_bgcolor="#333399";if (typeof ol_textcolor=='undefined') var ol_textcolor="#000000";if (typeof ol_capcolor=='undefined') var ol_capcolor="#FFFFFF";if (typeof ol_closecolor=='undefined') var ol_closecolor="#9999FF";if (typeof ol_textfont=='undefined') var ol_textfont="Verdana,Arial,Helvetica";if (typeof ol_captionfont=='undefined') var ol_captionfont="Verdana,Arial,Helvetica";if (typeof ol_closefont=='undefined') var ol_closefont="Verdana,Arial,Helvetica";if (typeof ol_textsize=='undefined') var ol_textsize="1";if (typeof ol_captionsize=='undefined') var ol_captionsize="1";if (typeof ol_closesize=='undefined') var ol_closesize="1";if (typeof ol_width=='undefined') var ol_width="200";if (typeof ol_border=='undefined') var ol_border="1";if (typeof ol_cellpad=='undefined') var ol_cellpad=2;if (typeof ol_offsetx=='undefined') var ol_offsetx=10;if (typeof ol_offsety=='undefined') var ol_offsety=10;if (typeof ol_text=='undefined') var ol_text="Default Text";if (typeof ol_cap=='undefined') var ol_cap="";if (typeof ol_sticky=='undefined') var ol_sticky=0;if (typeof ol_background=='undefined') var ol_background="";if (typeof ol_close=='undefined') var ol_close="Close";if (typeof ol_hpos=='undefined') var ol_hpos=RIGHT;if (typeof ol_status=='undefined') var ol_status="";if (typeof ol_autostatus=='undefined') var ol_autostatus=0;if (typeof ol_height=='undefined') var ol_height=-1;if (typeof ol_snapx=='undefined') var ol_snapx=0;if (typeof ol_snapy=='undefined') var ol_snapy=0;if (typeof ol_fixx=='undefined') var ol_fixx=-1;if (typeof ol_fixy=='undefined') var ol_fixy=-1;if (typeof ol_relx=='undefined') var ol_relx=null;if (typeof ol_rely=='undefined') var ol_rely=null;if (typeof ol_fgbackground=='undefined') var ol_fgbackground="";if (typeof ol_bgbackground=='undefined') var ol_bgbackground="";if (typeof ol_padxl=='undefined') var ol_padxl=1;if (typeof ol_padxr=='undefined') var ol_padxr=1;if (typeof ol_padyt=='undefined') var ol_padyt=1;if (typeof ol_padyb=='undefined') var ol_padyb=1;if (typeof ol_fullhtml=='undefined') var ol_fullhtml=0;if (typeof ol_vpos=='undefined') var ol_vpos=BELOW;if (typeof ol_aboveheight=='undefined') var ol_aboveheight=0;if (typeof ol_capicon=='undefined') var ol_capicon="";if (typeof ol_frame=='undefined') var ol_frame=self;if (typeof ol_timeout=='undefined') var ol_timeout=0;if (typeof ol_function=='undefined') var ol_function=null;if (typeof ol_delay=='undefined') var ol_delay=0;if (typeof ol_hauto=='undefined') var ol_hauto=0;if (typeof ol_vauto=='undefined') var ol_vauto=0;if (typeof ol_closeclick=='undefined') var ol_closeclick=0;if (typeof ol_wrap=='undefined') var ol_wrap=0;if (typeof ol_followmouse=='undefined') var ol_followmouse=1;if (typeof ol_mouseoff=='undefined') var ol_mouseoff=0;if (typeof ol_closetitle=='undefined') var ol_closetitle='Close';if (typeof ol_css=='undefined') var ol_css=CSSOFF;if (typeof ol_fgclass=='undefined') var ol_fgclass="";if (typeof ol_bgclass=='undefined') var ol_bgclass="";if (typeof ol_textfontclass=='undefined') var ol_textfontclass="";if (typeof ol_captionfontclass=='undefined') var ol_captionfontclass="";if (typeof ol_closefontclass=='undefined') var ol_closefontclass="";
+if (typeof ol_texts=='undefined') var ol_texts=new Array("Text 0", "Text 1");if (typeof ol_caps=='undefined') var ol_caps=new Array("Caption 0", "Caption 1");
+var o3_text="";var o3_cap="";var o3_sticky=0;var o3_background="";var o3_close="Close";var o3_hpos=RIGHT;var o3_offsetx=2;var o3_offsety=2;var o3_fgcolor="";var o3_bgcolor="";var o3_textcolor="";var o3_capcolor="";var o3_closecolor="";var o3_width=100;var o3_border=1;var o3_cellpad=2;var o3_status="";var o3_autostatus=0;var o3_height=-1;var o3_snapx=0;var o3_snapy=0;var o3_fixx=-1;var o3_fixy=-1;var o3_relx=null;var o3_rely=null;var o3_fgbackground="";var o3_bgbackground="";var o3_padxl=0;var o3_padxr=0;var o3_padyt=0;var o3_padyb=0;var o3_fullhtml=0;var o3_vpos=BELOW;var o3_aboveheight=0;var o3_capicon="";var o3_textfont="Verdana,Arial,Helvetica";var o3_captionfont="Verdana,Arial,Helvetica";var o3_closefont="Verdana,Arial,Helvetica";var o3_textsize="1";var o3_captionsize="1";var o3_closesize="1";var o3_frame=self;var o3_timeout=0;var o3_timerid=0;var o3_allowmove=0;var o3_function=null;var o3_delay=0;var o3_delayid=0;var o3_hauto=0;var o3_vauto=0;var o3_closeclick=0;var o3_wrap=0;var o3_followmouse=1;var o3_mouseoff=0;var o3_closetitle='';var o3_css=CSSOFF;var o3_fgclass="";var o3_bgclass="";var o3_textfontclass="";var o3_captionfontclass="";var o3_closefontclass="";
+var o3_x=0;var o3_y=0;var o3_showingsticky=0;var o3_removecounter=0;
+var over=null;var fnRef, hoveringSwitch=false;
+var isMac=(navigator.userAgent.indexOf("Mac")!=-1);var olOp=(navigator.userAgent.toLowerCase().indexOf('opera 7.')>-1);var olNs4=(navigator.appName=='Netscape'&&parseInt(navigator.appVersion)==4);var olNs6=(document.getElementById)?true:false;var olIe4=(document.all)?true:false;var olIe5=false;var olIe55=false;var docRoot='document.body';
+if (olNs4) {var oW=window.innerWidth;var oH=window.innerHeight;window.onresize=function() { if (oW!=window.innerWidth||oH!=window.innerHeight) location.reload(); }
+}
+if (olIe4) {var versNum=parseFloat(navigator.userAgent.match(/MSIE (\d\.\d+)\.*/i)[1]);if (versNum>=5){olIe5=true;olIe55=(versNum>=5.5&&!olOp)?true:false;if (olNs6) olNs6=false;}
+if (olNs6) olIe4=false;}
+if (document.compatMode&&document.compatMode=='CSS1Compat') {docRoot=((olIe4&&!olOp)?'document.documentElement':docRoot);}
+if(window.addEventListener) window.addEventListener("load",OLonLoad_handler,true);else if (window.attachEvent) window.attachEvent("onload",OLonLoad_handler);else window.onload=OLonLoad_handler;
+var olCheckMouseCapture=true;if ((olNs4||olNs6||olIe4)) {olMouseCapture();} else {overlib=no_overlib;nd=no_overlib;ver3fix=true;}
+function overlib() {if (!olLoaded||isExclusive(overlib.arguments)) return true;if (olCheckMouseCapture) olMouseCapture();if (over) cClick();
+o3_text=ol_text;o3_cap=ol_cap;o3_sticky=ol_sticky;o3_background=ol_background;o3_close=ol_close;o3_hpos=ol_hpos;o3_offsetx=ol_offsetx;o3_offsety=ol_offsety;o3_fgcolor=ol_fgcolor;o3_bgcolor=ol_bgcolor;o3_textcolor=ol_textcolor;o3_capcolor=ol_capcolor;o3_closecolor=ol_closecolor;o3_width=ol_width;o3_border=ol_border;o3_cellpad=ol_cellpad;o3_status=ol_status;o3_autostatus=ol_autostatus;o3_height=ol_height;o3_snapx=ol_snapx;o3_snapy=ol_snapy;o3_fixx=ol_fixx;o3_fixy=ol_fixy;o3_relx=ol_relx;o3_rely=ol_rely;o3_fgbackground=ol_fgbackground;o3_bgbackground=ol_bgbackground;o3_padxl=ol_padxl;o3_padxr=ol_padxr;o3_padyt=ol_padyt;o3_padyb=ol_padyb;o3_fullhtml=ol_fullhtml;o3_vpos=ol_vpos;o3_aboveheight=ol_aboveheight;o3_capicon=ol_capicon;o3_textfont=ol_textfont;o3_captionfont=ol_captionfont;o3_closefont=ol_closefont;o3_textsize=ol_textsize;o3_captionsize=ol_captionsize;o3_closesize=ol_closesize;o3_timeout=ol_timeout;o3_function=ol_function;o3_delay=ol_delay;o3_hauto=ol_hauto;o3_vauto=ol_vauto;o3_closeclick=ol_closeclick;o3_wrap=ol_wrap;o3_followmouse=ol_followmouse;o3_mouseoff=ol_mouseoff;o3_closetitle=ol_closetitle;o3_css=ol_css;o3_fgclass=ol_fgclass;o3_bgclass=ol_bgclass;o3_textfontclass=ol_textfontclass;o3_captionfontclass=ol_captionfontclass;o3_closefontclass=ol_closefontclass;
+setRunTimeVariables();
+fnRef='';
+o3_frame=ol_frame;
+if (olNs4) {over=o3_frame.document.layers['overDiv'];} else if (document.all) {over=o3_frame.document.all['overDiv'];} else if (document.getElementById) {over=o3_frame.document.getElementById("overDiv");}
+parseTokens('o3_', overlib.arguments);if (!postParseChecks()) return false;
+if (o3_delay==0) {return runHook("olMain", FREPLACE);} else {o3_delayid=setTimeout("runHook('olMain', FREPLACE)", o3_delay);return false;}
+}
+function nd(time) {if (olLoaded&&!isExclusive()) {if (time&&!o3_delay) {if (o3_timerid>0) clearTimeout(o3_timerid);
+o3_timerid=setTimeout("cClick()",(o3_timeout=time));}
+if (o3_removecounter>=1) { o3_showingsticky=0 };
+if (o3_showingsticky==0) {o3_allowmove=0;if (over!=null&&o3_timerid==0) runHook("hideObject", FREPLACE, over);} else {o3_removecounter++;}
+}
+return true;}
+function cClick() {if (olLoaded) {runHook("hideObject", FREPLACE, over);o3_showingsticky=0;}
+return false;}
+function overlib_pagedefaults() {parseTokens('ol_', overlib_pagedefaults.arguments);}
+function olMain() {var layerhtml, styleType;runHook("olMain", FBEFORE);
+if (o3_background!=""||o3_fullhtml) {
+layerhtml=runHook('ol_content_background', FALTERNATE, o3_css, o3_text, o3_background, o3_fullhtml);} else {
+styleType=(pms[o3_css-1-pmStart]=="cssoff"||pms[o3_css-1-pmStart]=="cssclass");
+if (o3_fgbackground!="") o3_fgbackground="background=\""+o3_fgbackground+"\"";if (o3_bgbackground!="") o3_bgbackground=(styleType?"background=\""+o3_bgbackground+"\"":o3_bgbackground);
+if (o3_fgcolor!="") o3_fgcolor=(styleType?"bgcolor=\""+o3_fgcolor+"\"":o3_fgcolor);if (o3_bgcolor!="") o3_bgcolor=(styleType?"bgcolor=\""+o3_bgcolor+"\"":o3_bgcolor);
+if (o3_height>0) o3_height=(styleType?"height=\""+o3_height+"\"":o3_height);else o3_height="";
+if (o3_cap=="") {
+layerhtml=runHook('ol_content_simple', FALTERNATE, o3_css, o3_text);} else {
+if (o3_sticky) {
+layerhtml=runHook('ol_content_caption', FALTERNATE, o3_css, o3_text, o3_cap, o3_close);} else {
+layerhtml=runHook('ol_content_caption', FALTERNATE, o3_css, o3_text, o3_cap, "");}
+}
+}
+if (o3_sticky) {if (o3_timerid>0) {clearTimeout(o3_timerid);o3_timerid=0;}
+o3_showingsticky=1;o3_removecounter=0;}
+if (!runHook("createPopup", FREPLACE, layerhtml)) return false;
+if (o3_autostatus>0) {o3_status=o3_text;if (o3_autostatus>1) o3_status=o3_cap;}
+o3_allowmove=0;
+if (o3_timeout>0) {if (o3_timerid>0) clearTimeout(o3_timerid);o3_timerid=setTimeout("cClick()", o3_timeout);}
+runHook("disp", FREPLACE, o3_status);runHook("olMain", FAFTER);
+if (o3_status!='') {return true;} else {return;}
+}
+function ol_content_simple(text) {txt='<table width="'+o3_width+'" border="0" cellpadding="'+o3_border+'" cellspacing="0" '+(o3_bgclass?'class="'+o3_bgclass+'"':o3_bgcolor+' '+o3_height)+'><tr><td><table width="100%" border="0" cellpadding="'+o3_cellpad+'" cellspacing="0" '+(o3_fgclass?'class="'+o3_fgclass+'"':o3_fgcolor+' '+o3_fgbackground+' '+o3_height)+'><tr><td valign="TOP"'+(o3_textfontclass?' class="'+o3_textfontclass+'">':'>')+(o3_textfontclass?'':wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass?'':wrapStr(1,o3_textsize))+'</td></tr></table></td></tr></table>';
+set_background("");return txt;}
+function ol_content_caption(text,title,close) {var nameId;closing="";closeevent="onmouseover";if (o3_closeclick==1) closeevent=(o3_closetitle?"title='"+o3_closetitle+"'":"")+" onclick";if (o3_capicon!="") {nameId=' hspace=\"5\"'+' align=\"middle\" alt=\"\"';if (typeof o3_dragimg!='undefined'&&o3_dragimg) nameId=' hspace=\"5\"'+' name=\"'+o3_dragimg+'\" id=\"'+o3_dragimg+'\" align=\"middle\" alt=\"Drag Enabled\" title=\"Drag Enabled\"';o3_capicon='<img src=\"'+o3_capicon+'\"'+nameId+' />';}
+if (close!="") closing='<td '+(o3_closefontclass?'class="'+o3_closefontclass:'align="RIGHT')+'"><a href="javascript:return '+fnRef+'cClick();" '+closeevent+'="return '+fnRef+'cClick();">'+(o3_closefontclass?'':wrapStr(0,o3_closesize,'close'))+close+(o3_closefontclass?'':wrapStr(1,o3_closesize,'close'))+'</a></td>';txt='<table width="'+o3_width+'" border="0" cellpadding="'+o3_border+'" cellspacing="0" '+(o3_bgclass?'class="'+o3_bgclass+'"':o3_bgcolor+' '+o3_bgbackground+' '+o3_height)+'><tr><td><table width="100%" border="0" cellpadding="0" cellspacing="0"><tr><td'+(o3_captionfontclass?' class="'+o3_captionfontclass+'">':'>')+(o3_captionfontclass?'':'<b>'+wrapStr(0,o3_captionsize,'caption'))+o3_capicon+title+(o3_captionfontclass?'':wrapStr(1,o3_captionsize)+'</b>')+'</td>'+closing+'</tr></table><table width="100%" border="0" cellpadding="'+o3_cellpad+'" cellspacing="0" '+(o3_fgclass?'class="'+o3_fgclass+'"':o3_fgcolor+' '+o3_fgbackground+' '+o3_height)+'><tr><td valign="TOP"'+(o3_textfontclass?' class="'+o3_textfontclass+'">' :'>')+(o3_textfontclass?'':wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass?'':wrapStr(1,o3_textsize))+'</td></tr></table></td></tr></table>';
+set_background("");return txt;}
+function ol_content_background(text,picture,hasfullhtml) {if (hasfullhtml) {txt=text;} else {txt='<table width="'+o3_width+'" border="0" cellpadding="0" cellspacing="0" height="'+o3_height+'"><tr><td colspan="3" height="'+o3_padyt+'"></td></tr><tr><td width="'+o3_padxl+'"></td><td valign="TOP" width="'+(o3_width-o3_padxl-o3_padxr)+'">'+wrapStr(0,o3_textsize,'text')+text+wrapStr(1,o3_textsize)+'</td><td width="'+o3_padxr+'"></td></tr><tr><td colspan="3" height="'+o3_padyb+'"></td></tr></table>';}
+set_background(picture);return txt;}
+function set_background(pic) {if (pic=="") {if (olNs4) {over.background.src=null;} else if (over.style) {over.style.backgroundImage="none";}
+} else {if (olNs4) {over.background.src=pic;} else if (over.style) {over.style.backgroundImage="url("+pic+")";}
+}
+}
+function disp(statustext) {runHook("disp", FBEFORE);
+if (o3_allowmove==0) {runHook("placeLayer", FREPLACE);runHook("showObject", FREPLACE, over);o3_allowmove=(o3_sticky||o3_followmouse==0)?0:1;}
+runHook("disp", FAFTER);
+if (statustext!="") self.status=statustext;}
+function createPopup(lyrContent){runHook("createPopup", FBEFORE);
+if (o3_wrap&&!(olNs4||olOp)) {if (olIe4) {over.style.pixelWidth=0;} else if (olNs6) {repositionTo(over, 0,-over.offsetHeight);}
+}
+layerWrite(lyrContent);
+if (o3_wrap) o3_width=(olNs4?over.clip.width:over.offsetWidth);
+runHook("createPopup", FAFTER, lyrContent);
+return true;}
+function placeLayer() {var placeX, placeY, widthFix=0;
+if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientWidth=='number'")&&eval('o3_frame.'+docRoot+'.clientWidth')) {iwidth=eval('o3_frame.'+docRoot+'.clientWidth');} else if (typeof(o3_frame.innerWidth)=='number') {widthFix=Math.ceil(1.2*(o3_frame.outerWidth-o3_frame.innerWidth));iwidth=o3_frame.innerWidth;}
+winoffset=(olIe4)?eval('o3_frame.'+docRoot+'.scrollLeft'):o3_frame.pageXOffset;var parsedWidth=parseInt(o3_width);
+if (o3_fixx>-1||o3_relx!=null) {
+placeX=(o3_relx!=null?( o3_relx<0?winoffset+o3_relx+iwidth-parsedWidth-widthFix:winoffset+o3_relx):o3_fixx);} else {
+if (o3_hauto==1) {if ((o3_x-winoffset)>(iwidth/2)) {o3_hpos=LEFT;} else {o3_hpos=RIGHT;}
+}
+if (o3_hpos==CENTER) {placeX=o3_x+o3_offsetx-(parsedWidth/2);
+if (placeX<winoffset) placeX=winoffset;}
+if (o3_hpos==RIGHT) {placeX=o3_x+o3_offsetx;
+if ((placeX+parsedWidth)>(winoffset+iwidth-widthFix)) {placeX=iwidth+winoffset-parsedWidth-widthFix;if (placeX<0) placeX=0;}
+}
+if (o3_hpos==LEFT) {placeX=o3_x-o3_offsetx-parsedWidth;if (placeX<winoffset) placeX=winoffset;}
+if (o3_snapx>1) {var snapping=placeX % o3_snapx;
+if (o3_hpos==LEFT) {placeX=placeX-(o3_snapx+snapping);} else {
+placeX=placeX+(o3_snapx-snapping);}
+if (placeX<winoffset) placeX=winoffset;}
+}
+if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientHeight=='number'")&&eval('o3_frame.'+docRoot+'.clientHeight')) {iheight=eval('o3_frame.'+docRoot+'.clientHeight');} else if (typeof(o3_frame.innerHeight)=='number') {iheight=o3_frame.innerHeight;}
+scrolloffset=(olIe4)?eval('o3_frame.'+docRoot+'.scrollTop'):o3_frame.pageYOffset;var parsedHeight=(o3_aboveheight?parseInt(o3_aboveheight):(olNs4?over.clip.height:over.offsetHeight));
+if (o3_fixy>-1||o3_rely!=null) {
+placeY=(o3_rely!=null?(o3_rely<0?scrolloffset+o3_rely+iheight-parsedHeight:scrolloffset+o3_rely):o3_fixy);} else {
+if (o3_vauto==1) {if ((o3_y-scrolloffset)>(iheight/2)) {o3_vpos=ABOVE;} else {o3_vpos=BELOW;}
+}
+if (o3_vpos==ABOVE) {if (o3_aboveheight==0) o3_aboveheight=parsedHeight;
+placeY=o3_y-(o3_aboveheight+o3_offsety);if (placeY<scrolloffset) placeY=scrolloffset;} else {
+placeY=o3_y+o3_offsety;}
+if (o3_snapy>1) {var snapping=placeY % o3_snapy;
+if (o3_aboveheight>0&&o3_vpos==ABOVE) {placeY=placeY-(o3_snapy+snapping);} else {placeY=placeY+(o3_snapy-snapping);}
+if (placeY<scrolloffset) placeY=scrolloffset;}
+}
+repositionTo(over, placeX, placeY);}
+function olMouseMove(e) {var e=(e)?e:event;
+if (e.pageX) {o3_x=e.pageX;o3_y=e.pageY;} else if (e.clientX) {o3_x=eval('e.clientX+o3_frame.'+docRoot+'.scrollLeft');o3_y=eval('e.clientY+o3_frame.'+docRoot+'.scrollTop');}
+if (o3_allowmove==1) runHook("placeLayer", FREPLACE);
+if (hoveringSwitch&&!olNs4&&runHook("cursorOff", FREPLACE)) {cClick();hoveringSwitch=!hoveringSwitch;}
+}
+function no_overlib() { return ver3fix; }
+function olMouseCapture() {capExtent=document;var fN, mseHandler=olMouseMove;var re=/function[ ]+(\w+)\(/;
+if (document.onmousemove||(!olIe4&&window.onmousemove)) {if (window.onmousemove) capExtent=window;fN=capExtent.onmousemove.toString().match(re);
+if (fN[1]=='anonymous'||fN[1]=='olMouseMove') {olCheckMouseCapture=false;return;}
+var str=fN[1]+'(e); '+'olMouseMove(e); ';mseHandler=new Function('e', str);}
+capExtent.onmousemove=mseHandler;if (olNs4) capExtent.captureEvents(Event.MOUSEMOVE);}
+function parseTokens(pf, ar) {
+var v, mode=-1, par=(pf!='ol_');var fnMark=(par&&!ar.length?1:0);
+for (i=0; i<ar.length; i++) {if (mode<0) {
+if (typeof ar[i]=='number'&&ar[i]>pmStart&&ar[i]<pmUpper) {fnMark=(par?1:0);i--;} else {switch(pf) {case 'ol_':
+ol_text=ar[i].toString();break;default:
+o3_text=ar[i].toString();}
+}
+mode=0;} else {
+if (ar[i]>=pmCount||ar[i]==DONOTHING) { continue; }
+if (ar[i]==INARRAY) { fnMark=0; eval(pf+'text=ol_texts['+ar[++i]+'].toString()'); continue; }
+if (ar[i]==CAPARRAY) { eval(pf+'cap=ol_caps['+ar[++i]+'].toString()'); continue; }
+if (ar[i]==STICKY) { if (pf!='ol_') eval(pf+'sticky=1'); continue; }
+if (ar[i]==BACKGROUND) { eval(pf+'background="'+ar[++i]+'"'); continue; }
+if (ar[i]==NOCLOSE) { if (pf!='ol_') opt_NOCLOSE(); continue; }
+if (ar[i]==CAPTION) { eval(pf+"cap='"+escSglQuote(ar[++i])+"'"); continue; }
+if (ar[i]==CENTER||ar[i]==LEFT||ar[i]==RIGHT) { eval(pf+'hpos='+ar[i]); continue; }
+if (ar[i]==OFFSETX) { eval(pf+'offsetx='+ar[++i]); continue; }
+if (ar[i]==OFFSETY) { eval(pf+'offsety='+ar[++i]); continue; }
+if (ar[i]==FGCOLOR) { eval(pf+'fgcolor="'+ar[++i]+'"'); continue; }
+if (ar[i]==BGCOLOR) { eval(pf+'bgcolor="'+ar[++i]+'"'); continue; }
+if (ar[i]==TEXTCOLOR) { eval(pf+'textcolor="'+ar[++i]+'"'); continue; }
+if (ar[i]==CAPCOLOR) { eval(pf+'capcolor="'+ar[++i]+'"'); continue; }
+if (ar[i]==CLOSECOLOR) { eval(pf+'closecolor="'+ar[++i]+'"'); continue; }
+if (ar[i]==WIDTH) { eval(pf+'width='+ar[++i]); continue; }
+if (ar[i]==BORDER) { eval(pf+'border='+ar[++i]); continue; }
+if (ar[i]==CELLPAD) { i=opt_MULTIPLEARGS(++i,ar,(pf+'cellpad')); continue; }
+if (ar[i]==STATUS) { eval(pf+"status='"+escSglQuote(ar[++i])+"'"); continue; }
+if (ar[i]==AUTOSTATUS) { eval(pf+'autostatus=('+pf+'autostatus==1)?0:1'); continue; }
+if (ar[i]==AUTOSTATUSCAP) { eval(pf+'autostatus=('+pf+'autostatus==2)?0:2'); continue; }
+if (ar[i]==HEIGHT) { eval(pf+'height='+pf+'aboveheight='+ar[++i]); continue; }
+if (ar[i]==CLOSETEXT) { eval(pf+"close='"+escSglQuote(ar[++i])+"'"); continue; }
+if (ar[i]==SNAPX) { eval(pf+'snapx='+ar[++i]); continue; }
+if (ar[i]==SNAPY) { eval(pf+'snapy='+ar[++i]); continue; }
+if (ar[i]==FIXX) { eval(pf+'fixx='+ar[++i]); continue; }
+if (ar[i]==FIXY) { eval(pf+'fixy='+ar[++i]); continue; }
+if (ar[i]==RELX) { eval(pf+'relx='+ar[++i]); continue; }
+if (ar[i]==RELY) { eval(pf+'rely='+ar[++i]); continue; }
+if (ar[i]==FGBACKGROUND) { eval(pf+'fgbackground="'+ar[++i]+'"'); continue; }
+if (ar[i]==BGBACKGROUND) { eval(pf+'bgbackground="'+ar[++i]+'"'); continue; }
+if (ar[i]==PADX) { eval(pf+'padxl='+ar[++i]); eval(pf+'padxr='+ar[++i]); continue; }
+if (ar[i]==PADY) { eval(pf+'padyt='+ar[++i]); eval(pf+'padyb='+ar[++i]); continue; }
+if (ar[i]==FULLHTML) { if (pf!='ol_') eval(pf+'fullhtml=1'); continue; }
+if (ar[i]==BELOW||ar[i]==ABOVE) { eval(pf+'vpos='+ar[i]); continue; }
+if (ar[i]==CAPICON) { eval(pf+'capicon="'+ar[++i]+'"'); continue; }
+if (ar[i]==TEXTFONT) { eval(pf+"textfont='"+escSglQuote(ar[++i])+"'"); continue; }
+if (ar[i]==CAPTIONFONT) { eval(pf+"captionfont='"+escSglQuote(ar[++i])+"'"); continue; }
+if (ar[i]==CLOSEFONT) { eval(pf+"closefont='"+escSglQuote(ar[++i])+"'"); continue; }
+if (ar[i]==TEXTSIZE) { eval(pf+'textsize="'+ar[++i]+'"'); continue; }
+if (ar[i]==CAPTIONSIZE) { eval(pf+'captionsize="'+ar[++i]+'"'); continue; }
+if (ar[i]==CLOSESIZE) { eval(pf+'closesize="'+ar[++i]+'"'); continue; }
+if (ar[i]==TIMEOUT) { eval(pf+'timeout='+ar[++i]); continue; }
+if (ar[i]==FUNCTION) { if (pf=='ol_') { if (typeof ar[i+1]!='number') { v=ar[++i]; ol_function=(typeof v=='function'?v:null); }} else {fnMark=0; v=null; if (typeof ar[i+1]!='number') v=ar[++i]; opt_FUNCTION(v); } continue; }
+if (ar[i]==DELAY) { eval(pf+'delay='+ar[++i]); continue; }
+if (ar[i]==HAUTO) { eval(pf+'hauto=('+pf+'hauto==0)?1:0'); continue; }
+if (ar[i]==VAUTO) { eval(pf+'vauto=('+pf+'vauto==0)?1:0'); continue; }
+if (ar[i]==CLOSECLICK) { eval(pf+'closeclick=('+pf+'closeclick==0)?1:0'); continue; }
+if (ar[i]==WRAP) { eval(pf+'wrap=('+pf+'wrap==0)?1:0'); continue; }
+if (ar[i]==FOLLOWMOUSE) { eval(pf+'followmouse=('+pf+'followmouse==1)?0:1'); continue; }
+if (ar[i]==MOUSEOFF) { eval(pf+'mouseoff=('+pf+'mouseoff==0)?1:0'); continue; }
+if (ar[i]==CLOSETITLE) { eval(pf+"closetitle='"+escSglQuote(ar[++i])+"'"); continue; }
+if (ar[i]==CSSOFF||ar[i]==CSSCLASS) { eval(pf+'css='+ar[i]); continue; }
+if (ar[i]==FGCLASS) { eval(pf+'fgclass="'+ar[++i]+'"'); continue; }
+if (ar[i]==BGCLASS) { eval(pf+'bgclass="'+ar[++i]+'"'); continue; }
+if (ar[i]==TEXTFONTCLASS) { eval(pf+'textfontclass="'+ar[++i]+'"'); continue; }
+if (ar[i]==CAPTIONFONTCLASS) { eval(pf+'captionfontclass="'+ar[++i]+'"'); continue; }
+if (ar[i]==CLOSEFONTCLASS) { eval(pf+'closefontclass="'+ar[++i]+'"'); continue; }
+i=parseCmdLine(pf, i, ar);}
+}
+if (fnMark&&o3_function) o3_text=o3_function();
+if ((pf=='o3_')&&o3_wrap) {o3_width=0;
+if (olOp||(olIe4&&isMac)) {var tReg=/<.*\n*>/ig;if (!tReg.test(o3_text)) o3_text=o3_text.replace(/[ ]+/g, ' ');if (!tReg.test(o3_cap))o3_cap=o3_cap.replace(/[ ]+/g, ' ');}
+}
+if ((pf=='o3_')&&o3_sticky) {if (!o3_close&&(o3_frame!=ol_frame)) o3_close=ol_close;if (o3_mouseoff&&(o3_frame==ol_frame)) opt_NOCLOSE(' ');}
+}
+function layerWrite(txt) {txt+="\n";if (olNs4) {var lyr=o3_frame.document.overDiv.document
+lyr.write(txt)
+lyr.close()
+} else if (typeof over.innerHTML!='undefined') {if (olIe5&&isMac) over.innerHTML='';over.innerHTML=txt;} else {range=o3_frame.document.createRange();range.setStartAfter(over);domfrag=range.createContextualFragment(txt);
+while (over.hasChildNodes()) {over.removeChild(over.lastChild);}
+over.appendChild(domfrag);}
+}
+function showObject(obj) {runHook("showObject", FBEFORE);
+var theObj=(olNs4?obj:obj.style);theObj.visibility='visible';
+runHook("showObject", FAFTER);}
+function hideObject(obj) {runHook("hideObject", FBEFORE);
+var theObj=(olNs4?obj:obj.style);theObj.visibility='hidden';
+if (o3_timerid>0) clearTimeout(o3_timerid);if (o3_delayid>0) clearTimeout(o3_delayid);
+o3_timerid=0;o3_delayid=0;self.status="";
+if (over.onmouseout||over.onmouseover) {if (olNs4) over.releaseEvents(Event.MOUSEOUT||Event.MOUSEOVER);over.onmouseout=over.onmouseover=null;}
+runHook("hideObject", FAFTER);}
+function repositionTo(obj, xL, yL) {var theObj=(olNs4?obj:obj.style);theObj.left=xL+(!olNs4?'px':0);theObj.top=yL+(!olNs4?'px':0);}
+function cursorOff() {var left=parseInt(over.style.left);var top=parseInt(over.style.top);var right=left+over.offsetWidth;var bottom=top+over.offsetHeight;
+if (o3_x<left||o3_x>right||o3_y<top||o3_y>bottom) return true;
+return false;}
+function opt_FUNCTION(callme) {o3_text=(callme?(typeof callme=='string'?(/.+\(.*\)/.test(callme)?eval(callme):callme):callme()):(o3_function?o3_function():'No Function'));
+return 0;}
+function opt_NOCLOSE(unused) {if (!unused) o3_close="";
+if (olNs4) {over.captureEvents(Event.MOUSEOUT||Event.MOUSEOVER);over.onmouseover=function () { if (o3_timerid>0) { clearTimeout(o3_timerid); o3_timerid=0; } }
+over.onmouseout=cClick;} else {over.onmouseover=function () {hoveringSwitch=true; if (o3_timerid>0) { clearTimeout(o3_timerid); o3_timerid=0; } }
+}
+return 0;}
+function opt_MULTIPLEARGS(i, args, parameter) {var k=i, l, re, pV, str='';
+for(k=i; k<args.length; k++) {str+=args[k]+',';if(typeof args[k]=='number'&&args[k]>pmStart) break;}
+if(k>=args.length) l=str.length-1;else {re=eval('/,'+args[k]+'/');l=str.search(re);}
+k--;str=str.substring(0, l);pV=(olNs4&&/cellpad/i.test(parameter))?str.split(',')[0]:str;eval(parameter+'="'+pV+'"');
+return k;}
+function nbspCleanup() {if (o3_wrap&&(olOp||(olIe4&&isMac))) {o3_text=o3_text.replace(/\ /g, ' ');o3_cap=o3_cap.replace(/\ /g, ' ');}
+}
+function escSglQuote(str) {return str.toString().replace(/'/g,"\\'");}
+function OLonLoad_handler(e) {if (!olLoaded) olLoaded=1;
+if (window.removeEventListener) window.removeEventListener("load",OLonLoad_handler,true);else if (window.detachEvent) window.detachEvent("onload",OLonLoad_handler);
+if (olNs4) routeEvent(e);}
+function wrapStr(endWrap,fontSizeStr,whichString) {var fontStr, fontColor, isClose=((whichString=='close')?1:0), hasDims=/[%\-a-z]+$/.test(fontSizeStr);fontSizeStr=(olNs4)?(!hasDims?fontSizeStr:'1'):fontSizeStr;if (endWrap) return (hasDims&&!olNs4)?(isClose?'</span>':'</div>'):'</font>';else {fontStr='o3_'+whichString+'font';fontColor='o3_'+((whichString=='caption')? 'cap':whichString)+'color';return (hasDims&&!olNs4)?(isClose?'<span style="font-family: '+quoteMultiNameFonts(eval(fontStr))+'; color: '+eval(fontColor)+'; font-size: '+fontSizeStr+';">':'<div style="font-family: '+quoteMultiNameFonts(eval(fontStr))+'; color: '+eval(fontColor)+'; font-size: '+fontSizeStr+';">'):'<font face="'+eval(fontStr)+'" color="'+eval(fontColor)+'" size="'+(parseInt(fontSizeStr)>7?'7':fontSizeStr)+'">';}
+}
+function quoteMultiNameFonts(theFont) {var v, pM=theFont.split(',');for (var i=0; i<pM.length; i++) {v=pM[i];v=v.replace(/^\s+/,'').replace(/\s+$/,'');if(/\s/.test(v)&&!/['"]/.test(v)) {v="\'"+v+"\'";pM[i]=v;}
+}
+return pM.join();}
+function isExclusive(args) {return false;}
+function setRunTimeVariables(){if (typeof runTime!='undefined'&&runTime.length) {for (var k=0; k<runTime.length; k++) {runTime[k]();}
+}
+}
+function parseCmdLine(pf, i, args) {if (typeof cmdLine!='undefined'&&cmdLine.length) {for (var k=0; k<cmdLine.length; k++) {var j=cmdLine[k](pf, i, args);if (j >-1) {i=j;break;}
+}
+}
+return i;}
+function postParseChecks(){if (typeof postParse!='undefined'&&postParse.length) {for (var k=0; k<postParse.length; k++) {if (postParse[k]()) continue;return false;}
+}
+return true;}
+function registerCommands(cmdStr) {if (typeof cmdStr!='string') return;
+var pM=cmdStr.split(',');pms=pms.concat(pM);
+for (var i=0; i< pM.length; i++) {eval(pM[i].toUpperCase()+'='+pmCount++);}
+}
+function registerHook(fnHookTo, fnRef, hookType, optPm) {var hookPt, last=typeof optPm;
+if (fnHookTo=='plgIn'||fnHookTo=='postParse') return;if (typeof hookPts=='undefined') hookPts=new Array();if (typeof hookPts[fnHookTo]=='undefined') hookPts[fnHookTo]=new FunctionReference();
+hookPt=hookPts[fnHookTo];
+if (hookType!=null) {if (hookType==FREPLACE) {hookPt.ovload=fnRef;if (fnHookTo.indexOf('ol_content_')>-1) hookPt.alt[pms[CSSOFF-1-pmStart]]=fnRef;
+} else if (hookType==FBEFORE||hookType==FAFTER) {var hookPt=(hookType==1?hookPt.before:hookPt.after);
+if (typeof fnRef=='object') {hookPt=hookPt.concat(fnRef);} else {hookPt[hookPt.length++]=fnRef;}
+if (optPm) hookPt=reOrder(hookPt, fnRef, optPm);
+} else if (hookType==FALTERNATE) {if (last=='number') hookPt.alt[pms[optPm-1-pmStart]]=fnRef;}
+return;}
+}
+function registerRunTimeFunction(fn) {if (isFunction(fn)) {if (typeof runTime=='undefined') runTime=new Array();if (typeof fn=='object') {runTime=runTime.concat(fn);} else {runTime[runTime.length++]=fn;}
+}
+}
+function registerCmdLineFunction(fn){if (isFunction(fn)) {if (typeof cmdLine=='undefined') cmdLine=new Array();if (typeof fn=='object') {cmdLine=cmdLine.concat(fn);} else {cmdLine[cmdLine.length++]=fn;}
+}
+}
+function registerPostParseFunction(fn){if (isFunction(fn)) {if (typeof postParse=='undefined') postParse=new Array();if (typeof fn=='object') {postParse=postParse.concat(fn);} else {postParse[postParse.length++]=fn;}
+}
+}
+function runHook(fnHookTo, hookType) {var l=hookPts[fnHookTo], optPm, arS, ar=runHook.arguments;
+if (hookType==FREPLACE) {arS=argToString(ar, 2);
+if (typeof l=='undefined'||!(l=l.ovload)) return eval(fnHookTo+'('+arS+')');else return eval('l('+arS+')');
+} else if (hookType==FBEFORE||hookType==FAFTER) {if (typeof l=='undefined') return;l=(hookType==1?l.before:l.after);
+if (!l.length) return;
+arS=argToString(ar, 2);for (var k=0; k<l.length; k++) eval('l[k]('+arS+')');
+} else if (hookType==FALTERNATE) {optPm=ar[2];arS=argToString(ar, 3);
+if (typeof l=='undefined'||(l=l.alt[pms[optPm-1-pmStart]])=='undefined') {return eval(fnHookTo+'('+arS+')');} else {return eval('l('+arS+')');}
+}
+}
+function isFunction(fnRef) {var rtn=true;
+if (typeof fnRef=='object') {for (var i=0; i<fnRef.length; i++) {if (typeof fnRef[i]=='function') continue;rtn=false;break;}
+} else if (typeof fnRef!='function') {rtn=false;}
+return rtn;}
+function argToString(array, strtInd, argName) {var jS=strtInd, aS='', ar=array;argName=(argName?argName:'ar');
+if (ar.length>jS) {for (var k=jS; k<ar.length; k++) aS+=argName+'['+k+'], ';aS=aS.substring(0, aS.length-2);}
+return aS;}
+function reOrder(hookPt, fnRef, order) {if (!order||typeof order=='undefined'||typeof order=='number') return;
+var newPt=new Array(), match;
+if (typeof order=='function') {if (typeof fnRef=='object') {newPt=newPt.concat(fnRef);} else {newPt[newPt.length++]=fnRef;}
+for (var i=0; i<hookPt.length; i++) {match=false;if (typeof fnRef=='function'&&hookPt[i]==fnRef) {continue;} else {for(var j=0; j<fnRef.length; j++) if (hookPt[i]==fnRef[j]) {match=true;break;}
+}
+if (!match) newPt[newPt.length++]=hookPt[i];}
+newPt[newPt.length++]=order;
+} else if (typeof order=='object') {if (typeof fnRef=='object') {newPt=newPt.concat(fnRef);} else {newPt[newPt.length++]=fnRef;}
+for (var j=0; j<hookPt.length; j++) {match=false;if (typeof fnRef=='function'&&hookPt[j]==fnRef) {continue;} else {for (var i=0; i<fnRef.length; i++) if (hookPt[j]==fnRef[i]) {match=true;break;}
+}
+if (!match) newPt[newPt.length++]=hookPt[j];}
+for (i=0; i<newPt.length; i++) hookPt[i]=newPt[i];newPt.length=0;
+for (var j=0; j<hookPt.length; j++) {match=false;for (var i=0; i<order.length; i++) {if (hookPt[j]==order[i]) {match=true;break;}
+}
+if (!match) newPt[newPt.length++]=hookPt[j];}
+newPt=newPt.concat(order);}
+for(i=0; i<newPt.length; i++) hookPt[i]=newPt[i];
+return hookPt;}
+function FunctionReference() {this.ovload=null;this.before=new Array();this.after=new Array();this.alt=new Array();}
+function Info(version, prerelease) {this.version=version;this.prerelease=prerelease;
+this.simpleversion=parseInt(this.version*100);this.major=parseInt(this.simpleversion/100);this.minor=parseInt(this.simpleversion/10)-this.major * 10;this.revision=parseInt(this.simpleversion)-this.major * 100-this.minor * 10;}
+registerHook("ol_content_simple", ol_content_simple, FALTERNATE, CSSOFF);registerHook("ol_content_caption", ol_content_caption, FALTERNATE, CSSOFF);registerHook("ol_content_background", ol_content_background, FALTERNATE, CSSOFF);registerHook("ol_content_simple", ol_content_simple, FALTERNATE, CSSCLASS);registerHook("ol_content_caption", ol_content_caption, FALTERNATE, CSSCLASS);registerHook("ol_content_background", ol_content_background, FALTERNATE, CSSCLASS);registerHook("hideObject", nbspCleanup, FAFTER);
--- /dev/null
+//\/////
+//\ overLIB Shadow Plugin
+//\ This file requires overLIB 4.00 or later.
+//\
+//\ overLIB 4.00 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2003. All rights reserved.
+//\ Contributors are listed on the homepage.
+//\ See http://www.bosrup.com/web/overlib/ for details.
+//\/////
+if (typeof olInfo=='undefined'||olInfo.simpleversion<400) alert('overLIB 4.00 or later is required for the Shadow Plugin.');registerCommands('shadow,shadowcolor,shadowimage,shadowopacity,shadowx,shadowy');
+if (typeof ol_shadowadjust=='undefined') var ol_shadowadjust=2;if (typeof ol_shadow=='undefined') var ol_shadow=0;if (typeof ol_shadowcolor=='undefined') var ol_shadowcolor='#CCCCCC';if (typeof ol_shadowimage=='undefined') var ol_shadowimage='';if (typeof ol_shadowopacity=='undefined') var ol_shadowopacity=0;if (typeof ol_shadowx=='undefined') var ol_shadowx=5;if (typeof ol_shadowy=='undefined') var ol_shadowy=5;
+var o3_shadow=0;var o3_shadowcolor="#cccccc";var o3_shadowimage='';var o3_shadowopacity=0;var o3_shadowx=5;var o3_shadowy=5;var bkSet=0;
+function setShadowVariables() {o3_shadow=ol_shadow;o3_shadowcolor=ol_shadowcolor;o3_shadowimage=ol_shadowimage;o3_shadowopacity=ol_shadowopacity;o3_shadowx=ol_shadowx;o3_shadowy=ol_shadowy;}
+function parseShadowExtras(pf,i,ar) {var k=i, v;
+if (k<ar.length) {if (ar[k]==SHADOW) { eval(pf+'shadow=('+pf+'shadow==0)?1:0'); return k; }
+if (ar[k]==SHADOWCOLOR) { eval(pf+'shadowcolor="'+ar[++k]+'"'); return k; }
+if (ar[k]==SHADOWOPACITY) {v=ar[++k]; eval(pf+'shadowopacity='+(olOp?0:v)); return k; }
+if (ar[k]==SHADOWIMAGE) { eval(pf+'shadowimage="'+ar[++k]+'"'); return k; }
+if (ar[k]==SHADOWX) { eval(pf+'shadowx='+ar[++k]); return k; }
+if (ar[k]==SHADOWY) { eval(pf+'shadowy='+ar[++k]); return k; }
+}
+return-1;}
+function shadow_cursorOff() {var left=parseInt(over.style.left);var top=parseInt(over.style.top);var right=left+(o3_shadow?o3_width:over.offsetWidth);var bottom=top+(o3_shadow?o3_aboveheight:over.offsetHeight);
+if (o3_x<left||o3_x>right||o3_y<top||o3_y>bottom) return true;return false;}
+function checkShadowPreHide() {if (o3_shadow&&o3_shadowopacity) cleanUpShadowEffects();if (o3_shadow&&(olIe4&&isMac) ) over.style.pixelWidth=over.style.pixelHeight=0;}
+function generateShadow(content) {var wd, ht, X=0, Y=0, zIdx=0, txt, dpObj, puObj, bS='', aPos, posStr=new Array();
+if (!o3_shadow||(o3_shadowx==0&&o3_shadowy==0)) return;
+X=Math.abs(o3_shadowx);Y=Math.abs(o3_shadowy);wd=parseInt(o3_width);if(olHideForm&&!olNs4) ht=over.offsetHeight;
+if (o3_shadowx==0) {if (o3_shadowy<0) {posStr[0]=' left:0; top: 0';posStr[1]=' left:0; top: '+Y+'px';} else if (o3_shadowy>0) {posStr[0]=' left:0; top: '+Y+'px';posStr[1]=' left:0; top:0';}
+} else if (o3_shadowy==0) {if (o3_shadowx<0) {posStr[0]=' left:0; top: 0';posStr[1]=' left: '+X+'px';} else if (o3_shadowx>0) {posStr[0]=' left: '+X+'px; top: 0';posStr[1]=' left:0; top:0';}
+} else if (o3_shadowx>0) {if (o3_shadowy>0) {posStr[0]=' left:'+X+'px; top:'+Y+'px';posStr[1]=' left:0; top:0';} else if (o3_shadowy<0) {posStr[0]=' left:'+X+'px; top:0';posStr[1]=' left:0; top: '+Y+'px';}
+} else if (o3_shadowx<0) {if (o3_shadowy>0) {posStr[0]=' left:0; top:'+Y+'px';posStr[1]=' left:'+X+'px; top:0';} else if (o3_shadowy<0) {posStr[0]=' left:0; top:0';posStr[1]=' left:'+X+'px; top:'+Y+'px';}
+}
+txt=(olNs4)?'<div id="backdrop"></div>':((olIe55&&olHideForm)?bckDropSrc(wd+X,ht+Y,zIdx++):'')+'<div id="backdrop" style="position: absolute;'+posStr[0]+'; width: '+wd+'px; z-index: '+(zIdx++)+'; ';
+if (o3_shadowimage) {bS='background-image: url('+o3_shadowimage+');';if (olNs4) bkSet=1;} else {bS='background-color: '+o3_shadowcolor+';';if (olNs4) bkSet=2;}
+if (olNs4) {txt+='<div id="PUContent">'+content+'</div>';} else {txt+=bS+'"></div><div id="PUContent" style="position: absolute;'+posStr[1]+'; width: '+wd+'px; z-index: '+(zIdx++)+';">'+content+'</div>';}
+layerWrite(txt);
+if (olNs4&&bkSet) {dpObj=over.document.layers['backdrop'];if (typeof dpObj=='undefined') return;
+puObj=over.document.layers['PUContent'];wd=puObj.clip.width;ht=puObj.clip.height;aPos=posStr[0].split(';');
+dpObj.clip.width=wd;dpObj.clip.height=ht;dpObj.left=parseInt(aPos[0].split(':')[1]);dpObj.top=parseInt(aPos[1].split(':')[1]);
+dpObj.bgColor=(bkSet==1)?null:o3_shadowcolor;dpObj.background.src=(bkSet==2)?null:o3_shadowimage;dpObj.zIndex=0;
+aPos=posStr[1].split(';');puObj.left=parseInt(aPos[0].split(':')[1]);puObj.top=parseInt(aPos[1].split(':')[1]);puObj.zIndex=1;
+} else {puObj=(olIe4?o3_frame.document.all['PUContent']:o3_frame.document.getElementById('PUContent'));dpObj=(olIe4?o3_frame.document.all['backdrop']:o3_frame.document.getElementById('backdrop'));ht=puObj.offsetHeight;dpObj.style.height=ht+'px';
+if (o3_shadowopacity) {var op=o3_shadowopacity;op=(op<=100?op:100);
+if (olIe4&&!isMac) {dpObj.style.filter='Beta(Opacity='+op+')';dpObj.filters.Beta.enabled=true;} else {if (typeof(dpObj.style.MozOpacity)=='string') dpObj.style.MozOpacity=op/100;}
+}
+}
+o3_width=wd+X;o3_aboveheight=ht+Y;}
+function cleanUpShadowEffects() {if (olNs4) return;else {var dpObj=(olIe4?o3_frame.document.all['backdrop']:o3_frame.document.getElementById('backdrop'));if (olIe4&&!isMac&&dpObj.filters.Beta) dpObj.filters.Beta.enabled=false;else if (typeof(dpObj.style.MozOpacity)=='string') dpObj.style.MozOpacity=1.0;}
+}
+function shadowAdjust() {if (!olNs4) return;var fac=ol_shadowadjust;if (olNs4) {document.write('<style type="text/css">\n<!--\n');document.write('#backdrop, #PUContent {position: absolute; left: '+fac*o3_shadowx+'px; top: '+fac*o3_shadowy+'px; }\n');document.write('-->\n<'+'\/style>');}
+}
+var before=(typeof rmrkPreface!='undefined'?rmrkPreface:null);
+registerRunTimeFunction(setShadowVariables);registerCmdLineFunction(parseShadowExtras);registerHook("cursorOff",shadow_cursorOff,FREPLACE);registerHook("hideObject",checkShadowPreHide,FBEFORE);registerHook("createPopup",generateShadow,FAFTER,before);
+if (olNs4) shadowAdjust();
--- /dev/null
+//\/////
+//\ overLIB 4.00 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\
+//\ Contributors are listed on the homepage.
+//\ This file might be old, always check for the latest version at:
+//\ http://www.bosrup.com/web/overlib/
+//\
+//\ Please read the license agreement (available through the link above)
+//\ before using overLIB. Direct any licensing questions to erik@bosrup.com.
+//\
+//\ Do not sell this as your own work or remove this copyright notice.
+//\ For full details on copying or changing this script please read the
+//\ license agreement at the link above. Please give credit on sites that
+//\ use overLIB and submit changes of the script so other people can use
+//\ them as well.
+// $Revision$ $Date$
+//\/////
+//\mini
+
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+var olLoaded = 0;var pmStart = 10000000; var pmUpper = 10001000; var pmCount = pmStart+1; var pms = new Array(); var olInfo = new Info('4.00', 1);
+var FREPLACE = 0; var FBEFORE = 1; var FAFTER = 2; var FALTERNATE = 3;
+var olHideForm=0; // parameter for hiding SELECT and ActiveX elements in IE5.5+
+registerCommands('donothing,inarray,caparray,sticky,background,noclose,caption,left,right,center,offsetx,offsety,fgcolor,bgcolor,textcolor,capcolor,closecolor,width,border,cellpad,status,autostatus,autostatuscap,height,closetext,snapx,snapy,fixx,fixy,relx,rely,fgbackground,bgbackground,padx,pady,fullhtml,above,below,capicon,textfont,captionfont,closefont,textsize,captionsize,closesize,timeout,function,delay,hauto,vauto,closeclick,wrap,followmouse,mouseoff,closetitle,cssoff,cssclass,fgclass,bgclass,textfontclass,captionfontclass,closefontclass');
+
+////////
+// DEFAULT CONFIGURATION
+// Settings you want everywhere are set here. All of this can also be
+// changed on your html page or through an overLIB call.
+////////
+if (typeof ol_fgcolor=='undefined') var ol_fgcolor="#CCCCFF";
+if (typeof ol_bgcolor=='undefined') var ol_bgcolor="#333399";
+if (typeof ol_textcolor=='undefined') var ol_textcolor="#000000";
+if (typeof ol_capcolor=='undefined') var ol_capcolor="#FFFFFF";
+if (typeof ol_closecolor=='undefined') var ol_closecolor="#9999FF";
+if (typeof ol_textfont=='undefined') var ol_textfont="Verdana,Arial,Helvetica";
+if (typeof ol_captionfont=='undefined') var ol_captionfont="Verdana,Arial,Helvetica";
+if (typeof ol_closefont=='undefined') var ol_closefont="Verdana,Arial,Helvetica";
+if (typeof ol_textsize=='undefined') var ol_textsize="1";
+if (typeof ol_captionsize=='undefined') var ol_captionsize="1";
+if (typeof ol_closesize=='undefined') var ol_closesize="1";
+if (typeof ol_width=='undefined') var ol_width="200";
+if (typeof ol_border=='undefined') var ol_border="1";
+if (typeof ol_cellpad=='undefined') var ol_cellpad=2;
+if (typeof ol_offsetx=='undefined') var ol_offsetx=10;
+if (typeof ol_offsety=='undefined') var ol_offsety=10;
+if (typeof ol_text=='undefined') var ol_text="Default Text";
+if (typeof ol_cap=='undefined') var ol_cap="";
+if (typeof ol_sticky=='undefined') var ol_sticky=0;
+if (typeof ol_background=='undefined') var ol_background="";
+if (typeof ol_close=='undefined') var ol_close="Close";
+if (typeof ol_hpos=='undefined') var ol_hpos=RIGHT;
+if (typeof ol_status=='undefined') var ol_status="";
+if (typeof ol_autostatus=='undefined') var ol_autostatus=0;
+if (typeof ol_height=='undefined') var ol_height=-1;
+if (typeof ol_snapx=='undefined') var ol_snapx=0;
+if (typeof ol_snapy=='undefined') var ol_snapy=0;
+if (typeof ol_fixx=='undefined') var ol_fixx=-1;
+if (typeof ol_fixy=='undefined') var ol_fixy=-1;
+if (typeof ol_relx=='undefined') var ol_relx=null;
+if (typeof ol_rely=='undefined') var ol_rely=null;
+if (typeof ol_fgbackground=='undefined') var ol_fgbackground="";
+if (typeof ol_bgbackground=='undefined') var ol_bgbackground="";
+if (typeof ol_padxl=='undefined') var ol_padxl=1;
+if (typeof ol_padxr=='undefined') var ol_padxr=1;
+if (typeof ol_padyt=='undefined') var ol_padyt=1;
+if (typeof ol_padyb=='undefined') var ol_padyb=1;
+if (typeof ol_fullhtml=='undefined') var ol_fullhtml=0;
+if (typeof ol_vpos=='undefined') var ol_vpos=BELOW;
+if (typeof ol_aboveheight=='undefined') var ol_aboveheight=0;
+if (typeof ol_capicon=='undefined') var ol_capicon="";
+if (typeof ol_frame=='undefined') var ol_frame=self;
+if (typeof ol_timeout=='undefined') var ol_timeout=0;
+if (typeof ol_function=='undefined') var ol_function=null;
+if (typeof ol_delay=='undefined') var ol_delay=0;
+if (typeof ol_hauto=='undefined') var ol_hauto=0;
+if (typeof ol_vauto=='undefined') var ol_vauto=0;
+if (typeof ol_closeclick=='undefined') var ol_closeclick=0;
+if (typeof ol_wrap=='undefined') var ol_wrap=0;
+if (typeof ol_followmouse=='undefined') var ol_followmouse=1;
+if (typeof ol_mouseoff=='undefined') var ol_mouseoff=0;
+if (typeof ol_closetitle=='undefined') var ol_closetitle='Close';
+if (typeof ol_css=='undefined') var ol_css=CSSOFF;
+if (typeof ol_fgclass=='undefined') var ol_fgclass="";
+if (typeof ol_bgclass=='undefined') var ol_bgclass="";
+if (typeof ol_textfontclass=='undefined') var ol_textfontclass="";
+if (typeof ol_captionfontclass=='undefined') var ol_captionfontclass="";
+if (typeof ol_closefontclass=='undefined') var ol_closefontclass="";
+
+////////
+// ARRAY CONFIGURATION
+////////
+
+// You can use these arrays to store popup text here instead of in the html.
+if (typeof ol_texts=='undefined') var ol_texts = new Array("Text 0", "Text 1");
+if (typeof ol_caps=='undefined') var ol_caps = new Array("Caption 0", "Caption 1");
+
+////////
+// END OF CONFIGURATION
+// Don't change anything below this line, all configuration is above.
+////////
+
+
+
+
+
+////////
+// INIT
+////////
+// Runtime variables init. Don't change for config!
+var o3_text="";
+var o3_cap="";
+var o3_sticky=0;
+var o3_background="";
+var o3_close="Close";
+var o3_hpos=RIGHT;
+var o3_offsetx=2;
+var o3_offsety=2;
+var o3_fgcolor="";
+var o3_bgcolor="";
+var o3_textcolor="";
+var o3_capcolor="";
+var o3_closecolor="";
+var o3_width=100;
+var o3_border=1;
+var o3_cellpad=2;
+var o3_status="";
+var o3_autostatus=0;
+var o3_height=-1;
+var o3_snapx=0;
+var o3_snapy=0;
+var o3_fixx=-1;
+var o3_fixy=-1;
+var o3_relx=null;
+var o3_rely=null;
+var o3_fgbackground="";
+var o3_bgbackground="";
+var o3_padxl=0;
+var o3_padxr=0;
+var o3_padyt=0;
+var o3_padyb=0;
+var o3_fullhtml=0;
+var o3_vpos=BELOW;
+var o3_aboveheight=0;
+var o3_capicon="";
+var o3_textfont="Verdana,Arial,Helvetica";
+var o3_captionfont="Verdana,Arial,Helvetica";
+var o3_closefont="Verdana,Arial,Helvetica";
+var o3_textsize="1";
+var o3_captionsize="1";
+var o3_closesize="1";
+var o3_frame=self;
+var o3_timeout=0;
+var o3_timerid=0;
+var o3_allowmove=0;
+var o3_function=null;
+var o3_delay=0;
+var o3_delayid=0;
+var o3_hauto=0;
+var o3_vauto=0;
+var o3_closeclick=0;
+var o3_wrap=0;
+var o3_followmouse=1;
+var o3_mouseoff=0;
+var o3_closetitle='';
+var o3_css=CSSOFF;
+var o3_fgclass="";
+var o3_bgclass="";
+var o3_textfontclass="";
+var o3_captionfontclass="";
+var o3_closefontclass="";
+
+// Display state variables
+var o3_x = 0;
+var o3_y = 0;
+var o3_showingsticky = 0;
+var o3_removecounter = 0;
+
+// Our layer
+var over = null;
+var fnRef, hoveringSwitch = false;
+
+// Decide browser version
+var isMac = (navigator.userAgent.indexOf("Mac") != -1);
+var olOp = (navigator.userAgent.toLowerCase().indexOf('opera 7.') > -1);
+var olNs4 = (navigator.appName=='Netscape' && parseInt(navigator.appVersion) == 4);
+var olNs6 = (document.getElementById) ? true : false;
+var olIe4 = (document.all) ? true : false;
+var olIe5 = false;
+var olIe55 = false; // Added additional variable to identify IE5.5+
+var docRoot = 'document.body';
+
+// Resize fix for NS4.x to keep track of layer
+if (olNs4) {
+ var oW = window.innerWidth;
+ var oH = window.innerHeight;
+ window.onresize = function() { if (oW != window.innerWidth || oH != window.innerHeight) location.reload(); }
+}
+
+// Microsoft Stupidity Check(tm).
+if (olIe4) {
+ var versNum=parseFloat(navigator.userAgent.match(/MSIE (\d\.\d+)\.*/i)[1]);
+ if (versNum >= 5){
+ olIe5=true;
+ olIe55=(versNum>=5.5&&!olOp) ? true : false;
+ if (olNs6) olNs6=false;
+ }
+ if (olNs6) olIe4 = false;
+}
+
+// Check for compatability mode.
+if (document.compatMode && document.compatMode == 'CSS1Compat') {
+ docRoot= ((olIe4 && !olOp) ? 'document.documentElement' : docRoot);
+}
+
+// Add window onload handlers to indicate when all modules have been loaded
+// For Netscape 6+ and Mozilla, uses addEventListener method on the window object
+// For IE it uses the attachEvent method of the window object and for Netscape 4.x
+// it sets the window.onload handler to the OLonload_handler function
+if(window.addEventListener) window.addEventListener("load",OLonLoad_handler,true);
+else if (window.attachEvent) window.attachEvent("onload",OLonLoad_handler);
+else window.onload=OLonLoad_handler;
+
+// Capture events, alt. diffuses the overlib function.
+var olCheckMouseCapture = true;
+if ((olNs4 || olNs6 || olIe4)) {
+ olMouseCapture();
+} else {
+ overlib = no_overlib;
+ nd = no_overlib;
+ ver3fix = true;
+}
+
+
+////////
+// PUBLIC FUNCTIONS
+////////
+
+// overlib(arg0,...,argN)
+// Loads parameters into global runtime variables.
+function overlib() {
+ if (!olLoaded || isExclusive(overlib.arguments)) return true;
+ if (olCheckMouseCapture) olMouseCapture();
+ if (over) cClick();
+
+ // Load defaults to runtime.
+ o3_text=ol_text;
+ o3_cap=ol_cap;
+ o3_sticky=ol_sticky;
+ o3_background=ol_background;
+ o3_close=ol_close;
+ o3_hpos=ol_hpos;
+ o3_offsetx=ol_offsetx;
+ o3_offsety=ol_offsety;
+ o3_fgcolor=ol_fgcolor;
+ o3_bgcolor=ol_bgcolor;
+ o3_textcolor=ol_textcolor;
+ o3_capcolor=ol_capcolor;
+ o3_closecolor=ol_closecolor;
+ o3_width=ol_width;
+ o3_border=ol_border;
+ o3_cellpad=ol_cellpad;
+ o3_status=ol_status;
+ o3_autostatus=ol_autostatus;
+ o3_height=ol_height;
+ o3_snapx=ol_snapx;
+ o3_snapy=ol_snapy;
+ o3_fixx=ol_fixx;
+ o3_fixy=ol_fixy;
+ o3_relx=ol_relx;
+ o3_rely=ol_rely;
+ o3_fgbackground=ol_fgbackground;
+ o3_bgbackground=ol_bgbackground;
+ o3_padxl=ol_padxl;
+ o3_padxr=ol_padxr;
+ o3_padyt=ol_padyt;
+ o3_padyb=ol_padyb;
+ o3_fullhtml=ol_fullhtml;
+ o3_vpos=ol_vpos;
+ o3_aboveheight=ol_aboveheight;
+ o3_capicon=ol_capicon;
+ o3_textfont=ol_textfont;
+ o3_captionfont=ol_captionfont;
+ o3_closefont=ol_closefont;
+ o3_textsize=ol_textsize;
+ o3_captionsize=ol_captionsize;
+ o3_closesize=ol_closesize;
+ o3_timeout=ol_timeout;
+ o3_function=ol_function;
+ o3_delay=ol_delay;
+ o3_hauto=ol_hauto;
+ o3_vauto=ol_vauto;
+ o3_closeclick=ol_closeclick;
+ o3_wrap=ol_wrap;
+ o3_followmouse=ol_followmouse;
+ o3_mouseoff=ol_mouseoff;
+ o3_closetitle=ol_closetitle;
+ o3_css=ol_css;
+ o3_fgclass=ol_fgclass;
+ o3_bgclass=ol_bgclass;
+ o3_textfontclass=ol_textfontclass;
+ o3_captionfontclass=ol_captionfontclass;
+ o3_closefontclass=ol_closefontclass;
+
+ setRunTimeVariables();
+
+ fnRef = '';
+
+ // Special for frame support, over must be reset...
+ o3_frame = ol_frame;
+
+ if (olNs4) {
+ over = o3_frame.document.layers['overDiv'];
+ } else if (document.all) {
+ over = o3_frame.document.all['overDiv'];
+ } else if (document.getElementById) {
+ over = o3_frame.document.getElementById("overDiv");
+ }
+
+ parseTokens('o3_', overlib.arguments);
+ if (!postParseChecks()) return false;
+
+ if (o3_delay == 0) {
+ return runHook("olMain", FREPLACE);
+ } else {
+ o3_delayid = setTimeout("runHook('olMain', FREPLACE)", o3_delay);
+ return false;
+ }
+}
+
+// Clears popups if appropriate
+function nd(time) {
+ if (olLoaded && !isExclusive()) {
+ if (time && !o3_delay) {
+ if (o3_timerid > 0) clearTimeout(o3_timerid);
+
+ o3_timerid = setTimeout("cClick()",(o3_timeout = time));
+ }
+ if (o3_removecounter >= 1) { o3_showingsticky = 0 };
+
+ if (o3_showingsticky == 0) {
+ o3_allowmove = 0;
+ if (over != null && o3_timerid == 0) runHook("hideObject", FREPLACE, over);
+ } else {
+ o3_removecounter++;
+ }
+ }
+
+ return true;
+}
+
+// The Close onMouseOver function for stickies
+function cClick() {
+ if (olLoaded) {
+ runHook("hideObject", FREPLACE, over);
+ o3_showingsticky = 0;
+ }
+ return false;
+}
+
+// Method for setting page specific defaults.
+function overlib_pagedefaults() {
+ parseTokens('ol_', overlib_pagedefaults.arguments);
+}
+
+
+////////
+// OVERLIB MAIN FUNCTION
+////////
+
+// This function decides what it is we want to display and how we want it done.
+function olMain() {
+ var layerhtml, styleType;
+ runHook("olMain", FBEFORE);
+
+ if (o3_background!="" || o3_fullhtml) {
+ // Use background instead of box.
+ layerhtml = runHook('ol_content_background', FALTERNATE, o3_css, o3_text, o3_background, o3_fullhtml);
+ } else {
+ // They want a popup box.
+ styleType = (pms[o3_css-1-pmStart] == "cssoff" || pms[o3_css-1-pmStart] == "cssclass");
+
+ // Prepare popup background
+ if (o3_fgbackground != "") o3_fgbackground = "background=\""+o3_fgbackground+"\"";
+ if (o3_bgbackground != "") o3_bgbackground = (styleType ? "background=\""+o3_bgbackground+"\"" : o3_bgbackground);
+
+ // Prepare popup colors
+ if (o3_fgcolor != "") o3_fgcolor = (styleType ? "bgcolor=\""+o3_fgcolor+"\"" : o3_fgcolor);
+ if (o3_bgcolor != "") o3_bgcolor = (styleType ? "bgcolor=\""+o3_bgcolor+"\"" : o3_bgcolor);
+
+ // Prepare popup height
+ if (o3_height > 0) o3_height = (styleType ? "height=\""+o3_height+"\"" : o3_height);
+ else o3_height = "";
+
+ // Decide which kinda box.
+ if (o3_cap=="") {
+ // Plain
+ layerhtml = runHook('ol_content_simple', FALTERNATE, o3_css, o3_text);
+ } else {
+ // With caption
+ if (o3_sticky) {
+ // Show close text
+ layerhtml = runHook('ol_content_caption', FALTERNATE, o3_css, o3_text, o3_cap, o3_close);
+ } else {
+ // No close text
+ layerhtml = runHook('ol_content_caption', FALTERNATE, o3_css, o3_text, o3_cap, "");
+ }
+ }
+ }
+
+ // We want it to stick!
+ if (o3_sticky) {
+ if (o3_timerid > 0) {
+ clearTimeout(o3_timerid);
+ o3_timerid = 0;
+ }
+ o3_showingsticky = 1;
+ o3_removecounter = 0;
+ }
+
+ // Created a separate routine to generate the popup to make it easier
+ // to implement a plugin capability
+ if (!runHook("createPopup", FREPLACE, layerhtml)) return false;
+
+ // Prepare status bar
+ if (o3_autostatus > 0) {
+ o3_status = o3_text;
+ if (o3_autostatus > 1) o3_status = o3_cap;
+ }
+
+ // When placing the layer the first time, even stickies may be moved.
+ o3_allowmove = 0;
+
+ // Initiate a timer for timeout
+ if (o3_timeout > 0) {
+ if (o3_timerid > 0) clearTimeout(o3_timerid);
+ o3_timerid = setTimeout("cClick()", o3_timeout);
+ }
+
+ // Show layer
+ runHook("disp", FREPLACE, o3_status);
+ runHook("olMain", FAFTER);
+
+ if (o3_status != '') {
+ return true;
+ } else {
+ return;
+ }
+}
+
+////////
+// LAYER GENERATION FUNCTIONS
+////////
+// These functions just handle popup content with tags that should adhere to the W3C standards specification.
+
+// Makes simple table without caption
+function ol_content_simple(text) {
+ txt='<table width="'+o3_width+ '" border="0" cellpadding="'+o3_border+'" cellspacing="0" '+(o3_bgclass ? 'class="'+o3_bgclass+'"' : o3_bgcolor+' '+o3_height)+'><tr><td><table width="100%" border="0" cellpadding="' + o3_cellpad + '" cellspacing="0" '+(o3_fgclass ? 'class="'+o3_fgclass+'"' : o3_fgcolor+' '+o3_fgbackground+' '+o3_height)+'><tr><td valign="TOP"'+(o3_textfontclass ? ' class="'+o3_textfontclass+'">' : '>')+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize))+'</td></tr></table></td></tr></table>';
+
+ set_background("");
+ return txt;
+}
+
+// Makes table with caption and optional close link
+function ol_content_caption(text,title,close) {
+ var nameId;
+ closing="";
+ closeevent="onmouseover";
+ if (o3_closeclick==1) closeevent= (o3_closetitle ? "title='" + o3_closetitle +"'" : "") + " onclick";
+ if (o3_capicon!="") {
+ nameId=' hspace=\"5\"'+' align=\"middle\" alt=\"\"';
+ if (typeof o3_dragimg!='undefined'&&o3_dragimg) nameId=' hspace=\"5\"'+' name=\"'+o3_dragimg+'\" id=\"'+o3_dragimg+'\" align=\"middle\" alt=\"Drag Enabled\" title=\"Drag Enabled\"';
+ o3_capicon='<img src=\"'+o3_capicon+'\"'+nameId+' />';
+ }
+
+ if (close != "") closing='<td '+(o3_closefontclass ? 'class="'+o3_closefontclass : 'align="RIGHT')+'"><a href="javascript:return '+fnRef+'cClick();" '+closeevent+'="return '+fnRef+'cClick();">'+(o3_closefontclass ? '' : wrapStr(0,o3_closesize,'close'))+close+(o3_closefontclass ? '' : wrapStr(1,o3_closesize,'close'))+'</a></td>';
+ txt='<table width="'+o3_width+ '" border="0" cellpadding="'+o3_border+'" cellspacing="0" '+(o3_bgclass ? 'class="'+o3_bgclass+'"' : o3_bgcolor+' '+o3_bgbackground+' '+o3_height)+'><tr><td><table width="100%" border="0" cellpadding="0" cellspacing="0"><tr><td'+(o3_captionfontclass ? ' class="'+o3_captionfontclass+'">' : '>')+(o3_captionfontclass ? '' : '<b>'+wrapStr(0,o3_captionsize,'caption'))+o3_capicon+title+(o3_captionfontclass ? '' : wrapStr(1,o3_captionsize)+'</b>')+'</td>'+closing+'</tr></table><table width="100%" border="0" cellpadding="' + o3_cellpad + '" cellspacing="0" '+(o3_fgclass ? 'class="'+o3_fgclass+'"' : o3_fgcolor+' '+o3_fgbackground+' '+o3_height)+'><tr><td valign="TOP"'+(o3_textfontclass ? ' class="'+o3_textfontclass+'">' :'>')+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize)) + '</td></tr></table></td></tr></table>';
+
+ set_background("");
+ return txt;
+}
+
+// Sets the background picture,padding and lots more. :)
+function ol_content_background(text,picture,hasfullhtml) {
+ if (hasfullhtml) {
+ txt=text;
+ } else {
+ txt='<table width="'+o3_width+'" border="0" cellpadding="0" cellspacing="0" height="'+o3_height+'"><tr><td colspan="3" height="'+o3_padyt+'"></td></tr><tr><td width="'+o3_padxl+'"></td><td valign="TOP" width="'+(o3_width-o3_padxl-o3_padxr)+'">'+wrapStr(0,o3_textsize,'text')+text+wrapStr(1,o3_textsize)+'</td><td width="'+o3_padxr+'"></td></tr><tr><td colspan="3" height="'+o3_padyb+'"></td></tr></table>';
+ }
+
+ set_background(picture);
+ return txt;
+}
+
+// Loads a picture into the div.
+function set_background(pic) {
+ if (pic == "") {
+ if (olNs4) {
+ over.background.src = null;
+ } else if (over.style) {
+ over.style.backgroundImage = "none";
+ }
+ } else {
+ if (olNs4) {
+ over.background.src = pic;
+ } else if (over.style) {
+ over.style.backgroundImage = "url("+pic+")";
+ }
+ }
+}
+
+////////
+// HANDLING FUNCTIONS
+////////
+
+// Displays the popup
+function disp(statustext) {
+ runHook("disp", FBEFORE);
+
+ if (o3_allowmove == 0) {
+ runHook("placeLayer", FREPLACE);
+ runHook("showObject", FREPLACE, over);
+ o3_allowmove = (o3_sticky || o3_followmouse==0) ? 0 : 1;
+ }
+
+ runHook("disp", FAFTER);
+
+ if (statustext != "") self.status = statustext;
+}
+
+// Creates the actual popup structure
+function createPopup(lyrContent){
+ runHook("createPopup", FBEFORE);
+
+ if (o3_wrap && !(olNs4 || olOp)) {
+ if (olIe4) {
+ over.style.pixelWidth = 0;
+ } else if (olNs6) {
+ repositionTo(over, 0, -over.offsetHeight);
+ }
+ }
+
+ layerWrite(lyrContent);
+
+ // Have to set o3_width for placeLayer() routine if o3_wrap is turned on
+ if (o3_wrap) o3_width=(olNs4 ? over.clip.width : over.offsetWidth);
+
+ runHook("createPopup", FAFTER, lyrContent);
+
+ return true;
+}
+
+// Decides where we want the popup.
+function placeLayer() {
+ var placeX, placeY, widthFix = 0;
+
+ // HORIZONTAL PLACEMENT
+ if (eval('o3_frame.'+docRoot) && eval("typeof o3_frame."+docRoot+".clientWidth=='number'") && eval('o3_frame.'+docRoot+'.clientWidth')) {
+ iwidth = eval('o3_frame.'+docRoot+'.clientWidth');
+ } else if (typeof(o3_frame.innerWidth) == 'number') {
+ widthFix = Math.ceil(1.2*(o3_frame.outerWidth - o3_frame.innerWidth));
+ iwidth = o3_frame.innerWidth;
+ }
+
+ // Horizontal scroll offset
+ winoffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollLeft') : o3_frame.pageXOffset;
+ var parsedWidth = parseInt(o3_width);
+
+ if (o3_fixx > -1 || o3_relx != null) {
+ // Fixed position
+ placeX=(o3_relx != null ? ( o3_relx < 0 ? winoffset +o3_relx+ iwidth - parsedWidth - widthFix : winoffset+o3_relx) : o3_fixx);
+ } else {
+ // If HAUTO, decide what to use.
+ if (o3_hauto == 1) {
+ if ((o3_x - winoffset) > (iwidth / 2)) {
+ o3_hpos = LEFT;
+ } else {
+ o3_hpos = RIGHT;
+ }
+ }
+
+ // From mouse
+ if (o3_hpos == CENTER) { // Center
+ placeX = o3_x+o3_offsetx-(parsedWidth/2);
+
+ if (placeX < winoffset) placeX = winoffset;
+ }
+
+ if (o3_hpos == RIGHT) { // Right
+ placeX = o3_x+o3_offsetx;
+
+ if ((placeX+parsedWidth) > (winoffset+iwidth - widthFix)) {
+ placeX = iwidth+winoffset - parsedWidth - widthFix;
+ if (placeX < 0) placeX = 0;
+ }
+ }
+ if (o3_hpos == LEFT) { // Left
+ placeX = o3_x-o3_offsetx-parsedWidth;
+ if (placeX < winoffset) placeX = winoffset;
+ }
+
+ // Snapping!
+ if (o3_snapx > 1) {
+ var snapping = placeX % o3_snapx;
+
+ if (o3_hpos == LEFT) {
+ placeX = placeX - (o3_snapx+snapping);
+ } else {
+ // CENTER and RIGHT
+ placeX = placeX+(o3_snapx - snapping);
+ }
+
+ if (placeX < winoffset) placeX = winoffset;
+ }
+ }
+
+ // VERTICAL PLACEMENT
+ if (eval('o3_frame.'+docRoot) && eval("typeof o3_frame."+docRoot+".clientHeight=='number'") && eval('o3_frame.'+docRoot+'.clientHeight')) {
+ iheight = eval('o3_frame.'+docRoot+'.clientHeight');
+ } else if (typeof(o3_frame.innerHeight)=='number') {
+ iheight = o3_frame.innerHeight;
+ }
+
+ // Vertical scroll offset
+ scrolloffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollTop') : o3_frame.pageYOffset;
+ var parsedHeight=(o3_aboveheight ? parseInt(o3_aboveheight) : (olNs4 ? over.clip.height : over.offsetHeight));
+
+ if (o3_fixy > -1 || o3_rely != null) {
+ // Fixed position
+ placeY=(o3_rely != null ? (o3_rely < 0 ? scrolloffset+o3_rely+iheight - parsedHeight : scrolloffset+o3_rely) : o3_fixy);
+ } else {
+ // If VAUTO, decide what to use.
+ if (o3_vauto == 1) {
+ if ((o3_y - scrolloffset) > (iheight/2)) {
+ o3_vpos = ABOVE;
+ } else {
+ o3_vpos = BELOW;
+ }
+ }
+
+ // From mouse
+ if (o3_vpos == ABOVE) {
+ if (o3_aboveheight == 0) o3_aboveheight = parsedHeight;
+
+ placeY = o3_y - (o3_aboveheight+o3_offsety);
+ if (placeY < scrolloffset) placeY = scrolloffset;
+ } else {
+ // BELOW
+ placeY = o3_y+o3_offsety;
+ }
+
+ // Snapping!
+ if (o3_snapy > 1) {
+ var snapping = placeY % o3_snapy;
+
+ if (o3_aboveheight > 0 && o3_vpos == ABOVE) {
+ placeY = placeY - (o3_snapy+snapping);
+ } else {
+ placeY = placeY+(o3_snapy - snapping);
+ }
+
+ if (placeY < scrolloffset) placeY = scrolloffset;
+ }
+ }
+
+ // Actually move the object.
+ repositionTo(over, placeX, placeY);
+}
+
+// Moves the layer
+function olMouseMove(e) {
+ var e = (e) ? e : event;
+
+ if (e.pageX) {
+ o3_x = e.pageX;
+ o3_y = e.pageY;
+ } else if (e.clientX) {
+ o3_x = eval('e.clientX+o3_frame.'+docRoot+'.scrollLeft');
+ o3_y = eval('e.clientY+o3_frame.'+docRoot+'.scrollTop');
+ }
+
+ if (o3_allowmove == 1) runHook("placeLayer", FREPLACE);
+
+ // MouseOut handler
+ if (hoveringSwitch && !olNs4 && runHook("cursorOff", FREPLACE)) {
+ cClick();
+ hoveringSwitch = !hoveringSwitch;
+ }
+}
+
+// Fake function for 3.0 users.
+function no_overlib() { return ver3fix; }
+
+// Capture the mouse and chain other scripts.
+function olMouseCapture() {
+ capExtent = document;
+ var fN, mseHandler = olMouseMove;
+ var re = /function[ ]+(\w+)\(/;
+
+ if (document.onmousemove || (!olIe4 && window.onmousemove)) {
+ if (window.onmousemove) capExtent = window;
+ fN = capExtent.onmousemove.toString().match(re);
+
+ if (fN[1] == 'anonymous' || fN[1] == 'olMouseMove') {
+ olCheckMouseCapture = false;
+ return;
+ }
+ var str = fN[1]+'(e); ' + 'olMouseMove(e); ';
+ mseHandler = new Function('e', str);
+ }
+
+ capExtent.onmousemove = mseHandler;
+ if (olNs4) capExtent.captureEvents(Event.MOUSEMOVE);
+}
+
+
+////////
+// PARSING FUNCTIONS
+////////
+
+// Does the actual command parsing.
+function parseTokens(pf, ar) {
+ // What the next argument is expected to be.
+ var v, mode=-1, par = (pf != 'ol_');
+ var fnMark = (par && !ar.length ? 1 : 0);
+
+ for (i = 0; i < ar.length; i++) {
+ if (mode < 0) {
+ // Arg is maintext,unless its a number between pmStart and pmUpper
+ // then its a command.
+ if (typeof ar[i] == 'number' && ar[i] > pmStart && ar[i] < pmUpper) {
+ fnMark = (par ? 1 : 0);
+ i--; // backup one so that the next block can parse it
+ } else {
+ switch(pf) {
+ case 'ol_':
+ ol_text = ar[i].toString();
+ break;
+ default:
+ o3_text=ar[i].toString();
+ }
+ }
+ mode = 0;
+ } else {
+ // Note: NS4 doesn't like switch cases with vars.
+ if (ar[i] >= pmCount || ar[i]==DONOTHING) { continue; }
+ if (ar[i]==INARRAY) { fnMark = 0; eval(pf+'text=ol_texts['+ar[++i]+'].toString()'); continue; }
+ if (ar[i]==CAPARRAY) { eval(pf+'cap=ol_caps['+ar[++i]+'].toString()'); continue; }
+ if (ar[i]==STICKY) { if (pf!='ol_') eval(pf+'sticky=1'); continue; }
+ if (ar[i]==BACKGROUND) { eval(pf+'background="'+ar[++i]+'"'); continue; }
+ if (ar[i]==NOCLOSE) { if (pf!='ol_') opt_NOCLOSE(); continue; }
+ if (ar[i]==CAPTION) { eval(pf+"cap='"+escSglQuote(ar[++i])+"'"); continue; }
+ if (ar[i]==CENTER || ar[i]==LEFT || ar[i]==RIGHT) { eval(pf+'hpos='+ar[i]); continue; }
+ if (ar[i]==OFFSETX) { eval(pf+'offsetx='+ar[++i]); continue; }
+ if (ar[i]==OFFSETY) { eval(pf+'offsety='+ar[++i]); continue; }
+ if (ar[i]==FGCOLOR) { eval(pf+'fgcolor="'+ar[++i]+'"'); continue; }
+ if (ar[i]==BGCOLOR) { eval(pf+'bgcolor="'+ar[++i]+'"'); continue; }
+ if (ar[i]==TEXTCOLOR) { eval(pf+'textcolor="'+ar[++i]+'"'); continue; }
+ if (ar[i]==CAPCOLOR) { eval(pf+'capcolor="'+ar[++i]+'"'); continue; }
+ if (ar[i]==CLOSECOLOR) { eval(pf+'closecolor="'+ar[++i]+'"'); continue; }
+ if (ar[i]==WIDTH) { eval(pf+'width='+ar[++i]); continue; }
+ if (ar[i]==BORDER) { eval(pf+'border='+ar[++i]); continue; }
+ if (ar[i]==CELLPAD) { i=opt_MULTIPLEARGS(++i,ar,(pf+'cellpad')); continue; }
+ if (ar[i]==STATUS) { eval(pf+"status='"+escSglQuote(ar[++i])+"'"); continue; }
+ if (ar[i]==AUTOSTATUS) { eval(pf +'autostatus=('+pf+'autostatus == 1) ? 0 : 1'); continue; }
+ if (ar[i]==AUTOSTATUSCAP) { eval(pf +'autostatus=('+pf+'autostatus == 2) ? 0 : 2'); continue; }
+ if (ar[i]==HEIGHT) { eval(pf+'height='+pf+'aboveheight='+ar[++i]); continue; } // Same param again.
+ if (ar[i]==CLOSETEXT) { eval(pf+"close='"+escSglQuote(ar[++i])+"'"); continue; }
+ if (ar[i]==SNAPX) { eval(pf+'snapx='+ar[++i]); continue; }
+ if (ar[i]==SNAPY) { eval(pf+'snapy='+ar[++i]); continue; }
+ if (ar[i]==FIXX) { eval(pf+'fixx='+ar[++i]); continue; }
+ if (ar[i]==FIXY) { eval(pf+'fixy='+ar[++i]); continue; }
+ if (ar[i]==RELX) { eval(pf+'relx='+ar[++i]); continue; }
+ if (ar[i]==RELY) { eval(pf+'rely='+ar[++i]); continue; }
+ if (ar[i]==FGBACKGROUND) { eval(pf+'fgbackground="'+ar[++i]+'"'); continue; }
+ if (ar[i]==BGBACKGROUND) { eval(pf+'bgbackground="'+ar[++i]+'"'); continue; }
+ if (ar[i]==PADX) { eval(pf+'padxl='+ar[++i]); eval(pf+'padxr='+ar[++i]); continue; }
+ if (ar[i]==PADY) { eval(pf+'padyt='+ar[++i]); eval(pf+'padyb='+ar[++i]); continue; }
+ if (ar[i]==FULLHTML) { if (pf!='ol_') eval(pf+'fullhtml=1'); continue; }
+ if (ar[i]==BELOW || ar[i]==ABOVE) { eval(pf+'vpos='+ar[i]); continue; }
+ if (ar[i]==CAPICON) { eval(pf+'capicon="'+ar[++i]+'"'); continue; }
+ if (ar[i]==TEXTFONT) { eval(pf+"textfont='"+escSglQuote(ar[++i])+"'"); continue; }
+ if (ar[i]==CAPTIONFONT) { eval(pf+"captionfont='"+escSglQuote(ar[++i])+"'"); continue; }
+ if (ar[i]==CLOSEFONT) { eval(pf+"closefont='"+escSglQuote(ar[++i])+"'"); continue; }
+ if (ar[i]==TEXTSIZE) { eval(pf+'textsize="'+ar[++i]+'"'); continue; }
+ if (ar[i]==CAPTIONSIZE) { eval(pf+'captionsize="'+ar[++i]+'"'); continue; }
+ if (ar[i]==CLOSESIZE) { eval(pf+'closesize="'+ar[++i]+'"'); continue; }
+ if (ar[i]==TIMEOUT) { eval(pf+'timeout='+ar[++i]); continue; }
+ if (ar[i]==FUNCTION) { if (pf=='ol_') { if (typeof ar[i+1]!='number') { v=ar[++i]; ol_function=(typeof v=='function' ? v : null); }} else {fnMark = 0; v = null; if (typeof ar[i+1]!='number') v = ar[++i]; opt_FUNCTION(v); } continue; }
+ if (ar[i]==DELAY) { eval(pf+'delay='+ar[++i]); continue; }
+ if (ar[i]==HAUTO) { eval(pf+'hauto=('+pf+'hauto == 0) ? 1 : 0'); continue; }
+ if (ar[i]==VAUTO) { eval(pf+'vauto=('+pf+'vauto == 0) ? 1 : 0'); continue; }
+ if (ar[i]==CLOSECLICK) { eval(pf +'closeclick=('+pf+'closeclick == 0) ? 1 : 0'); continue; }
+ if (ar[i]==WRAP) { eval(pf +'wrap=('+pf+'wrap == 0) ? 1 : 0'); continue; }
+ if (ar[i]==FOLLOWMOUSE) { eval(pf +'followmouse=('+pf+'followmouse == 1) ? 0 : 1'); continue; }
+ if (ar[i]==MOUSEOFF) { eval(pf +'mouseoff=('+pf+'mouseoff == 0) ? 1 : 0'); continue; }
+ if (ar[i]==CLOSETITLE) { eval(pf+"closetitle='"+escSglQuote(ar[++i])+"'"); continue; }
+ if (ar[i]==CSSOFF||ar[i]==CSSCLASS) { eval(pf+'css='+ar[i]); continue; }
+ if (ar[i]==FGCLASS) { eval(pf+'fgclass="'+ar[++i]+'"'); continue; }
+ if (ar[i]==BGCLASS) { eval(pf+'bgclass="'+ar[++i]+'"'); continue; }
+ if (ar[i]==TEXTFONTCLASS) { eval(pf+'textfontclass="'+ar[++i]+'"'); continue; }
+ if (ar[i]==CAPTIONFONTCLASS) { eval(pf+'captionfontclass="'+ar[++i]+'"'); continue; }
+ if (ar[i]==CLOSEFONTCLASS) { eval(pf+'closefontclass="'+ar[++i]+'"'); continue; }
+ i = parseCmdLine(pf, i, ar);
+ }
+ }
+
+ if (fnMark && o3_function) o3_text = o3_function();
+
+ if ((pf == 'o3_') && o3_wrap) {
+ o3_width = 0;
+
+ if (olOp || (olIe4 && isMac)) {
+ var tReg=/<.*\n*>/ig;
+ if (!tReg.test(o3_text)) o3_text = o3_text.replace(/[ ]+/g, ' ');
+ if (!tReg.test(o3_cap))o3_cap = o3_cap.replace(/[ ]+/g, ' ');
+ }
+ }
+ if ((pf == 'o3_') && o3_sticky) {
+ if (!o3_close && (o3_frame != ol_frame)) o3_close = ol_close;
+ if (o3_mouseoff && (o3_frame == ol_frame)) opt_NOCLOSE(' ');
+ }
+}
+
+
+////////
+// LAYER FUNCTIONS
+////////
+
+// Writes to a layer
+function layerWrite(txt) {
+ txt += "\n";
+ if (olNs4) {
+ var lyr = o3_frame.document.overDiv.document
+ lyr.write(txt)
+ lyr.close()
+ } else if (typeof over.innerHTML != 'undefined') {
+ if (olIe5 && isMac) over.innerHTML = '';
+ over.innerHTML = txt;
+ } else {
+ range = o3_frame.document.createRange();
+ range.setStartAfter(over);
+ domfrag = range.createContextualFragment(txt);
+
+ while (over.hasChildNodes()) {
+ over.removeChild(over.lastChild);
+ }
+
+ over.appendChild(domfrag);
+ }
+}
+
+// Make an object visible
+function showObject(obj) {
+ runHook("showObject", FBEFORE);
+
+ var theObj=(olNs4 ? obj : obj.style);
+ theObj.visibility = 'visible';
+
+ runHook("showObject", FAFTER);
+}
+
+// Hides an object
+function hideObject(obj) {
+ runHook("hideObject", FBEFORE);
+
+ var theObj=(olNs4 ? obj : obj.style);
+ theObj.visibility = 'hidden';
+
+ if (o3_timerid > 0) clearTimeout(o3_timerid);
+ if (o3_delayid > 0) clearTimeout(o3_delayid);
+
+ o3_timerid = 0;
+ o3_delayid = 0;
+ self.status = "";
+
+ if (over.onmouseout || over.onmouseover) {
+ if (olNs4) over.releaseEvents(Event.MOUSEOUT || Event.MOUSEOVER);
+ over.onmouseout = over.onmouseover = null;
+ }
+
+ runHook("hideObject", FAFTER);
+}
+
+// Move a layer
+function repositionTo(obj, xL, yL) {
+ var theObj=(olNs4 ? obj : obj.style);
+ theObj.left = xL + (!olNs4 ? 'px' : 0);
+ theObj.top = yL + (!olNs4 ? 'px' : 0);
+}
+
+// Check position of cursor relative to overDiv DIVision; mouseOut function
+function cursorOff() {
+ var left = parseInt(over.style.left);
+ var top = parseInt(over.style.top);
+ var right = left+over.offsetWidth;
+ var bottom = top+ over.offsetHeight;
+
+ if (o3_x < left || o3_x > right || o3_y < top || o3_y > bottom) return true;
+
+ return false;
+}
+
+
+////////
+// COMMAND FUNCTIONS
+////////
+
+// Calls callme or the default function.
+function opt_FUNCTION(callme) {
+ o3_text = (callme ? (typeof callme=='string' ? (/.+\(.*\)/.test(callme) ? eval(callme) : callme) : callme()) : (o3_function ? o3_function() : 'No Function'));
+
+ return 0;
+}
+
+// Handle hovering
+function opt_NOCLOSE(unused) {
+ if (!unused) o3_close = "";
+
+ if (olNs4) {
+ over.captureEvents(Event.MOUSEOUT || Event.MOUSEOVER);
+ over.onmouseover = function () { if (o3_timerid > 0) { clearTimeout(o3_timerid); o3_timerid = 0; } }
+ over.onmouseout = cClick;
+ } else {
+ over.onmouseover = function () {hoveringSwitch = true; if (o3_timerid > 0) { clearTimeout(o3_timerid); o3_timerid =0; } }
+ }
+
+ return 0;
+}
+
+// Function to scan command line arguments for multiples
+function opt_MULTIPLEARGS(i, args, parameter) {
+ var k = i, l, re, pV, str = '';
+
+ for(k=i; k<args.length; k++) {
+ str += args[k] + ',';
+ if(typeof args[k] == 'number'&&args[k]>pmStart) break;
+ }
+ if(k >= args.length) l = str.length-1;
+ else {
+ re = eval('/,' + args[k] + '/');
+ l = str.search(re);
+ }
+
+ k--; // reduce by one so the for loop this is in works correctly
+ str = str.substring(0, l);
+ pV = (olNs4&&/cellpad/i.test(parameter)) ? str.split(',')[0] : str;
+ eval(parameter + '="' + pV + '"');
+
+ return k;
+}
+
+// Remove in texts when done.
+function nbspCleanup() {
+ if (o3_wrap && (olOp || (olIe4 && isMac))) {
+ o3_text = o3_text.replace(/\ /g, ' ');
+ o3_cap = o3_cap.replace(/\ /g, ' ');
+ }
+}
+
+// Escape embedded single quotes in text strings
+function escSglQuote(str) {
+ return str.toString().replace(/'/g,"\\'");
+}
+
+// Onload handler for window onload event
+function OLonLoad_handler(e) {
+ if (!olLoaded) olLoaded=1; // indicates that all modules have loaded now
+
+ // remove the OLonload_handler for Ns6+, Mozilla based browsers, and IE
+ if (window.removeEventListener) window.removeEventListener("load",OLonLoad_handler,true);
+ else if (window.detachEvent) window.detachEvent("onload",OLonLoad_handler);
+
+ // Route the event to the normal handler in Nx4.x
+ if (olNs4) routeEvent(e);
+}
+
+// Wraps strings in Layer Generation Functions with the correct tags
+// endWrap true(if end tag) or false if start tag
+// fontSizeStr - font size string such as '1' or '10px'
+// whichString is being wrapped -- 'text', 'caption', or 'close'
+function wrapStr(endWrap,fontSizeStr,whichString) {
+ var fontStr, fontColor, isClose=((whichString=='close') ? 1 : 0), hasDims=/[%\-a-z]+$/.test(fontSizeStr);
+ fontSizeStr = (olNs4) ? (!hasDims ? fontSizeStr : '1') : fontSizeStr;
+ if (endWrap) return (hasDims&&!olNs4) ? (isClose ? '</span>' : '</div>') : '</font>';
+ else {
+ fontStr='o3_'+whichString+'font';
+ fontColor='o3_'+((whichString=='caption')? 'cap' : whichString)+'color';
+ return (hasDims&&!olNs4) ? (isClose ? '<span style="font-family: '+quoteMultiNameFonts(eval(fontStr))+'; color: '+eval(fontColor)+'; font-size: '+fontSizeStr+';">' : '<div style="font-family: '+quoteMultiNameFonts(eval(fontStr))+'; color: '+eval(fontColor)+'; font-size: '+fontSizeStr+';">') : '<font face="'+eval(fontStr)+'" color="'+eval(fontColor)+'" size="'+(parseInt(fontSizeStr)>7 ? '7' : fontSizeStr)+'">';
+ }
+}
+
+// Quotes Multi word font names; needed for CSS Standards adherence in font-family
+function quoteMultiNameFonts(theFont) {
+ var v, pM=theFont.split(',');
+ for (var i=0; i<pM.length; i++) {
+ v=pM[i];
+ v=v.replace(/^\s+/,'').replace(/\s+$/,'');
+ if(/\s/.test(v) && !/['"]/.test(v)) {
+ v="\'"+v+"\'";
+ pM[i]=v;
+ }
+ }
+ return pM.join();
+}
+
+// dummy function which will be overridden
+function isExclusive(args) {
+ return false;
+}
+////////
+// PLUGIN ACTIVATION FUNCTIONS
+////////
+
+// Runs plugin functions to set runtime variables.
+function setRunTimeVariables(){
+ if (typeof runTime != 'undefined' && runTime.length) {
+ for (var k = 0; k < runTime.length; k++) {
+ runTime[k]();
+ }
+ }
+}
+
+// Runs plugin functions to parse commands.
+function parseCmdLine(pf, i, args) {
+ if (typeof cmdLine != 'undefined' && cmdLine.length) {
+ for (var k = 0; k < cmdLine.length; k++) {
+ var j = cmdLine[k](pf, i, args);
+ if (j >- 1) {
+ i = j;
+ break;
+ }
+ }
+ }
+
+ return i;
+}
+
+// Runs plugin functions to do things after parse.
+function postParseChecks(){
+ if (typeof postParse != 'undefined' && postParse.length) {
+ for (var k = 0; k < postParse.length; k++) {
+ if (postParse[k]()) continue;
+ return false; // end now since have an error
+ }
+ }
+ return true;
+}
+
+
+////////
+// PLUGIN REGISTRATION FUNCTIONS
+////////
+
+// Registers commands and creates constants.
+function registerCommands(cmdStr) {
+ if (typeof cmdStr!='string') return;
+
+ var pM = cmdStr.split(',');
+ pms = pms.concat(pM);
+
+ for (var i = 0; i< pM.length; i++) {
+ eval(pM[i].toUpperCase()+'='+pmCount++);
+ }
+}
+
+// Register a function to hook at a certain point.
+function registerHook(fnHookTo, fnRef, hookType, optPm) {
+ var hookPt, last = typeof optPm;
+
+ if (fnHookTo == 'plgIn'||fnHookTo == 'postParse') return;
+ if (typeof hookPts == 'undefined') hookPts = new Array();
+ if (typeof hookPts[fnHookTo] == 'undefined') hookPts[fnHookTo] = new FunctionReference();
+
+ hookPt = hookPts[fnHookTo];
+
+ if (hookType != null) {
+ if (hookType == FREPLACE) {
+ hookPt.ovload = fnRef; // replace normal overlib routine
+ if (fnHookTo.indexOf('ol_content_') > -1) hookPt.alt[pms[CSSOFF-1-pmStart]]=fnRef;
+
+ } else if (hookType == FBEFORE || hookType == FAFTER) {
+ var hookPt=(hookType == 1 ? hookPt.before : hookPt.after);
+
+ if (typeof fnRef == 'object') {
+ hookPt = hookPt.concat(fnRef);
+ } else {
+ hookPt[hookPt.length++] = fnRef;
+ }
+
+ if (optPm) hookPt = reOrder(hookPt, fnRef, optPm);
+
+ } else if (hookType == FALTERNATE) {
+ if (last=='number') hookPt.alt[pms[optPm-1-pmStart]] = fnRef;
+ }
+
+ return;
+ }
+}
+
+// Register a function that will set runtime variables.
+function registerRunTimeFunction(fn) {
+ if (isFunction(fn)) {
+ if (typeof runTime == 'undefined') runTime = new Array();
+ if (typeof fn == 'object') {
+ runTime = runTime.concat(fn);
+ } else {
+ runTime[runTime.length++] = fn;
+ }
+ }
+}
+
+// Register a function that will handle command parsing.
+function registerCmdLineFunction(fn){
+ if (isFunction(fn)) {
+ if (typeof cmdLine == 'undefined') cmdLine = new Array();
+ if (typeof fn == 'object') {
+ cmdLine = cmdLine.concat(fn);
+ } else {
+ cmdLine[cmdLine.length++] = fn;
+ }
+ }
+}
+
+// Register a function that does things after command parsing.
+function registerPostParseFunction(fn){
+ if (isFunction(fn)) {
+ if (typeof postParse == 'undefined') postParse = new Array();
+ if (typeof fn == 'object') {
+ postParse = postParse.concat(fn);
+ } else {
+ postParse[postParse.length++] = fn;
+ }
+ }
+}
+
+////////
+// PLUGIN REGISTRATION FUNCTIONS
+////////
+
+// Runs any hooks registered.
+function runHook(fnHookTo, hookType) {
+ var l = hookPts[fnHookTo], optPm, arS, ar = runHook.arguments;
+
+ if (hookType == FREPLACE) {
+ arS = argToString(ar, 2);
+
+ if (typeof l == 'undefined' || !(l = l.ovload)) return eval(fnHookTo+'('+arS+')');
+ else return eval('l('+arS+')');
+
+ } else if (hookType == FBEFORE || hookType == FAFTER) {
+ if (typeof l == 'undefined') return;
+ l=(hookType == 1 ? l.before : l.after);
+
+ if (!l.length) return;
+
+ arS = argToString(ar, 2);
+ for (var k = 0; k < l.length; k++) eval('l[k]('+arS+')');
+
+ } else if (hookType == FALTERNATE) {
+ optPm = ar[2];
+ arS = argToString(ar, 3);
+
+ if (typeof l == 'undefined' || (l = l.alt[pms[optPm-1-pmStart]]) == 'undefined') {
+ return eval(fnHookTo+'('+arS+')');
+ } else {
+ return eval('l('+arS+')');
+ }
+ }
+}
+
+////////
+// UTILITY FUNCTIONS
+////////
+
+// Checks if something is a function.
+function isFunction(fnRef) {
+ var rtn = true;
+
+ if (typeof fnRef == 'object') {
+ for (var i = 0; i < fnRef.length; i++) {
+ if (typeof fnRef[i]=='function') continue;
+ rtn = false;
+ break;
+ }
+ } else if (typeof fnRef != 'function') {
+ rtn = false;
+ }
+
+ return rtn;
+}
+
+// Converts an array into an argument string for use in eval.
+function argToString(array, strtInd, argName) {
+ var jS = strtInd, aS = '', ar = array;
+ argName=(argName ? argName : 'ar');
+
+ if (ar.length > jS) {
+ for (var k = jS; k < ar.length; k++) aS += argName+'['+k+'], ';
+ aS = aS.substring(0, aS.length-2);
+ }
+
+ return aS;
+}
+
+// Places a hook in the correct position in a hook point.
+function reOrder(hookPt, fnRef, order) {
+ if (!order || typeof order == 'undefined' || typeof order == 'number') return;
+
+ var newPt = new Array(), match;
+
+ if (typeof order=='function') {
+ if (typeof fnRef=='object') {
+ newPt = newPt.concat(fnRef);
+ } else {
+ newPt[newPt.length++]=fnRef;
+ }
+
+ for (var i = 0; i < hookPt.length; i++) {
+ match = false;
+ if (typeof fnRef == 'function' && hookPt[i] == fnRef) {
+ continue;
+ } else {
+ for(var j = 0; j < fnRef.length; j++) if (hookPt[i] == fnRef[j]) {
+ match = true;
+ break;
+ }
+ }
+ if (!match) newPt[newPt.length++] = hookPt[i];
+ }
+
+ newPt[newPt.length++] = order;
+
+ } else if (typeof order == 'object') {
+ if (typeof fnRef == 'object') {
+ newPt = newPt.concat(fnRef);
+ } else {
+ newPt[newPt.length++] = fnRef;
+ }
+
+ for (var j = 0; j < hookPt.length; j++) {
+ match = false;
+ if (typeof fnRef == 'function' && hookPt[j] == fnRef) {
+ continue;
+ } else {
+ for (var i = 0; i < fnRef.length; i++) if (hookPt[j] == fnRef[i]) {
+ match = true;
+ break;
+ }
+ }
+ if (!match) newPt[newPt.length++]=hookPt[j];
+ }
+
+ for (i = 0; i < newPt.length; i++) hookPt[i] = newPt[i];
+ newPt.length = 0;
+
+ for (var j = 0; j < hookPt.length; j++) {
+ match = false;
+ for (var i = 0; i < order.length; i++) {
+ if (hookPt[j] == order[i]) {
+ match = true;
+ break;
+ }
+ }
+ if (!match) newPt[newPt.length++] = hookPt[j];
+ }
+ newPt = newPt.concat(order);
+ }
+
+ for(i = 0; i < newPt.length; i++) hookPt[i] = newPt[i];
+
+ return hookPt;
+}
+
+////////
+// OBJECT CONSTRUCTORS
+////////
+
+// Object for handling hooks.
+function FunctionReference() {
+ this.ovload = null;
+ this.before = new Array();
+ this.after = new Array();
+ this.alt = new Array();
+}
+
+// Object for simple access to the overLIB version used.
+// Examples: simpleversion:351 major:3 minor:5 revision:1
+function Info(version, prerelease) {
+ this.version = version;
+ this.prerelease = prerelease;
+
+ this.simpleversion = parseInt(this.version*100);
+ this.major = parseInt(this.simpleversion / 100);
+ this.minor = parseInt(this.simpleversion / 10) - this.major * 10;
+ this.revision = parseInt(this.simpleversion) - this.major * 100 - this.minor * 10;
+}
+
+
+
+////////
+// STANDARD REGISTRATIONS
+////////
+registerHook("ol_content_simple", ol_content_simple, FALTERNATE, CSSOFF);
+registerHook("ol_content_caption", ol_content_caption, FALTERNATE, CSSOFF);
+registerHook("ol_content_background", ol_content_background, FALTERNATE, CSSOFF);
+registerHook("ol_content_simple", ol_content_simple, FALTERNATE, CSSCLASS);
+registerHook("ol_content_caption", ol_content_caption, FALTERNATE, CSSCLASS);
+registerHook("ol_content_background", ol_content_background, FALTERNATE, CSSCLASS);
+registerHook("hideObject", nbspCleanup, FAFTER);
+
--- /dev/null
+//\/////
+//\ overLIB Anchor Plugin
+//\ This file requires overLIB 4.00 or later.
+//\
+//\ overLIB 4.00 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\ Contributors are listed on the homepage.
+//\ See http://www.bosrup.com/web/overlib/ for details.
+// $Revision$ $Date$
+//\/////
+
+
+
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+if (typeof olInfo == 'undefined' || olInfo.simpleversion < 400) alert('overLIB 4.00 or later is required for the Anchor Plugin.');
+registerCommands('anchor,anchorx,anchory,noanchorwarn,anchoralign');
+
+
+
+////////
+// DEFAULT CONFIGURATION
+// Settings you want everywhere are set here. All of this can also be
+// changed on your html page or through an overLIB call.
+////////
+if (typeof ol_anchor == 'undefined') var ol_anchor = '';
+if (typeof ol_anchorx == 'undefined') var ol_anchorx = 0;
+if (typeof ol_anchory == 'undefined') var ol_anchory = 0;
+if (typeof ol_noanchorwarn == 'undefined') var ol_noanchorwarn = 1;
+if (typeof ol_anchoralign == 'undefined') var ol_anchoralign = 'UL';
+
+////////
+// END OF CONFIGURATION
+// Don't change anything below this line, all configuration is above.
+////////
+
+
+
+
+
+////////
+// INIT
+////////
+// Runtime variables init. Don't change for config!
+var o3_anchor = "";
+var o3_anchorx = 0;
+var o3_anchory = 0;
+var o3_noanchorwarn = 1;
+var o3_anchoralign = 'UL';
+var mrkObj, rmrkPosition; //reference mark object, reference mark position, an array;
+
+
+////////
+// PLUGIN FUNCTIONS
+////////
+function setAnchorVariables() {
+ o3_anchor = ol_anchor;
+ o3_anchorx = ol_anchorx;
+ o3_anchory = ol_anchory;
+ o3_noanchorwarn = ol_noanchorwarn;
+ o3_anchoralign = ol_anchoralign;
+ mrkObj = null; // initialize this variable
+}
+
+// Parses Reference Mark commands
+function parseAnchorExtras(pf,i,ar) {
+ var v, k=i;
+
+ if (k < ar.length) {
+ if (ar[k] == ANCHOR) { eval(pf + "anchor = '" + escSglQuote(ar[++k]) + "'"); return k; }
+ if (ar[k] == ANCHORX) { eval(pf + 'anchorx = ' + ar[++k]); return k; }
+ if (ar[k] == ANCHORY) { eval(pf + 'anchory = ' + ar[++k]); return k; }
+ if (ar[k] == NOANCHORWARN) { eval(pf + 'noanchorwarn = (' + pf + 'noanchorwarn==1) ? 0 : 1'); return k; }
+ if (ar[k] == ANCHORALIGN) { k = opt_MULTIPLEARGS(++k, ar, (pf + 'anchoralign')); return k; }
+ }
+
+ return -1;
+}
+
+
+///////
+// FUNCTION WHICH CHECKS FOR THE EXISTENCE OF A REFERENCE MARKER
+///////
+function checkAnchorObject() {
+ var w = o3_anchor;
+
+ if (w) {
+ if (!(mrkObj = getAnchorObjectRef(w))) {
+ if (o3_noanchorwarn) {
+ alert('WARNING! Reference mark "' + w + '" not found.');
+ return false;
+ } else w = '';
+ }
+ }
+
+ return true;
+}
+
+
+//////
+// HANDLING FUNCTIONS, OVERLOADS CORE MODULE
+//////
+
+// Decides where we want the popup.
+function anchorPlaceLayer() {
+ var placeX, placeY, widthFix = 0;
+
+ // HORIZONTAL PLACEMENT
+ if (eval('o3_frame.'+docRoot) && eval("typeof o3_frame."+docRoot+".clientWidth == 'number'") && eval('o3_frame.'+docRoot+'.clientWidth')) {
+ iwidth = eval('o3_frame.'+docRoot+'.clientWidth');
+ } else if (typeof(o3_frame.innerWidth) == 'number') {
+ widthFix = Math.ceil(1.2*(o3_frame.outerWidth - o3_frame.innerWidth));
+ iwidth = o3_frame.innerWidth;
+ }
+
+ if (o3_anchor) {
+ placeX = rmrkPosition[0];
+ placeY = rmrkPosition[1];
+ } else {
+ // Horizontal scroll offset
+ winoffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollLeft') : o3_frame.pageXOffset;
+ var parsedWidth = parseInt(o3_width);
+
+ if (o3_fixx > -1 || o3_relx != null) {
+ // Fixed position
+ placeX=(o3_relx != null ? ( o3_relx < 0 ? winoffset +o3_relx+ iwidth - parsedWidth - widthFix : winoffset+o3_relx) : o3_fixx);
+ } else {
+ // If HAUTO, decide what to use.
+ if (o3_hauto == 1) {
+ if ((o3_x - winoffset) > (iwidth / 2)) {
+ o3_hpos = LEFT;
+ } else {
+ o3_hpos = RIGHT;
+ }
+ }
+
+ // From mouse
+ if (o3_hpos == CENTER) { // Center
+ placeX = o3_x+o3_offsetx-(parsedWidth/2);
+
+ if (placeX < winoffset) placeX = winoffset;
+ }
+
+ if (o3_hpos == RIGHT) { // Right
+ placeX = o3_x+o3_offsetx;
+
+ if ((placeX+parsedWidth) > (winoffset+iwidth - widthFix)) {
+ placeX = iwidth+winoffset - parsedWidth - widthFix;
+ if (placeX < 0) placeX = 0;
+ }
+ }
+ if (o3_hpos == LEFT) { // Left
+ placeX = o3_x-o3_offsetx-parsedWidth;
+ if (placeX < winoffset) placeX = winoffset;
+ }
+
+ // Snapping!
+ if (o3_snapx > 1) {
+ var snapping = placeX % o3_snapx;
+
+ if (o3_hpos == LEFT) {
+ placeX = placeX - (o3_snapx+snapping);
+ } else {
+ // CENTER and RIGHT
+ placeX = placeX+(o3_snapx - snapping);
+ }
+
+ if (placeX < winoffset) placeX = winoffset;
+ }
+ }
+
+ // VERTICAL PLACEMENT
+ if (eval('o3_frame.'+docRoot) && eval("typeof o3_frame."+docRoot+".clientHeight == 'number'") && eval('o3_frame.'+docRoot+'.clientHeight')) {
+ iheight = eval('o3_frame.'+docRoot+'.clientHeight');
+ } else if (typeof(o3_frame.innerHeight) == 'number') {
+ iheight = o3_frame.innerHeight;
+ }
+
+ // Vertical scroll offset
+ scrolloffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollTop') : o3_frame.pageYOffset;
+ var parsedHeight=(o3_aboveheight ? parseInt(o3_aboveheight) : (olNs4 ? over.clip.height : over.offsetHeight));
+
+ if (o3_fixy > -1 || o3_rely != null) {
+ // Fixed position
+ placeY = (o3_rely != null ? (o3_rely < 0 ? scrolloffset+o3_rely+iheight - parsedHeight : scrolloffset+o3_rely) : o3_fixy);
+ } else {
+ // If VAUTO, decide what to use.
+ if (o3_vauto == 1) {
+ if ((o3_y - scrolloffset) > (iheight/2)) {
+ o3_vpos = ABOVE;
+ } else {
+ o3_vpos = BELOW;
+ }
+ }
+
+ // From mouse
+ if (o3_vpos == ABOVE) {
+ if (o3_aboveheight == 0) o3_aboveheight = parsedHeight;
+
+ placeY = o3_y - (o3_aboveheight+o3_offsety);
+ if (placeY < scrolloffset) placeY = scrolloffset;
+ } else {
+ // BELOW
+ placeY = o3_y+o3_offsety;
+ }
+
+ // Snapping!
+ if (o3_snapy > 1) {
+ var snapping = placeY % o3_snapy;
+
+ if (o3_aboveheight > 0 && o3_vpos == ABOVE) {
+ placeY = placeY - (o3_snapy+snapping);
+ } else {
+ placeY = placeY+(o3_snapy - snapping);
+ }
+
+ if (placeY < scrolloffset) placeY = scrolloffset;
+ }
+ }
+ }
+
+ // Actually move the object.
+ repositionTo(over, placeX, placeY);
+ if (typeof o3_scroll != 'undefined' && o3_scroll && o3_sticky && (o3_relx || o3_rely) && (typeof o3_draggable == 'undefined' || !o3_draggable)) {
+ if (typeof over.scroller == 'undefined' || over.scroller.canScroll) over.scroller = new scroller(placeX - winoffset, placeY - scrolloffset, setTimeout("repositionOver()", 20));
+ }
+}
+///////
+// EXTERNAL SUPPORT FUNCTIONS TO HANDLE ANCHOR PROPERTIES
+///////
+
+// Stub function for the runHook routine
+function anchorPreface() {
+ if (!mrkObj) return;
+ rmrkPosition = getAnchorLocation(mrkObj);
+}
+
+// Get Reference Mark object
+function getAnchorObjectRef(aObj) {
+ return getRefById(aObj, o3_frame.document) || getRefByName(aObj, o3_frame.document)
+}
+
+// Adapted to overlib from jwin by Jason Anderson -- http://www.jwinlib.com
+function getAnchorLocation(objRef){
+ var mkObj, of, offsets, mlyr
+
+ mkObj = mlyr = objRef
+ offsets = [o3_anchorx, o3_anchory]
+
+ if (document.layers){
+ if (typeof mlyr.length != 'undefined' && mlyr.length > 1) {
+ mkObj = mlyr[0]
+ offsets[0] += mlyr[0].x + mlyr[1].pageX
+ offsets[1] += mlyr[0].y + mlyr[1].pageY
+ } else {
+ if(mlyr.toString().indexOf('Image') != -1 || mlyr.toString().indexOf('Anchor') != -1){
+ offsets[0] += mlyr.x
+ offsets[1] += mlyr.y
+ } else {
+ offsets[0] += mlyr.pageX
+ offsets[1] += mlyr.pageY
+ }
+ }
+ } else {
+ offsets[0] += pageLocation(mlyr, 'Left')
+ offsets[1] += pageLocation(mlyr, 'Top')
+ }
+
+ of = getAnchorOffsets(mkObj)
+
+ if (typeof o3_dragimg != 'undefined' && o3_dragimg) {
+ olImgLeft = offsets[0];
+ olImgTop = offsets[1];
+ }
+
+ offsets[0] += of[0]
+ offsets[1] += of[1]
+
+ if (typeof o3_dragimg != 'undefined' && o3_dragimg) {
+ olImgRight = offsets[0];
+ olImgBottom = offsets[1];
+ return;
+ }
+
+ return offsets;
+}
+
+// Adapted to overlib from jwin by Jason Anderson -- http://www.jwinlib.com
+function getAnchorOffsets(mkObj){
+ var fx = fy = 0, mp, puc, mkAry, sx = sy = 0, w = o3_anchoralign
+ var mW = mH = pW = pH = 0
+ var off = [0, 0]
+
+ mkAry = w.split(',');
+
+ if (mkAry.length < 3) {
+ mp = mkAry[0].toUpperCase();
+ puc = (mkAry.length == 1) ? mp : mkAry[1].toUpperCase();
+ } else if (mkAry.length == 3) {
+ if (!isNaN(mkAry[0])) {
+ mp = mkAry.slice(0, 2);
+ puc = mkAry[2].toUpperCase();
+ } else {
+ mp = mkAry[0].toUpperCase();
+ puc = mkAry.slice(1);
+ }
+ } else {
+ mp = mkAry.slice(0, 2);
+ puc = mkAry.slice(2);
+ }
+
+ var shdwPresent = typeof o3_shadow != 'undefined' && o3_shadow
+
+ if (shdwPresent) {
+ sx = Math.abs(o3_shadowx);
+ sy = Math.abs(o3_shadowy);
+ }
+
+ pW = (shdwPresent ? parseInt(o3_width) : (olNs4 ? over.clip.width : over.offsetWidth))
+ pH = (shdwPresent ? parseInt(o3_aboveheight) : (olNs4 ? over.clip.height : over.offsetHeight))
+
+ if (olOp && o3_wrap) {
+ pW = (shdwPresent ? parseInt(o3_width) : (olNs4 ? over.clip.width : over.offsetWidth))
+ pH = (shdwPresent ? parseInt(o3_aboveheight) : (olNs4 ? over.clip.height : over.offsetHeight))
+ }
+
+ if (!olOp && mkObj.toString().indexOf('Image') != -1){
+ mW = mkObj.width
+ mH = mkObj.height
+ } else if (!olOp && mkObj.toString().indexOf('Anchor') != -1) { // enforced only for NS4
+ mp = 'UL'
+ } else {
+ mW = (olNs4) ? mkObj.clip.width : mkObj.offsetWidth
+ mH = (olNs4) ? mkObj.clip.height : mkObj.offsetHeight
+ }
+
+ if (!isNaN(mp) || typeof mp == 'object') {
+ if (typeof mp == 'object') {
+ fx = parseFloat(mp[0]);
+ fy = parseFloat(mp[1]);
+ } else
+ fx = fy = parseFloat(mp);
+ off = [Math.round(fx*mW), Math.round(fy*mH)];
+ } else {
+ if (mp == 'UR') off = [mW, 0]
+ else if (mp == 'LL') off = [0, mH]
+ else if (mp == 'LR') off = [mW, mH]
+ }
+
+ if (typeof o3_dragimg != 'undefined' && o3_dragimg) return off;
+ else {
+ if (!isNaN(puc) || typeof puc == 'object' ) {
+ if (typeof puc == 'object') {
+ fx = parseFloat(puc[0]);
+ fy = parseFloat(puc[1]);
+ } else
+ fx = fy = parseFloat(puc);
+ off[0] -= Math.round(fx*(pW - sx));
+ off[1] -= Math.round(fy*(pH - sy));
+ } else {
+ if (puc == 'UR') {
+ off[0] -= (pW - sx);
+ off[1] -= sy
+ } else if (puc == 'LL') {
+ off[0] -= sx;
+ off[1] -= (pH - sy)
+ } else if (puc == 'LR') {
+ off[0] -= (pW-sx);
+ off[1] -= (pH - sy)
+ }
+ }
+ return off
+ }
+}
+
+// Adapted to overlib from jwin by Jason Anderson -- http://www.jwinlib.com
+function pageLocation(o, t){
+ var x = 0
+
+ while(o.offsetParent){
+ x += o['offset' + t]
+ o = o.offsetParent
+ }
+ x += o['offset' + t]
+
+ return x
+}
+
+// Adapted to overlib from jwin by Jason Anderson -- http://www.jwinlib.com
+function getRefById(l, d){
+ var r = "", j
+
+ d = (d || document)
+ if (d.all) return d.all[l]
+ else if (d.getElementById) return d.getElementById(l)
+ else if (d.layers && d.layers.length > 0) {
+ if (d.layers[l]) return d.layers[l]
+
+ for (j=0; j < d.layers.length; j++) {
+ r = getRefById(l, d.layers[j].document)
+ if(r) return r
+ }
+ }
+
+ return false
+}
+
+// Adapted to overlib from jwin by Jason Anderson -- http://www.jwinlib.com
+function getRefByName(l, d) {
+ var r = null, j
+
+ d = (d || document)
+
+ if (d.images[l]) return d.images[l]
+ else if (d.anchors[l]) return d.anchors[l];
+ else if (d.layers && d.layers.length > 0) {
+ for (j=0; j < d.layers.length; j++) {
+ r = getRefByName(l, d.layers[j].document)
+ if (r && r.length > 0) return r
+ else if (r) return [r, d.layers[j]]
+ }
+ }
+
+ return null
+}
+
+////////
+// PLUGIN REGISTRATIONS
+////////
+registerHook("placeLayer", anchorPlaceLayer, FREPLACE);
+registerRunTimeFunction(setAnchorVariables);
+registerCmdLineFunction(parseAnchorExtras);
+registerPostParseFunction(checkAnchorObject);
+registerHook("createPopup", anchorPreface, FAFTER);
+
--- /dev/null
+//\/////
+//\ overLIB Crossframe Support Plugin
+//\ This file requires overLIB 4.00 or later.
+//\
+//\ overLIB 4.00 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\ Contributors are listed on the homepage.
+//\ See http://www.bosrup.com/web/overlib/ for details.
+// $Revision$ $Date$
+//\/////
+
+
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+if (typeof olInfo == 'undefined' || olInfo.simpleversion < 400) alert('overLIB 4.00 or later is required for the Cross Frame Support Plugin.');
+registerCommands('frame');
+
+
+////////
+// PLUGIN FUNCTIONS
+///////
+
+// Parses FRAME command
+function parseFrameExtras(pf,i,ar) {
+ var k = i,v;
+
+ if (k < ar.length) {
+ if (ar[k] == FRAME) { v = ar[++k]; if(pf == 'ol_'&&compatibleframe(v)) ol_frame = v; else opt_FRAME(v); return k; }
+ }
+
+ return -1;
+}
+
+////////
+// SUPPORT FUNCTIONS
+////////
+
+// Defines which frame we should point to.
+function opt_FRAME(frm) {
+ o3_frame = compatibleFrame(frm) ? frm : ol_frame;
+
+ if (olNs4) {
+ over = o3_frame.document.layers['overDiv'];
+ } else if (document.all) {
+ over = o3_frame.document.all['overDiv'];
+ } else if (document.getElementById) {
+ over = o3_frame.document.getElementById("overDiv");
+ }
+
+ return 0;
+}
+
+// Makes sure target frame has overLIB
+function compatibleFrame(frameid) {
+ if (olNs4 && typeof frameid.document.overDiv == 'undefined') {
+ return false;
+ } else if (document.all && typeof frameid.document.all["overDiv"] == 'undefined') {
+ return false;
+ } else if (document.getElementById && frameid.document.getElementById('overDiv') == null) {
+ return false;
+ }
+
+ return true;
+}
+
+// Get frame depth of nested frames
+function frmDepth(thisFrame,ofrm) {
+ var retVal = '';
+
+ for (var i = 0; i<thisFrame.length; i++) {
+ if (thisFrame[i].length > 0) {
+ retVal = frmDepth(thisFrame[i],ofrm);
+ if (retVal == '') continue;
+ } else if (thisFrame[i] != ofrm) continue;
+ retVal = '[' + i + ']' + retVal;
+ break;
+ }
+
+ return retVal;
+}
+
+// Gets frame reference value relative to top frame
+function getFrmRef(srcFrm,tgetFrm) {
+ var rtnVal = ''
+
+ if (tgetFrm != srcFrm) {
+ var tFrm = frmDepth(top.frames,tgetFrm)
+ var sFrm = frmDepth(top.frames,srcFrm)
+ if (sFrm.length == tFrm.length) {
+ l = tFrm.lastIndexOf('[')
+
+ if (l) {
+ while ( sFrm.substring(0,l) != tFrm.substring(0,l) )
+ l = tFrm.lastIndexOf('[',l-1)
+ tFrm = tFrm.substr(l)
+ sFrm = sFrm.substr(l)
+ }
+ }
+
+ var cnt = 0, p = '',str = tFrm
+ while ((k = str.lastIndexOf('[')) != -1) {
+ cnt++
+ str = str.substring(0,k)
+ }
+
+ for (var i = 0; i<cnt; i++) p = p + 'parent.'
+ rtnVal = p + 'frames' + sFrm + '.'
+ }
+
+ return rtnVal
+}
+
+function chkForFrmRef() {
+ if(o3_frame != ol_frame) fnRef = getFrmRef(ol_frame,o3_frame)
+ return true;
+}
+
+////////
+// PLUGIN REGISTRATIONS
+////////
+registerCmdLineFunction(parseFrameExtras);
+registerPostParseFunction(chkForFrmRef);
+
--- /dev/null
+//\/////
+//\ overLIB CSS Style Plugin
+//\ This file requires overLIB 4.00 or later.
+//\
+//\ overLIB 4.00 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\ Contributors are listed on the homepage.
+//\ See http://www.bosrup.com/web/overlib/ for details.
+// $Revision$ $Date$
+//\/////
+
+
+
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+if (typeof olInfo == 'undefined' || olInfo.simpleversion < 400) alert('overLIB 4.00 or later is required for the CSS Style Plugin.');
+registerCommands('cssstyle,padunit,heightunit,widthunit,textsizeunit,textdecoration,textstyle,textweight,captionsizeunit,captiondecoration,captionstyle,captionweight,closesizeunit,closedecoration,closestyle,closeweight');
+
+
+////////
+// DEFAULT CONFIGURATION
+// Settings you want everywhere are set here. All of this can also be
+// changed on your html page or through an overLIB call.
+////////
+if (typeof ol_padunit=='undefined') var ol_padunit="px";
+if (typeof ol_heightunit=='undefined') var ol_heightunit="px";
+if (typeof ol_widthunit=='undefined') var ol_widthunit="px";
+if (typeof ol_textsizeunit=='undefined') var ol_textsizeunit="px";
+if (typeof ol_textdecoration=='undefined') var ol_textdecoration="none";
+if (typeof ol_textstyle=='undefined') var ol_textstyle="normal";
+if (typeof ol_textweight=='undefined') var ol_textweight="normal";
+if (typeof ol_captionsizeunit=='undefined') var ol_captionsizeunit="px";
+if (typeof ol_captiondecoration=='undefined') var ol_captiondecoration="none";
+if (typeof ol_captionstyle=='undefined') var ol_captionstyle="normal";
+if (typeof ol_captionweight=='undefined') var ol_captionweight="bold";
+if (typeof ol_closesizeunit=='undefined') var ol_closesizeunit="px";
+if (typeof ol_closedecoration=='undefined') var ol_closedecoration="none";
+if (typeof ol_closestyle=='undefined') var ol_closestyle="normal";
+if (typeof ol_closeweight=='undefined') var ol_closeweight="normal";
+
+////////
+// END OF CONFIGURATION
+// Don't change anything below this line, all configuration is above.
+////////
+
+
+
+////////
+// INIT
+////////
+// Runtime variables init. Don't change for config!
+var o3_padunit="px";
+var o3_heightunit="px";
+var o3_widthunit="px";
+var o3_textsizeunit="px";
+var o3_textdecoration="";
+var o3_textstyle="";
+var o3_textweight="";
+var o3_captionsizeunit="px";
+var o3_captiondecoration="";
+var o3_captionstyle="";
+var o3_captionweight="";
+var o3_closesizeunit="px";
+var o3_closedecoration="";
+var o3_closestyle="";
+var o3_closeweight="";
+
+
+////////
+// PLUGIN FUNCTIONS
+////////
+
+// Function which sets runtime variables to their default values
+function setCSSStyleVariables() {
+ o3_padunit=ol_padunit;
+ o3_heightunit=ol_heightunit;
+ o3_widthunit=ol_widthunit;
+ o3_textsizeunit=ol_textsizeunit;
+ o3_textdecoration=ol_textdecoration;
+ o3_textstyle=ol_textstyle;
+ o3_textweight=ol_textweight;
+ o3_captionsizeunit=ol_captionsizeunit;
+ o3_captiondecoration=ol_captiondecoration;
+ o3_captionstyle=ol_captionstyle;
+ o3_captionweight=ol_captionweight;
+ o3_closesizeunit=ol_closesizeunit;
+ o3_closedecoration=ol_closedecoration;
+ o3_closestyle=ol_closestyle;
+ o3_closeweight=ol_closeweight;
+}
+
+// Parses CSS Style commands.
+function parseCSSStyleExtras(pf, i, ar) {
+ var k = i;
+
+ if (k < ar.length) {
+ if (ar[k]==CSSSTYLE) { eval(pf+'css='+ar[k]); return k; }
+ if (ar[k]==PADUNIT) { eval(pf+'padunit="'+ar[++k]+'"'); return k; }
+ if (ar[k]==HEIGHTUNIT) { eval(pf+'heightunit="'+ar[++k]+'"'); return k; }
+ if (ar[k]==WIDTHUNIT) { eval(pf+'widthunit="'+ar[++k]+'"'); return k; }
+ if (ar[k]==TEXTSIZEUNIT) { eval(pf+'textsizeunit="'+ar[++k]+'"'); return k; }
+ if (ar[k]==TEXTDECORATION) { eval(pf+'textdecoration="'+ar[++k]+'"'); return k; }
+ if (ar[k]==TEXTSTYLE) { eval(pf+'textstyle="'+ar[++k]+'"'); return k; }
+ if (ar[k]==TEXTWEIGHT) { eval(pf+'textweight="'+ar[++k]+'"'); return k; }
+ if (ar[k]==CAPTIONSIZEUNIT) { eval(pf+'captionsizeunit="'+ar[++k]+'"'); return k; }
+ if (ar[k]==CAPTIONDECORATION) { eval(pf+'captiondecoration="'+ar[++k]+'"'); return k; }
+ if (ar[k]==CAPTIONSTYLE) { eval(pf+'captionstyle="'+ar[++k]+'"'); return k; }
+ if (ar[k]==CAPTIONWEIGHT) { eval(pf+'captionweight="'+ar[++k]+'"'); return k; }
+ if (ar[k]==CLOSESIZEUNIT) { eval(pf+'closesizeunit="'+ar[++k]+'"'); return k; }
+ if (ar[k]==CLOSEDECORATION) { eval(pf+'closedecoration="'+ar[++k]+'"'); return k; }
+ if (ar[k]==CLOSESTYLE) { eval(pf+'closestyle="'+ar[++k]+'"'); return k; }
+ if (ar[k]==CLOSEWEIGHT) { eval(pf+'closeweight="'+ar[++k]+'"'); return k; }
+ }
+
+ return -1;
+}
+
+////////
+// LAYER GENERATION FUNCTIONS
+////////
+
+// Makes simple table without caption
+function ol_content_simple_cssstyle(text) {
+ txt = '<table width="'+o3_width+ '" border="0" cellpadding="'+o3_border+'" cellspacing="0" style="background-color: '+o3_bgcolor+'; height: '+o3_height+o3_heightunit+';"><tr><td><table width="100%" border="0" cellpadding="' + o3_cellpad + '" cellspacing="0" style="color: '+o3_fgcolor+'; background-color: '+o3_fgcolor+'; height: '+o3_height+o3_heightunit+';"><tr><td valign="TOP"><font style="font-family: '+o3_textfont+'; color: '+o3_textcolor+'; font-size: '+o3_textsize+o3_textsizeunit+'; text-decoration: '+o3_textdecoration+'; font-weight: '+o3_textweight+'; font-style:'+o3_textstyle+'">'+text+'</font></td></tr></table></td></tr></table>';
+ set_background("");
+
+ return txt;
+}
+
+// Makes table with caption and optional close link
+function ol_content_caption_cssstyle(text, title, close) {
+ var nameId;
+ closing = "";
+ closeevent = "onMouseOver";
+
+ if (o3_closeclick == 1) closeevent= (o3_closetitle ? "title='" + o3_closetitle +"'" : "") + " onClick";
+
+ if (o3_capicon!="") {
+ nameId=' hspace=\"5\"'+' align=\"middle\" alt=\"\"';
+ if (typeof o3_dragimg != 'undefined' && o3_dragimg) nameId = ' hspace=\"5\"'+' name=\"'+o3_dragimg+'\" id=\"'+o3_dragimg+'\" align=\"middle\" alt=\"Drag Enabled\" title=\"Drag Enabled\"';
+ o3_capicon = '<img src=\"'+o3_capicon+'\"'+nameId+' />';
+ }
+
+ if (close != "") {
+ closing = '<td align="RIGHT"><a href="javascript:return '+fnRef+'cClick();" '+closeevent+'="return '+fnRef+'cClick();" style="color: '+o3_closecolor+'; font-family: '+o3_closefont+'; font-size: '+o3_closesize+o3_closesizeunit+'; text-decoration: '+o3_closedecoration+'; font-weight: '+o3_closeweight+'; font-style:'+o3_closestyle+';">'+close+'</a></td>';
+ }
+
+ txt = '<table width="'+o3_width+ '" border="0" cellpadding="'+o3_border+'" cellspacing="0" style="background-color: '+o3_bgcolor+'; background-image: url('+o3_bgbackground+'); height: '+o3_height+o3_heightunit+';"><tr><td><table width="100%" border="0" cellpadding="0" cellspacing="0"><tr><td><font style="font-family: '+o3_captionfont+'; color: '+o3_capcolor+'; font-size: '+o3_captionsize+o3_captionsizeunit+'; font-weight: '+o3_captionweight+'; font-style: '+o3_captionstyle+'; text-decoration: '+o3_captiondecoration+';">'+o3_capicon+title+'</font></td>'+closing+'</tr></table><table width="100%" border="0" cellpadding="' + o3_cellpad + '" cellspacing="0" style="color: '+o3_fgcolor+'; background-color: '+o3_fgcolor+'; height: '+o3_height+o3_heightunit+';"><tr><td valign="TOP"><font style="font-family: '+o3_textfont+'; color: '+o3_textcolor+'; font-size: '+o3_textsize+o3_textsizeunit+'; text-decoration: '+o3_textdecoration+'; font-weight: '+o3_textweight+'; font-style:'+o3_textstyle+'">'+text+'</font></td></tr></table></td></tr></table>';
+ set_background("");
+
+ return txt;
+}
+
+// Sets the background picture, padding and lots more. :)
+function ol_content_background_cssstyle(text, picture, hasfullhtml) {
+ if (hasfullhtml) {
+ txt = text;
+ } else {
+ var pU, hU, wU;
+ pU = (o3_padunit == '%' ? '%' : '');
+ hU = (o3_heightunit == '%' ? '%' : '');
+ wU = (o3_widthunit == '%' ? '%' : '');
+ txt = '<table width="'+o3_width+wu+'" border="0" cellpadding="0" cellspacing="0" height="'+o3_height+hu+'"><tr><td colspan="3" height="'+o3_padyt+pu+'"></td></tr><tr><td width="'+o3_padxl+pu+'"></td><td valign="TOP" width="'+(o3_width-o3_padxl-o3_padxr)+pu+'"><font style="font-family: '+o3_textfont+'; color: '+o3_textcolor+'; font-size: '+o3_textsize+o3_textsizeunit+';">'+text+'</font></td><td width="'+o3_padxr+pu+'"></td></tr><tr><td colspan="3" height="'+o3_padyb+pu+'"></td></tr></table>';
+ }
+
+ set_background(picture);
+
+ return txt;
+}
+
+////////
+// PLUGIN REGISTRATIONS
+////////
+registerRunTimeFunction(setCSSStyleVariables);
+registerCmdLineFunction(parseCSSStyleExtras);
+registerHook("ol_content_simple", ol_content_simple_cssstyle, FALTERNATE, CSSSTYLE);
+registerHook("ol_content_caption", ol_content_caption_cssstyle, FALTERNATE, CSSSTYLE);
+registerHook("ol_content_background", ol_content_background_cssstyle, FALTERNATE, CSSSTYLE);
--- /dev/null
+//\/////
+//\ overLIB Exclusive Plugin
+//\ This file requires overLIB 4.00 or later.
+//\
+//\ overLIB 4.00 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\ Contributors are listed on the homepage.
+//\ See http://www.bosrup.com/web/overlib/ for details.
+// $Revision$ $Date$
+//\/////
+
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+if (typeof olInfo == 'undefined' || olInfo.simpleversion < 400) alert('overLIB 4.00 or later is required for the Debug Plugin.');
+registerCommands('exclusive,exclusivestatus,exclusiveoverride');
+var olOverrideIsSet; // variable which tells if override is set
+
+
+////////
+// DEFAULT CONFIGURATION
+// Settings you want everywhere are set here. All of this can also be
+// changed on your html page or through an overLIB call.
+////////
+if (typeof ol_exclusive == 'undefined') var ol_exclusive = 0;
+if (typeof ol_exclusivestatus == 'undefined') var ol_exclusivestatus = 'Please close open popup first.';
+
+////////
+// END OF CONFIGURATION
+// Don't change anything below this line, all configuration is above.
+////////
+
+
+////////
+// INIT
+////////
+// Runtime variables init. Don't change for config!
+var o3_exclusive = 0;
+var o3_exclusivestatus = '';
+
+////////
+// PLUGIN FUNCTIONS
+////////
+
+// Set runtime variables
+function setExclusiveVariables() {
+ o3_exclusive = ol_exclusive;
+ o3_exclusivestatus = ol_exclusivestatus;
+}
+
+// Parses Exclusive Parameters
+function parseExclusiveExtras(pf,i,ar) {
+ var k = i,v;
+
+ olOverrideIsSet = false; // a global variable
+
+ if (k < ar.length) {
+ if (ar[k] == EXCLUSIVEOVERRIDE) { if(pf != 'ol_') olOverrideIsSet = true; return k; }
+ if (ar[k] == EXCLUSIVE) { eval(pf + 'exclusive = (' + pf + 'exclusive == 0) ? 1 : 0'); return k; }
+ if (ar[k] == EXCLUSIVESTATUS) { eval(pf + "exclusivestatus = '" + escSglQuote(ar[++k]) + "'"); return k; }
+ }
+
+ return -1;
+}
+
+///////
+// HELPER FUNCTIONS
+///////
+// set status message and indicate whether popup is exclusive
+function isExclusive(args) {
+ var rtnVal = false;
+
+ if(args != null) rtnVal = hasCommand(args, EXCLUSIVEOVERRIDE);
+
+ if(rtnVal) return false;
+ else {
+ self.status = (o3_exclusive) ? o3_exclusivestatus : '';
+ return o3_exclusive;
+ }
+
+}
+
+// checks overlib argument list to see if it has a COMMAND argument
+function hasCommand(args, COMMAND) {
+ var rtnFlag = false;
+
+ for (var i=0; i<args.length; i++) {
+ if (typeof args[i] == 'number' && args[i] == COMMAND) {
+ rtnFlag = true;
+ break;
+ }
+ }
+
+ return rtnFlag;
+}
+
+// makes sure exclusive setting is off
+function clearExclusive() {
+ o3_exclusive = 0;
+}
+
+function setExclusive() {
+ o3_exclusive = (o3_showingsticky && o3_exclusive);
+}
+
+function chkForExclusive() {
+ if (olOverrideIsSet) o3_exclusive = 0; // turn it off in case it's been set.
+
+ return true;
+}
+
+////////
+// PLUGIN REGISTRATIONS
+////////
+registerRunTimeFunction(setExclusiveVariables);
+registerCmdLineFunction(parseExclusiveExtras);
+registerPostParseFunction(chkForExclusive);
+registerHook("createPopup",setExclusive,FBEFORE);
+registerHook("hideObject",clearExclusive,FAFTER);
+
+
--- /dev/null
+//\/////
+//\ overLIB Follow Scroll Plugin
+//\ This file requires overLIB 4.00 or later.
+//\
+//\ overLIB 4.00 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\ Contributors are listed on the homepage.
+//\ See http://www.bosrup.com/web/overlib/ for details.
+// $Revision$ $Date$
+//\/////
+
+
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+if (typeof olInfo == 'undefined' || olInfo.simpleversion < 400) alert('overLIB 4.00 or later is required for the Follow Scroll Plugin.');
+registerCommands('followscroll,followscrollrefresh');
+
+
+////////
+// DEFAULT CONFIGURATION
+// You don't have to change anything here if you don't want to. All of this can be
+// changed on your html page or through an overLIB call.
+////////
+// Default value for scroll is not to scroll (0)
+if (typeof ol_followscroll=='undefined') var ol_followscroll=0;
+if (typeof ol_followscrollrefresh=='undefined') var ol_followscrollrefresh=100;
+
+////////
+// END OF CONFIGURATION
+// Don't change anything below this line, all configuration is above.
+////////
+
+
+
+
+
+
+
+////////
+// INIT
+////////
+// Runtime variables init. Don't change for config!
+var o3_followscroll=0;
+var o3_followscrollrefresh=100;
+
+
+////////
+// PLUGIN FUNCTIONS
+////////
+function setScrollVariables() {
+ o3_followscroll=ol_followscroll;
+ o3_followscrollrefresh=ol_followscrollrefresh;
+}
+
+// Parses Shadow and Scroll commands
+function parseScrollExtras(pf,i,ar) {
+ var k=i,v;
+ if (k < ar.length) {
+ if (ar[k]==FOLLOWSCROLL) { eval(pf +'followscroll=('+pf+'followscroll==0) ? 1 : 0'); return k; }
+ if (ar[k]==FOLLOWSCROLLREFRESH) { eval(pf+'followscrollrefresh='+ar[++k]); return k; }
+ }
+ return -1;
+}
+
+
+
+// Function to support scroll feature (overloads default)
+function scroll_placeLayer() {
+ var placeX, placeY, widthFix = 0;
+ var hasAnchor=(typeof o3_anchor != 'undefined' && o3_anchor);
+
+ // HORIZONTAL PLACEMENT
+ if (eval('o3_frame.'+docRoot) && eval("typeof o3_frame."+docRoot+".clientWidth=='number'") && eval('o3_frame.'+docRoot+'.clientWidth')) {
+ iwidth = eval('o3_frame.'+docRoot+'.clientWidth');
+ } else if (typeof(o3_frame.innerWidth) == 'number') {
+ widthFix = Math.ceil(1.2*(o3_frame.outerWidth - o3_frame.innerWidth));
+ iwidth = o3_frame.innerWidth;
+ }
+
+ if (hasAnchor) {
+ placeX = rmrkPosition[0];
+ placeY = rmrkPosition[1];
+ } else {
+ // Horizontal scroll offset
+ winoffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollLeft') : o3_frame.pageXOffset;
+ var parsedWidth = parseInt(o3_width);
+
+ if (o3_fixx > -1 || o3_relx != null) {
+ // Fixed position
+ placeX=(o3_relx != null ? ( o3_relx < 0 ? winoffset +o3_relx+ iwidth - parsedWidth - widthFix : winoffset+o3_relx) : o3_fixx);
+ } else {
+ // If HAUTO, decide what to use.
+ if (o3_hauto == 1) {
+ if ((o3_x - winoffset) > (iwidth / 2)) {
+ o3_hpos = LEFT;
+ } else {
+ o3_hpos = RIGHT;
+ }
+ }
+
+ // From mouse
+ if (o3_hpos == CENTER) { // Center
+ placeX = o3_x+o3_offsetx-(parsedWidth/2);
+
+ if (placeX < winoffset) placeX = winoffset;
+ }
+
+ if (o3_hpos == RIGHT) { // Right
+ placeX = o3_x+o3_offsetx;
+
+ if ((placeX+parsedWidth) > (winoffset+iwidth - widthFix)) {
+ placeX = iwidth+winoffset - parsedWidth - widthFix;
+ if (placeX < 0) placeX = 0;
+ }
+ }
+ if (o3_hpos == LEFT) { // Left
+ placeX = o3_x-o3_offsetx-parsedWidth;
+ if (placeX < winoffset) placeX = winoffset;
+ }
+
+ // Snapping!
+ if (o3_snapx > 1) {
+ var snapping = placeX % o3_snapx;
+
+ if (o3_hpos == LEFT) {
+ placeX = placeX - (o3_snapx+snapping);
+ } else {
+ // CENTER and RIGHT
+ placeX = placeX+(o3_snapx - snapping);
+ }
+
+ if (placeX < winoffset) placeX = winoffset;
+ }
+ }
+
+ // VERTICAL PLACEMENT
+ if (eval('o3_frame.'+docRoot) && eval("typeof o3_frame."+docRoot+".clientHeight=='number'") && eval('o3_frame.'+docRoot+'.clientHeight')) {
+ iheight = eval('o3_frame.'+docRoot+'.clientHeight');
+ } else if (typeof(o3_frame.innerHeight)=='number') {
+ iheight = o3_frame.innerHeight;
+ }
+
+ // Vertical scroll offset
+ scrolloffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollTop') : o3_frame.pageYOffset;
+ var parsedHeight=(o3_aboveheight ? parseInt(o3_aboveheight) : (olNs4 ? over.clip.height : over.offsetHeight));
+
+ if (o3_fixy > -1 || o3_rely != null) {
+ // Fixed position
+ placeY=(o3_rely != null ? (o3_rely < 0 ? scrolloffset+o3_rely+iheight - parsedHeight : scrolloffset+o3_rely) : o3_fixy);
+ } else {
+ // If VAUTO, decide what to use.
+ if (o3_vauto == 1) {
+ if ((o3_y - scrolloffset) > (iheight/2)) {
+ o3_vpos = ABOVE;
+ } else {
+ o3_vpos = BELOW;
+ }
+ }
+
+ // From mouse
+ if (o3_vpos == ABOVE) {
+ if (o3_aboveheight == 0) o3_aboveheight = parsedHeight;
+
+ placeY = o3_y - (o3_aboveheight+o3_offsety);
+ if (placeY < scrolloffset) placeY = scrolloffset;
+ } else {
+ // BELOW
+ placeY = o3_y+o3_offsety;
+ }
+
+ // Snapping!
+ if (o3_snapy > 1) {
+ var snapping = placeY % o3_snapy;
+
+ if (o3_aboveheight > 0 && o3_vpos == ABOVE) {
+ placeY = placeY - (o3_snapy+snapping);
+ } else {
+ placeY = placeY+(o3_snapy - snapping);
+ }
+
+ if (placeY < scrolloffset) placeY = scrolloffset;
+ }
+ }
+ }
+
+ // Actually move the object.
+ repositionTo(over,placeX,placeY);
+
+ if (o3_followscroll && o3_sticky && (o3_relx || o3_rely) && (typeof o3_draggable == 'undefined' || !o3_draggable)) {
+ if (typeof over.scroller=='undefined' || over.scroller.canScroll) over.scroller = new Scroller(placeX-winoffset,placeY-scrolloffset,o3_followscrollrefresh);
+ }
+}
+
+
+
+///////
+// SUPPORT ROUTINES FOR SCROLL FEATURE
+///////
+
+// Scroller constructor
+function Scroller(X,Y,refresh) {
+ this.canScroll=0;
+ this.refresh=refresh;
+ this.x=X;
+ this.y=Y;
+ this.timer=setTimeout("repositionOver()",this.refresh);
+}
+
+// Removes the timer to stop replacing the layer.
+function cancelScroll() {
+ if (!o3_followscroll || typeof over.scroller == 'undefined') return;
+ over.scroller.canScroll = 1;
+
+ if (over.scroller.timer) {
+ clearTimeout(over.scroller.timer);
+ over.scroller.timer=null;
+ }
+}
+
+// Find out how much we've scrolled.
+ function getPageScrollY() {
+ if (o3_frame.pageYOffset) return o3_frame.pageYOffset;
+ if (eval(docRoot)) return eval('o3_frame.' + docRoot + '.scrollTop');
+ return -1;
+}
+function getPageScrollX() {
+ if (o3_frame.pageXOffset) return o3_frame.pageXOffset;
+ if (eval(docRoot)) return eval('o3_frame.'+docRoot+'.scrollLeft');
+ return -1;
+}
+
+// Find out where our layer is
+function getLayerTop(layer) {
+ if (layer.pageY) return layer.pageY;
+ if (layer.style.top) return parseInt(layer.style.top);
+ return -1;
+}
+function getLayerLeft(layer) {
+ if (layer.pageX) return layer.pageX;
+ if (layer.style.left) return parseInt(layer.style.left);
+ return -1;
+}
+
+// Repositions the layer if needed
+function repositionOver() {
+ var X, Y, pgLeft, pgTop;
+ pgTop = getPageScrollY();
+ pgLeft = getPageScrollX();
+ X = getLayerLeft(over)-pgLeft;
+ Y = getLayerTop(over)-pgTop;
+
+ if (X != over.scroller.x || Y != over.scroller.y) repositionTo(over, pgLeft+over.scroller.x, pgTop+over.scroller.y);
+ over.scroller.timer = setTimeout("repositionOver()", over.scroller.refresh);
+}
+
+////////
+// PLUGIN REGISTRATIONS
+////////
+registerRunTimeFunction(setScrollVariables);
+registerCmdLineFunction(parseScrollExtras);
+registerHook("hideObject",cancelScroll,FAFTER);
+registerHook("placeLayer",scroll_placeLayer,FREPLACE);
+//end
--- /dev/null
+//\/////
+//\ overLIB Hide Form Plugin
+//\ This file requires overLIB 4.00 or later.
+//\
+//\ Uses an iframe shim to mask system controls for IE v5.5 or higher as suggested in
+//\ http://dotnetjunkies.com/weblog/jking/posts/488.aspx
+//\
+//\ overLIB 4.00 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\ Contributors are listed on the homepage.
+//\ See http://www.bosrup.com/web/overlib/ for details.
+// $Revision$ $Date$
+//\/////
+
+if (typeof olInfo == 'undefined' || olInfo.simpleversion < 400) alert('overLIB 4.00 or later is required for the HideForm Plugin.');
+
+// Function which generates the popup with an IFRAME shim
+function generatePopUp(content) {
+ if(!olIe4||olOp||!olIe55||(typeof o3_shadow != 'undefined' && o3_shadow)||(typeof o3_bubble != 'undefined' && o3_bubble)) return;
+
+ var wd,ht,txt, zIdx = 0;
+
+ wd = parseInt(o3_width);
+ ht = over.offsetHeight;
+ txt = bckDropSrc(wd,ht,zIdx++);
+ txt += '<div style="position: absolute; top: 0; left: 0; width: '+ wd+'px; z-index: ' + zIdx + ';">' + content + '</div>';
+ layerWrite(txt);
+}
+
+// Code for the IFRAME which is used in other places
+function bckDropSrc(width, height, Z) {
+ return '<iframe frameborder="0" scrolling="no" src="" width="' + width + '" height="' + height + '" style="z-index: ' + Z + '; filter: Beta(Style=0,Opacity=0);"></iframe>';
+}
+
+// Hides SELECT boxes that will be under the popup
+// Checking Gecko version number to try to include other browsers based on the Gecko engine
+function hideSelectBox() {
+ if(olNs4 || olOp || olIe55) return;
+ var px, py, pw, ph, sx, sw, sy, sh, selEl, v;
+
+ if(olIe4) v = 0;
+ else {
+ v = navigator.userAgent.match(/Gecko\/(\d{8})/i);
+ if(!v) return; // return if no string match
+ v = parseInt(v[1]);
+ }
+
+ if (v < 20030624) { // versions less than June 24, 2003 were earlier Netscape browsers
+ px = parseInt(over.style.left);
+ py = parseInt(over.style.top);
+ pw = o3_width;
+ ph = (o3_aboveheight ? parseInt(o3_aboveheight) : over.offsetHeight);
+ selEl = (olIe4) ? o3_frame.document.all.tags("SELECT") : o3_frame.document.getElementsByTagName("SELECT");
+ for (var i=0; i<selEl.length; i++) {
+ if(!olIe4 && selEl[i].size < 2) continue; // Not IE and SELECT size is 1 or not specified
+ sx = pageLocation(selEl[i],'Left');
+ sy = pageLocation(selEl[i],'Top');
+ sw = selEl[i].offsetWidth;
+ sh = selEl[i].offsetHeight;
+ if((px+pw) < sx || px > (sx+sw) || (py+ph) < sy || py > (sy+sh)) continue;
+ selEl[i].isHidden = 1;
+ selEl[i].style.visibility = 'hidden';
+ }
+ }
+}
+
+// Shows previously hidden SELECT Boxes
+function showSelectBox() {
+ if(olNs4 || olOp || olIe55) return;
+ var selEl, v;
+
+ if(olIe4) v = 0;
+ else {
+ v = navigator.userAgent.match(/Gecko\/(\d{8})/i);
+ if(!v) return;
+ v = parseInt(v[1]);
+ }
+
+ if(v < 20030624) {
+ selEl = (olIe4) ? o3_frame.document.all.tags("SELECT") : o3_frame.document.getElementsByTagName("SELECT");
+ for (var i=0; i<selEl.length; i++) {
+ if(typeof selEl[i].isHidden != 'undefined' && selEl[i].isHidden) {
+ selEl[i].isHidden = 0;
+ selEl[i].style.visibility = 'visible';
+ }
+ }
+ }
+}
+
+// function gets the total offset properties of an element
+// this same function occurs in overlib_mark.js.
+function pageLocation(o,t){
+ var x = 0
+
+ while(o.offsetParent){
+ x += o['offset'+t]
+ o = o.offsetParent
+ }
+
+ x += o['offset'+t]
+
+ return x
+}
+
+// reset mouse move routine for NS7 but not NS7.1,Opera, or IE5.5+
+// It also bypasses Netscape 6 since the modifications mess up the display of popups
+// and don't work anyways.
+// Modify mouse move routine while loading so that hideSelectBox()
+// can be called from the correct location
+if (!(olNs4 || olOp || olIe55 || navigator.userAgent.indexOf('Netscape6') != -1)) {
+ var MMStr = olMouseMove.toString();
+ var strRe = /(if\s*\(o3_allowmove\s*==\s*1.*\)\s*)/;
+ var f = MMStr.match(strRe);
+
+ if (f) {
+ var ls = MMStr.search(strRe);
+ ls += f[1].length;
+ var le = MMStr.substring(ls).search(/[;|}]\n/);
+ MMStr = MMStr.substring(0,ls) + ' { runHook("placeLayer",FREPLACE); if(olHideForm) hideSelectBox(); ' + MMStr.substring(ls + (le != -1 ? le+3 : 0));
+ document.writeln('<script type="text/javascript">\n<!--\n' + MMStr + '\n//-->\n</' + 'script>');
+ }
+
+ f = capExtent.onmousemove.toString().match(/function[ ]+(\w*)\(/);
+ if (f&&f[1] != 'annoymous') capExtent.onmousemove = olMouseMove;
+}
+
+
+////////
+// PLUGIN REGISTRATIONS
+////////
+registerHook("createPopup",generatePopUp,FAFTER);
+registerHook("hideObject",showSelectBox,FAFTER);
+olHideForm=1;
--- /dev/null
+//\/////
+//\ overLIB Shadow Plugin
+//\ This file requires overLIB 4.00 or later.
+//\
+//\ overLIB 4.00 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2003. All rights reserved.
+//\ Contributors are listed on the homepage.
+//\ See http://www.bosrup.com/web/overlib/ for details.
+// $Revision$ $Date$
+//\/////
+
+
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+if (typeof olInfo == 'undefined' || olInfo.simpleversion < 400) alert('overLIB 4.00 or later is required for the Shadow Plugin.');
+registerCommands('shadow,shadowcolor,shadowimage,shadowopacity,shadowx,shadowy');
+
+
+////////
+// DEFAULT CONFIGURATION
+// You don't have to change anything here if you don't want to. All of this can be
+// changed on your html page or through an overLIB call.
+////////
+if (typeof ol_shadowadjust=='undefined') var ol_shadowadjust=2; // for Ns4.x only
+if (typeof ol_shadow=='undefined') var ol_shadow=0;
+if (typeof ol_shadowcolor=='undefined') var ol_shadowcolor='#CCCCCC';
+if (typeof ol_shadowimage=='undefined') var ol_shadowimage='';
+if (typeof ol_shadowopacity=='undefined') var ol_shadowopacity=0;
+if (typeof ol_shadowx=='undefined') var ol_shadowx=5;
+if (typeof ol_shadowy=='undefined') var ol_shadowy=5;
+
+////////
+// END OF CONFIGURATION
+// Don't change anything below this line, all configuration is above.
+////////
+
+
+
+
+////////
+// INIT
+////////
+// Runtime variables init. Don't change for config!
+var o3_shadow=0;
+var o3_shadowcolor="#cccccc";
+var o3_shadowimage='';
+var o3_shadowopacity=0;
+var o3_shadowx=5;
+var o3_shadowy=5;
+var bkSet=0; // Needed for this effect in NS4
+
+
+
+// Function which sets runtime variables to their default values
+function setShadowVariables() {
+ o3_shadow=ol_shadow;
+ o3_shadowcolor=ol_shadowcolor;
+ o3_shadowimage=ol_shadowimage;
+ o3_shadowopacity=ol_shadowopacity;
+ o3_shadowx=ol_shadowx;
+ o3_shadowy=ol_shadowy;
+}
+
+
+// Parses shadow commands
+function parseShadowExtras(pf,i,ar) {
+ var k = i, v;
+
+ if (k < ar.length) {
+ if (ar[k]==SHADOW) { eval(pf +'shadow=('+pf+'shadow==0) ? 1 : 0'); return k; }
+ if (ar[k]==SHADOWCOLOR) { eval(pf+'shadowcolor="'+ar[++k]+'"'); return k; }
+ if (ar[k]==SHADOWOPACITY) {v=ar[++k]; eval(pf+'shadowopacity='+(olOp ? 0 : v)); return k; }
+ if (ar[k]==SHADOWIMAGE) { eval(pf+'shadowimage="'+ar[++k]+'"'); return k; }
+ if (ar[k]==SHADOWX) { eval(pf+'shadowx='+ar[++k]); return k; }
+ if (ar[k]==SHADOWY) { eval(pf+'shadowy='+ar[++k]); return k; }
+ }
+
+ return -1;
+}
+
+
+// Function for MOUSEOUT/MOUSEOFF feature with shadow
+function shadow_cursorOff() {
+ var left= parseInt(over.style.left);
+ var top=parseInt(over.style.top);
+ var right=left+(o3_shadow ? o3_width : over.offsetWidth);
+ var bottom=top+(o3_shadow ? o3_aboveheight : over.offsetHeight);
+
+ if (o3_x < left || o3_x > right || o3_y < top || o3_y > bottom) return true;
+ return false;
+}
+
+// Pre-hide processing to clean-up.
+function checkShadowPreHide() {
+ if (o3_shadow && o3_shadowopacity) cleanUpShadowEffects();
+ if (o3_shadow && (olIe4 && isMac) ) over.style.pixelWidth=over.style.pixelHeight = 0;
+}
+
+
+// Funciton that creates the actual shadow
+function generateShadow(content) {
+ var wd, ht, X = 0, Y = 0, zIdx = 0, txt, dpObj, puObj, bS= '', aPos, posStr=new Array();
+
+ if (!o3_shadow || (o3_shadowx == 0 && o3_shadowy == 0)) return;
+
+ X = Math.abs(o3_shadowx);
+ Y = Math.abs(o3_shadowy);
+ wd = parseInt(o3_width);
+ if(olHideForm&&!olNs4) ht=over.offsetHeight;
+
+ if (o3_shadowx == 0) {
+ if (o3_shadowy < 0) {
+ posStr[0]=' left:0; top: 0';
+ posStr[1]=' left:0; top: '+Y+'px';
+ } else if (o3_shadowy > 0) {
+ posStr[0]=' left:0; top: '+Y+'px';
+ posStr[1]=' left:0; top:0';
+ }
+ } else if (o3_shadowy == 0) {
+ if (o3_shadowx < 0) {
+ posStr[0]=' left:0; top: 0';
+ posStr[1]=' left: '+X+'px';
+ } else if (o3_shadowx > 0) {
+ posStr[0]=' left: '+ X+'px; top: 0';
+ posStr[1]=' left:0; top:0';
+ }
+ } else if (o3_shadowx > 0) {
+ if (o3_shadowy > 0) {
+ posStr[0]=' left:'+ X+'px; top:'+Y+'px';
+ posStr[1]=' left:0; top:0';
+ } else if (o3_shadowy < 0) {
+ posStr[0]=' left:'+X+'px; top:0';
+ posStr[1]=' left:0; top: '+Y+'px';
+ }
+ } else if (o3_shadowx < 0) {
+ if (o3_shadowy > 0) {
+ posStr[0]=' left:0; top:'+Y+'px';
+ posStr[1]=' left:'+X+'px; top:0';
+ } else if (o3_shadowy < 0) {
+ posStr[0]=' left:0; top:0';
+ posStr[1]=' left:'+X+'px; top:'+Y+'px';
+ }
+ }
+
+ txt = (olNs4) ? '<div id="backdrop"></div>' : ((olIe55&&olHideForm) ? bckDropSrc(wd+X,ht+Y,zIdx++) : '') + '<div id="backdrop" style="position: absolute;'+posStr[0]+'; width: '+wd+'px; z-index: ' + (zIdx++) + '; ';
+
+ if (o3_shadowimage) {
+ bS='background-image: url('+o3_shadowimage+');';
+ if (olNs4) bkSet=1;
+ } else {
+ bS='background-color: '+o3_shadowcolor +';';
+ if (olNs4) bkSet=2;
+ }
+
+ if (olNs4) {
+ txt += '<div id="PUContent">'+content+'</div>';
+ } else {
+ txt += bS+'"></div><div id="PUContent" style="position: absolute;'+posStr[1]+'; width: '+ wd+'px; z-index: '+(zIdx++)+';">'+content+'</div>';
+ }
+
+ layerWrite(txt);
+
+ if (olNs4 && bkSet) {
+ dpObj = over.document.layers['backdrop'];
+ if (typeof dpObj == 'undefined') return; // if shadow layer not found, then content layer won't be either
+
+ puObj = over.document.layers['PUContent'];
+ wd = puObj.clip.width;
+ ht = puObj.clip.height;
+ aPos = posStr[0].split(';');
+
+ dpObj.clip.width = wd;
+ dpObj.clip.height = ht;
+ dpObj.left = parseInt(aPos[0].split(':')[1]);
+ dpObj.top = parseInt(aPos[1].split(':')[1]);
+
+ dpObj.bgColor = (bkSet == 1) ? null : o3_shadowcolor;
+ dpObj.background.src = (bkSet==2) ? null : o3_shadowimage;
+ dpObj.zIndex = 0;
+
+ aPos = posStr[1].split(';');
+ puObj.left = parseInt(aPos[0].split(':')[1]);
+ puObj.top = parseInt(aPos[1].split(':')[1]);
+ puObj.zIndex = 1;
+
+ } else {
+ puObj = (olIe4 ? o3_frame.document.all['PUContent'] : o3_frame.document.getElementById('PUContent'));
+ dpObj = (olIe4 ? o3_frame.document.all['backdrop'] : o3_frame.document.getElementById('backdrop'));
+ ht = puObj.offsetHeight;
+ dpObj.style.height = ht + 'px';
+
+ if (o3_shadowopacity) {
+ var op = o3_shadowopacity;
+ op = (op <= 100 ? op : 100);
+
+ if (olIe4 && !isMac) {
+ dpObj.style.filter = 'Beta(Opacity='+op+')';
+ dpObj.filters.Beta.enabled = true;
+ } else {
+ if (typeof(dpObj.style.MozOpacity) == 'string') dpObj.style.MozOpacity = op / 100;
+ }
+ }
+ }
+
+ // Set popup's new width and height values here so they are available in placeLayer()
+ o3_width = wd+X;
+ o3_aboveheight = ht+Y;
+}
+
+
+////////
+// SUPPORT FUNCTIONS
+////////
+
+// Cleans up opacity settings if any.
+function cleanUpShadowEffects() {
+ if (olNs4) return;
+ else {
+ var dpObj = (olIe4 ? o3_frame.document.all['backdrop'] : o3_frame.document.getElementById('backdrop'));
+ if (olIe4 && !isMac && dpObj.filters.Beta) dpObj.filters.Beta.enabled = false;
+ else if (typeof(dpObj.style.MozOpacity) == 'string') dpObj.style.MozOpacity= 1.0;
+ }
+}
+
+// This routine is needed only for Ns4.x to allow use of popups with dropshadows and CSSCLASS at the same time on a page
+function shadowAdjust() {
+ if (!olNs4) return;
+ var fac = ol_shadowadjust;
+ if (olNs4) {
+ document.write('<style type="text/css">\n<!--\n');
+ document.write('#backdrop, #PUContent {position: absolute; left: '+fac*o3_shadowx+'px; top: '+fac*o3_shadowy+'px; }\n');
+ document.write('-->\n<' + '\/style>');
+ }
+}
+
+////////
+// PLUGIN REGISTRATIONS
+////////
+var before = (typeof rmrkPreface!='undefined' ? rmrkPreface : null);
+
+registerRunTimeFunction(setShadowVariables);
+registerCmdLineFunction(parseShadowExtras);
+registerHook("cursorOff",shadow_cursorOff,FREPLACE);
+registerHook("hideObject",checkShadowPreHide,FBEFORE);
+registerHook("createPopup",generateShadow,FAFTER,before);
+
+if (olNs4) shadowAdjust(); // write style rules for proper support of Ns4.x
+//end
--- /dev/null
+<?
+/*
++-------------------------------------------------------------------------+
+| Copyright (C) 2004 Juan Luis Francés Jiménez |
+| |
+| 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. |
++-------------------------------------------------------------------------+
+*/
+// begin Gettext initialization
+// and we check if it is present at the system
+
+if ( function_exists("gettext") ) {
+ require($smarty_gettext_path."smarty_gettext.php");
+ $smarty->register_block('t','smarty_translate');
+
+ $vars = $smarty->get_config_vars();
+ $language = $vars[lang];
+ $domain = "messages";
+ putenv("LANG=$language");
+ setlocale(LC_ALL, $language);
+ bindtextdomain($domain,"./locale");
+ textdomain($domain);
+}
+else {
+ function smarty_translate($params, $text, &$smarty) {
+ return $text;
+ }
+ $smarty->register_block('t','smarty_translate');
+}
+?>
\ No newline at end of file
--- /dev/null
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2004-06-11 13:02+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: ENCODING\n"
+
+#: lang.c:1 lang.c:2
+msgid "Bytes transferred last 30 days from ALL clients"
+msgstr ""
+
+#: lang.c:3
+msgid "GENERAL DATA"
+msgstr ""
+
+#: lang.c:4
+msgid "Total clients:"
+msgstr ""
+
+#: lang.c:5
+msgid "Total bytes stored"
+msgstr ""
+
+#: lang.c:6
+msgid "Total files:"
+msgstr ""
+
+#: lang.c:7
+msgid "Last month, bytes transferred"
+msgstr ""
+
+#: lang.c:8
+msgid "Last month, bytes transferred (pie)"
+msgstr ""
+
+#: lang.c:9
+msgid "General%20report"
+msgstr ""
+
+#: lang.c:10
+msgid "Status from last 24h"
+msgstr ""
+
+#: lang.c:11
+msgid "Errors:"
+msgstr ""
+
+#: lang.c:12
+msgid "Terminated Jobs:"
+msgstr ""
+
+#: lang.c:13
+msgid "Total time spent to do backup:"
+msgstr ""
+
+#: lang.c:14
+msgid "Bytes transferred last 24h"
+msgstr ""
+
+#: lang.c:15
+msgid "Show details"
+msgstr ""
+
+#: lang.c:16
+msgid "Jobs with errors"
+msgstr ""
+
+#: lang.c:17
+msgid "Name"
+msgstr ""
+
+#: lang.c:18
+msgid "EndTime"
+msgstr ""
+
+#: lang.c:19
+msgid "JobStatus"
+msgstr ""
+
+#: lang.c:20
+msgid "Detailed report"
+msgstr ""
+
+#: lang.c:21 lang.c:42
+msgid "Select a job:"
+msgstr ""
+
+#: lang.c:22
+msgid "go"
+msgstr ""
+
+#: lang.c:23
+msgid "Elapsed time"
+msgstr ""
+
+#: lang.c:24
+msgid "Job"
+msgstr ""
+
+#: lang.c:25
+msgid "Start Time"
+msgstr ""
+
+#: lang.c:26
+msgid "End Time"
+msgstr ""
+
+#: lang.c:27
+msgid "Type"
+msgstr ""
+
+#: lang.c:28
+msgid "Pool"
+msgstr ""
+
+#: lang.c:29 lang.c:40
+msgid "Status"
+msgstr ""
+
+#: lang.c:30
+msgid "Stats Bacula: Job"
+msgstr ""
+
+#: lang.c:31
+msgid "Client:"
+msgstr ""
+
+#: lang.c:32
+msgid "Period: From"
+msgstr ""
+
+#: lang.c:33
+msgid "to"
+msgstr ""
+
+#: lang.c:34
+msgid "Bytes transferred in the period:"
+msgstr ""
+
+#: lang.c:35
+msgid "Files transferred in the period:"
+msgstr ""
+
+#: lang.c:36
+msgid "Date"
+msgstr ""
+
+#: lang.c:37
+msgid "Elapsed"
+msgstr ""
+
+#: lang.c:38
+msgid "Level"
+msgstr ""
+
+#: lang.c:39
+msgid "Bytes"
+msgstr ""
+
+#: lang.c:41
+msgid "SELECT NEW REPORT"
+msgstr ""
+
+#: lang.c:43
+msgid "Graph mode:"
+msgstr ""
+
+#: lang.c:44
+msgid "lines"
+msgstr ""
+
+#: lang.c:45
+msgid "linepoints"
+msgstr ""
+
+#: lang.c:46
+msgid "points"
+msgstr ""
+
+#: lang.c:47
+msgid "bars"
+msgstr ""
+
+#: lang.c:48
+msgid "area"
+msgstr ""
+
+#: lang.c:49
+msgid "Data to show:"
+msgstr ""
+
+#: lang.c:50
+msgid "Transferred bytes"
+msgstr ""
+
+#: lang.c:51
+msgid "Start period:"
+msgstr ""
+
+#: lang.c:52
+msgid "End period:"
+msgstr ""
+
+#: lang.c:53
+msgid "Create report"
+msgstr ""
+
+#: lang.c:54
+msgid "Volume Name"
+msgstr ""
+
+#: lang.c:55
+msgid "Volume Bytes"
+msgstr ""
+
+#: lang.c:56
+msgid "Media Type"
+msgstr ""
+
+#: lang.c:57
+msgid "When expire?"
+msgstr ""
+
+#: lang.c:58
+msgid "Last Written"
+msgstr ""
+
+#: lang.c:59
+msgid "Volume Status"
+msgstr ""
--- /dev/null
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Bacula-web\n"
+"POT-Creation-Date: 2004-06-11 13:02+0200\n"
+"PO-Revision-Date: 2004-06-10 18:35+0100\n"
+"Last-Translator: Juan Luis Francés <bacula_listATveloxia.com>\n"
+"Language-Team: LANGUAGE <bacula_listATveloxia.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: lang.c:1 lang.c:2
+msgid "Bytes transferred last 30 days from ALL clients"
+msgstr "Bytes transferidos los últimos 30 dÃas de todos los clientes."
+
+#: lang.c:3
+msgid "GENERAL DATA"
+msgstr "DATOS GENERALES"
+
+#: lang.c:4
+msgid "Total clients:"
+msgstr "Clientes totales:"
+
+#: lang.c:5
+msgid "Total bytes stored"
+msgstr "Bytes totales guardados"
+
+#: lang.c:6
+msgid "Total files:"
+msgstr "Archivos totales:"
+
+#: lang.c:7
+msgid "Last month, bytes transferred"
+msgstr "Último mes, bytes transferidos"
+
+#: lang.c:8
+msgid "Last month, bytes transferred (pie)"
+msgstr "Último mes, bytes transferidos(queso)"
+
+#: lang.c:9
+msgid "General%20report"
+msgstr "Informe%20general"
+
+#: lang.c:10
+msgid "Status from last 24h"
+msgstr "Estado de las últimas 24h"
+
+#: lang.c:11
+msgid "Errors:"
+msgstr "Errores:"
+
+#: lang.c:12
+msgid "Terminated Jobs:"
+msgstr "Jobs terminados:"
+
+#: lang.c:13
+msgid "Total time spent to do backup:"
+msgstr "Tiempo total en hacer el backup:"
+
+#: lang.c:14
+msgid "Bytes transferred last 24h"
+msgstr "Bytes transferidos en las últimas 24h"
+
+#: lang.c:15
+msgid "Show details"
+msgstr "Mostrar detalles"
+
+#: lang.c:16
+msgid "Jobs with errors"
+msgstr "Jobs con errores"
+
+#: lang.c:17
+msgid "Name"
+msgstr "Nombre"
+
+#: lang.c:18
+msgid "EndTime"
+msgstr ""
+
+#: lang.c:19
+msgid "JobStatus"
+msgstr ""
+
+#: lang.c:20
+msgid "Detailed report"
+msgstr "Informe detallado"
+
+#: lang.c:21 lang.c:42
+msgid "Select a job:"
+msgstr "Seleccione un job:"
+
+#: lang.c:22
+msgid "go"
+msgstr "Ir"
+
+#: lang.c:23
+msgid "Elapsed time"
+msgstr ""
+
+#: lang.c:24
+msgid "Job"
+msgstr "Job"
+
+#: lang.c:25
+msgid "Start Time"
+msgstr ""
+
+#: lang.c:26
+msgid "End Time"
+msgstr ""
+
+#: lang.c:27
+msgid "Type"
+msgstr "Tipo"
+
+#: lang.c:28
+msgid "Pool"
+msgstr ""
+
+#: lang.c:29 lang.c:40
+msgid "Status"
+msgstr "Estado"
+
+#: lang.c:30
+msgid "Stats Bacula: Job"
+msgstr "Bacula estadÃsticas: Job"
+
+#: lang.c:31
+msgid "Client:"
+msgstr "Cliente:"
+
+#: lang.c:32
+msgid "Period: From"
+msgstr "PerÃodo: De"
+
+#: lang.c:33
+msgid "to"
+msgstr "a"
+
+#: lang.c:34
+msgid "Bytes transferred in the period:"
+msgstr "Bytes transferidos en el perÃodo:"
+
+#: lang.c:35
+msgid "Files transferred in the period:"
+msgstr "Archivos transferidos en el perÃodo:"
+
+#: lang.c:36
+msgid "Date"
+msgstr "Fecha"
+
+#: lang.c:37
+msgid "Elapsed"
+msgstr "Transcurrido"
+
+#: lang.c:38
+msgid "Level"
+msgstr "Nivel"
+
+#: lang.c:39
+msgid "Bytes"
+msgstr "Bytes"
+
+#: lang.c:41
+msgid "SELECT NEW REPORT"
+msgstr "SELECCIONAR NUEVO INFORME"
+
+#: lang.c:43
+msgid "Graph mode:"
+msgstr "Modo gráfico"
+
+#: lang.c:44
+msgid "lines"
+msgstr "lÃneas"
+
+#: lang.c:45
+msgid "linepoints"
+msgstr ""
+
+#: lang.c:46
+msgid "points"
+msgstr "puntos"
+
+#: lang.c:47
+msgid "bars"
+msgstr "barras"
+
+#: lang.c:48
+msgid "area"
+msgstr "área"
+
+#: lang.c:49
+msgid "Data to show:"
+msgstr "Datos a mostrar"
+
+#: lang.c:50
+msgid "Transferred bytes"
+msgstr "Bytes transferidos"
+
+#: lang.c:51
+msgid "Start period:"
+msgstr ""
+
+#: lang.c:52
+msgid "End period:"
+msgstr ""
+
+#: lang.c:53
+msgid "Create report"
+msgstr "Crear informe"
+
+#: lang.c:54
+msgid "Volume Name"
+msgstr ""
+
+#: lang.c:55
+msgid "Volume Bytes"
+msgstr ""
+
+#: lang.c:56
+msgid "Media Type"
+msgstr ""
+
+#: lang.c:57
+msgid "When expire?"
+msgstr "Cuándo expira?"
+
+#: lang.c:58
+msgid "Last Written"
+msgstr ""
+
+#: lang.c:59
+msgid "Volume Status"
+msgstr ""
--- /dev/null
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2004-06-11 13:02+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: ENCODING\n"
+
+#: lang.c:1 lang.c:2
+msgid "Bytes transferred last 30 days from ALL clients"
+msgstr "Octets transférés durant les 30 derniers jours de TOUS les clients"
+
+#: lang.c:3
+msgid "GENERAL DATA"
+msgstr "DONNEES GENERALES"
+
+#: lang.c:4
+msgid "Total clients:"
+msgstr "Nombre total de clients:"
+
+#: lang.c:5
+msgid "Total bytes stored"
+msgstr "Total des octets stockés"
+
+#: lang.c:6
+msgid "Total files:"
+msgstr " Nombre total de fichiers:"
+
+#: lang.c:7
+msgid "Last month, bytes transferred"
+msgstr "Octets transférés le mois dernier"
+
+#: lang.c:8
+msgid "Last month, bytes transferred (pie)"
+msgstr "Octets transférés le mois dernier (pie)"
+
+#: lang.c:9
+msgid "General%20report"
+msgstr "Rapport%20général"
+
+#: lang.c:10
+msgid "Status from last 24h"
+msgstr "Status des dernières 24h"
+
+#: lang.c:11
+msgid "Errors:"
+msgstr "Erreurs:"
+
+#: lang.c:12
+msgid "Terminated Jobs:"
+msgstr "Travaux terminés:"
+
+#: lang.c:13
+msgid "Total time spent to do backup:"
+msgstr "Temps total passé à faire la sauvegarde:"
+
+#: lang.c:14
+msgid "Bytes transferred last 24h"
+msgstr "Octets transférés durants les dernières 24h"
+
+#: lang.c:15
+msgid "Show details"
+msgstr "Afficher les détails"
+
+#: lang.c:16
+msgid "Jobs with errors"
+msgstr "Travaux comportant des erreurs"
+
+#: lang.c:17
+msgid "Name"
+msgstr "Nom"
+
+#: lang.c:18
+msgid "EndTime"
+msgstr "Heure de fin"
+
+#: lang.c:19
+msgid "JobStatus"
+msgstr "Etat du travail"
+
+#: lang.c:20
+msgid "Detailed report"
+msgstr "Rapport détaillé"
+
+#: lang.c:21 lang.c:42
+msgid "Select a job:"
+msgstr "Sélectionnez un job:"
+
+#: lang.c:22
+msgid "go"
+msgstr " Démarrer !"
+
+#: lang.c:23
+msgid "Elapsed time"
+msgstr "Temps écoulé"
+
+#: lang.c:24
+msgid "Job"
+msgstr ""
+
+#: lang.c:25
+msgid "Start Time"
+msgstr "Heure de début"
+
+#: lang.c:26
+msgid "End Time"
+msgstr "Heure de fin"
+
+#: lang.c:27
+msgid "Type"
+msgstr ""
+
+#: lang.c:28
+msgid "Pool"
+msgstr ""
+
+#: lang.c:29 lang.c:40
+msgid "Status"
+msgstr "Etat"
+
+#: lang.c:30
+msgid "Stats Bacula: Job"
+msgstr "Statistiques Bacula: Job"
+
+#: lang.c:31
+msgid "Client:"
+msgstr ""
+
+#: lang.c:32
+msgid "Period: From"
+msgstr "Période: Du"
+
+#: lang.c:33
+msgid "to"
+msgstr "au"
+
+#: lang.c:34
+msgid "Bytes transferred in the period:"
+msgstr "Octets transférés durant la période:"
+
+#: lang.c:35
+msgid "Files transferred in the period:"
+msgstr "Fichiers transférés durant la période:"
+
+#: lang.c:36
+msgid "Date"
+msgstr ""
+
+#: lang.c:37
+msgid "Elapsed"
+msgstr "Ecoulés"
+
+#: lang.c:38
+msgid "Level"
+msgstr "Niveau"
+
+#: lang.c:39
+msgid "Bytes"
+msgstr "Octets"
+
+#: lang.c:41
+msgid "SELECT NEW REPORT"
+msgstr "SELECTIONNER UN NOUVEAU RAPPORT"
+
+#: lang.c:43
+msgid "Graph mode:"
+msgstr "Mode Graphique:"
+
+#: lang.c:44
+msgid "lines"
+msgstr "lignes"
+
+#: lang.c:45
+msgid "linepoints"
+msgstr "lignes de points"
+
+#: lang.c:46
+msgid "points"
+msgstr ""
+
+#: lang.c:47
+msgid "bars"
+msgstr "histogrammes"
+
+#: lang.c:48
+msgid "area"
+msgstr "aire"
+
+#: lang.c:49
+msgid "Data to show"
+msgstr "Données à afficher:"
+
+#: lang.c:50
+msgid "Transferred bytes"
+msgstr "Octets transférés"
+
+#: lang.c:51
+msgid "Start period:"
+msgstr "Période de début:"
+
+#: lang.c:52
+msgid "End period:"
+msgstr "Période de fin:"
+
+#: lang.c:53
+msgid "Create report"
+msgstr "Créer un rapport"
+
+#: lang.c:54
+msgid "Volume Name"
+msgstr "Nom du Volume"
+
+#: lang.c:55
+msgid "Volume Bytes"
+msgstr "Taille du volume (octets)"
+
+#: lang.c:56
+msgid "Media Type"
+msgstr "Type de média"
+
+#: lang.c:57
+msgid "When expire?"
+msgstr "Date d'expiration:"
+
+#: lang.c:58
+msgid "Last Written"
+msgstr "Dernier enregistrement"
+
+#: lang.c:59
+msgid "Volume Status"
+msgstr "Etat du volume"
--- /dev/null
+# translation of messages_it.po to italiano
+# translation of messages.po to italiano
+# Copyright (C) 2004 Free Software Foundation, Inc.
+# Gian Domenico <gianni.messina@c-ict.it>, 2004
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: messages_it\n"
+"POT-Creation-Date: 2004-06-11 13:02+0200\n"
+"PO-Revision-Date: 2004-06-17 15:05+0200\n"
+"Last-Translator: Gian Domenico <gianni.messina@c-ict.it>\n"
+"Language-Team: italiano <it@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.0\n"
+
+#: lang.c:1 lang.c:2
+msgid "Bytes transferred last 30 days from ALL clients"
+msgstr "Bytes trasferiti da TUTTI i clients negli ultimi 30 giorni"
+
+#: lang.c:3
+msgid "GENERAL DATA"
+msgstr "Dati Generali"
+
+#: lang.c:4
+msgid "Total clients:"
+msgstr "Totale clients:"
+
+#: lang.c:5
+msgid "Total bytes stored"
+msgstr "Bytes totali memorizzati"
+
+#: lang.c:6
+msgid "Total files:"
+msgstr "Totale dei files:"
+
+#: lang.c:7
+msgid "Last month, bytes transferred"
+msgstr "Ultimo mese, bytes trasferiti"
+
+#: lang.c:8
+msgid "Last month, bytes transferred (pie)"
+msgstr "Ultimo mese, bytes trasferiti (torta)"
+
+#: lang.c:9
+msgid "General%20report"
+msgstr "Report%20generale"
+
+#: lang.c:10
+msgid "Status from last 24h"
+msgstr "Stato nelle ultime 24ore"
+
+#: lang.c:11
+msgid "Errors:"
+msgstr "Errori:"
+
+#: lang.c:12
+msgid "Terminated Jobs:"
+msgstr "Jobs Terminati:"
+
+#: lang.c:13
+msgid "Total time spent to do backup:"
+msgstr "Totale tempo impiegato per il backup:"
+
+#: lang.c:14
+msgid "Bytes transferred last 24h"
+msgstr "Bytes trasferiti ultime 24ore"
+
+#: lang.c:15
+msgid "Show details"
+msgstr "Mostra dettagli"
+
+#: lang.c:16
+msgid "Jobs with errors"
+msgstr "Jobs con errori"
+
+#: lang.c:17
+msgid "Name"
+msgstr "Nome"
+
+#: lang.c:18
+msgid "EndTime"
+msgstr "Termine"
+
+#: lang.c:19
+msgid "JobStatus"
+msgstr "Stato del Job"
+
+#: lang.c:20
+msgid "Detailed report"
+msgstr "Report dettagliato"
+
+#: lang.c:21 lang.c:42
+msgid "Select a job:"
+msgstr "Seleziona un job:"
+
+#: lang.c:22
+msgid "go"
+msgstr "vai"
+
+#: lang.c:23
+msgid "Elapsed time"
+msgstr "Tempo trascorso"
+
+#: lang.c:24
+msgid "Job"
+msgstr "Job"
+
+#: lang.c:25
+msgid "Start Time"
+msgstr "Inizio"
+
+#: lang.c:26
+msgid "End Time"
+msgstr "Termine"
+
+#: lang.c:27
+msgid "Type"
+msgstr "Tipo"
+
+#: lang.c:28
+msgid "Pool"
+msgstr "Pool"
+
+#: lang.c:29 lang.c:40
+msgid "Status"
+msgstr "Stato"
+
+#: lang.c:30
+msgid "Stats Bacula: Job"
+msgstr "Statistiche Bacula: Job"
+
+#: lang.c:31
+msgid "Client:"
+msgstr "Client:"
+
+#: lang.c:32
+msgid "Period: From"
+msgstr "Periodo: da"
+
+#: lang.c:33
+msgid "to"
+msgstr "a"
+
+#: lang.c:34
+msgid "Bytes transferred in the period:"
+msgstr "Bytes trasferiti nel periodo:"
+
+#: lang.c:35
+msgid "Files transferred in the period:"
+msgstr "Files trasferiti nel periodo:"
+
+#: lang.c:36
+msgid "Date"
+msgstr "Data"
+
+#: lang.c:37
+msgid "Elapsed"
+msgstr "Trascorso"
+
+#: lang.c:38
+msgid "Level"
+msgstr "Livello"
+
+#: lang.c:39
+msgid "Bytes"
+msgstr "Bytes"
+
+#: lang.c:41
+msgid "SELECT NEW REPORT"
+msgstr "SELEZIONA NUOVO REPORT"
+
+#: lang.c:43
+msgid "Graph mode:"
+msgstr "Modalità del Grafico:"
+
+#: lang.c:44
+msgid "lines"
+msgstr "linee"
+
+#: lang.c:45
+msgid "linepoints"
+msgstr "linepoints"
+
+#: lang.c:46
+msgid "points"
+msgstr "punti"
+
+#: lang.c:47
+msgid "bars"
+msgstr "barre"
+
+#: lang.c:48
+msgid "area"
+msgstr "area"
+
+#: lang.c:49
+msgid "Data to show:"
+msgstr "Data da mostrare:"
+
+#: lang.c:50
+msgid "Transferred bytes"
+msgstr "Bytes trasferiti"
+
+#: lang.c:51
+msgid "Start period:"
+msgstr "Inizio Periodo:"
+
+#: lang.c:52
+msgid "End period:"
+msgstr "Fine periodo:"
+
+#: lang.c:53
+msgid "Create report"
+msgstr "Crea report"
+
+#: lang.c:54
+msgid "Volume Name"
+msgstr "Nome del Volume"
+
+#: lang.c:55
+msgid "Volume Bytes"
+msgstr "Bytes nel Volume"
+
+#: lang.c:56
+msgid "Media Type"
+msgstr "Media Type"
+
+#: lang.c:57
+msgid "When expire?"
+msgstr "Quando scade?"
+
+#: lang.c:58
+msgid "Last Written"
+msgstr "Ultimo Salvataggio"
+
+#: lang.c:59
+msgid "Volume Status"
+msgstr "Stato del Volume"
+
--- /dev/null
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2004-06-11 13:02+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: ENCODING\n"
+
+#: lang.c:1 lang.c:2
+msgid "Bytes transferred last 30 days from ALL clients"
+msgstr ""
+
+#: lang.c:3
+msgid "GENERAL DATA"
+msgstr ""
+
+#: lang.c:4
+msgid "Total clients:"
+msgstr ""
+
+#: lang.c:5
+msgid "Total bytes stored"
+msgstr ""
+
+#: lang.c:6
+msgid "Total files:"
+msgstr ""
+
+#: lang.c:7
+msgid "Last month, bytes transferred"
+msgstr ""
+
+#: lang.c:8
+msgid "Last month, bytes transferred (pie)"
+msgstr ""
+
+#: lang.c:9
+msgid "General%20report"
+msgstr ""
+
+#: lang.c:10
+msgid "Status from last 24h"
+msgstr ""
+
+#: lang.c:11
+msgid "Errors:"
+msgstr ""
+
+#: lang.c:12
+msgid "Terminated Jobs:"
+msgstr ""
+
+#: lang.c:13
+msgid "Total time spent to do backup:"
+msgstr ""
+
+#: lang.c:14
+msgid "Bytes transferred last 24h"
+msgstr ""
+
+#: lang.c:15
+msgid "Show details"
+msgstr ""
+
+#: lang.c:16
+msgid "Jobs with errors"
+msgstr ""
+
+#: lang.c:17
+msgid "Name"
+msgstr ""
+
+#: lang.c:18
+msgid "EndTime"
+msgstr ""
+
+#: lang.c:19
+msgid "JobStatus"
+msgstr ""
+
+#: lang.c:20
+msgid "Detailed report"
+msgstr ""
+
+#: lang.c:21 lang.c:42
+msgid "Select a job:"
+msgstr ""
+
+#: lang.c:22
+msgid "go"
+msgstr ""
+
+#: lang.c:23
+msgid "Elapsed time"
+msgstr ""
+
+#: lang.c:24
+msgid "Job"
+msgstr ""
+
+#: lang.c:25
+msgid "Start Time"
+msgstr ""
+
+#: lang.c:26
+msgid "End Time"
+msgstr ""
+
+#: lang.c:27
+msgid "Type"
+msgstr ""
+
+#: lang.c:28
+msgid "Pool"
+msgstr ""
+
+#: lang.c:29 lang.c:40
+msgid "Status"
+msgstr ""
+
+#: lang.c:30
+msgid "Stats Bacula: Job"
+msgstr ""
+
+#: lang.c:31
+msgid "Client:"
+msgstr ""
+
+#: lang.c:32
+msgid "Period: From"
+msgstr ""
+
+#: lang.c:33
+msgid "to"
+msgstr ""
+
+#: lang.c:34
+msgid "Bytes transferred in the period:"
+msgstr ""
+
+#: lang.c:35
+msgid "Files transferred in the period:"
+msgstr ""
+
+#: lang.c:36
+msgid "Date"
+msgstr ""
+
+#: lang.c:37
+msgid "Elapsed"
+msgstr ""
+
+#: lang.c:38
+msgid "Level"
+msgstr ""
+
+#: lang.c:39
+msgid "Bytes"
+msgstr ""
+
+#: lang.c:41
+msgid "SELECT NEW REPORT"
+msgstr ""
+
+#: lang.c:43
+msgid "Graph mode:"
+msgstr ""
+
+#: lang.c:44
+msgid "lines"
+msgstr ""
+
+#: lang.c:45
+msgid "linepoints"
+msgstr ""
+
+#: lang.c:46
+msgid "points"
+msgstr ""
+
+#: lang.c:47
+msgid "bars"
+msgstr ""
+
+#: lang.c:48
+msgid "area"
+msgstr ""
+
+#: lang.c:49
+msgid "Data to show:"
+msgstr ""
+
+#: lang.c:50
+msgid "Transferred bytes"
+msgstr ""
+
+#: lang.c:51
+msgid "Start period:"
+msgstr ""
+
+#: lang.c:52
+msgid "End period:"
+msgstr ""
+
+#: lang.c:53
+msgid "Create report"
+msgstr ""
+
+#: lang.c:54
+msgid "Volume Name"
+msgstr ""
+
+#: lang.c:55
+msgid "Volume Bytes"
+msgstr ""
+
+#: lang.c:56
+msgid "Media Type"
+msgstr ""
+
+#: lang.c:57
+msgid "When expire?"
+msgstr ""
+
+#: lang.c:58
+msgid "Last Written"
+msgstr ""
+
+#: lang.c:59
+msgid "Volume Status"
+msgstr ""
--- /dev/null
+<?
+// LOCATION OF EXTERNAL PACKAGES
+// -----------------------------
+
+// PhPlot package. version 5.0RC1. http://www.phplot.com
+$phplot_path = "external_packages/phplot/";
+
+//Smarty package. version 2.6.6. http://smarty.php.net
+$smarty_path = "external_packages/smarty/";
+
+//Smarty_gettext. version 0.9. http://www.boom.org.il/smarty/gettext/
+$smarty_gettext_path = "external_packages/smarty_gettext-0.9/";
+
+?>
\ No newline at end of file
--- /dev/null
+<?
+/*
++-------------------------------------------------------------------------+
+| Copyright (C) 2004 Juan Luis Francés Jiménez |
+| |
+| 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. |
++-------------------------------------------------------------------------+
+*/
+
+require ("paths.php");
+require($smarty_path."Smarty.class.php");
+include "classes.inc";
+
+$smarty = new Smarty;
+
+//$smarty->compile_check = true;
+//$smarty->debugging = true;
+
+$smarty->template_dir = "./templates";
+$smarty->compile_dir = "./templates_c";
+$smarty->config_dir = "./configs";
+$smarty->config_load("bacula.conf");
+require("lang.php");
+
+$dbSql = new Bweb();
+
+if ( $_GET['default'] == 1) { // Default params, 1 month
+ $dbSql->StartDate = strftime("%Y-%m-%d %H:%M:%S",time()-2678400);
+ $dbSql->EndDate = strftime("%Y-%m-%d %H:%M:%S",time());
+}
+else // With params
+ $dbSql->PrepareDate($_GET['StartDateMonth'],$_GET['StartDateDay'],$_GET['StartDateYear'],$_GET['EndDateMonth'],$_GET['EndDateDay'],$_GET['EndDateYear']);
+
+$bytes = $dbSql->CalculateBytesPeriod($_GET['server'],$dbSql->StartDate,$dbSql->EndDate);
+$files = $dbSql->CalculateFilesPeriod($_GET['server'],$dbSql->StartDate,$dbSql->EndDate);
+$smarty->assign('startperiod',$dbSql->StartDate);
+$smarty->assign('endperiod',$dbSql->EndDate);
+$smarty->assign('bytesperiod',$bytes);
+$smarty->assign('filesperiod',$files);
+
+// Array with jobs data
+$a_jobs = array();
+$res_jobs = $dbSql->link->query("select *,SEC_TO_TIME( UNIX_TIMESTAMP(Job.EndTime)-UNIX_TIMESTAMP(Job.StartTime) ) as elapsed from Job where EndTime < '$dbSql->EndDate' and EndTime > '$dbSql->StartDate' and Name='$_GET[server]' order by EndTime")
+ or die("Error query row 50");
+
+while ( $tmp = $res_jobs->fetchRow(DB_FETCHMODE_ASSOC) ) {
+ $tdate = explode (":",$tmp[elapsed]); // Temporal "workaround" ;) Fix later
+ if ( $tdate[0] > 300000 )
+ $tmp[elapsed] = "00:00:00";
+ array_push($a_jobs,$tmp);
+}
+$smarty->assign('jobs',$a_jobs);
+
+// report_select.tpl
+$res = $dbSql->link->query("select Name from Job group by Name");
+$a_jobs = array();
+while ( $tmp = $res->fetchRow() )
+ array_push($a_jobs, $tmp[0]);
+$smarty->assign('total_name_jobs',$a_jobs);
+$res->free();
+$smarty->assign('time2',( (time())-2678400) ); // Current time - 1 month. <select> date
+
+
+
+$smarty->display('report.tpl');
+?>
+
--- /dev/null
+<?
+/*
++-------------------------------------------------------------------------+
+| Copyright (C) 2004 Juan Luis Francés Jiménez |
+| |
+| 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. |
++-------------------------------------------------------------------------+
+*/
+
+// Create a graph, showing a img. SP: Genera el gráfico.
+// $server= Client of backup. SP: Servidor de Backup
+// $tipo_dato= Type of data SP: Datos a mostar
+// $title= Title of graph. SP: Titulo de la gráfica
+// $xlabel= Leyend X axis. SP: Leyenda eje X
+// $ylabel= Leyend Y axis. SP: Leyenda eje Y
+// $sizex
+// $sizey
+// $MBottom = Margin of the bottom of the graph
+// $modo_graph= Type of graph (bars, lines, linepoints, area, points, and pie).
+// $elapsed = Period in seconds to show complex graph (tipo_dato <3) 1 month = 18144000
+
+require ("classes.inc");
+
+$graph = new BCreateGraph();
+
+
+if ( isset($_GET['sizey']) && isset($_GET['sizex']) ) {
+ $graph->sizey = $_GET['sizey'];
+ $graph->sizex = $_GET['sizex'];
+}
+
+if ( isset($_GET['MBottom']) ) {
+ $graph->MarginBottom = $_GET['MBottom'];
+}
+
+if ( isset($_GET['EndDateYear']) )
+ $graph->PrepareDate($_GET['StartDateMonth'],$_GET['StartDateDay'],$_GET['StartDateYear'],$_GET['EndDateMonth'],$_GET['EndDateDay'],$_GET['EndDateYear']);
+
+if ( isset($_GET['legend']) )
+ $graph->Leg = $_GET['legend'];
+
+if ( isset($_GET['elapsed']) )
+ $graph->elapsed = $_GET['elapsed'];
+
+if (!isset($_GET['modo_graph']) )
+ $graph->BCreate ($_GET['server'],$_GET['tipo_dato'],$_GET['title']);
+else if (!isset($_GET['xlabel']))
+ $graph->BCreate ($_GET['server'],$_GET['tipo_dato'],$_GET['title'],$_GET['modo_graph']);
+else if (!isset($_GET['ylabel']))
+ $graph->BCreate ($_GET['server'],$_GET['tipo_dato'],$_GET['title'],$_GET['modo_graph'],$_GET['xlabel']);
+else
+ $graph->BCreate ($_GET['server'],$_GET['tipo_dato'],$_GET['title'],$_GET['modo_graph'],$_GET['xlabel'],$_GET['ylabel']);
+
+
+?>
--- /dev/null
+<style>
+{literal}
+a:link { color: #0000c0 }
+a:visited { color: #0000c0 }
+a:hover { color: #6040ff }
+img {border: 0}
+td,input,select { font-family: Verdana,Arial; font-size: 7.5pt; color: #000000 }
+.back { background-color: #E6E6F5; } {* Background color for main table *}
+.tbl_header { background-color: #47A9E5; }
+.genmed { font-size : 11px; }
+.tbl_medium { border-bottom: black solid 1px;
+ border-left: black solid 1px;
+ border-right: black solid 1px;
+ border-top: black solid 1px;
+ background-color: #FDFFBF;
+ }
+.tbl_pool_inter_1 { background-color: #D4D4D9; border-style: solid; border-left-width: 1px; border-top-width: 1px; border-right-width: 0px;}
+.tbl_pool_inter_2 { background-color: #D4D4D9; border-style: solid; border-left-width: 0px; border-top-width: 1px; border-right-width: 0px;}
+.tbl_pool_inter_3 { background-color: #D4D4D9; border-style: solid; border-left-width: 0px; border-top-width: 1px; border-right-width: 1px}
+.titulo {
+ font-size : 20px;
+ background-color: #FDFFBF; border: #D1D7DC; border-style: solid;
+ border-left-width: 1px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px
+}
+.tbl_header1 {
+ font-size : 14px;
+ background-color: #FDFFBF; border: #D1D7DC; border-style: solid;
+ border-left-width: 1px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px
+}
+.tbl_header2 {
+ font-size: 14px;
+ background-color: #FDFFBF;
+}
+.titulo2 { font-size : 13px; font-weight: bold; }
+.table1 { background-color: #D1D7DC; }
+.table2 { background-color: #A7D7D1; }
+.table3 { background-color: #D1D7DC; }
+.table4 { background-color: #A7D7D1; }
+.code {
+ font-family: Courier, 'Courier New', sans-serif; font-size: 11px; color: #10738F;
+ background-color: #FAFAFA; border: #D1D7DC; border-style: solid;
+ border-left-width: 1px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px
+}
+.notas { font-size : 13px; color: red;}
+.header { font-size : 18px; }
+.size_small { font-size: 9px; }
+{/literal}
+</style>
\ No newline at end of file
--- /dev/null
+</BODY>
+</HTML>
--- /dev/null
+{config_load file=bacula.conf}
+<html>
+<head>
+{include file=css.tpl}
+<title>Popup</title></head>
+<body bgcolor="#FBF7CE" topmargin=0 bottommargin=0 leftmargin=0 rightmargin=0 marginwidth=0 marginheight=0>
+{if $smarty.get.Full_popup == "yes"}
+ {include file=last_run_report.tpl}
+{elseif $smarty.get.pop_graph1 == "yes"}
+ <img src="stats.php?tipo_dato=69&title={t}Bytes transferred last 30 days from ALL clients{/t}&modo_graph=lines&sizex=600&sizey=400&MBottom=80&legend=1&elapsed=2592000">
+{elseif $smarty.get.pop_graph2 == "yes"}
+ <img src="stats.php?tipo_dato=69&title={t}Bytes transferred last 30 days from ALL clients{/t}&modo_graph=pie&sizex=600&sizey=400&MBottom=80&legend=1&elapsed=2592000">
+{/if}
+{include file=footer.tpl}
\ No newline at end of file
--- /dev/null
+<table class=genmed cellspacing="0" cellpadding="0" border=1 align="center" width=90%>
+<tr><td align=center class=tbl_medium background="images/bg3.png">
+{t}GENERAL DATA{/t}
+</td></tr>
+<tr><td class=code>
+
+<table class=genmed width="90%" cellspacing="1" cellpadding="3" border="0" align="center" border=0>
+<tr>
+ <td width=35%>
+ {t}Total clients:{/t}
+ </td>
+
+ <td>
+ <font color=red>{$clientes_totales}</font>
+ </td>
+
+ <td width=35%>
+ {t}Total bytes stored{/t}:
+ </td>
+
+ <td>
+ <font color=red>{$bytes_stored|fsize_format}</font>
+ </td>
+</tr>
+
+<tr>
+ <td width=35%>
+ {t}Total files:{/t}
+ </td>
+
+ <td>
+ <font color=red>{$files_totales}</font>
+ </td>
+</tr>
+
+<tr>
+ <td colspan=2 align=center>
+ <a href="javascript:OpenWin('index.php?pop_graph1=yes','600','400')">{t}Last month, bytes transferred{/t}</a>
+ </td>
+ <td colspan=2 align=center>
+ <a href="javascript:OpenWin('index.php?pop.graph2=yes','600','400')">{t}Last month, bytes transferred (pie){/t}</a>
+ </td>
+</tr>
+</table>
+
+</td></tr>
+</table>
--- /dev/null
+<HTML>
+<HEAD>
+{popup_init src="js/overlib.js"}
+{literal}
+<script language="Javascript">
+ function OpenWin(URL,wid,hei) {
+ window.open(URL,"window1","width="+wid+",height="+hei+",scrollbars=yes,menubar=no,location=no,resizable=no")
+ }
+</script>
+{/literal}
+<TITLE>{#title#}</TITLE>
+</HEAD>
+<BODY bgcolor="#ffffff">
+<table width=1000px cellpadding=0 cellspacing=0 border=0 bgcolor="#2F92AF">
+ <tr>
+ <td class=titulo2 background="images/bg2.png">
+ {#title#}
+ </td>
+ <td background="images/bg2.png" align=right>
+ <a href="http://indpnday.com/bacula_stuff/bacula-web/mantisbt/login_page.php" target="_blank" {popup text="They grow thanks to Juan Luis Francés...Please, click here to report them"}>
+ Bugs?
+ </a>
+ </td>
+ <td background="images/end2.png>
+ <img src="images/empty.png">
+ </td>
+ </tr>
+</table>
\ No newline at end of file
--- /dev/null
+{* BACULA main page*}
+
+{config_load file=bacula.conf}
+
+{include file=css.tpl}
+
+{include file=header.tpl}
+
+<table width=1000px border=0 cellspacing=5 class=back>
+ <tr><td valign=top width=60%> {include file=generaldata.tpl} <br> {include file=volumes.tpl}</td>
+ <td valign=top width=40% bgcolor=#DDDFF9 style="border-style: solid; border-color: grey">
+ {if !#IndexReport#}
+ {include file=last_run_report.tpl}
+ {else}
+ {include file=report_select.tpl}
+ {/if}
+ <table class=genmed cellspacing="1" cellpadding="3" border=0 align="center">
+ <tr><td>
+ {if $server==""}
+ <img src=stats.php?server={$server}&tipo_dato=69&title={t}General%20report{/t}&modo_graph=bars&sizex=400&sizey=250&MBottom=20&legend=1>
+ {else}
+ <img src=stats.php?server={$server}&tipo_dato=3&title={$server}&modo_graph=bars>
+ {/if}
+ </td></tr>
+ </table>
+ </td>
+ </tr>
+
+</table>
+
+
+{include file="footer.tpl"}
\ No newline at end of file
--- /dev/null
+<table width=90% align=center {if !$status }background="images/backlast.gif"{else}background="images/backlastred.gif" {/if} style="background-repeat:no-repeat" height=178px border=0 cellspacing=0 cellpadding=0>
+ <tr>
+ <td colspan=2 align=center style="font-size: 12px; font-weight: bold; background-repeat: repeat" background="images/bg6.png" height=25>
+ {t}Status from last 24h{/t}
+ </td>
+ </tr>
+{if #mode# == "Lite" && $smarty.get.Full_popup != "yes"}
+ <tr>
+ <td>
+ <b>{t}Errors:{/t}</b>
+ </td>
+ <td style="font-size: 13px; color: blue">
+ {$status}
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <b>{t}Terminated Jobs:{/t}</b>
+ </td>
+ <td style="font-size: 13px; color: blue">
+ {$total_jobs}
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <b>{t}Total time spent to do backup:{/t}</b>
+ </td>
+ <td style="font-size: 13px; color: blue">
+ {$TotalElapsed}
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <b>{t}Bytes transferred last 24h{/t}</b>
+ </td>
+ <td style="font-size: 13px; color: blue">
+ {$bytes_totales|fsize_format}
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2 align=center>
+ <a href="javascript:OpenWin('index.php?Full_popup=yes','490','350')">{t}Show details{/t}</a>
+ </td>
+ </tr>
+
+ {if $status != 0}
+ <tr>
+ <td colspan=2>
+ <table border=0 cellpadding=0 cellspacing=0>
+ <tr>
+ <td align=right colspan=4 height=25 background="images/bg7.gif" style="font-size: 12px">
+ <b>{t}Jobs with errors{/t}</b>
+ </td>
+ </tr>
+ <tr>
+ <td background="images/bg6.png"><b>JobId </b></td>
+ <td background="images/bg6.png"><b>{t}Name{/t}</b></td>
+ <td background="images/bg6.png"><b>{t}EndTime{/t}</b></td>
+ <td background="images/bg6.png"><b>{t}JobStatus{/t}</b></td>
+ </tr>
+ {section name=row loop=$errors_array}
+ <tr {* bgcolor=#{cycle values="E6E6F5,E1E5E0"} *}>
+ {section name=tmp loop=$errors_array[row]}
+ <td {if $smarty.section.tmp.iteration == 4}align=center
+ {if $errors_array[row][tmp] == "C"}
+ {assign var=pop value="Created but not yet running"}
+ {elseif $errors_array[row][tmp] == "R"}
+ {assign var=pop value="Running"}
+ {elseif $errors_array[row][tmp] == "B"}
+ {assign var=pop value="Blocked"}
+ {elseif $errors_array[row][tmp] == "E"}
+ {assign var=pop value="Terminated in Error"}
+ {elseif $errors_array[row][tmp] == "e"}
+ {assign var=pop value="Non-fatal error"}
+ {elseif $errors_array[row][tmp] == "f"}
+ {assign var=pop value="Fatal error"}
+ {elseif $errors_array[row][tmp] == "D"}
+ {assign var=pop value="Verify Differences"}
+ {elseif $errors_array[row][tmp] == "A"}
+ {assign var=pop value="Canceled by the user"}
+ {elseif $errors_array[row][tmp] == "F"}
+ {assign var=pop value="Waiting on the File daemon"}
+ {elseif $errors_array[row][tmp] == "S"}
+ {assign var=pop value="Waiting on the Storage daemon"}
+ {elseif $errors_array[row][tmp] == "m"}
+ {assign var=pop value="Waiting for a new Volume to be mounted"}
+ {elseif $errors_array[row][tmp] == "M"}
+ {assign var=pop value="Waiting for a Mount"}
+ {elseif $errors_array[row][tmp] == "s"}
+ {assign var=pop value="Waiting for Storage resource"}
+ {elseif $errors_array[row][tmp] == "j"}
+ {assign var=pop value="Waiting for Job resource"}
+ {elseif $errors_array[row][tmp] == "c"}
+ {assign var=pop value="Waiting for Client resource"}
+ {elseif $errors_array[row][tmp] == "d"}
+ {assign var=pop value="Wating for Maximum jobs"}
+ {elseif $errors_array[row][tmp] == "t"}
+ {assign var=pop value="Waiting for Start Time"}
+ {elseif $errors_array[row][tmp] == "p"}
+ {assign var=pop value="Waiting for higher priority job to finish"}
+ {/if}
+ {popup caption="Status detail" autostatus=yes fgcolor=red textcolor=yellow text="$pop"}
+ {/if}
+ >
+ {if $smarty.section.tmp.iteration == 2}
+ <a href=report.php?default=1&server={$errors_array[row][tmp]} target="_blank">
+ {/if}
+ {$errors_array[row][tmp]}
+ {if $smarty.section.row.iteration == 2}
+ </a>
+ {/if}
+ </td>
+ {/section}
+ </tr>
+ {/section}
+ </table>
+ </td>
+ </tr>
+ {/if}
+
+ <tr>
+ <td align=right colspan=2 valign=bottom>
+ <table widh=100% cellpadding=0 cellspacing=3 border=0>
+ <tr bgcolor=white>
+ <td align=right colspan=3 background="images/bg1.png" style="font-size: 12px; font-weight: bold;">
+ <i>{t}Detailed report{/t}</i>
+ </td>
+ </tr>
+
+ <tr>
+ <td align=left>
+ {t}Select a job:{/t}
+ </td>
+ <form method=get action="report.php" target="_blank">
+ <input type=hidden name="default" value="1">
+ <td align=right>
+ <select name=server>
+ {if $smarty.get.server!=""}
+ {html_options values=$smarty.get.server output=$smarty.get.server}
+ {else}
+ {html_options values=$total_name_jobs output=$total_name_jobs}
+ {/if}
+ </select>
+ </td>
+ <td>
+ <input type=submit value="{t}go{/t}">
+ </td>
+ </form>
+ </tr>
+ </table>
+ </td>
+ </tr>
+{else if #mode# == "Full" || $smarty.get.Full_popup == "yes"}
+ <tr>
+ <td>
+ <table width=100% class="genmed" cellpadding=2 cellspacing=0>
+ <tr class="tbl_header1">
+ <td><b>{t}Elapsed time{/t}</b></td>
+ <td><b>{t}Client{/t}</b></td>
+ <td><b>{t}Start Time{/t}</b></td>
+ <td><b>{t}End Time{/t}</b></td>
+ <td><b>{t}Type{/t}</b></td>
+ <td><b>{t}Pool{/t}</b></td>
+ <td><b>{t}Status{/t}</b></td>
+ </tr>
+ {section name=job loop=$clients}
+ <tr class={cycle values="table3,table4"}>
+ {section name=row loop=$clients[job]}
+ <td align=left class="size_small">
+ {if $smarty.section.row.iteration == 2}
+ <a href=report.php?default=1&server={$clients[job][row]|escape:"url"} target="_blank">
+ {/if}
+ {if $smarty.section.row.last == TRUE}
+ {if $clients[job][row] eq "T"}
+ <img src={#root#}/images/s_ok.gif>
+ {else}
+ <img src={#root#}/images/s_error.gif>
+ {/if}
+ {else}
+ {$clients[job][row]}
+ {/if}
+ {if $smarty.section.row.iteration == 2}
+ </a>
+ {/if}
+ </td>
+ {/section}
+ </tr>
+ {/section}
+ </table>
+ </td>
+ </tr>
+{/if}
+</table>
\ No newline at end of file
--- /dev/null
+{* Página principal BACULA *}
+{config_load file=bacula.conf}
+{popup_init src="js/overlib.js"}
+<html>
+<head>
+
+<title>{t}Stats Bacula: Job{/t} {$smarty.get.server}</title></head>
+<body>
+
+{include file=css.tpl}
+
+<table width=100% border=1 class=back>
+<tr>
+ <td width=65% valign=top>
+ <table width=100% cellpadding=5>
+ <tr>
+ <td align=center class=titulo>
+ {t}Job:{/t} <font color=blue> {$smarty.get.server}</font>
+ <br>
+ {t}Period: From{/t} <font color=red>{$startperiod|date_format:"%d/%m/%Y"}</font> {t}to{/t} <font color=red>{$endperiod|date_format:"%d/%m/%Y"}</font>
+ </td>
+ </tr>
+
+ <tr>
+ <td align=left>
+ <table width=100%>
+ <tr>
+ <td class=table1>
+ {t}Bytes transferred in the period:{/t}
+ </td>
+ <td align=right width=15% class=table2>
+ {$bytesperiod|fsize_format}
+ </td>
+ </tr>
+ <tr>
+ <td class=table1 >
+ {t}Files transferred in the period:{/t}
+ </td>
+ <td align=right class=table2>
+ {$filesperiod}
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2>
+ {if $smarty.get.server==""}
+ <img src=stats.php?server={$smarty.get.server|escape:"url"}&tipo_dato=69&title=Análisis%20general&modo_graph=lines>
+ {elseif $smarty.get.default == 1}
+ <img src=stats.php?server={$smarty.get.server|escape:"url"}&tipo_dato=3&title={$smarty.get.server|escape:"url"}&modo_graph=bars&StartDateMonth={$startperiod|date_format:"%m"}&StartDateDay={$startperiod|date_format:"%d"}&StartDateYear={$startperiod|date_format:"%Y"}&EndDateMonth={$endperiod|date_format:"%m"}&EndDateDay={$endperiod|date_format:"%d"}&EndDateYear={$endperiod|date_format:"%Y"}>
+ {else}
+ <img src=stats.php?server={$smarty.get.server|escape:"url"}&tipo_dato={$smarty.get.tipo_dato}&title={$smarty.get.server|escape:"url"}&modo_graph={$smarty.get.modo_graph}&StartDateMonth={$smarty.get.StartDateMonth}&StartDateDay={$smarty.get.StartDateDay}&StartDateYear={$smarty.get.StartDateYear}&EndDateMonth={$smarty.get.EndDateMonth}&EndDateDay={$smarty.get.EndDateDay}&EndDateYear={$smarty.get.EndDateYear}>
+ {/if}
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td width=35%>
+ <table width=100% border=0>
+ <tr>
+ <td>{include file=report_select.tpl}</td>
+ </tr>
+ <tr>
+ <td>
+ <table width=100% border=0 class=genmed cellpadding=0 cellspacing=2>
+ <tr class=titulo2>
+ <td background="images/bg7.gif" height=25>{t}Date{/t}</td>
+ <td background="images/bg7.gif" height=25>{t}Elapsed{/t}</td>
+ <td background="images/bg7.gif" height=25>{t}Level{/t}</td>
+ <td background="images/bg7.gif" height=25 align=center>{t}Bytes{/t}</td>
+ <td background="images/bg7.gif" height=25 width=1%>{t}Status{/t}</td>
+ </tr>
+ {section name=job loop=$jobs}
+ <tr class={cycle values="table1,table2"}>
+ <td {popup caption="Sheduled time" text=$jobs[job].SchedTime}>{$jobs[job].StartTime}</td>
+ <td {popup autostatus=yes caption="EndTime" text=$jobs[job].EndTime}>{$jobs[job].elapsed}</td>
+ <td align=center>{$jobs[job].Level}</td>
+ <td align=right>{$jobs[job].JobBytes|fsize_format}</td>
+ <td align=center width=1%>
+ {if $jobs[job].JobStatus eq "T"}
+ <img src={#root#}/images/s_ok.gif>
+ {else}
+ <img src={#root#}/images/s_error.gif>
+ {/if}
+ </td>
+ </tr>
+ {/section}
+ </table>
+ </td>
+ </tr>
+ </table>
+ <td>
+</tr>
+</table>
+
+
+
+{include file="footer.tpl"}
--- /dev/null
+<table width=100% border=0>
+ <tr><td align=center colspan=3 class=titulo background="images/bg8.png">
+ {t}SELECT NEW REPORT{/t}
+ </td></tr>
+ <tr class=table1><td align=left>
+ <form method=get action=report.php {if !isset($smarty.get.default) }target=_blank{/if}>
+ <input type=hidden name=default value=2>
+ {t}Select a job:{/t}
+ </td>
+ <td align=right>
+ <select name=server>
+ {html_options values=$total_name_jobs output=$total_name_jobs selected=$smarty.get.server}
+ </select>
+ </td>
+ </tr>
+ <tr class=table2>
+ <td align=left>
+ {t}Graph mode:{/t}
+ </td>
+ <td align=right>
+ <select name="modo_graph">
+ <option value="lines">{t}lines{/t}</option>
+ <option value="linepoints">{t}linepoints{/t}</option>
+ <option value="points">{t}points{/t}</option>
+ <option value="bars" selected>{t}bars{/t}</option>
+ <option value="area">{t}area{/t}</option>
+ </select>
+
+ </td>
+
+ </tr>
+ <tr class=table1>
+ <td>
+ {t}Data to show:{/t}
+ </td>
+ <td align=right>
+ <select name="tipo_dato">
+ <option value="3" selected>{t}Transferred bytes{/t}</option>
+ </select>
+ </td>
+ </tr>
+ <tr class=table2>
+ <td align=left>
+ {t}Start period:{/t}
+ </td>
+ <td align=right>
+ {html_select_date prefix="StartDate" time=$time2 field_order="DMY" start_year="-1" end_year="+1" display_days=true}
+ </td>
+ </tr>
+ <tr class=table1>
+ <td align=left>{t}End period:{/t}
+ </td>
+ <td align=right>
+ {html_select_date prefix="EndDate" time=$time field_order="DMY" start_year="-1" end_year="+1" display_days=true}
+ </td>
+ </tr>
+ <tr>
+ <td colspan=3 align=center>
+ <input type=submit value="{t}Create report{/t}">
+ </form>
+ </td>
+ </tr>
+ </table>
\ No newline at end of file
--- /dev/null
+{* Design of table of pools *}
+<table border=0 width=100% class=code cellspacing=0 cellpadding=0>
+<tr align=center width=100%>
+ <td class=tbl_header2 background="images/bg4.png"><b>Pools</b></td>
+ <td class=tbl_header2 background="images/end4.png"><img src="images/empty.png"></td>
+</tr>
+<tr><td colspan=2>
+<table border=0 width=100% class=code cellspacing=0 cellpadding=0>
+{foreach from=$pools item=current}
+ <tr><td colspan=6> </td></tr>
+ <tr>
+ <th align=left style="background-color: #E0C8E5; color: black;" background="images/bg6.png">
+ {$current}
+ </th>
+ </tr>
+ {foreach from=$volumes item=current2}
+ {assign var=key value=$current2}
+ {foreach from=$key item=current3 name=loop}
+ {if $current3.3 == $current && $current3.0 != ""}
+ {if $smarty.foreach.loop.first == TRUE}
+ <tr align=center background="images/bg5.png">
+ <td background="images/bg5.png" class=tbl_pool_inter_1>{t}Volume Name{/t}</td>
+ <td background="images/bg5.png" class=tbl_pool_inter_2>{t}Volume Bytes{/t}</td>
+ <td background="images/bg5.png" class=tbl_pool_inter_2>{t}Media Type{/t}</td>
+ <td background="images/bg5.png" class=tbl_pool_inter_2>{t}When expire?{/t}</td>
+ <td background="images/bg5.png" class=tbl_pool_inter_2>{t}Last Written{/t}
+ <td background="images/bg5.png" class=tbl_pool_inter_3>{t}Volume Status{/t}</td>
+ </tr>
+ {/if}
+ <tr align=center bgcolor={cycle values="#D9E3FC,#CBE7F5"}>
+ <td>{$current3.0}</td>
+ <td>{$current3.1|fsize_format|default:0}</td>
+ <td>{$current3.4}</td>
+ <td {popup text="$current3.6}">{if $current3.6|date_format:"%Y" <= "1979"}--{else}{$current3.6|date_format:"%Y/%m/%d"}{/if}</td>
+ <td {popup text="$current3.5}">{if $current3.5 == "0000-00-00 00:00:00"}--{else}{$current3.5|date_format:"%Y/%m/%d"}{/if}</td>
+ <td>
+ <font color=
+ {if $current3.2 == "Error"}
+ red>
+ {elseif $current3.2 == "Purged"}
+ yellow>
+ {elseif $current3.2 == "Append"}
+ green>
+ {else}
+ "">
+ {/if}
+ {$current3.2}
+ </font>
+ </td>
+ </tr>
+ {/if}
+ {/foreach}
+ {/foreach}
+{/foreach}
+</table>
+</td></tr></table>
\ No newline at end of file
--- /dev/null
+<?
+
+function Check($function,$text,$description="") {
+
+ if (!function_exists($function) )
+ echo "<font color=red>NO</font></td> <td> ".$text." disabled</td><td> ".$description;
+ else
+ echo "<font color=green>YES</font></td> <td> ".$text." enabled<td> ";
+}
+
+?>
+
+<html>
+<head>
+ <title>Testing page</title>
+</head>
+<body>
+
+Checking system for dependencies...<br><br><br>
+<table width=100% border=0>
+<tr>
+ <td width=20%>
+ Checking gettext:
+ <? Check("gettext","Language support", "If you want view Bacula-web in your language, please compile PHP with Gettext");?>
+ </td>
+</tr>
+<tr>
+ <td width=20%>
+ Checking Pear(DB):
+ <?
+ if (@include_once("DB.php") )
+ echo "<font color=green>YES</font></td> <td> Pear DB enabled</td><td> ";
+ else
+ echo "<font color=red>NO</font></td> <td> Pear DB NOT FOUND</td><td>This is required. Please download from <a href=\"http://pear.php.net/package/DB/download\">http://pear.php.net/package/DB/download</a> .";
+ ?>
+ </td>
+</tr>
+<tr>
+ <td>
+ Checking GD:
+ <?Check("gd_info","GD support", "This is required. Please, compile php with GD support");?>
+ </td>
+</tr>
+</table>
+<br><br>
+
+Please, click the link below to test your graph system capabilities (Bacula-web only use PNG): <br>
+
+<a href="external_packages/phplot/examples/test_setup.php" target="_blank">Test</a>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+#!/usr/local/bin/php -qn
+<?php
+/**
+ * tsmarty2c.php - rips gettext strings from smarty template
+ *
+ * ------------------------------------------------------------------------- *
+ * 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 *
+ * ------------------------------------------------------------------------- *
+ *
+ * This command line script rips gettext strings from smarty file, and prints them to stdout in C format,
+ * that can later be used with the standard gettext tools.
+ *
+ * Usage:
+ * ./tsmarty2c.php <filename or directory> <file2> <..> > smarty.c
+ *
+ * If a parameter is a directory, the template files within will be parsed.
+ *
+ * @package smarty_gettext
+ * @version 0.9
+ * @link http://www.boom.org.il/smarty/gettext/
+ * @author Sagi Bashari <sagi@boom.org.il>
+ * @copyright 2004 Sagi Bashari
+ */
+
+// smarty open tag
+$ldq = preg_quote('{');
+
+// smarty close tag
+$rdq = preg_quote('}');
+
+// smarty command
+$cmd = preg_quote('t');
+
+// extensions of smarty files, used when going through a directory
+$extensions = array('tpl');
+
+// "fix" string - strip slashes, escape and convert new lines to \n
+function fs($str)
+{
+ $str = stripslashes($str);
+ $str = str_replace('"', '\"', $str);
+ $str = str_replace("\n", '\n', $str);
+ return $str;
+}
+
+// rips gettext strings from $file and prints them in C format
+function do_file($file)
+{
+ $content = @file_get_contents($file);
+
+ if (empty($content)) {
+ return;
+ }
+
+ global $ldq, $rdq, $cmd;
+
+ preg_match_all("/{$ldq}\s*({$cmd})\s*([^{$rdq}]*){$rdq}([^{$ldq}]*){$ldq}\/\\1{$rdq}/", $content, $matches);
+
+ for ($i=0; $i < count($matches[0]); $i++) {
+ if (preg_match('/plural\s*=\s*["\']?\s*(.[^\"\']*)\s*["\']?/', $matches[2][$i], $match)) {
+ print 'ngettext("'.fs($matches[3][$i]).'","'.fs($match[1]).'",x);'."\n";
+ } else {
+ print 'gettext("'.fs($matches[3][$i]).'");'."\n";
+ }
+ }
+}
+
+// go through a directory
+function do_dir($dir)
+{
+ $d = dir($dir);
+
+ while (false !== ($entry = $d->read())) {
+ if ($entry == '.' || $entry == '..') {
+ continue;
+ }
+
+ $entry = $dir.'/'.$entry;
+
+ if (is_dir($entry)) { // if a directory, go through it
+ do_dir($entry);
+ } else { // if file, parse only if extension is matched
+ $pi = pathinfo($entry);
+
+ if (in_array($pi['extension'], $GLOBALS['extensions'])) {
+ do_file($entry);
+ }
+ }
+ }
+
+ $d->close();
+}
+
+for ($ac=1; $ac < $_SERVER['argc']; $ac++) {
+ if (is_dir($_SERVER['argv'][$ac])) { // go through directory
+ do_dir($_SERVER['argv'][$ac]);
+ } else { // do file
+ do_file($_SERVER['argv'][$ac]);
+ }
+}
+
+?>
--- /dev/null
+Makefile
+bacula-bimagemgr.spec
--- /dev/null
+# Makefile to install bimagemgr utility
+# 29 Aug 2004 D. Scott Barninger
+
+BINOWNER=@bimagemgr_binowner@
+BINGROUP=@bimagemgr_bingroup@
+DATAOWNER=@bimagemgr_dataowner@
+DATAGROUP=@bimagemgr_datagroup@
+CGIDIR=@bimagemgr_cgidir@
+DOCDIR=@bimagemgr_docdir@
+SYSCONFDIR=@sysconfdir@
+INSTALL=@INSTALL@
+
+all: install
+
+install:
+ $(INSTALL) -d $(DESTDIR)$(CGIDIR)
+ $(INSTALL) -d $(DESTDIR)$(DOCDIR)
+ $(INSTALL) -d $(DESTDIR)$(SYSCONFDIR)
+
+ $(INSTALL) -o $(BINOWNER) -g $(BINGROUP) -m 755 bimagemgr.pl $(DESTDIR)$(CGIDIR)
+ $(INSTALL) -o $(BINOWNER) -g $(BINGROUP) -m 750 create_cdimage_table.pl $(DESTDIR)$(SYSCONFDIR)
+ $(INSTALL) -o $(BINOWNER) -g $(BINGROUP) -m 644 README $(DESTDIR)$(SYSCONFDIR)/README.bimagemgr
+ $(INSTALL) -o $(BINOWNER) -g $(BINGROUP) -m 644 bimagemgr.gif $(DESTDIR)$(DOCDIR)
+ $(INSTALL) -o $(BINOWNER) -g $(BINGROUP) -m 644 cdrom_spins.gif $(DESTDIR)$(DOCDIR)
+ $(INSTALL) -o $(BINOWNER) -g $(BINGROUP) -m 644 clearpixel.gif $(DESTDIR)$(DOCDIR)
+ $(INSTALL) -o $(DATAOWNER) -g $(DATAGROUP) -m 664 temp.html $(DESTDIR)$(DOCDIR)
+
+uninstall:
+ rm -f $(DESTDIR)$(DOCDIR)/bimagemgr.gif
+ rm -f $(DESTDIR)$(DOCDIR)/cdrom_spins.gif
+ rm -f $(DESTDIR)$(DOCDIR)/clearpixel.gif
+ rm -f $(DESTDIR)$(DOCDIR)/temp.html
+ rm -f $(DESTDIR)$(SYSCONFDIR)/create_cdimage_table.pl
+ rm -f $(DESTDIR)$(CGIDIR)/bimagemgr.pl
+ rm -f $(DESTDIR)$(SYSCONFDIR)/README.bimagemgr
--- /dev/null
+bimagemgr.pl
+14 Nov 2004
+
+This is a utility to monitor and burn file backups to CDR. It is a web
+based interface written in perl. It requires perl and an apache or other
+http server. It also requires the perl DBI module and the driver for the
+database used to store your bacula catalog. It has been tested on MySQL
+catalogs but an untested configuration is present for Postgresql.
+
+It can be run on the same server as bacula or on another machine on the
+network if you are willing to relax permissions on the backup Volume files
+(see below).
+
+Installation:
+
+1. Examine the Makefile and adjust it to your configuration if needed.
+2. Edit the configuration section of bimagemgr.pl to fit your configuration.
+3. Do 'make install' as root.
+4. Edit httpd.conf and change the Timeout value. The web server must not time
+out and close the connection before the burn process is finished. The exact
+value needed may vary depending upon your cd recorder speed and whether you are
+burning on the bacula server on on another machine across your network. In my
+case I set it to 1000 seconds. Restart httpd.
+5. Make sure that cdrecord is setuid root.
+
+For bacula systems less than 1.36:
+1. Edit the configuration section of create_cdimage_table.pl to fit your configuration.
+2. Run /etc/bacula/create_cdimage_table.pl from a console on your bacula
+server (as root) to add the CDImage table to your bacula database.
+
+Accessing the Volume files:
+The Volume files by default have permissions 640 and can only be read by root.
+The recommended approach to this is as follows (and only works if bimagemgr and
+apache are running on the same host as bacula.
+
+For bacula-1.34 or 1.36 installed from tarball -
+1. Create a new user group bacula and add the user apache to the group for
+Red Hat or Mandrake systems. For SuSE systems add the user wwwrun to the
+bacula group.
+2. Change ownership of all of your Volume files to root.bacula
+3. Edit the /etc/bacula/bacula startup script and set SD_USER=root and
+SD_GROUP=bacula. Restart bacula.
+
+Note: step 3 should also be done in /etc/init.d/bacula-sd but released versions
+of this file prior to 1.36 do not support it. In that case it would be necessary after
+a reboot of the server to execute '/etc/bacula/bacula restart'.
+
+For bacula-1.36 installed from rpm -
+1. Add the user apache to the group bacula for Red Hat or Mandrake systems.
+For SuSE systems add the user wwwrun to the bacula group.
+2. Change ownership of all of your Volume files to root.bacula
+
+bimagemgr will now be able to read the Volume files but they are still not
+world readable.
+
+If you are running bimagemgr on another host (not recommended) then you will
+need to change the permissions on all of your backup volume files to 644 in
+order to access them via nfs share or other means. This approach should only
+be taken if you are sure of the security of your environment as it exposes
+the backup Volume files to world read.
+
+That's it. Call the script from a web browser as http://server/cgi-bin/bimagemgr.pl
+place a blank cd in your recorder and press a Burn button.
--- /dev/null
+# Bacula Image Manager RPM spec file
+# Copyright (C) 2004 Kern Sibbald
+
+# Platform defines
+
+%define rhel 0
+%{?build_rhel:%define rhel 1}
+
+%define suse 0
+%{?build_suse:%define suse 1}
+
+%define mdk 0
+%{?build_mdk:%define mdk 1}
+
+# test for a platform definition
+%if ! %{rhel} && ! %{suse} && ! %{mdk}
+%{error: You must specify a platform. Please examine the spec file.}
+exit 1
+%endif
+
+# set destination directories
+%define cgidir /var/www/cgi-bin
+%define docdir /var/www/html
+%define sysconfdir /etc/bacula
+%if %{suse}
+%define cgidir /srv/www/cgi-bin
+%define docdir /srv/www/htdocs
+%endif
+
+# set ownership of files
+%define binowner root
+%define bingroup root
+%define dataowner apache
+%define datagroup apache
+%if %{suse}
+%define dataowner wwwrun
+%define datagroup www
+%endif
+
+Summary: Bacula - The Network Backup Solution
+Name: bacula
+Version: @VERSION@
+Release: 1
+Group: System Environment/Daemons
+Copyright: GPL v2
+Source: %{name}-%{version}.tar.gz
+BuildRoot: %{_tmppath}/%{name}-root
+URL: http://www.bacula.org/
+BuildArchitectures: noarch
+Vendor: The Bacula Team
+Distribution: The Bacula Team
+Packager: D. Scott Barninger <barninger at fairfieldcomputers dot com>
+
+%description
+
+%package bimagemgr
+Summary: Bacula - The Network Backup Solution
+Group: System Environment/Daemons
+
+Requires: perl, perl-DBI, bacula-server, cdrecord, mkisofs
+%if %{mdk}
+Requires: apache
+%else
+Requires: httpd
+%endif
+
+%description bimagemgr
+Bacula is a set of computer programs that permit you (or the system
+administrator) to manage backup, recovery, and verification of computer
+data across a network of computers of different kinds. bimagemgr is a
+utility to manage backups made to files intended for burning to CDR
+disk. bimagemgr allows you to easily see which Volumes have been written
+to more recently than they have been recorded to CDR disk and record those
+which have.
+
+
+%prep
+
+%setup
+
+%build
+
+%install
+
+[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf "$RPM_BUILD_ROOT"
+
+mkdir -p $RPM_BUILD_ROOT/%{cgidir}
+mkdir -p $RPM_BUILD_ROOT/%{docdir}
+mkdir -p $RPM_BUILD_ROOT/%{sysconfdir}
+
+cp -p src/bimagemgr/bimagemgr.pl $RPM_BUILD_ROOT/%{cgidir}/
+cp -p src/bimagemgr/create_cdimage_table.pl $RPM_BUILD_ROOT/%{sysconfdir}/
+cp -p src/bimagemgr/README $RPM_BUILD_ROOT/%{sysconfdir}/README.bimagemgr
+cp -p src/bimagemgr/bimagemgr.gif $RPM_BUILD_ROOT/%{docdir}/
+cp -p src/bimagemgr/cdrom_spins.gif $RPM_BUILD_ROOT/%{docdir}/
+cp -p src/bimagemgr/clearpixel.gif $RPM_BUILD_ROOT/%{docdir}/
+cp -p src/bimagemgr/temp.html $RPM_BUILD_ROOT/%{docdir}/
+
+chmod 755 $RPM_BUILD_ROOT/%{cgidir}/bimagemgr.pl
+chmod 750 $RPM_BUILD_ROOT/%{sysconfdir}/create_cdimage_table.pl
+chmod 644 $RPM_BUILD_ROOT/%{sysconfdir}/README.bimagemgr
+chmod 644 $RPM_BUILD_ROOT/%{docdir}/*
+chmod 664 $RPM_BUILD_ROOT/%{docdir}/temp.html
+
+%clean
+[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf "$RPM_BUILD_ROOT"
+
+%files bimagemgr
+%defattr(-,%{binowner},%{bingroup})
+%{cgidir}/bimagemgr.pl
+%{sysconfdir}/create_cdimage_table.pl
+%{sysconfdir}/README.bimagemgr
+%{docdir}/bimagemgr.gif
+%{docdir}/cdrom_spins.gif
+%{docdir}/clearpixel.gif
+
+%defattr(-,%{dataowner},%{datagroup})
+%{docdir}/temp.html
+
+%post bimagemgr
+
+%preun bimagemgr
+
+%changelog
+* Thu Dec 09 2004 D. Scott Barninger <barninger at fairfieldcomputers.com>
+- ASSIGNMENT OF COPYRIGHT
+- FOR VALUE RECEIVED, D. Scott Barninger hereby sells, transfers and
+- assigns unto Kern Sibbald, his successors, assigns and personal representatives,
+- all right, title and interest in and to the copyright in this software RPM
+- spec file. D. Scott Barninger warrants good title to said copyright, that it is
+- free of all liens, encumbrances or any known claims against said copyright.
+* Sun Nov 14 2004 D. Scott Barninger <barninger at fairfieldcomputers.com>
+- initial spec file
--- /dev/null
+#!/usr/bin/perl
+##
+# bimagemgr.pl
+# burn manager for bacula CD image files
+#
+# Copyright (C) 2004 Kern Sibbald
+#
+# Thu Dec 09 2004 D. Scott Barninger <barninger at fairfieldcomputers.com>
+# ASSIGNMENT OF COPYRIGHT
+# FOR VALUE RECEIVED, D. Scott Barninger hereby sells, transfers and
+# assigns unto Kern Sibbald, his successors, assigns and personal representatives,
+# all right, title and interest in and to the copyright in this software.
+# D. Scott Barninger warrants good title to said copyright, that it is
+# free of all liens, encumbrances or any known claims against said copyright.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public
+# License version 2 as published by the Free Software Foundation.
+#
+# 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.
+##
+
+my $VERSION = "0.2.6";
+
+require 5.000; use strict 'vars', 'refs', 'subs';
+use DBI;
+
+#-------------------------------------------------------------------#
+# Program Configuration
+
+## web server configuration
+#
+# web server path to program from server root
+my $prog_name = "/cgi-bin/bimagemgr.pl";
+#
+# web server host
+my $http_host="localhost";
+#
+# path to graphics from document root
+my $logo_graphic = "/bimagemgr.gif";
+my $spacer_graphic = "/clearpixel.gif";
+my $burn_graphic = "/cdrom_spins.gif";
+##
+
+## database configuration
+#
+# database name
+my $database = "bacula";
+#
+# database host
+my $host = "backup";
+#
+# database user
+my $user = "bacula";
+#
+# database password
+my $password = "";
+#
+# database driver selection - uncomment one set
+# MySQL
+my $db_driver = "mysql";
+my $db_name_param = "database";
+my $catalog_dump = "mysqldump --host=$host --user=$user --password=$password $database";
+# Postgresql
+# my $db_driver = "Pg";
+# my $db_name_param = "dbname";
+# my $catalog_dump = "pg_dump --host=$host --username=$user --password=$password $database";
+##
+
+# path to backup files
+my $image_path = "/mnt/backup/backup";
+
+## path to cdrecord and burner settings
+my $cdrecord = "/usr/bin/cdrecord";
+my $mkisofs = "/usr/bin/mkisofs";
+my $cdburner = "1,0,0";
+my $burner_speed = "40";
+# burnfree option - uncomment one
+#my $burnfree = "driveropts=noburnfree"; # no buffer underrun protection
+my $burnfree = "driveropts=burnfree"; # with buffer underrun
+##
+
+# temporary files
+my $tempfile="temp.html";
+my $tempfile_path="/var/www/html/temp.html";
+my $working_dir="/var/tmp";
+
+# copyright info for page footer
+my $copyright = "Copyright © 2004 The Bacula Team";
+#-------------------------------------------------------------------#
+
+my %input = &getcgivars;
+my $action = $input{'action'};
+my $vol = $input{'vol'};
+
+&Main();
+exit;
+
+#-------------------------------------------------------------------#
+# Function Main
+# Description: check requested action and call appropriate subroutine
+#
+
+sub Main {
+ # set default action & department
+ if (!$action) {$action = "display"};
+
+ if ($action eq "display") {
+ &Display();
+ }
+ elsif ($action eq "burn") {
+ &Burn();
+ }
+ elsif ($action eq "reset") {
+ &Reset();
+ }
+ elsif ($action eq "version") {
+ &DisplayHeader();
+ print "<div align=\"center\">";
+ print "<br>Bacula CD Image Manager version $VERSION<br><br>";
+ print "Copyright © 2004 D. Scott Barninger<br>";
+ print "Licensed under the GNU GPL version 2.0";
+ print "</div>";
+ print "</body></html>";
+ }
+ else {
+ &HTMLdie("Unknown action $action","So sorry Kimosabe..");
+ }
+ return;
+}
+
+#-------------------------------------------------------------------#
+# Function Display
+# Description: main page display routine
+
+sub Display {
+ my ($MediaId,$VolumeName,$LastWritten,$VolWrites,$VolStatus,$data);
+
+ &DisplayHeader();
+ &UpdateImageTable();
+
+ # connect to database
+ my $dbh = DBI->connect("DBI:$db_driver:$db_name_param=$database;host=$host","$user","$password",
+ {'RaiseError' => 1}) || &HTMLdie("Unable to connect to database.");
+ my $sth = $dbh->prepare("SELECT Media.VolumeName,Media.LastWritten,CDImages.LastBurn,
+ Media.VolWrites,Media.VolStatus
+ FROM CDImages,Media
+ WHERE CDImages.MediaId = Media.MediaId");
+
+ print "<div align=\"center\">";
+ print "<table width=\"80%\" border=\"0\">";
+ print "<tr>";
+ print "<td colspan=\"6\"><b>";
+ print "<p>Backup files which need to be committed to CDR disk since their last write date are shown below with a Burn button. ";
+ print "Place a blank CDR disk in the drive and click the Burn button for the volume you wish to burn to disk.</p>";
+ print "<p>When CD recording is complete the popup window will display the output of cdrecord. ";
+ print "A successful burn is indicated by the last line showing that all bytes were successfully recorded.</p>";
+ print "<p>After the popup window indicates that the burn is complete, close the popup and <a href=\"$prog_name\">refresh this window</a>. ";
+ print "If the burn is not successful click the Reset link under the last burn date to restore the Burn button and <a href=\"$prog_name\">refresh this window</a>.</p>";
+ print "<p>To burn a copy of your catalog click the catalog Burn button at the bottom of the page. ";
+ print "Up to date copies of your catalog and all backup volumes ensure that your bacula server can be rebuilt in the event of a catastrophe.</p>";
+ print "</b></td>";
+ print "</tr>";
+ print "<tr>";
+ print "<td colspan=\"6\"> </td>";
+ print "</tr>";
+ print "</table>";
+ print "<table width=\"80%\" border=\"1\">";
+ print "<tr>";
+ print "<td align=\"center\" colspan=\"6\"><h3>Current Volume Information</h3>Make sure the backup file path $image_path is mounted.</td>";
+ print "</tr>";
+ print "<tr>";
+ print "<td align=\"center\"><b>Volume Name</b></td>";
+ print "<td align=\"center\"><b>Last Written</b></td>";
+ print "<td align=\"center\"><b>Last Burn</b></td>";
+ print "<td align=\"center\"><b>Writes</b></td>";
+ print "<td align=\"center\"><b>Status</b></td>";
+ print "<td align=\"center\"> </td>";
+ print "</tr>";
+
+ $sth->execute();
+ while ($data = $sth->fetchrow_arrayref) {
+ print "<tr>";
+ print "<td align=\"center\">$$data[0]</td>";
+ print "<td align=\"center\">$$data[1]</td>";
+ print "<td align=\"center\">$$data[2]<br><a href=\"$prog_name?action=reset&vol=$$data[0]\">Reset</a></td>";
+ print "<td align=\"center\">$$data[3]</td>";
+ print "<td align=\"center\">$$data[4]</td>";
+ if ($$data[1] gt $$data[2] && $$data[3] gt "0" && $$data[4] ne "Purged") {
+ print "<td align=\"center\"><form><input type=button value=\"Burn\" onClick=\"BurnWindow=window.open(\'$prog_name?action=burn&vol=$$data[0]\', \'BurnWindow\', \'scrollbars=yes,menubar=no,width=550,height=450,screenX=0,screenY=15\')\"></form></td>";
+ }
+ else {
+ print "<td align=\"center\">No Burn</td>";
+ }
+ print "</tr>";
+ }
+ $sth->finish();
+ $dbh->disconnect();
+
+ print "<tr>";
+ print "<td align=\"center\" colspan=\"6\"><img src=\"$spacer_graphic\" height=\"18\"><form><input type=button value=\"Burn Catalog\" onClick=\"BurnWindow=window.open(\'$prog_name?action=burn&vol=bacula.sql\', \'BurnWindow\', \'scrollbars=yes,menubar=no,width=550,height=450,screenX=0,screenY=15\')\"><img src=\"$spacer_graphic\" width=\"5\"><input type=button value=\"Blank CDRW\" onClick=\"BurnWindow=window.open(\'$prog_name?action=burn&vol=blank\', \'BurnWindow\', \'scrollbars=yes,menubar=no,width=550,height=450,screenX=0,screenY=15\')\"></form><img src=\"$spacer_graphic\" height=\"1\"></td>";
+ print "</tr>";
+ print "</table>";
+ print "</div>";
+ print "<p><p>";
+ &DisplayFooter();
+ return;
+}
+
+#-------------------------------------------------------------------#
+# Function Burn
+# Description: burn cd images
+
+sub Burn {
+
+ my $Volume = "$image_path/$vol";
+
+ # check to see if this is a catalog request
+ if ($vol eq "bacula.sql") {
+ $Volume = "$working_dir/bacula.sql";
+ }
+ # check to see if this is a blanking request
+ if ($vol eq "blank") {
+ $Volume = "Blank CD/RW";
+ }
+
+ # open the burn results file and write header info
+ open(OUTF,">$tempfile_path") || &HTMLdie("Unable to open temporary output file.");
+ print OUTF "<html>";
+ print OUTF "<head>";
+ print OUTF "<title>Burning Volume $Volume</title>";
+ print OUTF "</head>";
+ print OUTF "<body>";
+ print OUTF "<div align=\"center\">";
+ print OUTF "<table width=\"100%\">";
+ print OUTF "<tbody>";
+ print OUTF "<tr>";
+ print OUTF "<td align=\"center\"> <img src=\"$logo_graphic\"> </td>";
+ print OUTF "</tr>";
+ print OUTF "</tbody>";
+ print OUTF "</table>";
+ print OUTF "</div>";
+ close(OUTF);
+
+ # now send to the burn status window that we are burning
+ print "Content-type: text/html\n\n";
+ print "<html>";
+ print "<head>";
+ print "<meta http-equiv=\"Refresh\" content=\"3; url=http://$http_host/$tempfile\">";
+ print "<title>Burning Volume $Volume</title>";
+ print "</head>";
+ print "<body>";
+ print "<div align=\"center\">";
+ print "<table width=\"100%\">";
+ print "<tbody>";
+ print "<tr>";
+ print "<td align=\"center\"> <img src=\"$logo_graphic\"> </td>";
+ print "</tr>";
+ print "<tr>";
+ print "<td align=\"center\"> <img src=\"$spacer_graphic\" height=\"10\"> </td>";
+ print "</tr>";
+ print "<tr>";
+ print "<td align=\"center\"> <img src=\"$burn_graphic\"> </td>";
+ print "</tr>";
+ print "</tbody>";
+ print "</table>";
+ print "<p>Now burning $Volume ...</p>";
+ print "</div>";
+ print "</body>";
+ print "</html>";
+
+ # check to see if this is a catalog request
+ if ($vol eq "bacula.sql") {
+ system("$catalog_dump > $working_dir/bacula.sql");
+ }
+
+ # check to see if this is a blanking request
+ if ($vol eq "blank") {
+ system("$cdrecord -eject speed=2 dev=$cdburner blank=fast >> $tempfile_path");
+ }
+ else {
+ # burn the image and clean up
+ system("$mkisofs -o $working_dir/temp.iso -J -r -V $vol $Volume");
+ system("$cdrecord -eject $burnfree speed=$burner_speed dev=$cdburner $working_dir/temp.iso >> $tempfile_path");
+ system("rm -f $working_dir/temp.iso");
+ }
+
+ if ($vol eq "bacula.sql") {
+ system("rm -f $working_dir/bacula.sql");
+ }
+
+ # finish up the burn results file
+ open(OUTF,">>$tempfile_path") || &HTMLdie("Unable to open temporary output file.");
+ print OUTF "<table width=\"100%\">";
+ print OUTF "<tbody>";
+ print OUTF "<tr>";
+ print OUTF "<td><div align=\"center\">If you do not see successful output from cdrecord above the burn has failed.</div></td>";
+ print OUTF "</tr>";
+ print OUTF "<tr>";
+ print OUTF "<td><div align=\"center\">Please close this window and refresh the main window.</div></td>";
+ print OUTF "</tr>";
+ print OUTF "<tr>";
+ print OUTF "<td><div align=\"center\"><font size=\"-3\"> $copyright </font></div></td>";
+ print OUTF "</tr>";
+ print OUTF "</tbody>";
+ print OUTF "</table>";
+ print OUTF "</div>";
+ print OUTF "</body>";
+ print OUTF "</html>";
+ close(OUTF);
+
+ # now pretty up the burn results file by replacing \n with <br>
+ open(INFILE, "$tempfile_path") || &HTMLdie("Unable to open input file $tempfile_path");
+ open(OUTFILE, ">$working_dir/bimagemgr-temp") || &HTMLdie("Unable to open output file bimagemgr-temp");
+ while(my $line = <INFILE>) {
+ $line =~ s/\n/<br>/g;
+ print OUTFILE ($line);
+ }
+ close(INFILE);
+ close(OUTFILE);
+ system("cp -f $working_dir/bimagemgr-temp $tempfile_path");
+
+ if ($vol ne "bacula.sql" && $vol ne "blank") {
+ ## update the burn date in the CDImages table
+ # get current timestamp
+ my($sysdate,$systime,$sysyear,$sysmon,$sysmday) = &SysDate;
+ my $burndate = "$sysdate $systime";
+
+ # connect to database
+ my $dbh = DBI->connect("DBI:$db_driver:$db_name_param=$database;host=$host","$user","$password",
+ {'RaiseError' => 1}) || &HTMLdie("Unable to connect to database.");
+ # get the MediaId for our volume
+ my $sth = $dbh->prepare("SELECT MediaId from Media WHERE VolumeName = \"$vol\"");
+ $sth->execute();
+ my $media_id = $sth->fetchrow_array;
+ $sth->finish();
+ # set LastBurn date
+ $dbh->do("UPDATE CDImages SET LastBurn = \"$burndate\" WHERE MediaId = $media_id");
+ $dbh->disconnect();
+ ##
+ }
+
+ return;
+}
+
+#-------------------------------------------------------------------#
+# Function UpdateImageTable
+# Description: update the CDImages table from the Media table
+
+sub UpdateImageTable {
+
+ my ($data,@MediaId,$id,$exists,$sth1,$sth2);
+
+ # connect to database
+ my $dbh = DBI->connect("DBI:$db_driver:$db_name_param=$database;host=$host","$user","$password",
+ {'RaiseError' => 1}) || &HTMLdie("Unable to connect to database.");
+
+ # get the list of current MediaId
+ $sth1 = $dbh->prepare("SELECT MediaId from Media");
+ $sth1->execute();
+ while ($data = $sth1->fetchrow_arrayref) {
+ push(@MediaId,$$data[0]);
+ }
+ $sth1->finish();
+
+ # now check if we have a matching row in CDImages
+ # if not then insert a record
+ foreach $id (@MediaId) {
+ $sth2 = $dbh->prepare("SELECT MediaId from CDImages
+ WHERE MediaId = $id");
+ $sth2->execute();
+ $exists = $sth2->fetchrow_array;
+ if ($exists ne $id) {
+ $dbh->do("INSERT into CDImages SET MediaId=$id");
+ }
+ $sth2->finish();
+ }
+
+ # disconnect
+ $dbh->disconnect();
+ return;
+}
+
+#-------------------------------------------------------------------#
+# Function Reset
+# Description: reset the Last Burn date to 0
+
+sub Reset {
+ my ($id,$sth);
+
+ # connect to database
+ my $dbh = DBI->connect("DBI:$db_driver:$db_name_param=$database;host=$host","$user","$password",
+ {'RaiseError' => 1}) || &HTMLdie("Unable to connect to database.");
+
+ # get the MediaId
+ $sth = $dbh->prepare("SELECT MediaId FROM Media WHERE VolumeName=\"$vol\"");
+ $sth->execute();
+ $id = $sth->fetchrow_array;
+ $sth->finish();
+
+ # reset the date
+ $dbh->do("UPDATE CDImages SET LastBurn=\"0000-00-00 00:00:00\"
+ WHERE MediaId=$id") || &HTMLdie("Unable to update Last Burn Date.");
+
+ $dbh->disconnect();
+
+ print "Location:http://$http_host$prog_name\n\n";
+}
+
+#-------------------------------------------------------------------#
+# Function DisplayHeader
+# Description: main page display header
+
+sub DisplayHeader {
+ my($title)= @_ ;
+ $title || ($title= "Bacula CD Image Manager") ;
+ print "Content-type: text/html\n\n";
+ print "<html>";
+ print "<head>";
+ print "<title>$title</title>";
+ print "</head>";
+ print "<body>";
+ print "<div align=\"center\">";
+ print "<table width=\"100%\">";
+ print "<tbody>";
+ print "<tr>";
+ print "<td align=\"center\"><a href=\"$prog_name?action=version\" alt=\"About bimagemgr\"><img src=\"$logo_graphic\" border=\"0\"></a></td>";
+ print "</tr>";
+ print "</tbody>";
+ print "</table>";
+ print "</div>";
+ print "<p></p>";
+ return;
+}
+
+#-------------------------------------------------------------------#
+# Function DisplayFooter
+# Description: main page display footer
+
+sub DisplayFooter {
+ print "<table width=\"100%\">";
+ print "<tbody>";
+ print "<tr>";
+ print "<td><div align=\"center\"><font size=\"-3\"> $copyright </font></div></td>";
+ print "</tr>";
+ print "</tbody>";
+ print "</table>";
+ print "</div>";
+ print "</body>";
+ print "</html>";
+ return;
+}
+
+#-------------------------------------------------------------------#
+# Function SysDate
+# Description: get current date/time
+#
+sub SysDate {
+ # usage: my($sysdate,$systime,$sysyear,$sysmon,$sysmday) = &SysDate;
+
+ my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
+ if (length ($min) == 1) {$min = '0'.$min;}
+ if (length ($sec) == 1) {$sec = '0'.$sec;}
+ # since localtime returns the month as 0-11
+ $mon = $mon + 1;
+ if (length ($mon) == 1) {$mon = '0'.$mon;}
+ if (length ($mday) == 1) {$mday = '0'.$mday;}
+ # since localtime returns the year as the number of years since 1900
+ # ie year is 100 in the year 2000 (so is y2k OK)
+ $year = $year + 1900;
+ my $date = "$year-$mon-$mday";
+ my $time = "$hour:$min:$sec";
+ return($date,$time,$year,$mon,$mday);
+}
+
+#-------------------------------------------------------------------#
+# Function getcgivars
+# Read all CGI vars into an associative array.
+# courtesy James Marshall james@jmarshall.com http://www.jmarshall.com/easy/cgi/
+# If multiple input fields have the same name, they are concatenated into
+# one array element and delimited with the \0 character (which fails if
+# the input has any \0 characters, very unlikely but conceivably possible).
+# Currently only supports Content-Type of application/x-www-form-urlencoded.
+sub getcgivars {
+ my($in, %in) ;
+ my($name, $value) ;
+
+
+ # First, read entire string of CGI vars into $in
+ if ( ($ENV{'REQUEST_METHOD'} eq 'GET') ||
+ ($ENV{'REQUEST_METHOD'} eq 'HEAD') ) {
+ $in= $ENV{'QUERY_STRING'} ;
+
+ } elsif ($ENV{'REQUEST_METHOD'} eq 'POST') {
+ if ($ENV{'CONTENT_TYPE'}=~ m#^application/x-www-form-urlencoded$#i) {
+ length($ENV{'CONTENT_LENGTH'})
+ || &HTMLdie("No Content-Length sent with the POST request.") ;
+ read(STDIN, $in, $ENV{'CONTENT_LENGTH'}) ;
+
+ } else {
+ &HTMLdie("Unsupported Content-Type: $ENV{'CONTENT_TYPE'}") ;
+ }
+
+ } else {
+ &HTMLdie("Script was called with unsupported REQUEST_METHOD.") ;
+ }
+
+ # Resolve and unencode name/value pairs into %in
+ foreach (split('&', $in)) {
+ s/\+/ /g ;
+ ($name, $value)= split('=', $_, 2) ;
+ $name=~ s/%(..)/chr(hex($1))/ge ;
+ $value=~ s/%(..)/chr(hex($1))/ge ;
+ $in{$name}.= "\0" if defined($in{$name}) ; # concatenate multiple vars
+ $in{$name}.= $value ;
+ }
+
+ return %in ;
+
+}
+
+#-------------------------------------------------------------------#
+# Function HTMLdie
+# Description: Die, outputting HTML error page
+# If no $title, use a default title
+sub HTMLdie {
+ my ($msg,$title)= @_ ;
+ $title || ($title= "CGI Error") ;
+ print "Content-type: text/html\n\n";
+ print "<html>";
+ print "<head>";
+ print "<title>$title</title>";
+ print "</head>";
+ print "<body>";
+ print "<h1>$title</h1>";
+ print "<h3>$msg</h3>";
+ print "<form>";
+ print "<input type=button name=\"BackButton\" value=\"<- Back\" id=\"Button1\" onClick=\"history.back()\">";
+ print "</form>";
+ print "</body>";
+ print "</html>";
+
+ exit ;
+}
+
+#-------------------------------------------------------------------#
+# Changelog
+#
+# 0.2 14 Aug 2004
+# first functional version
+#
+# 0.2.1 15 Aug 2004
+# add configuration option for Postgresql driver
+#
+# 0.2.2 21 Aug 2004
+# add Reset subroutine and version display
+#
+# 0.2.3 21 Aug 2004
+# add burn of catalog
+# add instructions to the main display
+#
+# 0.2.4 23 Aug 2004
+# correct equivalence operator in Burn function
+#
+# 0.2.5 28 Aug 2004
+# add blank of CD/RW disk
+#
+# 0.2.6 29 Aug 2004
+# add conditional in Burn() to prevent updating of CDImages
+# for catalog or CD/RW blanking burns
+#
--- /dev/null
+#!/usr/bin/perl
+##
+# create_cdimage_table.pl
+# create the bacula table for CD image management
+#
+# Copyright (C) 2004 Kern Sibbald
+#
+# Thu Dec 09 2004 D. Scott Barninger <barninger at fairfieldcomputers.com>
+# ASSIGNMENT OF COPYRIGHT
+# FOR VALUE RECEIVED, D. Scott Barninger hereby sells, transfers and
+# assigns unto Kern Sibbald, his successors, assigns and personal representatives,
+# all right, title and interest in and to the copyright in this software.
+# D. Scott Barninger warrants good title to said copyright, that it is
+# free of all liens, encumbrances or any known claims against said copyright.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public
+# License version 2 as published by the Free Software Foundation.
+#
+# 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.
+##
+
+$VERSION = "0.2.1";
+
+require 5.000; use strict 'vars', 'refs', 'subs';
+use DBI;
+
+#------------------------------------------------------------------------------------
+# configuration section
+my($dbh,$sql,$database,$host,$user,$password,$db_driver,$db_name_param);
+$database = "bacula";
+$host = "localhost";
+$user = "bacula";
+$password = "";
+## database driver selection - uncomment one set
+# MySQL
+$db_driver = "mysql";
+$db_name_param = "database";
+# Postgresql
+# $db_driver = "Pg";
+# $db_name_param = "dbname";
+##
+# end configuration section
+#------------------------------------------------------------------------------------
+
+# connect to the database
+$dbh = DBI->connect("DBI:$db_driver:$db_name_param=$database;host=$host","$user","$password",{'RaiseError' => 1}) || die("Unable to connect to database.");
+
+if ($db_driver eq "mysql") {
+$sql = "CREATE TABLE CDImages (
+ MediaId INTEGER UNSIGNED NOT NULL,
+ LastBurn DATETIME NOT NULL,
+ PRIMARY KEY (MediaId))";
+}
+
+if ($db_driver eq "Pg") {
+$sql = "CREATE TABLE CDImages (
+ MediaId integer not null,
+ LastBurn timestamp without time zone not null,
+ primary key (MediaId))";
+}
+
+$dbh->do($sql);
+
+$dbh->disconnect();
+print "\nFinished creating the CDImages table.\n";
+exit;
+
+#-------------------------------------------------------------------#
+# Changelog
+#
+# 0.2 14 Aug 2004
+# first functional version
+#
+# 0.2.1 15 Aug 2004
+# add configuration option for Postgresql driver
+