From: Andreas Gohr Date: Tue, 19 Jun 2007 14:07:20 +0000 (+0200) Subject: file hierachy reordering X-Git-Tag: 0.7.1~62 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=64fca63a29fb2a863d159734627795acfb17c853;p=contagged file hierachy reordering darcs-hash:20070619140720-6e07b-2001276d635b4578c12c90724ce6b2cd7f41e785.gz --- diff --git a/COPYING b/COPYING deleted file mode 100644 index 5b6e7c6..0000000 --- a/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - 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/Contact_Vcard_Parse.php b/Contact_Vcard_Parse.php deleted file mode 100644 index da1f16f..0000000 --- a/Contact_Vcard_Parse.php +++ /dev/null @@ -1,836 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: Contact_Vcard_Parse.php,v 1.1 2004/06/01 08:48:59 gohr Exp $ - - -/** -* -* Parser for vCards. -* -* This class parses vCard 2.1 and 3.0 sources from file or text into a -* structured array. -* -* Usage: -* -* -* // include this class file -* require_once 'Contact_Vcard_Parse.php'; -* -* // instantiate a parser object -* $parse = new Contact_Vcard_Parse(); -* -* // parse a vCard file and store the data -* // in $cardinfo -* $cardinfo = $parse->fromFile('sample.vcf'); -* -* // view the card info array -* echo '
';
-*     print_r($cardinfo);
-*     echo '
'; -*
-* -* -* @author Paul M. Jones -* -* @package Contact_Vcard_Parse -* -* @version 1.30 -* -*/ - -class Contact_Vcard_Parse { - - - /** - * - * Reads a file for parsing, then sends it to $this->fromText() - * and returns the results. - * - * @access public - * - * @param array $filename The filename to read for vCard information. - * - * @return array An array of of vCard information extracted from the - * file. - * - * @see Contact_Vcard_Parse::fromText() - * - * @see Contact_Vcard_Parse::_fromArray() - * - */ - - function fromFile($filename, $decode_qp = true) - { - $text = $this->fileGetContents($filename); - - if ($text === false) { - return false; - } else { - // dump to, and get return from, the fromText() method. - return $this->fromText($text, $decode_qp); - } - } - - - /** - * - * Reads the contents of a file. Included for users whose PHP < 4.3.0. - * - * @access public - * - * @param array $filename The filename to read for vCard information. - * - * @return string|bool The contents of the file if it exists and is - * readable, or boolean false if not. - * - * @see Contact_Vcard_Parse::fromFile() - * - */ - - function fileGetContents($filename) - { - if (file_exists($filename) && - is_readable($filename)) { - - $text = ''; - $len = filesize($filename); - - $fp = fopen($filename, 'r'); - while ($line = fread($fp, filesize($filename))) { - $text .= $line; - } - fclose($fp); - - return $text; - - } else { - - return false; - - } - } - - - /** - * - * Prepares a block of text for parsing, then sends it through and - * returns the results from $this->fromArray(). - * - * @access public - * - * @param array $text A block of text to read for vCard information. - * - * @return array An array of vCard information extracted from the - * source text. - * - * @see Contact_Vcard_Parse::_fromArray() - * - */ - - function fromText($text, $decode_qp = true) - { - // convert all kinds of line endings to Unix-standard and get - // rid of double blank lines. - $this->convertLineEndings($text); - - // unfold lines. concat two lines where line 1 ends in \n and - // line 2 starts with a whitespace character. only removes - // the first whitespace character, leaves others in place. - $fold_regex = '(\n)([ |\t])'; - $text = preg_replace("/$fold_regex/i", "", $text); - - // massage for Macintosh OS X Address Book (remove nulls that - // Address Book puts in for unicode chars) - $text = str_replace("\x00", '', $text); - - // convert the resulting text to an array of lines - $lines = explode("\n", $text); - - // parse the array of lines and return vCard info - return $this->_fromArray($lines, $decode_qp); - } - - - /** - * - * Converts line endings in text. - * - * Takes any text block and converts all line endings to UNIX - * standard. DOS line endings are \r\n, Mac are \r, and UNIX is \n. - * - * NOTE: Acts on the text block in-place; does not return a value. - * - * @access public - * - * @param string $text The string on which to convert line endings. - * - * @return void - * - */ - - function convertLineEndings(&$text) - { - // DOS - $text = str_replace("\r\n", "\n", $text); - - // Mac - $text = str_replace("\r", "\n", $text); - } - - - /** - * - * Splits a string into an array at semicolons. Honors backslash- - * escaped semicolons (i.e., splits at ';' not '\;'). - * - * @access public - * - * @param string $text The string to split into an array. - * - * @param bool $convertSingle If splitting the string results in a - * single array element, return a string instead of a one-element - * array. - * - * @return mixed An array of values, or a single string. - * - */ - - function splitBySemi($text, $convertSingle = false) - { - // we use these double-backs (\\) because they get get converted - // to single-backs (\) by preg_split. the quad-backs (\\\\) end - // up as as double-backs (\\), which is what preg_split requires - // to indicate a single backslash (\). what a mess. - $regex = '(? ; - * \, => , - * literal \n => newline - * - * @access public - * - * @param mixed $text The text to unescape. - * - * @return void - * - */ - - function unescape(&$text) - { - if (is_array($text)) { - foreach ($text as $key => $val) { - $this->unescape($val); - $text[$key] = $val; - } - } else { - $text = str_replace('\;', ';', $text); - $text = str_replace('\,', ',', $text); - $text = str_replace('\n', "\n", $text); - } - } - - - /** - * - * Emulated destructor. - * - * @access private - * @return boolean true - * - */ - - function _Contact_Vcard_Parse() - { - return true; - } - - - /** - * - * Parses an array of source lines and returns an array of vCards. - * Each element of the array is itself an array expressing the types, - * parameters, and values of each part of the vCard. Processes both - * 2.1 and 3.0 vCard sources. - * - * @access private - * - * @param array $source An array of lines to be read for vCard - * information. - * - * @return array An array of of vCard information extracted from the - * source array. - * - */ - - function _fromArray($source, $decode_qp = true) - { - // the info array will hold all resulting vCard information. - $info = array(); - - // tells us whether the source text indicates the beginning of a - // new vCard with a BEGIN:VCARD tag. - $begin = false; - - // holds information about the current vCard being read from the - // source text. - $card = array(); - - // loop through each line in the source array - foreach ($source as $line) { - - // if the line is blank, skip it. - if (trim($line) == '') { - continue; - } - - // find the first instance of ':' on the line. The part - // to the left of the colon is the type and parameters; - // the part to the right of the colon is the value data. - $pos = strpos($line, ':'); - - // if there is no colon, skip the line. - if ($pos === false) { - continue; - } - - // get the left and right portions - $left = trim(substr($line, 0, $pos)); - $right = trim(substr($line, $pos+1, strlen($line))); - - // have we started yet? - if (! $begin) { - - // nope. does this line indicate the beginning of - // a new vCard? - if (strtoupper($left) == 'BEGIN' && - strtoupper($right) == 'VCARD') { - - // tell the loop that we've begun a new card - $begin = true; - } - - // regardless, loop to the next line of source. if begin - // is still false, the next loop will check the line. if - // begin has now been set to true, the loop will start - // collecting card info. - continue; - - } else { - - // yep, we've started, but we don't know how far along - // we are in the card. is this the ending line of the - // current vCard? - if (strtoupper($left) == 'END' && - strtoupper($right) == 'VCARD') { - - // yep, we're done. keep the info from the current - // card... - $info[] = $card; - - // ...and reset to grab a new card if one exists in - // the source array. - $begin = false; - $card = array(); - - } else { - - // we're not on an ending line, so collect info from - // this line into the current card. split the - // left-portion of the line into a type-definition - // (the kind of information) and parameters for the - // type. - $typedef = $this->_getTypeDef($left); - $params = $this->_getParams($left); - - // if we are decoding quoted-printable, do so now. - // QUOTED-PRINTABLE is not allowed in version 3.0, - // but we don't check for versioning, so we do it - // regardless. ;-) - $this->_decode_qp($params, $right); - - // now get the value-data from the line, based on - // the typedef - switch ($typedef) { - - case 'N': - // structured name of the person - $value = $this->_parseN($right); - break; - - case 'ADR': - // structured address of the person - $value = $this->_parseADR($right); - break; - - case 'NICKNAME': - // nicknames - $value = $this->_parseNICKNAME($right); - break; - - case 'ORG': - // organizations the person belongs to - $value = $this->_parseORG($right); - break; - - case 'CATEGORIES': - // categories to which this card is assigned - $value = $this->_parseCATEGORIES($right); - break; - - case 'GEO': - // geographic coordinates - $value = $this->_parseGEO($right); - break; - - default: - // by default, just grab the plain value. keep - // as an array to make sure *all* values are - // arrays. for consistency. ;-) - $value = array(array($right)); - break; - } - - // add the type, parameters, and value to the - // current card array. note that we allow multiple - // instances of the same type, which might be dumb - // in some cases (e.g., N). - $card[$typedef][] = array( - 'param' => $params, - 'value' => $value - ); - } - } - } - - $this->unescape($info); - return $info; - } - - - /** - * - * Takes a vCard line and extracts the Type-Definition for the line. - * - * @access private - * - * @param string $text A left-part (before-the-colon part) from a - * vCard line. - * - * @return string The type definition for the line. - * - */ - - function _getTypeDef($text) - { - // split the text by semicolons - $split = $this->splitBySemi($text); - - // only return first element (the typedef) - return $split[0]; - } - - - /** - * - * Finds the Type-Definition parameters for a vCard line. - * - * @access private - * - * @param string $text A left-part (before-the-colon part) from a - * vCard line. - * - * @return mixed An array of parameters. - * - */ - - function _getParams($text) - { - // split the text by semicolons into an array - $split = $this->splitBySemi($text); - - // drop the first element of the array (the type-definition) - array_shift($split); - - // set up an array to retain the parameters, if any - $params = array(); - - // loop through each parameter. the params may be in the format... - // "TYPE=type1,type2,type3" - // ...or... - // "TYPE=type1;TYPE=type2;TYPE=type3" - foreach ($split as $full) { - - // split the full parameter at the equal sign so we can tell - // the parameter name from the parameter value - $tmp = explode("=", $full); - - // the key is the left portion of the parameter (before - // '='). if in 2.1 format, the key may in fact be the - // parameter value, not the parameter name. - $key = strtoupper(trim($tmp[0])); - - // get the parameter name by checking to see if it's in - // vCard 2.1 or 3.0 format. - $name = $this->_getParamName($key); - - // list of all parameter values - $listall = trim($tmp[1]); - - // if there is a value-list for this parameter, they are - // separated by commas, so split them out too. - $list = $this->splitByComma($listall); - - // now loop through each value in the parameter and retain - // it. if the value is blank, that means it's a 2.1-style - // param, and the key itself is the value. - foreach ($list as $val) { - if (trim($val) != '') { - // 3.0 formatted parameter - $params[$name][] = trim($val); - } else { - // 2.1 formatted parameter - $params[$name][] = $key; - } - } - - // if, after all this, there are no parameter values for the - // parameter name, retain no info about the parameter (saves - // ram and checking-time later). - if (count($params[$name]) == 0) { - unset($params[$name]); - } - } - - // return the parameters array. - return $params; - } - - - /** - * - * Looks at the parameters of a vCard line; if one of them is - * ENCODING[] => QUOTED-PRINTABLE then decode the text in-place. - * - * @access private - * - * @param array $params A parameter array from a vCard line. - * - * @param string $text A right-part (after-the-colon part) from a - * vCard line. - * - * @return void - * - */ - - function _decode_qp(&$params, &$text) - { - // loop through each parameter - foreach ($params as $param_key => $param_val) { - - // check to see if it's an encoding param - if (trim(strtoupper($param_key)) == 'ENCODING') { - - // loop through each encoding param value - foreach ($param_val as $enc_key => $enc_val) { - - // if any of the values are QP, decode the text - // in-place and return - if (trim(strtoupper($enc_val)) == 'QUOTED-PRINTABLE') { - $text = quoted_printable_decode($text); - return; - } - } - } - } - } - - - /** - * - * Returns parameter names from 2.1-formatted vCards. - * - * The vCard 2.1 specification allows parameter values without a - * name. The parameter name is then determined from the unique - * parameter value. - * - * Shamelessly lifted from Frank Hellwig and his - * vCard PHP project . - * - * @access private - * - * @param string $value The first element in a parameter name-value - * pair. - * - * @return string The proper parameter name (TYPE, ENCODING, or - * VALUE). - * - */ - - function _getParamName($value) - { - static $types = array ( - 'DOM', 'INTL', 'POSTAL', 'PARCEL','HOME', 'WORK', - 'PREF', 'VOICE', 'FAX', 'MSG', 'CELL', 'PAGER', - 'BBS', 'MODEM', 'CAR', 'ISDN', 'VIDEO', - 'AOL', 'APPLELINK', 'ATTMAIL', 'CIS', 'EWORLD', - 'INTERNET', 'IBMMAIL', 'MCIMAIL', - 'POWERSHARE', 'PRODIGY', 'TLX', 'X400', - 'GIF', 'CGM', 'WMF', 'BMP', 'MET', 'PMB', 'DIB', - 'PICT', 'TIFF', 'PDF', 'PS', 'JPEG', 'QTIME', - 'MPEG', 'MPEG2', 'AVI', - 'WAVE', 'AIFF', 'PCM', - 'X509', 'PGP' - ); - - // CONTENT-ID added by pmj - static $values = array ( - 'INLINE', 'URL', 'CID', 'CONTENT-ID' - ); - - // 8BIT added by pmj - static $encodings = array ( - '7BIT', '8BIT', 'QUOTED-PRINTABLE', 'BASE64' - ); - - // changed by pmj to the following so that the name defaults to - // whatever the original value was. Frank Hellwig's original - // code was "$name = 'UNKNOWN'". - $name = $value; - - if (in_array($value, $types)) { - $name = 'TYPE'; - } elseif (in_array($value, $values)) { - $name = 'VALUE'; - } elseif (in_array($value, $encodings)) { - $name = 'ENCODING'; - } - - return $name; - } - - - /** - * - * Parses a vCard line value identified as being of the "N" - * (structured name) type-defintion. - * - * @access private - * - * @param string $text The right-part (after-the-colon part) of a - * vCard line. - * - * @return array An array of key-value pairs where the key is the - * portion-name and the value is the portion-value. The value itself - * may be an array as well if multiple comma-separated values were - * indicated in the vCard source. - * - */ - - function _parseN($text) - { - $tmp = $this->splitBySemi($text); - return array( - $this->splitByComma($tmp[0]), // family (last) - $this->splitByComma($tmp[1]), // given (first) - $this->splitByComma($tmp[2]), // addl (middle) - $this->splitByComma($tmp[3]), // prefix - $this->splitByComma($tmp[4]) // suffix - ); - } - - - /** - * - * Parses a vCard line value identified as being of the "ADR" - * (structured address) type-defintion. - * - * @access private - * - * @param string $text The right-part (after-the-colon part) of a - * vCard line. - * - * @return array An array of key-value pairs where the key is the - * portion-name and the value is the portion-value. The value itself - * may be an array as well if multiple comma-separated values were - * indicated in the vCard source. - * - */ - - function _parseADR($text) - { - $tmp = $this->splitBySemi($text); - return array( - $this->splitByComma($tmp[0]), // pob - $this->splitByComma($tmp[1]), // extend - $this->splitByComma($tmp[2]), // street - $this->splitByComma($tmp[3]), // locality (city) - $this->splitByComma($tmp[4]), // region (state) - $this->splitByComma($tmp[5]), // postcode (ZIP) - $this->splitByComma($tmp[6]) // country - ); - } - - - /** - * - * Parses a vCard line value identified as being of the "NICKNAME" - * (informal or descriptive name) type-defintion. - * - * @access private - * - * @param string $text The right-part (after-the-colon part) of a - * vCard line. - * - * @return array An array of nicknames. - * - */ - - function _parseNICKNAME($text) - { - return array($this->splitByComma($text)); - } - - - /** - * - * Parses a vCard line value identified as being of the "ORG" - * (organizational info) type-defintion. - * - * @access private - * - * @param string $text The right-part (after-the-colon part) of a - * vCard line. - * - * @return array An array of organizations; each element of the array - * is itself an array, which indicates primary organization and - * sub-organizations. - * - */ - - function _parseORG($text) - { - $tmp = $this->splitbySemi($text); - $list = array(); - foreach ($tmp as $val) { - $list[] = array($val); - } - - return $list; - } - - - /** - * - * Parses a vCard line value identified as being of the "CATEGORIES" - * (card-category) type-defintion. - * - * @access private - * - * @param string $text The right-part (after-the-colon part) of a - * vCard line. - * - * @return mixed An array of categories. - * - */ - - function _parseCATEGORIES($text) - { - return array($this->splitByComma($text)); - } - - - /** - * - * Parses a vCard line value identified as being of the "GEO" - * (geographic coordinate) type-defintion. - * - * @access private - * - * @param string $text The right-part (after-the-colon part) of a - * vCard line. - * - * @return mixed An array of lat-lon geocoords. - * - */ - - function _parseGEO($text) - { - $tmp = $this->splitBySemi($text); - return array( - array($tmp[0]), // lat - array($tmp[1]) // lon - ); - } -} - -?> \ No newline at end of file diff --git a/README b/README deleted file mode 100644 index d37c796..0000000 --- a/README +++ /dev/null @@ -1,112 +0,0 @@ -=== ABOUT === - -ConTagged is a webbased address book for small companies. It features a public -address book which is writable for all company staff and a personal address -book for each staff member. ConTagged requires an already setup LDAP server to -authenticate users and store it's data. - -=== REQUIREMENTS === - -You need to have a running LDAP Server with some users (objectClass=posixUser) -in it. It is important that you already have these users because LDAPab uses -them to authenticate. - -You need a webserver (peferable Apache) with PHP (4.3 or higher). PHP needs to -be compiled with LDAP support (compiled in or as extension) - -=== SETUP LDAPab === - -Copy the contents of the .tgz file to a directory below your webserver document -root. Make sure the webserver is able to write to the cache directory which is -used for the template engine's cache files. A 'chmod 777 cache' will do. - -Open the config.php file in your favourite editor and edit the options -according to your needs. Some knowlege about LDAP may come in handy. - -If HTTP auth is wanted have a look at the provided _htaccess file, edit it as -needed and rename it back to .htaccess - -=== SETUP THE LDAP SERVER === - -The following only describes what to do for open-ldap 2.0! If you use any -other LDAP server you're left to our own. - -You need to include the inetOrgPerson schema in you slapd.conf: - - include /etc/ldap/schema/inetorgperson.schema - -If youwant to use the extended schema (needed for tagging and birthday support) -you need to copy the ldapab.schema file to /etc/ldap/schema/ and include it, too. - - include /etc/ldap/schema/ldapab.schema - -Be sure to enable the extended option in config.php. - -To setup the access rights add the following statement to your slapd.conf. Of -course you have to replace "o=cosmocode,c=de" with your own root DN. The first -entry may have to adjusted also if your users aren't stored in a ou=people -entry. Make sure you include these lines before other access control lists that -match these parts of the ldap tree. If you are unsure have a look at the -included slapd.example file - - access to dn.regex="(.*,)?ou=contacts,cn=([^,]+),ou=people,(.*)$" - by dn.regex="cn=$2,ou=people,$3" write - by * none - - access to dn.subtree="ou=contacts,o=cosmocode,c=de" - by users write - by * read - -After this modifications you have to restart the slapd server. - -The last thing is to add the contacts leafs to your LDAP tree. You'll need to -add a global contacts leaf at top. - - eg: 'ou=contacts,o=cosmocode,c=de' - -And a contacts leaf for every user. - - eg: 'ou=contacts,cn=Joe Schmoe,ou=people,o=cosmocode,c=de' - - -If you made everything correct you can point your webbrowser to the newly -installed ConTagged and use it :-) If you encounter problems try to enable -logging in your LDAP server to see what the problem is. - -=== FEEDBACK, PATCHES, SUPPORT === - -This software was developed to satisfy a need in our company. We give it to the -public because it may be helpful to other companies with the same needs. -However this is not a supported product. We like to get feedback and patches -but we can't promise to answer, to fix bugs or include feature wishes. However -don't hesitate to contact us but understand that our core business has priority -over this project. - -To contact us send a mail to ldapab@cosmocode.de or visit our homepage at -http://www.cosmocode.de - -=== KNOWN BUGS === - -ConTagged was only tested with open-ldap 2.1 - there may be problems with other -LDAP Servers. - -=== LICENSE === - -ConTagged - An LDAP based Company Address Book -Copyright 2004 - 2006 - CosmoCode GmbH - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of -the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -See COPYING for details diff --git a/TODO b/TODO deleted file mode 100644 index 478af17..0000000 --- a/TODO +++ /dev/null @@ -1,6 +0,0 @@ -Any help is welcome :-) - - - clean up the code - - clean up the HTML (make it validate) - - clean up the CSS (it's a mess) - - spice up interface (some more web2.0 colors and fonts would be a start) diff --git a/ajax.php b/ajax.php index 997eba1..7e16b2f 100644 --- a/ajax.php +++ b/ajax.php @@ -1,14 +1,7 @@ <[!CDATA['; -print_r($_REQUEST); -echo ']]>'; -*/ - $FIELD = preg_replace('/entry\[/','',$_REQUEST['field']); $FIELD = preg_replace('/\W+/','',$FIELD); @@ -46,7 +39,7 @@ function ajax_addnote($dn,$note){ ldap_modify($LDAP_CON,$dn,$entry); - require_once(dirname(__FILE__).'/smarty/plugins/modifier.noteparser.php'); + require_once(dirname(__FILE__).'/inc/smarty/plugins/modifier.noteparser.php'); print smarty_modifier_noteparser($note); } diff --git a/config.php b/config.php deleted file mode 100644 index d46910e..0000000 --- a/config.php +++ /dev/null @@ -1,59 +0,0 @@ - + 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/doc/README b/doc/README new file mode 100644 index 0000000..d37c796 --- /dev/null +++ b/doc/README @@ -0,0 +1,112 @@ +=== ABOUT === + +ConTagged is a webbased address book for small companies. It features a public +address book which is writable for all company staff and a personal address +book for each staff member. ConTagged requires an already setup LDAP server to +authenticate users and store it's data. + +=== REQUIREMENTS === + +You need to have a running LDAP Server with some users (objectClass=posixUser) +in it. It is important that you already have these users because LDAPab uses +them to authenticate. + +You need a webserver (peferable Apache) with PHP (4.3 or higher). PHP needs to +be compiled with LDAP support (compiled in or as extension) + +=== SETUP LDAPab === + +Copy the contents of the .tgz file to a directory below your webserver document +root. Make sure the webserver is able to write to the cache directory which is +used for the template engine's cache files. A 'chmod 777 cache' will do. + +Open the config.php file in your favourite editor and edit the options +according to your needs. Some knowlege about LDAP may come in handy. + +If HTTP auth is wanted have a look at the provided _htaccess file, edit it as +needed and rename it back to .htaccess + +=== SETUP THE LDAP SERVER === + +The following only describes what to do for open-ldap 2.0! If you use any +other LDAP server you're left to our own. + +You need to include the inetOrgPerson schema in you slapd.conf: + + include /etc/ldap/schema/inetorgperson.schema + +If youwant to use the extended schema (needed for tagging and birthday support) +you need to copy the ldapab.schema file to /etc/ldap/schema/ and include it, too. + + include /etc/ldap/schema/ldapab.schema + +Be sure to enable the extended option in config.php. + +To setup the access rights add the following statement to your slapd.conf. Of +course you have to replace "o=cosmocode,c=de" with your own root DN. The first +entry may have to adjusted also if your users aren't stored in a ou=people +entry. Make sure you include these lines before other access control lists that +match these parts of the ldap tree. If you are unsure have a look at the +included slapd.example file + + access to dn.regex="(.*,)?ou=contacts,cn=([^,]+),ou=people,(.*)$" + by dn.regex="cn=$2,ou=people,$3" write + by * none + + access to dn.subtree="ou=contacts,o=cosmocode,c=de" + by users write + by * read + +After this modifications you have to restart the slapd server. + +The last thing is to add the contacts leafs to your LDAP tree. You'll need to +add a global contacts leaf at top. + + eg: 'ou=contacts,o=cosmocode,c=de' + +And a contacts leaf for every user. + + eg: 'ou=contacts,cn=Joe Schmoe,ou=people,o=cosmocode,c=de' + + +If you made everything correct you can point your webbrowser to the newly +installed ConTagged and use it :-) If you encounter problems try to enable +logging in your LDAP server to see what the problem is. + +=== FEEDBACK, PATCHES, SUPPORT === + +This software was developed to satisfy a need in our company. We give it to the +public because it may be helpful to other companies with the same needs. +However this is not a supported product. We like to get feedback and patches +but we can't promise to answer, to fix bugs or include feature wishes. However +don't hesitate to contact us but understand that our core business has priority +over this project. + +To contact us send a mail to ldapab@cosmocode.de or visit our homepage at +http://www.cosmocode.de + +=== KNOWN BUGS === + +ConTagged was only tested with open-ldap 2.1 - there may be problems with other +LDAP Servers. + +=== LICENSE === + +ConTagged - An LDAP based Company Address Book +Copyright 2004 - 2006 - CosmoCode GmbH + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of +the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +See COPYING for details diff --git a/doc/TODO b/doc/TODO new file mode 100644 index 0000000..478af17 --- /dev/null +++ b/doc/TODO @@ -0,0 +1,6 @@ +Any help is welcome :-) + + - clean up the code + - clean up the HTML (make it validate) + - clean up the CSS (it's a mess) + - spice up interface (some more web2.0 colors and fonts would be a start) diff --git a/doc/docs b/doc/docs new file mode 100644 index 0000000..19f2060 --- /dev/null +++ b/doc/docs @@ -0,0 +1,51 @@ +# LDAP 2 Schema +# +# This is a schema extension for the LDAPab Addressbook by +# CosmoCode GmbH www.cosmocode.de +# +# CosmoCode owns the following MIB Block: +# iso.org.dod.internet.private.enterprise.16331.* +# +# CosmoCode currently uses the following OID hierachy to organize the IDs: +# +# defined in cosmo4ML.schema +# 1.3.6.1.4.1.16331.1 formel CMS (cosmo4ML prefix) +# 1.3.6.1.4.1.16331.1.1 SNMP (not used) +# 1.3.6.1.4.1.16331.1.2 LDAP +# 1.3.6.1.4.1.16331.1.2.1 AttributeTypes +# 1.3.6.1.4.1.16331.1.2.2 ObjectClasses +# +# defined in ldapab.schema: +# 1.3.6.1.4.1.16331.2 LDAPab +# 1.3.6.1.4.1.16331.2.1 SNMP (not used) +# 1.3.6.1.4.1.16331.2.2 LDAP +# 1.3.6.1.4.1.16331.2.2.1 AttributeTypes +# 1.3.6.1.4.1.16331.2.2.2 ObjectClasses + + +# OID macros for ease of use: +objectIdentifier cosmocodeOID 1.3.6.1.4.1.16331 +objectIdentifier LDAPab cosmocodeOID:2.2 + + +attributetype ( 1.3.6.1.4.1.16331.2.2.1.1 NAME 'anniversary' + DESC 'Holds Birthdays etc.' + EQUALITY caseIgnoreMatch + ORDERING caseIgnoreOrderingMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.16331.2.2.1.2 NAME 'marker' + DESC 'marking flag' + EQUALITY caseIgnoreMatch + ORDERING caseIgnoreOrderingMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} + ) + +objectclass ( 1.3.6.1.4.1.16331.2.2.2.1 NAME 'contactPerson' + DESC 'Contact - Addressbook entry' + AUXILIARY + MAY ( anniversary $ marker ) + ) diff --git a/doc/slapd.example b/doc/slapd.example new file mode 100644 index 0000000..cd7643a --- /dev/null +++ b/doc/slapd.example @@ -0,0 +1,111 @@ +# This is the main ldapd configuration file. See slapd.conf(5) for more +# info on the configuration options. + +# Schema and objectClass definitions +include /etc/ldap/schema/core.schema +include /etc/ldap/schema/cosine.schema +include /etc/ldap/schema/nis.schema +include /etc/ldap/schema/inetorgperson.schema +include /etc/ldap/schema/samba.schema +include /etc/ldap/schema/courierimap.schema +include /etc/ldap/schema/phpgwaccount.schema +include /etc/ldap/schema/phpgwcontact.schema +include /etc/ldap/schema/ldapab.schema + + +# Schema check allows for forcing entries to +# match schemas for their objectClasses's +schemacheck on + +# Where the pid file is put. The init.d script +# will not stop the server if you change this. +pidfile /var/run/slapd.pid + +# List of arguments that were passed to the server +argsfile /var/run/slapd.args + +# Where to store the replica logs +replogfile /var/lib/ldap/replog + +# Read slapd.conf(5) for possible values +#loglevel 256 +loglevel 0 + +####################################################################### +# ldbm database definitions +####################################################################### + +# The backend type, ldbm, is the default standard +database ldbm + +# The base of your directory +suffix "o=cosmocode,c=de" + +# Where the database file are physically stored +directory "/var/lib/ldap" + +# Indexing options +index objectClass eq + +# Folgende Indizies sind im samba-LDAP-HOWTO empfohlen; + +## support pbb_getsampwnam() +index uid pres,eq +## support pdb_getsampwrid() +index rid eq + +## uncomment these if you are storing posixAccount and +## posixGroup entries in the directory as well +index uidNumber eq +index gidNumber eq +index cn eq +index memberUid eq + +# Save the time that the entry gets modified +lastmod on + +# The userPassword by default can be changed +# by the entry owning it if they are authenticated. +# Others should not be able to see it, except the +# admin entry below +access to attribute=userPassword + by dn="cn=admin,o=cosmocode,c=de" write + by anonymous auth + by self write + by * none + +access to attribute=lmPassword + by dn="cn=admin,o=cosmocode,c=de" write + by anonymous auth + by self write + by * none + +access to attribute=ntPassword + by dn="cn=admin,o=cosmocode,c=de" write + by anonymous auth + by self write + by * none + +# private LDAP Addressbook is readable and writable for the owner only +access to dn="(.*,)?ou=contacts,cn=([^,]+),ou=people,(.*)$" + by dn="cn=$2,ou=people,$3" write + by * none + +# global LDAP Addressbook is writable for all authenticated users +# This entry has to be _before_ any other entry that matches the contact +# tree eg. the * entry +access to dn.subtree="ou=contacts,o=cosmocode,c=de" + by users write + by * read + +# The admin dn has full write access +access to * + by dn="cn=admin,o=cosmocode,c=de" write + by * read + +# For Netscape Roaming support, each user gets a roaming +# profile for which they have write access to +#access to dn=".*,ou=Roaming,o=morsnet" +# by dn="cn=admin,o=cosmocode,c=de" write +# by dnattr=owner write + diff --git a/entries.conf b/entries.conf deleted file mode 100644 index 0809369..0000000 --- a/entries.conf +++ /dev/null @@ -1,20 +0,0 @@ -dn dn -sn name -givenName givenname -title title -o organization -physicalDeliveryOfficeName office -postalAddress street -postalCode zip -l location -telephoneNumber phone -facsimileTelephoneNumber fax -mobile mobile -pager pager -homePhone homephone -homePostalAddress homestreet -photo photo -jpegPhoto photo -labeledURI url -description note -manager manager diff --git a/entry.php b/entry.php index ec73909..e224522 100644 --- a/entry.php +++ b/entry.php @@ -1,141 +1,136 @@ - clean it up (trim, unique, sort) - $_REQUEST['entry'][$field] = array_map('trim',$_REQUEST['entry'][$field]); - $_REQUEST['entry'][$field] = array_unique($_REQUEST['entry'][$field]); - $_REQUEST['entry'][$field] = array_filter($_REQUEST['entry'][$field]); - natcasesort($_REQUEST['entry'][$field]); - } - } - $dn = _saveData(); + clean it up (trim, unique, sort) + $_REQUEST['entry'][$field] = array_map('trim',$_REQUEST['entry'][$field]); + $_REQUEST['entry'][$field] = array_unique($_REQUEST['entry'][$field]); + $_REQUEST['entry'][$field] = array_filter($_REQUEST['entry'][$field]); + natcasesort($_REQUEST['entry'][$field]); + } } + $dn = _saveData(); +} - if(empty($dn)){ - if(!$_REQUEST['mode']=='edit'){ - $smarty->assign('error','No dn was given'); - $template = 'error.tpl'; - } - }elseif(!empty($_REQUEST['del']) && $_REQUEST['del']){ - _delEntry($dn); - }elseif(!_fetchData($dn)){ - $smarty->assign('error',"The requested entry '$dn' was not found"); +if(empty($dn)){ + if(!$_REQUEST['mode']=='edit'){ + $smarty->assign('error','No dn was given'); $template = 'error.tpl'; } - - //prepare templates - $smarty->assign('dn',$dn); - $smarty->assign('managers',$users); - tpl_std(); - tpl_orgs(); - tpl_markers(); - tpl_categories(); - tpl_timezone(); - tpl_country(); - //display templates - if($_REQUEST['mode']=='vcf'){ - $entry = $smarty->get_template_vars('entry'); - $filename = $entry['givenname'].'_'.$entry['name'].'.vcf'; - header("Content-Disposition: attachment; filename=\"$filename\""); - header("Content-type: text/x-vcard; name=\"$filename\"; charset=utf-8"); - $smarty->display($template); - }else{ - header('Content-Type: text/html; charset=utf-8'); - $smarty->display($template); +}elseif(!empty($_REQUEST['del']) && $_REQUEST['del']){ + _delEntry($dn); +}elseif(!_fetchData($dn)){ + $smarty->assign('error',"The requested entry '$dn' was not found"); + $template = 'error.tpl'; +} + +//prepare templates +$smarty->assign('dn',$dn); +$smarty->assign('managers',$users); +tpl_std(); +//display templates +if($_REQUEST['mode']=='vcf'){ + $entry = $smarty->get_template_vars('entry'); + $filename = $entry['givenname'].'_'.$entry['name'].'.vcf'; + header("Content-Disposition: attachment; filename=\"$filename\""); + header("Content-type: text/x-vcard; name=\"$filename\"; charset=utf-8"); + $smarty->display($template); +}else{ + header('Content-Type: text/html; charset=utf-8'); + $smarty->display($template); +} + +//-------------------------------------------------------------- + +/** + * fetches the Data from the LDAP directory and assigns it to + * the global smarty object using tpl_entry() + */ +function _fetchData($dn){ + global $LDAP_CON; + global $conf; + global $smarty; + global $users; //contains the users for manager role + + $sr = ldap_search($LDAP_CON,$dn,'(objectClass=inetOrgPerson)'); + if(!ldap_count_entries($LDAP_CON,$sr)){ + return false; } + $result = ldap_get_binentries($LDAP_CON, $sr); + $entry = $result[0]; - //-------------------------------------------------------------- - - /** - * fetches the Data from the LDAP directory and assigns it to - * the global smarty object using tpl_entry() - */ - function _fetchData($dn){ - global $LDAP_CON; - global $conf; - global $smarty; - global $users; //contains the users for manager role - - $sr = ldap_search($LDAP_CON,$dn,'(objectClass=inetOrgPerson)'); - if(!ldap_count_entries($LDAP_CON,$sr)){ - return false; - } - $result = ldap_get_binentries($LDAP_CON, $sr); - $entry = $result[0]; - - //remove dn from entry when copy - if(!empty($_REQUEST['mode']) && $_REQUEST['mode'] == 'copy'){ - $entry['dn']=''; - } + //remove dn from entry when copy + if(!empty($_REQUEST['mode']) && $_REQUEST['mode'] == 'copy'){ + $entry['dn']=''; + } - //assign entry to template: - tpl_entry($entry); + //assign entry to template: + tpl_entry($entry); /*print '
';
 print_r($entry);
 print '
';*/ - // make username from dn for manager: - if (empty($entry['manager'])) { $entry['manager']=array(""); } - if (empty($users[$entry['manager'][0]])) { $users[$entry['manager'][0]]=''; } - $smarty->assign('managername',$users[$entry['manager'][0]]); - return true; + // make username from dn for manager: + if (empty($entry['manager'])) { $entry['manager']=array(""); } + if (empty($users[$entry['manager'][0]])) { $users[$entry['manager'][0]]=''; } + $smarty->assign('managername',$users[$entry['manager'][0]]); + return true; +} + +/** + * saves the data from $_REQUEST['entry'] to the LDAP directory + * + * returns given or constructed dn + */ +function _saveData(){ + global $LDAP_CON; + global $conf; + global $FIELDS; + global $OCLASSES; + + $entry = $_REQUEST['entry']; + $dn = $_REQUEST['dn']; + //construct new dn + $now = time(); + $newdn = 'uid='.$now; + if (empty($_REQUEST['type'])) { $_REQUEST['type']='public'; } + if($_REQUEST['type'] == 'private'){ + $newdn .= ', '.$conf['privatebook'].', '.$_SESSION['ldapab']['binddn']; + }else{ + $newdn .= ', '.$conf['publicbook']; } - - /** - * saves the data from $_REQUEST['entry'] to the LDAP directory - * - * returns given or constructed dn - */ - function _saveData(){ - global $LDAP_CON; - global $conf; - global $FIELDS; - global $OCLASSES; - - $entry = $_REQUEST['entry']; - $dn = $_REQUEST['dn']; - //construct new dn - $now = time(); - $newdn = 'uid='.$now; - if (empty($_REQUEST['type'])) { $_REQUEST['type']='public'; } - if($_REQUEST['type'] == 'private'){ - $newdn .= ', '.$conf['privatebook'].', '.$_SESSION['ldapab']['binddn']; - }else{ - $newdn .= ', '.$conf['publicbook']; - } - $entry['displayname'] = $entry['givenname'].' '.$entry['name'];; - $entry = prepare_ldap_entry($entry); + $entry['displayname'] = $entry['givenname'].' '.$entry['name'];; + $entry = prepare_ldap_entry($entry); /* print '
';
@@ -143,68 +138,68 @@ print_r($entry);
 print '
'; */ - if(empty($dn)){ - //new entry - $entry['uid'][] = $now; - $r = ldap_add($LDAP_CON,$newdn,$entry); - tpl_ldaperror(); - return $newdn; - }else{ - // update the objectClasses - ldap_store_objectclasses($dn,$OCLASSES); - unset($entry['objectclass']); - - //modify entry attribute by attribute - this ensure we don't delete unknown stuff - foreach (array_values($FIELDS) as $key){ - if($key == 'dn'){ + if(empty($dn)){ + //new entry + $entry['uid'][] = $now; + $r = ldap_add($LDAP_CON,$newdn,$entry); + tpl_ldaperror(); + return $newdn; + }else{ + // update the objectClasses + ldap_store_objectclasses($dn,$OCLASSES); + unset($entry['objectclass']); + + //modify entry attribute by attribute - this ensure we don't delete unknown stuff + foreach (array_values($FIELDS) as $key){ + if($key == 'dn'){ + continue; + }elseif(empty($entry[$key])){ + // field is empty -> handle deletion (except for photo unless deletion triggered) + if (empty($_REQUEST['delphoto'])) { $_REQUEST['delphoto']=0; } + if($key == 'jpegPhoto' && !$_REQUEST['delphoto']){ continue; - }elseif(empty($entry[$key])){ - // field is empty -> handle deletion (except for photo unless deletion triggered) - if (empty($_REQUEST['delphoto'])) { $_REQUEST['delphoto']=0; } - if($key == 'jpegPhoto' && !$_REQUEST['delphoto']){ - continue; - } - unset($del); - $del[$key]=array(); - $r = @ldap_mod_replace($LDAP_CON,$dn,$del); - tpl_ldaperror("del $key"); - }else{ - unset($add); - $add[$key]=$entry[$key]; - $r = @ldap_mod_replace($LDAP_CON,$dn,$add); - tpl_ldaperror("mod $key"); } + unset($del); + $del[$key]=array(); + $r = @ldap_mod_replace($LDAP_CON,$dn,$del); + tpl_ldaperror("del $key"); + }else{ + unset($add); + $add[$key]=$entry[$key]; + $r = @ldap_mod_replace($LDAP_CON,$dn,$add); + tpl_ldaperror("mod $key"); } - return $dn; } + return $dn; } - - /** - * does as the name says - delete the whole entry - */ - function _delEntry($dn){ - global $LDAP_CON; - if(ldap_full_delete($LDAP_CON,$dn,true)){ - header("Location: index.php"); - exit; - } +} + +/** + * does as the name says - delete the whole entry + */ +function _delEntry($dn){ + global $LDAP_CON; + if(ldap_full_delete($LDAP_CON,$dn,true)){ + header("Location: index.php"); + exit; } - - /** - * gets the binary data from an uploaded file - */ - function _getUploadData(){ - $file = $_FILES['photoupload']; - - if (is_uploaded_file($file['tmp_name'])) { - if(preg_match('=image/p?jpe?g=',$file['type'])){ - $fh = fopen($file['tmp_name'],'r'); - $data = fread($fh,$file['size']); - fclose($fh); - unlink($file['tmp_name']); - return $data; - } +} + +/** + * gets the binary data from an uploaded file + */ +function _getUploadData(){ + $file = $_FILES['photoupload']; + + if (is_uploaded_file($file['tmp_name'])) { + if(preg_match('=image/p?jpe?g=',$file['type'])){ + $fh = fopen($file['tmp_name'],'r'); + $data = fread($fh,$file['size']); + fclose($fh); + unlink($file['tmp_name']); + return $data; } - return ''; } + return ''; +} diff --git a/fields.php b/fields.php deleted file mode 100644 index 8f3d3c3..0000000 --- a/fields.php +++ /dev/null @@ -1,94 +0,0 @@ - 'dn', // don't touch! - 'name' => 'sn', - 'displayname' => 'cn', - 'givenname' => 'givenName', - 'title' => 'title', - 'organization' => 'o', // aka. company - 'office' => 'physicalDeliveryOfficeName', - 'street' => 'postalAddress', - 'zip' => 'postalCode', - 'location' => 'l', // aka. city - 'phone' => 'telephoneNumber', - 'fax' => 'facsimileTelephoneNumber', - 'mobile' => 'mobile', // aka. cell phone - 'pager' => 'pager', - 'homephone' => 'homePhone', - 'homestreet' => 'homePostalAddress', - 'photo' => 'jpegPhoto', - 'url' => 'labeledURI', - 'note' => 'description', - 'manager' => 'manager', // aka. key account - '_mail' => 'mail', -); - -/** - * If the provided "extended" schema is used the following fields - * and object classes are added - */ -$OCLASSES[] = 'contactPerson'; -$FIELDS['anniversary'] = 'anniversary'; -$FIELDS['_marker'] = 'marker'; // aka. tags - -/** - * If the open exchange schema is used the following fields - * and object classes are added - */ -/* comment in if you want to use it -$OCLASSES[] = 'OXUserObject'; -$FIELDS['country'] = 'userCountry'; -$FIELDS['birthday'] = 'birthDay'; -$FIELDS['ipphone'] = 'IPPhone'; -$FIELDS['_marker'] = 'OXUserCategories'; -$FIELDS['instantmessenger'] = 'OXUserInstantMessenger'; -$FIELDS['timezone'] = 'OXTimeZone'; -$FIELDS['position'] = 'OXUserPosition'; -$FIELDS['certificate'] = 'relClientCert'; -$FIELDS['domain'] = 'domain'; -*/ - -/** - * If the Evolution schema is used the following fields - * and object classes are added - */ -/* comment in if you want to use it -$OCLASSES[] = 'evolutionPerson'; -$OCLASSES[] = 'officePerson'; -$FIELDS['department'] = 'ou'; -$FIELDS['state'] = 'st'; -$FIELDS['country'] = 'c'; -$FIELDS['phone'] = 'primaryPhone'; -$FIELDS['switchboard'] = 'companyPhone'; -$FIELDS['note'] = 'note'; -$FIELDS['manager'] = 'seeAlso'; -$FIELDS['birthday'] = 'birthDate'; -$FIELDS['spouse'] = 'spouseName'; -*/ - - -/** - * Flip the array - */ -$RFIELDS = array_flip($FIELDS); - diff --git a/functions.php b/functions.php deleted file mode 100644 index 9166d31..0000000 --- a/functions.php +++ /dev/null @@ -1,486 +0,0 @@ -assign('USER',$_SESSION['ldapab']['username']); -} - -/** - * Uses Username and Password from Session to initialize the LDAP handle - * If it fails it redirects to login.php - */ -function ldap_login(){ - global $conf; - if(!empty($_SESSION['ldapab']['username'])){ - // existing session! Check if valid - if($_SESSION['ldapab']['browserid'] != auth_browseruid()){ - //session hijacking detected - header('Location: login.php?username='); - exit; - } - } elseif ($conf['httpd_auth'] && !empty($_SERVER['PHP_AUTH_USER'])) { - // use HTTP auth if wanted and possible - $_SESSION['ldapab']['username'] = $_SERVER['PHP_AUTH_USER']; - $_SESSION['ldapab']['password'] = $_SERVER['PHP_AUTH_PW']; - } elseif (!empty($_COOKIE['ldapabauth'])) { - // check persistent cookie - $cookie = base64_decode($_COOKIE['ldapabauth']); - $cookie = x_Decrypt($cookie,get_cookie_secret()); - list($u,$p) = unserialize($cookie); - $_SESSION['ldapab']['username'] = $u; - $_SESSION['ldapab']['password'] = $p; - } - - if(empty($_SESSION['ldapab']) || - !do_ldap_bind($_SESSION['ldapab']['username'], - $_SESSION['ldapab']['password'], - $_SESSION['ldapab']['binddn'])){ - header('Location: login.php?username='); - exit; - } -} - -/** - * Creates a global LDAP connection handle called $LDAP_CON - */ -function do_ldap_bind($user,$pass,$dn=""){ - global $conf; - global $LDAP_CON; - - //create global connection to LDAP if necessary - if(!$LDAP_CON){ - if (!empty($conf['ldapurl'])){ - $LDAP_CON = ldap_connect($conf['ldapurl']); - }else{ - $LDAP_CON = ldap_connect($conf['ldapserver'],$conf['ldapport']); - } - if(!$LDAP_CON){ - die("couldn't connect to LDAP server"); - } - } - - if($conf['ldapv3']) ldap_set_option($LDAP_CON, LDAP_OPT_PROTOCOL_VERSION, 3); - - if(empty($dn)){ - //anonymous bind to lookup users - //blank binddn or blank bindpw will result in anonymous bind - if(!ldap_bind($LDAP_CON,$conf['anonbinddn'],$conf['anonbindpw'])){ - die("can not bind for user lookup"); - } - - //when no user was given stay connected anonymous - if(empty($user)){ - set_session('','',''); - return true; - } - - //get dn for given user - $filter = str_replace('%u',$user,$conf['userfilter']); - $sr = ldap_search($LDAP_CON, $conf['usertree'], $filter);; - $result = ldap_get_entries($LDAP_CON, $sr); - if($result['count'] != 1){ - set_session('','',''); - return false; - } - $dn = $result[0]['dn']; - } - - //bind with dn - if(ldap_bind($LDAP_CON,$dn,$pass)){ - //bind successful -> set up session - set_session($user,$pass,$dn); - return true; - } - //bind failed -> remove session - set_session('','',''); - return false; -} - -/** - * Builds a pseudo UID from browser and IP data - * - * This is neither unique nor unfakable - still it adds some - * security. Using the first part of the IP makes sure - * proxy farms like AOLs are stil okay. - * - * @author Andreas Gohr - * - * @return string a MD5 sum of various browser headers - */ -function auth_browseruid(){ - $uid = ''; - if (empty($_SERVER['HTTP_USER_AGENT'])) { $_SERVER['HTTP_USER_AGENT']='USER_AGENT'; } - if (empty($_SERVER['HTTP_ACCEPT_ENCODING'])) { $_SERVER['HTTP_ACCEPT_ENCODING']='ACCEPT_ENCODING'; } - if (empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { $_SERVER['HTTP_ACCEPT_LANGUAGE']='ACCEPT_LANGUAGE'; } - if (empty($_SERVER['HTTP_ACCEPT_CHARSET'])) { $_SERVER['HTTP_ACCEPT_CHARSET']='ACCEPT_CHARSET'; } - $uid .= $_SERVER['HTTP_USER_AGENT']; - $uid .= $_SERVER['HTTP_ACCEPT_ENCODING']; - $uid .= $_SERVER['HTTP_ACCEPT_LANGUAGE']; - $uid .= $_SERVER['HTTP_ACCEPT_CHARSET']; - $uid .= substr($_SERVER['REMOTE_ADDR'],0,strpos($_SERVER['REMOTE_ADDR'],'.')); - return md5($uid); -} - - -/** - * saves user data to Session and cookies - */ -function set_session($user,$pass,$dn){ - global $conf; - - $rand = rand(); - $_SESSION['ldapab']['username'] = $user; - $_SESSION['ldapab']['binddn'] = $dn; - $_SESSION['ldapab']['password'] = $pass; - $_SESSION['ldapab']['browserid'] = auth_browseruid(); - - // (re)set the persistent auth cookie - if($user == ''){ - setcookie('ldapabauth','',time()+60*60*24*365); - }elseif(!empty($_REQUEST['remember'])){ - $cookie = serialize(array($user,$pass)); - $cookie = x_Encrypt($cookie,get_cookie_secret()); - $cookie = base64_encode($cookie); - setcookie('ldapabauth',$cookie,time()+60*60*24*365); - } -} - -/** - * Creates a random string to encrypt persistent auth - * cookies; the string is stored inside the cache dir - */ -function get_cookie_secret(){ - $file = dirname(__FILE__).'/cache/.htcookiesecret.php'; - if(@file_exists($file)){ - return md5(trim(file($file))); - } - - $secret = ''; - if(!$fh = fopen($file,'w')) die("Couldn't write to $file"); - if(fwrite($fh, $secret) === FALSE) die("Couldn't write to $file"); - fclose($fh); - - return md5($secret); -} - -/** - * binary safe function to get all search result data. - * It will use ldap_get_values_len() instead and build the array - * note: it's similar with the array returned by ldap_get_entries() - * except it has no "count" elements - * - * @author: Original code by Ovidiu Geaboc - */ -function ldap_get_binentries($conn,$srchRslt){ - if(!@ldap_count_entries($conn,$srchRslt)){ - return null; - } - $entry = ldap_first_entry($conn, $srchRslt); - $i=0; - do { - $dn = ldap_get_dn($conn,$entry); - $attrs = ldap_get_attributes($conn, $entry); - for($j=0; $j<$attrs['count']; $j++) { - $vals = ldap_get_values_len($conn, $entry,$attrs[$j]); - for($k=0; $k<$vals['count']; $k++){ - $data[$i][$attrs[$j]][$k]=$vals[$k]; - } - } - $data[$i]['dn']=$dn; - $i++; - }while ($entry = ldap_next_entry($conn, $entry)); - - return $data; -} - - -/** - * loads ldap names and their cleartext meanings from - * entries.conf file and returns it as hash - */ -function namedentries($flip=false){ - trigger_error('deprecated namedentries called',E_USER_WARNING); -} - -/** - * Creates an array for submission to ldap from websitedata - */ -function prepare_ldap_entry($in){ - global $conf; - global $FIELDS; - global $OCLASSES; - - //check dateformats - if(!preg_match('/\d\d\d\d-\d\d-\d\d/',$in['anniversary'])) $in['anniversary']=''; - if(!preg_match('/\d\d\d\d-\d\d-\d\d/',$in['birthday'])) $in['birthday']=''; - - // we map all internal names to the configured LDAP attributes here - foreach($in as $key => $value){ - if($FIELDS[$key]){ - // normal mapped field - $out[$FIELDS[$key]][] = $value; - }elseif($FIELDS["_$key"]){ - // mapped multi field - if(is_array($value)){ - $out[$FIELDS["_$key"]] = $value; - }else{ - $out[$FIELDS["_$key"]][] = $value; //shouldn't happen, but to be sure - } - }else{ - // no mapping found - assume it to be a LDAP attribute (shouldn't happen) - if(is_array($value)){ - $out[$key] = $value; - }else{ - $out[$key][] = $value; - } - } - } - - // add the Objectclasses - $out['objectclass'] = $OCLASSES; - - return clear_array($out); -} - -/** - * remove empty element from arrays recursively - * - * @author Original by - */ -function clear_array ( $a ) { - if ($a !== array()) { - $b = array(); - foreach ( $a as $key => $value ) { - if (is_array($value)) { - if (clear_array($value) !== false) { - $b[$key] = clear_array ( $value ); - } - } elseif ($value !== '') { - $b[$key] = $value; - } - } - if ($b !== array()) { - return $b; - } else { - return false; - } - } else { - return false; - } -} - -/** - * deletes an entryfrom ldap - optional with recursion - * - * @author Original by - */ -function ldap_full_delete($ds,$dn,$recursive=false){ - if($recursive == false){ - return(ldap_delete($ds,$dn)); - }else{ - //searching for sub entries - $sr=ldap_list($ds,$dn,"ObjectClass=*",array("")); - $info = ldap_get_entries($ds, $sr); - for($i=0;$i<$info['count'];$i++){ - //deleting recursively sub entries - $result=myldap_delete($ds,$info[$i]['dn'],$recursive); - if(!$result){ - //return result code, if delete fails - return($result); - } - } - return(ldap_delete($ds,$dn)); - } -} - -/** - * Returns all User Accounts as assoziative array - */ -function get_users(){ - global $conf; - global $LDAP_CON; - - $sr = ldap_list($LDAP_CON,$conf['usertree'],"ObjectClass=inetOrgPerson"); - $result = ldap_get_binentries($LDAP_CON, $sr); - $users = array(); - if(count($result)){ - foreach ($result as $entry){ - if(!empty($entry['sn'][0])){ - $users[$entry['dn']] = $entry['givenName'][0]." ".$entry['sn'][0]; - } - } - } - return $users; -} - -/** - * makes sure the given DN contains exactly one space - * after each , - */ -function normalize_dn($dn){ - $dn = preg_replace('/,/',', ',$dn); - $dn = preg_replace('/,\s+/',', ',$dn); - return $dn; -} - -/** - * Merges the given classes with the existing ones - */ -function ldap_store_objectclasses($dn,$classes){ - global $conf; - global $LDAP_CON; - - $sr = ldap_search($LDAP_CON,$dn,"objectClass=*",array('objectClass')); - $result = ldap_get_binentries($LDAP_CON, $sr); - $set = $result[0]['objectClass']; - $set = array_unique_renumber(array_merge((array)$set,(array)$classes)); - $add['objectClass'] = $set; - - $r = @ldap_mod_replace($LDAP_CON,$dn,$add); - tpl_ldaperror(); - -/* print '
';
-  print_r($set);
-  print '
';*/ -} - -/** - * Escape a string to be used in a LDAP filter - * - * Ported from Perl's Net::LDAP::Util escape_filter_value - * - * @author Andreas Gohr - */ -function ldap_filterescape($string){ - return preg_replace('/([\x00-\x1F\*\(\)\\\\])/e', - '"\\\\\".join("",unpack("H2","$1"))', - $string); -} - -/** - * Queries public and private addressbooks, combining the - * results - * - * @todo This function should be used where ever possible, replacing - * lots of duplicate code - */ -function ldap_queryabooks($filter,$types){ - global $conf; - global $LDAP_CON; - - // make sure $types is an array - if(!is_array($types)){ - $types = explode(',',$types); - $types = array_map('trim',$types); - } - - $results = array(); - $result1 = array(); - $result2 = array(); - - // public addressbook - $sr = ldap_list($LDAP_CON,$conf['publicbook'], - $filter,$types); - $result1 = ldap_get_binentries($LDAP_CON, $sr); - ldap_free_result($sr); - - // private addressbook - if(!empty($_SESSION['ldapab']['binddn'])){ - $sr = @ldap_list($LDAP_CON,$conf['privatebook']. - ','.$_SESSION['ldapab']['binddn'], - $filter,$types); - $result2 = ldap_get_binentries($LDAP_CON, $sr); - } - - // return merged results - return array_merge((array)$result1,(array)$result2); -} - -/** - * Makes array unique and renumbers the entries - * - * @author - */ -function array_unique_renumber($somearray){ - $tmparr = array_unique($somearray); - $i=0; - foreach ($tmparr as $v) { - $newarr[$i] = $v; - $i++; - } - return $newarr; -} - -/** - * Simple XOR encryption - * - * @author Dustin Schneider - * @link http://www.phpbuilder.com/tips/item.php?id=68 - */ -function x_Encrypt($string, $key){ - for($i=0; $i diff --git a/help.php b/help.php index dd933da..3efcf4d 100644 --- a/help.php +++ b/help.php @@ -1,11 +1,11 @@ -display('help.tpl'); +//prepare templates +tpl_std(); +//display templates +header('Content-Type: text/html; charset=utf-8'); +$smarty->display('help.tpl'); ?> diff --git a/img.php b/img.php index eeb4471..27a49b6 100644 --- a/img.php +++ b/img.php @@ -1,16 +1,16 @@ - diff --git a/import.php b/import.php index c26e85c..de4d3a2 100644 --- a/import.php +++ b/import.php @@ -1,162 +1,126 @@ fromFile($_FILES['userfile']['tmp_name']); - }elseif(preg_match('/^addressbook\.xml$/i', $_FILES['userfile']['name'])){ - //parse Zaurus Addressbook - $contacts = XML_unserialize(@join('',@file($_FILES['userfile']['tmp_name']))); - }else{ - $error = "Only *.vcf or addressbook.xml are accepted"; - } +$error = ''; +if(isset($_FILES['userfile'])){ + if (is_uploaded_file($_FILES['userfile']['tmp_name'])){ + if(preg_match('/\.vcf$/i', $_FILES['userfile']['name'])){ + //parse VCF + $vcfparser = new Contact_Vcard_Parse(); + $vcards = $vcfparser->fromFile($_FILES['userfile']['tmp_name']); }else{ - switch($_FILES['userfile']['error']){ - case 0: //no error; possible file attack! - $error = "There was a problem with your upload."; - break; - case 1: //uploaded file exceeds the upload_max_filesize directive in php.ini - $error = "The file you are trying to upload is too big."; - break; - case 2: //uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form - $error = "The file you are trying to upload is too big."; - break; - case 3: //uploaded file was only partially uploaded - $error = "The file you are trying upload was only partially uploaded."; - break; - case 4: //no file was uploaded - $error = "You must select a VCF file for upload."; - break; - default: //a default error, just in case! :) - $error = "There was a problem with your upload."; - break; - } - } - } - - //prepare templates for all found entries - $list = ''; - if(count($vcards)){ - foreach ($vcards as $vcard){ - $entry = vcard_entry($vcard); - $smarty->clear_all_assign(); - tpl_std(); - $smarty->assign('entry',$entry); - $list .= $smarty->fetch('import_entry.tpl'); + $error = "Only *.vcf accepted"; } - }elseif(count($contacts)){ - foreach ($contacts['AddressBook']['Contacts']['Contact'] as $contact){ - if (!is_array($contact)) continue; - $entry = zaurus_entry($contact); - $smarty->clear_all_assign(); - tpl_std(); - $smarty->assign('entry',$entry); - $list .= $smarty->fetch('import_entry.tpl'); + }else{ + switch($_FILES['userfile']['error']){ + case 0: //no error; possible file attack! + $error = "There was a problem with your upload."; + break; + case 1: //uploaded file exceeds the upload_max_filesize directive in php.ini + $error = "The file you are trying to upload is too big."; + break; + case 2: //uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form + $error = "The file you are trying to upload is too big."; + break; + case 3: //uploaded file was only partially uploaded + $error = "The file you are trying upload was only partially uploaded."; + break; + case 4: //no file was uploaded + $error = "You must select a VCF file for upload."; + break; + default: //a default error, just in case! :) + $error = "There was a problem with your upload."; + break; } } +} - //prepare templates - tpl_std(); - tpl_orgs(); - tpl_markers(); - $smarty->assign('error',$error); - $smarty->assign('list',$list); - //display templates - $smarty->display('header.tpl'); - $smarty->display('import.tpl'); - $smarty->display('footer.tpl'); - +//prepare templates for all found entries +$list = ''; +if(count($vcards)){ + foreach ($vcards as $vcard){ + $entry = vcard_entry($vcard); + $smarty->clear_all_assign(); + tpl_std(); + $smarty->assign('entry',$entry); + $list .= $smarty->fetch('import_entry.tpl'); + } +} -function zaurus_entry($cnct){ - $entry['name'] = $cnct['LastName']; - $entry['givenname'] = trim($cnct['FirstName'].' '.$cnct['MiddleName']); - $entry['title'] = $cnct['JobTitle']; - $entry['organization'] = $cnct['Company']; - $entry['office'] = $cnct['Office']; - $entry['note'] = $cnct['Notes']; - $entry['mail'] = split(' ',$cnct['Emails']); - $entry['street'] = $cnct['BusinessStreet']; - $entry['location'] = $cnct['BusinessCity']; - $entry['zip'] = $cnct['BusinessZip']; - $entry['homestreet'] = $cnct['HomeStreet']."\n". //str - $cnct['HomeZip']." ". //plz - $cnct['HomeCity']; //ort - $entry['homephone'] = $cnct['HomePhone']; - $entry['phone'] = $cnct['BusinessPhone']; - $entry['fax'] = empty($cnct['BusinessFax']) ? $cnct['HomeFax'] : $cnct['BusinessFax']; - $entry['mobile'] = empty($cnct['HomeMobile']) ? $cnct['BusinessMobile'] : $cnct['HomeMobile']; - $entry['fax'] = empty($cnct['BusinessFax']) ? $cnct['HomeFax'] : $cnct['BusinessFax']; +//prepare templates +tpl_std(); +tpl_orgs(); +tpl_markers(); +$smarty->assign('error',$error); +$smarty->assign('list',$list); +//display templates +$smarty->display('header.tpl'); +$smarty->display('import.tpl'); +$smarty->display('footer.tpl'); - return $entry; -} function vcard_entry($vcf){ - $entry['name'] = $vcf['N'][0]['value'][0][0]; - $entry['givenname'] = trim($vcf['N'][0]['value'][1][0].' '.$vcf['N'][0]['value'][2][0]); - $entry['title'] = $vcf['N'][0]['value'][3][0]; - $entry['organization'] = $vcf['ORG'][0]['value'][0][0]; - $entry['office'] = $vcf['ORG'][0]['value'][1][0]; - $entry['note'] = $vcf['NOTE'][0]['value'][0][0]; - $entry['url'] = $vcf['URL'][0]['value'][0][0]; - $bday = $vcf['BDAY'][0]['value'][0][0]; - $entry['anniversary'] = substr($bday,0,4).'-'.substr($bday,4,2).'-'.substr($bday,6,2); +$entry['name'] = $vcf['N'][0]['value'][0][0]; +$entry['givenname'] = trim($vcf['N'][0]['value'][1][0].' '.$vcf['N'][0]['value'][2][0]); +$entry['title'] = $vcf['N'][0]['value'][3][0]; +$entry['organization'] = $vcf['ORG'][0]['value'][0][0]; +$entry['office'] = $vcf['ORG'][0]['value'][1][0]; +$entry['note'] = $vcf['NOTE'][0]['value'][0][0]; +$entry['url'] = $vcf['URL'][0]['value'][0][0]; +$bday = $vcf['BDAY'][0]['value'][0][0]; +$entry['anniversary'] = substr($bday,0,4).'-'.substr($bday,4,2).'-'.substr($bday,6,2); - foreach($vcf['TEL'] as $tel){ - if( empty($entry['phone']) && - array_search('WORK',$tel['param']['TYPE']) !== FALSE && +foreach($vcf['TEL'] as $tel){ + if( empty($entry['phone']) && + array_search('WORK',$tel['param']['TYPE']) !== FALSE && + array_search('VOICE',$tel['param']['TYPE']) !== FALSE){ + // Work phone + $entry['phone'] = $tel['value'][0][0]; + }elseif(empty($entry['fax']) && + array_search('FAX',$tel['param']['TYPE']) !== FALSE){ + $entry['fax'] = $tel['value'][0][0]; + }elseif(empty($entry['mobile']) && + array_search('CELL',$tel['param']['TYPE']) !== FALSE){ + $entry['mobile'] = $tel['value'][0][0]; + }elseif(empty($entry['pager']) && + array_search('PAGER',$tel['param']['TYPE']) !== FALSE){ + $entry['pager'] = $tel['value'][0][0]; + }elseif(empty($entry['homephone']) && + array_search('HOME',$tel['param']['TYPE']) !== FALSE && array_search('VOICE',$tel['param']['TYPE']) !== FALSE){ - // Work phone - $entry['phone'] = $tel['value'][0][0]; - }elseif(empty($entry['fax']) && - array_search('FAX',$tel['param']['TYPE']) !== FALSE){ - $entry['fax'] = $tel['value'][0][0]; - }elseif(empty($entry['mobile']) && - array_search('CELL',$tel['param']['TYPE']) !== FALSE){ - $entry['mobile'] = $tel['value'][0][0]; - }elseif(empty($entry['pager']) && - array_search('PAGER',$tel['param']['TYPE']) !== FALSE){ - $entry['pager'] = $tel['value'][0][0]; - }elseif(empty($entry['homephone']) && - array_search('HOME',$tel['param']['TYPE']) !== FALSE && - array_search('VOICE',$tel['param']['TYPE']) !== FALSE){ - $entry['homephone'] = $tel['value'][0][0]; - } - } - foreach($vcf['EMAIL'] as $mail){ - $entry['mail'][] = $mail['value'][0][0]; + $entry['homephone'] = $tel['value'][0][0]; } - foreach($vcf['ADR'] as $adr){ - if(array_search('HOME',$adr['param']['TYPE']) !== FALSE){ - $entry['homestreet'] = $adr['value'][2][0]."\n". //str - $adr['value'][5][0]." ". //plz - $adr['value'][3][0]; //ort +} +foreach($vcf['EMAIL'] as $mail){ + $entry['mail'][] = $mail['value'][0][0]; +} +foreach($vcf['ADR'] as $adr){ + if(array_search('HOME',$adr['param']['TYPE']) !== FALSE){ + $entry['homestreet'] = $adr['value'][2][0]."\n". //str + $adr['value'][5][0]." ". //plz + $adr['value'][3][0]; //ort - }elseif(array_search('WORK',$adr['param']['TYPE']) !== FALSE){ - $entry['street'] = $adr['value'][2][0]; - $entry['location'] = $adr['value'][3][0]; - $entry['zip'] = $adr['value'][5][0]; - } + }elseif(array_search('WORK',$adr['param']['TYPE']) !== FALSE){ + $entry['street'] = $adr['value'][2][0]; + $entry['location'] = $adr['value'][3][0]; + $entry['zip'] = $adr['value'][5][0]; } +} /* - print '
';
-  print_r($entry);
-  print '
'; +print '
';
+print_r($entry);
+print '
'; */ - return $entry; +return $entry; } diff --git a/importVCF.php b/importVCF.php deleted file mode 100644 index 1138b99..0000000 --- a/importVCF.php +++ /dev/null @@ -1,127 +0,0 @@ -fromFile($_FILES['userfile']['tmp_name']); - }else{ - switch($_FILES['userfile']['error']){ - case 0: //no error; possible file attack! - $error = "There was a problem with your upload."; - break; - case 1: //uploaded file exceeds the upload_max_filesize directive in php.ini - $error = "The file you are trying to upload is too big."; - break; - case 2: //uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form - $error = "The file you are trying to upload is too big."; - break; - case 3: //uploaded file was only partially uploaded - $error = "The file you are trying upload was only partially uploaded."; - break; - case 4: //no file was uploaded - $error = "You must select a VCF file for upload."; - break; - default: //a default error, just in case! :) - $error = "There was a problem with your upload."; - break; - } - } - }else{ - $error = "Only VCF extension is allowed"; - } - } - - //prepare templates for all found VCARDs - $list = ''; - if (count($vcards)){ - foreach ($vcards as $vcard){ - $entry = vcard_entry($vcard); - $smarty->clear_all_assign(); - tpl_std(); - $smarty->assign('entry',$entry); - $list .= $smarty->fetch('importVCF_entry.tpl'); - } - } - - //prepare templates - tpl_std(); - tpl_orgs(); - tpl_markers(); - $smarty->assign('error',$error); - $smarty->assign('list',$list); - //display templates - $smarty->display('header.tpl'); - $smarty->display('importVCF.tpl'); - $smarty->display('footer.tpl'); - - -function vcard_entry($vcf){ - $entry['name'] = $vcf['N'][0]['value'][0][0]; - $entry['givenname'] = trim($vcf['N'][0]['value'][1][0].' '.$vcf['N'][0]['value'][2][0]); - $entry['title'] = $vcf['N'][0]['value'][3][0]; - $entry['organization'] = $vcf['ORG'][0]['value'][0][0]; - $entry['office'] = $vcf['ORG'][0]['value'][1][0]; - $entry['note'] = $vcf['NOTE'][0]['value'][0][0]; - $entry['url'] = $vcf['URL'][0]['value'][0][0]; - $bday = $vcf['BDAY'][0]['value'][0][0]; - $entry['anniversary'] = substr($bday,0,4).'-'.substr($bday,4,2).'-'.substr($bday,6,2); - - foreach($vcf['TEL'] as $tel){ - if( empty($entry['phone']) && - array_search('WORK',$tel['param']['TYPE']) !== FALSE && - array_search('VOICE',$tel['param']['TYPE']) !== FALSE){ - // Work phone - $entry['phone'] = $tel['value'][0][0]; - }elseif(empty($entry['fax']) && - array_search('FAX',$tel['param']['TYPE']) !== FALSE){ - $entry['fax'] = $tel['value'][0][0]; - }elseif(empty($entry['mobile']) && - array_search('CELL',$tel['param']['TYPE']) !== FALSE){ - $entry['mobile'] = $tel['value'][0][0]; - }elseif(empty($entry['pager']) && - array_search('PAGER',$tel['param']['TYPE']) !== FALSE){ - $entry['pager'] = $tel['value'][0][0]; - }elseif(empty($entry['homephone']) && - array_search('HOME',$tel['param']['TYPE']) !== FALSE && - array_search('VOICE',$tel['param']['TYPE']) !== FALSE){ - $entry['homephone'] = $tel['value'][0][0]; - } - } - foreach($vcf['EMAIL'] as $mail){ - $entry['mail'][] = $mail['value'][0][0]; - } - foreach($vcf['ADR'] as $adr){ - if(array_search('HOME',$adr['param']['TYPE']) !== FALSE){ - $entry['homestreet'] = $adr['value'][2][0]."\n". //str - $adr['value'][5][0]." ". //plz - $adr['value'][3][0]; //ort - - }elseif(array_search('WORK',$adr['param']['TYPE']) !== FALSE){ - $entry['street'] = $adr['value'][2][0]; - $entry['location'] = $adr['value'][3][0]; - $entry['plz'] = $adr['value'][5][0]; - } - } - -/* - print '
';
-  print_r($entry);
-  print '
'; -*/ - - return $entry; -} - - -?> diff --git a/inc/Contact_Vcard_Parse.php b/inc/Contact_Vcard_Parse.php new file mode 100644 index 0000000..da1f16f --- /dev/null +++ b/inc/Contact_Vcard_Parse.php @@ -0,0 +1,836 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Contact_Vcard_Parse.php,v 1.1 2004/06/01 08:48:59 gohr Exp $ + + +/** +* +* Parser for vCards. +* +* This class parses vCard 2.1 and 3.0 sources from file or text into a +* structured array. +* +* Usage: +* +* +* // include this class file +* require_once 'Contact_Vcard_Parse.php'; +* +* // instantiate a parser object +* $parse = new Contact_Vcard_Parse(); +* +* // parse a vCard file and store the data +* // in $cardinfo +* $cardinfo = $parse->fromFile('sample.vcf'); +* +* // view the card info array +* echo '
';
+*     print_r($cardinfo);
+*     echo '
'; +*
+* +* +* @author Paul M. Jones +* +* @package Contact_Vcard_Parse +* +* @version 1.30 +* +*/ + +class Contact_Vcard_Parse { + + + /** + * + * Reads a file for parsing, then sends it to $this->fromText() + * and returns the results. + * + * @access public + * + * @param array $filename The filename to read for vCard information. + * + * @return array An array of of vCard information extracted from the + * file. + * + * @see Contact_Vcard_Parse::fromText() + * + * @see Contact_Vcard_Parse::_fromArray() + * + */ + + function fromFile($filename, $decode_qp = true) + { + $text = $this->fileGetContents($filename); + + if ($text === false) { + return false; + } else { + // dump to, and get return from, the fromText() method. + return $this->fromText($text, $decode_qp); + } + } + + + /** + * + * Reads the contents of a file. Included for users whose PHP < 4.3.0. + * + * @access public + * + * @param array $filename The filename to read for vCard information. + * + * @return string|bool The contents of the file if it exists and is + * readable, or boolean false if not. + * + * @see Contact_Vcard_Parse::fromFile() + * + */ + + function fileGetContents($filename) + { + if (file_exists($filename) && + is_readable($filename)) { + + $text = ''; + $len = filesize($filename); + + $fp = fopen($filename, 'r'); + while ($line = fread($fp, filesize($filename))) { + $text .= $line; + } + fclose($fp); + + return $text; + + } else { + + return false; + + } + } + + + /** + * + * Prepares a block of text for parsing, then sends it through and + * returns the results from $this->fromArray(). + * + * @access public + * + * @param array $text A block of text to read for vCard information. + * + * @return array An array of vCard information extracted from the + * source text. + * + * @see Contact_Vcard_Parse::_fromArray() + * + */ + + function fromText($text, $decode_qp = true) + { + // convert all kinds of line endings to Unix-standard and get + // rid of double blank lines. + $this->convertLineEndings($text); + + // unfold lines. concat two lines where line 1 ends in \n and + // line 2 starts with a whitespace character. only removes + // the first whitespace character, leaves others in place. + $fold_regex = '(\n)([ |\t])'; + $text = preg_replace("/$fold_regex/i", "", $text); + + // massage for Macintosh OS X Address Book (remove nulls that + // Address Book puts in for unicode chars) + $text = str_replace("\x00", '', $text); + + // convert the resulting text to an array of lines + $lines = explode("\n", $text); + + // parse the array of lines and return vCard info + return $this->_fromArray($lines, $decode_qp); + } + + + /** + * + * Converts line endings in text. + * + * Takes any text block and converts all line endings to UNIX + * standard. DOS line endings are \r\n, Mac are \r, and UNIX is \n. + * + * NOTE: Acts on the text block in-place; does not return a value. + * + * @access public + * + * @param string $text The string on which to convert line endings. + * + * @return void + * + */ + + function convertLineEndings(&$text) + { + // DOS + $text = str_replace("\r\n", "\n", $text); + + // Mac + $text = str_replace("\r", "\n", $text); + } + + + /** + * + * Splits a string into an array at semicolons. Honors backslash- + * escaped semicolons (i.e., splits at ';' not '\;'). + * + * @access public + * + * @param string $text The string to split into an array. + * + * @param bool $convertSingle If splitting the string results in a + * single array element, return a string instead of a one-element + * array. + * + * @return mixed An array of values, or a single string. + * + */ + + function splitBySemi($text, $convertSingle = false) + { + // we use these double-backs (\\) because they get get converted + // to single-backs (\) by preg_split. the quad-backs (\\\\) end + // up as as double-backs (\\), which is what preg_split requires + // to indicate a single backslash (\). what a mess. + $regex = '(? ; + * \, => , + * literal \n => newline + * + * @access public + * + * @param mixed $text The text to unescape. + * + * @return void + * + */ + + function unescape(&$text) + { + if (is_array($text)) { + foreach ($text as $key => $val) { + $this->unescape($val); + $text[$key] = $val; + } + } else { + $text = str_replace('\;', ';', $text); + $text = str_replace('\,', ',', $text); + $text = str_replace('\n', "\n", $text); + } + } + + + /** + * + * Emulated destructor. + * + * @access private + * @return boolean true + * + */ + + function _Contact_Vcard_Parse() + { + return true; + } + + + /** + * + * Parses an array of source lines and returns an array of vCards. + * Each element of the array is itself an array expressing the types, + * parameters, and values of each part of the vCard. Processes both + * 2.1 and 3.0 vCard sources. + * + * @access private + * + * @param array $source An array of lines to be read for vCard + * information. + * + * @return array An array of of vCard information extracted from the + * source array. + * + */ + + function _fromArray($source, $decode_qp = true) + { + // the info array will hold all resulting vCard information. + $info = array(); + + // tells us whether the source text indicates the beginning of a + // new vCard with a BEGIN:VCARD tag. + $begin = false; + + // holds information about the current vCard being read from the + // source text. + $card = array(); + + // loop through each line in the source array + foreach ($source as $line) { + + // if the line is blank, skip it. + if (trim($line) == '') { + continue; + } + + // find the first instance of ':' on the line. The part + // to the left of the colon is the type and parameters; + // the part to the right of the colon is the value data. + $pos = strpos($line, ':'); + + // if there is no colon, skip the line. + if ($pos === false) { + continue; + } + + // get the left and right portions + $left = trim(substr($line, 0, $pos)); + $right = trim(substr($line, $pos+1, strlen($line))); + + // have we started yet? + if (! $begin) { + + // nope. does this line indicate the beginning of + // a new vCard? + if (strtoupper($left) == 'BEGIN' && + strtoupper($right) == 'VCARD') { + + // tell the loop that we've begun a new card + $begin = true; + } + + // regardless, loop to the next line of source. if begin + // is still false, the next loop will check the line. if + // begin has now been set to true, the loop will start + // collecting card info. + continue; + + } else { + + // yep, we've started, but we don't know how far along + // we are in the card. is this the ending line of the + // current vCard? + if (strtoupper($left) == 'END' && + strtoupper($right) == 'VCARD') { + + // yep, we're done. keep the info from the current + // card... + $info[] = $card; + + // ...and reset to grab a new card if one exists in + // the source array. + $begin = false; + $card = array(); + + } else { + + // we're not on an ending line, so collect info from + // this line into the current card. split the + // left-portion of the line into a type-definition + // (the kind of information) and parameters for the + // type. + $typedef = $this->_getTypeDef($left); + $params = $this->_getParams($left); + + // if we are decoding quoted-printable, do so now. + // QUOTED-PRINTABLE is not allowed in version 3.0, + // but we don't check for versioning, so we do it + // regardless. ;-) + $this->_decode_qp($params, $right); + + // now get the value-data from the line, based on + // the typedef + switch ($typedef) { + + case 'N': + // structured name of the person + $value = $this->_parseN($right); + break; + + case 'ADR': + // structured address of the person + $value = $this->_parseADR($right); + break; + + case 'NICKNAME': + // nicknames + $value = $this->_parseNICKNAME($right); + break; + + case 'ORG': + // organizations the person belongs to + $value = $this->_parseORG($right); + break; + + case 'CATEGORIES': + // categories to which this card is assigned + $value = $this->_parseCATEGORIES($right); + break; + + case 'GEO': + // geographic coordinates + $value = $this->_parseGEO($right); + break; + + default: + // by default, just grab the plain value. keep + // as an array to make sure *all* values are + // arrays. for consistency. ;-) + $value = array(array($right)); + break; + } + + // add the type, parameters, and value to the + // current card array. note that we allow multiple + // instances of the same type, which might be dumb + // in some cases (e.g., N). + $card[$typedef][] = array( + 'param' => $params, + 'value' => $value + ); + } + } + } + + $this->unescape($info); + return $info; + } + + + /** + * + * Takes a vCard line and extracts the Type-Definition for the line. + * + * @access private + * + * @param string $text A left-part (before-the-colon part) from a + * vCard line. + * + * @return string The type definition for the line. + * + */ + + function _getTypeDef($text) + { + // split the text by semicolons + $split = $this->splitBySemi($text); + + // only return first element (the typedef) + return $split[0]; + } + + + /** + * + * Finds the Type-Definition parameters for a vCard line. + * + * @access private + * + * @param string $text A left-part (before-the-colon part) from a + * vCard line. + * + * @return mixed An array of parameters. + * + */ + + function _getParams($text) + { + // split the text by semicolons into an array + $split = $this->splitBySemi($text); + + // drop the first element of the array (the type-definition) + array_shift($split); + + // set up an array to retain the parameters, if any + $params = array(); + + // loop through each parameter. the params may be in the format... + // "TYPE=type1,type2,type3" + // ...or... + // "TYPE=type1;TYPE=type2;TYPE=type3" + foreach ($split as $full) { + + // split the full parameter at the equal sign so we can tell + // the parameter name from the parameter value + $tmp = explode("=", $full); + + // the key is the left portion of the parameter (before + // '='). if in 2.1 format, the key may in fact be the + // parameter value, not the parameter name. + $key = strtoupper(trim($tmp[0])); + + // get the parameter name by checking to see if it's in + // vCard 2.1 or 3.0 format. + $name = $this->_getParamName($key); + + // list of all parameter values + $listall = trim($tmp[1]); + + // if there is a value-list for this parameter, they are + // separated by commas, so split them out too. + $list = $this->splitByComma($listall); + + // now loop through each value in the parameter and retain + // it. if the value is blank, that means it's a 2.1-style + // param, and the key itself is the value. + foreach ($list as $val) { + if (trim($val) != '') { + // 3.0 formatted parameter + $params[$name][] = trim($val); + } else { + // 2.1 formatted parameter + $params[$name][] = $key; + } + } + + // if, after all this, there are no parameter values for the + // parameter name, retain no info about the parameter (saves + // ram and checking-time later). + if (count($params[$name]) == 0) { + unset($params[$name]); + } + } + + // return the parameters array. + return $params; + } + + + /** + * + * Looks at the parameters of a vCard line; if one of them is + * ENCODING[] => QUOTED-PRINTABLE then decode the text in-place. + * + * @access private + * + * @param array $params A parameter array from a vCard line. + * + * @param string $text A right-part (after-the-colon part) from a + * vCard line. + * + * @return void + * + */ + + function _decode_qp(&$params, &$text) + { + // loop through each parameter + foreach ($params as $param_key => $param_val) { + + // check to see if it's an encoding param + if (trim(strtoupper($param_key)) == 'ENCODING') { + + // loop through each encoding param value + foreach ($param_val as $enc_key => $enc_val) { + + // if any of the values are QP, decode the text + // in-place and return + if (trim(strtoupper($enc_val)) == 'QUOTED-PRINTABLE') { + $text = quoted_printable_decode($text); + return; + } + } + } + } + } + + + /** + * + * Returns parameter names from 2.1-formatted vCards. + * + * The vCard 2.1 specification allows parameter values without a + * name. The parameter name is then determined from the unique + * parameter value. + * + * Shamelessly lifted from Frank Hellwig and his + * vCard PHP project . + * + * @access private + * + * @param string $value The first element in a parameter name-value + * pair. + * + * @return string The proper parameter name (TYPE, ENCODING, or + * VALUE). + * + */ + + function _getParamName($value) + { + static $types = array ( + 'DOM', 'INTL', 'POSTAL', 'PARCEL','HOME', 'WORK', + 'PREF', 'VOICE', 'FAX', 'MSG', 'CELL', 'PAGER', + 'BBS', 'MODEM', 'CAR', 'ISDN', 'VIDEO', + 'AOL', 'APPLELINK', 'ATTMAIL', 'CIS', 'EWORLD', + 'INTERNET', 'IBMMAIL', 'MCIMAIL', + 'POWERSHARE', 'PRODIGY', 'TLX', 'X400', + 'GIF', 'CGM', 'WMF', 'BMP', 'MET', 'PMB', 'DIB', + 'PICT', 'TIFF', 'PDF', 'PS', 'JPEG', 'QTIME', + 'MPEG', 'MPEG2', 'AVI', + 'WAVE', 'AIFF', 'PCM', + 'X509', 'PGP' + ); + + // CONTENT-ID added by pmj + static $values = array ( + 'INLINE', 'URL', 'CID', 'CONTENT-ID' + ); + + // 8BIT added by pmj + static $encodings = array ( + '7BIT', '8BIT', 'QUOTED-PRINTABLE', 'BASE64' + ); + + // changed by pmj to the following so that the name defaults to + // whatever the original value was. Frank Hellwig's original + // code was "$name = 'UNKNOWN'". + $name = $value; + + if (in_array($value, $types)) { + $name = 'TYPE'; + } elseif (in_array($value, $values)) { + $name = 'VALUE'; + } elseif (in_array($value, $encodings)) { + $name = 'ENCODING'; + } + + return $name; + } + + + /** + * + * Parses a vCard line value identified as being of the "N" + * (structured name) type-defintion. + * + * @access private + * + * @param string $text The right-part (after-the-colon part) of a + * vCard line. + * + * @return array An array of key-value pairs where the key is the + * portion-name and the value is the portion-value. The value itself + * may be an array as well if multiple comma-separated values were + * indicated in the vCard source. + * + */ + + function _parseN($text) + { + $tmp = $this->splitBySemi($text); + return array( + $this->splitByComma($tmp[0]), // family (last) + $this->splitByComma($tmp[1]), // given (first) + $this->splitByComma($tmp[2]), // addl (middle) + $this->splitByComma($tmp[3]), // prefix + $this->splitByComma($tmp[4]) // suffix + ); + } + + + /** + * + * Parses a vCard line value identified as being of the "ADR" + * (structured address) type-defintion. + * + * @access private + * + * @param string $text The right-part (after-the-colon part) of a + * vCard line. + * + * @return array An array of key-value pairs where the key is the + * portion-name and the value is the portion-value. The value itself + * may be an array as well if multiple comma-separated values were + * indicated in the vCard source. + * + */ + + function _parseADR($text) + { + $tmp = $this->splitBySemi($text); + return array( + $this->splitByComma($tmp[0]), // pob + $this->splitByComma($tmp[1]), // extend + $this->splitByComma($tmp[2]), // street + $this->splitByComma($tmp[3]), // locality (city) + $this->splitByComma($tmp[4]), // region (state) + $this->splitByComma($tmp[5]), // postcode (ZIP) + $this->splitByComma($tmp[6]) // country + ); + } + + + /** + * + * Parses a vCard line value identified as being of the "NICKNAME" + * (informal or descriptive name) type-defintion. + * + * @access private + * + * @param string $text The right-part (after-the-colon part) of a + * vCard line. + * + * @return array An array of nicknames. + * + */ + + function _parseNICKNAME($text) + { + return array($this->splitByComma($text)); + } + + + /** + * + * Parses a vCard line value identified as being of the "ORG" + * (organizational info) type-defintion. + * + * @access private + * + * @param string $text The right-part (after-the-colon part) of a + * vCard line. + * + * @return array An array of organizations; each element of the array + * is itself an array, which indicates primary organization and + * sub-organizations. + * + */ + + function _parseORG($text) + { + $tmp = $this->splitbySemi($text); + $list = array(); + foreach ($tmp as $val) { + $list[] = array($val); + } + + return $list; + } + + + /** + * + * Parses a vCard line value identified as being of the "CATEGORIES" + * (card-category) type-defintion. + * + * @access private + * + * @param string $text The right-part (after-the-colon part) of a + * vCard line. + * + * @return mixed An array of categories. + * + */ + + function _parseCATEGORIES($text) + { + return array($this->splitByComma($text)); + } + + + /** + * + * Parses a vCard line value identified as being of the "GEO" + * (geographic coordinate) type-defintion. + * + * @access private + * + * @param string $text The right-part (after-the-colon part) of a + * vCard line. + * + * @return mixed An array of lat-lon geocoords. + * + */ + + function _parseGEO($text) + { + $tmp = $this->splitBySemi($text); + return array( + array($tmp[0]), // lat + array($tmp[1]) // lon + ); + } +} + +?> \ No newline at end of file diff --git a/inc/config.php b/inc/config.php new file mode 100644 index 0000000..d46910e --- /dev/null +++ b/inc/config.php @@ -0,0 +1,59 @@ + 'dn', // don't touch! + 'name' => 'sn', + 'displayname' => 'cn', + 'givenname' => 'givenName', + 'title' => 'title', + 'organization' => 'o', // aka. company + 'office' => 'physicalDeliveryOfficeName', + 'street' => 'postalAddress', + 'zip' => 'postalCode', + 'location' => 'l', // aka. city + 'phone' => 'telephoneNumber', + 'fax' => 'facsimileTelephoneNumber', + 'mobile' => 'mobile', // aka. cell phone + 'pager' => 'pager', + 'homephone' => 'homePhone', + 'homestreet' => 'homePostalAddress', + 'photo' => 'jpegPhoto', + 'url' => 'labeledURI', + 'note' => 'description', + 'manager' => 'manager', // aka. key account + '_mail' => 'mail', +); + +/** + * If the provided "extended" schema is used the following fields + * and object classes are added + */ +$OCLASSES[] = 'contactPerson'; +$FIELDS['anniversary'] = 'anniversary'; +$FIELDS['_marker'] = 'marker'; // aka. tags + +/** + * If the open exchange schema is used the following fields + * and object classes are added + */ +/* comment in if you want to use it +$OCLASSES[] = 'OXUserObject'; +$FIELDS['country'] = 'userCountry'; +$FIELDS['birthday'] = 'birthDay'; +$FIELDS['ipphone'] = 'IPPhone'; +$FIELDS['_marker'] = 'OXUserCategories'; +$FIELDS['instantmessenger'] = 'OXUserInstantMessenger'; +$FIELDS['timezone'] = 'OXTimeZone'; +$FIELDS['position'] = 'OXUserPosition'; +$FIELDS['certificate'] = 'relClientCert'; +$FIELDS['domain'] = 'domain'; +*/ + +/** + * If the Evolution schema is used the following fields + * and object classes are added + */ +/* comment in if you want to use it +$OCLASSES[] = 'evolutionPerson'; +$OCLASSES[] = 'officePerson'; +$FIELDS['department'] = 'ou'; +$FIELDS['state'] = 'st'; +$FIELDS['country'] = 'c'; +$FIELDS['phone'] = 'primaryPhone'; +$FIELDS['switchboard'] = 'companyPhone'; +$FIELDS['note'] = 'note'; +$FIELDS['manager'] = 'seeAlso'; +$FIELDS['birthday'] = 'birthDate'; +$FIELDS['spouse'] = 'spouseName'; +*/ + + +/** + * Flip the array + */ +$RFIELDS = array_flip($FIELDS); + diff --git a/inc/functions.php b/inc/functions.php new file mode 100644 index 0000000..9166d31 --- /dev/null +++ b/inc/functions.php @@ -0,0 +1,486 @@ +assign('USER',$_SESSION['ldapab']['username']); +} + +/** + * Uses Username and Password from Session to initialize the LDAP handle + * If it fails it redirects to login.php + */ +function ldap_login(){ + global $conf; + if(!empty($_SESSION['ldapab']['username'])){ + // existing session! Check if valid + if($_SESSION['ldapab']['browserid'] != auth_browseruid()){ + //session hijacking detected + header('Location: login.php?username='); + exit; + } + } elseif ($conf['httpd_auth'] && !empty($_SERVER['PHP_AUTH_USER'])) { + // use HTTP auth if wanted and possible + $_SESSION['ldapab']['username'] = $_SERVER['PHP_AUTH_USER']; + $_SESSION['ldapab']['password'] = $_SERVER['PHP_AUTH_PW']; + } elseif (!empty($_COOKIE['ldapabauth'])) { + // check persistent cookie + $cookie = base64_decode($_COOKIE['ldapabauth']); + $cookie = x_Decrypt($cookie,get_cookie_secret()); + list($u,$p) = unserialize($cookie); + $_SESSION['ldapab']['username'] = $u; + $_SESSION['ldapab']['password'] = $p; + } + + if(empty($_SESSION['ldapab']) || + !do_ldap_bind($_SESSION['ldapab']['username'], + $_SESSION['ldapab']['password'], + $_SESSION['ldapab']['binddn'])){ + header('Location: login.php?username='); + exit; + } +} + +/** + * Creates a global LDAP connection handle called $LDAP_CON + */ +function do_ldap_bind($user,$pass,$dn=""){ + global $conf; + global $LDAP_CON; + + //create global connection to LDAP if necessary + if(!$LDAP_CON){ + if (!empty($conf['ldapurl'])){ + $LDAP_CON = ldap_connect($conf['ldapurl']); + }else{ + $LDAP_CON = ldap_connect($conf['ldapserver'],$conf['ldapport']); + } + if(!$LDAP_CON){ + die("couldn't connect to LDAP server"); + } + } + + if($conf['ldapv3']) ldap_set_option($LDAP_CON, LDAP_OPT_PROTOCOL_VERSION, 3); + + if(empty($dn)){ + //anonymous bind to lookup users + //blank binddn or blank bindpw will result in anonymous bind + if(!ldap_bind($LDAP_CON,$conf['anonbinddn'],$conf['anonbindpw'])){ + die("can not bind for user lookup"); + } + + //when no user was given stay connected anonymous + if(empty($user)){ + set_session('','',''); + return true; + } + + //get dn for given user + $filter = str_replace('%u',$user,$conf['userfilter']); + $sr = ldap_search($LDAP_CON, $conf['usertree'], $filter);; + $result = ldap_get_entries($LDAP_CON, $sr); + if($result['count'] != 1){ + set_session('','',''); + return false; + } + $dn = $result[0]['dn']; + } + + //bind with dn + if(ldap_bind($LDAP_CON,$dn,$pass)){ + //bind successful -> set up session + set_session($user,$pass,$dn); + return true; + } + //bind failed -> remove session + set_session('','',''); + return false; +} + +/** + * Builds a pseudo UID from browser and IP data + * + * This is neither unique nor unfakable - still it adds some + * security. Using the first part of the IP makes sure + * proxy farms like AOLs are stil okay. + * + * @author Andreas Gohr + * + * @return string a MD5 sum of various browser headers + */ +function auth_browseruid(){ + $uid = ''; + if (empty($_SERVER['HTTP_USER_AGENT'])) { $_SERVER['HTTP_USER_AGENT']='USER_AGENT'; } + if (empty($_SERVER['HTTP_ACCEPT_ENCODING'])) { $_SERVER['HTTP_ACCEPT_ENCODING']='ACCEPT_ENCODING'; } + if (empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { $_SERVER['HTTP_ACCEPT_LANGUAGE']='ACCEPT_LANGUAGE'; } + if (empty($_SERVER['HTTP_ACCEPT_CHARSET'])) { $_SERVER['HTTP_ACCEPT_CHARSET']='ACCEPT_CHARSET'; } + $uid .= $_SERVER['HTTP_USER_AGENT']; + $uid .= $_SERVER['HTTP_ACCEPT_ENCODING']; + $uid .= $_SERVER['HTTP_ACCEPT_LANGUAGE']; + $uid .= $_SERVER['HTTP_ACCEPT_CHARSET']; + $uid .= substr($_SERVER['REMOTE_ADDR'],0,strpos($_SERVER['REMOTE_ADDR'],'.')); + return md5($uid); +} + + +/** + * saves user data to Session and cookies + */ +function set_session($user,$pass,$dn){ + global $conf; + + $rand = rand(); + $_SESSION['ldapab']['username'] = $user; + $_SESSION['ldapab']['binddn'] = $dn; + $_SESSION['ldapab']['password'] = $pass; + $_SESSION['ldapab']['browserid'] = auth_browseruid(); + + // (re)set the persistent auth cookie + if($user == ''){ + setcookie('ldapabauth','',time()+60*60*24*365); + }elseif(!empty($_REQUEST['remember'])){ + $cookie = serialize(array($user,$pass)); + $cookie = x_Encrypt($cookie,get_cookie_secret()); + $cookie = base64_encode($cookie); + setcookie('ldapabauth',$cookie,time()+60*60*24*365); + } +} + +/** + * Creates a random string to encrypt persistent auth + * cookies; the string is stored inside the cache dir + */ +function get_cookie_secret(){ + $file = dirname(__FILE__).'/cache/.htcookiesecret.php'; + if(@file_exists($file)){ + return md5(trim(file($file))); + } + + $secret = ''; + if(!$fh = fopen($file,'w')) die("Couldn't write to $file"); + if(fwrite($fh, $secret) === FALSE) die("Couldn't write to $file"); + fclose($fh); + + return md5($secret); +} + +/** + * binary safe function to get all search result data. + * It will use ldap_get_values_len() instead and build the array + * note: it's similar with the array returned by ldap_get_entries() + * except it has no "count" elements + * + * @author: Original code by Ovidiu Geaboc + */ +function ldap_get_binentries($conn,$srchRslt){ + if(!@ldap_count_entries($conn,$srchRslt)){ + return null; + } + $entry = ldap_first_entry($conn, $srchRslt); + $i=0; + do { + $dn = ldap_get_dn($conn,$entry); + $attrs = ldap_get_attributes($conn, $entry); + for($j=0; $j<$attrs['count']; $j++) { + $vals = ldap_get_values_len($conn, $entry,$attrs[$j]); + for($k=0; $k<$vals['count']; $k++){ + $data[$i][$attrs[$j]][$k]=$vals[$k]; + } + } + $data[$i]['dn']=$dn; + $i++; + }while ($entry = ldap_next_entry($conn, $entry)); + + return $data; +} + + +/** + * loads ldap names and their cleartext meanings from + * entries.conf file and returns it as hash + */ +function namedentries($flip=false){ + trigger_error('deprecated namedentries called',E_USER_WARNING); +} + +/** + * Creates an array for submission to ldap from websitedata + */ +function prepare_ldap_entry($in){ + global $conf; + global $FIELDS; + global $OCLASSES; + + //check dateformats + if(!preg_match('/\d\d\d\d-\d\d-\d\d/',$in['anniversary'])) $in['anniversary']=''; + if(!preg_match('/\d\d\d\d-\d\d-\d\d/',$in['birthday'])) $in['birthday']=''; + + // we map all internal names to the configured LDAP attributes here + foreach($in as $key => $value){ + if($FIELDS[$key]){ + // normal mapped field + $out[$FIELDS[$key]][] = $value; + }elseif($FIELDS["_$key"]){ + // mapped multi field + if(is_array($value)){ + $out[$FIELDS["_$key"]] = $value; + }else{ + $out[$FIELDS["_$key"]][] = $value; //shouldn't happen, but to be sure + } + }else{ + // no mapping found - assume it to be a LDAP attribute (shouldn't happen) + if(is_array($value)){ + $out[$key] = $value; + }else{ + $out[$key][] = $value; + } + } + } + + // add the Objectclasses + $out['objectclass'] = $OCLASSES; + + return clear_array($out); +} + +/** + * remove empty element from arrays recursively + * + * @author Original by + */ +function clear_array ( $a ) { + if ($a !== array()) { + $b = array(); + foreach ( $a as $key => $value ) { + if (is_array($value)) { + if (clear_array($value) !== false) { + $b[$key] = clear_array ( $value ); + } + } elseif ($value !== '') { + $b[$key] = $value; + } + } + if ($b !== array()) { + return $b; + } else { + return false; + } + } else { + return false; + } +} + +/** + * deletes an entryfrom ldap - optional with recursion + * + * @author Original by + */ +function ldap_full_delete($ds,$dn,$recursive=false){ + if($recursive == false){ + return(ldap_delete($ds,$dn)); + }else{ + //searching for sub entries + $sr=ldap_list($ds,$dn,"ObjectClass=*",array("")); + $info = ldap_get_entries($ds, $sr); + for($i=0;$i<$info['count'];$i++){ + //deleting recursively sub entries + $result=myldap_delete($ds,$info[$i]['dn'],$recursive); + if(!$result){ + //return result code, if delete fails + return($result); + } + } + return(ldap_delete($ds,$dn)); + } +} + +/** + * Returns all User Accounts as assoziative array + */ +function get_users(){ + global $conf; + global $LDAP_CON; + + $sr = ldap_list($LDAP_CON,$conf['usertree'],"ObjectClass=inetOrgPerson"); + $result = ldap_get_binentries($LDAP_CON, $sr); + $users = array(); + if(count($result)){ + foreach ($result as $entry){ + if(!empty($entry['sn'][0])){ + $users[$entry['dn']] = $entry['givenName'][0]." ".$entry['sn'][0]; + } + } + } + return $users; +} + +/** + * makes sure the given DN contains exactly one space + * after each , + */ +function normalize_dn($dn){ + $dn = preg_replace('/,/',', ',$dn); + $dn = preg_replace('/,\s+/',', ',$dn); + return $dn; +} + +/** + * Merges the given classes with the existing ones + */ +function ldap_store_objectclasses($dn,$classes){ + global $conf; + global $LDAP_CON; + + $sr = ldap_search($LDAP_CON,$dn,"objectClass=*",array('objectClass')); + $result = ldap_get_binentries($LDAP_CON, $sr); + $set = $result[0]['objectClass']; + $set = array_unique_renumber(array_merge((array)$set,(array)$classes)); + $add['objectClass'] = $set; + + $r = @ldap_mod_replace($LDAP_CON,$dn,$add); + tpl_ldaperror(); + +/* print '
';
+  print_r($set);
+  print '
';*/ +} + +/** + * Escape a string to be used in a LDAP filter + * + * Ported from Perl's Net::LDAP::Util escape_filter_value + * + * @author Andreas Gohr + */ +function ldap_filterescape($string){ + return preg_replace('/([\x00-\x1F\*\(\)\\\\])/e', + '"\\\\\".join("",unpack("H2","$1"))', + $string); +} + +/** + * Queries public and private addressbooks, combining the + * results + * + * @todo This function should be used where ever possible, replacing + * lots of duplicate code + */ +function ldap_queryabooks($filter,$types){ + global $conf; + global $LDAP_CON; + + // make sure $types is an array + if(!is_array($types)){ + $types = explode(',',$types); + $types = array_map('trim',$types); + } + + $results = array(); + $result1 = array(); + $result2 = array(); + + // public addressbook + $sr = ldap_list($LDAP_CON,$conf['publicbook'], + $filter,$types); + $result1 = ldap_get_binentries($LDAP_CON, $sr); + ldap_free_result($sr); + + // private addressbook + if(!empty($_SESSION['ldapab']['binddn'])){ + $sr = @ldap_list($LDAP_CON,$conf['privatebook']. + ','.$_SESSION['ldapab']['binddn'], + $filter,$types); + $result2 = ldap_get_binentries($LDAP_CON, $sr); + } + + // return merged results + return array_merge((array)$result1,(array)$result2); +} + +/** + * Makes array unique and renumbers the entries + * + * @author + */ +function array_unique_renumber($somearray){ + $tmparr = array_unique($somearray); + $i=0; + foreach ($tmparr as $v) { + $newarr[$i] = $v; + $i++; + } + return $newarr; +} + +/** + * Simple XOR encryption + * + * @author Dustin Schneider + * @link http://www.phpbuilder.com/tips/item.php?id=68 + */ +function x_Encrypt($string, $key){ + for($i=0; $i diff --git a/inc/importVCF.php b/inc/importVCF.php new file mode 100644 index 0000000..1138b99 --- /dev/null +++ b/inc/importVCF.php @@ -0,0 +1,127 @@ +fromFile($_FILES['userfile']['tmp_name']); + }else{ + switch($_FILES['userfile']['error']){ + case 0: //no error; possible file attack! + $error = "There was a problem with your upload."; + break; + case 1: //uploaded file exceeds the upload_max_filesize directive in php.ini + $error = "The file you are trying to upload is too big."; + break; + case 2: //uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form + $error = "The file you are trying to upload is too big."; + break; + case 3: //uploaded file was only partially uploaded + $error = "The file you are trying upload was only partially uploaded."; + break; + case 4: //no file was uploaded + $error = "You must select a VCF file for upload."; + break; + default: //a default error, just in case! :) + $error = "There was a problem with your upload."; + break; + } + } + }else{ + $error = "Only VCF extension is allowed"; + } + } + + //prepare templates for all found VCARDs + $list = ''; + if (count($vcards)){ + foreach ($vcards as $vcard){ + $entry = vcard_entry($vcard); + $smarty->clear_all_assign(); + tpl_std(); + $smarty->assign('entry',$entry); + $list .= $smarty->fetch('importVCF_entry.tpl'); + } + } + + //prepare templates + tpl_std(); + tpl_orgs(); + tpl_markers(); + $smarty->assign('error',$error); + $smarty->assign('list',$list); + //display templates + $smarty->display('header.tpl'); + $smarty->display('importVCF.tpl'); + $smarty->display('footer.tpl'); + + +function vcard_entry($vcf){ + $entry['name'] = $vcf['N'][0]['value'][0][0]; + $entry['givenname'] = trim($vcf['N'][0]['value'][1][0].' '.$vcf['N'][0]['value'][2][0]); + $entry['title'] = $vcf['N'][0]['value'][3][0]; + $entry['organization'] = $vcf['ORG'][0]['value'][0][0]; + $entry['office'] = $vcf['ORG'][0]['value'][1][0]; + $entry['note'] = $vcf['NOTE'][0]['value'][0][0]; + $entry['url'] = $vcf['URL'][0]['value'][0][0]; + $bday = $vcf['BDAY'][0]['value'][0][0]; + $entry['anniversary'] = substr($bday,0,4).'-'.substr($bday,4,2).'-'.substr($bday,6,2); + + foreach($vcf['TEL'] as $tel){ + if( empty($entry['phone']) && + array_search('WORK',$tel['param']['TYPE']) !== FALSE && + array_search('VOICE',$tel['param']['TYPE']) !== FALSE){ + // Work phone + $entry['phone'] = $tel['value'][0][0]; + }elseif(empty($entry['fax']) && + array_search('FAX',$tel['param']['TYPE']) !== FALSE){ + $entry['fax'] = $tel['value'][0][0]; + }elseif(empty($entry['mobile']) && + array_search('CELL',$tel['param']['TYPE']) !== FALSE){ + $entry['mobile'] = $tel['value'][0][0]; + }elseif(empty($entry['pager']) && + array_search('PAGER',$tel['param']['TYPE']) !== FALSE){ + $entry['pager'] = $tel['value'][0][0]; + }elseif(empty($entry['homephone']) && + array_search('HOME',$tel['param']['TYPE']) !== FALSE && + array_search('VOICE',$tel['param']['TYPE']) !== FALSE){ + $entry['homephone'] = $tel['value'][0][0]; + } + } + foreach($vcf['EMAIL'] as $mail){ + $entry['mail'][] = $mail['value'][0][0]; + } + foreach($vcf['ADR'] as $adr){ + if(array_search('HOME',$adr['param']['TYPE']) !== FALSE){ + $entry['homestreet'] = $adr['value'][2][0]."\n". //str + $adr['value'][5][0]." ". //plz + $adr['value'][3][0]; //ort + + }elseif(array_search('WORK',$adr['param']['TYPE']) !== FALSE){ + $entry['street'] = $adr['value'][2][0]; + $entry['location'] = $adr['value'][3][0]; + $entry['plz'] = $adr['value'][5][0]; + } + } + +/* + print '
';
+  print_r($entry);
+  print '
'; +*/ + + return $entry; +} + + +?> diff --git a/inc/init.php b/inc/init.php new file mode 100644 index 0000000..ad5c900 --- /dev/null +++ b/inc/init.php @@ -0,0 +1,42 @@ +compile_dir = dirname(__FILE__).'/../cache'; + $smarty->use_sub_dirs = 0; + $smarty->template_dir = dirname(__FILE__).'/../templates'; + $smarty->force_compile = $conf['smartycompile']; +?> diff --git a/inc/lang/ca.php b/inc/lang/ca.php new file mode 100644 index 0000000..9464345 --- /dev/null +++ b/inc/lang/ca.php @@ -0,0 +1,90 @@ + + * @author Xavi Pastó + */ + +$lang['ldapab'] = 'La llibreta d\'adreces LDAP'; + +$lang['name'] = 'Cognoms'; +$lang['givenname'] = 'Nom'; +$lang['title'] = 'Títol'; +$lang['organization'] = 'Companyia'; +$lang['office'] = 'Oficina'; +$lang['street'] = 'Adreça'; +$lang['zip'] = 'Codi postal'; +$lang['location'] = 'Ciutat'; +$lang['phone'] = 'Telèfon'; +$lang['fax'] = 'Fax'; +$lang['mobile'] = 'Telefon Mòbil'; +$lang['pager'] = 'Buscapersones'; +$lang['homephone'] = 'Telèfon particular'; +$lang['homestreet'] = 'Adreça particular'; +$lang['photo'] = 'Fotografia'; +$lang['url'] = 'Pàgina web'; +$lang['note'] = 'Notes'; +$lang['mail'] = 'Correu electrònic'; +$lang['manager'] = 'Key Account'; + +$lang['anniversary'] = 'Aniversari'; +$lang['marker'] = 'Tags'; +$lang['tagcloud'] = 'Tots els tags usats, ordenats alfabeticament. Els tags més freqüents es mostren més grans.'; + +$lang['business'] = 'Feina'; +$lang['private'] = 'Particular'; +$lang['extended'] = 'Informació addicional'; + +$lang['delphoto'] = 'Esborrar la foto actual'; + +$lang['notloggedin'] = 'No esteu validats'; +$lang['loggedinas'] = 'L\'usuari validat és'; +$lang['login'] = 'Valideu-vos'; +$lang['logout'] = 'Sortir'; +$lang['edit'] = 'Editar'; +$lang['show'] = 'Veure'; +$lang['new'] = 'Nou'; +$lang['delete'] = 'Esborrar'; +$lang['copy'] = 'Copiar'; +$lang['csvexport'] = 'CSV'; +$lang['vcfexport'] = 'VCard'; +$lang['vcfimport'] = 'Importar'; +$lang['search'] = 'Buscar'; +$lang['submit'] = 'Enviar'; +$lang['help'] = 'Ajuda'; +$lang['select'] = 'Seleccionar'; +$lang['orgs'] = 'Empreses'; +$lang['upload'] = 'Pujar'; + +$lang['publicbook'] = 'Llibreta d\'adreçes publica'; +$lang['privatebook'] = 'Llibreta d\'adreçes privada'; + +$lang['username'] = 'Usuari'; +$lang['password'] = 'Clau'; +$lang['remember'] = 'Recorda\'m en aquest ordinador'; + +$lang['msg_login'] = 'Valideu-vos, si us plau!'; +$lang['msg_loginfail'] = 'La validació ha fallat'; +$lang['msg_reallydel'] = 'Realment voleu esborrar aquesta l\'entrada?'; +$lang['msg_addto'] = 'Seleccioneu la llibreta d\'addreçes on afegir l\'entrada:'; +$lang['msg_jpegonly'] = 'El sistema només accepta imatges JPEG'; +$lang['msg_dateformat'] = 'YYYY-MM-DD'; +$lang['msg_uploadvcf'] = 'Pugeu un fitxer VCard'; +$lang['msg_tagsep'] = 'Separat per comes'; + +$lang['err_noentries'] = 'No hi ha entrades'; +$lang['err_ldap'] = 'El servidor LDAP ha tornat els següents errors:'; + +$lang['openxchange'] = 'Xchange Information'; +$lang['moreopenxchange'] = 'Xchange Information Cont\'d'; +$lang['instantmessenger'] = 'Inst Msg'; +$lang['categories'] = 'Categories'; +$lang['birthday'] = 'Aniversari'; +$lang['domain'] = 'Domini de correu'; +$lang['country'] = 'País'; +$lang['certificate'] = 'x.509 Cert'; +$lang['timezone'] = 'Zona horària'; +$lang['position'] = 'Posició'; +$lang['ipphone'] = 'Telèfon IP'; + diff --git a/inc/lang/de.php b/inc/lang/de.php new file mode 100644 index 0000000..6e84d83 --- /dev/null +++ b/inc/lang/de.php @@ -0,0 +1,79 @@ + + */ + +$lang['ldapab'] = 'Das LDAP Adressbuch'; + +$lang['name'] = 'Name'; +$lang['givenname'] = 'Vorname'; +$lang['title'] = 'Titel'; +$lang['organization'] = 'Firma'; +$lang['office'] = 'Abteilung'; +$lang['street'] = 'Straße, Nr.'; +$lang['zip'] = 'Postleitzahl'; +$lang['location'] = 'Ort'; +$lang['phone'] = 'Telefon'; +$lang['fax'] = 'FAX'; +$lang['mobile'] = 'Handy'; +$lang['pager'] = 'Pieper'; +$lang['homephone'] = 'Telefon (priv.)'; +$lang['homestreet'] = 'Adresse (priv.)'; +$lang['photo'] = 'Foto'; +$lang['url'] = 'Webseite'; +$lang['note'] = 'Notizen'; +$lang['mail'] = 'E-Mail'; +$lang['manager'] = 'Key Account'; + +$lang['anniversary'] = 'Jubiläum'; +$lang['marker'] = 'Tags'; +$lang['tagcloud'] = 'Alle verwendeten Tags, alphabetisch sortiert. Häufig verwendete Tags werden größer dargestellt.'; + +$lang['business'] = 'Geschäftlich'; +$lang['private'] = 'Privat'; +$lang['extended'] = 'Zusätzliche Infos'; + +$lang['delphoto'] = 'Vorhandenes Foto löschen'; + +$lang['notloggedin'] = 'Nicht angemeldet'; +$lang['loggedinas'] = 'Angemeldet als'; +$lang['login'] = 'Anmelden'; +$lang['logout'] = 'Abmelden'; +$lang['edit'] = 'Bearbeiten'; +$lang['show'] = 'Anzeigen'; +$lang['new'] = 'Neu'; +$lang['delete'] = 'Löschen'; +$lang['copy'] = 'Kopieren'; +$lang['csvexport'] = 'CSV'; +$lang['vcfexport'] = 'VCard'; +$lang['vcfimport'] = 'Import'; +$lang['search'] = 'Suchen'; +$lang['submit'] = 'Absenden'; +$lang['help'] = 'Hilfe'; +$lang['select'] = 'Auswählen'; +$lang['orgs'] = 'Firmen'; +$lang['upload'] = 'Hochladen'; + +$lang['publicbook'] = 'Öffentliches Adressbuch'; +$lang['privatebook'] = 'Privates Adressbuch'; + + +$lang['username'] = 'Benutzername'; +$lang['password'] = 'Passwort'; +$lang['remember'] = 'Auf diesem Computer angemeldet bleiben'; + +$lang['msg_login'] = 'Bitte melden sie sich an!'; +$lang['msg_loginfail'] = 'Anmeldung fehlgeschlagen!'; +$lang['msg_reallydel'] = 'Eintrag wirklich löschen?'; +$lang['msg_addto'] = 'Zu welchem Adressbuch soll der Eintrag hinzugefügt werden?'; +$lang['msg_jpegonly'] = 'Nur JPEG'; +$lang['msg_dateformat'] = 'JJJJ-MM-TT'; +$lang['msg_uploadvcf'] = 'Upload VCard File'; +$lang['msg_tagsep'] = 'Durch Komma getrennt'; + +$lang['err_noentries'] = 'Keine Einträge'; +$lang['err_ldap'] = 'Der LDAP Server lieferte folgende Fehlermeldungen'; + + diff --git a/inc/lang/en.php b/inc/lang/en.php new file mode 100644 index 0000000..1f2b97d --- /dev/null +++ b/inc/lang/en.php @@ -0,0 +1,94 @@ + + */ + +$lang['ldapab'] = 'The LDAP address book'; + +$lang['name'] = 'Last Name'; +$lang['givenname'] = 'First Name'; +$lang['title'] = 'Title'; +$lang['organization'] = 'Company'; +$lang['office'] = 'Office'; +$lang['street'] = 'Street No.'; +$lang['zip'] = 'Postal Code'; +$lang['location'] = 'City'; +$lang['state'] = 'State'; +$lang['phone'] = 'Phone'; +$lang['switchboard'] = 'Switchboard'; +$lang['fax'] = 'FAX'; +$lang['mobile'] = 'Mobile'; +$lang['pager'] = 'Pager'; +$lang['homephone'] = 'Phone (priv.)'; +$lang['homestreet'] = 'Address (priv.)'; +$lang['photo'] = 'Picture'; +$lang['url'] = 'Website'; +$lang['note'] = 'Notes'; +$lang['mail'] = 'E-Mail'; +$lang['manager'] = 'Key Account'; + +$lang['anniversary'] = 'Anniversary'; +$lang['marker'] = 'Tags'; +$lang['tagcloud'] = 'All used tags, sorted alphabetically. Frequently used tags are shown bigger.'; + +$lang['business'] = 'Business'; +$lang['private'] = 'Private'; +$lang['extended'] = 'Additional Information'; +$lang['communication'] = 'Communication'; + +$lang['delphoto'] = 'Delete existing photo'; + +$lang['notloggedin'] = 'Not logged in'; +$lang['loggedinas'] = 'Logged in as'; +$lang['login'] = 'Log in'; +$lang['logout'] = 'Log out'; +$lang['edit'] = 'Edit'; +$lang['show'] = 'Show'; +$lang['new'] = 'New'; +$lang['delete'] = 'Delete'; +$lang['copy'] = 'Copy'; +$lang['csvexport'] = 'CSV'; +$lang['vcfexport'] = 'VCard'; +$lang['vcfimport'] = 'Import'; +$lang['search'] = 'Search'; +$lang['submit'] = 'Save'; +$lang['help'] = 'Help'; +$lang['select'] = 'Select'; +$lang['orgs'] = 'Companies'; +$lang['upload'] = 'Upload'; + +$lang['publicbook'] = 'Public Addressbook'; +$lang['privatebook'] = 'Private Addressbook'; + +$lang['username'] = 'Username'; +$lang['password'] = 'Password'; +$lang['remember'] = 'Stay logged in on this computer'; + +$lang['msg_login'] = 'Please log in!'; +$lang['msg_loginfail'] = 'Log in failed!'; +$lang['msg_reallydel'] = 'Really delete entry?'; +$lang['msg_addto'] = 'Select address book to which the entry should be added:'; +$lang['msg_jpegonly'] = 'JPEG only'; +$lang['msg_dateformat'] = 'YYYY-MM-DD'; +$lang['msg_uploadvcf'] = 'Upload VCard File'; +$lang['msg_tagsep'] = 'Comma separated'; + +$lang['err_noentries'] = 'No entries'; +$lang['err_ldap'] = 'The LDAP server returned the following errors'; + +$lang['openxchange'] = 'Xchange Information'; +$lang['moreopenxchange'] = 'Xchange Information Cont\'d'; +$lang['instantmessenger'] = 'Inst Msg'; +$lang['categories'] = 'Categories'; +$lang['birthday'] = 'Birthday'; +$lang['domain'] = 'Mail Domain'; +$lang['country'] = 'Country'; +$lang['certificate'] = 'x.509 Cert'; +$lang['timezone'] = 'Time Zone'; +$lang['position'] = 'Position'; +$lang['department'] = 'Department'; +$lang['ipphone'] = 'IP Phone'; +$lang['spouse'] = 'Spouse'; +?> diff --git a/inc/lang/fr.php b/inc/lang/fr.php new file mode 100644 index 0000000..66aeb96 --- /dev/null +++ b/inc/lang/fr.php @@ -0,0 +1,89 @@ + + */ + +$lang['ldapab'] = 'Le carnet d\'adresse LDAP'; + +$lang['name'] = 'Nom de famille'; +$lang['givenname'] = 'Prénom'; +$lang['title'] = 'Titre'; +$lang['organization'] = 'Compagnie'; +$lang['office'] = 'Bureau'; +$lang['street'] = 'N° de rue'; +$lang['zip'] = 'Code Postal'; +$lang['location'] = 'Ville'; +$lang['phone'] = 'Téléphone'; +$lang['fax'] = 'FAX'; +$lang['mobile'] = 'Portable'; +$lang['pager'] = 'Pager'; +$lang['homephone'] = 'Téléphone (priv.)'; +$lang['homestreet'] = 'Adresse (priv.)'; +$lang['photo'] = 'Photo'; +$lang['url'] = 'Site web'; +$lang['note'] = 'Notes'; +$lang['mail'] = 'E-Mail'; +$lang['manager'] = 'Key Account'; + +$lang['anniversary'] = 'Anniversaire'; +$lang['marker'] = 'Tags'; +$lang['tagcloud'] = 'Tous les marqueurs par ordre alphabétique. Les marqueurs fréquent sont montré plus grand.'; + +$lang['business'] = 'Business'; +$lang['private'] = 'Privé'; +$lang['extended'] = 'Information Additionelle'; + +$lang['delphoto'] = 'Effacer la photo existante'; + +$lang['notloggedin'] = 'Non connecté'; +$lang['loggedinas'] = 'Connecté en tant que'; +$lang['login'] = 'Se connecter'; +$lang['logout'] = 'Se déconnecter'; +$lang['edit'] = 'Editer'; +$lang['show'] = 'Montrer'; +$lang['new'] = 'Nouveau'; +$lang['delete'] = 'Effacer'; +$lang['copy'] = 'Copier'; +$lang['csvexport'] = 'CSV'; +$lang['vcfexport'] = 'VCard'; +$lang['vcfimport'] = 'Import'; +$lang['search'] = 'Rechercher'; +$lang['submit'] = 'Envoyer'; +$lang['help'] = 'Aide'; +$lang['select'] = 'Sélectionner'; +$lang['orgs'] = 'Organisation'; +$lang['upload'] = 'Upload'; + +$lang['publicbook'] = 'Carnet d\'adresse public'; +$lang['privatebook'] = 'Carnet d\'adresse privé'; + +$lang['username'] = 'Utilisateur'; +$lang['password'] = 'Mot de passe'; +$lang['remember'] = 'Rester connecté sur cet ordinateur'; + +$lang['msg_login'] = 'Veuillez vous connecter !'; +$lang['msg_loginfail'] = 'Echec de la connexion !'; +$lang['msg_reallydel'] = 'Voulez-vous vraiment effacer cette entrée ?'; +$lang['msg_addto'] = 'Séléectionnez le carnet d\'adresse ou ajouter une entrée:'; +$lang['msg_jpegonly'] = 'seulement JPEG'; +$lang['msg_dateformat'] = 'YYYY-MM-DD'; +$lang['msg_uploadvcf'] = 'Envoyer un fichier VCard'; +$lang['msg_tagsep'] = 'Séparé par des virgules'; + +$lang['err_noentries'] = 'Pas d\'entrée'; +$lang['err_ldap'] = 'Le serveur LDAP à retourné les erreurs suivantes'; + +$lang['openxchange'] = 'Xchange Information'; +$lang['moreopenxchange'] = 'Xchange Information Cont\'d'; +$lang['instantmessenger'] = 'Inst Msg'; +$lang['categories'] = 'Catégories'; +$lang['birthday'] = 'Anniversaire'; +$lang['domain'] = 'Mail Domain'; +$lang['country'] = 'Pays'; +$lang['certificate'] = 'x.509 Cert'; +$lang['timezone'] = 'Fuseau horaire'; +$lang['position'] = 'Position'; +$lang['ipphone'] = 'Téléphone IP'; + diff --git a/inc/lang/it.php b/inc/lang/it.php new file mode 100644 index 0000000..0e24f50 --- /dev/null +++ b/inc/lang/it.php @@ -0,0 +1,89 @@ + + */ + +$lang['ldapab'] = 'The LDAP address book'; + +$lang['name'] = 'Cognome'; +$lang['givenname'] = 'Nome'; +$lang['title'] = 'Titolo'; +$lang['organization'] = 'Azienda'; +$lang['office'] = 'Ufficio'; +$lang['street'] = 'Via'; +$lang['zip'] = 'Codice Postale'; +$lang['location'] = 'Citt'; +$lang['phone'] = 'Telefono'; +$lang['fax'] = 'FAX'; +$lang['mobile'] = 'Cellulare'; +$lang['pager'] = 'Pager'; +$lang['homephone'] = 'Telefono (priv.)'; +$lang['homestreet'] = 'Indirizzo (priv.)'; +$lang['photo'] = 'Foto'; +$lang['url'] = 'Sito Web'; +$lang['note'] = 'Note'; +$lang['mail'] = 'E-Mail'; +$lang['manager'] = 'Key Account'; + +$lang['anniversary'] = 'Compleanno'; +$lang['marker'] = 'Etichetta'; +$lang['tagcloud'] = 'Tutte le etichette in ordine alfaberico. Le piu usate sono piu grandi.'; + +$lang['business'] = 'Affari'; +$lang['private'] = 'Privato'; +$lang['extended'] = 'Informazione addizionale'; + +$lang['delphoto'] = 'Cancella foto esistente'; + +$lang['notloggedin'] = 'Non connesso'; +$lang['loggedinas'] = 'Connesso come'; +$lang['login'] = 'Connetti'; +$lang['logout'] = 'Disconnetti'; +$lang['edit'] = 'Modifica'; +$lang['show'] = 'Mostra'; +$lang['new'] = 'Nuovo'; +$lang['delete'] = 'Cancella'; +$lang['copy'] = 'Copia'; +$lang['csvexport'] = 'CSV'; +$lang['vcfexport'] = 'VCard'; +$lang['vcfimport'] = 'Importa'; +$lang['search'] = 'Cerca'; +$lang['submit'] = 'Invia'; +$lang['help'] = 'Aiuto'; +$lang['select'] = 'Seleziona'; +$lang['orgs'] = 'Aziende'; +$lang['upload'] = 'Carica'; + +$lang['publicbook'] = 'Indirizzario pubblico'; +$lang['privatebook'] = 'Indirizzario privato'; + +$lang['username'] = 'Username'; +$lang['password'] = 'Password'; +$lang['remember'] = 'Rimani connesso su questo computer'; + +$lang['msg_login'] = 'Collegarsi, prego!'; +$lang['msg_loginfail'] = 'Accessi fallito!'; +$lang['msg_reallydel'] = 'Cancella veramente?'; +$lang['msg_addto'] = 'Scegli l\'indirizzario a cui aggiungere la voce:'; +$lang['msg_jpegonly'] = 'Solo JPEG'; +$lang['msg_dateformat'] = 'YYYY-MM-DD'; +$lang['msg_uploadvcf'] = 'Upload VCard File'; +$lang['msg_tagsep'] = 'Separato da virgole'; + +$lang['err_noentries'] = 'Nessuna voce'; +$lang['err_ldap'] = 'Il server LDAP ha restituito i seguenti errori'; + +$lang['openxchange'] = 'Xchange Information'; +$lang['moreopenxchange'] = 'Xchange Information Cont\'d'; +$lang['instantmessenger'] = 'Inst Msg'; +$lang['categories'] = 'Categorie'; +$lang['birthday'] = 'Compleanno'; +$lang['domain'] = 'Dominio e-mail'; +$lang['country'] = 'Paese'; +$lang['certificate'] = 'Certificato x.509'; +$lang['timezone'] = 'Fuso orario'; +$lang['position'] = 'Posizione'; +$lang['ipphone'] = 'Telefono IP'; + diff --git a/inc/lang/nl.php b/inc/lang/nl.php new file mode 100644 index 0000000..6c11f73 --- /dev/null +++ b/inc/lang/nl.php @@ -0,0 +1,90 @@ + + */ + +$lang['ldapab'] = 'Het LDAP adresboek'; + +$lang['name'] = 'Achternaam'; +$lang['givenname'] = 'Voornaam'; +$lang['title'] = 'Titel'; +$lang['organization'] = 'Bedrijf'; +$lang['office'] = 'Kantoor'; +$lang['street'] = 'Straat'; +$lang['zip'] = 'Postcode'; +$lang['location'] = 'Stad'; +$lang['phone'] = 'Telefoon'; +$lang['fax'] = 'FAX'; +$lang['mobile'] = 'Mobiel'; +$lang['pager'] = 'Pager'; +$lang['homephone'] = 'Telefoon (priv.)'; +$lang['homestreet'] = 'Adres (priv.)'; +$lang['photo'] = 'Afbeelding'; +$lang['url'] = 'Website'; +$lang['note'] = 'Aantekeningen'; +$lang['mail'] = 'E-Mail'; +$lang['manager'] = 'Key Account'; + +$lang['anniversary'] = 'Verjaardag'; +$lang['marker'] = 'Categorieen'; +$lang['tagcloud'] = 'Alle gebruikte categorieen, op alfabet gesorteerd. Veelgebruikte categorieen worden groter afgebeeld'; + +$lang['business'] = 'Bedrijf'; +$lang['private'] = 'Prive'; +$lang['extended'] = 'Overige informatie'; + +$lang['delphoto'] = 'Verwijder bestaande afbeelding'; + +$lang['notloggedin'] = 'Niet ingelogd'; +$lang['loggedinas'] = 'Ingelogd als'; +$lang['login'] = 'Log in'; +$lang['logout'] = 'Log uit'; +$lang['edit'] = 'Wijzig'; +$lang['show'] = 'Toon'; +$lang['new'] = 'Nieuw'; +$lang['delete'] = 'Verwijder'; +$lang['copy'] = 'Dupliceer'; +$lang['csvexport'] = 'CSV'; +$lang['vcfexport'] = 'VCard'; +$lang['vcfimport'] = 'Importeer'; +$lang['search'] = 'Zoek'; +$lang['submit'] = 'Verstuur'; +$lang['help'] = 'Help'; +$lang['select'] = 'Selecteer'; +$lang['orgs'] = 'Bedrijven'; +$lang['upload'] = 'Upload'; + +$lang['publicbook'] = 'Publiek Adresboek'; +$lang['privatebook'] = 'Persoonlijk Adresboek'; + +$lang['username'] = 'Gebruikersnaam'; +$lang['password'] = 'Wachtwoord'; +$lang['remember'] = 'Blijf ingelogd op deze computer'; + +$lang['msg_login'] = 'Log eerst in SVP!'; +$lang['msg_loginfail'] = 'Inloggen mislukt!'; +$lang['msg_reallydel'] = 'Deze definitief verwijderen?'; +$lang['msg_addto'] = 'Kies adresboek om op te slaan:'; +$lang['msg_jpegonly'] = 'Alleen JPEG afbeeldingen'; +$lang['msg_dateformat'] = 'YYYY-MM-DD'; +$lang['msg_uploadvcf'] = 'Upload VCard bestand'; +$lang['msg_tagsep'] = 'Komma gescheiden (CSV)'; + +$lang['err_noentries'] = 'Geen gegevens'; +$lang['err_ldap'] = 'De LDAP server meldt de volgende fouten:'; + +$lang['openxchange'] = 'Xchange Informatie'; +$lang['moreopenxchange'] = 'Xchange Informatie (meer..)'; +$lang['instantmessenger'] = 'Intstant messenger'; +$lang['categories'] = 'Categorieen'; +$lang['birthday'] = 'Verjaardag'; +$lang['domain'] = 'Email domein'; +$lang['country'] = 'Land'; +$lang['certificate'] = 'x.509 Certificaat'; +$lang['timezone'] = 'Tijdzone'; +$lang['position'] = 'Positie'; +$lang['ipphone'] = 'VOIP Telefoon'; + + diff --git a/inc/smarty/Config_File.class.php b/inc/smarty/Config_File.class.php new file mode 100644 index 0000000..3d7c1b4 --- /dev/null +++ b/inc/smarty/Config_File.class.php @@ -0,0 +1,389 @@ + + * @access public + * @package Smarty + */ + +/* $Id: Config_File.class.php,v 1.88 2007/03/06 10:40:06 messju Exp $ */ + +/** + * Config file reading class + * @package Smarty + */ +class Config_File { + /**#@+ + * Options + * @var boolean + */ + /** + * Controls whether variables with the same name overwrite each other. + */ + var $overwrite = true; + + /** + * Controls whether config values of on/true/yes and off/false/no get + * converted to boolean values automatically. + */ + var $booleanize = true; + + /** + * Controls whether hidden config sections/vars are read from the file. + */ + var $read_hidden = true; + + /** + * Controls whether or not to fix mac or dos formatted newlines. + * If set to true, \r or \r\n will be changed to \n. + */ + var $fix_newlines = true; + /**#@-*/ + + /** @access private */ + var $_config_path = ""; + var $_config_data = array(); + /**#@-*/ + + /** + * Constructs a new config file class. + * + * @param string $config_path (optional) path to the config files + */ + function Config_File($config_path = NULL) + { + if (isset($config_path)) + $this->set_path($config_path); + } + + + /** + * Set the path where configuration files can be found. + * + * @param string $config_path path to the config files + */ + function set_path($config_path) + { + if (!empty($config_path)) { + if (!is_string($config_path) || !file_exists($config_path) || !is_dir($config_path)) { + $this->_trigger_error_msg("Bad config file path '$config_path'"); + return; + } + if(substr($config_path, -1) != DIRECTORY_SEPARATOR) { + $config_path .= DIRECTORY_SEPARATOR; + } + + $this->_config_path = $config_path; + } + } + + + /** + * Retrieves config info based on the file, section, and variable name. + * + * @param string $file_name config file to get info for + * @param string $section_name (optional) section to get info for + * @param string $var_name (optional) variable to get info for + * @return string|array a value or array of values + */ + function get($file_name, $section_name = NULL, $var_name = NULL) + { + if (empty($file_name)) { + $this->_trigger_error_msg('Empty config file name'); + return; + } else { + $file_name = $this->_config_path . $file_name; + if (!isset($this->_config_data[$file_name])) + $this->load_file($file_name, false); + } + + if (!empty($var_name)) { + if (empty($section_name)) { + return $this->_config_data[$file_name]["vars"][$var_name]; + } else { + if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name])) + return $this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name]; + else + return array(); + } + } else { + if (empty($section_name)) { + return (array)$this->_config_data[$file_name]["vars"]; + } else { + if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"])) + return (array)$this->_config_data[$file_name]["sections"][$section_name]["vars"]; + else + return array(); + } + } + } + + + /** + * Retrieves config info based on the key. + * + * @param $file_name string config key (filename/section/var) + * @return string|array same as get() + * @uses get() retrieves information from config file and returns it + */ + function &get_key($config_key) + { + list($file_name, $section_name, $var_name) = explode('/', $config_key, 3); + $result = &$this->get($file_name, $section_name, $var_name); + return $result; + } + + /** + * Get all loaded config file names. + * + * @return array an array of loaded config file names + */ + function get_file_names() + { + return array_keys($this->_config_data); + } + + + /** + * Get all section names from a loaded file. + * + * @param string $file_name config file to get section names from + * @return array an array of section names from the specified file + */ + function get_section_names($file_name) + { + $file_name = $this->_config_path . $file_name; + if (!isset($this->_config_data[$file_name])) { + $this->_trigger_error_msg("Unknown config file '$file_name'"); + return; + } + + return array_keys($this->_config_data[$file_name]["sections"]); + } + + + /** + * Get all global or section variable names. + * + * @param string $file_name config file to get info for + * @param string $section_name (optional) section to get info for + * @return array an array of variables names from the specified file/section + */ + function get_var_names($file_name, $section = NULL) + { + if (empty($file_name)) { + $this->_trigger_error_msg('Empty config file name'); + return; + } else if (!isset($this->_config_data[$file_name])) { + $this->_trigger_error_msg("Unknown config file '$file_name'"); + return; + } + + if (empty($section)) + return array_keys($this->_config_data[$file_name]["vars"]); + else + return array_keys($this->_config_data[$file_name]["sections"][$section]["vars"]); + } + + + /** + * Clear loaded config data for a certain file or all files. + * + * @param string $file_name file to clear config data for + */ + function clear($file_name = NULL) + { + if ($file_name === NULL) + $this->_config_data = array(); + else if (isset($this->_config_data[$file_name])) + $this->_config_data[$file_name] = array(); + } + + + /** + * Load a configuration file manually. + * + * @param string $file_name file name to load + * @param boolean $prepend_path whether current config path should be + * prepended to the filename + */ + function load_file($file_name, $prepend_path = true) + { + if ($prepend_path && $this->_config_path != "") + $config_file = $this->_config_path . $file_name; + else + $config_file = $file_name; + + ini_set('track_errors', true); + $fp = @fopen($config_file, "r"); + if (!is_resource($fp)) { + $this->_trigger_error_msg("Could not open config file '$config_file'"); + return false; + } + + $contents = ($size = filesize($config_file)) ? fread($fp, $size) : ''; + fclose($fp); + + $this->_config_data[$config_file] = $this->parse_contents($contents); + return true; + } + + /** + * Store the contents of a file manually. + * + * @param string $config_file file name of the related contents + * @param string $contents the file-contents to parse + */ + function set_file_contents($config_file, $contents) + { + $this->_config_data[$config_file] = $this->parse_contents($contents); + return true; + } + + /** + * parse the source of a configuration file manually. + * + * @param string $contents the file-contents to parse + */ + function parse_contents($contents) + { + if($this->fix_newlines) { + // fix mac/dos formatted newlines + $contents = preg_replace('!\r\n?!', "\n", $contents); + } + + $config_data = array(); + $config_data['sections'] = array(); + $config_data['vars'] = array(); + + /* reference to fill with data */ + $vars =& $config_data['vars']; + + /* parse file line by line */ + preg_match_all('!^.*\r?\n?!m', $contents, $match); + $lines = $match[0]; + for ($i=0, $count=count($lines); $i<$count; $i++) { + $line = $lines[$i]; + if (empty($line)) continue; + + if ( substr($line, 0, 1) == '[' && preg_match('!^\[(.*?)\]!', $line, $match) ) { + /* section found */ + if (substr($match[1], 0, 1) == '.') { + /* hidden section */ + if ($this->read_hidden) { + $section_name = substr($match[1], 1); + } else { + /* break reference to $vars to ignore hidden section */ + unset($vars); + $vars = array(); + continue; + } + } else { + $section_name = $match[1]; + } + if (!isset($config_data['sections'][$section_name])) + $config_data['sections'][$section_name] = array('vars' => array()); + $vars =& $config_data['sections'][$section_name]['vars']; + continue; + } + + if (preg_match('/^\s*(\.?\w+)\s*=\s*(.*)/s', $line, $match)) { + /* variable found */ + $var_name = rtrim($match[1]); + if (strpos($match[2], '"""') === 0) { + /* handle multiline-value */ + $lines[$i] = substr($match[2], 3); + $var_value = ''; + while ($i<$count) { + if (($pos = strpos($lines[$i], '"""')) === false) { + $var_value .= $lines[$i++]; + } else { + /* end of multiline-value */ + $var_value .= substr($lines[$i], 0, $pos); + break; + } + } + $booleanize = false; + + } else { + /* handle simple value */ + $var_value = preg_replace('/^([\'"])(.*)\1$/', '\2', rtrim($match[2])); + $booleanize = $this->booleanize; + + } + $this->_set_config_var($vars, $var_name, $var_value, $booleanize); + } + /* else unparsable line / means it is a comment / means ignore it */ + } + return $config_data; + } + + /**#@+ @access private */ + /** + * @param array &$container + * @param string $var_name + * @param mixed $var_value + * @param boolean $booleanize determines whether $var_value is converted to + * to true/false + */ + function _set_config_var(&$container, $var_name, $var_value, $booleanize) + { + if (substr($var_name, 0, 1) == '.') { + if (!$this->read_hidden) + return; + else + $var_name = substr($var_name, 1); + } + + if (!preg_match("/^[a-zA-Z_]\w*$/", $var_name)) { + $this->_trigger_error_msg("Bad variable name '$var_name'"); + return; + } + + if ($booleanize) { + if (preg_match("/^(on|true|yes)$/i", $var_value)) + $var_value = true; + else if (preg_match("/^(off|false|no)$/i", $var_value)) + $var_value = false; + } + + if (!isset($container[$var_name]) || $this->overwrite) + $container[$var_name] = $var_value; + else { + settype($container[$var_name], 'array'); + $container[$var_name][] = $var_value; + } + } + + /** + * @uses trigger_error() creates a PHP warning/error + * @param string $error_msg + * @param integer $error_type one of + */ + function _trigger_error_msg($error_msg, $error_type = E_USER_WARNING) + { + trigger_error("Config_File error: $error_msg", $error_type); + } + /**#@-*/ +} + +?> diff --git a/inc/smarty/Smarty.class.php b/inc/smarty/Smarty.class.php new file mode 100644 index 0000000..f05e0da --- /dev/null +++ b/inc/smarty/Smarty.class.php @@ -0,0 +1,1944 @@ + + * @author Andrei Zmievski + * @package Smarty + * @version 2.6.18 + */ + +/* $Id: Smarty.class.php,v 1.528 2007/03/06 10:40:06 messju Exp $ */ + +/** + * DIR_SEP isn't used anymore, but third party apps might + */ +if(!defined('DIR_SEP')) { + define('DIR_SEP', DIRECTORY_SEPARATOR); +} + +/** + * set SMARTY_DIR to absolute path to Smarty library files. + * if not defined, include_path will be used. Sets SMARTY_DIR only if user + * application has not already defined it. + */ + +if (!defined('SMARTY_DIR')) { + define('SMARTY_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR); +} + +if (!defined('SMARTY_CORE_DIR')) { + define('SMARTY_CORE_DIR', SMARTY_DIR . 'internals' . DIRECTORY_SEPARATOR); +} + +define('SMARTY_PHP_PASSTHRU', 0); +define('SMARTY_PHP_QUOTE', 1); +define('SMARTY_PHP_REMOVE', 2); +define('SMARTY_PHP_ALLOW', 3); + +/** + * @package Smarty + */ +class Smarty +{ + /**#@+ + * Smarty Configuration Section + */ + + /** + * The name of the directory where templates are located. + * + * @var string + */ + var $template_dir = 'templates'; + + /** + * The directory where compiled templates are located. + * + * @var string + */ + var $compile_dir = 'templates_c'; + + /** + * The directory where config files are located. + * + * @var string + */ + var $config_dir = 'configs'; + + /** + * An array of directories searched for plugins. + * + * @var array + */ + var $plugins_dir = array('plugins'); + + /** + * If debugging is enabled, a debug console window will display + * when the page loads (make sure your browser allows unrequested + * popup windows) + * + * @var boolean + */ + var $debugging = false; + + /** + * When set, smarty does uses this value as error_reporting-level. + * + * @var boolean + */ + var $error_reporting = null; + + /** + * This is the path to the debug console template. If not set, + * the default one will be used. + * + * @var string + */ + var $debug_tpl = ''; + + /** + * This determines if debugging is enable-able from the browser. + *
    + *
  • 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', 'null'), + 'INCLUDE_ANY' => false, + 'PHP_TAGS' => false, + 'MODIFIER_FUNCS' => array('count'), + 'ALLOW_CONSTANTS' => false + ); + + /** + * This is an array of directories where trusted php scripts reside. + * {@link $security} is disabled during their inclusion/execution. + * + * @var array + */ + var $trusted_dir = array(); + + /** + * The left delimiter used for the template tags. + * + * @var string + */ + var $left_delimiter = '{'; + + /** + * The right delimiter used for the template tags. + * + * @var string + */ + var $right_delimiter = '}'; + + /** + * The order in which request variables are registered, similar to + * variables_order in php.ini E = Environment, G = GET, P = POST, + * C = Cookies, S = Server + * + * @var string + */ + var $request_vars_order = 'EGPCS'; + + /** + * Indicates wether $HTTP_*_VARS[] (request_use_auto_globals=false) + * are uses as request-vars or $_*[]-vars. note: if + * request_use_auto_globals is true, then $request_vars_order has + * no effect, but the php-ini-value "gpc_order" + * + * @var boolean + */ + var $request_use_auto_globals = true; + + /** + * Set this if you want different sets of compiled files for the same + * templates. This is useful for things like different languages. + * Instead of creating separate sets of templates per language, you + * set different compile_ids like 'en' and 'de'. + * + * @var string + */ + var $compile_id = null; + + /** + * This tells Smarty whether or not to use sub dirs in the cache/ and + * templates_c/ directories. sub directories better organized, but + * may not work well with PHP safe mode enabled. + * + * @var boolean + * + */ + var $use_sub_dirs = false; + + /** + * This is a list of the modifiers to apply to all template variables. + * Put each modifier in a separate array element in the order you want + * them applied. example: 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.18'; + + /** + * current template inclusion depth + * + * @var integer + */ + var $_inclusion_depth = 0; + + /** + * for different compiled templates + * + * @var string + */ + var $_compile_id = null; + + /** + * text in URL to enable debug mode + * + * @var string + */ + var $_smarty_debug_id = 'SMARTY_DEBUG'; + + /** + * debugging information for debug console + * + * @var array + */ + var $_smarty_debug_info = array(); + + /** + * info that makes up a cache file + * + * @var array + */ + var $_cache_info = array(); + + /** + * default file permissions + * + * @var integer + */ + var $_file_perms = 0644; + + /** + * default dir permissions + * + * @var integer + */ + var $_dir_perms = 0771; + + /** + * registered objects + * + * @var array + */ + var $_reg_objects = array(); + + /** + * table keeping track of plugins + * + * @var array + */ + var $_plugins = array( + 'modifier' => array(), + 'function' => array(), + 'block' => array(), + 'compiler' => array(), + 'prefilter' => array(), + 'postfilter' => array(), + 'outputfilter' => array(), + 'resource' => array(), + 'insert' => array()); + + + /** + * cache serials + * + * @var array + */ + var $_cache_serials = array(); + + /** + * name of optional cache include file + * + * @var string + */ + var $_cache_include = null; + + /** + * indicate if the current code is used in a compiled + * include + * + * @var string + */ + var $_cache_including = false; + + /**#@-*/ + /** + * The class constructor. + */ + function Smarty() + { + $this->assign('SCRIPT_NAME', isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] + : @$GLOBALS['HTTP_SERVER_VARS']['SCRIPT_NAME']); + } + + /** + * assigns values to template variables + * + * @param array|string $tpl_var the template variable name(s) + * @param mixed $value the value to assign + */ + function assign($tpl_var, $value = null) + { + if (is_array($tpl_var)){ + foreach ($tpl_var as $key => $val) { + if ($key != '') { + $this->_tpl_vars[$key] = $val; + } + } + } else { + if ($tpl_var != '') + $this->_tpl_vars[$tpl_var] = $value; + } + } + + /** + * assigns values to template variables by reference + * + * @param string $tpl_var the template variable name + * @param mixed $value the referenced value to assign + */ + function assign_by_ref($tpl_var, &$value) + { + if ($tpl_var != '') + $this->_tpl_vars[$tpl_var] = &$value; + } + + /** + * appends values to template variables + * + * @param array|string $tpl_var the template variable name(s) + * @param mixed $value the value to append + */ + function append($tpl_var, $value=null, $merge=false) + { + if (is_array($tpl_var)) { + // $tpl_var is an array, ignore $value + foreach ($tpl_var as $_key => $_val) { + if ($_key != '') { + if(!@is_array($this->_tpl_vars[$_key])) { + settype($this->_tpl_vars[$_key],'array'); + } + if($merge && is_array($_val)) { + foreach($_val as $_mkey => $_mval) { + $this->_tpl_vars[$_key][$_mkey] = $_mval; + } + } else { + $this->_tpl_vars[$_key][] = $_val; + } + } + } + } else { + if ($tpl_var != '' && isset($value)) { + if(!@is_array($this->_tpl_vars[$tpl_var])) { + settype($this->_tpl_vars[$tpl_var],'array'); + } + if($merge && is_array($value)) { + foreach($value as $_mkey => $_mval) { + $this->_tpl_vars[$tpl_var][$_mkey] = $_mval; + } + } else { + $this->_tpl_vars[$tpl_var][] = $value; + } + } + } + } + + /** + * appends values to template variables by reference + * + * @param string $tpl_var the template variable name + * @param mixed $value the referenced value to append + */ + function append_by_ref($tpl_var, &$value, $merge=false) + { + if ($tpl_var != '' && isset($value)) { + if(!@is_array($this->_tpl_vars[$tpl_var])) { + settype($this->_tpl_vars[$tpl_var],'array'); + } + if ($merge && is_array($value)) { + foreach($value as $_key => $_val) { + $this->_tpl_vars[$tpl_var][$_key] = &$value[$_key]; + } + } else { + $this->_tpl_vars[$tpl_var][] = &$value; + } + } + } + + + /** + * clear the given assigned template variable. + * + * @param string $tpl_var the template variable to clear + */ + function clear_assign($tpl_var) + { + if (is_array($tpl_var)) + foreach ($tpl_var as $curr_var) + unset($this->_tpl_vars[$curr_var]); + else + unset($this->_tpl_vars[$tpl_var]); + } + + + /** + * Registers custom function to be used in templates + * + * @param string $function the name of the template function + * @param string $function_impl the name of the PHP function to register + */ + function register_function($function, $function_impl, $cacheable=true, $cache_attrs=null) + { + $this->_plugins['function'][$function] = + array($function_impl, null, null, false, $cacheable, $cache_attrs); + + } + + /** + * Unregisters custom function + * + * @param string $function name of template function + */ + function unregister_function($function) + { + unset($this->_plugins['function'][$function]); + } + + /** + * Registers object to be used in templates + * + * @param string $object name of template object + * @param object &$object_impl the referenced PHP object to register + * @param null|array $allowed list of allowed methods (empty = all) + * @param boolean $smarty_args smarty argument format, else traditional + * @param null|array $block_functs list of methods that are block format + */ + function register_object($object, &$object_impl, $allowed = array(), $smarty_args = true, $block_methods = array()) + { + settype($allowed, 'array'); + settype($smarty_args, 'boolean'); + $this->_reg_objects[$object] = + array(&$object_impl, $allowed, $smarty_args, $block_methods); + } + + /** + * Unregisters object + * + * @param string $object name of template object + */ + function unregister_object($object) + { + unset($this->_reg_objects[$object]); + } + + + /** + * Registers block function to be used in templates + * + * @param string $block name of template block + * @param string $block_impl PHP function to register + */ + function register_block($block, $block_impl, $cacheable=true, $cache_attrs=null) + { + $this->_plugins['block'][$block] = + array($block_impl, null, null, false, $cacheable, $cache_attrs); + } + + /** + * Unregisters block function + * + * @param string $block name of template function + */ + function unregister_block($block) + { + unset($this->_plugins['block'][$block]); + } + + /** + * Registers compiler function + * + * @param string $function name of template function + * @param string $function_impl name of PHP function to register + */ + function register_compiler_function($function, $function_impl, $cacheable=true) + { + $this->_plugins['compiler'][$function] = + array($function_impl, null, null, false, $cacheable); + } + + /** + * Unregisters compiler function + * + * @param string $function name of template function + */ + function unregister_compiler_function($function) + { + unset($this->_plugins['compiler'][$function]); + } + + /** + * Registers modifier to be used in templates + * + * @param string $modifier name of template modifier + * @param string $modifier_impl name of PHP function to register + */ + function register_modifier($modifier, $modifier_impl) + { + $this->_plugins['modifier'][$modifier] = + array($modifier_impl, null, null, false); + } + + /** + * Unregisters modifier + * + * @param string $modifier name of template modifier + */ + function unregister_modifier($modifier) + { + unset($this->_plugins['modifier'][$modifier]); + } + + /** + * Registers a resource to fetch a template + * + * @param string $type name of resource + * @param array $functions array of functions to handle resource + */ + function register_resource($type, $functions) + { + if (count($functions)==4) { + $this->_plugins['resource'][$type] = + array($functions, false); + + } elseif (count($functions)==5) { + $this->_plugins['resource'][$type] = + array(array(array(&$functions[0], $functions[1]) + ,array(&$functions[0], $functions[2]) + ,array(&$functions[0], $functions[3]) + ,array(&$functions[0], $functions[4])) + ,false); + + } else { + $this->trigger_error("malformed function-list for '$type' in register_resource"); + + } + } + + /** + * Unregisters a resource + * + * @param string $type name of resource + */ + function unregister_resource($type) + { + unset($this->_plugins['resource'][$type]); + } + + /** + * Registers a prefilter function to apply + * to a template before compiling + * + * @param string $function name of PHP function to register + */ + function register_prefilter($function) + { + $_name = (is_array($function)) ? $function[1] : $function; + $this->_plugins['prefilter'][$_name] + = array($function, null, null, false); + } + + /** + * Unregisters a prefilter function + * + * @param string $function name of PHP function + */ + function unregister_prefilter($function) + { + unset($this->_plugins['prefilter'][$function]); + } + + /** + * Registers a postfilter function to apply + * to a compiled template after compilation + * + * @param string $function name of PHP function to register + */ + function register_postfilter($function) + { + $_name = (is_array($function)) ? $function[1] : $function; + $this->_plugins['postfilter'][$_name] + = array($function, null, null, false); + } + + /** + * Unregisters a postfilter function + * + * @param string $function name of PHP function + */ + function unregister_postfilter($function) + { + unset($this->_plugins['postfilter'][$function]); + } + + /** + * Registers an output filter function to apply + * to a template output + * + * @param string $function name of PHP function + */ + function register_outputfilter($function) + { + $_name = (is_array($function)) ? $function[1] : $function; + $this->_plugins['outputfilter'][$_name] + = array($function, null, null, false); + } + + /** + * Unregisters an outputfilter function + * + * @param string $function name of PHP function + */ + function unregister_outputfilter($function) + { + unset($this->_plugins['outputfilter'][$function]); + } + + /** + * load a filter of specified type and name + * + * @param string $type filter type + * @param string $name filter name + */ + function load_filter($type, $name) + { + switch ($type) { + case 'output': + $_params = array('plugins' => array(array($type . 'filter', $name, null, null, false))); + require_once(SMARTY_CORE_DIR . 'core.load_plugins.php'); + smarty_core_load_plugins($_params, $this); + break; + + case 'pre': + case 'post': + if (!isset($this->_plugins[$type . 'filter'][$name])) + $this->_plugins[$type . 'filter'][$name] = false; + break; + } + } + + /** + * clear cached content for the given template and cache id + * + * @param string $tpl_file name of template file + * @param string $cache_id name of cache_id + * @param string $compile_id name of compile_id + * @param string $exp_time expiration time + * @return boolean + */ + function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null) + { + + if (!isset($compile_id)) + $compile_id = $this->compile_id; + + if (!isset($tpl_file)) + $compile_id = null; + + $_auto_id = $this->_get_auto_id($cache_id, $compile_id); + + if (!empty($this->cache_handler_func)) { + return call_user_func_array($this->cache_handler_func, + array('clear', &$this, &$dummy, $tpl_file, $cache_id, $compile_id, $exp_time)); + } else { + $_params = array('auto_base' => $this->cache_dir, + 'auto_source' => $tpl_file, + 'auto_id' => $_auto_id, + 'exp_time' => $exp_time); + require_once(SMARTY_CORE_DIR . 'core.rm_auto.php'); + return smarty_core_rm_auto($_params, $this); + } + + } + + + /** + * clear the entire contents of cache (all templates) + * + * @param string $exp_time expire time + * @return boolean results of {@link smarty_core_rm_auto()} + */ + function clear_all_cache($exp_time = null) + { + return $this->clear_cache(null, null, null, $exp_time); + } + + + /** + * test to see if valid cache exists for this template + * + * @param string $tpl_file name of template file + * @param string $cache_id + * @param string $compile_id + * @return string|false results of {@link _read_cache_file()} + */ + function is_cached($tpl_file, $cache_id = null, $compile_id = null) + { + if (!$this->caching) + return false; + + if (!isset($compile_id)) + $compile_id = $this->compile_id; + + $_params = array( + 'tpl_file' => $tpl_file, + 'cache_id' => $cache_id, + 'compile_id' => $compile_id + ); + require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php'); + return smarty_core_read_cache_file($_params, $this); + } + + + /** + * clear all the assigned template variables. + * + */ + function clear_all_assign() + { + $this->_tpl_vars = array(); + } + + /** + * clears compiled version of specified template resource, + * or all compiled template files if one is not specified. + * This function is for advanced use only, not normally needed. + * + * @param string $tpl_file + * @param string $compile_id + * @param string $exp_time + * @return boolean results of {@link smarty_core_rm_auto()} + */ + function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp_time = null) + { + if (!isset($compile_id)) { + $compile_id = $this->compile_id; + } + $_params = array('auto_base' => $this->compile_dir, + 'auto_source' => $tpl_file, + 'auto_id' => $compile_id, + 'exp_time' => $exp_time, + 'extensions' => array('.inc', '.php')); + require_once(SMARTY_CORE_DIR . 'core.rm_auto.php'); + return smarty_core_rm_auto($_params, $this); + } + + /** + * Checks whether requested template exists. + * + * @param string $tpl_file + * @return boolean + */ + function template_exists($tpl_file) + { + $_params = array('resource_name' => $tpl_file, 'quiet'=>true, 'get_source'=>false); + return $this->_fetch_resource_info($_params); + } + + /** + * Returns an array containing template variables + * + * @param string $name + * @param string $type + * @return array + */ + function &get_template_vars($name=null) + { + if(!isset($name)) { + return $this->_tpl_vars; + } elseif(isset($this->_tpl_vars[$name])) { + return $this->_tpl_vars[$name]; + } else { + // var non-existant, return valid reference + $_tmp = null; + return $_tmp; + } + } + + /** + * Returns an array containing config variables + * + * @param string $name + * @param string $type + * @return array + */ + function &get_config_vars($name=null) + { + if(!isset($name) && is_array($this->_config[0])) { + return $this->_config[0]['vars']; + } else if(isset($this->_config[0]['vars'][$name])) { + return $this->_config[0]['vars'][$name]; + } else { + // var non-existant, return valid reference + $_tmp = null; + return $_tmp; + } + } + + /** + * trigger Smarty error + * + * @param string $error_msg + * @param integer $error_type + */ + function trigger_error($error_msg, $error_type = E_USER_WARNING) + { + trigger_error("Smarty error: $error_msg", $error_type); + } + + + /** + * executes & displays the template results + * + * @param string $resource_name + * @param string $cache_id + * @param string $compile_id + */ + function display($resource_name, $cache_id = null, $compile_id = null) + { + $this->fetch($resource_name, $cache_id, $compile_id, true); + } + + /** + * executes & returns or displays the template results + * + * @param string $resource_name + * @param string $cache_id + * @param string $compile_id + * @param boolean $display + */ + function fetch($resource_name, $cache_id = null, $compile_id = null, $display = false) + { + static $_cache_info = array(); + + $_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(isset($this->error_reporting) + ? $this->error_reporting : error_reporting() & ~E_NOTICE); + + if (!$this->debugging && $this->debugging_ctrl == 'URL') { + $_query_string = $this->request_use_auto_globals ? $_SERVER['QUERY_STRING'] : $GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING']; + if (@strstr($_query_string, $this->_smarty_debug_id)) { + if (@strstr($_query_string, $this->_smarty_debug_id . '=on')) { + // enable debugging for this browser session + @setcookie('SMARTY_DEBUG', true); + $this->debugging = true; + } elseif (@strstr($_query_string, $this->_smarty_debug_id . '=off')) { + // disable debugging for this browser session + @setcookie('SMARTY_DEBUG', false); + $this->debugging = false; + } else { + // enable debugging for this page + $this->debugging = true; + } + } else { + $this->debugging = (bool)($this->request_use_auto_globals ? @$_COOKIE['SMARTY_DEBUG'] : @$GLOBALS['HTTP_COOKIE_VARS']['SMARTY_DEBUG']); + } + } + + if ($this->debugging) { + // capture time for debugging info + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $_debug_start_time = smarty_core_get_microtime($_params, $this); + $this->_smarty_debug_info[] = array('type' => 'template', + 'filename' => $resource_name, + 'depth' => 0); + $_included_tpls_idx = count($this->_smarty_debug_info) - 1; + } + + if (!isset($compile_id)) { + $compile_id = $this->compile_id; + } + + $this->_compile_id = $compile_id; + $this->_inclusion_depth = 0; + + if ($this->caching) { + // save old cache_info, initialize cache_info + array_push($_cache_info, $this->_cache_info); + $this->_cache_info = array(); + $_params = array( + 'tpl_file' => $resource_name, + 'cache_id' => $cache_id, + 'compile_id' => $compile_id, + 'results' => null + ); + require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php'); + if (smarty_core_read_cache_file($_params, $this)) { + $_smarty_results = $_params['results']; + if (!empty($this->_cache_info['insert_tags'])) { + $_params = array('plugins' => $this->_cache_info['insert_tags']); + require_once(SMARTY_CORE_DIR . 'core.load_plugins.php'); + smarty_core_load_plugins($_params, $this); + $_params = array('results' => $_smarty_results); + require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php'); + $_smarty_results = smarty_core_process_cached_inserts($_params, $this); + } + if (!empty($this->_cache_info['cache_serials'])) { + $_params = array('results' => $_smarty_results); + require_once(SMARTY_CORE_DIR . 'core.process_compiled_include.php'); + $_smarty_results = smarty_core_process_compiled_include($_params, $this); + } + + + if ($display) { + if ($this->debugging) + { + // capture time for debugging info + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $_debug_start_time; + require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php'); + $_smarty_results .= smarty_core_display_debug_console($_params, $this); + } + if ($this->cache_modified_check) { + $_server_vars = ($this->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS']; + $_last_modified_date = @substr($_server_vars['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_server_vars['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3); + $_gmt_mtime = gmdate('D, d M Y H:i:s', $this->_cache_info['timestamp']).' GMT'; + if (@count($this->_cache_info['insert_tags']) == 0 + && !$this->_cache_serials + && $_gmt_mtime == $_last_modified_date) { + if (php_sapi_name()=='cgi') + header('Status: 304 Not Modified'); + else + header('HTTP/1.1 304 Not Modified'); + + } else { + header('Last-Modified: '.$_gmt_mtime); + echo $_smarty_results; + } + } else { + echo $_smarty_results; + } + error_reporting($_smarty_old_error_level); + // restore initial cache_info + $this->_cache_info = array_pop($_cache_info); + return true; + } else { + error_reporting($_smarty_old_error_level); + // restore initial cache_info + $this->_cache_info = array_pop($_cache_info); + return $_smarty_results; + } + } else { + $this->_cache_info['template'][$resource_name] = true; + if ($this->cache_modified_check && $display) { + header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT'); + } + } + } + + // load filters that are marked as autoload + if (count($this->autoload_filters)) { + foreach ($this->autoload_filters as $_filter_type => $_filters) { + foreach ($_filters as $_filter) { + $this->load_filter($_filter_type, $_filter); + } + } + } + + $_smarty_compile_path = $this->_get_compile_path($resource_name); + + // if we just need to display the results, don't perform output + // buffering - for speed + $_cache_including = $this->_cache_including; + $this->_cache_including = false; + if ($display && !$this->caching && count($this->_plugins['outputfilter']) == 0) { + if ($this->_is_compiled($resource_name, $_smarty_compile_path) + || $this->_compile_resource($resource_name, $_smarty_compile_path)) + { + include($_smarty_compile_path); + } + } else { + ob_start(); + if ($this->_is_compiled($resource_name, $_smarty_compile_path) + || $this->_compile_resource($resource_name, $_smarty_compile_path)) + { + include($_smarty_compile_path); + } + $_smarty_results = ob_get_contents(); + ob_end_clean(); + + foreach ((array)$this->_plugins['outputfilter'] as $_output_filter) { + $_smarty_results = call_user_func_array($_output_filter[0], array($_smarty_results, &$this)); + } + } + + if ($this->caching) { + $_params = array('tpl_file' => $resource_name, + 'cache_id' => $cache_id, + 'compile_id' => $compile_id, + 'results' => $_smarty_results); + require_once(SMARTY_CORE_DIR . 'core.write_cache_file.php'); + smarty_core_write_cache_file($_params, $this); + require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php'); + $_smarty_results = smarty_core_process_cached_inserts($_params, $this); + + if ($this->_cache_serials) { + // strip nocache-tags from output + $_smarty_results = preg_replace('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!s' + ,'' + ,$_smarty_results); + } + // restore initial cache_info + $this->_cache_info = array_pop($_cache_info); + } + $this->_cache_including = $_cache_including; + + if ($display) { + if (isset($_smarty_results)) { echo $_smarty_results; } + if ($this->debugging) { + // capture time for debugging info + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = (smarty_core_get_microtime($_params, $this) - $_debug_start_time); + require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php'); + echo smarty_core_display_debug_console($_params, $this); + } + error_reporting($_smarty_old_error_level); + return; + } else { + error_reporting($_smarty_old_error_level); + if (isset($_smarty_results)) { return $_smarty_results; } + } + } + + /** + * load configuration values + * + * @param string $file + * @param string $section + * @param string $scope + */ + function config_load($file, $section = null, $scope = 'global') + { + require_once($this->_get_plugin_filepath('function', 'config_load')); + smarty_function_config_load(array('file' => $file, 'section' => $section, 'scope' => $scope), $this); + } + + /** + * return a reference to a registered object + * + * @param string $name + * @return object + */ + function &get_registered_object($name) { + if (!isset($this->_reg_objects[$name])) + $this->_trigger_fatal_error("'$name' is not a registered object"); + + if (!is_object($this->_reg_objects[$name][0])) + $this->_trigger_fatal_error("registered '$name' is not an object"); + + return $this->_reg_objects[$name][0]; + } + + /** + * clear configuration values + * + * @param string $var + */ + function clear_config($var = null) + { + if(!isset($var)) { + // clear all values + $this->_config = array(array('vars' => array(), + 'files' => array())); + } else { + unset($this->_config[0]['vars'][$var]); + } + } + + /** + * get filepath of requested plugin + * + * @param string $type + * @param string $name + * @return string|false + */ + function _get_plugin_filepath($type, $name) + { + $_params = array('type' => $type, 'name' => $name); + require_once(SMARTY_CORE_DIR . 'core.assemble_plugin_filepath.php'); + return smarty_core_assemble_plugin_filepath($_params, $this); + } + + /** + * test if resource needs compiling + * + * @param string $resource_name + * @param string $compile_path + * @return boolean + */ + function _is_compiled($resource_name, $compile_path) + { + if (!$this->force_compile && file_exists($compile_path)) { + if (!$this->compile_check) { + // no need to check compiled file + return true; + } else { + // get file source and timestamp + $_params = array('resource_name' => $resource_name, 'get_source'=>false); + if (!$this->_fetch_resource_info($_params)) { + return false; + } + if ($_params['resource_timestamp'] <= filemtime($compile_path)) { + // template not expired, no recompile + return true; + } else { + // compile template + return false; + } + } + } else { + // compiled template does not exist, or forced compile + return false; + } + } + + /** + * compile the template + * + * @param string $resource_name + * @param string $compile_path + * @return boolean + */ + function _compile_resource($resource_name, $compile_path) + { + + $_params = array('resource_name' => $resource_name); + if (!$this->_fetch_resource_info($_params)) { + return false; + } + + $_source_content = $_params['source_content']; + $_cache_include = substr($compile_path, 0, -4).'.inc'; + + if ($this->_compile_source($resource_name, $_source_content, $_compiled_content, $_cache_include)) { + // if a _cache_serial was set, we also have to write an include-file: + if ($this->_cache_include_info) { + require_once(SMARTY_CORE_DIR . 'core.write_compiled_include.php'); + smarty_core_write_compiled_include(array_merge($this->_cache_include_info, array('compiled_content'=>$_compiled_content, 'resource_name'=>$resource_name)), $this); + } + + $_params = array('compile_path'=>$compile_path, 'compiled_content' => $_compiled_content); + require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php'); + smarty_core_write_compiled_resource($_params, $this); + + return true; + } else { + return false; + } + + } + + /** + * compile the given source + * + * @param string $resource_name + * @param string $source_content + * @param string $compiled_content + * @return boolean + */ + function _compile_source($resource_name, &$source_content, &$compiled_content, $cache_include_path=null) + { + if (file_exists(SMARTY_DIR . $this->compiler_file)) { + require_once(SMARTY_DIR . $this->compiler_file); + } else { + // use include_path + require_once($this->compiler_file); + } + + + $smarty_compiler = new $this->compiler_class; + + $smarty_compiler->template_dir = $this->template_dir; + $smarty_compiler->compile_dir = $this->compile_dir; + $smarty_compiler->plugins_dir = $this->plugins_dir; + $smarty_compiler->config_dir = $this->config_dir; + $smarty_compiler->force_compile = $this->force_compile; + $smarty_compiler->caching = $this->caching; + $smarty_compiler->php_handling = $this->php_handling; + $smarty_compiler->left_delimiter = $this->left_delimiter; + $smarty_compiler->right_delimiter = $this->right_delimiter; + $smarty_compiler->_version = $this->_version; + $smarty_compiler->security = $this->security; + $smarty_compiler->secure_dir = $this->secure_dir; + $smarty_compiler->security_settings = $this->security_settings; + $smarty_compiler->trusted_dir = $this->trusted_dir; + $smarty_compiler->use_sub_dirs = $this->use_sub_dirs; + $smarty_compiler->_reg_objects = &$this->_reg_objects; + $smarty_compiler->_plugins = &$this->_plugins; + $smarty_compiler->_tpl_vars = &$this->_tpl_vars; + $smarty_compiler->default_modifiers = $this->default_modifiers; + $smarty_compiler->compile_id = $this->_compile_id; + $smarty_compiler->_config = $this->_config; + $smarty_compiler->request_use_auto_globals = $this->request_use_auto_globals; + + if (isset($cache_include_path) && isset($this->_cache_serials[$cache_include_path])) { + $smarty_compiler->_cache_serial = $this->_cache_serials[$cache_include_path]; + } + $smarty_compiler->_cache_include = $cache_include_path; + + + $_results = $smarty_compiler->_compile_file($resource_name, $source_content, $compiled_content); + + if ($smarty_compiler->_cache_serial) { + $this->_cache_include_info = array( + 'cache_serial'=>$smarty_compiler->_cache_serial + ,'plugins_code'=>$smarty_compiler->_plugins_code + ,'include_file_path' => $cache_include_path); + + } else { + $this->_cache_include_info = null; + + } + + return $_results; + } + + /** + * Get the compile path for this resource + * + * @param string $resource_name + * @return string results of {@link _get_auto_filename()} + */ + function _get_compile_path($resource_name) + { + return $this->_get_auto_filename($this->compile_dir, $resource_name, + $this->_compile_id) . '.php'; + } + + /** + * fetch the template info. Gets timestamp, and source + * if get_source is true + * + * sets $source_content to the source of the template, and + * $resource_timestamp to its time stamp + * @param string $resource_name + * @param string $source_content + * @param integer $resource_timestamp + * @param boolean $get_source + * @param boolean $quiet + * @return boolean + */ + + function _fetch_resource_info(&$params) + { + if(!isset($params['get_source'])) { $params['get_source'] = true; } + if(!isset($params['quiet'])) { $params['quiet'] = false; } + + $_return = false; + $_params = array('resource_name' => $params['resource_name']) ; + if (isset($params['resource_base_path'])) + $_params['resource_base_path'] = $params['resource_base_path']; + else + $_params['resource_base_path'] = $this->template_dir; + + if ($this->_parse_resource_name($_params)) { + $_resource_type = $_params['resource_type']; + $_resource_name = $_params['resource_name']; + switch ($_resource_type) { + case 'file': + if ($params['get_source']) { + $params['source_content'] = $this->_read_file($_resource_name); + } + $params['resource_timestamp'] = filemtime($_resource_name); + $_return = is_file($_resource_name); + break; + + default: + // call resource functions to fetch the template source and timestamp + if ($params['get_source']) { + $_source_return = isset($this->_plugins['resource'][$_resource_type]) && + call_user_func_array($this->_plugins['resource'][$_resource_type][0][0], + array($_resource_name, &$params['source_content'], &$this)); + } else { + $_source_return = true; + } + + $_timestamp_return = isset($this->_plugins['resource'][$_resource_type]) && + call_user_func_array($this->_plugins['resource'][$_resource_type][0][1], + array($_resource_name, &$params['resource_timestamp'], &$this)); + + $_return = $_source_return && $_timestamp_return; + break; + } + } + + if (!$_return) { + // see if we can get a template with the default template handler + if (!empty($this->default_template_handler_func)) { + if (!is_callable($this->default_template_handler_func)) { + $this->trigger_error("default template handler function \"$this->default_template_handler_func\" doesn't exist."); + } else { + $_return = call_user_func_array( + $this->default_template_handler_func, + array($_params['resource_type'], $_params['resource_name'], &$params['source_content'], &$params['resource_timestamp'], &$this)); + } + } + } + + if (!$_return) { + if (!$params['quiet']) { + $this->trigger_error('unable to read resource: "' . $params['resource_name'] . '"'); + } + } else if ($_return && $this->security) { + require_once(SMARTY_CORE_DIR . 'core.is_secure.php'); + if (!smarty_core_is_secure($_params, $this)) { + if (!$params['quiet']) + $this->trigger_error('(secure mode) accessing "' . $params['resource_name'] . '" is not allowed'); + $params['source_content'] = null; + $params['resource_timestamp'] = null; + return false; + } + } + return $_return; + } + + + /** + * parse out the type and name from the resource + * + * @param string $resource_base_path + * @param string $resource_name + * @param string $resource_type + * @param string $resource_name + * @return boolean + */ + + function _parse_resource_name(&$params) + { + + // split tpl_path by the first colon + $_resource_name_parts = explode(':', $params['resource_name'], 2); + + if (count($_resource_name_parts) == 1) { + // no resource type given + $params['resource_type'] = $this->default_resource_type; + $params['resource_name'] = $_resource_name_parts[0]; + } else { + if(strlen($_resource_name_parts[0]) == 1) { + // 1 char is not resource type, but part of filepath + $params['resource_type'] = $this->default_resource_type; + $params['resource_name'] = $params['resource_name']; + } else { + $params['resource_type'] = $_resource_name_parts[0]; + $params['resource_name'] = $_resource_name_parts[1]; + } + } + + if ($params['resource_type'] == 'file') { + if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $params['resource_name'])) { + // relative pathname to $params['resource_base_path'] + // use the first directory where the file is found + foreach ((array)$params['resource_base_path'] as $_curr_path) { + $_fullpath = $_curr_path . DIRECTORY_SEPARATOR . $params['resource_name']; + if (file_exists($_fullpath) && is_file($_fullpath)) { + $params['resource_name'] = $_fullpath; + return true; + } + // didn't find the file, try include_path + $_params = array('file_path' => $_fullpath); + require_once(SMARTY_CORE_DIR . 'core.get_include_path.php'); + if(smarty_core_get_include_path($_params, $this)) { + $params['resource_name'] = $_params['new_file_path']; + return true; + } + } + return false; + } else { + /* absolute path */ + return file_exists($params['resource_name']); + } + } elseif (empty($this->_plugins['resource'][$params['resource_type']])) { + $_params = array('type' => $params['resource_type']); + require_once(SMARTY_CORE_DIR . 'core.load_resource_plugin.php'); + smarty_core_load_resource_plugin($_params, $this); + } + + return true; + } + + + /** + * Handle modifiers + * + * @param string|null $modifier_name + * @param array|null $map_array + * @return string result of modifiers + */ + function _run_mod_handler() + { + $_args = func_get_args(); + list($_modifier_name, $_map_array) = array_splice($_args, 0, 2); + list($_func_name, $_tpl_file, $_tpl_line) = + $this->_plugins['modifier'][$_modifier_name]; + + $_var = $_args[0]; + foreach ($_var as $_key => $_val) { + $_args[0] = $_val; + $_var[$_key] = call_user_func_array($_func_name, $_args); + } + return $_var; + } + + /** + * Remove starting and ending quotes from the string + * + * @param string $string + * @return string + */ + function _dequote($string) + { + if ((substr($string, 0, 1) == "'" || substr($string, 0, 1) == '"') && + substr($string, -1) == substr($string, 0, 1)) + return substr($string, 1, -1); + else + return $string; + } + + + /** + * read in a file + * + * @param string $filename + * @return string + */ + function _read_file($filename) + { + if ( file_exists($filename) && ($fd = @fopen($filename, 'rb')) ) { + $contents = ''; + while (!feof($fd)) { + $contents .= fread($fd, 8192); + } + fclose($fd); + return $contents; + } else { + return false; + } + } + + /** + * get a concrete filename for automagically created content + * + * @param string $auto_base + * @param string $auto_source + * @param string $auto_id + * @return string + * @staticvar string|null + * @staticvar string|null + */ + function _get_auto_filename($auto_base, $auto_source = null, $auto_id = null) + { + $_compile_dir_sep = $this->use_sub_dirs ? DIRECTORY_SEPARATOR : '^'; + $_return = $auto_base . DIRECTORY_SEPARATOR; + + if(isset($auto_id)) { + // make auto_id safe for directory names + $auto_id = str_replace('%7C',$_compile_dir_sep,(urlencode($auto_id))); + // split into separate directories + $_return .= $auto_id . $_compile_dir_sep; + } + + if(isset($auto_source)) { + // make source name safe for filename + $_filename = urlencode(basename($auto_source)); + $_crc32 = sprintf('%08X', crc32($auto_source)); + // prepend %% to avoid name conflicts with + // with $params['auto_id'] names + $_crc32 = substr($_crc32, 0, 2) . $_compile_dir_sep . + substr($_crc32, 0, 3) . $_compile_dir_sep . $_crc32; + $_return .= '%%' . $_crc32 . '%%' . $_filename; + } + + return $_return; + } + + /** + * unlink a file, possibly using expiration time + * + * @param string $resource + * @param integer $exp_time + */ + function _unlink($resource, $exp_time = null) + { + if(isset($exp_time)) { + if(time() - @filemtime($resource) >= $exp_time) { + return @unlink($resource); + } + } else { + return @unlink($resource); + } + } + + /** + * returns an auto_id for auto-file-functions + * + * @param string $cache_id + * @param string $compile_id + * @return string|null + */ + function _get_auto_id($cache_id=null, $compile_id=null) { + if (isset($cache_id)) + return (isset($compile_id)) ? $cache_id . '|' . $compile_id : $cache_id; + elseif(isset($compile_id)) + return $compile_id; + else + return null; + } + + /** + * trigger Smarty plugin error + * + * @param string $error_msg + * @param string $tpl_file + * @param integer $tpl_line + * @param string $file + * @param integer $line + * @param integer $error_type + */ + function _trigger_fatal_error($error_msg, $tpl_file = null, $tpl_line = null, + $file = null, $line = null, $error_type = E_USER_ERROR) + { + if(isset($file) && isset($line)) { + $info = ' ('.basename($file).", line $line)"; + } else { + $info = ''; + } + if (isset($tpl_line) && isset($tpl_file)) { + $this->trigger_error('[in ' . $tpl_file . ' line ' . $tpl_line . "]: $error_msg$info", $error_type); + } else { + $this->trigger_error($error_msg . $info, $error_type); + } + } + + + /** + * callback function for preg_replace, to call a non-cacheable block + * @return string + */ + function _process_compiled_include_callback($match) { + $_func = '_smarty_tplfunc_'.$match[2].'_'.$match[3]; + ob_start(); + $_func($this); + $_ret = ob_get_contents(); + ob_end_clean(); + return $_ret; + } + + + /** + * called for included templates + * + * @param string $_smarty_include_tpl_file + * @param string $_smarty_include_vars + */ + + // $_smarty_include_tpl_file, $_smarty_include_vars + + function _smarty_include($params) + { + if ($this->debugging) { + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $debug_start_time = smarty_core_get_microtime($_params, $this); + $this->_smarty_debug_info[] = array('type' => 'template', + 'filename' => $params['smarty_include_tpl_file'], + 'depth' => ++$this->_inclusion_depth); + $included_tpls_idx = count($this->_smarty_debug_info) - 1; + } + + $this->_tpl_vars = array_merge($this->_tpl_vars, $params['smarty_include_vars']); + + // config vars are treated as local, so push a copy of the + // current ones onto the front of the stack + array_unshift($this->_config, $this->_config[0]); + + $_smarty_compile_path = $this->_get_compile_path($params['smarty_include_tpl_file']); + + + if ($this->_is_compiled($params['smarty_include_tpl_file'], $_smarty_compile_path) + || $this->_compile_resource($params['smarty_include_tpl_file'], $_smarty_compile_path)) + { + include($_smarty_compile_path); + } + + // pop the local vars off the front of the stack + array_shift($this->_config); + + $this->_inclusion_depth--; + + if ($this->debugging) { + // capture time for debugging info + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $this->_smarty_debug_info[$included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $debug_start_time; + } + + if ($this->caching) { + $this->_cache_info['template'][$params['smarty_include_tpl_file']] = true; + } + } + + + /** + * get or set an array of cached attributes for function that is + * not cacheable + * @return array + */ + function &_smarty_cache_attrs($cache_serial, $count) { + $_cache_attrs =& $this->_cache_info['cache_attrs'][$cache_serial][$count]; + + if ($this->_cache_including) { + /* return next set of cache_attrs */ + $_return = current($_cache_attrs); + next($_cache_attrs); + return $_return; + + } else { + /* add a reference to a new set of cache_attrs */ + $_cache_attrs[] = array(); + return $_cache_attrs[count($_cache_attrs)-1]; + + } + + } + + + /** + * wrapper for include() retaining $this + * @return mixed + */ + function _include($filename, $once=false, $params=null) + { + if ($once) { + return include_once($filename); + } else { + return include($filename); + } + } + + + /** + * wrapper for eval() retaining $this + * @return mixed + */ + function _eval($code, $params=null) + { + return eval($code); + } + /**#@-*/ + +} + +/* vim: set expandtab: */ + +?> diff --git a/inc/smarty/Smarty_Compiler.class.php b/inc/smarty/Smarty_Compiler.class.php new file mode 100644 index 0000000..f54cc21 --- /dev/null +++ b/inc/smarty/Smarty_Compiler.class.php @@ -0,0 +1,2327 @@ + + * @author Andrei Zmievski + * @version 2.6.18 + * @copyright 2001-2005 New Digital Group, Inc. + * @package Smarty + */ + +/* $Id: Smarty_Compiler.class.php,v 1.395 2007/03/06 10:40:06 messju Exp $ */ + +/** + * Template compiling class + * @package Smarty + */ +class Smarty_Compiler extends Smarty { + + // internal vars + /**#@+ + * @access private + */ + var $_folded_blocks = array(); // keeps folded template blocks + var $_current_file = null; // the current template being compiled + var $_current_line_no = 1; // line number for error messages + var $_capture_stack = array(); // keeps track of nested capture buffers + var $_plugin_info = array(); // keeps track of plugins to load + var $_init_smarty_vars = false; + var $_permitted_tokens = array('true','false','yes','no','on','off','null'); + var $_db_qstr_regexp = null; // regexps are setup in the constructor + var $_si_qstr_regexp = null; + var $_qstr_regexp = null; + var $_func_regexp = null; + var $_reg_obj_regexp = null; + var $_var_bracket_regexp = null; + var $_num_const_regexp = null; + var $_dvar_guts_regexp = null; + var $_dvar_regexp = null; + var $_cvar_regexp = null; + var $_svar_regexp = null; + var $_avar_regexp = null; + var $_mod_regexp = null; + var $_var_regexp = null; + var $_parenth_param_regexp = null; + var $_func_call_regexp = null; + var $_obj_ext_regexp = null; + var $_obj_start_regexp = null; + var $_obj_params_regexp = null; + var $_obj_call_regexp = null; + var $_cacheable_state = 0; + var $_cache_attrs_count = 0; + var $_nocache_count = 0; + var $_cache_serial = null; + var $_cache_include = null; + + var $_strip_depth = 0; + var $_additional_newline = "\n"; + + /**#@-*/ + /** + * The class constructor. + */ + function Smarty_Compiler() + { + // matches double quoted strings: + // "foobar" + // "foo\"bar" + $this->_db_qstr_regexp = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"'; + + // matches single quoted strings: + // 'foobar' + // 'foo\'bar' + $this->_si_qstr_regexp = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\''; + + // matches single or double quoted strings + $this->_qstr_regexp = '(?:' . $this->_db_qstr_regexp . '|' . $this->_si_qstr_regexp . ')'; + + // matches bracket portion of vars + // [0] + // [foo] + // [$bar] + $this->_var_bracket_regexp = '\[\$?[\w\.]+\]'; + + // matches numerical constants + // 30 + // -12 + // 13.22 + $this->_num_const_regexp = '(?:\-?\d+(?:\.\d+)?)'; + + // matches $ vars (not objects): + // $foo + // $foo.bar + // $foo.bar.foobar + // $foo[0] + // $foo[$bar] + // $foo[5][blah] + // $foo[5].bar[$foobar][4] + $this->_dvar_math_regexp = '(?:[\+\*\/\%]|(?:-(?!>)))'; + $this->_dvar_math_var_regexp = '[\$\w\.\+\-\*\/\%\d\>\[\]]'; + $this->_dvar_guts_regexp = '\w+(?:' . $this->_var_bracket_regexp + . ')*(?:\.\$?\w+(?:' . $this->_var_bracket_regexp . ')*)*(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?'; + $this->_dvar_regexp = '\$' . $this->_dvar_guts_regexp; + + // matches config vars: + // #foo# + // #foobar123_foo# + $this->_cvar_regexp = '\#\w+\#'; + + // matches section vars: + // %foo.bar% + $this->_svar_regexp = '\%\w+\.\w+\%'; + + // matches all valid variables (no quotes, no modifiers) + $this->_avar_regexp = '(?:' . $this->_dvar_regexp . '|' + . $this->_cvar_regexp . '|' . $this->_svar_regexp . ')'; + + // matches valid variable syntax: + // $foo + // $foo + // #foo# + // #foo# + // "text" + // "text" + $this->_var_regexp = '(?:' . $this->_avar_regexp . '|' . $this->_qstr_regexp . ')'; + + // matches valid object call (one level of object nesting allowed in parameters): + // $foo->bar + // $foo->bar() + // $foo->bar("text") + // $foo->bar($foo, $bar, "text") + // $foo->bar($foo, "foo") + // $foo->bar->foo() + // $foo->bar->foo->bar() + // $foo->bar($foo->bar) + // $foo->bar($foo->bar()) + // $foo->bar($foo->bar($blah,$foo,44,"foo",$foo[0].bar)) + $this->_obj_ext_regexp = '\->(?:\$?' . $this->_dvar_guts_regexp . ')'; + $this->_obj_restricted_param_regexp = '(?:' + . '(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')(?:' . $this->_obj_ext_regexp . '(?:\((?:(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')' + . '(?:\s*,\s*(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . '))*)?\))?)*)'; + $this->_obj_single_param_regexp = '(?:\w+|' . $this->_obj_restricted_param_regexp . '(?:\s*,\s*(?:(?:\w+|' + . $this->_var_regexp . $this->_obj_restricted_param_regexp . ')))*)'; + $this->_obj_params_regexp = '\((?:' . $this->_obj_single_param_regexp + . '(?:\s*,\s*' . $this->_obj_single_param_regexp . ')*)?\)'; + $this->_obj_start_regexp = '(?:' . $this->_dvar_regexp . '(?:' . $this->_obj_ext_regexp . ')+)'; + $this->_obj_call_regexp = '(?:' . $this->_obj_start_regexp . '(?:' . $this->_obj_params_regexp . ')?(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?)'; + + // matches valid modifier syntax: + // |foo + // |@foo + // |foo:"bar" + // |foo:$bar + // |foo:"bar":$foobar + // |foo|bar + // |foo:$foo->bar + $this->_mod_regexp = '(?:\|@?\w+(?::(?:\w+|' . $this->_num_const_regexp . '|' + . $this->_obj_call_regexp . '|' . $this->_avar_regexp . '|' . $this->_qstr_regexp .'))*)'; + + // matches valid function name: + // foo123 + // _foo_bar + $this->_func_regexp = '[a-zA-Z_]\w*'; + + // matches valid registered object: + // foo->bar + $this->_reg_obj_regexp = '[a-zA-Z_]\w*->[a-zA-Z_]\w*'; + + // matches valid parameter values: + // true + // $foo + // $foo|bar + // #foo# + // #foo#|bar + // "text" + // "text"|bar + // $foo->bar + $this->_param_regexp = '(?:\s*(?:' . $this->_obj_call_regexp . '|' + . $this->_var_regexp . '|' . $this->_num_const_regexp . '|\w+)(?>' . $this->_mod_regexp . '*)\s*)'; + + // matches valid parenthesised function parameters: + // + // "text" + // $foo, $bar, "text" + // $foo|bar, "foo"|bar, $foo->bar($foo)|bar + $this->_parenth_param_regexp = '(?:\((?:\w+|' + . $this->_param_regexp . '(?:\s*,\s*(?:(?:\w+|' + . $this->_param_regexp . ')))*)?\))'; + + // matches valid function call: + // foo() + // foo_bar($foo) + // _foo_bar($foo,"bar") + // foo123($foo,$foo->bar(),"foo") + $this->_func_call_regexp = '(?:' . $this->_func_regexp . '\s*(?:' + . $this->_parenth_param_regexp . '))'; + } + + /** + * compile a resource + * + * sets $compiled_content to the compiled source + * @param string $resource_name + * @param string $source_content + * @param string $compiled_content + * @return true + */ + function _compile_file($resource_name, $source_content, &$compiled_content) + { + + if ($this->security) { + // do not allow php syntax to be executed unless specified + if ($this->php_handling == SMARTY_PHP_ALLOW && + !$this->security_settings['PHP_HANDLING']) { + $this->php_handling = SMARTY_PHP_PASSTHRU; + } + } + + $this->_load_filters(); + + $this->_current_file = $resource_name; + $this->_current_line_no = 1; + $ldq = preg_quote($this->left_delimiter, '~'); + $rdq = preg_quote($this->right_delimiter, '~'); + + // run template source through prefilter functions + if (count($this->_plugins['prefilter']) > 0) { + foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) { + if ($prefilter === false) continue; + if ($prefilter[3] || is_callable($prefilter[0])) { + $source_content = call_user_func_array($prefilter[0], + array($source_content, &$this)); + $this->_plugins['prefilter'][$filter_name][3] = true; + } else { + $this->_trigger_fatal_error("[plugin] prefilter '$filter_name' is not implemented"); + } + } + } + + /* fetch all special blocks */ + $search = "~{$ldq}\*(.*?)\*{$rdq}|{$ldq}\s*literal\s*{$rdq}(.*?){$ldq}\s*/literal\s*{$rdq}|{$ldq}\s*php\s*{$rdq}(.*?){$ldq}\s*/php\s*{$rdq}~s"; + + preg_match_all($search, $source_content, $match, PREG_SET_ORDER); + $this->_folded_blocks = $match; + reset($this->_folded_blocks); + + /* replace special blocks by "{php}" */ + $source_content = preg_replace($search.'e', "'" + . $this->_quote_replace($this->left_delimiter) . 'php' + . "' . str_repeat(\"\n\", substr_count('\\0', \"\n\")) .'" + . $this->_quote_replace($this->right_delimiter) + . "'" + , $source_content); + + /* Gather all template tags. */ + preg_match_all("~{$ldq}\s*(.*?)\s*{$rdq}~s", $source_content, $_match); + $template_tags = $_match[1]; + /* Split content by template tags to obtain non-template content. */ + $text_blocks = preg_split("~{$ldq}.*?{$rdq}~s", $source_content); + + /* loop through text blocks */ + for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) { + /* match anything resembling php tags */ + if (preg_match_all('~(<\?(?:\w+|=)?|\?>|language\s*=\s*[\"\']?\s*php\s*[\"\']?)~is', $text_blocks[$curr_tb], $sp_match)) { + /* replace tags with placeholders to prevent recursive replacements */ + $sp_match[1] = array_unique($sp_match[1]); + usort($sp_match[1], '_smarty_sort_length'); + for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) { + $text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],'%%%SMARTYSP'.$curr_sp.'%%%',$text_blocks[$curr_tb]); + } + /* process each one */ + for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) { + if ($this->php_handling == SMARTY_PHP_PASSTHRU) { + /* echo php contents */ + $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', ''."\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; + } + + /* Reformat $text_blocks between 'strip' and '/strip' tags, + removing spaces, tabs and newlines. */ + $strip = false; + for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) { + if ($compiled_tags[$i] == '{strip}') { + $compiled_tags[$i] = ''; + $strip = true; + /* remove leading whitespaces */ + $text_blocks[$i + 1] = ltrim($text_blocks[$i + 1]); + } + if ($strip) { + /* strip all $text_blocks before the next '/strip' */ + for ($j = $i + 1; $j < $for_max; $j++) { + /* remove leading and trailing whitespaces of each line */ + $text_blocks[$j] = preg_replace('![\t ]*[\r\n]+[\t ]*!', '', $text_blocks[$j]); + if ($compiled_tags[$j] == '{/strip}') { + /* remove trailing whitespaces from the last text_block */ + $text_blocks[$j] = rtrim($text_blocks[$j]); + } + $text_blocks[$j] = ""\'", "\\"=>"\\\\")) . "'; ?>"; + if ($compiled_tags[$j] == '{/strip}') { + $compiled_tags[$j] = "\n"; /* slurped by php, but necessary + if a newline is following the closing strip-tag */ + $strip = false; + $i = $j; + break; + } + } + } + } + $compiled_content = ''; + + $tag_guard = '%%%SMARTYOTG' . md5(uniqid(rand(), true)) . '%%%'; + + /* Interleave the compiled contents and text blocks to get the final result. */ + for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) { + if ($compiled_tags[$i] == '') { + // tag result empty, remove first newline from following text block + $text_blocks[$i+1] = preg_replace('~^(\r\n|\r|\n)~', '', $text_blocks[$i+1]); + } + // replace legit PHP tags with placeholder + $text_blocks[$i] = str_replace('\n", $compiled_content); + $compiled_content = preg_replace("~(?\n", $compiled_content); + + // recover legit tags + $compiled_content = str_replace($tag_guard, '_cache_serial)) { + $compiled_content = "_cache_serials['".$this->_cache_include."'] = '".$this->_cache_serial."'; ?>" . $compiled_content; + } + + // run compiled template through postfilter functions + if (count($this->_plugins['postfilter']) > 0) { + foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) { + if ($postfilter === false) continue; + if ($postfilter[3] || is_callable($postfilter[0])) { + $compiled_content = call_user_func_array($postfilter[0], + array($compiled_content, &$this)); + $this->_plugins['postfilter'][$filter_name][3] = true; + } else { + $this->_trigger_fatal_error("Smarty plugin error: postfilter '$filter_name' is not implemented"); + } + } + } + + // put header at the top of the compiled template + $template_header = "_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n"; + $template_header .= " compiled from ".strtr(urlencode($resource_name), array('%2F'=>'/', '%3A'=>':'))." */ ?>\n"; + + /* Emit code to load needed plugins. */ + $this->_plugins_code = ''; + if (count($this->_plugin_info)) { + $_plugins_params = "array('plugins' => array("; + foreach ($this->_plugin_info as $plugin_type => $plugins) { + foreach ($plugins as $plugin_name => $plugin_info) { + $_plugins_params .= "array('$plugin_type', '$plugin_name', '" . strtr($plugin_info[0], array("'" => "\\'", "\\" => "\\\\")) . "', $plugin_info[1], "; + $_plugins_params .= $plugin_info[2] ? 'true),' : 'false),'; + } + } + $_plugins_params .= '))'; + $plugins_code = "\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 (substr($template_tag, 0, 1) == '*' && substr($template_tag, -1) == '*') + return ''; + + /* Split tag into two three parts: command, command modifiers and the arguments. */ + if(! preg_match('~^(?:(' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp + . '|\/?' . $this->_reg_obj_regexp . '|\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*)) + (?:\s+(.*))?$ + ~xs', $template_tag, $match)) { + $this->_syntax_error("unrecognized tag: $template_tag", E_USER_ERROR, __FILE__, __LINE__); + } + + $tag_command = $match[1]; + $tag_modifier = isset($match[2]) ? $match[2] : null; + $tag_args = isset($match[3]) ? $match[3] : null; + + if (preg_match('~^' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$~', $tag_command)) { + /* tag name is a variable or object */ + $_return = $this->_parse_var_props($tag_command . $tag_modifier); + return "" . $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 (substr($tag_command, 0, 1)=='/') { + $this->_pop_tag('strip'); + if (--$this->_strip_depth==0) { /* outermost closing {/strip} */ + $this->_additional_newline = "\n"; + return '{' . $tag_command . '}'; + } + } else { + $this->_push_tag('strip'); + if ($this->_strip_depth++==0) { /* outermost opening {strip} */ + $this->_additional_newline = ""; + return '{' . $tag_command . '}'; + } + } + return ''; + + case 'php': + /* handle folded tags replaced by {php} */ + list(, $block) = each($this->_folded_blocks); + $this->_current_line_no += substr_count($block[0], "\n"); + /* the number of matched elements in the regexp in _compile_file() + determins the type of folded tag that was found */ + switch (count($block)) { + case 2: /* comment */ + return ''; + + case 3: /* literal */ + return ""\'", "\\"=>"\\\\")) . "'; ?>" . $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 (substr($tag_command, 0, 1) == '/') { + $start_tag = false; + $tag_command = substr($tag_command, 1); + } else + $start_tag = true; + + $found = false; + $have_function = true; + + /* + * First we check if the block function has already been registered + * or loaded from a plugin file. + */ + if (isset($this->_plugins['block'][$tag_command])) { + $found = true; + $plugin_func = $this->_plugins['block'][$tag_command][0]; + if (!is_callable($plugin_func)) { + $message = "block function '$tag_command' is not implemented"; + $have_function = false; + } + } + /* + * Otherwise we need to load plugin file and look for the function + * inside it. + */ + else if ($plugin_file = $this->_get_plugin_filepath('block', $tag_command)) { + $found = true; + + include_once $plugin_file; + + $plugin_func = 'smarty_block_' . $tag_command; + if (!function_exists($plugin_func)) { + $message = "plugin function $plugin_func() not found in $plugin_file\n"; + $have_function = false; + } else { + $this->_plugins['block'][$tag_command] = array($plugin_func, null, null, null, true); + + } + } + + if (!$found) { + return false; + } else if (!$have_function) { + $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__); + return true; + } + + /* + * Even though we've located the plugin function, compilation + * happens only once, so the plugin will still need to be loaded + * at runtime for future requests. + */ + $this->_add_plugin('block', $tag_command); + + if ($start_tag) + $this->_push_tag($tag_command); + else + $this->_pop_tag($tag_command); + + if ($start_tag) { + $output = '_push_cacheable_state('block', $tag_command); + $attrs = $this->_parse_attrs($tag_args); + $_cache_attrs=''; + $arg_list = $this->_compile_arg_list('block', $tag_command, $attrs, $_cache_attrs); + $output .= "$_cache_attrs\$this->_tag_stack[] = array('$tag_command', array(".implode(',', $arg_list).')); '; + $output .= '$_block_repeat=true;' . $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], null, $this, $_block_repeat);'; + $output .= 'while ($_block_repeat) { ob_start(); ?>'; + } else { + $output = '_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], $_block_content, $this, $_block_repeat)'; + if ($tag_modifier != '') { + $this->_parse_modifiers($_out_tag_text, $tag_modifier); + } + $output .= '$_block_repeat=false;echo ' . $_out_tag_text . '; } '; + $output .= " array_pop(\$this->_tag_stack); " . $this->_pop_cacheable_state('block', $tag_command) . '?>'; + } + + return true; + } + + + /** + * compile custom function tag + * + * @param string $tag_command + * @param string $tag_args + * @param string $tag_modifier + * @return string + */ + function _compile_custom_tag($tag_command, $tag_args, $tag_modifier, &$output) + { + $found = false; + $have_function = true; + + /* + * First we check if the custom function has already been registered + * or loaded from a plugin file. + */ + if (isset($this->_plugins['function'][$tag_command])) { + $found = true; + $plugin_func = $this->_plugins['function'][$tag_command][0]; + if (!is_callable($plugin_func)) { + $message = "custom function '$tag_command' is not implemented"; + $have_function = false; + } + } + /* + * Otherwise we need to load plugin file and look for the function + * inside it. + */ + else if ($plugin_file = $this->_get_plugin_filepath('function', $tag_command)) { + $found = true; + + include_once $plugin_file; + + $plugin_func = 'smarty_function_' . $tag_command; + if (!function_exists($plugin_func)) { + $message = "plugin function $plugin_func() not found in $plugin_file\n"; + $have_function = false; + } else { + $this->_plugins['function'][$tag_command] = array($plugin_func, null, null, null, true); + + } + } + + if (!$found) { + return false; + } else if (!$have_function) { + $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__); + return true; + } + + /* declare plugin to be loaded on display of the template that + we compile right now */ + $this->_add_plugin('function', $tag_command); + + $_cacheable_state = $this->_push_cacheable_state('function', $tag_command); + $attrs = $this->_parse_attrs($tag_args); + $_cache_attrs = ''; + $arg_list = $this->_compile_arg_list('function', $tag_command, $attrs, $_cache_attrs); + + $output = $this->_compile_plugin_call('function', $tag_command).'(array('.implode(',', $arg_list)."), \$this)"; + if($tag_modifier != '') { + $this->_parse_modifiers($output, $tag_modifier); + } + + if($output != '') { + $output = '_pop_cacheable_state('function', $tag_command) . "?>" . $this->_additional_newline; + } + + return true; + } + + /** + * compile a registered object tag + * + * @param string $tag_command + * @param array $attrs + * @param string $tag_modifier + * @return string + */ + function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier) + { + if (substr($tag_command, 0, 1) == '/') { + $start_tag = false; + $tag_command = substr($tag_command, 1); + } else { + $start_tag = true; + } + + list($object, $obj_comp) = explode('->', $tag_command); + + $arg_list = array(); + if(count($attrs)) { + $_assign_var = false; + foreach ($attrs as $arg_name => $arg_value) { + if($arg_name == 'assign') { + $_assign_var = $arg_value; + unset($attrs['assign']); + continue; + } + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + } + + if($this->_reg_objects[$object][2]) { + // smarty object argument format + $args = "array(".implode(',', (array)$arg_list)."), \$this"; + } else { + // traditional argument format + $args = implode(',', array_values($attrs)); + if (empty($args)) { + $args = 'null'; + } + } + + $prefix = ''; + $postfix = ''; + $newline = ''; + if(!is_object($this->_reg_objects[$object][0])) { + $this->_trigger_fatal_error("registered '$object' is not an object" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__); + } elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) { + $this->_trigger_fatal_error("'$obj_comp' is not a registered component of object '$object'", $this->_current_file, $this->_current_line_no, __FILE__, __LINE__); + } elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) { + // method + if(in_array($obj_comp, $this->_reg_objects[$object][3])) { + // block method + if ($start_tag) { + $prefix = "\$this->_tag_stack[] = array('$obj_comp', $args); "; + $prefix .= "\$_block_repeat=true; \$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], null, \$this, \$_block_repeat); "; + $prefix .= "while (\$_block_repeat) { ob_start();"; + $return = null; + $postfix = ''; + } else { + $prefix = "\$_obj_block_content = ob_get_contents(); ob_end_clean(); \$_block_repeat=false;"; + $return = "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], \$_obj_block_content, \$this, \$_block_repeat)"; + $postfix = "} array_pop(\$this->_tag_stack);"; + } + } else { + // non-block method + $return = "\$this->_reg_objects['$object'][0]->$obj_comp($args)"; + } + } else { + // property + $return = "\$this->_reg_objects['$object'][0]->$obj_comp"; + } + + if($return != null) { + if($tag_modifier != '') { + $this->_parse_modifiers($return, $tag_modifier); + } + + if(!empty($_assign_var)) { + $output = "\$this->assign('" . $this->_dequote($_assign_var) ."', $return);"; + } else { + $output = 'echo ' . $return . ';'; + $newline = $this->_additional_newline; + } + } else { + $output = ''; + } + + return '" . $newline; + } + + /** + * Compile {insert ...} tag + * + * @param string $tag_args + * @return string + */ + function _compile_insert_tag($tag_args) + { + $attrs = $this->_parse_attrs($tag_args); + $name = $this->_dequote($attrs['name']); + + if (empty($name)) { + return $this->_syntax_error("missing insert name", E_USER_ERROR, __FILE__, __LINE__); + } + + if (!preg_match('~^\w+$~', $name)) { + return $this->_syntax_error("'insert: 'name' must be an insert function name", E_USER_ERROR, __FILE__, __LINE__); + } + + if (!empty($attrs['script'])) { + $delayed_loading = true; + } else { + $delayed_loading = false; + } + + foreach ($attrs as $arg_name => $arg_value) { + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + + $this->_add_plugin('insert', $name, $delayed_loading); + + $_params = "array('args' => array(".implode(', ', (array)$arg_list)."))"; + + return "" . $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 .= "{$foreach_props} = array('total' => count(\$_from), 'iteration' => 0);\n"; + $output .= "if ({$foreach_props}['total'] > 0):\n"; + $output .= " foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n"; + $output .= " {$foreach_props}['iteration']++;\n"; + } else { + $output .= "if (count(\$_from)):\n"; + $output .= " foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n"; + } + $output .= '?>'; + + return $output; + } + + + /** + * Compile {capture} .. {/capture} tags + * + * @param boolean $start true if this is the {capture} tag + * @param string $tag_args + * @return string + */ + + function _compile_capture_tag($start, $tag_args = '') + { + $attrs = $this->_parse_attrs($tag_args); + + if ($start) { + if (isset($attrs['name'])) + $buffer = $attrs['name']; + else + $buffer = "'default'"; + + if (isset($attrs['assign'])) + $assign = $attrs['assign']; + else + $assign = null; + $output = ""; + $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]; + + if(empty($tokens)) { + $_error_msg = $elseif ? "'elseif'" : "'if'"; + $_error_msg .= ' statement requires arguments'; + $this->_syntax_error($_error_msg, E_USER_ERROR, __FILE__, __LINE__); + } + + + // make sure we have balanced parenthesis + $token_count = array_count_values($tokens); + if(isset($token_count['(']) && $token_count['('] != $token_count[')']) { + $this->_syntax_error("unbalanced parenthesis in if statement", E_USER_ERROR, __FILE__, __LINE__); + } + + $is_arg_stack = array(); + + for ($i = 0; $i < count($tokens); $i++) { + + $token = &$tokens[$i]; + + switch (strtolower($token)) { + case '!': + case '%': + case '!==': + case '==': + case '===': + case '>': + case '<': + case '!=': + case '<>': + case '<<': + case '>>': + case '<=': + case '>=': + case '&&': + case '||': + case '|': + case '^': + case '&': + case '~': + case ')': + case ',': + case '+': + case '-': + case '*': + case '/': + case '@': + break; + + case 'eq': + $token = '=='; + break; + + case 'ne': + case 'neq': + $token = '!='; + break; + + case 'lt': + $token = '<'; + break; + + case 'le': + case 'lte': + $token = '<='; + break; + + case 'gt': + $token = '>'; + break; + + case 'ge': + case 'gte': + $token = '>='; + break; + + case 'and': + $token = '&&'; + break; + + case 'or': + $token = '||'; + break; + + case 'not': + $token = '!'; + break; + + case 'mod': + $token = '%'; + break; + + case '(': + array_push($is_arg_stack, $i); + break; + + case 'is': + /* If last token was a ')', we operate on the parenthesized + expression. The start of the expression is on the stack. + Otherwise, we operate on the last encountered token. */ + if ($tokens[$i-1] == ')') + $is_arg_start = array_pop($is_arg_stack); + else + $is_arg_start = $i-1; + /* Construct the argument for 'is' expression, so it knows + what to operate on. */ + $is_arg = implode(' ', array_slice($tokens, $is_arg_start, $i - $is_arg_start)); + + /* Pass all tokens from next one until the end to the + 'is' expression parsing function. The function will + return modified tokens, where the first one is the result + of the 'is' expression and the rest are the tokens it + didn't touch. */ + $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1)); + + /* Replace the old tokens with the new ones. */ + array_splice($tokens, $is_arg_start, count($tokens), $new_tokens); + + /* Adjust argument start so that it won't change from the + current position for the next iteration. */ + $i = $is_arg_start; + break; + + default: + if(preg_match('~^' . $this->_func_regexp . '$~', $token) ) { + // function call + if($this->security && + !in_array($token, $this->security_settings['IF_FUNCS'])) { + $this->_syntax_error("(secure mode) '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__); + } + } elseif(preg_match('~^' . $this->_var_regexp . '$~', $token) && (strpos('+-*/^%&|', substr($token, -1)) === false) && isset($tokens[$i+1]) && $tokens[$i+1] == '(') { + // variable function call + $this->_syntax_error("variable function call '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__); + } elseif(preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)$~', $token)) { + // object or variable + $token = $this->_parse_var_props($token); + } elseif(is_numeric($token)) { + // number, skip it + } else { + $this->_syntax_error("unidentified token '$token'", E_USER_ERROR, __FILE__, __LINE__); + } + break; + } + } + + if ($elseif) + return ''; + 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('"' . strtr($val, array('\\' => '\\\\', '"' => '\\"')) .'"'); + } + return $val; + } + + /** + * expand quoted text with embedded variables + * + * @param string $var_expr + * @return string + */ + function _expand_quoted_text($var_expr) + { + // if contains unescaped $, expand it + if(preg_match_all('~(?:\`(?_dvar_guts_regexp . '(?:' . $this->_obj_ext_regexp . ')*\`)|(?:(?_parse_var(str_replace('`','',$_var)) . ')."'; + } + $var_expr = strtr($var_expr, $_replace); + $_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(substr($var_expr, 0, 1))) + $_var_ref = $var_expr; + else + $_var_ref = substr($var_expr, 1); + + if(!$_has_math) { + + // get [foo] and .foo and ->foo and (...) pieces + preg_match_all('~(?:^\w+)|' . $this->_obj_params_regexp . '|(?:' . $this->_var_bracket_regexp . ')|->\$?\w+|\.\$?\w+|\S+~', $_var_ref, $match); + + $_indexes = $match[0]; + $_var_name = array_shift($_indexes); + + /* Handle $smarty.* variable references as a special case. */ + if ($_var_name == 'smarty') { + /* + * If the reference could be compiled, use the compiled output; + * otherwise, fall back on the $smarty variable generated at + * run-time. + */ + if (($smarty_ref = $this->_compile_smarty_ref($_indexes)) !== null) { + $_output = $smarty_ref; + } else { + $_var_name = substr(array_shift($_indexes), 1); + $_output = "\$this->_smarty_vars['$_var_name']"; + } + } elseif(is_numeric($_var_name) && is_numeric(substr($var_expr, 0, 1))) { + // because . is the operator for accessing arrays thru inidizes we need to put it together again for floating point numbers + if(count($_indexes) > 0) + { + $_var_name .= implode("", $_indexes); + $_indexes = array(); + } + $_output = $_var_name; + } else { + $_output = "\$this->_tpl_vars['$_var_name']"; + } + + foreach ($_indexes as $_index) { + if (substr($_index, 0, 1) == '[') { + $_index = substr($_index, 1, -1); + if (is_numeric($_index)) { + $_output .= "[$_index]"; + } elseif (substr($_index, 0, 1) == '$') { + if (strpos($_index, '.') !== false) { + $_output .= '[' . $this->_parse_var($_index) . ']'; + } else { + $_output .= "[\$this->_tpl_vars['" . substr($_index, 1) . "']]"; + } + } else { + $_var_parts = explode('.', $_index); + $_var_section = $_var_parts[0]; + $_var_section_prop = isset($_var_parts[1]) ? $_var_parts[1] : 'index'; + $_output .= "[\$this->_sections['$_var_section']['$_var_section_prop']]"; + } + } else if (substr($_index, 0, 1) == '.') { + if (substr($_index, 1, 1) == '$') + $_output .= "[\$this->_tpl_vars['" . substr($_index, 2) . "']]"; + else + $_output .= "['" . substr($_index, 1) . "']"; + } else if (substr($_index,0,2) == '->') { + if(substr($_index,2,2) == '__') { + $this->_syntax_error('call to internal object members is not allowed', E_USER_ERROR, __FILE__, __LINE__); + } elseif($this->security && substr($_index, 2, 1) == '_') { + $this->_syntax_error('(secure) call to private object member is not allowed', E_USER_ERROR, __FILE__, __LINE__); + } elseif (substr($_index, 2, 1) == '$') { + if ($this->security) { + $this->_syntax_error('(secure) call to dynamic object member is not allowed', E_USER_ERROR, __FILE__, __LINE__); + } else { + $_output .= '->{(($_var=$this->_tpl_vars[\''.substr($_index,3).'\']) && substr($_var,0,2)!=\'__\') ? $_var : $this->trigger_error("cannot access property \\"$_var\\"")}'; + } + } else { + $_output .= $_index; + } + } elseif (substr($_index, 0, 1) == '(') { + $_index = $this->_parse_parenth_args($_index); + $_output .= $_index; + } else { + $_output .= $_index; + } + } + } + + return $_output; + } + + /** + * parse arguments in function call parenthesis + * + * @param string $parenth_args + * @return string + */ + function _parse_parenth_args($parenth_args) + { + preg_match_all('~' . $this->_param_regexp . '~',$parenth_args, $match); + $orig_vals = $match = $match[0]; + $this->_parse_vars_props($match); + $replace = array(); + for ($i = 0, $count = count($match); $i < $count; $i++) { + $replace[$orig_vals[$i]] = $match[$i]; + } + return strtr($parenth_args, $replace); + } + + /** + * parse configuration variable expression into PHP code + * + * @param string $conf_var_expr + */ + function _parse_conf_var($conf_var_expr) + { + $parts = explode('|', $conf_var_expr, 2); + $var_ref = $parts[0]; + $modifiers = isset($parts[1]) ? $parts[1] : ''; + + $var_name = substr($var_ref, 1, -1); + + $output = "\$this->_config[0]['vars']['$var_name']"; + + $this->_parse_modifiers($output, $modifiers); + + return $output; + } + + /** + * parse section property expression into PHP code + * + * @param string $section_prop_expr + * @return string + */ + function _parse_section_prop($section_prop_expr) + { + $parts = explode('|', $section_prop_expr, 2); + $var_ref = $parts[0]; + $modifiers = isset($parts[1]) ? $parts[1] : ''; + + preg_match('!%(\w+)\.(\w+)%!', $var_ref, $match); + $section_name = $match[1]; + $prop_name = $match[2]; + + $output = "\$this->_sections['$section_name']['$prop_name']"; + + $this->_parse_modifiers($output, $modifiers); + + return $output; + } + + + /** + * parse modifier chain into PHP code + * + * sets $output to parsed modified chain + * @param string $output + * @param string $modifier_string + */ + function _parse_modifiers(&$output, $modifier_string) + { + preg_match_all('~\|(@?\w+)((?>:(?:'. $this->_qstr_regexp . '|[^|]+))*)~', '|' . $modifier_string, $_match); + list(, $_modifiers, $modifier_arg_strings) = $_match; + + for ($_i = 0, $_for_max = count($_modifiers); $_i < $_for_max; $_i++) { + $_modifier_name = $_modifiers[$_i]; + + if($_modifier_name == 'smarty') { + // skip smarty modifier + continue; + } + + preg_match_all('~:(' . $this->_qstr_regexp . '|[^:]+)~', $modifier_arg_strings[$_i], $_match); + $_modifier_args = $_match[1]; + + if (substr($_modifier_name, 0, 1) == '@') { + $_map_array = false; + $_modifier_name = substr($_modifier_name, 1); + } else { + $_map_array = true; + } + + if (empty($this->_plugins['modifier'][$_modifier_name]) + && !$this->_get_plugin_filepath('modifier', $_modifier_name) + && function_exists($_modifier_name)) { + if ($this->security && !in_array($_modifier_name, $this->security_settings['MODIFIER_FUNCS'])) { + $this->_trigger_fatal_error("[plugin] (secure mode) modifier '$_modifier_name' is not allowed" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__); + } else { + $this->_plugins['modifier'][$_modifier_name] = array($_modifier_name, null, null, false); + } + } + $this->_add_plugin('modifier', $_modifier_name); + + $this->_parse_vars_props($_modifier_args); + + if($_modifier_name == 'default') { + // supress notifications of default modifier vars and args + if(substr($output, 0, 1) == '$') { + $output = '@' . $output; + } + if(isset($_modifier_args[0]) && substr($_modifier_args[0], 0, 1) == '$') { + $_modifier_args[0] = '@' . $_modifier_args[0]; + } + } + if (count($_modifier_args) > 0) + $_modifier_args = ', '.implode(', ', $_modifier_args); + else + $_modifier_args = ''; + + if ($_map_array) { + $output = "((is_array(\$_tmp=$output)) ? \$this->_run_mod_handler('$_modifier_name', true, \$_tmp$_modifier_args) : " . $this->_compile_plugin_call('modifier', $_modifier_name) . "(\$_tmp$_modifier_args))"; + + } else { + + $output = $this->_compile_plugin_call('modifier', $_modifier_name)."($output$_modifier_args)"; + + } + } + } + + + /** + * add plugin + * + * @param string $type + * @param string $name + * @param boolean? $delayed_loading + */ + function _add_plugin($type, $name, $delayed_loading = null) + { + if (!isset($this->_plugin_info[$type])) { + $this->_plugin_info[$type] = array(); + } + if (!isset($this->_plugin_info[$type][$name])) { + $this->_plugin_info[$type][$name] = array($this->_current_file, + $this->_current_line_no, + $delayed_loading); + } + } + + + /** + * Compiles references of type $smarty.foo + * + * @param string $indexes + * @return string + */ + function _compile_smarty_ref(&$indexes) + { + /* Extract the reference name. */ + $_ref = substr($indexes[0], 1); + foreach($indexes as $_index_no=>$_index) { + if (substr($_index, 0, 1) != '.' && $_index_no<2 || !preg_match('~^(\.|\[|->)~', $_index)) { + $this->_syntax_error('$smarty' . implode('', array_slice($indexes, 0, 2)) . ' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__); + } + } + + switch ($_ref) { + case 'now': + $compiled_ref = 'time()'; + $_max_index = 1; + break; + + case 'foreach': + array_shift($indexes); + $_var = $this->_parse_var_props(substr($indexes[0], 1)); + $_propname = substr($indexes[1], 1); + $_max_index = 1; + switch ($_propname) { + case 'index': + array_shift($indexes); + $compiled_ref = "(\$this->_foreach[$_var]['iteration']-1)"; + break; + + case 'first': + array_shift($indexes); + $compiled_ref = "(\$this->_foreach[$_var]['iteration'] <= 1)"; + break; + + case 'last': + array_shift($indexes); + $compiled_ref = "(\$this->_foreach[$_var]['iteration'] == \$this->_foreach[$_var]['total'])"; + break; + + case 'show': + array_shift($indexes); + $compiled_ref = "(\$this->_foreach[$_var]['total'] > 0)"; + break; + + default: + unset($_max_index); + $compiled_ref = "\$this->_foreach[$_var]"; + } + break; + + case 'section': + array_shift($indexes); + $_var = $this->_parse_var_props(substr($indexes[0], 1)); + $compiled_ref = "\$this->_sections[$_var]"; + break; + + case 'get': + $compiled_ref = ($this->request_use_auto_globals) ? '$_GET' : "\$GLOBALS['HTTP_GET_VARS']"; + break; + + case 'post': + $compiled_ref = ($this->request_use_auto_globals) ? '$_POST' : "\$GLOBALS['HTTP_POST_VARS']"; + break; + + case 'cookies': + $compiled_ref = ($this->request_use_auto_globals) ? '$_COOKIE' : "\$GLOBALS['HTTP_COOKIE_VARS']"; + break; + + case 'env': + $compiled_ref = ($this->request_use_auto_globals) ? '$_ENV' : "\$GLOBALS['HTTP_ENV_VARS']"; + break; + + case 'server': + $compiled_ref = ($this->request_use_auto_globals) ? '$_SERVER' : "\$GLOBALS['HTTP_SERVER_VARS']"; + break; + + case 'session': + $compiled_ref = ($this->request_use_auto_globals) ? '$_SESSION' : "\$GLOBALS['HTTP_SESSION_VARS']"; + break; + + /* + * These cases are handled either at run-time or elsewhere in the + * compiler. + */ + case 'request': + if ($this->request_use_auto_globals) { + $compiled_ref = '$_REQUEST'; + break; + } else { + $this->_init_smarty_vars = true; + } + return null; + + case 'capture': + return null; + + case 'template': + $compiled_ref = "'$this->_current_file'"; + $_max_index = 1; + break; + + case 'version': + $compiled_ref = "'$this->_version'"; + $_max_index = 1; + break; + + case 'const': + if ($this->security && !$this->security_settings['ALLOW_CONSTANTS']) { + $this->_syntax_error("(secure mode) constants not permitted", + E_USER_WARNING, __FILE__, __LINE__); + return; + } + array_shift($indexes); + if (preg_match('!^\.\w+$!', $indexes[0])) { + $compiled_ref = '@' . substr($indexes[0], 1); + } else { + $_val = $this->_parse_var_props(substr($indexes[0], 1)); + $compiled_ref = '@constant(' . $_val . ')'; + } + $_max_index = 1; + break; + + case 'config': + $compiled_ref = "\$this->_config[0]['vars']"; + $_max_index = 3; + break; + + case 'ldelim': + $compiled_ref = "'$this->left_delimiter'"; + break; + + case 'rdelim': + $compiled_ref = "'$this->right_delimiter'"; + break; + + default: + $this->_syntax_error('$smarty.' . $_ref . ' is an unknown reference', E_USER_ERROR, __FILE__, __LINE__); + break; + } + + if (isset($_max_index) && count($indexes) > $_max_index) { + $this->_syntax_error('$smarty' . implode('', $indexes) .' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__); + } + + array_shift($indexes); + return $compiled_ref; + } + + /** + * compiles call to plugin of type $type with name $name + * returns a string containing the function-name or method call + * without the paramter-list that would have follow to make the + * call valid php-syntax + * + * @param string $type + * @param string $name + * @return string + */ + function _compile_plugin_call($type, $name) { + if (isset($this->_plugins[$type][$name])) { + /* plugin loaded */ + if (is_array($this->_plugins[$type][$name][0])) { + return ((is_object($this->_plugins[$type][$name][0][0])) ? + "\$this->_plugins['$type']['$name'][0][0]->" /* method callback */ + : (string)($this->_plugins[$type][$name][0][0]).'::' /* class callback */ + ). $this->_plugins[$type][$name][0][1]; + + } else { + /* function callback */ + return $this->_plugins[$type][$name][0]; + + } + } else { + /* plugin not loaded -> auto-loadable-plugin */ + return 'smarty_'.$type.'_'.$name; + + } + } + + /** + * load pre- and post-filters + */ + function _load_filters() + { + if (count($this->_plugins['prefilter']) > 0) { + foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) { + if ($prefilter === false) { + unset($this->_plugins['prefilter'][$filter_name]); + $_params = array('plugins' => array(array('prefilter', $filter_name, null, null, false))); + require_once(SMARTY_CORE_DIR . 'core.load_plugins.php'); + smarty_core_load_plugins($_params, $this); + } + } + } + if (count($this->_plugins['postfilter']) > 0) { + foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) { + if ($postfilter === false) { + unset($this->_plugins['postfilter'][$filter_name]); + $_params = array('plugins' => array(array('postfilter', $filter_name, null, null, false))); + require_once(SMARTY_CORE_DIR . 'core.load_plugins.php'); + smarty_core_load_plugins($_params, $this); + } + } + } + } + + + /** + * Quote subpattern references + * + * @param string $string + * @return string + */ + function _quote_replace($string) + { + return strtr($string, array('\\' => '\\\\', '$' => '\\$')); + } + + /** + * display Smarty syntax error + * + * @param string $error_msg + * @param integer $error_type + * @param string $file + * @param integer $line + */ + function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=null, $line=null) + { + $this->_trigger_fatal_error("syntax error: $error_msg", $this->_current_file, $this->_current_line_no, $file, $line, $error_type); + } + + + /** + * check if the compilation changes from cacheable to + * non-cacheable state with the beginning of the current + * plugin. return php-code to reflect the transition. + * @return string + */ + function _push_cacheable_state($type, $name) { + $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4]; + if ($_cacheable + || 0<$this->_cacheable_state++) return ''; + if (!isset($this->_cache_serial)) $this->_cache_serial = md5(uniqid('Smarty')); + $_ret = 'if ($this->caching && !$this->_cache_including): echo \'{nocache:' + . $this->_cache_serial . '#' . $this->_nocache_count + . '}\'; endif;'; + return $_ret; + } + + + /** + * check if the compilation changes from non-cacheable to + * cacheable state with the end of the current plugin return + * php-code to reflect the transition. + * @return string + */ + function _pop_cacheable_state($type, $name) { + $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4]; + if ($_cacheable + || --$this->_cacheable_state>0) return ''; + return 'if ($this->caching && !$this->_cache_including): echo \'{/nocache:' + . $this->_cache_serial . '#' . ($this->_nocache_count++) + . '}\'; endif;'; + } + + + /** + * push opening tag-name, file-name and line-number on the tag-stack + * @param string the opening tag's name + */ + function _push_tag($open_tag) + { + array_push($this->_tag_stack, array($open_tag, $this->_current_line_no)); + } + + /** + * pop closing tag-name + * raise an error if this stack-top doesn't match with the closing tag + * @param string the closing tag's name + * @return string the opening tag's name + */ + function _pop_tag($close_tag) + { + $message = ''; + if (count($this->_tag_stack)>0) { + list($_open_tag, $_line_no) = array_pop($this->_tag_stack); + if ($close_tag == $_open_tag) { + return $_open_tag; + } + if ($close_tag == 'if' && ($_open_tag == 'else' || $_open_tag == 'elseif' )) { + return $this->_pop_tag($close_tag); + } + if ($close_tag == 'section' && $_open_tag == 'sectionelse') { + $this->_pop_tag($close_tag); + return $_open_tag; + } + if ($close_tag == 'foreach' && $_open_tag == 'foreachelse') { + $this->_pop_tag($close_tag); + return $_open_tag; + } + if ($_open_tag == 'else' || $_open_tag == 'elseif') { + $_open_tag = 'if'; + } elseif ($_open_tag == 'sectionelse') { + $_open_tag = 'section'; + } elseif ($_open_tag == 'foreachelse') { + $_open_tag = 'foreach'; + } + $message = " expected {/$_open_tag} (opened line $_line_no)."; + } + $this->_syntax_error("mismatched tag {/$close_tag}.$message", + E_USER_ERROR, __FILE__, __LINE__); + } + +} + +/** + * compare to values by their string length + * + * @access private + * @param string $a + * @param string $b + * @return 0|-1|1 + */ +function _smarty_sort_length($a, $b) +{ + if($a == $b) + return 0; + + if(strlen($a) == strlen($b)) + return ($a > $b) ? -1 : 1; + + return (strlen($a) > strlen($b)) ? -1 : 1; +} + + +/* vim: set et: */ + +?> diff --git a/inc/smarty/debug.tpl b/inc/smarty/debug.tpl new file mode 100644 index 0000000..c05ef5d --- /dev/null +++ b/inc/smarty/debug.tpl @@ -0,0 +1,157 @@ +{* Smarty *} +{* debug.tpl, last updated version 2.1.0 *} +{assign_debug_info} +{capture assign=debug_output} + + + + Smarty Debug Console +{literal} + +{/literal} + + + +

Smarty Debug Console

+ +

included templates & config files (load time in seconds)

+ +
+{section name=templates loop=$_debug_tpls} + {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} +
+{sectionelse} +

no templates included

+{/section} +
+ +

assigned template variables

+ + + {section name=vars loop=$_debug_keys} + + + + {sectionelse} + + {/section} +
{ldelim}${$_debug_keys[vars]|escape:'html'}{rdelim}{$_debug_vals[vars]|@debug_print_var}

no template variables assigned

+ +

assigned config file variables (outer template scope)

+ + + {section name=config_vars loop=$_debug_config_keys} + + + + {sectionelse} + + {/section} +
{ldelim}#{$_debug_config_keys[config_vars]|escape:'html'}#{rdelim}{$_debug_config_vals[config_vars]|@debug_print_var}

no config vars assigned

+ + +{/capture} +{if isset($_smarty_debug_output) and $_smarty_debug_output eq "html"} + {$debug_output} +{else} + +{/if} \ No newline at end of file diff --git a/inc/smarty/internals/core.assemble_plugin_filepath.php b/inc/smarty/internals/core.assemble_plugin_filepath.php new file mode 100644 index 0000000..690d3dd --- /dev/null +++ b/inc/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/inc/smarty/internals/core.assign_smarty_interface.php b/inc/smarty/internals/core.assign_smarty_interface.php new file mode 100644 index 0000000..7e65a73 --- /dev/null +++ b/inc/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/inc/smarty/internals/core.create_dir_structure.php b/inc/smarty/internals/core.create_dir_structure.php new file mode 100644 index 0000000..3eecc49 --- /dev/null +++ b/inc/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/inc/smarty/internals/core.display_debug_console.php b/inc/smarty/internals/core.display_debug_console.php new file mode 100644 index 0000000..1a80f39 --- /dev/null +++ b/inc/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[] = realpath($smarty->debug_tpl); + } + $smarty->debug_tpl = 'file:' . SMARTY_DIR . 'debug.tpl'; + } + + $_ldelim_orig = $smarty->left_delimiter; + $_rdelim_orig = $smarty->right_delimiter; + + $smarty->left_delimiter = '{'; + $smarty->right_delimiter = '}'; + + $_compile_id_orig = $smarty->_compile_id; + $smarty->_compile_id = null; + + $_compile_path = $smarty->_get_compile_path($smarty->debug_tpl); + if ($smarty->_compile_resource($smarty->debug_tpl, $_compile_path)) + { + ob_start(); + $smarty->_include($_compile_path); + $_results = ob_get_contents(); + ob_end_clean(); + } else { + $_results = ''; + } + + $smarty->_compile_id = $_compile_id_orig; + + $smarty->left_delimiter = $_ldelim_orig; + $smarty->right_delimiter = $_rdelim_orig; + + return $_results; +} + +/* vim: set expandtab: */ + +?> diff --git a/inc/smarty/internals/core.get_include_path.php b/inc/smarty/internals/core.get_include_path.php new file mode 100644 index 0000000..4343241 --- /dev/null +++ b/inc/smarty/internals/core.get_include_path.php @@ -0,0 +1,44 @@ + diff --git a/inc/smarty/internals/core.get_microtime.php b/inc/smarty/internals/core.get_microtime.php new file mode 100644 index 0000000..f1a28e0 --- /dev/null +++ b/inc/smarty/internals/core.get_microtime.php @@ -0,0 +1,23 @@ + diff --git a/inc/smarty/internals/core.get_php_resource.php b/inc/smarty/internals/core.get_php_resource.php new file mode 100644 index 0000000..786d4e7 --- /dev/null +++ b/inc/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/inc/smarty/internals/core.is_secure.php b/inc/smarty/internals/core.is_secure.php new file mode 100644 index 0000000..d54abd4 --- /dev/null +++ b/inc/smarty/internals/core.is_secure.php @@ -0,0 +1,59 @@ +security || $smarty->security_settings['INCLUDE_ANY']) { + return true; + } + + if ($params['resource_type'] == 'file') { + $_rp = realpath($params['resource_name']); + if (isset($params['resource_base_path'])) { + foreach ((array)$params['resource_base_path'] as $curr_dir) { + if ( ($_cd = realpath($curr_dir)) !== false && + strncmp($_rp, $_cd, strlen($_cd)) == 0 && + substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR ) { + return true; + } + } + } + if (!empty($smarty->secure_dir)) { + foreach ((array)$smarty->secure_dir as $curr_dir) { + if ( ($_cd = realpath($curr_dir)) !== false) { + if($_cd == $_rp) { + return true; + } elseif (strncmp($_rp, $_cd, strlen($_cd)) == 0 && + substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR) { + return true; + } + } + } + } + } else { + // resource is not on local file system + return call_user_func_array( + $smarty->_plugins['resource'][$params['resource_type']][0][2], + array($params['resource_name'], &$smarty)); + } + + return false; +} + +/* vim: set expandtab: */ + +?> diff --git a/inc/smarty/internals/core.is_trusted.php b/inc/smarty/internals/core.is_trusted.php new file mode 100644 index 0000000..4299731 --- /dev/null +++ b/inc/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 + && substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR ) { + $_smarty_trusted = true; + break; + } + } + } + } + + } else { + // resource is not on local file system + $_smarty_trusted = call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][3], + array($params['resource_name'], $smarty)); + } + + return $_smarty_trusted; +} + +/* vim: set expandtab: */ + +?> diff --git a/inc/smarty/internals/core.load_plugins.php b/inc/smarty/internals/core.load_plugins.php new file mode 100644 index 0000000..6db1dc5 --- /dev/null +++ b/inc/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/inc/smarty/internals/core.load_resource_plugin.php b/inc/smarty/internals/core.load_resource_plugin.php new file mode 100644 index 0000000..a7d37d1 --- /dev/null +++ b/inc/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/inc/smarty/internals/core.process_cached_inserts.php b/inc/smarty/internals/core.process_cached_inserts.php new file mode 100644 index 0000000..1d78edd --- /dev/null +++ b/inc/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'] = substr_replace($params['results'], $replace, strpos($params['results'], $cached_inserts[$i]), strlen($cached_inserts[$i])); + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $smarty->_smarty_debug_info[] = array('type' => 'insert', + 'filename' => 'insert_'.$name, + 'depth' => $smarty->_inclusion_depth, + 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $debug_start_time); + } + } + + return $params['results']; +} + +/* vim: set expandtab: */ + +?> diff --git a/inc/smarty/internals/core.process_compiled_include.php b/inc/smarty/internals/core.process_compiled_include.php new file mode 100644 index 0000000..d539423 --- /dev/null +++ b/inc/smarty/internals/core.process_compiled_include.php @@ -0,0 +1,37 @@ +_cache_including; + $smarty->_cache_including = true; + + $_return = $params['results']; + + foreach ($smarty->_cache_info['cache_serials'] as $_include_file_path=>$_cache_serial) { + $smarty->_include($_include_file_path, true); + } + + foreach ($smarty->_cache_serials as $_include_file_path=>$_cache_serial) { + $_return = preg_replace_callback('!(\{nocache\:('.$_cache_serial.')#(\d+)\})!s', + array(&$smarty, '_process_compiled_include_callback'), + $_return); + } + $smarty->_cache_including = $_cache_including; + return $_return; +} + +?> diff --git a/inc/smarty/internals/core.read_cache_file.php b/inc/smarty/internals/core.read_cache_file.php new file mode 100644 index 0000000..c60e113 --- /dev/null +++ b/inc/smarty/internals/core.read_cache_file.php @@ -0,0 +1,101 @@ +force_compile) { + // force compile enabled, always regenerate + return false; + } + + if (isset($content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']])) { + list($params['results'], $smarty->_cache_info) = $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']]; + return true; + } + + if (!empty($smarty->cache_handler_func)) { + // use cache_handler function + call_user_func_array($smarty->cache_handler_func, + array('read', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null)); + } else { + // use local cache file + $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']); + $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id); + $params['results'] = $smarty->_read_file($_cache_file); + } + + if (empty($params['results'])) { + // nothing to parse (error?), regenerate cache + return false; + } + + $_contents = $params['results']; + $_info_start = strpos($_contents, "\n") + 1; + $_info_len = (int)substr($_contents, 0, $_info_start - 1); + $_cache_info = unserialize(substr($_contents, $_info_start, $_info_len)); + $params['results'] = substr($_contents, $_info_start + $_info_len); + + if ($smarty->caching == 2 && isset ($_cache_info['expires'])){ + // caching by expiration time + if ($_cache_info['expires'] > -1 && (time() > $_cache_info['expires'])) { + // cache expired, regenerate + return false; + } + } else { + // caching by lifetime + if ($smarty->cache_lifetime > -1 && (time() - $_cache_info['timestamp'] > $smarty->cache_lifetime)) { + // cache expired, regenerate + return false; + } + } + + if ($smarty->compile_check) { + $_params = array('get_source' => false, 'quiet'=>true); + foreach (array_keys($_cache_info['template']) as $_template_dep) { + $_params['resource_name'] = $_template_dep; + if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) { + // template file has changed, regenerate cache + return false; + } + } + + if (isset($_cache_info['config'])) { + $_params = array('resource_base_path' => $smarty->config_dir, 'get_source' => false, 'quiet'=>true); + foreach (array_keys($_cache_info['config']) as $_config_dep) { + $_params['resource_name'] = $_config_dep; + if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) { + // config file has changed, regenerate cache + return false; + } + } + } + } + + $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']] = array($params['results'], $_cache_info); + + $smarty->_cache_info = $_cache_info; + return true; +} + +/* vim: set expandtab: */ + +?> diff --git a/inc/smarty/internals/core.rm_auto.php b/inc/smarty/internals/core.rm_auto.php new file mode 100644 index 0000000..b251f64 --- /dev/null +++ b/inc/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/inc/smarty/internals/core.rmdir.php b/inc/smarty/internals/core.rmdir.php new file mode 100644 index 0000000..2166c44 --- /dev/null +++ b/inc/smarty/internals/core.rmdir.php @@ -0,0 +1,54 @@ + keep root) + * WARNING: no tests, it will try to remove what you tell it! + * + * @param string $dirname + * @param integer $level + * @param integer $exp_time + * @return boolean + */ + +// $dirname, $level = 1, $exp_time = null + +function smarty_core_rmdir($params, &$smarty) +{ + if(!isset($params['level'])) { $params['level'] = 1; } + if(!isset($params['exp_time'])) { $params['exp_time'] = null; } + + if($_handle = @opendir($params['dirname'])) { + + while (false !== ($_entry = readdir($_handle))) { + if ($_entry != '.' && $_entry != '..') { + if (@is_dir($params['dirname'] . DIRECTORY_SEPARATOR . $_entry)) { + $_params = array( + 'dirname' => $params['dirname'] . DIRECTORY_SEPARATOR . $_entry, + 'level' => $params['level'] + 1, + 'exp_time' => $params['exp_time'] + ); + smarty_core_rmdir($_params, $smarty); + } + else { + $smarty->_unlink($params['dirname'] . DIRECTORY_SEPARATOR . $_entry, $params['exp_time']); + } + } + } + closedir($_handle); + } + + if ($params['level']) { + return @rmdir($params['dirname']); + } + return (bool)$_handle; + +} + +/* vim: set expandtab: */ + +?> diff --git a/inc/smarty/internals/core.run_insert_handler.php b/inc/smarty/internals/core.run_insert_handler.php new file mode 100644 index 0000000..71c3845 --- /dev/null +++ b/inc/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/inc/smarty/internals/core.smarty_include_php.php b/inc/smarty/internals/core.smarty_include_php.php new file mode 100644 index 0000000..30c6e76 --- /dev/null +++ b/inc/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/inc/smarty/internals/core.write_cache_file.php b/inc/smarty/internals/core.write_cache_file.php new file mode 100644 index 0000000..72f785b --- /dev/null +++ b/inc/smarty/internals/core.write_cache_file.php @@ -0,0 +1,96 @@ +_cache_info['timestamp'] = time(); + if ($smarty->cache_lifetime > -1){ + // expiration set + $smarty->_cache_info['expires'] = $smarty->_cache_info['timestamp'] + $smarty->cache_lifetime; + } else { + // cache will never expire + $smarty->_cache_info['expires'] = -1; + } + + // collapse nocache.../nocache-tags + if (preg_match_all('!\{(/?)nocache\:[0-9a-f]{32}#\d+\}!', $params['results'], $match, PREG_PATTERN_ORDER)) { + // remove everything between every pair of outermost noache.../nocache-tags + // and replace it by a single nocache-tag + // this new nocache-tag will be replaced by dynamic contents in + // smarty_core_process_compiled_includes() on a cache-read + + $match_count = count($match[0]); + $results = preg_split('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!', $params['results'], -1, PREG_SPLIT_DELIM_CAPTURE); + + $level = 0; + $j = 0; + for ($i=0, $results_count = count($results); $i < $results_count && $j < $match_count; $i++) { + if ($results[$i] == $match[0][$j]) { + // nocache tag + if ($match[1][$j]) { // closing tag + $level--; + unset($results[$i]); + } else { // opening tag + if ($level++ > 0) unset($results[$i]); + } + $j++; + } elseif ($level > 0) { + unset($results[$i]); + } + } + $params['results'] = implode('', $results); + } + $smarty->_cache_info['cache_serials'] = $smarty->_cache_serials; + + // prepend the cache header info into cache file + $_cache_info = serialize($smarty->_cache_info); + $params['results'] = strlen($_cache_info) . "\n" . $_cache_info . $params['results']; + + if (!empty($smarty->cache_handler_func)) { + // use cache_handler function + call_user_func_array($smarty->cache_handler_func, + array('write', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null)); + } else { + // use local cache file + + if(!@is_writable($smarty->cache_dir)) { + // cache_dir not writable, see if it exists + if(!@is_dir($smarty->cache_dir)) { + $smarty->trigger_error('the $cache_dir \'' . $smarty->cache_dir . '\' does not exist, or is not a directory.', E_USER_ERROR); + return false; + } + $smarty->trigger_error('unable to write to $cache_dir \'' . realpath($smarty->cache_dir) . '\'. Be sure $cache_dir is writable by the web server user.', E_USER_ERROR); + return false; + } + + $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']); + $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id); + $_params = array('filename' => $_cache_file, 'contents' => $params['results'], 'create_dirs' => true); + require_once(SMARTY_CORE_DIR . 'core.write_file.php'); + smarty_core_write_file($_params, $smarty); + return true; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/inc/smarty/internals/core.write_compiled_include.php b/inc/smarty/internals/core.write_compiled_include.php new file mode 100644 index 0000000..c14adb5 --- /dev/null +++ b/inc/smarty/internals/core.write_compiled_include.php @@ -0,0 +1,91 @@ +caching && \!\$this->_cache_including\)\: echo \'\{nocache\:('.$params['cache_serial'].')#(\d+)\}\'; endif;'; + $_tag_end = 'if \(\$this->caching && \!\$this->_cache_including\)\: echo \'\{/nocache\:(\\2)#(\\3)\}\'; endif;'; + + preg_match_all('!('.$_tag_start.'(.*)'.$_tag_end.')!Us', + $params['compiled_content'], $_match_source, PREG_SET_ORDER); + + // no nocache-parts found: done + if (count($_match_source)==0) return; + + // convert the matched php-code to functions + $_include_compiled = "_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/inc/smarty/internals/core.write_compiled_resource.php b/inc/smarty/internals/core.write_compiled_resource.php new file mode 100644 index 0000000..b902eff --- /dev/null +++ b/inc/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/inc/smarty/internals/core.write_file.php b/inc/smarty/internals/core.write_file.php new file mode 100644 index 0000000..8a3a3b3 --- /dev/null +++ b/inc/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); + + if (DIRECTORY_SEPARATOR == '\\' || !@rename($_tmp_file, $params['filename'])) { + // On platforms and filesystems that cannot overwrite with rename() + // delete the file before renaming it -- because windows always suffers + // this, it is short-circuited to avoid the initial rename() attempt + @unlink($params['filename']); + @rename($_tmp_file, $params['filename']); + } + @chmod($params['filename'], $smarty->_file_perms); + + return true; +} + +/* vim: set expandtab: */ + +?> \ No newline at end of file diff --git a/inc/smarty/plugins/block.textformat.php b/inc/smarty/plugins/block.textformat.php new file mode 100644 index 0000000..8cd010a --- /dev/null +++ b/inc/smarty/plugins/block.textformat.php @@ -0,0 +1,103 @@ + + * 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)
+ * 
+ * @author Monte Ohrt + * @param string contents of the block + * @param Smarty clever simulation of a method + * @return string string $content re-formatted + */ +function smarty_block_textformat($params, $content, &$smarty) +{ + if (is_null($content)) { + return; + } + + $style = null; + $indent = 0; + $indent_first = 0; + $indent_char = ' '; + $wrap = 80; + $wrap_char = "\n"; + $wrap_cut = false; + $assign = null; + + foreach ($params as $_key => $_val) { + switch ($_key) { + case 'style': + case 'indent_char': + case 'wrap_char': + case 'assign': + $$_key = (string)$_val; + break; + + case 'indent': + case 'indent_first': + case 'wrap': + $$_key = (int)$_val; + break; + + case 'wrap_cut': + $$_key = (bool)$_val; + break; + + default: + $smarty->trigger_error("textformat: unknown attribute '$_key'"); + } + } + + if ($style == 'email') { + $wrap = 72; + } + + // split into paragraphs + $_paragraphs = preg_split('![\r\n][\r\n]!',$content); + $_output = ''; + + for($_x = 0, $_y = count($_paragraphs); $_x < $_y; $_x++) { + if ($_paragraphs[$_x] == '') { + continue; + } + // convert mult. spaces & special chars to single space + $_paragraphs[$_x] = preg_replace(array('!\s+!','!(^\s+)|(\s+$)!'), array(' ',''), $_paragraphs[$_x]); + // indent first line + if($indent_first > 0) { + $_paragraphs[$_x] = str_repeat($indent_char, $indent_first) . $_paragraphs[$_x]; + } + // wordwrap sentences + $_paragraphs[$_x] = wordwrap($_paragraphs[$_x], $wrap - $indent, $wrap_char, $wrap_cut); + // indent lines + if($indent > 0) { + $_paragraphs[$_x] = preg_replace('!^!m', str_repeat($indent_char, $indent), $_paragraphs[$_x]); + } + } + $_output = implode($wrap_char . $wrap_char, $_paragraphs); + + return $assign ? $smarty->assign($assign, $_output) : $_output; + +} + +/* vim: set expandtab: */ + +?> diff --git a/inc/smarty/plugins/compiler.assign.php b/inc/smarty/plugins/compiler.assign.php new file mode 100644 index 0000000..be17298 --- /dev/null +++ b/inc/smarty/plugins/compiler.assign.php @@ -0,0 +1,40 @@ + + * 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) + * @author Monte Ohrt (initial author) + * @auther messju mohr (conversion to compiler function) + * @param string containing var-attribute and value-attribute + * @param Smarty_Compiler + */ +function smarty_compiler_assign($tag_attrs, &$compiler) +{ + $_params = $compiler->_parse_attrs($tag_attrs); + + if (!isset($_params['var'])) { + $compiler->_syntax_error("assign: missing 'var' parameter", E_USER_WARNING); + return; + } + + if (!isset($_params['value'])) { + $compiler->_syntax_error("assign: missing 'value' parameter", E_USER_WARNING); + return; + } + + return "\$this->assign({$_params['var']}, {$_params['value']});"; +} + +/* vim: set expandtab: */ + +?> diff --git a/inc/smarty/plugins/function.assign.php b/inc/smarty/plugins/function.assign.php new file mode 100644 index 0000000..ad23f04 --- /dev/null +++ b/inc/smarty/plugins/function.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 array Format: array('var' => variable name, 'value' => value to assign) + * @param Smarty + */ +function smarty_function_assign($params, &$smarty) +{ + extract($params); + + if (empty($var)) { + $smarty->trigger_error("assign: missing 'var' parameter"); + return; + } + + if (!in_array('value', array_keys($params))) { + $smarty->trigger_error("assign: missing 'value' parameter"); + return; + } + + $smarty->assign($var, $value); +} + +/* vim: set expandtab: */ + +?> diff --git a/inc/smarty/plugins/function.assign_debug_info.php b/inc/smarty/plugins/function.assign_debug_info.php new file mode 100644 index 0000000..6540498 --- /dev/null +++ b/inc/smarty/plugins/function.assign_debug_info.php @@ -0,0 +1,40 @@ + + * Name: assign_debug_info
+ * Purpose: assign debug info to the template
+ * @author Monte Ohrt + * @param array unused in this plugin, this plugin uses {@link Smarty::$_config}, + * {@link Smarty::$_tpl_vars} and {@link Smarty::$_smarty_debug_info} + * @param Smarty + */ +function smarty_function_assign_debug_info($params, &$smarty) +{ + $assigned_vars = $smarty->_tpl_vars; + ksort($assigned_vars); + if (@is_array($smarty->_config[0])) { + $config_vars = $smarty->_config[0]; + ksort($config_vars); + $smarty->assign("_debug_config_keys", array_keys($config_vars)); + $smarty->assign("_debug_config_vals", array_values($config_vars)); + } + + $included_templates = $smarty->_smarty_debug_info; + + $smarty->assign("_debug_keys", array_keys($assigned_vars)); + $smarty->assign("_debug_vals", array_values($assigned_vars)); + + $smarty->assign("_debug_tpls", $included_templates); +} + +/* vim: set expandtab: */ + +?> diff --git a/inc/smarty/plugins/function.config_load.php b/inc/smarty/plugins/function.config_load.php new file mode 100644 index 0000000..db89f63 --- /dev/null +++ b/inc/smarty/plugins/function.config_load.php @@ -0,0 +1,142 @@ + + * 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) + * @author Monte Ohrt + * @author messju mohr (added use of resources) + * @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/inc/smarty/plugins/function.counter.php b/inc/smarty/plugins/function.counter.php new file mode 100644 index 0000000..1f26db5 --- /dev/null +++ b/inc/smarty/plugins/function.counter.php @@ -0,0 +1,80 @@ + + * Name: counter
+ * Purpose: print out a counter value + * @author Monte Ohrt + * @link http://smarty.php.net/manual/en/language.function.counter.php {counter} + * (Smarty online manual) + * @param array parameters + * @param Smarty + * @return string|null + */ +function smarty_function_counter($params, &$smarty) +{ + static $counters = array(); + + $name = (isset($params['name'])) ? $params['name'] : 'default'; + if (!isset($counters[$name])) { + $counters[$name] = array( + 'start'=>1, + 'skip'=>1, + 'direction'=>'up', + 'count'=>1 + ); + } + $counter =& $counters[$name]; + + if (isset($params['start'])) { + $counter['start'] = $counter['count'] = (int)$params['start']; + } + + if (!empty($params['assign'])) { + $counter['assign'] = $params['assign']; + } + + if (isset($counter['assign'])) { + $smarty->assign($counter['assign'], $counter['count']); + } + + if (isset($params['print'])) { + $print = (bool)$params['print']; + } else { + $print = empty($counter['assign']); + } + + if ($print) { + $retval = $counter['count']; + } else { + $retval = null; + } + + if (isset($params['skip'])) { + $counter['skip'] = $params['skip']; + } + + if (isset($params['direction'])) { + $counter['direction'] = $params['direction']; + } + + if ($counter['direction'] == "down") + $counter['count'] -= $counter['skip']; + else + $counter['count'] += $counter['skip']; + + return $retval; + +} + +/* vim: set expandtab: */ + +?> diff --git a/inc/smarty/plugins/function.cycle.php b/inc/smarty/plugins/function.cycle.php new file mode 100644 index 0000000..fe78bb8 --- /dev/null +++ b/inc/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/inc/smarty/plugins/function.debug.php b/inc/smarty/plugins/function.debug.php new file mode 100644 index 0000000..4345230 --- /dev/null +++ b/inc/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/inc/smarty/plugins/function.eval.php b/inc/smarty/plugins/function.eval.php new file mode 100644 index 0000000..ff0472d --- /dev/null +++ b/inc/smarty/plugins/function.eval.php @@ -0,0 +1,49 @@ + + * 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) + * @author Monte Ohrt + * @param array + * @param Smarty + */ +function smarty_function_eval($params, &$smarty) +{ + + if (!isset($params['var'])) { + $smarty->trigger_error("eval: missing 'var' parameter"); + return; + } + + if($params['var'] == '') { + return; + } + + $smarty->_compile_source('evaluated template', $params['var'], $_var_compiled); + + ob_start(); + $smarty->_eval('?>' . $_var_compiled); + $_contents = ob_get_contents(); + ob_end_clean(); + + if (!empty($params['assign'])) { + $smarty->assign($params['assign'], $_contents); + } else { + return $_contents; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/inc/smarty/plugins/function.fetch.php b/inc/smarty/plugins/function.fetch.php new file mode 100644 index 0000000..81b1bfc --- /dev/null +++ b/inc/smarty/plugins/function.fetch.php @@ -0,0 +1,221 @@ + + * 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) + * @author Monte Ohrt + * @param array + * @param Smarty + * @return string|null if the assign parameter is passed, Smarty assigns the + * result to a template variable + */ +function smarty_function_fetch($params, &$smarty) +{ + if (empty($params['file'])) { + $smarty->_trigger_fatal_error("[plugin] parameter 'file' cannot be empty"); + return; + } + + $content = ''; + if ($smarty->security && !preg_match('!^(http|ftp)://!i', $params['file'])) { + $_params = array('resource_type' => 'file', 'resource_name' => $params['file']); + require_once(SMARTY_CORE_DIR . 'core.is_secure.php'); + if(!smarty_core_is_secure($_params, $smarty)) { + $smarty->_trigger_fatal_error('[plugin] (secure mode) fetch \'' . $params['file'] . '\' is not allowed'); + return; + } + + // fetch the file + if($fp = @fopen($params['file'],'r')) { + while(!feof($fp)) { + $content .= fgets ($fp,4096); + } + fclose($fp); + } else { + $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] . '\''); + return; + } + } else { + // not a local file + if(preg_match('!^http://!i',$params['file'])) { + // http fetch + if($uri_parts = parse_url($params['file'])) { + // set defaults + $host = $server_name = $uri_parts['host']; + $timeout = 30; + $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*"; + $agent = "Smarty Template Engine ".$smarty->_version; + $referer = ""; + $uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/'; + $uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : ''; + $_is_proxy = false; + if(empty($uri_parts['port'])) { + $port = 80; + } else { + $port = $uri_parts['port']; + } + if(!empty($uri_parts['user'])) { + $user = $uri_parts['user']; + } + if(!empty($uri_parts['pass'])) { + $pass = $uri_parts['pass']; + } + // loop through parameters, setup headers + foreach($params as $param_key => $param_value) { + switch($param_key) { + case "file": + case "assign": + case "assign_headers": + break; + case "user": + if(!empty($param_value)) { + $user = $param_value; + } + break; + case "pass": + if(!empty($param_value)) { + $pass = $param_value; + } + break; + case "accept": + if(!empty($param_value)) { + $accept = $param_value; + } + break; + case "header": + if(!empty($param_value)) { + if(!preg_match('![\w\d-]+: .+!',$param_value)) { + $smarty->_trigger_fatal_error("[plugin] invalid header format '".$param_value."'"); + return; + } else { + $extra_headers[] = $param_value; + } + } + break; + case "proxy_host": + if(!empty($param_value)) { + $proxy_host = $param_value; + } + break; + case "proxy_port": + if(!preg_match('!\D!', $param_value)) { + $proxy_port = (int) $param_value; + } else { + $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'"); + return; + } + break; + case "agent": + if(!empty($param_value)) { + $agent = $param_value; + } + break; + case "referer": + if(!empty($param_value)) { + $referer = $param_value; + } + break; + case "timeout": + if(!preg_match('!\D!', $param_value)) { + $timeout = (int) $param_value; + } else { + $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'"); + return; + } + break; + default: + $smarty->_trigger_fatal_error("[plugin] unrecognized attribute '".$param_key."'"); + return; + } + } + if(!empty($proxy_host) && !empty($proxy_port)) { + $_is_proxy = true; + $fp = fsockopen($proxy_host,$proxy_port,$errno,$errstr,$timeout); + } else { + $fp = fsockopen($server_name,$port,$errno,$errstr,$timeout); + } + + if(!$fp) { + $smarty->_trigger_fatal_error("[plugin] unable to fetch: $errstr ($errno)"); + return; + } else { + if($_is_proxy) { + fputs($fp, 'GET ' . $params['file'] . " HTTP/1.0\r\n"); + } else { + fputs($fp, "GET $uri HTTP/1.0\r\n"); + } + if(!empty($host)) { + fputs($fp, "Host: $host\r\n"); + } + if(!empty($accept)) { + fputs($fp, "Accept: $accept\r\n"); + } + if(!empty($agent)) { + fputs($fp, "User-Agent: $agent\r\n"); + } + if(!empty($referer)) { + fputs($fp, "Referer: $referer\r\n"); + } + if(isset($extra_headers) && is_array($extra_headers)) { + foreach($extra_headers as $curr_header) { + fputs($fp, $curr_header."\r\n"); + } + } + if(!empty($user) && !empty($pass)) { + fputs($fp, "Authorization: BASIC ".base64_encode("$user:$pass")."\r\n"); + } + + fputs($fp, "\r\n"); + while(!feof($fp)) { + $content .= fgets($fp,4096); + } + fclose($fp); + $csplit = split("\r\n\r\n",$content,2); + + $content = $csplit[1]; + + if(!empty($params['assign_headers'])) { + $smarty->assign($params['assign_headers'],split("\r\n",$csplit[0])); + } + } + } else { + $smarty->_trigger_fatal_error("[plugin] unable to parse URL, check syntax"); + return; + } + } else { + // ftp fetch + if($fp = @fopen($params['file'],'r')) { + while(!feof($fp)) { + $content .= fgets ($fp,4096); + } + fclose($fp); + } else { + $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] .'\''); + return; + } + } + + } + + + if (!empty($params['assign'])) { + $smarty->assign($params['assign'],$content); + } else { + return $content; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/inc/smarty/plugins/function.html_checkboxes.php b/inc/smarty/plugins/function.html_checkboxes.php new file mode 100644 index 0000000..ed8ad7f --- /dev/null +++ b/inc/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 (isset($options)) { + + foreach ($options as $_key=>$_val) + $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels); + + + } else { + foreach ($values as $_i=>$_key) { + $_val = isset($output[$_i]) ? $output[$_i] : ''; + $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels); + } + + } + + if(!empty($params['assign'])) { + $smarty->assign($params['assign'], $_html_result); + } else { + return implode("\n",$_html_result); + } + +} + +function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels) { + $_output = ''; + if ($labels) $_output .= ''; + $_output .= $separator; + + return $_output; +} + +?> diff --git a/inc/smarty/plugins/function.html_image.php b/inc/smarty/plugins/function.html_image.php new file mode 100644 index 0000000..9abae72 --- /dev/null +++ b/inc/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) + * - height = image height (optional, default actual height) + * - width = image width (optional, default actual width) + * - basedir = base directory for absolute paths, default + * is environment variable DOCUMENT_ROOT + * - path_prefix = prefix for path output (optional, default empty) + * + * Examples: {html_image file="/images/masthead.gif"} + * Output: + * @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 = ''; + $height = ''; + $width = ''; + $extra = ''; + $prefix = ''; + $suffix = ''; + $path_prefix = ''; + $server_vars = ($smarty->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS']; + $basedir = isset($server_vars['DOCUMENT_ROOT']) ? $server_vars['DOCUMENT_ROOT'] : ''; + foreach($params as $_key => $_val) { + switch($_key) { + case 'file': + case 'height': + case 'width': + case 'dpi': + case 'path_prefix': + case 'basedir': + $$_key = $_val; + break; + + case 'alt': + if(!is_array($_val)) { + $$_key = smarty_function_escape_special_chars($_val); + } else { + $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE); + } + break; + + case 'link': + case 'href': + $prefix = ''; + $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(!$_image_data = @getimagesize($_image_path)) { + if(!file_exists($_image_path)) { + $smarty->trigger_error("html_image: unable to find '$_image_path'", E_USER_NOTICE); + return; + } else if(!is_readable($_image_path)) { + $smarty->trigger_error("html_image: unable to read '$_image_path'", E_USER_NOTICE); + return; + } else { + $smarty->trigger_error("html_image: '$_image_path' is not a valid image file", E_USER_NOTICE); + return; + } + } + if ($smarty->security && + ($_params = array('resource_type' => 'file', 'resource_name' => $_image_path)) && + (require_once(SMARTY_CORE_DIR . 'core.is_secure.php')) && + (!smarty_core_is_secure($_params, $smarty)) ) { + $smarty->trigger_error("html_image: (secure) '$_image_path' not in secure directory", E_USER_NOTICE); + } + + if(!isset($params['width'])) { + $width = $_image_data[0]; + } + if(!isset($params['height'])) { + $height = $_image_data[1]; + } + + } + + if(isset($params['dpi'])) { + if(strstr($server_vars['HTTP_USER_AGENT'], 'Mac')) { + $dpi_default = 72; + } else { + $dpi_default = 96; + } + $_resize = $dpi_default/$params['dpi']; + $width = round($width * $_resize); + $height = round($height * $_resize); + } + + return $prefix . ''.$alt.'' . $suffix; +} + +/* vim: set expandtab: */ + +?> diff --git a/inc/smarty/plugins/function.html_options.php b/inc/smarty/plugins/function.html_options.php new file mode 100644 index 0000000..cebadde --- /dev/null +++ b/inc/smarty/plugins/function.html_options.php @@ -0,0 +1,122 @@ + + * 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