From: Kern Sibbald Date: Wed, 15 Jun 2005 14:59:12 +0000 (+0000) Subject: Initial revision X-Git-Tag: Release-1.38.0~374 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=5fedadc4bf894d632f8423c04a2076c9c415f3c0;p=bacula%2Fbacula Initial revision git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2126 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/gui/bacula-web/.cvsignore b/gui/bacula-web/.cvsignore new file mode 100644 index 0000000000..75790c67fc --- /dev/null +++ b/gui/bacula-web/.cvsignore @@ -0,0 +1 @@ +%%*.php diff --git a/gui/bacula-web/CONTACT b/gui/bacula-web/CONTACT new file mode 100644 index 0000000000..edc09b93b8 --- /dev/null +++ b/gui/bacula-web/CONTACT @@ -0,0 +1,2 @@ + +Juan Luis Francés, bacula_list AT veloxia.com diff --git a/gui/bacula-web/COPYING b/gui/bacula-web/COPYING new file mode 100644 index 0000000000..960fe7469f --- /dev/null +++ b/gui/bacula-web/COPYING @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/gui/bacula-web/ChangeLog b/gui/bacula-web/ChangeLog new file mode 100644 index 0000000000..fc6c64a846 --- /dev/null +++ b/gui/bacula-web/ChangeLog @@ -0,0 +1,24 @@ +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". diff --git a/gui/bacula-web/README b/gui/bacula-web/README new file mode 100644 index 0000000000..30e00570d4 --- /dev/null +++ b/gui/bacula-web/README @@ -0,0 +1,67 @@ +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 diff --git a/gui/bacula-web/TODO b/gui/bacula-web/TODO new file mode 100644 index 0000000000..7c22ebdeb9 --- /dev/null +++ b/gui/bacula-web/TODO @@ -0,0 +1,22 @@ +- 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. diff --git a/gui/bacula-web/array_fill.func.php b/gui/bacula-web/array_fill.func.php new file mode 100644 index 0000000000..d6c23c823b --- /dev/null +++ b/gui/bacula-web/array_fill.func.php @@ -0,0 +1,14 @@ + \ No newline at end of file diff --git a/gui/bacula-web/classes.inc b/gui/bacula-web/classes.inc new file mode 100644 index 0000000000..4f48e12567 --- /dev/null +++ b/gui/bacula-web/classes.inc @@ -0,0 +1,405 @@ +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 "
";
+//					print_r ($this->clientes);
+//					echo "
"; + + + $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 "
";
+//						print_r ($spr2);
+//						echo "
"; + + 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:
"; +// echo "
";
+//					print_r ($whole_result);
+//					echo "
"; + 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 diff --git a/gui/bacula-web/configs/.htaccess b/gui/bacula-web/configs/.htaccess new file mode 100644 index 0000000000..8d2f25636d --- /dev/null +++ b/gui/bacula-web/configs/.htaccess @@ -0,0 +1 @@ +deny from all diff --git a/gui/bacula-web/configs/bacula.conf b/gui/bacula-web/configs/bacula.conf new file mode 100644 index 0000000000..85ad3748dd --- /dev/null +++ b/gui/bacula-web/configs/bacula.conf @@ -0,0 +1,67 @@ +# 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 + diff --git a/gui/bacula-web/external_packages/phplot/ChangeLog b/gui/bacula-web/external_packages/phplot/ChangeLog new file mode 100644 index 0000000000..9110149ff7 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/ChangeLog @@ -0,0 +1,1392 @@ +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 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 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 + diff --git a/gui/bacula-web/external_packages/phplot/LICENSE.GPL b/gui/bacula-web/external_packages/phplot/LICENSE.GPL new file mode 100644 index 0000000000..5b6e7c66c2 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/LICENSE.GPL @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/gui/bacula-web/external_packages/phplot/LICENSE.PHP_3_0 b/gui/bacula-web/external_packages/phplot/LICENSE.PHP_3_0 new file mode 100644 index 0000000000..ffc1ab71f3 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/LICENSE.PHP_3_0 @@ -0,0 +1,68 @@ +-------------------------------------------------------------------- + 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 + ". + +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 . + +This product includes the Zend Engine, freely available at +. diff --git a/gui/bacula-web/external_packages/phplot/README b/gui/bacula-web/external_packages/phplot/README new file mode 100644 index 0000000000..b571f13ee3 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/README @@ -0,0 +1,45 @@ +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("") where is png, gif, jpeg, ... + + or edit the file phplot.php and change the line + + var $file_format = ""; + +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. diff --git a/gui/bacula-web/external_packages/phplot/doc/imgs/graph1.png b/gui/bacula-web/external_packages/phplot/doc/imgs/graph1.png new file mode 100644 index 0000000000..3b5a1c205a Binary files /dev/null and b/gui/bacula-web/external_packages/phplot/doc/imgs/graph1.png differ diff --git a/gui/bacula-web/external_packages/phplot/doc/imgs/graph2.png b/gui/bacula-web/external_packages/phplot/doc/imgs/graph2.png new file mode 100644 index 0000000000..ff0e80beb8 Binary files /dev/null and b/gui/bacula-web/external_packages/phplot/doc/imgs/graph2.png differ diff --git a/gui/bacula-web/external_packages/phplot/doc/imgs/graph3.png b/gui/bacula-web/external_packages/phplot/doc/imgs/graph3.png new file mode 100644 index 0000000000..e437c8789e Binary files /dev/null and b/gui/bacula-web/external_packages/phplot/doc/imgs/graph3.png differ diff --git a/gui/bacula-web/external_packages/phplot/doc/imgs/phplot-dia.png b/gui/bacula-web/external_packages/phplot/doc/imgs/phplot-dia.png new file mode 100644 index 0000000000..eac14eb27d Binary files /dev/null and b/gui/bacula-web/external_packages/phplot/doc/imgs/phplot-dia.png differ diff --git a/gui/bacula-web/external_packages/phplot/doc/imgs/qstart_fig1.png b/gui/bacula-web/external_packages/phplot/doc/imgs/qstart_fig1.png new file mode 100644 index 0000000000..08fc68bc3b Binary files /dev/null and b/gui/bacula-web/external_packages/phplot/doc/imgs/qstart_fig1.png differ diff --git a/gui/bacula-web/external_packages/phplot/doc/imgs/qstart_fig2.png b/gui/bacula-web/external_packages/phplot/doc/imgs/qstart_fig2.png new file mode 100644 index 0000000000..5deafe4b04 Binary files /dev/null and b/gui/bacula-web/external_packages/phplot/doc/imgs/qstart_fig2.png differ diff --git a/gui/bacula-web/external_packages/phplot/doc/imgs/qstart_fig3.png b/gui/bacula-web/external_packages/phplot/doc/imgs/qstart_fig3.png new file mode 100644 index 0000000000..c98f692c52 Binary files /dev/null and b/gui/bacula-web/external_packages/phplot/doc/imgs/qstart_fig3.png differ diff --git a/gui/bacula-web/external_packages/phplot/doc/imgs/qstart_fig4.png b/gui/bacula-web/external_packages/phplot/doc/imgs/qstart_fig4.png new file mode 100644 index 0000000000..f6c6872c0a Binary files /dev/null and b/gui/bacula-web/external_packages/phplot/doc/imgs/qstart_fig4.png differ diff --git a/gui/bacula-web/external_packages/phplot/doc/index.php b/gui/bacula-web/external_packages/phplot/doc/index.php new file mode 100644 index 0000000000..4105dae223 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/doc/index.php @@ -0,0 +1,153 @@ + + + + + Welcome to PHPlot + + + + +

Welcome to PHPlot 5.0

+ + + + + +
+

+ PHPlot is a PHP4 class for on the fly graphs + generation. It was started by + Afan Ottenheimer in 2000 as an + opensource project, and is now co-developed with + Miguel de Benito thanks to + sourceforge. It is distributed under + the terms of the + GNU General Public License, + and the PHP license. You can always + obtain the latest source from the + sourceforge project page, please do also check CVS, we try to have it always working + there. +

+

For further information, please check + our website +

+
+ + + +
Example line graph with labels, legend + and left and lower axis titles.
+
+ + +

Features

+ + + + + +
+ + + +
Example 3d pie chart.
+
+

+ Here goes a (incomplete) list, in no particular order.: +

    +
  • Several different graph types: lines, bars, points, areas, pie, squared.
  • +
  • text-data, data only and data-error data types accepted.
  • +
  • 3D shading for pie and bar graphs.
  • +
  • Different line types: solid and wholly customizable dashed ones.
  • +
  • Can draw error margins along y-axis when supplied in data.
  • +
  • Highly customizable canvas: titles, labels and ticks can be + placed anywhere, with any color and everything gets automagically placed without overlapping.
  • +
  • Vertical and horizontal grids.
  • +
  • Legend. Different types on the works.
  • +
  • TrueType font support.
  • +
  • Linear and logaritmic scales.
  • +
  • Several output formats: jpeg, png, gif, wbmp (those supported by your GD)
  • +
+ And here a short to-do/whishlist: +
    +
  • Horizontal bars.
  • +
  • Simple isometric 3D plots.
  • +
  • Automatic placement of several plots in one image.
  • +
  • Better or automatic management of many drawing options (ticks, labels, etc.)
  • +
  • Subclassing for optimisation: move features into subclasses for optional use + and leave a fast core.
  • +
+

+
+ + +

Requirements

+

+We are not sure about exact requirements, but at least PHP 4.1.0 and +GD Lib 2 are necessary. Feedback is welcome. +

+ + +

Quick start

+

You can rush for a quick start here.

+ + +

Tests and examples

+

+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: +

+

+ + +

Internals

+

+Description of the use and inner workings of PHPlot: +

+

+ + +

The Authors

+

+

+

+ +

$Id$

+ + diff --git a/gui/bacula-web/external_packages/phplot/doc/internal_functions.html b/gui/bacula-web/external_packages/phplot/doc/internal_functions.html new file mode 100644 index 0000000000..90895c0d7c --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/doc/internal_functions.html @@ -0,0 +1,269 @@ + + +PHPlot Internal Functions + + + +

PHPlot Internal Functions

+ +

DrawArea() +
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.
Colors and border colors for each of the y1, y2, ... is set +by SetDataColors($which_data,$which_border) +This function is called if +you use SetPlotType("area") and SetDataType("data-data") + + +

DrawAreaSeries() +
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.
Colors and border colors for each of the y1, y2, ... is set +by SetDataColors($which_data,$which_border) +This function is called if +you use SetPlotType("area") and SetDataType("text-data") + +

DrawBackground() +
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 SetBackgroundColor and SetImageArea for setting +parameters. + +

DrawBars() +
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.
Colors and border colors for each of the y1, y2, ... is set +by SetDataColors($which_data,$which_border) +This function is called if +you use SetPlotType("bars") and SetDataType("text-data") + +

DrawDashedLine($x1,$y1,$x2,$y2,$dashed, $space, $color) +
Internal Function: Called instead of ImageLine when line_style = 'dashed' +line_style is set by SetLineStyles All variables passed to DrawDashedLine +are in pixel coordinates. + +

DrawDots() +
Internal Function: Draw Dots as defined by SetPointType 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.
Colors and border colors for each +y1, y2, , ... is set by SetDataColors($which_data,$which_border) +This function is called if +you use SetPlotType("dots") and SetDataType("data-data") + +

DrawDotSeries() +
Internal Function: Draw Dots as defined by SetPointType 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.
+Colors and border colors +for each y1, y2, , ... is set by SetDataColors($which_data,$which_border) +This function is called if +you use SetPlotType("dots") and SetDataType("text-data") + +

DrawDotsError() +
Internal Function: Draw Dots and Error Bars as defined by SetPointType 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 SetDataColors($which_data,$which_border) +The shape of the error bars is defined by SetErrorBarShape($which_ebs) +and SetErrorBarSize($which_ebs)
+This function is called if +you use SetPlotType("dots") and SetDataType("data-data-error") + +

DrawError($error_message) +
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. + +

DrawGraph() +
Internal Function: This is th last function called after you have set up +all the parameters of the graph see Set.... functions below. + +

DrawHorizontalTicks() +
Internal Function: Draw the ticks on the X axis. +The distance between ticks can be defined in a number of ways. Note: +that for text-data data its best to let the program handle the +distance between ticks - the default is 1. (Text-data data is data where the data is evenly spaced over +the x axis, no x-value is entered) + +

DrawImageBorder() +
Internal Function: Draw the border around the entire image. Currently this +generates the raised border look around the image. + +

DrawLabels() +
Internal Function: Draw the Title, X-axis label, and the Y-axis label. This +really just calls DrawTitle, DrawXLabel, and DrawYLabel. + +

DrawLegend(x,y,type) +
Internal Function: Draw the Legend. See SetLegendPixels() + +

DrawLines() +
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 SetDataColors($which_data,$which_border) +This function is called if +you use SetPlotType("lines") and SetDataType("data-data") +
+ +

DrawLineSeries() +
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.
Colors and border colors for each of the y1, y2, ... is set +by SetDataColors($which_data,$which_border) +This function is called if +you use SetPlotType("lines") and SetDataType("text-data") + +

DrawLinesError() +
Internal Function: Lines and Error Bars as defined by SetPointType 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 SetDataColors($which_data,$which_border) +The shape of the error bars is defined by SetErrorBarShape($which_ebs) +and SetErrorBarSize($which_ebs) +This function is called if +you use SetPlotType("lines") and SetDataType("data-data-error") + +

DrawPieChart() +
Internal Function: Draw pie chart. Data is in text-data format. $data[] must +already been defined as $data[] = array("label",y1,y2,y3,...)
+Colors and border colors for each of the y1, y2, ... is set +by SetDataColors($which_data,$which_border) +This function is called if +you use SetPlotType("pie") and SetDataType("text-data") + +

DrawPlotAreaBackground() +
Internal Function: Draw the Background - in the color as defined by X +and in an area as defined by X + +

DrawPlotBorder() +
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 +DrawVerticalTicks() and DrawXAxis() + +

DrawTitle() +
Internal Function: This will draw the title as set by +SetTitle and +SetTitleColor. This is also affected by SetUseTTF +to show how the title appears. + + +

DrawVerticalTicks() +
Internal Function: Called by DrawPlotBorder. The spacing between the ticks +is automatically set unless you have previously set the increment +by + SetNumVertTicks($which_nt) +or + SetVertTickIncrements but not both. + +

