diff --git a/resources/templates/engine/smarty/README b/resources/templates/engine/smarty/README new file mode 100644 index 0000000000..89230921da --- /dev/null +++ b/resources/templates/engine/smarty/README @@ -0,0 +1,574 @@ +Smarty 3.1.15 + +Author: Monte Ohrt +Author: Uwe Tews + +AN INTRODUCTION TO SMARTY 3 + +NOTICE FOR 3.1 release: + +Please see the SMARTY_3.1_NOTES.txt file that comes with the distribution. + +NOTICE for 3.0.5 release: + +Smarty now follows the PHP error_reporting level by default. If PHP does not mask E_NOTICE and you try to access an unset template variable, you will now get an E_NOTICE warning. To revert to the old behavior: + +$smarty->error_reporting = E_ALL & ~E_NOTICE; + +NOTICE for 3.0 release: + +IMPORTANT: Some API adjustments have been made between the RC4 and 3.0 release. +We felt it is better to make these now instead of after a 3.0 release, then have to +immediately deprecate APIs in 3.1. Online documentation has been updated +to reflect these changes. Specifically: + +---- API CHANGES RC4 -> 3.0 ---- + +$smarty->register->* +$smarty->unregister->* +$smarty->utility->* +$samrty->cache->* + +Have all been changed to local method calls such as: + +$smarty->clearAllCache() +$smarty->registerFoo() +$smarty->unregisterFoo() +$smarty->testInstall() +etc. + +Registration of function, block, compiler, and modifier plugins have been +consolidated under two API calls: + +$smarty->registerPlugin(...) +$smarty->unregisterPlugin(...) + +Registration of pre, post, output and variable filters have been +consolidated under two API calls: + +$smarty->registerFilter(...) +$smarty->unregisterFilter(...) + +Please refer to the online documentation for all specific changes: + +http://www.smarty.net/documentation + +---- + +The Smarty 3 API has been refactored to a syntax geared +for consistency and modularity. The Smarty 2 API syntax is still supported, but +will throw a deprecation notice. You can disable the notices, but it is highly +recommended to adjust your syntax to Smarty 3, as the Smarty 2 syntax must run +through an extra rerouting wrapper. + +Basically, all Smarty methods now follow the "fooBarBaz" camel case syntax. Also, +all Smarty properties now have getters and setters. So for example, the property +$smarty->cache_dir can be set with $smarty->setCacheDir('foo/') and can be +retrieved with $smarty->getCacheDir(). + +Some of the Smarty 3 APIs have been revoked such as the "is*" methods that were +just duplicate functions of the now available "get*" methods. + +Here is a rundown of the Smarty 3 API: + +$smarty->fetch($template, $cache_id = null, $compile_id = null, $parent = null) +$smarty->display($template, $cache_id = null, $compile_id = null, $parent = null) +$smarty->isCached($template, $cache_id = null, $compile_id = null) +$smarty->createData($parent = null) +$smarty->createTemplate($template, $cache_id = null, $compile_id = null, $parent = null) +$smarty->enableSecurity() +$smarty->disableSecurity() +$smarty->setTemplateDir($template_dir) +$smarty->addTemplateDir($template_dir) +$smarty->templateExists($resource_name) +$smarty->loadPlugin($plugin_name, $check = true) +$smarty->loadFilter($type, $name) +$smarty->setExceptionHandler($handler) +$smarty->addPluginsDir($plugins_dir) +$smarty->getGlobal($varname = null) +$smarty->getRegisteredObject($name) +$smarty->getDebugTemplate() +$smarty->setDebugTemplate($tpl_name) +$smarty->assign($tpl_var, $value = null, $nocache = false) +$smarty->assignGlobal($varname, $value = null, $nocache = false) +$smarty->assignByRef($tpl_var, &$value, $nocache = false) +$smarty->append($tpl_var, $value = null, $merge = false, $nocache = false) +$smarty->appendByRef($tpl_var, &$value, $merge = false) +$smarty->clearAssign($tpl_var) +$smarty->clearAllAssign() +$smarty->configLoad($config_file, $sections = null) +$smarty->getVariable($variable, $_ptr = null, $search_parents = true, $error_enable = true) +$smarty->getConfigVariable($variable) +$smarty->getStreamVariable($variable) +$smarty->getConfigVars($varname = null) +$smarty->clearConfig($varname = null) +$smarty->getTemplateVars($varname = null, $_ptr = null, $search_parents = true) +$smarty->clearAllCache($exp_time = null, $type = null) +$smarty->clearCache($template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null) + +$smarty->registerPlugin($type, $tag, $callback, $cacheable = true, $cache_attr = array()) + +$smarty->registerObject($object_name, $object_impl, $allowed = array(), $smarty_args = true, $block_methods = array()) + +$smarty->registerFilter($type, $function_name) +$smarty->registerResource($resource_type, $function_names) +$smarty->registerDefaultPluginHandler($function_name) +$smarty->registerDefaultTemplateHandler($function_name) + +$smarty->unregisterPlugin($type, $tag) +$smarty->unregisterObject($object_name) +$smarty->unregisterFilter($type, $function_name) +$smarty->unregisterResource($resource_type) + +$smarty->compileAllTemplates($extension = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null) +$smarty->clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null) +$smarty->testInstall() + +// then all the getters/setters, available for all properties. Here are a few: + +$caching = $smarty->getCaching(); // get $smarty->caching +$smarty->setCaching(true); // set $smarty->caching +$smarty->setDeprecationNotices(false); // set $smarty->deprecation_notices +$smarty->setCacheId($id); // set $smarty->cache_id +$debugging = $smarty->getDebugging(); // get $smarty->debugging + + +FILE STRUCTURE + +The Smarty 3 file structure is similar to Smarty 2: + +/libs/ + Smarty.class.php +/libs/sysplugins/ + internal.* +/libs/plugins/ + function.mailto.php + modifier.escape.php + ... + +A lot of Smarty 3 core functionality lies in the sysplugins directory; you do +not need to change any files here. The /libs/plugins/ folder is where Smarty +plugins are located. You can add your own here, or create a separate plugin +directory, just the same as Smarty 2. You will still need to create your own +/cache/, /templates/, /templates_c/, /configs/ folders. Be sure /cache/ and +/templates_c/ are writable. + +The typical way to use Smarty 3 should also look familiar: + +require('Smarty.class.php'); +$smarty = new Smarty; +$smarty->assign('foo','bar'); +$smarty->display('index.tpl'); + + +However, Smarty 3 works completely different on the inside. Smarty 3 is mostly +backward compatible with Smarty 2, except for the following items: + +*) Smarty 3 is PHP 5 only. It will not work with PHP 4. +*) The {php} tag is disabled by default. Enable with $smarty->allow_php_tag=true. +*) Delimiters surrounded by whitespace are no longer treated as Smarty tags. + Therefore, { foo } will not compile as a tag, you must use {foo}. This change + Makes Javascript/CSS easier to work with, eliminating the need for {literal}. + This can be disabled by setting $smarty->auto_literal = false; +*) The Smarty 3 API is a bit different. Many Smarty 2 API calls are deprecated + but still work. You will want to update your calls to Smarty 3 for maximum + efficiency. + + +There are many things that are new to Smarty 3. Here are the notable items: + +LEXER/PARSER +============ + +Smarty 3 now uses a lexing tokenizer for its parser/compiler. Basically, this +means Smarty has some syntax additions that make life easier such as in-template +math, shorter/intuitive function parameter options, infinite function recursion, +more accurate error handling, etc. + + +WHAT IS NEW IN SMARTY TEMPLATE SYNTAX +===================================== + +Smarty 3 allows expressions almost anywhere. Expressions can include PHP +functions as long as they are not disabled by the security policy, object +methods and properties, etc. The {math} plugin is no longer necessary but +is still supported for BC. + +Examples: +{$x+$y} will output the sum of x and y. +{$foo = strlen($bar)} function in assignment +{assign var=foo value= $x+$y} in attributes +{$foo = myfunct( ($x+$y)*3 )} as function parameter +{$foo[$x+3]} as array index + +Smarty tags can be used as values within other tags. +Example: {$foo={counter}+3} + +Smarty tags can also be used inside double quoted strings. +Example: {$foo="this is message {counter}"} + +You can define arrays within templates. +Examples: +{assign var=foo value=[1,2,3]} +{assign var=foo value=['y'=>'yellow','b'=>'blue']} +Arrays can be nested. +{assign var=foo value=[1,[9,8],3]} + +There is a new short syntax supported for assigning variables. +Example: {$foo=$bar+2} + +You can assign a value to a specific array element. If the variable exists but +is not an array, it is converted to an array before the new values are assigned. +Examples: +{$foo['bar']=1} +{$foo['bar']['blar']=1} + +You can append values to an array. If the variable exists but is not an array, +it is converted to an array before the new values are assigned. +Example: {$foo[]=1} + +You can use a PHP-like syntax for accessing array elements, as well as the +original "dot" notation. +Examples: +{$foo[1]} normal access +{$foo['bar']} +{$foo['bar'][1]} +{$foo[$x+$x]} index may contain any expression +{$foo[$bar[1]]} nested index +{$foo[section_name]} smarty section access, not array access! + +The original "dot" notation stays, and with improvements. +Examples: +{$foo.a.b.c} => $foo['a']['b']['c'] +{$foo.a.$b.c} => $foo['a'][$b]['c'] with variable index +{$foo.a.{$b+4}.c} => $foo['a'][$b+4]['c'] with expression as index +{$foo.a.{$b.c}} => $foo['a'][$b['c']] with nested index + +note that { and } are used to address ambiguties when nesting the dot syntax. + +Variable names themselves can be variable and contain expressions. +Examples: +$foo normal variable +$foo_{$bar} variable name containing other variable +$foo_{$x+$y} variable name containing expressions +$foo_{$bar}_buh_{$blar} variable name with multiple segments +{$foo_{$x}} will output the variable $foo_1 if $x has a value of 1. + +Object method chaining is implemented. +Example: {$object->method1($x)->method2($y)} + +{for} tag added for looping (replacement for {section} tag): +{for $x=0, $y=count($foo); $x<$y; $x++} .... {/for} +Any number of statements can be used separated by comma as the first +inital expression at {for}. + +{for $x = $start to $end step $step} ... {/for}is in the SVN now . +You can use also +{for $x = $start to $end} ... {/for} +In this case the step value will be automaticall 1 or -1 depending on the start and end values. +Instead of $start and $end you can use any valid expression. +Inside the loop the following special vars can be accessed: +$x@iteration = number of iteration +$x@total = total number of iterations +$x@first = true on first iteration +$x@last = true on last iteration + + +The Smarty 2 {section} syntax is still supported. + +New shorter {foreach} syntax to loop over an array. +Example: {foreach $myarray as $var}...{/foreach} + +Within the foreach loop, properties are access via: + +$var@key foreach $var array key +$var@iteration foreach current iteration count (1,2,3...) +$var@index foreach current index count (0,1,2...) +$var@total foreach $var array total +$var@first true on first iteration +$var@last true on last iteration + +The Smarty 2 {foreach} tag syntax is still supported. + +NOTE: {$bar[foo]} still indicates a variable inside of a {section} named foo. +If you want to access an array element with index foo, you must use quotes +such as {$bar['foo']}, or use the dot syntax {$bar.foo}. + +while block tag is now implemented: +{while $foo}...{/while} +{while $x lt 10}...{/while} + +Direct access to PHP functions: +Just as you can use PHP functions as modifiers directly, you can now access +PHP functions directly, provided they are permitted by security settings: +{time()} + +There is a new {function}...{/function} block tag to implement a template function. +This enables reuse of code sequences like a plugin function. It can call itself recursively. +Template function must be called with the new {call name=foo...} tag. + +Example: + +Template file: +{function name=menu level=0} + +{/function} + +{$menu = ['item1','item2','item3' => ['item3-1','item3-2','item3-3' => + ['item3-3-1','item3-3-2']],'item4']} + +{call name=menu data=$menu} + + +Generated output: + * item1 + * item2 + * item3 + o item3-1 + o item3-2 + o item3-3 + + item3-3-1 + + item3-3-2 + * item4 + +The function tag itself must have the "name" attribute. This name is the tag +name when calling the function. The function tag may have any number of +additional attributes. These will be default settings for local variables. + +New {nocache} block function: +{nocache}...{/nocache} will declare a section of the template to be non-cached +when template caching is enabled. + +New nocache attribute: +You can declare variable/function output as non-cached with the nocache attribute. +Examples: + +{$foo nocache=true} +{$foo nocache} /* same */ + +{foo bar="baz" nocache=true} +{foo bar="baz" nocache} /* same */ + +{time() nocache=true} +{time() nocache} /* same */ + +Or you can also assign the variable in your script as nocache: +$smarty->assign('foo',$something,true); // third param is nocache setting +{$foo} /* non-cached */ + +$smarty.current_dir returns the directory name of the current template. + +You can use strings directly as templates with the "string" resource type. +Examples: +$smarty->display('string:This is my template, {$foo}!'); // php +{include file="string:This is my template, {$foo}!"} // template + + + +VARIABLE SCOPE / VARIABLE STORAGE +================================= + +In Smarty 2, all assigned variables were stored within the Smarty object. +Therefore, all variables assigned in PHP were accessible by all subsequent +fetch and display template calls. + +In Smarty 3, we have the choice to assign variables to the main Smarty object, +to user-created data objects, and to user-created template objects. +These objects can be chained. The object at the end of a chain can access all +variables belonging to that template and all variables within the parent objects. +The Smarty object can only be the root of a chain, but a chain can be isolated +from the Smarty object. + +All known Smarty assignment interfaces will work on the data and template objects. + +Besides the above mentioned objects, there is also a special storage area for +global variables. + +A Smarty data object can be created as follows: +$data = $smarty->createData(); // create root data object +$data->assign('foo','bar'); // assign variables as usual +$data->config_load('my.conf'); // load config file + +$data= $smarty->createData($smarty); // create data object having a parent link to +the Smarty object + +$data2= $smarty->createData($data); // create data object having a parent link to +the $data data object + +A template object can be created by using the createTemplate method. It has the +same parameter assignments as the fetch() or display() method. +Function definition: +function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null) + +The first parameter can be a template name, a smarty object or a data object. + +Examples: +$tpl = $smarty->createTemplate('mytpl.tpl'); // create template object not linked to any parent +$tpl->assign('foo','bar'); // directly assign variables +$tpl->config_load('my.conf'); // load config file + +$tpl = $smarty->createTemplate('mytpl.tpl',$smarty); // create template having a parent link to the Smarty object +$tpl = $smarty->createTemplate('mytpl.tpl',$data); // create template having a parent link to the $data object + +The standard fetch() and display() methods will implicitly create a template object. +If the $parent parameter is not specified in these method calls, the template object +is will link back to the Smarty object as it's parent. + +If a template is called by an {include...} tag from another template, the +subtemplate links back to the calling template as it's parent. + +All variables assigned locally or from a parent template are accessible. If the +template creates or modifies a variable by using the {assign var=foo...} or +{$foo=...} tags, these new values are only known locally (local scope). When the +template exits, none of the new variables or modifications can be seen in the +parent template(s). This is same behavior as in Smarty 2. + +With Smarty 3, we can assign variables with a scope attribute which allows the +availablility of these new variables or modifications globally (ie in the parent +templates.) + +Possible scopes are local, parent, root and global. +Examples: +{assign var=foo value='bar'} // no scope is specified, the default 'local' +{$foo='bar'} // same, local scope +{assign var=foo value='bar' scope='local'} // same, local scope + +{assign var=foo value='bar' scope='parent'} // Values will be available to the parent object +{$foo='bar' scope='parent'} // (normally the calling template) + +{assign var=foo value='bar' scope='root'} // Values will be exported up to the root object, so they can +{$foo='bar' scope='root'} // be seen from all templates using the same root. + +{assign var=foo value='bar' scope='global'} // Values will be exported to global variable storage, +{$foo='bar' scope='global'} // they are available to any and all templates. + + +The scope attribute can also be attached to the {include...} tag. In this case, +the specified scope will be the default scope for all assignments within the +included template. + + +PLUGINS +======= + +Smarty3 are following the same coding rules as in Smarty2. +The only difference is that the template object is passed as additional third parameter. + +smarty_plugintype_name (array $params, object $smarty, object $template) + +The Smarty 2 plugins are still compatible as long as they do not make use of specific Smarty2 internals. + + +TEMPLATE INHERITANCE: +===================== + +With template inheritance you can define blocks, which are areas that can be +overriden by child templates, so your templates could look like this: + +parent.tpl: + + + {block name='title'}My site name{/block} + + +