DrawXAxis() +
Internal Function: Draw the horizontal X axis at the world position X=0. + +

DrawXLabel() +
Internal Function: Called from DrawLabels. Draws the label of the X-Axis. + +

DrawYErrorBar($x_world,$y_world,$error_height,$error_bar_type,$color) +
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). + +

DrawYLabel() +
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. + +

FindDataLimits() +
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. + +

InitImage() +
Internal Function: An internal function called to set the +image pointer for GD. + +

PrintError($error_message) +
Internal Function: Prints the given error message to stdout. The function +is used for fatal errors that do not allow for creating an image. + +

PrintImage() +
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 SetFileFormat() + +

SetColor($color_asked) +
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).
+ +

SetDefaultColors() +
Internal Function: Sets the default colors when first defining an image. +Overridden by functions like SetPlotBgColor, + SetBackgroundColor, + SetTextColor, + SetGridColor, + SetLightGridColor, + SetTickColor, and + SetTitleColor + +

SetDrawYGrid($which_dyg) +
Internal Function: 1 = Draw the Y grid. Anything else, don't draw the Y grid. + +

SetEqualXCoord() +
Internal Function: For text-data graphs set the spacing between +data points on the x-axis. + +

SetMargins() +
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(). + +

SetTranslation() +
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. + +

SetXLabelHeight() +
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. + + +

SetYLabelWidth() +
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. + + +

TTFBBoxSize($size, $angle, $font, $string) +
Internal Function: Calculate the size of the box which encloses the +text string $string using font $font, +angle $angle and size $size. This is +an internal function which is not called unless use_ttf is +set to 1. + +

xtr($x_world) +
Internal Function: Translate into x-pixels coordinates from x world coordinates. + +

ytr($y_world) +
Internal Function: Translate into y-pixels coordinates from y world coordinates. + + + + + + + + + diff --git a/gui/bacula-web/external_packages/phplot/doc/quickstart.html b/gui/bacula-web/external_packages/phplot/doc/quickstart.html new file mode 100644 index 0000000000..8e4323a6a0 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/doc/quickstart.html @@ -0,0 +1,458 @@ + + + + + PHPLOT Quick Start and Examples + + + + + + + + + + + + + + +

PHPlot Quick Start and Examples

+ +

Afan Ottenheimer, January 7, 2001

+

Miguel de Benito, January 21, 2004

+

Contents

+ + +

Introduction

+ +

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. +

+ +

First, lets discuss how PHPlot works in general with some +terminology. A PHPlot image can consist of several graphs , +each graph consisting of several elements. +You define an object (e.g. a variable like $graph), +select the properties of the element that compose the graph and "Draw" +what you want into the object. Tipically by selecting the plot type with +SetPlotType and at the end calling DrawGraph. You +can also directly invoke PrintImage, which either inserts the image +into the data streaming to the client or writes it to disk. +

+

In PHPlot there are World coordinates, which are the XY coordinates +relative to the axis origin, in the units of the data set; and +device (pixel) coordinates which in GD are relative to the +origin at the upper left side of the image. +

+

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. +

+

Since PHP is a server scripted language you have several options +for how you can "Print" the image. You can:

+
    +
  1. Write the image as a file on the server. (You specify a file + name and can specify caching as well)
  2. +
  3. Have the raw data stream out within an HTML file, as <IMG + SRC="my_PHPlot_code.php">
  4. +
  5. 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 .
  6. +
+

This document explains how to create plots using PHPlot from a +PHP script. Information on PHP can be found at www.php.net. +Information about the GD library which PHP uses to create images can +be found at www.boutell.com. +More information about PHPlot can be found at www.PHPlot.com.

+ +

Creating the Object

+ +

You create a PHPlot object by first including the code to be used +and then defining the variable:

+
+
<?php
+include('./phplot.php');  // here we include the PHPlot code 
+$graph = new PHPlot();   // here we define the variable graph 
+
+//Rest of code goes below
+?>
+
+ +

The above code assigns the PHPlot object to the variable $graph.

+ +

Now we have created a PHPlot graph object, we can access +information about the object and manipulate the object. In these +following examples, $graph is the variable/object we created +above.

+ +

Back to top

+ + +

Real World Examples

+

Case 1: A simple graph

+ +

We will start with a simple line graph.

+
+
<?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 PrintImage part for you 
+?>
+
+ +

And that's it! What we get is the following graph:

+ +
+ figure 1 +
Figure 1 +
+ +

That's a great start, but now we'd like to specify the width and height +of the image.

+ + +

Case 1a: Different Size Images and Titles

+

+Lets say we want it to have a width of 300 and a height of 250 pixels. +So instead of having the line

+ $graph = new PHPlot();

+we replace it with

+ $graph = new PHPlot(300,250);

+and you have specified the size in pixels of the image to be created. +A couple of things to note: +

+
    +
  • The default is not to use TTF fonts.
  • +
  • Since there was only one graph on the image we didn't have to + specify PrintImage, DrawGraph took care of it for us. +
  • +
  • + We did not specify the data type. If you do not specify the data + type PHPlot assumes text-data. +
  • +
  • + We did not specify the file type (gif, png, jpg, ...) . + PHPlot 5.0 assumes PNG image formats. +
  • +
  • + The data is passed in as an array of arrays. This may seem awkward + now, but as we add functionality this will be beneficial. +
  • +
+

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 $graph before printing the image. We achieve this with: +

+
+
<?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
+
+
+?>
+
+
+
+ Figure 2 +
+ +

Note that in order for the "\n" and "\r " to be interpreted as +new line/new return characters for SetTitle you have to +enclose the string in double quotes.

+ +

Case 2: Multiple Lines per Graph

+

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', y1, y2, y3, +...) This is very convenient when working with rows of data from databases. +
+Now our data will have three Y values for each position on the X axis +

+
+
<?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();
+?>
+
+

Which gives us:

+
+ +
Figure 3 +
+ +

Notice that each set of Y data gets a different color. +Also the missing data point is skipped, this behaviour can be adjusted with +SetDrawBrokenLines(TRUE); +

+

+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. +

+

Back to top

+ + +

Customization

+

Valid types of plots (as of PHPlot 5.0): +

    +
  • bars (with optional shadows)
  • +
  • lines
  • +
  • linepoints (a faster way of plotting when + you want both points and lines)
  • +
  • area
  • +
  • points (lots of point types here)
  • +
  • pie (2D or 3D)
  • +
  • thinbarline (sometimes also called impulse)
  • +
  • error bar (which can also be used for stock market data graphs)
  • +
  • squared (for binary data)
  • +
+

+

You specify which type with the SetPlotType function. +We'll look at that function with bars and lines in the next example when we look at +multiple graphs per image. +

+

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): +

    +
  • SetXTickPos()
  • +
  • SetYTickPos()
  • +
  • SetXTickLength()
  • +
  • SetYTickLength()
  • +
  • SetXTickCrossing()
  • +
  • SetYTickCrossing()
  • +
  • SetXTickIncrement()
  • +
  • SetYTickIncrement()
  • +
  • SetNumXTicks()
  • +
  • SetNumYticks()
  • +
  • SetSkipTopTick()
  • +
  • SetSkipBottomTick()
  • + +
  • SetDrawXGrid()
  • +
  • SetDrawYGrid()
  • +
  • SetDrawDashedGrid()
  • +
  • SetDrawXDataLabelLines()
  • +
  • SetDrawYDataLabelLines() (not yet implemented)
  • +
  • SetXDataLabelPos()
  • +
  • SetYDataLabelPos()
  • +
  • SetXLabelAngle()
  • +
  • SetYLabelAngle()
  • +
  • SetXLabelType()
  • +
  • SetYLabelType()
  • +
+As we go further we will introduce some of these features of PHPlot. +For more specialized examples, please go back to the index and +look in the examples section. +

+ +

Back to top

+ +

Case 3: Multiple Graphs per Image

+ +

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 +not print the image at the same time as the draw command. Now +we want it to wait for the explicit PrintImage function call. +To tell PHPlot this is the way we want to work, we use the +SetPrintImage function. +SetPrintImage(TRUE) is the default, and tells to draw the image +when DrawGraph is called. To turn this +off we use SetPrintImage(FALSE).

+

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. +

+

To specify in pixels the placement of each graph we use +SetNewPlotAreaPixels. The format is +SetNewPlotAreaPixels(upper_left_x, upper_left_y, lower_right_x, +lower_right_y) . Again we are using the GD coordinates where 0,0 +is the upper left corner of the image. +

+

In more detail:

+
+
<?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();
+?>
+
+ +

Lets now create an image with 2 graphs on it with some example data.

+ +
+
<?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 PrintImage 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();
+?>
+
+ +



Which gives us:

+ +
+
+ Figure 4
+
+ +

+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. +

+ + +
$Id$
+ + + diff --git a/gui/bacula-web/external_packages/phplot/doc/schema.html b/gui/bacula-web/external_packages/phplot/doc/schema.html new file mode 100644 index 0000000000..458ede2772 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/doc/schema.html @@ -0,0 +1,35 @@ + + + + PHPlot schema + + + + + + +

The Drawing

+

+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 (Miguel) +hope it will help somebody as it did with me when I first began browsing +through the 3000 lines of code Afan had written. +

+

If you are curious, for the drawing I used +Dia a gtk+ diagram creation +sofware which I find easy and suited for my purposes. +

schema
+

+ +

The words

+

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 +quickstart. +

+ +

$Id$