{block name='page-title'}Default page title{/block}

+
+ {block name='content'} + Default content + {/block} +
+ + + +child.tpl: +{extends file='parent.tpl'} +{block name='title'} +Child title +{/block} + +grandchild.tpl: +{extends file='child.tpl'} +{block name='title'}Home - {$smarty.block.parent}{/block} +{block name='page-title'}My home{/block} +{block name='content'} + {foreach $images as $img} + {$img.description} + {/foreach} +{/block} + +We redefined all the blocks here, however in the title block we used {$smarty.block.parent}, +which tells Smarty to insert the default content from the parent template in its place. +The content block was overriden to display the image files, and page-title has also be +overriden to display a completely different title. + +If we render grandchild.tpl we will get this: + + + Home - Child title + + +

My home

+
+ image + image + image +
+ + + +NOTE: In the child templates everything outside the {extends} or {block} tag sections +is ignored. + +The inheritance tree can be as big as you want (meaning you can extend a file that +extends another one that extends another one and so on..), but be aware that all files +have to be checked for modifications at runtime so the more inheritance the more overhead you add. + +Instead of defining the parent/child relationships with the {extends} tag in the child template you +can use the resource as follow: + +$smarty->display('extends:parent.tpl|child.tpl|grandchild.tpl'); + +Child {block} tags may optionally have a append or prepend attribute. In this case the parent block content +is appended or prepended to the child block content. + +{block name='title' append} My title {/block} + + +PHP STREAMS: +============ + +(see online documentation) + +VARIBLE FILTERS: +================ + +(see online documentation) + + +STATIC CLASS ACCESS AND NAMESPACE SUPPORT +========================================= + +You can register a class with optional namespace for the use in the template like: + +$smarty->register->templateClass('foo','name\name2\myclass'); + +In the template you can use it like this: +{foo::method()} etc. + + +======================= + +Please look through it and send any questions/suggestions/etc to the forums. + +http://www.phpinsider.com/smarty-forum/viewtopic.php?t=14168 + +Monte and Uwe diff --git a/resources/templates/engine/smarty/Smarty.class.php b/resources/templates/engine/smarty/Smarty.class.php new file mode 100644 index 0000000000..732b2df316 --- /dev/null +++ b/resources/templates/engine/smarty/Smarty.class.php @@ -0,0 +1,1575 @@ + + * @author Uwe Tews + * @author Rodney Rehm + * @package Smarty + * @version 3.1.15 + */ + +/** + * define shorthand directory separator constant + */ +if (!defined('DS')) { + define('DS', DIRECTORY_SEPARATOR); +} + +/** + * set SMARTY_DIR to absolute path to Smarty library files. + * Sets SMARTY_DIR only if user application has not already defined it. + */ +if (!defined('SMARTY_DIR')) { + define('SMARTY_DIR', dirname(__FILE__) . DS); +} + +/** + * set SMARTY_SYSPLUGINS_DIR to absolute path to Smarty internal plugins. + * Sets SMARTY_SYSPLUGINS_DIR only if user application has not already defined it. + */ +if (!defined('SMARTY_SYSPLUGINS_DIR')) { + define('SMARTY_SYSPLUGINS_DIR', SMARTY_DIR . 'sysplugins' . DS); +} +if (!defined('SMARTY_PLUGINS_DIR')) { + define('SMARTY_PLUGINS_DIR', SMARTY_DIR . 'plugins' . DS); +} +if (!defined('SMARTY_MBSTRING')) { + define('SMARTY_MBSTRING', function_exists('mb_split')); +} +if (!defined('SMARTY_RESOURCE_CHAR_SET')) { + // UTF-8 can only be done properly when mbstring is available! + /** + * @deprecated in favor of Smarty::$_CHARSET + */ + define('SMARTY_RESOURCE_CHAR_SET', SMARTY_MBSTRING ? 'UTF-8' : 'ISO-8859-1'); +} +if (!defined('SMARTY_RESOURCE_DATE_FORMAT')) { + /** + * @deprecated in favor of Smarty::$_DATE_FORMAT + */ + define('SMARTY_RESOURCE_DATE_FORMAT', '%b %e, %Y'); +} + +/** + * register the class autoloader + */ +if (!defined('SMARTY_SPL_AUTOLOAD')) { + define('SMARTY_SPL_AUTOLOAD', 0); +} + +if (SMARTY_SPL_AUTOLOAD && set_include_path(get_include_path() . PATH_SEPARATOR . SMARTY_SYSPLUGINS_DIR) !== false) { + $registeredAutoLoadFunctions = spl_autoload_functions(); + if (!isset($registeredAutoLoadFunctions['spl_autoload'])) { + spl_autoload_register(); + } +} else { + spl_autoload_register('smartyAutoload'); +} + +/** + * Load always needed external class files + */ +include_once SMARTY_SYSPLUGINS_DIR.'smarty_internal_data.php'; +include_once SMARTY_SYSPLUGINS_DIR.'smarty_internal_templatebase.php'; +include_once SMARTY_SYSPLUGINS_DIR.'smarty_internal_template.php'; +include_once SMARTY_SYSPLUGINS_DIR.'smarty_resource.php'; +include_once SMARTY_SYSPLUGINS_DIR.'smarty_internal_resource_file.php'; +include_once SMARTY_SYSPLUGINS_DIR.'smarty_cacheresource.php'; +include_once SMARTY_SYSPLUGINS_DIR.'smarty_internal_cacheresource_file.php'; + +/** + * This is the main Smarty class + * @package Smarty + */ +class Smarty extends Smarty_Internal_TemplateBase +{ + /**#@+ + * constant definitions + */ + + /** + * smarty version + */ + const SMARTY_VERSION = 'Smarty-3.1.15'; + + /** + * define variable scopes + */ + const SCOPE_LOCAL = 0; + const SCOPE_PARENT = 1; + const SCOPE_ROOT = 2; + const SCOPE_GLOBAL = 3; + /** + * define caching modes + */ + const CACHING_OFF = 0; + const CACHING_LIFETIME_CURRENT = 1; + const CACHING_LIFETIME_SAVED = 2; + /** + * define constant for clearing cache files be saved expiration datees + */ + const CLEAR_EXPIRED = -1; + + /** + * define compile check modes + */ + const COMPILECHECK_OFF = 0; + const COMPILECHECK_ON = 1; + const COMPILECHECK_CACHEMISS = 2; + /** + * modes for handling of "" tags in templates. + */ + const PHP_PASSTHRU = 0; //-> print tags as plain text + const PHP_QUOTE = 1; //-> escape tags as entities + const PHP_REMOVE = 2; //-> escape tags as entities + const PHP_ALLOW = 3; //-> escape tags as entities + /** + * filter types + */ + const FILTER_POST = 'post'; + const FILTER_PRE = 'pre'; + const FILTER_OUTPUT = 'output'; + const FILTER_VARIABLE = 'variable'; + /** + * plugin types + */ + const PLUGIN_FUNCTION = 'function'; + const PLUGIN_BLOCK = 'block'; + const PLUGIN_COMPILER = 'compiler'; + const PLUGIN_MODIFIER = 'modifier'; + const PLUGIN_MODIFIERCOMPILER = 'modifiercompiler'; + + /**#@-*/ + + /** + * assigned global tpl vars + */ + public static $global_tpl_vars = array(); + + /** + * error handler returned by set_error_hanlder() in Smarty::muteExpectedErrors() + */ + public static $_previous_error_handler = null; + /** + * contains directories outside of SMARTY_DIR that are to be muted by muteExpectedErrors() + */ + public static $_muted_directories = array(); + /** + * Flag denoting if Multibyte String functions are available + */ + public static $_MBSTRING = SMARTY_MBSTRING; + /** + * The character set to adhere to (e.g. "UTF-8") + */ + public static $_CHARSET = SMARTY_RESOURCE_CHAR_SET; + /** + * The date format to be used internally + * (accepts date() and strftime()) + */ + public static $_DATE_FORMAT = SMARTY_RESOURCE_DATE_FORMAT; + /** + * Flag denoting if PCRE should run in UTF-8 mode + */ + public static $_UTF8_MODIFIER = 'u'; + + /** + * Flag denoting if operating system is windows + */ + public static $_IS_WINDOWS = false; + + /**#@+ + * variables + */ + + /** + * auto literal on delimiters with whitspace + * @var boolean + */ + public $auto_literal = true; + /** + * display error on not assigned variables + * @var boolean + */ + public $error_unassigned = false; + /** + * look up relative filepaths in include_path + * @var boolean + */ + public $use_include_path = false; + /** + * template directory + * @var array + */ + private $template_dir = array(); + /** + * joined template directory string used in cache keys + * @var string + */ + public $joined_template_dir = null; + /** + * joined config directory string used in cache keys + * @var string + */ + public $joined_config_dir = null; + /** + * default template handler + * @var callable + */ + public $default_template_handler_func = null; + /** + * default config handler + * @var callable + */ + public $default_config_handler_func = null; + /** + * default plugin handler + * @var callable + */ + public $default_plugin_handler_func = null; + /** + * compile directory + * @var string + */ + private $compile_dir = null; + /** + * plugins directory + * @var array + */ + private $plugins_dir = array(); + /** + * cache directory + * @var string + */ + private $cache_dir = null; + /** + * config directory + * @var array + */ + private $config_dir = array(); + /** + * force template compiling? + * @var boolean + */ + public $force_compile = false; + /** + * check template for modifications? + * @var boolean + */ + public $compile_check = true; + /** + * use sub dirs for compiled/cached files? + * @var boolean + */ + public $use_sub_dirs = false; + /** + * allow ambiguous resources (that are made unique by the resource handler) + * @var boolean + */ + public $allow_ambiguous_resources = false; + /** + * caching enabled + * @var boolean + */ + public $caching = false; + /** + * merge compiled includes + * @var boolean + */ + public $merge_compiled_includes = false; + /** + * cache lifetime in seconds + * @var integer + */ + public $cache_lifetime = 3600; + /** + * force cache file creation + * @var boolean + */ + public $force_cache = false; + /** + * Set this if you want different sets of cache files for the same + * templates. + * + * @var string + */ + public $cache_id = null; + /** + * Set this if you want different sets of compiled files for the same + * templates. + * + * @var string + */ + public $compile_id = null; + /** + * template left-delimiter + * @var string + */ + public $left_delimiter = "{"; + /** + * template right-delimiter + * @var string + */ + public $right_delimiter = "}"; + /**#@+ + * security + */ + /** + * class name + * + * This should be instance of Smarty_Security. + * + * @var string + * @see Smarty_Security + */ + public $security_class = 'Smarty_Security'; + /** + * implementation of security class + * + * @var Smarty_Security + */ + public $security_policy = null; + /** + * controls handling of PHP-blocks + * + * @var integer + */ + public $php_handling = self::PHP_PASSTHRU; + /** + * controls if the php template file resource is allowed + * + * @var bool + */ + public $allow_php_templates = false; + /** + * Should compiled-templates be prevented from being called directly? + * + * {@internal + * Currently used by Smarty_Internal_Template only. + * }} + * + * @var boolean + */ + public $direct_access_security = true; + /**#@-*/ + /** + * debug mode + * + * Setting this to true enables the debug-console. + * + * @var boolean + */ + public $debugging = false; + /** + * This determines if debugging is enable-able from the browser. + * + * @var string + */ + public $debugging_ctrl = 'NONE'; + /** + * Name of debugging URL-param. + * + * Only used when $debugging_ctrl is set to 'URL'. + * The name of the URL-parameter that activates debugging. + * + * @var type + */ + public $smarty_debug_id = 'SMARTY_DEBUG'; + /** + * Path of debug template. + * @var string + */ + public $debug_tpl = null; + /** + * When set, smarty uses this value as error_reporting-level. + * @var int + */ + public $error_reporting = null; + /** + * Internal flag for getTags() + * @var boolean + */ + public $get_used_tags = false; + + /**#@+ + * config var settings + */ + + /** + * Controls whether variables with the same name overwrite each other. + * @var boolean + */ + public $config_overwrite = true; + /** + * Controls whether config values of on/true/yes and off/false/no get converted to boolean. + * @var boolean + */ + public $config_booleanize = true; + /** + * Controls whether hidden config sections/vars are read from the file. + * @var boolean + */ + public $config_read_hidden = false; + + /**#@-*/ + + /**#@+ + * resource locking + */ + + /** + * locking concurrent compiles + * @var boolean + */ + public $compile_locking = true; + /** + * Controls whether cache resources should emply locking mechanism + * @var boolean + */ + public $cache_locking = false; + /** + * seconds to wait for acquiring a lock before ignoring the write lock + * @var float + */ + public $locking_timeout = 10; + + /**#@-*/ + + /** + * global template functions + * @var array + */ + public $template_functions = array(); + /** + * resource type used if none given + * + * Must be an valid key of $registered_resources. + * @var string + */ + public $default_resource_type = 'file'; + /** + * caching type + * + * Must be an element of $cache_resource_types. + * + * @var string + */ + public $caching_type = 'file'; + /** + * internal config properties + * @var array + */ + public $properties = array(); + /** + * config type + * @var string + */ + public $default_config_type = 'file'; + /** + * cached template objects + * @var array + */ + public $template_objects = array(); + /** + * check If-Modified-Since headers + * @var boolean + */ + public $cache_modified_check = false; + /** + * registered plugins + * @var array + */ + public $registered_plugins = array(); + /** + * plugin search order + * @var array + */ + public $plugin_search_order = array('function', 'block', 'compiler', 'class'); + /** + * registered objects + * @var array + */ + public $registered_objects = array(); + /** + * registered classes + * @var array + */ + public $registered_classes = array(); + /** + * registered filters + * @var array + */ + public $registered_filters = array(); + /** + * registered resources + * @var array + */ + public $registered_resources = array(); + /** + * resource handler cache + * @var array + */ + public $_resource_handlers = array(); + /** + * registered cache resources + * @var array + */ + public $registered_cache_resources = array(); + /** + * cache resource handler cache + * @var array + */ + public $_cacheresource_handlers = array(); + /** + * autoload filter + * @var array + */ + public $autoload_filters = array(); + /** + * default modifier + * @var array + */ + public $default_modifiers = array(); + /** + * autoescape variable output + * @var boolean + */ + public $escape_html = false; + /** + * global internal smarty vars + * @var array + */ + public static $_smarty_vars = array(); + /** + * start time for execution time calculation + * @var int + */ + public $start_time = 0; + /** + * default file permissions + * @var int + */ + public $_file_perms = 0644; + /** + * default dir permissions + * @var int + */ + public $_dir_perms = 0771; + /** + * block tag hierarchy + * @var array + */ + public $_tag_stack = array(); + /** + * self pointer to Smarty object + * @var Smarty + */ + public $smarty; + /** + * required by the compiler for BC + * @var string + */ + public $_current_file = null; + /** + * internal flag to enable parser debugging + * @var bool + */ + public $_parserdebug = false; + /** + * Saved parameter of merged templates during compilation + * + * @var array + */ + public $merged_templates_func = array(); + /**#@-*/ + + /** + * Initialize new Smarty object + * + */ + public function __construct() + { + // selfpointer needed by some other class methods + $this->smarty = $this; + if (is_callable('mb_internal_encoding')) { + mb_internal_encoding(Smarty::$_CHARSET); + } + $this->start_time = microtime(true); + // set default dirs + $this->setTemplateDir('.' . DS . 'templates' . DS) + ->setCompileDir('.' . DS . 'templates_c' . DS) + ->setPluginsDir(SMARTY_PLUGINS_DIR) + ->setCacheDir('.' . DS . 'cache' . DS) + ->setConfigDir('.' . DS . 'configs' . DS); + + $this->debug_tpl = 'file:' . dirname(__FILE__) . '/debug.tpl'; + if (isset($_SERVER['SCRIPT_NAME'])) { + $this->assignGlobal('SCRIPT_NAME', $_SERVER['SCRIPT_NAME']); + } + } + + /** + * Class destructor + */ + public function __destruct() + { + // intentionally left blank + } + + /** + * <> set selfpointer on cloned object + */ + public function __clone() + { + $this->smarty = $this; + } + + /** + * <> Generic getter. + * + * Calls the appropriate getter function. + * Issues an E_USER_NOTICE if no valid getter is found. + * + * @param string $name property name + * @return mixed + */ + public function __get($name) + { + $allowed = array( + 'template_dir' => 'getTemplateDir', + 'config_dir' => 'getConfigDir', + 'plugins_dir' => 'getPluginsDir', + 'compile_dir' => 'getCompileDir', + 'cache_dir' => 'getCacheDir', + ); + + if (isset($allowed[$name])) { + return $this->{$allowed[$name]}(); + } else { + trigger_error('Undefined property: '. get_class($this) .'::$'. $name, E_USER_NOTICE); + } + } + + /** + * <> Generic setter. + * + * Calls the appropriate setter function. + * Issues an E_USER_NOTICE if no valid setter is found. + * + * @param string $name property name + * @param mixed $value parameter passed to setter + */ + public function __set($name, $value) + { + $allowed = array( + 'template_dir' => 'setTemplateDir', + 'config_dir' => 'setConfigDir', + 'plugins_dir' => 'setPluginsDir', + 'compile_dir' => 'setCompileDir', + 'cache_dir' => 'setCacheDir', + ); + + if (isset($allowed[$name])) { + $this->{$allowed[$name]}($value); + } else { + trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE); + } + } + + /** + * Check if a template resource exists + * + * @param string $resource_name template name + * @return boolean status + */ + public function templateExists($resource_name) + { + // create template object + $save = $this->template_objects; + $tpl = new $this->template_class($resource_name, $this); + // check if it does exists + $result = $tpl->source->exists; + $this->template_objects = $save; + + return $result; + } + + /** + * Returns a single or all global variables + * + * @param object $smarty + * @param string $varname variable name or null + * @return string variable value or or array of variables + */ + public function getGlobal($varname = null) + { + if (isset($varname)) { + if (isset(self::$global_tpl_vars[$varname])) { + return self::$global_tpl_vars[$varname]->value; + } else { + return ''; + } + } else { + $_result = array(); + foreach (self::$global_tpl_vars AS $key => $var) { + $_result[$key] = $var->value; + } + + return $_result; + } + } + + /** + * Empty cache folder + * + * @param integer $exp_time expiration time + * @param string $type resource type + * @return integer number of cache files deleted + */ + public function clearAllCache($exp_time = null, $type = null) + { + // load cache resource and call clearAll + $_cache_resource = Smarty_CacheResource::load($this, $type); + Smarty_CacheResource::invalidLoadedCache($this); + + return $_cache_resource->clearAll($this, $exp_time); + } + + /** + * Empty cache for a specific template + * + * @param string $template_name template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * @param integer $exp_time expiration time + * @param string $type resource type + * @return integer number of cache files deleted + */ + public function clearCache($template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null) + { + // load cache resource and call clear + $_cache_resource = Smarty_CacheResource::load($this, $type); + Smarty_CacheResource::invalidLoadedCache($this); + + return $_cache_resource->clear($this, $template_name, $cache_id, $compile_id, $exp_time); + } + + /** + * Loads security class and enables security + * + * @param string|Smarty_Security $security_class if a string is used, it must be class-name + * @return Smarty current Smarty instance for chaining + * @throws SmartyException when an invalid class name is provided + */ + public function enableSecurity($security_class = null) + { + if ($security_class instanceof Smarty_Security) { + $this->security_policy = $security_class; + + return $this; + } elseif (is_object($security_class)) { + throw new SmartyException("Class '" . get_class($security_class) . "' must extend Smarty_Security."); + } + if ($security_class == null) { + $security_class = $this->security_class; + } + if (!class_exists($security_class)) { + throw new SmartyException("Security class '$security_class' is not defined"); + } elseif ($security_class !== 'Smarty_Security' && !is_subclass_of($security_class, 'Smarty_Security')) { + throw new SmartyException("Class '$security_class' must extend Smarty_Security."); + } else { + $this->security_policy = new $security_class($this); + } + + return $this; + } + + /** + * Disable security + * @return Smarty current Smarty instance for chaining + */ + public function disableSecurity() + { + $this->security_policy = null; + + return $this; + } + + /** + * Set template directory + * + * @param string|array $template_dir directory(s) of template sources + * @return Smarty current Smarty instance for chaining + */ + public function setTemplateDir($template_dir) + { + $this->template_dir = array(); + foreach ((array) $template_dir as $k => $v) { + $this->template_dir[$k] = rtrim($v, '/\\') . DS; + } + + $this->joined_template_dir = join(DIRECTORY_SEPARATOR, $this->template_dir); + + return $this; + } + + /** + * Add template directory(s) + * + * @param string|array $template_dir directory(s) of template sources + * @param string $key of the array element to assign the template dir to + * @return Smarty current Smarty instance for chaining + * @throws SmartyException when the given template directory is not valid + */ + public function addTemplateDir($template_dir, $key=null) + { + // make sure we're dealing with an array + $this->template_dir = (array) $this->template_dir; + + if (is_array($template_dir)) { + foreach ($template_dir as $k => $v) { + if (is_int($k)) { + // indexes are not merged but appended + $this->template_dir[] = rtrim($v, '/\\') . DS; + } else { + // string indexes are overridden + $this->template_dir[$k] = rtrim($v, '/\\') . DS; + } + } + } elseif ($key !== null) { + // override directory at specified index + $this->template_dir[$key] = rtrim($template_dir, '/\\') . DS; + } else { + // append new directory + $this->template_dir[] = rtrim($template_dir, '/\\') . DS; + } + $this->joined_template_dir = join(DIRECTORY_SEPARATOR, $this->template_dir); + + return $this; + } + + /** + * Get template directories + * + * @param mixed index of directory to get, null to get all + * @return array|string list of template directories, or directory of $index + */ + public function getTemplateDir($index=null) + { + if ($index !== null) { + return isset($this->template_dir[$index]) ? $this->template_dir[$index] : null; + } + + return (array) $this->template_dir; + } + + /** + * Set config directory + * + * @param string|array $template_dir directory(s) of configuration sources + * @return Smarty current Smarty instance for chaining + */ + public function setConfigDir($config_dir) + { + $this->config_dir = array(); + foreach ((array) $config_dir as $k => $v) { + $this->config_dir[$k] = rtrim($v, '/\\') . DS; + } + + $this->joined_config_dir = join(DIRECTORY_SEPARATOR, $this->config_dir); + + return $this; + } + + /** + * Add config directory(s) + * + * @param string|array $config_dir directory(s) of config sources + * @param string key of the array element to assign the config dir to + * @return Smarty current Smarty instance for chaining + */ + public function addConfigDir($config_dir, $key=null) + { + // make sure we're dealing with an array + $this->config_dir = (array) $this->config_dir; + + if (is_array($config_dir)) { + foreach ($config_dir as $k => $v) { + if (is_int($k)) { + // indexes are not merged but appended + $this->config_dir[] = rtrim($v, '/\\') . DS; + } else { + // string indexes are overridden + $this->config_dir[$k] = rtrim($v, '/\\') . DS; + } + } + } elseif ($key !== null) { + // override directory at specified index + $this->config_dir[$key] = rtrim($config_dir, '/\\') . DS; + } else { + // append new directory + $this->config_dir[] = rtrim($config_dir, '/\\') . DS; + } + + $this->joined_config_dir = join(DIRECTORY_SEPARATOR, $this->config_dir); + + return $this; + } + + /** + * Get config directory + * + * @param mixed index of directory to get, null to get all + * @return array|string configuration directory + */ + public function getConfigDir($index=null) + { + if ($index !== null) { + return isset($this->config_dir[$index]) ? $this->config_dir[$index] : null; + } + + return (array) $this->config_dir; + } + + /** + * Set plugins directory + * + * @param string|array $plugins_dir directory(s) of plugins + * @return Smarty current Smarty instance for chaining + */ + public function setPluginsDir($plugins_dir) + { + $this->plugins_dir = array(); + foreach ((array) $plugins_dir as $k => $v) { + $this->plugins_dir[$k] = rtrim($v, '/\\') . DS; + } + + return $this; + } + + /** + * Adds directory of plugin files + * + * @param object $smarty + * @param string $ |array $ plugins folder + * @return Smarty current Smarty instance for chaining + */ + public function addPluginsDir($plugins_dir) + { + // make sure we're dealing with an array + $this->plugins_dir = (array) $this->plugins_dir; + + if (is_array($plugins_dir)) { + foreach ($plugins_dir as $k => $v) { + if (is_int($k)) { + // indexes are not merged but appended + $this->plugins_dir[] = rtrim($v, '/\\') . DS; + } else { + // string indexes are overridden + $this->plugins_dir[$k] = rtrim($v, '/\\') . DS; + } + } + } else { + // append new directory + $this->plugins_dir[] = rtrim($plugins_dir, '/\\') . DS; + } + + $this->plugins_dir = array_unique($this->plugins_dir); + + return $this; + } + + /** + * Get plugin directories + * + * @return array list of plugin directories + */ + public function getPluginsDir() + { + return (array) $this->plugins_dir; + } + + /** + * Set compile directory + * + * @param string $compile_dir directory to store compiled templates in + * @return Smarty current Smarty instance for chaining + */ + public function setCompileDir($compile_dir) + { + $this->compile_dir = rtrim($compile_dir, '/\\') . DS; + if (!isset(Smarty::$_muted_directories[$this->compile_dir])) { + Smarty::$_muted_directories[$this->compile_dir] = null; + } + + return $this; + } + + /** + * Get compiled directory + * + * @return string path to compiled templates + */ + public function getCompileDir() + { + return $this->compile_dir; + } + + /** + * Set cache directory + * + * @param string $cache_dir directory to store cached templates in + * @return Smarty current Smarty instance for chaining + */ + public function setCacheDir($cache_dir) + { + $this->cache_dir = rtrim($cache_dir, '/\\') . DS; + if (!isset(Smarty::$_muted_directories[$this->cache_dir])) { + Smarty::$_muted_directories[$this->cache_dir] = null; + } + + return $this; + } + + /** + * Get cache directory + * + * @return string path of cache directory + */ + public function getCacheDir() + { + return $this->cache_dir; + } + + /** + * Set default modifiers + * + * @param array|string $modifiers modifier or list of modifiers to set + * @return Smarty current Smarty instance for chaining + */ + public function setDefaultModifiers($modifiers) + { + $this->default_modifiers = (array) $modifiers; + + return $this; + } + + /** + * Add default modifiers + * + * @param array|string $modifiers modifier or list of modifiers to add + * @return Smarty current Smarty instance for chaining + */ + public function addDefaultModifiers($modifiers) + { + if (is_array($modifiers)) { + $this->default_modifiers = array_merge($this->default_modifiers, $modifiers); + } else { + $this->default_modifiers[] = $modifiers; + } + + return $this; + } + + /** + * Get default modifiers + * + * @return array list of default modifiers + */ + public function getDefaultModifiers() + { + return $this->default_modifiers; + } + + + /** + * Set autoload filters + * + * @param array $filters filters to load automatically + * @param string $type "pre", "output", … specify the filter type to set. Defaults to none treating $filters' keys as the appropriate types + * @return Smarty current Smarty instance for chaining + */ + public function setAutoloadFilters($filters, $type=null) + { + if ($type !== null) { + $this->autoload_filters[$type] = (array) $filters; + } else { + $this->autoload_filters = (array) $filters; + } + + return $this; + } + + /** + * Add autoload filters + * + * @param array $filters filters to load automatically + * @param string $type "pre", "output", … specify the filter type to set. Defaults to none treating $filters' keys as the appropriate types + * @return Smarty current Smarty instance for chaining + */ + public function addAutoloadFilters($filters, $type=null) + { + if ($type !== null) { + if (!empty($this->autoload_filters[$type])) { + $this->autoload_filters[$type] = array_merge($this->autoload_filters[$type], (array) $filters); + } else { + $this->autoload_filters[$type] = (array) $filters; + } + } else { + foreach ((array) $filters as $key => $value) { + if (!empty($this->autoload_filters[$key])) { + $this->autoload_filters[$key] = array_merge($this->autoload_filters[$key], (array) $value); + } else { + $this->autoload_filters[$key] = (array) $value; + } + } + } + + return $this; + } + + /** + * Get autoload filters + * + * @param string $type type of filter to get autoloads for. Defaults to all autoload filters + * @return array array( 'type1' => array( 'filter1', 'filter2', … ) ) or array( 'filter1', 'filter2', …) if $type was specified + */ + public function getAutoloadFilters($type=null) + { + if ($type !== null) { + return isset($this->autoload_filters[$type]) ? $this->autoload_filters[$type] : array(); + } + + return $this->autoload_filters; + } + + /** + * return name of debugging template + * + * @return string + */ + public function getDebugTemplate() + { + return $this->debug_tpl; + } + + /** + * set the debug template + * + * @param string $tpl_name + * @return Smarty current Smarty instance for chaining + * @throws SmartyException if file is not readable + */ + public function setDebugTemplate($tpl_name) + { + if (!is_readable($tpl_name)) { + throw new SmartyException("Unknown file '{$tpl_name}'"); + } + $this->debug_tpl = $tpl_name; + + return $this; + } + + /** + * creates a template object + * + * @param string $template the resource handle of the template file + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @param object $parent next higher level of Smarty variables + * @param boolean $do_clone flag is Smarty object shall be cloned + * @return object template object + */ + public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null, $do_clone = true) + { + if (!empty($cache_id) && (is_object($cache_id) || is_array($cache_id))) { + $parent = $cache_id; + $cache_id = null; + } + if (!empty($parent) && is_array($parent)) { + $data = $parent; + $parent = null; + } else { + $data = null; + } + // default to cache_id and compile_id of Smarty object + $cache_id = $cache_id === null ? $this->cache_id : $cache_id; + $compile_id = $compile_id === null ? $this->compile_id : $compile_id; + // already in template cache? + if ($this->allow_ambiguous_resources) { + $_templateId = Smarty_Resource::getUniqueTemplateName($this, $template) . $cache_id . $compile_id; + } else { + $_templateId = $this->joined_template_dir . '#' . $template . $cache_id . $compile_id; + } + if (isset($_templateId[150])) { + $_templateId = sha1($_templateId); + } + if ($do_clone) { + if (isset($this->template_objects[$_templateId])) { + // return cached template object + $tpl = clone $this->template_objects[$_templateId]; + $tpl->smarty = clone $tpl->smarty; + $tpl->parent = $parent; + $tpl->tpl_vars = array(); + $tpl->config_vars = array(); + } else { + $tpl = new $this->template_class($template, clone $this, $parent, $cache_id, $compile_id); + } + } else { + if (isset($this->template_objects[$_templateId])) { + // return cached template object + $tpl = $this->template_objects[$_templateId]; + $tpl->parent = $parent; + $tpl->tpl_vars = array(); + $tpl->config_vars = array(); + } else { + $tpl = new $this->template_class($template, $this, $parent, $cache_id, $compile_id); + } + } + // fill data if present + if (!empty($data) && is_array($data)) { + // set up variable values + foreach ($data as $_key => $_val) { + $tpl->tpl_vars[$_key] = new Smarty_variable($_val); + } + } + + return $tpl; + } + + + /** + * Takes unknown classes and loads plugin files for them + * class name format: Smarty_PluginType_PluginName + * plugin filename format: plugintype.pluginname.php + * + * @param string $plugin_name class plugin name to load + * @param bool $check check if already loaded + * @return string |boolean filepath of loaded file or false + */ + public function loadPlugin($plugin_name, $check = true) + { + // if function or class exists, exit silently (already loaded) + if ($check && (is_callable($plugin_name) || class_exists($plugin_name, false))) { + return true; + } + // Plugin name is expected to be: Smarty_[Type]_[Name] + $_name_parts = explode('_', $plugin_name, 3); + // class name must have three parts to be valid plugin + // count($_name_parts) < 3 === !isset($_name_parts[2]) + if (!isset($_name_parts[2]) || strtolower($_name_parts[0]) !== 'smarty') { + throw new SmartyException("plugin {$plugin_name} is not a valid name format"); + + return false; + } + // if type is "internal", get plugin from sysplugins + if (strtolower($_name_parts[1]) == 'internal') { + $file = SMARTY_SYSPLUGINS_DIR . strtolower($plugin_name) . '.php'; + if (file_exists($file)) { + require_once($file); + + return $file; + } else { + return false; + } + } + // plugin filename is expected to be: [type].[name].php + $_plugin_filename = "{$_name_parts[1]}.{$_name_parts[2]}.php"; + + $_stream_resolve_include_path = function_exists('stream_resolve_include_path'); + + // loop through plugin dirs and find the plugin + foreach ($this->getPluginsDir() as $_plugin_dir) { + $names = array( + $_plugin_dir . $_plugin_filename, + $_plugin_dir . strtolower($_plugin_filename), + ); + foreach ($names as $file) { + if (file_exists($file)) { + require_once($file); + + return $file; + } + if ($this->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_plugin_dir)) { + // try PHP include_path + if ($_stream_resolve_include_path) { + $file = stream_resolve_include_path($file); + } else { + $file = Smarty_Internal_Get_Include_Path::getIncludePath($file); + } + + if ($file !== false) { + require_once($file); + + return $file; + } + } + } + } + // no plugin loaded + return false; + } + + /** + * Compile all template files + * + * @param string $extension file extension + * @param bool $force_compile force all to recompile + * @param int $time_limit + * @param int $max_errors + * @return integer number of template files recompiled + */ + public function compileAllTemplates($extension = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null) + { + return Smarty_Internal_Utility::compileAllTemplates($extension, $force_compile, $time_limit, $max_errors, $this); + } + + /** + * Compile all config files + * + * @param string $extension file extension + * @param bool $force_compile force all to recompile + * @param int $time_limit + * @param int $max_errors + * @return integer number of template files recompiled + */ + public function compileAllConfig($extension = '.conf', $force_compile = false, $time_limit = 0, $max_errors = null) + { + return Smarty_Internal_Utility::compileAllConfig($extension, $force_compile, $time_limit, $max_errors, $this); + } + + /** + * Delete compiled template file + * + * @param string $resource_name template name + * @param string $compile_id compile id + * @param integer $exp_time expiration time + * @return integer number of template files deleted + */ + public function clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null) + { + return Smarty_Internal_Utility::clearCompiledTemplate($resource_name, $compile_id, $exp_time, $this); + } + + + /** + * Return array of tag/attributes of all tags used by an template + * + * @param object $templae template object + * @return array of tag/attributes + */ + public function getTags(Smarty_Internal_Template $template) + { + return Smarty_Internal_Utility::getTags($template); + } + + /** + * Run installation test + * + * @param array $errors Array to write errors into, rather than outputting them + * @return boolean true if setup is fine, false if something is wrong + */ + public function testInstall(&$errors=null) + { + return Smarty_Internal_Utility::testInstall($this, $errors); + } + + /** + * Error Handler to mute expected messages + * + * @link http://php.net/set_error_handler + * @param integer $errno Error level + * @return boolean + */ + public static function mutingErrorHandler($errno, $errstr, $errfile, $errline, $errcontext) + { + $_is_muted_directory = false; + + // add the SMARTY_DIR to the list of muted directories + if (!isset(Smarty::$_muted_directories[SMARTY_DIR])) { + $smarty_dir = realpath(SMARTY_DIR); + if ($smarty_dir !== false) { + Smarty::$_muted_directories[SMARTY_DIR] = array( + 'file' => $smarty_dir, + 'length' => strlen($smarty_dir), + ); + } + } + + // walk the muted directories and test against $errfile + foreach (Smarty::$_muted_directories as $key => &$dir) { + if (!$dir) { + // resolve directory and length for speedy comparisons + $file = realpath($key); + if ($file === false) { + // this directory does not exist, remove and skip it + unset(Smarty::$_muted_directories[$key]); + continue; + } + $dir = array( + 'file' => $file, + 'length' => strlen($file), + ); + } + if (!strncmp($errfile, $dir['file'], $dir['length'])) { + $_is_muted_directory = true; + break; + } + } + + // pass to next error handler if this error did not occur inside SMARTY_DIR + // or the error was within smarty but masked to be ignored + if (!$_is_muted_directory || ($errno && $errno & error_reporting())) { + if (Smarty::$_previous_error_handler) { + return call_user_func(Smarty::$_previous_error_handler, $errno, $errstr, $errfile, $errline, $errcontext); + } else { + return false; + } + } + } + + /** + * Enable error handler to mute expected messages + * + * @return void + */ + public static function muteExpectedErrors() + { + /* + error muting is done because some people implemented custom error_handlers using + http://php.net/set_error_handler and for some reason did not understand the following paragraph: + + It is important to remember that the standard PHP error handler is completely bypassed for the + error types specified by error_types unless the callback function returns FALSE. + error_reporting() settings will have no effect and your error handler will be called regardless - + however you are still able to read the current value of error_reporting and act appropriately. + Of particular note is that this value will be 0 if the statement that caused the error was + prepended by the @ error-control operator. + + Smarty deliberately uses @filemtime() over file_exists() and filemtime() in some places. Reasons include + - @filemtime() is almost twice as fast as using an additional file_exists() + - between file_exists() and filemtime() a possible race condition is opened, + which does not exist using the simple @filemtime() approach. + */ + $error_handler = array('Smarty', 'mutingErrorHandler'); + $previous = set_error_handler($error_handler); + + // avoid dead loops + if ($previous !== $error_handler) { + Smarty::$_previous_error_handler = $previous; + } + } + + /** + * Disable error handler muting expected messages + * + * @return void + */ + public static function unmuteExpectedErrors() + { + restore_error_handler(); + } +} + +// Check if we're running on windows +Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; + +// let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8 +if (Smarty::$_CHARSET !== 'UTF-8') { + Smarty::$_UTF8_MODIFIER = ''; +} + +/** + * Smarty exception class + * @package Smarty + */ +class SmartyException extends Exception +{ + public static $escape = false; + + public function __toString() + { + return ' --> Smarty: ' . (self::$escape ? htmlentities($this->message) : $this->message) . ' <-- '; + } +} + +/** + * Smarty compiler exception class + * @package Smarty + */ +class SmartyCompilerException extends SmartyException +{ + public function __toString() + { + return ' --> Smarty Compiler: ' . $this->message . ' <-- '; + } + /** + * The line number of the template error + * @type int|null + */ + public $line = null; + /** + * The template source snippet relating to the error + * @type string|null + */ + public $source = null; + /** + * The raw text of the error message + * @type string|null + */ + public $desc = null; + /** + * The resource identifier or template name + * @type string|null + */ + public $template = null; +} + +/** + * Autoloader + */ +function smartyAutoload($class) +{ + $_class = strtolower($class); + static $_classes = array( + 'smarty_config_source' => true, + 'smarty_config_compiled' => true, + 'smarty_security' => true, + 'smarty_cacheresource' => true, + 'smarty_cacheresource_custom' => true, + 'smarty_cacheresource_keyvaluestore' => true, + 'smarty_resource' => true, + 'smarty_resource_custom' => true, + 'smarty_resource_uncompiled' => true, + 'smarty_resource_recompiled' => true, + ); + + if (!strncmp($_class, 'smarty_internal_', 16) || isset($_classes[$_class])) { + include SMARTY_SYSPLUGINS_DIR . $_class . '.php'; + } +} diff --git a/resources/templates/engine/smarty/Smarty.license.txt b/resources/templates/engine/smarty/Smarty.license.txt new file mode 100644 index 0000000000..02bbb60bc4 --- /dev/null +++ b/resources/templates/engine/smarty/Smarty.license.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. \ No newline at end of file diff --git a/resources/templates/engine/smarty/debug.tpl b/resources/templates/engine/smarty/debug.tpl new file mode 100644 index 0000000000..12eef0ffdb --- /dev/null +++ b/resources/templates/engine/smarty/debug.tpl @@ -0,0 +1,133 @@ +{capture name='_smarty_debug' assign=debug_output} + + + + Smarty Debug Console + + + + +