+ + diff --git a/gui/bacula-web/external_packages/phplot/doc/style.css b/gui/bacula-web/external_packages/phplot/doc/style.css new file mode 100644 index 0000000000..ff700e0f5e --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/doc/style.css @@ -0,0 +1,42 @@ +/* $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" } + diff --git a/gui/bacula-web/external_packages/phplot/doc/user_functions.html b/gui/bacula-web/external_packages/phplot/doc/user_functions.html new file mode 100644 index 0000000000..9b529019f3 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/doc/user_functions.html @@ -0,0 +1,316 @@ + + +PHPlot User Functions + + + +

PHPlot User Functions

+ + + + +
+ +

Important functions

+ +

SetDataType($which_dt) +
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. +

+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.

+ +Colors and border colors are set by SetDataColors. 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.

+ +So in PHPLOT the datalabel,x-value,y-value and error are +grouped together as a value array. Then the +entire set of points to be plotted is passed in as a data array +E.g. Data_array = array(value_array_1,value_array_2,....)

+See below for examples of the various data types:
+ +

  • 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
    +
    +$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)
    +);
    +
    +Which will display data points at +(1,1.1), (1,2), (1,3), (1,4), (2,2), (2,3)....
    + +
  • +
  • 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 +
    +$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)
    +);
    +
    +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)... +
  • +
  • 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) +
  • + +

    SetDataValues($which_dv) +
    User Function: Passes the raw data values into the class variable +$this->data_values. This function needs to be called before any +image can be drawn. + +

    SetPlotType($which_pt) +
    User Function: Can be: bars, lines, linepoints, area, points, and pie + +

    SetErrorBarLineWidth($width) +
    Width of the Error Bars in Pixels. If not set then +uses "line_width" to set the width of the error_bar lines. + +

    SetFileFormat($which_file_format) +
    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. + +

    SetUseTTF($which_ttf) +
    User Function: Call this as SetUseTTF(1) when you have TTF compiled into PHP +otherwise call this as SetUseTTF(0) + + +
    + +

    Appearance functions

    + + +

    SetErrorBarShape($which_ebs) +
    User Function: Can be "tee" or "line." If it is tee, then +the half-width of the tee is set by SetErrorBarSize + +

    SetErrorBarSize($which_ebs) +
    User Function: Size in pixels of the Tee shape of the error bar. + +

    SetHorizTickIncrement($which_ti) +
    User Function: Set where to place the X-tick marks. + +

    SetNumHorizTicks($which_nt) +
    User Function: Use this or SetHorizTickIncrements but not both. + +

    SetNumVertTicks($which_nt) +
    User Function: Use this or SetVertTickIncrements but not both. + +

    SetPlotAreaPixels($x1,$y1,$x2,$y2) +
    User Function: You can use this to set the actual size in +pixels of the plot area on the image. + +

    SetPointShape($which_pt) +
    User Function: Can be: rect,circle,diamond,triangle,dot,line,halfline + +

    SetPointSize($which_ps) +
    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. + +

    SetPrecisionX($which_prec) +
    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. + +

    SetPrecisionY($which_prec) +
    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. + +

    SetShading($which_s) +
    User Function: Set the length of the shadows for shading bar charts +The color used is the LightGridColor See SetLightGridColor.
    + +

    SetTickLength($which_tl) +
    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).
    + + +

    SetTitle($title) +
    User Function: Set the title of the graph. Printed at the top +middle of the graph. + +

    SetHorizTickIncrement($which_ti) +
    User Function: Set the distance between tick marks on the X axis. $which_ti +is in world coordinates. + +

    SetVertTickIncrement($which_ti) +
    User Function: Set the distance between tick marks on the Y axis. $which_ti +is in world coordinates. + +

    SetXDatalabelMaxlength($which_xdlm) +
    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. + +

    + +

    SetXGridLabelType($which_xtf) +
    User Function: Can be "time", "title", "none", "default" or "data".
    +time - label is set by the the php command strftime()
    +title - label is treated as text, the first element of the data array.
    +data - label is formateed using php command number_format
    +none - no labelss are printed.
    +default - prints as it is entered.
    +

    + + +

    SetXScaleType($which_xct) +
    Can be "log" or "linear". + +

    SetXTimeFormat($which_xtf) +
    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. +

    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. +

    +The php strtotime() function also comes in handy turning dates into timestamps, especially for parameters to SetPlotAreaWorld(). +

    +Example:
    +$graph->SetPlotAreaWorld(strtotime("October 1"), 0,strtotime("December 15"),10);
    +$graph->SetXGridLabelType("time") ;
    +$graph->SetXTimeFormat("%b %d") ;
    + +

    SetXLabel($xlbl) +
    User Function: Set the label for the X axis. + +

    SetYLabel($ylbl) +
    User Function: Set the label for the Y axis. + +

    SetYScaleType($which_xct) +
    Can be "log" or "linear". + + +
    + +

    Color functions

    + +

    SetBackgroundColor($which_color) +
    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).
    It defaults to array(222,222,222) if +not defined.
    + +

    SetGridColor ($which_color) +
    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).
    + +

    SetLegend($which_legend) +
    $which_legend is an array of text for display in a small box +on the image. If you do not set the position with SetLegendPixels() +then it puts it in the upper right hand side. + +

    SetLegendPixels($which_x,$which_y,$which_type) +
    Pick the upper left corner of the legend box with +$which_x and $which_y in pixels. $which_type is reserved +for future use. + +

    SetLegendWorld($which_x,$which_y,$which_type) +
    Untested and documentation not written. Have Fun! + +

    SetLightGridColor ($which_color) +
    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).
    It defaults to array(222,222,222) if +not defined.
    + +

    SetLineWidth($which_lt) +
    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. + +

    SetLineStyles($which_sls) +
    User Function: Set style of the line to be printed. +This is an array. Currently only 'dashed' and 'solid' are +supported. + +

    SetPlotBgColor($which_color) +
    User Function: Set the Background color of the area on which +the plot is defined. Called from PlotAreaBackground
    +$which_color can be either a name like "black" or an rgb color array +array(int,int,int).
    It defaults to array(222,222,222) if +not defined. + +

    SetTextColor ($which_color) +
    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).
    + +

    SetTickColor ($which_color) +
    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).
    + +

    SetTitleColor($which_color) +
    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).
    + +
    + +

    Data manipulation functions

    + +

    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.

    + +

    DoScaleData($even, $show_in_legend) +
    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.
    + +

    DoMovingAverage($datarow, $interval, $show_in_legend) +
    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. +
    + +
    + +

    not implemented

    + +

    SetCharacterHeight() +
    User Function: Not yet implemented + + + diff --git a/gui/bacula-web/external_packages/phplot/doc/user_internal_functions.html b/gui/bacula-web/external_packages/phplot/doc/user_internal_functions.html new file mode 100644 index 0000000000..bb2346322d --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/doc/user_internal_functions.html @@ -0,0 +1,62 @@ + + +PHPlot User / Internal Functions + + + +

    PHPlot User / Internal Functions

    + + +

    DrawDataLabel($lab,$x_world,$y_world) +
    User Function and Internal Function: Draw a label at the world coordinates of x_world and y_world. + + +

    DrawDot($x_world,$y_world,$dot_type,$color) +
    User Function and Internal Function: Draw one dot at $x_world and $y_world where the world +coordinates (not pixel coordinates). + + +

    DrawXDataLabel($xlab,$xpos) +
    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. + + +

    SetDataColors($which_data,$which_border) +
    If called with $which_data="" it defaults to + $which_data = array("blue","bisque",array(0,176,0)); + $which_border = array("black"); + + +

    SetErrorBarColors($which_data) +
    If not called then the colors are the same as the +colors of the data as set by SetDataColors() +otherwise it sets the colors of the error bars. + +

    SetLabels($xlbl,$ylbl,$title) +
    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 SetXLabel. + + +

    SetNewPlotAreaPixels($x1,$y1,$x2,$y2) +
    Reserved - not used yet. + + + +

    SetPlotAreaWorld($xmin,$ymin,$xmax,$ymax) +
    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.
    You can call this function +as SetPlotAreaWorld("","","","") and it will set the +plot area based on max/min values of data. + + + + + + + + + diff --git a/gui/bacula-web/external_packages/phplot/examples/benjamingothic.ttf b/gui/bacula-web/external_packages/phplot/examples/benjamingothic.ttf new file mode 100644 index 0000000000..61058a6e21 Binary files /dev/null and b/gui/bacula-web/external_packages/phplot/examples/benjamingothic.ttf differ diff --git a/gui/bacula-web/external_packages/phplot/examples/create_chart.php b/gui/bacula-web/external_packages/phplot/examples/create_chart.php new file mode 100644 index 0000000000..37e43cb07c --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/create_chart.php @@ -0,0 +1,167 @@ +This file is intended to be called from format_chart.php, the example-o-matic.". + "Please click here to try it.

    "; + 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); +?> diff --git a/gui/bacula-web/external_packages/phplot/examples/data.php b/gui/bacula-web/external_packages/phplot/examples/data.php new file mode 100644 index 0000000000..b1d1314db9 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/data.php @@ -0,0 +1,27 @@ + diff --git a/gui/bacula-web/external_packages/phplot/examples/data_date.php b/gui/bacula-web/external_packages/phplot/examples/data_date.php new file mode 100644 index 0000000000..4a14d7b5cf --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/data_date.php @@ -0,0 +1,267 @@ + diff --git a/gui/bacula-web/external_packages/phplot/examples/data_date2.php b/gui/bacula-web/external_packages/phplot/examples/data_date2.php new file mode 100644 index 0000000000..37152c7c6f --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/data_date2.php @@ -0,0 +1,267 @@ + diff --git a/gui/bacula-web/external_packages/phplot/examples/data_sample1.php b/gui/bacula-web/external_packages/phplot/examples/data_sample1.php new file mode 100644 index 0000000000..11b8117c1e --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/data_sample1.php @@ -0,0 +1,58 @@ +

    +Data type: (Text-data)
    +

    + + + + + + + + + + + + + +
    Title (x axis)Y data 1Y data 2Y data 3 Y data 4
    + + + + + + + + + +
    + +

    +Graph type: + +

    +
    +Please note when writing your application that the graph
    +types marked with an asterisk only support the data
    +type for this form, "text-data". +
    diff --git a/gui/bacula-web/external_packages/phplot/examples/data_sample2.php b/gui/bacula-web/external_packages/phplot/examples/data_sample2.php new file mode 100644 index 0000000000..e754a039d3 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/data_sample2.php @@ -0,0 +1,52 @@ + +

    +Data type: (data-data)
    + + + + + + + + + + + + + + +
    Title (data label)X dataY data 1Y data 2Y data 3
    + + + + + + + + + +
    + +

    +Graph type: + +

    diff --git a/gui/bacula-web/external_packages/phplot/examples/data_sample3.php b/gui/bacula-web/external_packages/phplot/examples/data_sample3.php new file mode 100644 index 0000000000..46f774b56d --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/data_sample3.php @@ -0,0 +1,58 @@ +

    +Data set as X, Y, E+, E-, Y2, E2+, E2-,...
    + +Data type: (data-data-error) +

    + + + + + + + + +
    Title (data label)X dataY data 1Error +Error -Y data 2Error +Error -
    + + "; + + for ($i = 0; $i < $num_rows; $i++) { + // The label input element must be bigger. + $lines[0] = "\n"; + + // Show s for the rest of the columns + for ($j=1; $j<8; $j++) + $lines[$j] = "\n"; + $groups[$i] = join('', $lines); + } + echo join("
    \n", $groups); + ?> + +
    + +

    +Graph type: + +     +Error bar type: + +

    diff --git a/gui/bacula-web/external_packages/phplot/examples/data_sample4.php b/gui/bacula-web/external_packages/phplot/examples/data_sample4.php new file mode 100644 index 0000000000..5c4d14c16f --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/data_sample4.php @@ -0,0 +1,24 @@ +

    +Data type: data-data calculated from a function. +

    +
    +	$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)); 	
    +	}
    +
    +

    +Chart type: + + +

    diff --git a/gui/bacula-web/external_packages/phplot/examples/data_sample5.php b/gui/bacula-web/external_packages/phplot/examples/data_sample5.php new file mode 100644 index 0000000000..b8859b6345 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/data_sample5.php @@ -0,0 +1,31 @@ +

    +Data type: data-data-error calculated from a function. +

    +
    +    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);
    +    }
    +
    +

    +Chart type: + +     +Error bar type: + + +

    diff --git a/gui/bacula-web/external_packages/phplot/examples/example1.php b/gui/bacula-web/external_packages/phplot/examples/example1.php new file mode 100644 index 0000000000..a134097785 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/example1.php @@ -0,0 +1,16 @@ +SetDataValues($example_data); + + +//Draw it +$graph->DrawGraph(); + +?> diff --git a/gui/bacula-web/external_packages/phplot/examples/example2.php b/gui/bacula-web/external_packages/phplot/examples/example2.php new file mode 100644 index 0000000000..8f06a20dba --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/example2.php @@ -0,0 +1,22 @@ +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(); +?> diff --git a/gui/bacula-web/external_packages/phplot/examples/example3.php b/gui/bacula-web/external_packages/phplot/examples/example3.php new file mode 100644 index 0000000000..a518e1315e --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/example3.php @@ -0,0 +1,32 @@ +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(); +?> diff --git a/gui/bacula-web/external_packages/phplot/examples/example4.php b/gui/bacula-web/external_packages/phplot/examples/example4.php new file mode 100644 index 0000000000..360d2df8aa --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/example4.php @@ -0,0 +1,80 @@ +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(); +?> diff --git a/gui/bacula-web/external_packages/phplot/examples/example6.php b/gui/bacula-web/external_packages/phplot/examples/example6.php new file mode 100644 index 0000000000..405943b297 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/example6.php @@ -0,0 +1,19 @@ +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(); +?> diff --git a/gui/bacula-web/external_packages/phplot/examples/example7.php b/gui/bacula-web/external_packages/phplot/examples/example7.php new file mode 100644 index 0000000000..4b93ee8df2 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/example7.php @@ -0,0 +1,33 @@ +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(); +?> diff --git a/gui/bacula-web/external_packages/phplot/examples/example8.php b/gui/bacula-web/external_packages/phplot/examples/example8.php new file mode 100644 index 0000000000..d60c053957 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/example8.php @@ -0,0 +1,61 @@ +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(); +?> diff --git a/gui/bacula-web/external_packages/phplot/examples/example9.php b/gui/bacula-web/external_packages/phplot/examples/example9.php new file mode 100644 index 0000000000..32865c1526 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/example9.php @@ -0,0 +1,35 @@ +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(); + +?> diff --git a/gui/bacula-web/external_packages/phplot/examples/format_chart.php b/gui/bacula-web/external_packages/phplot/examples/format_chart.php new file mode 100644 index 0000000000..5e2f4b899c --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/format_chart.php @@ -0,0 +1,345 @@ + + + + Example-o-matic + + + + + + +

    PHPlot test graph form

    + +

    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. +

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Data Settings
    +

    + Data type: [ + text-data | + data-data | + function | + data-data-error | + randfunction ] +

    + +
    +
    +

    Optional values

    +
    +
    Sizes
    Width of graph in pixels:
    Height of graph in pixels:
    Maximum height of graph in y axis units:
    Minimum height of graph in y axis units:
    Titles and data labels
    Title:
    Y axis title:
    Y axis title position: + +
    Y axis data labels position: + +
    Y axis labels angle:
    X axis title:
    X axis title position: + +
    X axis data labels position: + +
    X axis labels angle:
    Grid and ticks
    Grid drawn: + +
    Dashed grid? + +
    X axis ticks length:
    X axis ticks crossing:
    X axis ticks position: + +
    X axis tick labels position: + +
    Y axis ticks length:
    Y axis ticks crossing:
    Y axis ticks position: + +
    Y axis tick labels position: + +
    X tick increment:
    Y tick increment:
    Other
    X axis position:
    Y axis position:
    Plot Border: + +
    Shade height (0 for none):
    Plot line width:
    Error bar line width:
    Point Type: + +
    Point Size:
    Draw broken lines with missing Y data: + +
    Use TrueType font: + +
    File format: + +
    +
    +
    + +

    +Please visit PHPlot's site, the +sourceforge project page, +or see more php code and examples +by Afan Ottenheimer of jeonet. +

    + +

    $Id$

    + + diff --git a/gui/bacula-web/external_packages/phplot/examples/inline_image.php b/gui/bacula-web/external_packages/phplot/examples/inline_image.php new file mode 100644 index 0000000000..16a5a352c5 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/inline_image.php @@ -0,0 +1,28 @@ + + ************************************************* + * This file is meant to be called only from the * + * test page * + * It will fail if called by itself. * + ************************************************* + +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(); +?> diff --git a/gui/bacula-web/external_packages/phplot/examples/test_setup.php b/gui/bacula-web/external_packages/phplot/examples/test_setup.php new file mode 100644 index 0000000000..b8860ca978 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/examples/test_setup.php @@ -0,0 +1,67 @@ + + + + + PHPlot graphic formats test + + + + + + +

    PHPlot test graph form

    + +

    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 +

    PHPlot graphic formats test

    + +

    +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. +

    + +
    + + + + + + + + + +
    PNG graphics
    +"; + +?> +
    JPEG graphics
    +"; +?> +
    GIF graphics
    +"; +?> +
    BMP graphics
    +"; +?> +
    +
    + + + diff --git a/gui/bacula-web/external_packages/phplot/phplot.php b/gui/bacula-web/external_packages/phplot/phplot.php new file mode 100644 index 0000000000..3c2dae113f --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/phplot.php @@ -0,0 +1,4086 @@ + + * + */ + + +// 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 "

    Fatal error: $error_message

    "; + 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 +} +?> diff --git a/gui/bacula-web/external_packages/phplot/phplot_data.php b/gui/bacula-web/external_packages/phplot/phplot_data.php new file mode 100644 index 0000000000..37351504c1 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/phplot_data.php @@ -0,0 +1,258 @@ +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 +?> diff --git a/gui/bacula-web/external_packages/phplot/rgb.inc.php b/gui/bacula-web/external_packages/phplot/rgb.inc.php new file mode 100644 index 0000000000..3353e28e50 --- /dev/null +++ b/gui/bacula-web/external_packages/phplot/rgb.inc.php @@ -0,0 +1,744 @@ + 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) +); +?> diff --git a/gui/bacula-web/external_packages/smarty/COPYING.lib b/gui/bacula-web/external_packages/smarty/COPYING.lib new file mode 100644 index 0000000000..3b204400cf --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/COPYING.lib @@ -0,0 +1,458 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 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. + + 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. + + 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. + + 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 diff --git a/gui/bacula-web/external_packages/smarty/Config_File.class.php b/gui/bacula-web/external_packages/smarty/Config_File.class.php new file mode 100644 index 0000000000..c7e30bd346 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/Config_File.class.php @@ -0,0 +1,389 @@ + + * @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); + } + /**#@-*/ +} + +?> diff --git a/gui/bacula-web/external_packages/smarty/Smarty.class.php b/gui/bacula-web/external_packages/smarty/Smarty.class.php new file mode 100644 index 0000000000..cdaf396a06 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/Smarty.class.php @@ -0,0 +1,1938 @@ + + * @author Andrei Zmievski + * @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. + *

      + *
    • NONE => no debugging control allowed
    • + *
    • URL => enable debugging when SMARTY_DEBUG is found in the URL.
    • + *
    + * @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. + *
      + *
    • 0 = no caching
    • + *
    • 1 = use class cache_lifetime value
    • + *
    • 2 = use cache_lifetime in cache file
    • + *
    + * @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. + *
      + *
    • 0 = always regenerate cache
    • + *
    • -1 = never expires
    • + *
    + * + * @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 "" tags in templates. + * possible values: + *
      + *
    • SMARTY_PHP_PASSTHRU -> print tags as plain text
    • + *
    • SMARTY_PHP_QUOTE -> escape tags as entities
    • + *
    • SMARTY_PHP_REMOVE -> remove php tags
    • + *
    • SMARTY_PHP_ALLOW -> execute php tags
    • + *
    + * + * @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: array('escape:"htmlall"'); + * + * @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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/Smarty_Compiler.class.php b/gui/bacula-web/external_packages/smarty/Smarty_Compiler.class.php new file mode 100644 index 0000000000..140fa2ee2b --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/Smarty_Compiler.class.php @@ -0,0 +1,2258 @@ + + * @author Andrei Zmievski + * @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.'%%%', ''."\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', ''."\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 = "_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 = "_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 = "\n"; + $template_header .= $plugins_code; + $this->_plugin_info = array(); + $this->_plugins_code = $plugins_code; + } + + if ($this->_init_smarty_vars) { + $template_header .= "\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 "assign('" . $this->_dequote($_tag_attrs['assign']) . "', $_return ); ?>\n"; + } else { + 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 ''; + + 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 ''; + + 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 ""; + break; + + case '/section': + $_open_tag = $this->_pop_tag('section'); + if ($_open_tag == 'sectionelse') + return ""; + else + return ""; + + case 'foreach': + $this->_push_tag('foreach'); + return $this->_compile_foreach_start($tag_args); + break; + + case 'foreachelse': + $this->_push_tag('foreachelse'); + return ""; + + case '/foreach': + $_open_tag = $this->_pop_tag('foreach'); + if ($_open_tag == 'foreachelse') + return ""; + else + return ""; + 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 ""\'", "\\"=>"\\\\")) . "'; ?>" . $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 ''; + } + 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 = '_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 = '_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 = '_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 = '_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 '" . $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 "" . $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 = '_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 "" . $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 = '_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 = '_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 = ""; + $this->_capture_stack[] = array($buffer, $assign); + } else { + list($buffer, $assign) = array_pop($this->_capture_stack); + $output = "_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 ''; + else + return ''; + } + + + 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('~(?:\`(?_dvar_guts_regexp . '(?:' . $this->_obj_ext_regexp . ')*\`)|(?:(?_parse_var(str_replace('`','',$_var)) . ')."', $var_expr); + } + $_return = preg_replace('~\.""|(?_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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/debug.tpl b/gui/bacula-web/external_packages/smarty/debug.tpl new file mode 100644 index 0000000000..7f1c9d4258 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/debug.tpl @@ -0,0 +1,64 @@ +{* Smarty *} + +{* debug.tpl, last updated version 2.0.1 *} + +{assign_debug_info} + +{if isset($_smarty_debug_output) and $_smarty_debug_output eq "html"} + + + + {section name=templates loop=$_debug_tpls} + + {sectionelse} + + {/section} + + {section name=vars loop=$_debug_keys} + + {sectionelse} + + {/section} + + {section name=config_vars loop=$_debug_config_keys} + + {sectionelse} + + {/section} +
    Smarty Debug Console
    included templates & config files (load time in seconds):
    {section name=indent loop=$_debug_tpls[templates].depth}   {/section}{$_debug_tpls[templates].filename|escape:html}{if isset($_debug_tpls[templates].exec_time)} ({$_debug_tpls[templates].exec_time|string_format:"%.5f"}){if %templates.index% eq 0} (total){/if}{/if}
    no templates included
    assigned template variables:
    {ldelim}${$_debug_keys[vars]}{rdelim}{$_debug_vals[vars]|@debug_print_var}
    no template variables assigned
    assigned config file variables (outer template scope):
    {ldelim}#{$_debug_config_keys[config_vars]}#{rdelim}{$_debug_config_vals[config_vars]|@debug_print_var}
    no config vars assigned
    + +{else} + +{/if} diff --git a/gui/bacula-web/external_packages/smarty/internals/core.assemble_plugin_filepath.php b/gui/bacula-web/external_packages/smarty/internals/core.assemble_plugin_filepath.php new file mode 100644 index 0000000000..690d3ddbc2 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.assemble_plugin_filepath.php @@ -0,0 +1,67 @@ +plugins_dir as $_plugin_dir) { + + $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename; + + // see if path is relative + if (!preg_match("/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/", $_plugin_dir)) { + $_relative_paths[] = $_plugin_dir; + // relative path, see if it is in the SMARTY_DIR + if (@is_readable(SMARTY_DIR . $_plugin_filepath)) { + $_return = SMARTY_DIR . $_plugin_filepath; + break; + } + } + // try relative to cwd (or absolute) + if (@is_readable($_plugin_filepath)) { + $_return = $_plugin_filepath; + break; + } + } + + if($_return === false) { + // still not found, try PHP include_path + if(isset($_relative_paths)) { + foreach ((array)$_relative_paths as $_plugin_dir) { + + $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename; + + $_params = array('file_path' => $_plugin_filepath); + require_once(SMARTY_CORE_DIR . 'core.get_include_path.php'); + if(smarty_core_get_include_path($_params, $smarty)) { + $_return = $_params['new_file_path']; + break; + } + } + } + } + $_filepaths_cache[$_plugin_filename] = $_return; + return $_return; +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.assign_smarty_interface.php b/gui/bacula-web/external_packages/smarty/internals/core.assign_smarty_interface.php new file mode 100644 index 0000000000..7e65a73ec2 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.assign_smarty_interface.php @@ -0,0 +1,43 @@ + + * Name: assign_smarty_interface
    + * Purpose: assign the $smarty interface variable + * @param array Format: null + * @param Smarty + */ +function smarty_core_assign_smarty_interface($params, &$smarty) +{ + if (isset($smarty->_smarty_vars) && isset($smarty->_smarty_vars['request'])) { + return; + } + + $_globals_map = array('g' => 'HTTP_GET_VARS', + 'p' => 'HTTP_POST_VARS', + 'c' => 'HTTP_COOKIE_VARS', + 's' => 'HTTP_SERVER_VARS', + 'e' => 'HTTP_ENV_VARS'); + + $_smarty_vars_request = array(); + + foreach (preg_split('!!', strtolower($smarty->request_vars_order)) as $_c) { + if (isset($_globals_map[$_c])) { + $_smarty_vars_request = array_merge($_smarty_vars_request, $GLOBALS[$_globals_map[$_c]]); + } + } + $_smarty_vars_request = @array_merge($_smarty_vars_request, $GLOBALS['HTTP_SESSION_VARS']); + + $smarty->_smarty_vars['request'] = $_smarty_vars_request; +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.create_dir_structure.php b/gui/bacula-web/external_packages/smarty/internals/core.create_dir_structure.php new file mode 100644 index 0000000000..999cf59302 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.create_dir_structure.php @@ -0,0 +1,79 @@ +_dir_perms) && !is_dir($_new_dir)) { + $smarty->trigger_error("problem creating directory '" . $_new_dir . "'"); + return false; + } + $_new_dir .= '/'; + } + } +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.display_debug_console.php b/gui/bacula-web/external_packages/smarty/internals/core.display_debug_console.php new file mode 100644 index 0000000000..a5d72913c0 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.display_debug_console.php @@ -0,0 +1,61 @@ + + * Name: display_debug_console
    + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.get_include_path.php b/gui/bacula-web/external_packages/smarty/internals/core.get_include_path.php new file mode 100644 index 0000000000..43432412b8 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.get_include_path.php @@ -0,0 +1,44 @@ + diff --git a/gui/bacula-web/external_packages/smarty/internals/core.get_microtime.php b/gui/bacula-web/external_packages/smarty/internals/core.get_microtime.php new file mode 100644 index 0000000000..f1a28e0425 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.get_microtime.php @@ -0,0 +1,23 @@ + diff --git a/gui/bacula-web/external_packages/smarty/internals/core.get_php_resource.php b/gui/bacula-web/external_packages/smarty/internals/core.get_php_resource.php new file mode 100644 index 0000000000..786d4e78e8 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.get_php_resource.php @@ -0,0 +1,80 @@ +trusted_dir; + $smarty->_parse_resource_name($params, $smarty); + + /* + * Find out if the resource exists. + */ + + if ($params['resource_type'] == 'file') { + $_readable = false; + if(file_exists($params['resource_name']) && is_readable($params['resource_name'])) { + $_readable = true; + } else { + // test for file in include_path + $_params = array('file_path' => $params['resource_name']); + require_once(SMARTY_CORE_DIR . 'core.get_include_path.php'); + if(smarty_core_get_include_path($_params, $smarty)) { + $_include_path = $_params['new_file_path']; + $_readable = true; + } + } + } else if ($params['resource_type'] != 'file') { + $_template_source = null; + $_readable = is_callable($smarty->_plugins['resource'][$params['resource_type']][0][0]) + && call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][0], + array($params['resource_name'], &$_template_source, &$smarty)); + } + + /* + * Set the error function, depending on which class calls us. + */ + if (method_exists($smarty, '_syntax_error')) { + $_error_funcc = '_syntax_error'; + } else { + $_error_funcc = 'trigger_error'; + } + + if ($_readable) { + if ($smarty->security) { + require_once(SMARTY_CORE_DIR . 'core.is_trusted.php'); + if (!smarty_core_is_trusted($params, $smarty)) { + $smarty->$_error_funcc('(secure mode) ' . $params['resource_type'] . ':' . $params['resource_name'] . ' is not trusted'); + return false; + } + } + } else { + $smarty->$_error_funcc($params['resource_type'] . ':' . $params['resource_name'] . ' is not readable'); + return false; + } + + if ($params['resource_type'] == 'file') { + $params['php_resource'] = $params['resource_name']; + } else { + $params['php_resource'] = $_template_source; + } + return true; +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.is_secure.php b/gui/bacula-web/external_packages/smarty/internals/core.is_secure.php new file mode 100644 index 0000000000..342f3aff87 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.is_secure.php @@ -0,0 +1,56 @@ +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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.is_trusted.php b/gui/bacula-web/external_packages/smarty/internals/core.is_trusted.php new file mode 100644 index 0000000000..f0bd2fb8c9 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.is_trusted.php @@ -0,0 +1,47 @@ +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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.load_plugins.php b/gui/bacula-web/external_packages/smarty/internals/core.load_plugins.php new file mode 100644 index 0000000000..6db1dc51d2 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.load_plugins.php @@ -0,0 +1,125 @@ +_plugins[$_type][$_name]; + + /* + * We do not load plugin more than once for each instance of Smarty. + * The following code checks for that. The plugin can also be + * registered dynamically at runtime, in which case template file + * and line number will be unknown, so we fill them in. + * + * The final element of the info array is a flag that indicates + * whether the dynamically registered plugin function has been + * checked for existence yet or not. + */ + if (isset($_plugin)) { + if (empty($_plugin[3])) { + if (!is_callable($_plugin[0])) { + $smarty->_trigger_fatal_error("[plugin] $_type '$_name' is not implemented", $_tpl_file, $_tpl_line, __FILE__, __LINE__); + } else { + $_plugin[1] = $_tpl_file; + $_plugin[2] = $_tpl_line; + $_plugin[3] = true; + if (!isset($_plugin[4])) $_plugin[4] = true; /* cacheable */ + } + } + continue; + } else if ($_type == 'insert') { + /* + * For backwards compatibility, we check for insert functions in + * the symbol table before trying to load them as a plugin. + */ + $_plugin_func = 'insert_' . $_name; + if (function_exists($_plugin_func)) { + $_plugin = array($_plugin_func, $_tpl_file, $_tpl_line, true, false); + continue; + } + } + + $_plugin_file = $smarty->_get_plugin_filepath($_type, $_name); + + if (! $_found = ($_plugin_file != false)) { + $_message = "could not load plugin file '$_type.$_name.php'\n"; + } + + /* + * If plugin file is found, it -must- provide the properly named + * plugin function. In case it doesn't, simply output the error and + * do not fall back on any other method. + */ + if ($_found) { + include_once $_plugin_file; + + $_plugin_func = 'smarty_' . $_type . '_' . $_name; + if (!function_exists($_plugin_func)) { + $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", $_tpl_file, $_tpl_line, __FILE__, __LINE__); + continue; + } + } + /* + * In case of insert plugins, their code may be loaded later via + * 'script' attribute. + */ + else if ($_type == 'insert' && $_delayed_loading) { + $_plugin_func = 'smarty_' . $_type . '_' . $_name; + $_found = true; + } + + /* + * Plugin specific processing and error checking. + */ + if (!$_found) { + if ($_type == 'modifier') { + /* + * In case modifier falls back on using PHP functions + * directly, we only allow those specified in the security + * context. + */ + if ($smarty->security && !in_array($_name, $smarty->security_settings['MODIFIER_FUNCS'])) { + $_message = "(secure mode) modifier '$_name' is not allowed"; + } else { + if (!function_exists($_name)) { + $_message = "modifier '$_name' is not implemented"; + } else { + $_plugin_func = $_name; + $_found = true; + } + } + } else if ($_type == 'function') { + /* + * This is a catch-all situation. + */ + $_message = "unknown tag - '$_name'"; + } + } + + if ($_found) { + $smarty->_plugins[$_type][$_name] = array($_plugin_func, $_tpl_file, $_tpl_line, true, true); + } else { + // output error + $smarty->_trigger_fatal_error('[plugin] ' . $_message, $_tpl_file, $_tpl_line, __FILE__, __LINE__); + } + } +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.load_resource_plugin.php b/gui/bacula-web/external_packages/smarty/internals/core.load_resource_plugin.php new file mode 100644 index 0000000000..a7d37d1afc --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.load_resource_plugin.php @@ -0,0 +1,74 @@ +_plugins['resource'][$params['type']]; + if (isset($_plugin)) { + if (!$_plugin[1] && count($_plugin[0])) { + $_plugin[1] = true; + foreach ($_plugin[0] as $_plugin_func) { + if (!is_callable($_plugin_func)) { + $_plugin[1] = false; + break; + } + } + } + + if (!$_plugin[1]) { + $smarty->_trigger_fatal_error("[plugin] resource '" . $params['type'] . "' is not implemented", null, null, __FILE__, __LINE__); + } + + return; + } + + $_plugin_file = $smarty->_get_plugin_filepath('resource', $params['type']); + $_found = ($_plugin_file != false); + + if ($_found) { /* + * If the plugin file is found, it -must- provide the properly named + * plugin functions. + */ + include_once($_plugin_file); + + /* + * Locate functions that we require the plugin to provide. + */ + $_resource_ops = array('source', 'timestamp', 'secure', 'trusted'); + $_resource_funcs = array(); + foreach ($_resource_ops as $_op) { + $_plugin_func = 'smarty_resource_' . $params['type'] . '_' . $_op; + if (!function_exists($_plugin_func)) { + $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", null, null, __FILE__, __LINE__); + return; + } else { + $_resource_funcs[] = $_plugin_func; + } + } + + $smarty->_plugins['resource'][$params['type']] = array($_resource_funcs, true); + } +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.process_cached_inserts.php b/gui/bacula-web/external_packages/smarty/internals/core.process_cached_inserts.php new file mode 100644 index 0000000000..29cb007eb1 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.process_cached_inserts.php @@ -0,0 +1,71 @@ +_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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.process_compiled_include.php b/gui/bacula-web/external_packages/smarty/internals/core.process_compiled_include.php new file mode 100644 index 0000000000..3e1d4c15a0 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.process_compiled_include.php @@ -0,0 +1,32 @@ +_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; +} + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.read_cache_file.php b/gui/bacula-web/external_packages/smarty/internals/core.read_cache_file.php new file mode 100644 index 0000000000..2ab428111d --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.read_cache_file.php @@ -0,0 +1,111 @@ +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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.rm_auto.php b/gui/bacula-web/external_packages/smarty/internals/core.rm_auto.php new file mode 100644 index 0000000000..b251f64911 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.rm_auto.php @@ -0,0 +1,71 @@ + $params['auto_base'], + 'level' => 0, + 'exp_time' => $params['exp_time'] + ); + require_once(SMARTY_CORE_DIR . 'core.rmdir.php'); + $_res = smarty_core_rmdir($_params, $smarty); + } else { + $_tname = $smarty->_get_auto_filename($params['auto_base'], $params['auto_source'], $params['auto_id']); + + if(isset($params['auto_source'])) { + if (isset($params['extensions'])) { + $_res = false; + foreach ((array)$params['extensions'] as $_extension) + $_res |= $smarty->_unlink($_tname.$_extension, $params['exp_time']); + } else { + $_res = $smarty->_unlink($_tname, $params['exp_time']); + } + } elseif ($smarty->use_sub_dirs) { + $_params = array( + 'dirname' => $_tname, + 'level' => 1, + 'exp_time' => $params['exp_time'] + ); + require_once(SMARTY_CORE_DIR . 'core.rmdir.php'); + $_res = smarty_core_rmdir($_params, $smarty); + } else { + // remove matching file names + $_handle = opendir($params['auto_base']); + $_res = true; + while (false !== ($_filename = readdir($_handle))) { + if($_filename == '.' || $_filename == '..') { + continue; + } elseif (substr($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, 0, strlen($_tname)) == $_tname) { + $_res &= (bool)$smarty->_unlink($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, $params['exp_time']); + } + } + } + } + + return $_res; +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.rmdir.php b/gui/bacula-web/external_packages/smarty/internals/core.rmdir.php new file mode 100644 index 0000000000..4fdbccc95c --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.rmdir.php @@ -0,0 +1,55 @@ + 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.run_insert_handler.php b/gui/bacula-web/external_packages/smarty/internals/core.run_insert_handler.php new file mode 100644 index 0000000000..71c3845080 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.run_insert_handler.php @@ -0,0 +1,71 @@ +debugging) { + $_params = array(); + $_debug_start_time = smarty_core_get_microtime($_params, $smarty); + } + + if ($smarty->caching) { + $_arg_string = serialize($params['args']); + $_name = $params['args']['name']; + if (!isset($smarty->_cache_info['insert_tags'][$_name])) { + $smarty->_cache_info['insert_tags'][$_name] = array('insert', + $_name, + $smarty->_plugins['insert'][$_name][1], + $smarty->_plugins['insert'][$_name][2], + !empty($params['args']['script']) ? true : false); + } + return $smarty->_smarty_md5."{insert_cache $_arg_string}".$smarty->_smarty_md5; + } else { + if (isset($params['args']['script'])) { + $_params = array('resource_name' => $smarty->_dequote($params['args']['script'])); + require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php'); + if(!smarty_core_get_php_resource($_params, $smarty)) { + return false; + } + + if ($_params['resource_type'] == 'file') { + $smarty->_include($_params['php_resource'], true); + } else { + $smarty->_eval($_params['php_resource']); + } + unset($params['args']['script']); + } + + $_funcname = $smarty->_plugins['insert'][$params['args']['name']][0]; + $_content = $_funcname($params['args'], $smarty); + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $smarty->_smarty_debug_info[] = array('type' => 'insert', + 'filename' => 'insert_'.$params['args']['name'], + 'depth' => $smarty->_inclusion_depth, + 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time); + } + + if (!empty($params['args']["assign"])) { + $smarty->assign($params['args']["assign"], $_content); + } else { + return $_content; + } + } +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.smarty_include_php.php b/gui/bacula-web/external_packages/smarty/internals/core.smarty_include_php.php new file mode 100644 index 0000000000..30c6e76549 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.smarty_include_php.php @@ -0,0 +1,50 @@ + $params['smarty_file']); + require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php'); + smarty_core_get_php_resource($_params, $smarty); + $_smarty_resource_type = $_params['resource_type']; + $_smarty_php_resource = $_params['php_resource']; + + if (!empty($params['smarty_assign'])) { + ob_start(); + if ($_smarty_resource_type == 'file') { + $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']); + } else { + $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']); + } + $smarty->assign($params['smarty_assign'], ob_get_contents()); + ob_end_clean(); + } else { + if ($_smarty_resource_type == 'file') { + $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']); + } else { + $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']); + } + } +} + + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.write_cache_file.php b/gui/bacula-web/external_packages/smarty/internals/core.write_cache_file.php new file mode 100644 index 0000000000..d7a828492f --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.write_cache_file.php @@ -0,0 +1,95 @@ +_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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.write_compiled_include.php b/gui/bacula-web/external_packages/smarty/internals/core.write_compiled_include.php new file mode 100644 index 0000000000..d17bee11c1 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.write_compiled_include.php @@ -0,0 +1,79 @@ +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 = "_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 .= "= 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('\n"; + + $_params = array('filename' => $_compile_path, + 'contents' => $_include_compiled, 'create_dirs' => true); + + require_once(SMARTY_CORE_DIR . 'core.write_file.php'); + smarty_core_write_file($_params, $smarty); + return true; +} + + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.write_compiled_resource.php b/gui/bacula-web/external_packages/smarty/internals/core.write_compiled_resource.php new file mode 100644 index 0000000000..b902eff3cb --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.write_compiled_resource.php @@ -0,0 +1,35 @@ +compile_dir)) { + // compile_dir not writable, see if it exists + if(!@is_dir($smarty->compile_dir)) { + $smarty->trigger_error('the $compile_dir \'' . $smarty->compile_dir . '\' does not exist, or is not a directory.', E_USER_ERROR); + return false; + } + $smarty->trigger_error('unable to write to $compile_dir \'' . realpath($smarty->compile_dir) . '\'. Be sure $compile_dir is writable by the web server user.', E_USER_ERROR); + return false; + } + + $_params = array('filename' => $params['compile_path'], 'contents' => $params['compiled_content'], 'create_dirs' => true); + require_once(SMARTY_CORE_DIR . 'core.write_file.php'); + smarty_core_write_file($_params, $smarty); + return true; +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/internals/core.write_file.php b/gui/bacula-web/external_packages/smarty/internals/core.write_file.php new file mode 100644 index 0000000000..09e1698403 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/internals/core.write_file.php @@ -0,0 +1,54 @@ + $_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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/block.textformat.php b/gui/bacula-web/external_packages/smarty/plugins/block.textformat.php new file mode 100644 index 0000000000..aaebab2f51 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/block.textformat.php @@ -0,0 +1,102 @@ + + * Name: textformat
    + * Purpose: format text a certain way with preset styles + * or custom wrap/indent settings
    + * @link http://smarty.php.net/manual/en/language.function.textformat.php {textformat} + * (Smarty online manual) + * @param array + *
    + * Params:   style: string (email)
    + *           indent: integer (0)
    + *           wrap: integer (80)
    + *           wrap_char string ("\n")
    + *           indent_char: string (" ")
    + *           wrap_boundary: boolean (true)
    + * 
    + * @param string contents of the block + * @param Smarty clever simulation of a method + * @return string string $content re-formatted + */ +function smarty_block_textformat($params, $content, &$smarty) +{ + if (is_null($content)) { + return; + } + + $style = null; + $indent = 0; + $indent_first = 0; + $indent_char = ' '; + $wrap = 80; + $wrap_char = "\n"; + $wrap_cut = false; + $assign = null; + + foreach ($params as $_key => $_val) { + switch ($_key) { + case 'style': + case 'indent_char': + case 'wrap_char': + case 'assign': + $$_key = (string)$_val; + break; + + case 'indent': + case 'indent_first': + case 'wrap': + $$_key = (int)$_val; + break; + + case 'wrap_cut': + $$_key = (bool)$_val; + break; + + default: + $smarty->trigger_error("textformat: unknown attribute '$_key'"); + } + } + + if ($style == 'email') { + $wrap = 72; + } + + // split into paragraphs + $_paragraphs = preg_split('![\r\n][\r\n]!',$content); + $_output = ''; + + for($_x = 0, $_y = count($_paragraphs); $_x < $_y; $_x++) { + if ($_paragraphs[$_x] == '') { + continue; + } + // convert mult. spaces & special chars to single space + $_paragraphs[$_x] = preg_replace(array('!\s+!','!(^\s+)|(\s+$)!'), array(' ',''), $_paragraphs[$_x]); + // indent first line + if($indent_first > 0) { + $_paragraphs[$_x] = str_repeat($indent_char, $indent_first) . $_paragraphs[$_x]; + } + // wordwrap sentences + $_paragraphs[$_x] = wordwrap($_paragraphs[$_x], $wrap - $indent, $wrap_char, $wrap_cut); + // indent lines + if($indent > 0) { + $_paragraphs[$_x] = preg_replace('!^!m', str_repeat($indent_char, $indent), $_paragraphs[$_x]); + } + } + $_output = implode($wrap_char . $wrap_char, $_paragraphs); + + return $assign ? $smarty->assign($assign, $_output) : $_output; + +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/compiler.assign.php b/gui/bacula-web/external_packages/smarty/plugins/compiler.assign.php new file mode 100644 index 0000000000..2e02017796 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/compiler.assign.php @@ -0,0 +1,38 @@ + + * Name: assign
    + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.assign_debug_info.php b/gui/bacula-web/external_packages/smarty/plugins/function.assign_debug_info.php new file mode 100644 index 0000000000..8015624b1f --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.assign_debug_info.php @@ -0,0 +1,39 @@ + + * Name: assign_debug_info
    + * Purpose: assign debug info to the template
    + * @param array unused in this plugin, this plugin uses {@link Smarty::$_config}, + * {@link Smarty::$_tpl_vars} and {@link Smarty::$_smarty_debug_info} + * @param Smarty + */ +function smarty_function_assign_debug_info($params, &$smarty) +{ + $assigned_vars = $smarty->_tpl_vars; + ksort($assigned_vars); + if (@is_array($smarty->_config[0])) { + $config_vars = $smarty->_config[0]; + ksort($config_vars); + $smarty->assign("_debug_config_keys", array_keys($config_vars)); + $smarty->assign("_debug_config_vals", array_values($config_vars)); + } + + $included_templates = $smarty->_smarty_debug_info; + + $smarty->assign("_debug_keys", array_keys($assigned_vars)); + $smarty->assign("_debug_vals", array_values($assigned_vars)); + + $smarty->assign("_debug_tpls", $included_templates); +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.config_load.php b/gui/bacula-web/external_packages/smarty/plugins/function.config_load.php new file mode 100644 index 0000000000..db7f8f6b9b --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.config_load.php @@ -0,0 +1,140 @@ + + * Name: config_load
    + * 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: + *
    + * 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)
    + * 
    + * @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 = ''; + } else { + $_output = ''\\\'', '\\'=>'\\\\')) . '\'); ?>'; + } + $_params = (array('compile_path' => $_compile_file, 'compiled_content' => $_output, 'resource_timestamp' => $_params['resource_timestamp'])); + require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php'); + smarty_core_write_compiled_resource($_params, $smarty); + } else { + include($_compile_file); + } + + if ($smarty->caching) { + $smarty->_cache_info['config'][$_file] = true; + } + + $smarty->_config[0]['vars'] = @array_merge($smarty->_config[0]['vars'], $_config_vars); + $smarty->_config[0]['files'][$_file] = true; + + if ($_scope == 'parent') { + $smarty->_config[1]['vars'] = @array_merge($smarty->_config[1]['vars'], $_config_vars); + $smarty->_config[1]['files'][$_file] = true; + } else if ($_scope == 'global') { + for ($i = 1, $for_max = count($smarty->_config); $i < $for_max; $i++) { + $smarty->_config[$i]['vars'] = @array_merge($smarty->_config[$i]['vars'], $_config_vars); + $smarty->_config[$i]['files'][$_file] = true; + } + } + + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $smarty->_smarty_debug_info[] = array('type' => 'config', + 'filename' => $_file.' ['.$_section.'] '.$_scope, + 'depth' => $smarty->_inclusion_depth, + 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time); + } + +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.counter.php b/gui/bacula-web/external_packages/smarty/plugins/function.counter.php new file mode 100644 index 0000000000..cfe5dd886f --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.counter.php @@ -0,0 +1,79 @@ + + * Name: counter
    + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.cycle.php b/gui/bacula-web/external_packages/smarty/plugins/function.cycle.php new file mode 100644 index 0000000000..f61ff0b130 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.cycle.php @@ -0,0 +1,102 @@ + + * Name: cycle
    + * Date: May 3, 2002
    + * Purpose: cycle through given values
    + * 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:
    + *
    + * {cycle values="#eeeeee,#d0d0d0d"}
    + * {cycle name=row values="one,two,three" reset=true}
    + * {cycle name=row}
    + * 
    + * @link http://smarty.php.net/manual/en/language.function.cycle.php {cycle} + * (Smarty online manual) + * @author Monte Ohrt + * @author credit to Mark Priatel + * @author credit to Gerard + * @author credit to Jason Sweat + * @version 1.3 + * @param array + * @param Smarty + * @return string|null + */ +function smarty_function_cycle($params, &$smarty) +{ + static $cycle_vars; + + $name = (empty($params['name'])) ? 'default' : $params['name']; + $print = (isset($params['print'])) ? (bool)$params['print'] : true; + $advance = (isset($params['advance'])) ? (bool)$params['advance'] : true; + $reset = (isset($params['reset'])) ? (bool)$params['reset'] : false; + + if (!in_array('values', array_keys($params))) { + if(!isset($cycle_vars[$name]['values'])) { + $smarty->trigger_error("cycle: missing 'values' parameter"); + return; + } + } else { + if(isset($cycle_vars[$name]['values']) + && $cycle_vars[$name]['values'] != $params['values'] ) { + $cycle_vars[$name]['index'] = 0; + } + $cycle_vars[$name]['values'] = $params['values']; + } + + $cycle_vars[$name]['delimiter'] = (isset($params['delimiter'])) ? $params['delimiter'] : ','; + + if(is_array($cycle_vars[$name]['values'])) { + $cycle_array = $cycle_vars[$name]['values']; + } else { + $cycle_array = explode($cycle_vars[$name]['delimiter'],$cycle_vars[$name]['values']); + } + + if(!isset($cycle_vars[$name]['index']) || $reset ) { + $cycle_vars[$name]['index'] = 0; + } + + if (isset($params['assign'])) { + $print = false; + $smarty->assign($params['assign'], $cycle_array[$cycle_vars[$name]['index']]); + } + + if($print) { + $retval = $cycle_array[$cycle_vars[$name]['index']]; + } else { + $retval = null; + } + + if($advance) { + if ( $cycle_vars[$name]['index'] >= count($cycle_array) -1 ) { + $cycle_vars[$name]['index'] = 0; + } else { + $cycle_vars[$name]['index']++; + } + } + + return $retval; +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.debug.php b/gui/bacula-web/external_packages/smarty/plugins/function.debug.php new file mode 100644 index 0000000000..77e7109219 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.debug.php @@ -0,0 +1,35 @@ + + * Name: debug
    + * Date: July 1, 2002
    + * Purpose: popup debug window + * @link http://smarty.php.net/manual/en/language.function.debug.php {debug} + * (Smarty online manual) + * @author Monte Ohrt + * @version 1.0 + * @param array + * @param Smarty + * @return string output from {@link Smarty::_generate_debug_output()} + */ +function smarty_function_debug($params, &$smarty) +{ + if (isset($params['output'])) { + $smarty->assign('_smarty_debug_output', $params['output']); + } + require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php'); + return smarty_core_display_debug_console(null, $smarty); +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.eval.php b/gui/bacula-web/external_packages/smarty/plugins/function.eval.php new file mode 100644 index 0000000000..3a4b8b2b8c --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.eval.php @@ -0,0 +1,48 @@ + + * Name: eval
    + * Purpose: evaluate a template variable as a template
    + * @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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.fetch.php b/gui/bacula-web/external_packages/smarty/plugins/function.fetch.php new file mode 100644 index 0000000000..f5a6987a90 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.fetch.php @@ -0,0 +1,220 @@ + + * Name: fetch
    + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.html_checkboxes.php b/gui/bacula-web/external_packages/smarty/plugins/function.html_checkboxes.php new file mode 100644 index 0000000000..a64d7db7ad --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.html_checkboxes.php @@ -0,0 +1,143 @@ + + * Type: function
    + * Name: html_checkboxes
    + * Date: 24.Feb.2003
    + * Purpose: Prints out a list of checkbox input types
    + * Input:
    + * - name (optional) - string default "checkbox" + * - values (required) - array + * - options (optional) - associative array + * - checked (optional) - array default not set + * - separator (optional) - ie
    or   + * - output (optional) - the output next to each checkbox + * - assign (optional) - assign the output as an array to this variable + * Examples: + *
    + * {html_checkboxes values=$ids output=$names}
    + * {html_checkboxes values=$ids name='box' separator='
    ' output=$names} + * {html_checkboxes values=$ids checked=$checked separator='
    ' output=$names} + *
    + * @link http://smarty.php.net/manual/en/language.function.html.checkboxes.php {html_checkboxes} + * (Smarty online manual) + * @author Christopher Kvarme + * @author credits to Monte Ohrt + * @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 .= ''; + $_output .= $separator; + + return $_output; +} + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.html_image.php b/gui/bacula-web/external_packages/smarty/plugins/function.html_image.php new file mode 100644 index 0000000000..aa2aa18751 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.html_image.php @@ -0,0 +1,142 @@ + + * Name: html_image
    + * Date: Feb 24, 2003
    + * Purpose: format HTML tags for the image
    + * Input:
    + * - 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: + * @link http://smarty.php.net/manual/en/language.function.html.image.php {html_image} + * (Smarty online manual) + * @author Monte Ohrt + * @author credits to Duda - 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 = ''; + $suffix = ''; + 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 . ''.$alt.'' . $suffix; +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.html_options.php b/gui/bacula-web/external_packages/smarty/plugins/function.html_options.php new file mode 100644 index 0000000000..da5571c5b8 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.html_options.php @@ -0,0 +1,121 @@ + + * Name: html_options
    + * Input:
    + * - 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 ' . "\n"; + foreach ($values as $key => $value) { + $optgroup_html .= smarty_function_html_options_optoutput($key, $value, $selected); + } + $optgroup_html .= "\n"; + return $optgroup_html; +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.html_radios.php b/gui/bacula-web/external_packages/smarty/plugins/function.html_radios.php new file mode 100644 index 0000000000..c8633c5dd4 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.html_radios.php @@ -0,0 +1,145 @@ + + * Type: function
    + * Name: html_radios
    + * Date: 24.Feb.2003
    + * Purpose: Prints out a list of radio input types
    + * Input:
    + * - name (optional) - string default "radio" + * - values (required) - array + * - options (optional) - associative array + * - checked (optional) - array default not set + * - separator (optional) - ie
    or   + * - output (optional) - the output next to each radio button + * - assign (optional) - assign the output as an array to this variable + * Examples: + *
    + * {html_radios values=$ids output=$names}
    + * {html_radios values=$ids name='box' separator='
    ' output=$names} + * {html_radios values=$ids checked=$checked separator='
    ' output=$names} + *
    + * @link http://smarty.php.net/manual/en/language.function.html.radios.php {html_radios} + * (Smarty online manual) + * @author Christopher Kvarme + * @author credits to Monte Ohrt + * @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 .= ''; + $_output .= $separator; + + return $_output; +} + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.html_select_date.php b/gui/bacula-web/external_packages/smarty/plugins/function.html_select_date.php new file mode 100644 index 0000000000..fc2d449a8e --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.html_select_date.php @@ -0,0 +1,316 @@ + + * Name: html_select_date
    + * Purpose: Prints the dropdowns for date selection. + * + * ChangeLog:
    + * - 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; + /* tags. + If not set, uses default dropdown. */ + $day_size = null; + $month_size = null; + $year_size = null; + /* Unparsed attributes common to *ALL* the 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 .= ''; + } + + 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 .= ''; + } + + if ($display_years) { + if (null !== $field_array){ + $year_name = $field_array . '[' . $prefix . 'Year]'; + } else { + $year_name = $prefix . 'Year'; + } + if ($year_as_text) { + $year_result .= ' $years, + 'values' => $yearvals, + 'selected' => $time[0], + 'print_result' => false), + $smarty); + $year_result .= ''; + } + } + + // 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.html_select_time.php b/gui/bacula-web/external_packages/smarty/plugins/function.html_select_time.php new file mode 100644 index 0000000000..00cd1ae889 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.html_select_time.php @@ -0,0 +1,192 @@ + + * Name: html_select_time
    + * 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 .= '\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 .= '\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 .= '\n"; + } + + if ($display_meridian && !$use_24_hours) { + $html_result .= '\n"; + } + + return $html_result; +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.html_table.php b/gui/bacula-web/external_packages/smarty/plugins/function.html_table.php new file mode 100644 index 0000000000..0f6d03b932 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.html_table.php @@ -0,0 +1,137 @@ + + * Name: html_table
    + * Date: Feb 17, 2003
    + * Purpose: make an html table from an array of data
    + * Input:
    + * - 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: + *
    + * {table loop=$data}
    + * {table loop=$data cols=4 tr_attr='"bgcolor=red"'}
    + * {table loop=$data cols=4 tr_attr=$colors}
    + * 
    + * @author Monte Ohrt + * @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 = "\n"; + + for ($r=0; $r<$rows; $r++) { + $output .= "\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 .= "" . $loop[$x] . "\n"; + } else { + $output .= "$trailpad\n"; + } + } + $output .= "\n"; + } + $output .= "
    \n"; + + return $output; +} + +function smarty_function_html_table_cycle($name, $var, $no) { + if(!is_array($var)) { + $ret = $var; + } else { + $ret = $var[$no % count($var)]; + } + + return ($ret) ? ' '.$ret : ''; +} + + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.mailto.php b/gui/bacula-web/external_packages/smarty/plugins/function.mailto.php new file mode 100644 index 0000000000..a4f4d2d5d9 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.mailto.php @@ -0,0 +1,143 @@ + + * Name: mailto
    + * Date: May 21, 2002 + * Purpose: automate mailto address link creation, and optionally + * encode them.
    + * Input:
    + * - 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: + *
    + * {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"'}
    + * 
    + * @link http://smarty.php.net/manual/en/language.function.mailto.php {mailto} + * (Smarty online manual) + * @version 1.2 + * @author Monte Ohrt + * @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; $itrigger_error("mailto: 'encode' parameter must be none, javascript or hex"); + return; + } + + if ($encode == 'javascript' ) { + $string = 'document.write(\''.$text.'\');'; + + $js_encode = ''; + for ($x=0; $x < strlen($string); $x++) { + $js_encode .= '%' . bin2hex($string[$x]); + } + + return ''; + + } 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 ''.$text_encode.''; + + } else { + // no encoding + return ''.$text.''; + + } + +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.math.php b/gui/bacula-web/external_packages/smarty/plugins/function.math.php new file mode 100644 index 0000000000..c080d4dfe6 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.math.php @@ -0,0 +1,82 @@ + + * Name: math
    + * Purpose: handle math computations in template
    + * @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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.popup.php b/gui/bacula-web/external_packages/smarty/plugins/function.popup.php new file mode 100644 index 0000000000..80bd62aafb --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.popup.php @@ -0,0 +1,110 @@ + + * Name: popup
    + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/function.popup_init.php b/gui/bacula-web/external_packages/smarty/plugins/function.popup_init.php new file mode 100644 index 0000000000..f62c33c13f --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/function.popup_init.php @@ -0,0 +1,39 @@ + + * Name: popup_init
    + * 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 '' . "\n" + . '' . "\n"; + } else { + $smarty->trigger_error("popup_init: missing src parameter"); + } +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.capitalize.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.capitalize.php new file mode 100644 index 0000000000..2b9169cefa --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.capitalize.php @@ -0,0 +1,42 @@ + + * Name: capitalize
    + * 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]; +} + + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.cat.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.cat.php new file mode 100644 index 0000000000..f5dc3d6893 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.cat.php @@ -0,0 +1,33 @@ + + * Name: cat
    + * 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 + * @version 1.0 + * @param string + * @param string + * @return string + */ +function smarty_modifier_cat($string, $cat) +{ + return $string . $cat; +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.count_characters.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.count_characters.php new file mode 100644 index 0000000000..49ce655e85 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.count_characters.php @@ -0,0 +1,31 @@ + + * Name: count_characteres
    + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.count_paragraphs.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.count_paragraphs.php new file mode 100644 index 0000000000..6a9833c97c --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.count_paragraphs.php @@ -0,0 +1,28 @@ + + * Name: count_paragraphs
    + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.count_sentences.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.count_sentences.php new file mode 100644 index 0000000000..0c210f08fe --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.count_sentences.php @@ -0,0 +1,28 @@ + + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.count_words.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.count_words.php new file mode 100644 index 0000000000..42c8a741c5 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.count_words.php @@ -0,0 +1,32 @@ + + * Name: count_words
    + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.date_format.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.date_format.php new file mode 100644 index 0000000000..2f36b3b79c --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.date_format.php @@ -0,0 +1,48 @@ +_get_plugin_filepath('shared','make_timestamp'); +/** + * Smarty date_format modifier plugin + * + * Type: modifier
    + * Name: date_format
    + * Purpose: format datestamps via strftime
    + * Input:
    + * - 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.debug_print_var.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.debug_print_var.php new file mode 100644 index 0000000000..b9bb184880 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.debug_print_var.php @@ -0,0 +1,56 @@ + + * Name: debug_print_var
    + * 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"=>'\n', "\r"=>'\r', "\t"=>'\t'); + if (is_array($var)) { + $results = "Array (".count($var).")"; + foreach ($var as $curr_key => $curr_val) { + $return = smarty_modifier_debug_print_var($curr_val, $depth+1, $length); + $results .= "
    ".str_repeat(' ', $depth*2)."".strtr($curr_key, $_replace)." => $return"; + } + } else if (is_object($var)) { + $object_vars = get_object_vars($var); + $results = "".get_class($var)." Object (".count($object_vars).")"; + foreach ($object_vars as $curr_key => $curr_val) { + $return = smarty_modifier_debug_print_var($curr_val, $depth+1, $length); + $results .= "
    ".str_repeat(' ', $depth*2)."$curr_key => $return"; + } + } else if (is_resource($var)) { + $results = ''.(string)$var.''; + } else if (empty($var) && $var != "0") { + $results = 'empty'; + } 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.default.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.default.php new file mode 100644 index 0000000000..8268e396ff --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.default.php @@ -0,0 +1,31 @@ + + * Name: default
    + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.escape.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.escape.php new file mode 100644 index 0000000000..0a0270c564 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.escape.php @@ -0,0 +1,89 @@ + + * Name: escape
    + * 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("%(?'\\\\',"'"=>"\\'",'"'=>'\\"',"\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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.fsize_format.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.fsize_format.php new file mode 100644 index 0000000000..c3bf4c4a8e --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.fsize_format.php @@ -0,0 +1,58 @@ + 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 diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.indent.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.indent.php new file mode 100644 index 0000000000..1642bac3de --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.indent.php @@ -0,0 +1,27 @@ + + * Name: indent
    + * 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); +} + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.lower.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.lower.php new file mode 100644 index 0000000000..0b4d1517dc --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.lower.php @@ -0,0 +1,25 @@ + + * Name: lower
    + * 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); +} + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.nl2br.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.nl2br.php new file mode 100644 index 0000000000..86a28d207a --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.nl2br.php @@ -0,0 +1,35 @@ + + * Name: nl2br
    + * Date: Feb 26, 2003 + * Purpose: convert \r\n, \r or \n to <
    > + * Input:
    + * - 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 + * @param string + * @return string + */ +function smarty_modifier_nl2br($string) +{ + return nl2br($string); +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.regex_replace.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.regex_replace.php new file mode 100644 index 0000000000..b9cc865ea8 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.regex_replace.php @@ -0,0 +1,29 @@ + + * Name: regex_replace
    + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.replace.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.replace.php new file mode 100644 index 0000000000..2a43515f7e --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.replace.php @@ -0,0 +1,29 @@ + + * Name: replace
    + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.spacify.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.spacify.php new file mode 100644 index 0000000000..dad057f9b5 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.spacify.php @@ -0,0 +1,29 @@ + + * Name: spacify
    + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.string_format.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.string_format.php new file mode 100644 index 0000000000..efd621506f --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.string_format.php @@ -0,0 +1,28 @@ + + * Name: string_format
    + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.strip.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.strip.php new file mode 100644 index 0000000000..738c6407e6 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.strip.php @@ -0,0 +1,33 @@ + + * Name: strip
    + * Purpose: Replace all repeated spaces, newlines, tabs + * with a single space or supplied replacement string.
    + * 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 + * @version 1.0 + * @param string + * @param string + * @return string + */ +function smarty_modifier_strip($text, $replace = ' ') +{ + return preg_replace('!\s+!', $replace, $text); +} + +/* vim: set expandtab: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.strip_tags.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.strip_tags.php new file mode 100644 index 0000000000..45f1ec14d1 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.strip_tags.php @@ -0,0 +1,31 @@ + + * Name: strip_tags
    + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.truncate.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.truncate.php new file mode 100644 index 0000000000..15a26ba975 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.truncate.php @@ -0,0 +1,43 @@ + + * Name: truncate
    + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.upper.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.upper.php new file mode 100644 index 0000000000..69960ae721 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.upper.php @@ -0,0 +1,25 @@ + + * Name: upper
    + * 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); +} + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/modifier.wordwrap.php b/gui/bacula-web/external_packages/smarty/plugins/modifier.wordwrap.php new file mode 100644 index 0000000000..b9a9fe94b3 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/modifier.wordwrap.php @@ -0,0 +1,28 @@ + + * Name: wordwrap
    + * 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); +} + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/outputfilter.trimwhitespace.php b/gui/bacula-web/external_packages/smarty/plugins/outputfilter.trimwhitespace.php new file mode 100644 index 0000000000..9979e85867 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/outputfilter.trimwhitespace.php @@ -0,0 +1,75 @@ + + * Type: outputfilter
    + * Name: trimwhitespace
    + * Date: Jan 25, 2003
    + * Purpose: trim leading white space and blank lines from + * template source after it gets interpreted, cleaning + * up code and saving bandwidth. Does not affect + * <
    >
    and blocks.
    + * Install: Drop into the plugin directory, call + * $smarty->load_filter('output','trimwhitespace'); + * from application. + * @author Monte Ohrt + * @author Contributions from Lars Noschinski + * @version 1.3 + * @param string + * @param Smarty + */ +function smarty_outputfilter_trimwhitespace($source, &$smarty) +{ + // Pull out the script blocks + preg_match_all("!]+>.*?!is", $source, $match); + $_script_blocks = $match[0]; + $source = preg_replace("!]+>.*?!is", + '@@@SMARTY:TRIM:SCRIPT@@@', $source); + + // Pull out the pre blocks + preg_match_all("!
    .*?
    !is", $source, $match); + $_pre_blocks = $match[0]; + $source = preg_replace("!
    .*?
    !is", + '@@@SMARTY:TRIM:PRE@@@', $source); + + // Pull out the textarea blocks + preg_match_all("!]+>.*?!is", $source, $match); + $_textarea_blocks = $match[0]; + $source = preg_replace("!]+>.*?!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; + +} + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/shared.escape_special_chars.php b/gui/bacula-web/external_packages/smarty/plugins/shared.escape_special_chars.php new file mode 100644 index 0000000000..515763abed --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/shared.escape_special_chars.php @@ -0,0 +1,30 @@ + + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty/plugins/shared.make_timestamp.php b/gui/bacula-web/external_packages/smarty/plugins/shared.make_timestamp.php new file mode 100644 index 0000000000..acdd777359 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty/plugins/shared.make_timestamp.php @@ -0,0 +1,43 @@ + + * 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: */ + +?> diff --git a/gui/bacula-web/external_packages/smarty_gettext-0.9/COPYING b/gui/bacula-web/external_packages/smarty_gettext-0.9/COPYING new file mode 100644 index 0000000000..3b204400cf --- /dev/null +++ b/gui/bacula-web/external_packages/smarty_gettext-0.9/COPYING @@ -0,0 +1,458 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 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. + + 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. + + 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. + + 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 diff --git a/gui/bacula-web/external_packages/smarty_gettext-0.9/ChangeLog b/gui/bacula-web/external_packages/smarty_gettext-0.9/ChangeLog new file mode 100644 index 0000000000..b683857c5d --- /dev/null +++ b/gui/bacula-web/external_packages/smarty_gettext-0.9/ChangeLog @@ -0,0 +1,9 @@ +2004-03-01 Sagi Bashari + + * tsmarty2c.php: + - added support for directories (originally by Uros Gruber ) + - fixed bug that prevented more than 1 block per line (reported by Eneko Lacunza ) + - convert new line to \n in output string + + * smarty_gettext.php: + - run nl2br() when escaping html diff --git a/gui/bacula-web/external_packages/smarty_gettext-0.9/README b/gui/bacula-web/external_packages/smarty_gettext-0.9/README new file mode 100644 index 0000000000..c6c468907f --- /dev/null +++ b/gui/bacula-web/external_packages/smarty_gettext-0.9/README @@ -0,0 +1,91 @@ +Gettext support for Smarty +-------------------------- + +Author: Sagi Bashari +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"}%2{/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 <..> > 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 diff --git a/gui/bacula-web/external_packages/smarty_gettext-0.9/smarty_gettext.php b/gui/bacula-web/external_packages/smarty_gettext-0.9/smarty_gettext.php new file mode 100644 index 0000000000..0e867f2240 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty_gettext-0.9/smarty_gettext.php @@ -0,0 +1,115 @@ +register_block('t', 'smarty_translate'); + * + * @package smarty_gettext + * @version 0.9 + * @link http://www.boom.org.il/smarty/gettext/ + * @author Sagi Bashari + * @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; +} + +?> diff --git a/gui/bacula-web/external_packages/smarty_gettext-0.9/tsmarty2c.php b/gui/bacula-web/external_packages/smarty_gettext-0.9/tsmarty2c.php new file mode 100644 index 0000000000..51d9b8bc23 --- /dev/null +++ b/gui/bacula-web/external_packages/smarty_gettext-0.9/tsmarty2c.php @@ -0,0 +1,114 @@ +#!/usr/local/bin/php -qn + <..> > 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 + * @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]); + } +} + +?> diff --git a/gui/bacula-web/images/backlast.gif b/gui/bacula-web/images/backlast.gif new file mode 100644 index 0000000000..83e2efafce Binary files /dev/null and b/gui/bacula-web/images/backlast.gif differ diff --git a/gui/bacula-web/images/backlastred.gif b/gui/bacula-web/images/backlastred.gif new file mode 100644 index 0000000000..dd7fb1ded3 Binary files /dev/null and b/gui/bacula-web/images/backlastred.gif differ diff --git a/gui/bacula-web/images/bg1.png b/gui/bacula-web/images/bg1.png new file mode 100644 index 0000000000..574e13283d Binary files /dev/null and b/gui/bacula-web/images/bg1.png differ diff --git a/gui/bacula-web/images/bg2.png b/gui/bacula-web/images/bg2.png new file mode 100644 index 0000000000..f5d066af6c Binary files /dev/null and b/gui/bacula-web/images/bg2.png differ diff --git a/gui/bacula-web/images/bg3.png b/gui/bacula-web/images/bg3.png new file mode 100644 index 0000000000..18f9e20e6e Binary files /dev/null and b/gui/bacula-web/images/bg3.png differ diff --git a/gui/bacula-web/images/bg4.png b/gui/bacula-web/images/bg4.png new file mode 100644 index 0000000000..dedc0ab83b Binary files /dev/null and b/gui/bacula-web/images/bg4.png differ diff --git a/gui/bacula-web/images/bg5.png b/gui/bacula-web/images/bg5.png new file mode 100644 index 0000000000..94dff52202 Binary files /dev/null and b/gui/bacula-web/images/bg5.png differ diff --git a/gui/bacula-web/images/bg6.png b/gui/bacula-web/images/bg6.png new file mode 100644 index 0000000000..27e71de555 Binary files /dev/null and b/gui/bacula-web/images/bg6.png differ diff --git a/gui/bacula-web/images/bg7.gif b/gui/bacula-web/images/bg7.gif new file mode 100644 index 0000000000..b77204f2bd Binary files /dev/null and b/gui/bacula-web/images/bg7.gif differ diff --git a/gui/bacula-web/images/bg8.png b/gui/bacula-web/images/bg8.png new file mode 100644 index 0000000000..908f0f7e57 Binary files /dev/null and b/gui/bacula-web/images/bg8.png differ diff --git a/gui/bacula-web/images/empty.png b/gui/bacula-web/images/empty.png new file mode 100644 index 0000000000..84c4f77625 Binary files /dev/null and b/gui/bacula-web/images/empty.png differ diff --git a/gui/bacula-web/images/end2.png b/gui/bacula-web/images/end2.png new file mode 100644 index 0000000000..81b54dd4cc Binary files /dev/null and b/gui/bacula-web/images/end2.png differ diff --git a/gui/bacula-web/images/end4.png b/gui/bacula-web/images/end4.png new file mode 100644 index 0000000000..d1245b9056 Binary files /dev/null and b/gui/bacula-web/images/end4.png differ diff --git a/gui/bacula-web/images/s_error.gif b/gui/bacula-web/images/s_error.gif new file mode 100644 index 0000000000..e21a60c59d Binary files /dev/null and b/gui/bacula-web/images/s_error.gif differ diff --git a/gui/bacula-web/images/s_ok.gif b/gui/bacula-web/images/s_ok.gif new file mode 100644 index 0000000000..dd27c075c9 Binary files /dev/null and b/gui/bacula-web/images/s_ok.gif differ diff --git a/gui/bacula-web/index.php b/gui/bacula-web/index.php new file mode 100644 index 0000000000..4d1800f388 --- /dev/null +++ b/gui/bacula-web/index.php @@ -0,0 +1,131 @@ +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. date + + + +$smarty->display('report.tpl'); +?> + diff --git a/gui/bacula-web/stats.php b/gui/bacula-web/stats.php new file mode 100644 index 0000000000..edfcb92ef3 --- /dev/null +++ b/gui/bacula-web/stats.php @@ -0,0 +1,63 @@ +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']); + + +?> diff --git a/gui/bacula-web/templates/css.tpl b/gui/bacula-web/templates/css.tpl new file mode 100644 index 0000000000..9d562d89f8 --- /dev/null +++ b/gui/bacula-web/templates/css.tpl @@ -0,0 +1,48 @@ + \ No newline at end of file diff --git a/gui/bacula-web/templates/footer.tpl b/gui/bacula-web/templates/footer.tpl new file mode 100644 index 0000000000..e04310fdd2 --- /dev/null +++ b/gui/bacula-web/templates/footer.tpl @@ -0,0 +1,2 @@ + + diff --git a/gui/bacula-web/templates/full_popup.tpl b/gui/bacula-web/templates/full_popup.tpl new file mode 100644 index 0000000000..8ebae7e379 --- /dev/null +++ b/gui/bacula-web/templates/full_popup.tpl @@ -0,0 +1,14 @@ +{config_load file=bacula.conf} + + +{include file=css.tpl} +Popup + +{if $smarty.get.Full_popup == "yes"} + {include file=last_run_report.tpl} +{elseif $smarty.get.pop_graph1 == "yes"} + +{elseif $smarty.get.pop_graph2 == "yes"} + +{/if} +{include file=footer.tpl} \ No newline at end of file diff --git a/gui/bacula-web/templates/generaldata.tpl b/gui/bacula-web/templates/generaldata.tpl new file mode 100644 index 0000000000..9fb3501f3d --- /dev/null +++ b/gui/bacula-web/templates/generaldata.tpl @@ -0,0 +1,47 @@ + + + +
    +{t}GENERAL DATA{/t} +
    + + + + + + + + + + + + + + + + + + + + + + +
    + {t}Total clients:{/t} + + {$clientes_totales} + + {t}Total bytes stored{/t}: + + {$bytes_stored|fsize_format} +
    + {t}Total files:{/t} + + {$files_totales} +
    + {t}Last month, bytes transferred{/t} + + {t}Last month, bytes transferred (pie){/t} +
    + +
    diff --git a/gui/bacula-web/templates/header.tpl b/gui/bacula-web/templates/header.tpl new file mode 100644 index 0000000000..564369e694 --- /dev/null +++ b/gui/bacula-web/templates/header.tpl @@ -0,0 +1,28 @@ + + +{popup_init src="js/overlib.js"} +{literal} + +{/literal} +{#title#} + + + + + + + + +
    + {#title#} + + + Bugs? + + +
    \ No newline at end of file diff --git a/gui/bacula-web/templates/index.tpl b/gui/bacula-web/templates/index.tpl new file mode 100644 index 0000000000..d7d3432745 --- /dev/null +++ b/gui/bacula-web/templates/index.tpl @@ -0,0 +1,32 @@ +{* BACULA main page*} + +{config_load file=bacula.conf} + +{include file=css.tpl} + +{include file=header.tpl} + + + + + + +
    {include file=generaldata.tpl}
    {include file=volumes.tpl}
    + {if !#IndexReport#} + {include file=last_run_report.tpl} + {else} + {include file=report_select.tpl} + {/if} + + +
    + {if $server==""} + + {else} + + {/if} +
    +
    + + +{include file="footer.tpl"} \ No newline at end of file diff --git a/gui/bacula-web/templates/last_run_report.tpl b/gui/bacula-web/templates/last_run_report.tpl new file mode 100644 index 0000000000..350b537e6b --- /dev/null +++ b/gui/bacula-web/templates/last_run_report.tpl @@ -0,0 +1,195 @@ + + + + +{if #mode# == "Lite" && $smarty.get.Full_popup != "yes"} + + + + + + + + + + + + + + + + + + + + + + + {if $status != 0} + + + + {/if} + + + + +{else if #mode# == "Full" || $smarty.get.Full_popup == "yes"} + + + +{/if} +
    + {t}Status from last 24h{/t} +
    + {t}Errors:{/t} + + {$status} +
    + {t}Terminated Jobs:{/t} + + {$total_jobs} +
    + {t}Total time spent to do backup:{/t} + + {$TotalElapsed} +
    + {t}Bytes transferred last 24h{/t} + + {$bytes_totales|fsize_format} +
    + {t}Show details{/t} +
    + + + + + + + + + + + {section name=row loop=$errors_array} + + {section name=tmp loop=$errors_array[row]} + + {/section} + + {/section} +
    + {t}Jobs with errors{/t} +
    JobId {t}Name{/t}{t}EndTime{/t}{t}JobStatus{/t}
    + {if $smarty.section.tmp.iteration == 2} + + {/if} + {$errors_array[row][tmp]} + {if $smarty.section.row.iteration == 2} + + {/if} +
    +
    + + + + + + + + + + + + + +
    + {t}Detailed report{/t} +
    + {t}Select a job:{/t} +
    + + + +
    +
    + + + + + + + + + + + {section name=job loop=$clients} + + {section name=row loop=$clients[job]} + + {/section} + + {/section} +
    {t}Elapsed time{/t}{t}Client{/t}{t}Start Time{/t}{t}End Time{/t}{t}Type{/t}{t}Pool{/t}{t}Status{/t}
    + {if $smarty.section.row.iteration == 2} + + {/if} + {if $smarty.section.row.last == TRUE} + {if $clients[job][row] eq "T"} + + {else} + + {/if} + {else} + {$clients[job][row]} + {/if} + {if $smarty.section.row.iteration == 2} + + {/if} +
    +
    \ No newline at end of file diff --git a/gui/bacula-web/templates/report.tpl b/gui/bacula-web/templates/report.tpl new file mode 100644 index 0000000000..f3f8ca7eb8 --- /dev/null +++ b/gui/bacula-web/templates/report.tpl @@ -0,0 +1,99 @@ +{* Página principal BACULA *} +{config_load file=bacula.conf} +{popup_init src="js/overlib.js"} + + + +{t}Stats Bacula: Job{/t} {$smarty.get.server} + + +{include file=css.tpl} + + + + + +
    + + + + + + + + +
    + {t}Job:{/t} {$smarty.get.server} +
    + {t}Period: From{/t} {$startperiod|date_format:"%d/%m/%Y"} {t}to{/t} {$endperiod|date_format:"%d/%m/%Y"} +
    + + + + + + + + + + + + +
    + {t}Bytes transferred in the period:{/t} + + {$bytesperiod|fsize_format} +
    + {t}Files transferred in the period:{/t} + + {$filesperiod} +
    + {if $smarty.get.server==""} + + {elseif $smarty.get.default == 1} + + {else} + + {/if} +
    +
    +
    + + + + + + + +
    {include file=report_select.tpl}
    + + + + + + + + + {section name=job loop=$jobs} + + + + + + + + {/section} +
    {t}Date{/t}{t}Elapsed{/t}{t}Level{/t}{t}Bytes{/t}{t}Status{/t}
    {$jobs[job].StartTime}{$jobs[job].elapsed}{$jobs[job].Level}{$jobs[job].JobBytes|fsize_format} + {if $jobs[job].JobStatus eq "T"} + + {else} + + {/if} +
    +
    +
    +
    + + + +{include file="footer.tpl"} diff --git a/gui/bacula-web/templates/report_select.tpl b/gui/bacula-web/templates/report_select.tpl new file mode 100644 index 0000000000..820ff4d5a0 --- /dev/null +++ b/gui/bacula-web/templates/report_select.tpl @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
    + {t}SELECT NEW REPORT{/t} +
    +
    + + {t}Select a job:{/t} +
    + +
    + {t}Graph mode:{/t} + + + +
    + {t}Data to show:{/t} + + +
    + {t}Start period:{/t} + + {html_select_date prefix="StartDate" time=$time2 field_order="DMY" start_year="-1" end_year="+1" display_days=true} +
    {t}End period:{/t} + + {html_select_date prefix="EndDate" time=$time field_order="DMY" start_year="-1" end_year="+1" display_days=true} +
    + + +
    \ No newline at end of file diff --git a/gui/bacula-web/templates/volumes.tpl b/gui/bacula-web/templates/volumes.tpl new file mode 100644 index 0000000000..ff667d3e99 --- /dev/null +++ b/gui/bacula-web/templates/volumes.tpl @@ -0,0 +1,56 @@ +{* Design of table of pools *} + + + + + +
    Pools
    + +{foreach from=$pools item=current} + + + + + {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} + + + + + + + + {/if} + + + + + + + + + {/if} + {/foreach} + {/foreach} +{/foreach} +
     
    + {$current} +
    {t}Volume Name{/t}{t}Volume Bytes{/t}{t}Media Type{/t}{t}When expire?{/t}{t}Last Written{/t} + {t}Volume Status{/t}
    {$current3.0}{$current3.1|fsize_format|default:0}{$current3.4}{if $current3.6|date_format:"%Y" <= "1979"}--{else}{$current3.6|date_format:"%Y/%m/%d"}{/if}{if $current3.5 == "0000-00-00 00:00:00"}--{else}{$current3.5|date_format:"%Y/%m/%d"}{/if} + + {elseif $current3.2 == "Purged"} + yellow> + {elseif $current3.2 == "Append"} + green> + {else} + ""> + {/if} + {$current3.2} + +
    +
    \ No newline at end of file diff --git a/gui/bacula-web/test.php b/gui/bacula-web/test.php new file mode 100644 index 0000000000..013fd8d6e5 --- /dev/null +++ b/gui/bacula-web/test.php @@ -0,0 +1,51 @@ +NO ".$text." disabled ".$description; + else + echo "YES ".$text." enabled "; +} + +?> + + + + Testing page + + + +Checking system for dependencies...


    + + + + + + + + + + +
    + Checking gettext: + +
    + Checking Pear(DB): + YES Pear DB enabled "; + else + echo "NO Pear DB NOT FOUNDThis is required. Please download from http://pear.php.net/package/DB/download ."; + ?> +
    + Checking GD: + +
    +

    + +Please, click the link below to test your graph system capabilities (Bacula-web only use PNG):
    + +Test + + \ No newline at end of file diff --git a/gui/bacula-web/tsmarty2c.php b/gui/bacula-web/tsmarty2c.php new file mode 100755 index 0000000000..51d9b8bc23 --- /dev/null +++ b/gui/bacula-web/tsmarty2c.php @@ -0,0 +1,114 @@ +#!/usr/local/bin/php -qn + <..> > 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 + * @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]); + } +} + +?> diff --git a/gui/bimagemgr/.cvsignore b/gui/bimagemgr/.cvsignore new file mode 100644 index 0000000000..3bfc6e30f6 --- /dev/null +++ b/gui/bimagemgr/.cvsignore @@ -0,0 +1,2 @@ +Makefile +bacula-bimagemgr.spec diff --git a/gui/bimagemgr/Makefile.in b/gui/bimagemgr/Makefile.in new file mode 100644 index 0000000000..81d1517ec1 --- /dev/null +++ b/gui/bimagemgr/Makefile.in @@ -0,0 +1,35 @@ +# 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 diff --git a/gui/bimagemgr/README b/gui/bimagemgr/README new file mode 100644 index 0000000000..a8e449e578 --- /dev/null +++ b/gui/bimagemgr/README @@ -0,0 +1,63 @@ +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. diff --git a/gui/bimagemgr/bacula-bimagemgr.spec.in b/gui/bimagemgr/bacula-bimagemgr.spec.in new file mode 100644 index 0000000000..e4cc92bb66 --- /dev/null +++ b/gui/bimagemgr/bacula-bimagemgr.spec.in @@ -0,0 +1,133 @@ +# 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 + +%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 +- 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 +- initial spec file diff --git a/gui/bimagemgr/bimagemgr.gif b/gui/bimagemgr/bimagemgr.gif new file mode 100644 index 0000000000..2cbd2ac901 Binary files /dev/null and b/gui/bimagemgr/bimagemgr.gif differ diff --git a/gui/bimagemgr/bimagemgr.pl b/gui/bimagemgr/bimagemgr.pl new file mode 100755 index 0000000000..1b3cea57e9 --- /dev/null +++ b/gui/bimagemgr/bimagemgr.pl @@ -0,0 +1,579 @@ +#!/usr/bin/perl +## +# bimagemgr.pl +# burn manager for bacula CD image files +# +# Copyright (C) 2004 Kern Sibbald +# +# Thu Dec 09 2004 D. Scott Barninger +# 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 "
    "; + print "
    Bacula CD Image Manager version $VERSION

    "; + print "Copyright © 2004 D. Scott Barninger
    "; + print "Licensed under the GNU GPL version 2.0"; + print "
    "; + print ""; + } + 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 "
    "; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print "
    "; + print "

    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.

    "; + print "

    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.

    "; + print "

    After the popup window indicates that the burn is complete, close the popup and refresh this window. "; + print "If the burn is not successful click the Reset link under the last burn date to restore the Burn button and refresh this window.

    "; + print "

    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.

    "; + print "
     
    "; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + + $sth->execute(); + while ($data = $sth->fetchrow_arrayref) { + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + if ($$data[1] gt $$data[2] && $$data[3] gt "0" && $$data[4] ne "Purged") { + print ""; + } + else { + print ""; + } + print ""; + } + $sth->finish(); + $dbh->disconnect(); + + print ""; + print ""; + print ""; + print "

    Current Volume Information

    Make sure the backup file path $image_path is mounted.
    Volume NameLast WrittenLast BurnWritesStatus 
    $$data[0]$$data[1]$$data[2]
    Reset
    $$data[3]$$data[4]
    No Burn
    "; + print "
    "; + print "

    "; + &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 ""; + print OUTF ""; + print OUTF "Burning Volume $Volume"; + print OUTF ""; + print OUTF ""; + print OUTF "

    "; + print OUTF ""; + print OUTF ""; + print OUTF ""; + print OUTF ""; + print OUTF ""; + print OUTF ""; + print OUTF "
    "; + print OUTF "
    "; + close(OUTF); + + # now send to the burn status window that we are burning + print "Content-type: text/html\n\n"; + print ""; + print ""; + print ""; + print "Burning Volume $Volume"; + print ""; + print ""; + print "
    "; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print "
    "; + print "

    Now burning $Volume ...

    "; + print "
    "; + print ""; + print ""; + + # 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 ""; + print OUTF ""; + print OUTF ""; + print OUTF ""; + print OUTF ""; + print OUTF ""; + print OUTF ""; + print OUTF ""; + print OUTF ""; + print OUTF ""; + print OUTF ""; + print OUTF ""; + print OUTF "
    If you do not see successful output from cdrecord above the burn has failed.
    Please close this window and refresh the main window.
    $copyright
    "; + print OUTF ""; + print OUTF ""; + print OUTF ""; + close(OUTF); + + # now pretty up the burn results file by replacing \n with
    + 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 = ) { + $line =~ s/\n/
    /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 ""; + print ""; + print "$title"; + print ""; + print ""; + print "
    "; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print "
    "; + print "
    "; + print "

    "; + return; +} + +#-------------------------------------------------------------------# +# Function DisplayFooter +# Description: main page display footer + +sub DisplayFooter { + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print "
    $copyright
    "; + print ""; + print ""; + print ""; + 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 ""; + print ""; + print "$title"; + print ""; + print ""; + print "

    $title

    "; + print "

    $msg

    "; + print "
    "; + print ""; + print "
    "; + print ""; + print ""; + + 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 +# diff --git a/gui/bimagemgr/cdrom_spins.gif b/gui/bimagemgr/cdrom_spins.gif new file mode 100644 index 0000000000..66b8e3c03e Binary files /dev/null and b/gui/bimagemgr/cdrom_spins.gif differ diff --git a/gui/bimagemgr/clearpixel.gif b/gui/bimagemgr/clearpixel.gif new file mode 100644 index 0000000000..ae710460bd Binary files /dev/null and b/gui/bimagemgr/clearpixel.gif differ diff --git a/gui/bimagemgr/create_cdimage_table.pl b/gui/bimagemgr/create_cdimage_table.pl new file mode 100755 index 0000000000..3b6b429600 --- /dev/null +++ b/gui/bimagemgr/create_cdimage_table.pl @@ -0,0 +1,85 @@ +#!/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 +# 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 + diff --git a/gui/bimagemgr/temp.html b/gui/bimagemgr/temp.html new file mode 100644 index 0000000000..e69de29bb2