Smarty Debug Console - {if isset($template_name)}{$template_name|debug_print_var nofilter}{else}Total Time {$execution_time|string_format:"%.5f"}{/if}

+ +{if !empty($template_data)} +

included templates & config files (load time in seconds)

+ +
+{foreach $template_data as $template} + {$template.name} + + (compile {$template['compile_time']|string_format:"%.5f"}) (render {$template['render_time']|string_format:"%.5f"}) (cache {$template['cache_time']|string_format:"%.5f"}) + +
+{/foreach} +
+{/if} + +

assigned template variables

+ + + {foreach $assigned_vars as $vars} + + + + {/foreach} +
${$vars@key|escape:'html'}{$vars|debug_print_var nofilter}
+ +

assigned config file variables (outer template scope)

+ + + {foreach $config_vars as $vars} + + + + {/foreach} + +
{$vars@key|escape:'html'}{$vars|debug_print_var nofilter}
+ + +{/capture} + diff --git a/resources/templates/engine/smarty/plugins/block.textformat.php b/resources/templates/engine/smarty/plugins/block.textformat.php new file mode 100644 index 0000000000..b62a4f8eee --- /dev/null +++ b/resources/templates/engine/smarty/plugins/block.textformat.php @@ -0,0 +1,110 @@ + + * Name: textformat
+ * Purpose: format text a certain way with preset styles + * or custom wrap/indent settings
+ * Params: + *
+ * - style         - string (email)
+ * - indent        - integer (0)
+ * - wrap          - integer (80)
+ * - wrap_char     - string ("\n")
+ * - indent_char   - string (" ")
+ * - wrap_boundary - boolean (true)
+ * 
+ * + * @link http://www.smarty.net/manual/en/language.function.textformat.php {textformat} + * (Smarty online manual) + * @param array $params parameters + * @param string $content contents of the block + * @param Smarty_Internal_Template $template template object + * @param boolean &$repeat repeat flag + * @return string content re-formatted + * @author Monte Ohrt + */ +function smarty_block_textformat($params, $content, $template, &$repeat) +{ + 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: + trigger_error("textformat: unknown attribute '$_key'"); + } + } + + if ($style == 'email') { + $wrap = 72; + } + // split into paragraphs + $_paragraphs = preg_split('![\r\n]{2}!', $content); + $_output = ''; + + foreach ($_paragraphs as &$_paragraph) { + if (!$_paragraph) { + continue; + } + // convert mult. spaces & special chars to single space + $_paragraph = preg_replace(array('!\s+!' . Smarty::$_UTF8_MODIFIER, '!(^\s+)|(\s+$)!' . Smarty::$_UTF8_MODIFIER), array(' ', ''), $_paragraph); + // indent first line + if ($indent_first > 0) { + $_paragraph = str_repeat($indent_char, $indent_first) . $_paragraph; + } + // wordwrap sentences + if (Smarty::$_MBSTRING) { + require_once(SMARTY_PLUGINS_DIR . 'shared.mb_wordwrap.php'); + $_paragraph = smarty_mb_wordwrap($_paragraph, $wrap - $indent, $wrap_char, $wrap_cut); + } else { + $_paragraph = wordwrap($_paragraph, $wrap - $indent, $wrap_char, $wrap_cut); + } + // indent lines + if ($indent > 0) { + $_paragraph = preg_replace('!^!m', str_repeat($indent_char, $indent), $_paragraph); + } + } + $_output = implode($wrap_char . $wrap_char, $_paragraphs); + + if ($assign) { + $template->assign($assign, $_output); + } else { + return $_output; + } +} diff --git a/resources/templates/engine/smarty/plugins/function.counter.php b/resources/templates/engine/smarty/plugins/function.counter.php new file mode 100644 index 0000000000..cd147634fd --- /dev/null +++ b/resources/templates/engine/smarty/plugins/function.counter.php @@ -0,0 +1,76 @@ + + * Name: counter
+ * Purpose: print out a counter value + * + * @author Monte Ohrt + * @link http://www.smarty.net/manual/en/language.function.counter.php {counter} + * (Smarty online manual) + * @param array $params parameters + * @param Smarty_Internal_Template $template template object + * @return string|null + */ +function smarty_function_counter($params, $template) +{ + 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'])) { + $template->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; + +} diff --git a/resources/templates/engine/smarty/plugins/function.cycle.php b/resources/templates/engine/smarty/plugins/function.cycle.php new file mode 100644 index 0000000000..9bf26f8c4a --- /dev/null +++ b/resources/templates/engine/smarty/plugins/function.cycle.php @@ -0,0 +1,105 @@ + + * Name: cycle
+ * Date: May 3, 2002
+ * Purpose: cycle through given values
+ * Params: + *
+ * - 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://www.smarty.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 $params parameters + * @param Smarty_Internal_Template $template template object + * @return string|null + */ + +function smarty_function_cycle($params, $template) +{ + 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 (!isset($params['values'])) { + if (!isset($cycle_vars[$name]['values'])) { + 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']; + } + + if (isset($params['delimiter'])) { + $cycle_vars[$name]['delimiter'] = $params['delimiter']; + } elseif (!isset($cycle_vars[$name]['delimiter'])) { + $cycle_vars[$name]['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; + $template->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; +} diff --git a/resources/templates/engine/smarty/plugins/function.fetch.php b/resources/templates/engine/smarty/plugins/function.fetch.php new file mode 100644 index 0000000000..a4eaef37fa --- /dev/null +++ b/resources/templates/engine/smarty/plugins/function.fetch.php @@ -0,0 +1,219 @@ + + * Name: fetch
+ * Purpose: fetch file, web or ftp data and display results + * + * @link http://www.smarty.net/manual/en/language.function.fetch.php {fetch} + * (Smarty online manual) + * @author Monte Ohrt + * @param array $params parameters + * @param Smarty_Internal_Template $template template object + * @return string|null if the assign parameter is passed, Smarty assigns the result to a template variable + */ +function smarty_function_fetch($params, $template) +{ + if (empty($params['file'])) { + trigger_error("[plugin] fetch parameter 'file' cannot be empty",E_USER_NOTICE); + + return; + } + + // strip file protocol + if (stripos($params['file'], 'file://') === 0) { + $params['file'] = substr($params['file'], 7); + } + + $protocol = strpos($params['file'], '://'); + if ($protocol !== false) { + $protocol = strtolower(substr($params['file'], 0, $protocol)); + } + + if (isset($template->smarty->security_policy)) { + if ($protocol) { + // remote resource (or php stream, …) + if (!$template->smarty->security_policy->isTrustedUri($params['file'])) { + return; + } + } else { + // local file + if (!$template->smarty->security_policy->isTrustedResourceDir($params['file'])) { + return; + } + } + } + + $content = ''; + if ($protocol == 'http') { + // 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::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)) { + trigger_error("[plugin] invalid header format '".$param_value."'",E_USER_NOTICE); + + 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 { + trigger_error("[plugin] invalid value for attribute '".$param_key."'",E_USER_NOTICE); + + 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 { + trigger_error("[plugin] invalid value for attribute '".$param_key."'",E_USER_NOTICE); + + return; + } + break; + default: + trigger_error("[plugin] unrecognized attribute '".$param_key."'",E_USER_NOTICE); + + 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) { + trigger_error("[plugin] unable to fetch: $errstr ($errno)",E_USER_NOTICE); + + 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 = preg_split("!\r\n\r\n!",$content,2); + + $content = $csplit[1]; + + if (!empty($params['assign_headers'])) { + $template->assign($params['assign_headers'],preg_split("!\r\n!",$csplit[0])); + } + } + } else { + trigger_error("[plugin fetch] unable to parse URL, check syntax",E_USER_NOTICE); + + return; + } + } else { + $content = @file_get_contents($params['file']); + if ($content === false) { + throw new SmartyException("{fetch} cannot read resource '" . $params['file'] ."'"); + } + } + + if (!empty($params['assign'])) { + $template->assign($params['assign'], $content); + } else { + return $content; + } +} diff --git a/resources/templates/engine/smarty/plugins/function.html_checkboxes.php b/resources/templates/engine/smarty/plugins/function.html_checkboxes.php new file mode 100644 index 0000000000..ad0e9cd415 --- /dev/null +++ b/resources/templates/engine/smarty/plugins/function.html_checkboxes.php @@ -0,0 +1,235 @@ + + * Type: function
+ * Name: html_checkboxes
+ * Date: 24.Feb.2003
+ * Purpose: Prints out a list of checkbox input types
+ * 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} + *
+ * Params: + *
+ * - 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 + * - escape (optional) - escape the content (not value), defaults to true + *
+ * + * @link http://www.smarty.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 $params parameters + * @param object $template template object + * @return string + * @uses smarty_function_escape_special_chars() + */ +function smarty_function_html_checkboxes($params, $template) +{ + require_once(SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php'); + + $name = 'checkbox'; + $values = null; + $options = null; + $selected = array(); + $separator = ''; + $escape = true; + $labels = true; + $label_ids = false; + $output = null; + + $extra = ''; + + foreach ($params as $_key => $_val) { + switch ($_key) { + case 'name': + case 'separator': + $$_key = (string) $_val; + break; + + case 'escape': + case 'labels': + case 'label_ids': + $$_key = (bool) $_val; + break; + + case 'options': + $$_key = (array) $_val; + break; + + case 'values': + case 'output': + $$_key = array_values((array) $_val); + break; + + case 'checked': + case 'selected': + if (is_array($_val)) { + $selected = array(); + foreach ($_val as $_sel) { + if (is_object($_sel)) { + if (method_exists($_sel, "__toString")) { + $_sel = smarty_function_escape_special_chars((string) $_sel->__toString()); + } else { + trigger_error("html_checkboxes: selected attribute contains an object of class '". get_class($_sel) ."' without __toString() method", E_USER_NOTICE); + continue; + } + } else { + $_sel = smarty_function_escape_special_chars((string) $_sel); + } + $selected[$_sel] = true; + } + } elseif (is_object($_val)) { + if (method_exists($_val, "__toString")) { + $selected = smarty_function_escape_special_chars((string) $_val->__toString()); + } else { + trigger_error("html_checkboxes: selected attribute is an object of class '". get_class($_val) ."' without __toString() method", E_USER_NOTICE); + } + } else { + $selected = smarty_function_escape_special_chars((string) $_val); + } + break; + + case 'checkboxes': + 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; + + case 'strict': break; + + case 'disabled': + case 'readonly': + if (!empty($params['strict'])) { + if (!is_scalar($_val)) { + trigger_error("html_options: $_key attribute must be a scalar, only boolean true or string '$_key' will actually add the attribute", E_USER_NOTICE); + } + + if ($_val === true || $_val === $_key) { + $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_key) . '"'; + } + + break; + } + // omit break; to fall through! + + default: + if (!is_array($_val)) { + $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"'; + } else { + trigger_error("html_checkboxes: extra attribute '$_key' cannot be an array", E_USER_NOTICE); + } + break; + } + } + + if (!isset($options) && !isset($values)) + return ''; /* raise error here? */ + + $_html_result = array(); + + if (isset($options)) { + foreach ($options as $_key=>$_val) { + $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids, $escape); + } + } 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, $label_ids, $escape); + } + } + + if (!empty($params['assign'])) { + $template->assign($params['assign'], $_html_result); + } else { + return implode("\n", $_html_result); + } + +} + +function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels, $label_ids, $escape=true) +{ + $_output = ''; + + if (is_object($value)) { + if (method_exists($value, "__toString")) { + $value = (string) $value->__toString(); + } else { + trigger_error("html_options: value is an object of class '". get_class($value) ."' without __toString() method", E_USER_NOTICE); + + return ''; + } + } else { + $value = (string) $value; + } + + if (is_object($output)) { + if (method_exists($output, "__toString")) { + $output = (string) $output->__toString(); + } else { + trigger_error("html_options: output is an object of class '". get_class($output) ."' without __toString() method", E_USER_NOTICE); + + return ''; + } + } else { + $output = (string) $output; + } + + if ($labels) { + if ($label_ids) { + $_id = smarty_function_escape_special_chars(preg_replace('![^\w\-\.]!' . Smarty::$_UTF8_MODIFIER, '_', $name . '_' . $value)); + $_output .= '