summaryrefslogtreecommitdiff
path: root/public_html
diff options
context:
space:
mode:
authorJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2011-12-20 12:06:48 (GMT)
committerJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2011-12-20 12:06:48 (GMT)
commite61dae23d75394a1ab4a2774975e51a8ff7b4e9c (patch)
tree88972c8886a364991a75cd160806ae4544caaff7 /public_html
parenta6d965456ce4be294593eee569b3b19de32be497 (diff)
downloadkolab-wap-e61dae23d75394a1ab4a2774975e51a8ff7b4e9c.tar.gz
Rename 'client' to be in 'public_html'
Diffstat (limited to 'public_html')
-rwxr-xr-xpublic_html/bin/smarty_install.sh29
-rw-r--r--public_html/config/config.php4
-rw-r--r--public_html/include/init.php100
-rw-r--r--public_html/include/kolab_admin_api.php165
-rw-r--r--public_html/include/kolab_admin_api_result.php42
-rw-r--r--public_html/include/kolab_admin_output.php161
-rw-r--r--public_html/include/kolab_admin_task.php291
-rw-r--r--public_html/include/kolab_html.php330
-rw-r--r--public_html/include/kolab_utils.php62
-rw-r--r--public_html/include/tasks/about.php34
-rw-r--r--public_html/include/tasks/group.php53
-rw-r--r--public_html/include/tasks/main.php24
-rw-r--r--public_html/include/tasks/user.php106
-rw-r--r--public_html/index.php32
-rw-r--r--public_html/js/jquery.min.js4
-rw-r--r--public_html/js/kolab_admin.js347
-rw-r--r--public_html/lib/HTTP/Request2.php1015
-rw-r--r--public_html/lib/HTTP/Request2/Adapter.php154
-rw-r--r--public_html/lib/HTTP/Request2/Adapter/Curl.php560
-rw-r--r--public_html/lib/HTTP/Request2/Adapter/Mock.php171
-rw-r--r--public_html/lib/HTTP/Request2/Adapter/Socket.php1084
-rw-r--r--public_html/lib/HTTP/Request2/CookieJar.php499
-rw-r--r--public_html/lib/HTTP/Request2/Exception.php160
-rw-r--r--public_html/lib/HTTP/Request2/MultipartBody.php274
-rw-r--r--public_html/lib/HTTP/Request2/Observer/Log.php215
-rw-r--r--public_html/lib/HTTP/Request2/Response.php643
-rwxr-xr-xpublic_html/lib/Net/URL2.php942
-rw-r--r--public_html/lib/Smarty/Smarty.class.php1473
-rw-r--r--public_html/lib/Smarty/plugins/block.t.php12
-rw-r--r--public_html/lib/Smarty/plugins/block.textformat.php113
-rw-r--r--public_html/lib/Smarty/plugins/function.counter.php78
-rw-r--r--public_html/lib/Smarty/plugins/function.cycle.php106
-rw-r--r--public_html/lib/Smarty/plugins/function.fetch.php216
-rw-r--r--public_html/lib/Smarty/plugins/function.gentime.php7
-rw-r--r--public_html/lib/Smarty/plugins/function.html_checkboxes.php216
-rw-r--r--public_html/lib/Smarty/plugins/function.html_image.php138
-rw-r--r--public_html/lib/Smarty/plugins/function.html_options.php174
-rw-r--r--public_html/lib/Smarty/plugins/function.html_radios.php200
-rw-r--r--public_html/lib/Smarty/plugins/function.html_select_date.php394
-rw-r--r--public_html/lib/Smarty/plugins/function.html_select_time.php366
-rw-r--r--public_html/lib/Smarty/plugins/function.html_table.php177
-rw-r--r--public_html/lib/Smarty/plugins/function.mailto.php152
-rw-r--r--public_html/lib/Smarty/plugins/function.math.php87
-rw-r--r--public_html/lib/Smarty/plugins/modifier.capitalize.php65
-rw-r--r--public_html/lib/Smarty/plugins/modifier.date_format.php62
-rw-r--r--public_html/lib/Smarty/plugins/modifier.debug_print_var.php105
-rw-r--r--public_html/lib/Smarty/plugins/modifier.escape.php143
-rw-r--r--public_html/lib/Smarty/plugins/modifier.regex_replace.php55
-rw-r--r--public_html/lib/Smarty/plugins/modifier.replace.php33
-rw-r--r--public_html/lib/Smarty/plugins/modifier.spacify.php27
-rw-r--r--public_html/lib/Smarty/plugins/modifier.truncate.php59
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.cat.php30
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.count_characters.php33
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.count_paragraphs.php28
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.count_sentences.php28
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.count_words.php32
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.default.php35
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.escape.php90
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.from_charset.php34
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.indent.php32
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.lower.php31
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.noprint.php25
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.string_format.php26
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.strip.php33
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.strip_tags.php33
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.to_charset.php34
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.unescape.php48
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.upper.php30
-rw-r--r--public_html/lib/Smarty/plugins/modifiercompiler.wordwrap.php46
-rw-r--r--public_html/lib/Smarty/plugins/outputfilter.trimwhitespace.php92
-rw-r--r--public_html/lib/Smarty/plugins/shared.escape_special_chars.php51
-rw-r--r--public_html/lib/Smarty/plugins/shared.literal_compiler_param.php33
-rw-r--r--public_html/lib/Smarty/plugins/shared.make_timestamp.php42
-rw-r--r--public_html/lib/Smarty/plugins/shared.mb_str_replace.php55
-rw-r--r--public_html/lib/Smarty/plugins/shared.mb_unicode.php48
-rw-r--r--public_html/lib/Smarty/plugins/shared.mb_wordwrap.php83
-rw-r--r--public_html/lib/Smarty/plugins/variablefilter.htmlspecialchars.php21
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_cacheresource.php381
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_cacheresource_custom.php238
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_cacheresource_keyvaluestore.php463
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_config_source.php95
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_cacheresource_file.php264
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_append.php53
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_assign.php77
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_block.php238
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_break.php77
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_call.php130
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_capture.php98
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_config_load.php85
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_continue.php78
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_debug.php43
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_eval.php73
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_extends.php121
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_for.php151
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_foreach.php231
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_function.php165
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_if.php207
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_include.php215
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_include_php.php108
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_insert.php142
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_ldelim.php41
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_nocache.php73
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_private_block_plugin.php87
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_private_function_plugin.php73
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_private_modifier.php81
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_private_object_block_function.php88
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_private_object_function.php79
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_private_print_expression.php156
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_private_registered_block.php113
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_private_registered_function.php81
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_private_special_variable.php104
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_rdelim.php41
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_section.php203
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_setfilter.php72
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compile_while.php94
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_compilebase.php176
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_config.php303
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_config_file_compiler.php144
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_configfilelexer.php606
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_configfileparser.php928
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_data.php551
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_debug.php206
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_filter_handler.php70
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_function_call_handler.php55
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_get_include_path.php43
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_nocache_insert.php53
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_parsetree.php395
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_resource_eval.php94
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_resource_extends.php148
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_resource_file.php90
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_resource_php.php114
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_resource_registered.php95
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_resource_stream.php76
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_resource_string.php96
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_smartytemplatecompiler.php127
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_template.php684
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_templatebase.php763
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_templatecompilerbase.php626
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_templatelexer.php1190
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_templateparser.php3218
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_utility.php810
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_internal_write_file.php70
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_resource.php820
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_resource_custom.php96
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_resource_recompiled.php36
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_resource_uncompiled.php44
-rw-r--r--public_html/lib/Smarty/sysplugins/smarty_security.php427
-rw-r--r--public_html/locale/en_US.php29
-rw-r--r--public_html/skins/default/images/body.pngbin0 -> 178 bytes
-rw-r--r--public_html/skins/default/images/error.pngbin0 -> 3328 bytes
-rw-r--r--public_html/skins/default/images/favicon.pngbin0 -> 1094 bytes
-rw-r--r--public_html/skins/default/images/info.pngbin0 -> 3424 bytes
-rw-r--r--public_html/skins/default/images/kolabsystems.pngbin0 -> 12281 bytes
-rw-r--r--public_html/skins/default/images/loading.gifbin0 -> 1780 bytes
-rw-r--r--public_html/skins/default/images/logo.pngbin0 -> 13367 bytes
-rw-r--r--public_html/skins/default/images/logout.pngbin0 -> 624 bytes
-rw-r--r--public_html/skins/default/style.css328
-rw-r--r--public_html/skins/default/templates/about.html14
-rw-r--r--public_html/skins/default/templates/about_kolab.html96
-rw-r--r--public_html/skins/default/templates/about_kolabsys.html54
-rw-r--r--public_html/skins/default/templates/about_technology.html161
-rw-r--r--public_html/skins/default/templates/error.html22
-rw-r--r--public_html/skins/default/templates/login.html32
-rw-r--r--public_html/skins/default/templates/main.html25
-rw-r--r--public_html/skins/default/templates/user.html8
165 files changed, 32074 insertions, 0 deletions
diff --git a/public_html/bin/smarty_install.sh b/public_html/bin/smarty_install.sh
new file mode 100755
index 0000000..9fe0860
--- /dev/null
+++ b/public_html/bin/smarty_install.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+#
+# Smarty templates library quick installation (with sources download)
+#
+
+SMARTYVER="3.1.6"
+
+cd ../lib
+# download
+echo -n "Downloading Smarty sources... "
+wget http://www.smarty.net/files/Smarty-$SMARTYVER.tar.gz
+echo "done."
+
+# extracting package
+echo -n "Extracting... "
+tar -xzf Smarty-$SMARTYVER.tar.gz
+echo "done."
+exit
+# merging
+echo -n "Merging... "
+mkdir Smarty > /dev/null
+mv Smarty-$SMARTYVER/libs/* Smarty/
+mv Smarty-$SMARTYVER/libs/plugins/* Smarty/plugins/
+echo "done."
+
+# cleanup
+echo -n "Cleaning up... "
+rm -Rf Smarty-$SMARTYVER Smarty-$SMARTYVER.tar.gz
+echo "done."
diff --git a/public_html/config/config.php b/public_html/config/config.php
new file mode 100644
index 0000000..23f9a05
--- /dev/null
+++ b/public_html/config/config.php
@@ -0,0 +1,4 @@
+<?php
+
+$CONFIG['api_url'] = 'http://admin.klab.cc/~machniak/kolab-wap/public_html/api';
+
diff --git a/public_html/include/init.php b/public_html/include/init.php
new file mode 100644
index 0000000..c2cd758
--- /dev/null
+++ b/public_html/include/init.php
@@ -0,0 +1,100 @@
+<?php
+
+/*
+ * Kolab Admin Panel
+ *
+ * (C) Copyright 2011 Kolab Systems AG
+ *
+ */
+
+// Initialisation and basic functions
+
+// Check critical PHP settings here.
+$crit_opts = array(
+ 'mbstring.func_overload' => 0,
+ 'magic_quotes_runtime' => 0,
+);
+foreach ($crit_opts as $optname => $optval) {
+ if ($optval != ini_get($optname)) {
+ die("ERROR: Wrong '$optname' option value!");
+ }
+}
+
+$include_path = INSTALL_PATH . '/lib' . PATH_SEPARATOR;
+$include_path.= ini_get('include_path');
+
+if (set_include_path($include_path) === false) {
+ die("Fatal error: ini_set/set_include_path does not work.");
+}
+
+ini_set('error_reporting', E_ALL&~E_NOTICE);
+ini_set('error_log', 'logs/errors');
+
+// Set internal charset
+mb_internal_encoding(KADM_CHARSET);
+@mb_regex_encoding(KADM_CHARSET);
+
+/**
+ * Kolab Admin Classes Autoloader
+ */
+function kolab_admin_autoload($classname)
+{
+ if (preg_match('/^kolab_/', $classname)) {
+ if (preg_match('/^kolab_admin_task_([a-z]+)$/', $classname, $m)) {
+ $filename = INSTALL_PATH . '/include/tasks/' . $m[1] . '.php';
+ }
+ else {
+ $filename = INSTALL_PATH . "/include/$classname.php";
+ }
+
+ if ($fp = @fopen($filename, 'r')) {
+ fclose($fp);
+ include_once($filename);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+spl_autoload_register('kolab_admin_autoload');
+
+/**
+ * Prints debug info into the 'console' log
+ */
+function console()
+{
+ $args = func_get_args();
+
+ $msg = array();
+ foreach ($args as $arg) {
+ $msg[] = !is_string($arg) ? var_export($arg, true) : $arg;
+ }
+
+ write_log('console', join(";\n", $msg));
+}
+
+/**
+ * Appends a line to a log file in the logs directory.
+ * Date will be added automatically to the line.
+ *
+ * @param string $name Name of the log file
+ * @param mixed $line Line to append
+ */
+function write_log($name, $line)
+{
+ if (!is_string($line)) {
+ $line = var_export($line, true);
+ }
+
+ $log_dir = INSTALL_PATH . '/logs';
+ $logfile = $log_dir . '/' . $name;
+ $date = date('d-M-Y H:i:s O');
+ $line = sprintf("[%s]: %s\n", $date, $line);
+
+ if ($fp = @fopen($logfile, 'a')) {
+ fwrite($fp, $line);
+ fflush($fp);
+ fclose($fp);
+ }
+}
diff --git a/public_html/include/kolab_admin_api.php b/public_html/include/kolab_admin_api.php
new file mode 100644
index 0000000..c1358db
--- /dev/null
+++ b/public_html/include/kolab_admin_api.php
@@ -0,0 +1,165 @@
+<?php
+
+
+class kolab_admin_api
+{
+ /**
+ * @var HTTP_Request2
+ */
+ private $request;
+
+ /**
+ * @var string
+ */
+ private $base_url;
+
+
+ const STATUS_OK = 0;
+ const STATUS_ERROR = 1;
+
+ const ERROR_INTERNAL = 500;
+
+ /**
+ * Class constructor.
+ *
+ * @param string $base_url Base URL of Kolab API
+ */
+ public function __construct($base_url)
+ {
+ $this->base_url = $base_url;
+ $this->init();
+ }
+
+ /**
+ * Initializes HTTP Request object.
+ */
+ public function init()
+ {
+ require_once 'HTTP/Request2.php';
+
+ $this->request = new HTTP_Request2();
+ }
+
+ /**
+ *
+ * @return array Session user data (token, domain)
+ */
+ public function login($username, $password)
+ {
+ $query = array(
+ 'username' => $username,
+ 'password' => $password
+ );
+
+ $response = $this->post('system.authenticate', null, $query);
+
+ if ($token = $response->get('session_token')) {
+ return array(
+ 'token' => $token,
+ 'domain' => $response->get('domain'),
+ );
+ }
+ }
+
+ public function logout()
+ {
+ $response = $this->get('system.quit');
+
+ return $response->get_error_code() ? false : true;
+ }
+
+ public function set_session_token($token)
+ {
+ $this->request->setHeader('X-Session-Token', $token);
+ }
+
+ public function get_capabilities()
+ {
+ $this->get('system.capabilities');
+ }
+
+ public function get($action, $args = array())
+ {
+ $url = $this->build_url($action, $args);
+
+ $this->request->setMethod(HTTP_Request2::METHOD_GET);
+
+ return $this->get_response($url);
+ }
+
+ public function post($action, $url_args = array(), $post = array())
+ {
+ $url = $this->build_url($action, $url_args);
+
+ $this->request->setMethod(HTTP_Request2::METHOD_POST);
+ $this->request->setBody(@json_encode($post));
+
+ return $this->get_response($url);
+ }
+
+ /**
+ * @param string $action Action GET parameter
+ * @param array $args GET parameters (hash array: name => value)
+ *
+ * @return Net_URL2 URL object
+ */
+ private function build_url($action, $args)
+ {
+ $url = $this->base_url;
+
+ if ($action) {
+ $url .= '/' . urlencode($action);
+ }
+
+ $url = new Net_URL2($url);
+
+ if (!empty($args)) {
+ $url->setQueryVariables($args);
+ }
+
+ return $url;
+ }
+
+ /**
+ * HTTP Response handler.
+ *
+ * @param Net_URL2 $url URL object
+ *
+ * @return kolab_admin_api_result Response object
+ */
+ private function get_response($url)
+ {
+ try {
+ $this->request->setUrl($url);
+ $response = $this->request->send();
+ }
+ catch (Exception $e) {
+ return new kolab_admin_api_result(null,
+ self::ERROR_INTERNAL, $e->getMessage());
+ }
+
+ try {
+ $body = $response->getBody();
+ }
+ catch (Exception $e) {
+ return new kolab_admin_api_result(null,
+ self::ERROR_INTERNAL, $e->getMessage());
+ }
+
+//print_r($body);
+ $body = @json_decode($body, true);
+ $err_code = null;
+ $err_str = null;
+
+ if (is_array($body) && (empty($body['status']) || $body['status'] != 'OK')) {
+ $err_code = !empty($data['code']) ? $data['code'] : self::ERROR_INTERNAL;
+ $err_str = !empty($data['reason']) ? $data['reason'] : 'Unknown error';
+ }
+ else if (!is_array($body)) {
+ $err_code = self::ERROR_INTERNAL;
+ $err_str = 'Unable to decode response';
+ }
+
+ return new kolab_admin_api_result($body, $err_code, $err_str);
+ }
+}
diff --git a/public_html/include/kolab_admin_api_result.php b/public_html/include/kolab_admin_api_result.php
new file mode 100644
index 0000000..772030f
--- /dev/null
+++ b/public_html/include/kolab_admin_api_result.php
@@ -0,0 +1,42 @@
+<?php
+
+class kolab_admin_api_result
+{
+ /**
+ * @var array
+ */
+ private $data = array();
+
+ private $error_code;
+ private $error_str;
+
+
+ public function __construct($data = array(), $error_code = null, $error_str = null)
+ {
+ if (is_array($data) && isset($data['result'])) {
+ $this->data = $data['result'];
+ }
+
+ $this->error_code = $error_code;
+ $this->error_str = $error_str;
+ }
+
+ public function get_error_code()
+ {
+ $this->error_code;
+ }
+
+ public function get_error_str()
+ {
+ $this->error_str;
+ }
+
+ public function get($name = null)
+ {
+ if ($name !== null) {
+ return isset($this->data[$name]) ? $this->data[$name] : null;
+ }
+
+ return $this->data;
+ }
+}
diff --git a/public_html/include/kolab_admin_output.php b/public_html/include/kolab_admin_output.php
new file mode 100644
index 0000000..711bf70
--- /dev/null
+++ b/public_html/include/kolab_admin_output.php
@@ -0,0 +1,161 @@
+<?php
+
+class kolab_admin_output
+{
+ private $tpl_vars = array();
+ private $env = array();
+ private $objects = array();
+ private $commands = array();
+ private $labels = array();
+ private $skin;
+
+ public function __construct($skin = null)
+ {
+ $this->skin = $skin ? $skin : 'default';
+ $this->init();
+ }
+
+ public function init()
+ {
+ require_once 'lib/Smarty/Smarty.class.php';
+
+ $SMARTY = new Smarty;
+ $SMARTY->template_dir = 'skins/' . $this->skin . '/templates';
+ $SMARTY->compile_dir = 'cache';
+ $SMARTY->debugging = false;
+
+ $this->tpl = $SMARTY;
+ }
+
+ public function send($template = null)
+ {
+ if ($this->is_ajax()) {
+ echo $this->send_json();
+ }
+ else {
+ $this->send_tpl($template);
+ }
+ }
+
+ private function send_json()
+ {
+ header('Content-Type: application/json');
+
+ $response = array(
+ 'objects' => $this->objects,
+ 'env' => array(),
+ );
+
+ foreach ($this->env as $name => $value) {
+ $response['env'][$name] = $value;
+ }
+
+ foreach ($this->commands as $command) {
+ $cname = array_shift($command);
+ $args = array();
+
+ foreach ($command as $arg) {
+ $args[] = json_encode($arg);
+ }
+
+ $commands[] = sprintf('kadm.%s(%s);', $cname, implode(',', $args));
+ }
+
+ if (!empty($commands)) {
+ $response['exec'] = implode("\n", $commands);
+ }
+
+ $this->labels = array_unique($this->labels);
+ foreach ($this->labels as $label) {
+ $response['labels'][$label] = kolab_admin_task::translate($label);
+ }
+
+ return json_encode($response);
+ }
+
+ private function send_tpl($template)
+ {
+ if (!$template) {
+ return;
+ }
+
+ foreach ($this->tpl_vars as $name => $value) {
+ $this->tpl->assign($name, $value);
+ }
+
+ $script = '';
+
+ if (!empty($this->env)) {
+ $script[] = 'kadm.env = ' . json_encode($this->env) . ';';
+ }
+
+ $this->labels = array_unique($this->labels);
+ if (!empty($this->labels)) {
+ foreach ($this->labels as $label) {
+ $labels[$label] = kolab_admin_task::translate($label);
+ }
+ $script[] = 'kadm.tdef(' . json_encode($labels) . ');';
+ }
+
+ foreach ($this->commands as $command) {
+ $cname = array_shift($command);
+ $args = array();
+
+ foreach ($command as $arg) {
+ $args[] = json_encode($arg);
+ }
+
+ $script[] = sprintf('kadm.%s(%s);', $cname, implode(',', $args));
+ }
+
+ $this->tpl->assign('skin_path', 'skins/' . $this->skin . '/');
+ if ($script) {
+ $script = "<script type=\"text/javascript\">\n" . implode("\n", $script) . "\n</script>";
+ $this->tpl->assign('script', $script);
+ }
+
+ $this->tpl->display($template . '.html');
+ }
+
+ public function is_ajax()
+ {
+ return !empty($_REQUEST['remote']);
+ }
+
+ public function assign($name, $value)
+ {
+ $this->tpl_vars[$name] = $value;
+ }
+
+ public function set_env($name, $value)
+ {
+ $this->env[$name] = $value;
+ }
+
+ public function set_object($name, $content, $is_template = false)
+ {
+ if ($is_template) {
+ ob_start();
+ $this->send_tpl($content);
+ $content = ob_get_contents();
+ ob_end_clean();
+ }
+
+ $this->objects[$name] = $content;
+ }
+
+ public function command()
+ {
+ $this->commands[] = func_get_args();
+ }
+
+ public function add_translation()
+ {
+ $this->labels = array_merge($this->labels, func_get_args());
+ }
+
+ public static function escape($str)
+ {
+
+ }
+}
diff --git a/public_html/include/kolab_admin_task.php b/public_html/include/kolab_admin_task.php
new file mode 100644
index 0000000..c49fda3
--- /dev/null
+++ b/public_html/include/kolab_admin_task.php
@@ -0,0 +1,291 @@
+<?php
+
+
+class kolab_admin_task
+{
+ /**
+ * @var kolab_admin_output
+ */
+ protected $output;
+
+ /**
+ * @var kolab_admin_api
+ */
+ protected $api;
+
+ protected $ajax_only = false;
+ protected $page_title = 'Kolab Admin Panel';
+ protected $menu = array();
+
+ static $translation = array();
+
+
+ public function __construct()
+ {
+ $this->config_init();
+ $this->output_init();
+ $this->api_init();
+
+ session_start();
+
+ $this->auth();
+ }
+
+ private function locale_init()
+ {
+ $aliases = array(
+ 'de' => 'de_DE',
+ 'en' => 'en_US',
+ 'pl' => 'pl_PL',
+ );
+
+ // UI language
+ $langs = !empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : '';
+ $langs = explode(',', $langs);
+
+ if (!empty($_SESSION['user']) && !empty($_SESSION['user']['language'])) {
+ array_unshift($langs, $_SESSION['user']['language']);
+ }
+
+ while ($lang = array_shift($langs)) {
+ $lang = explode(';', $lang);
+ $lang = $lang[0];
+ $lang = str_replace('-', '_', $lang);
+
+ if (file_exists(INSTALL_PATH . "/locale/$lang.php")) {
+ $language = $lang;
+ break;
+ }
+ if (isset($aliases[$lang]) && ($alias = $aliases[$lang])
+ && file_exists(INSTALL_PATH . "/locale/$alias.php")
+ ) {
+ $language = $alias;
+ break;
+ }
+ }
+
+ $LANG = array();
+ @include INSTALL_PATH . '/locale/en_US.php';
+
+ if (isset($language)) {
+ @include INSTALL_PATH . "/locale/$language.php";
+ setlocale(LC_ALL, $language . '.utf8', 'en_US.utf8');
+ }
+ else {
+ setlocale(LC_ALL, 'en_US.utf8');
+ }
+
+ self::$translation = $LANG;
+ }
+
+ private function config_init()
+ {
+ include_once INSTALL_PATH . '/config/config.php';
+
+ $this->config = $CONFIG;
+ }
+
+ private function output_init()
+ {
+ $skin = $this->config_get('skin', 'default');
+ $this->output = new kolab_admin_output($skin);
+ }
+
+ private function api_init()
+ {
+ $url = $this->config_get('api_url', '');
+ $this->api = new kolab_admin_api($url);
+ }
+
+ private function auth()
+ {
+ if (isset($_POST['login'])) {
+ $login = $this->get_input('login', 'POST');
+
+ if ($login['username']) {
+ $result = $this->api->login($login['username'], $login['password']);
+
+ if ($result) {
+ $this->api->set_session_token($result['token']);
+ // find user settings
+ $res = $this->api->get('user.info', array('user' => $login['username']));
+ $res = $res->get();
+
+ if (is_array($res) && ($res = array_shift($res))) {
+ $result['language'] = $res['preferredlanguage'];
+ $result['fullname'] = $res['cn'];
+ }
+
+ $_SESSION['user'] = $result;
+ header('Location: ?');
+ die;
+ }
+ else {
+ $this->output->command('display_message', 'loginerror', 'error');
+ }
+ }
+ }
+ else if (!empty($_SESSION['user']) && !empty($_SESSION['user']['token'])) {
+ $this->api->set_session_token($_SESSION['user']['token']);
+ return;
+ }
+
+ }
+
+ private function action_logout()
+ {
+ if (!empty($_SESSION['user']) && !empty($_SESSION['user']['token'])) {
+ $this->api->logout();
+ }
+ unset($_SESSION['user']);
+
+ if ($this->output->is_ajax()) {
+ $this->output->command('main_logout');
+ }
+ else {
+ $this->output->assign('login', $this->get_input('login', 'POST'));
+ $this->output->add_translation('loginerror');
+ $this->output->send('login');
+ }
+ exit;
+ }
+
+ public function run()
+ {
+ // Initialize locales
+ $this->locale_init();
+
+ // Run security checks
+ $this->input_checks();
+
+ if (empty($_SESSION['user']) || empty($_SESSION['user']['token'])) {
+ $this->action_logout();
+ }
+
+ $action = $this->get_input('action', 'GET');
+
+ if ($action) {
+ $method = 'action_' . $action;
+ if (method_exists($this, $method)) {
+ $this->$method();
+ }
+ }
+ else if (method_exists($this, 'action_default')) {
+ $this->action_default();
+ }
+ }
+
+ public function input_checks()
+ {
+ $ajax = $this->output->is_ajax();
+ // Check AJAX-only tasks
+ if ($this->ajax_only && !$ajax) {
+ $this->raise_error(500, 'Invalid request type!');
+ }
+
+ // CSRF prevention
+ $token = $ajax ? kolab_utils::request_header('X-KAP-Request') : $this->get_input('token');
+ $task = $this->get_task();
+
+ if ($task != 'main' && $token != $_SESSION['user']['token']) {
+ $this->raise_error(403, 'Invalid request data!');
+ }
+ }
+
+ public function raise_error($code, $msg)
+ {
+ // @TODO: log
+
+ if ($this->output->is_ajax()) {
+ header("HTTP/1.0 $code $msg");
+ die;
+ }
+
+ $this->output->assign('error_code', $code);
+ $this->output->assign('error_message', $msg);
+ $this->output->send('error');
+ exit;
+ }
+
+ public function send()
+ {
+ $template = $this->get_task();
+
+ if ($this->page_title) {
+ $this->output->assign('pagetitle', $this->page_title);
+ }
+
+ $this->output->send($template);
+ exit;
+ }
+
+ public function get_task()
+ {
+ $class_name = get_class($this);
+
+ if (preg_match('/^kolab_admin_task_([a-z]+)$/', $class_name, $m)) {
+ return $m[1];
+ }
+ }
+
+ public function config_get($name, $fallback = null)
+ {
+ return isset($this->config[$name]) ? $this->config[$name] : $fallback;
+ }
+
+ public static function translate()
+ {
+ $args = func_get_args();
+
+ if (is_array($args[0])) {
+ $args = $args[0];
+ }
+
+ $label = $args[0];
+
+ if (isset(self::$translation[$label])) {
+ $content = trim(self::$translation[$label]);
+ }
+ else {
+ $content = $label;
+ }
+
+ for ($i = 1, $len = count($args); $i < $len; $i++) {
+ $content = str_replace('$'.$i, $args[$i], $content);
+ }
+
+ return $content;
+ }
+
+ public static function get_input($name, $type = null, $allow_html = false)
+ {
+ return kolab_utils::get_input($name, $type = null, $allow_html = false);
+ }
+
+ public function menu()
+ {
+ if (empty($this->menu)) {
+ return '';
+ }
+
+ $task = $this->get_task();
+
+ foreach ($this->menu as $idx => $label) {
+ if (strpos($idx, '.')) {
+ $action = $idx;
+ $class = preg_replace('/\.[a-z_-]+$/', '', $idx);
+ }
+ else {
+ $action = $task . '.' . $idx;
+ $class = $idx;
+ }
+
+ $menu[$idx] = sprintf('<li class="%s"><a href="#%s" '
+ .'onclick="return kadm.command(\'%s\', \'\', this)">%s</a></li>',
+ $class, $idx, $action, $this->translate($label));
+ }
+
+ return '<ul>' . implode("\n", $menu) . '</ul>';
+ }
+
+}
diff --git a/public_html/include/kolab_html.php b/public_html/include/kolab_html.php
new file mode 100644
index 0000000..333a3f8
--- /dev/null
+++ b/public_html/include/kolab_html.php
@@ -0,0 +1,330 @@
+<?php
+
+
+class kolab_html
+{
+ const INPUT_NONE = 0;
+ const INPUT_TEXT = 1;
+ const INPUT_PASSWORD = 2;
+ const INPUT_TEXTAREA = 3;
+ const INPUT_CHECKBOX = 4;
+ const INPUT_RADIO = 5;
+ const INPUT_BUTTON = 6;
+ const INPUT_SUBMIT = 7;
+
+ public static $common_attribs = array('id', 'class', 'style', 'title', 'align', 'dir');
+ public static $event_attribs = array('onclick', 'ondblclick', 'onmousedown', 'onmouseup',
+ 'onmouseover', 'onmousemove', 'onmouseout');
+ public static $input_event_attribs = array('onfocus', 'onblur', 'onkeypress', 'onkeydown', 'onkeyup',
+ 'onsubmit', 'onreset', 'onselect', 'onchange');
+ public static $table_attribs = array('summary');
+ public static $tr_attribs = array();
+ public static $td_attribs = array('colspan', 'rowspan');
+ public static $textarea_attribs = array('cols', 'rows', 'disabled', 'name', 'readonly', 'tabindex');
+ public static $input_attribs = array('checked', 'disabled', 'name', 'readonly', 'tabindex',
+ 'type', 'size', 'maxlength', 'value');
+ public static $select_attribs = array('multiple', 'name', 'size', 'disabled');
+ public static $option_attribs = array('selected', 'value', 'disabled');
+ public static $a_attribs = array('href', 'name', 'rel', 'tabindex', 'target');
+ public static $form_attribs = array('action', 'enctype', 'method', 'name', 'target');
+ public static $label_attribs = array('for');
+
+
+ public static function form_table($attribs = array(), $definition = array(), $data = array())
+ {
+ $content = '';
+ if (!empty($definition) && is_array($definition)) {
+ foreach ($definition as $set) {
+ $set_content = '';
+ if (isset($set['fields'])) {
+ $fields = $set['fields'];
+ }
+ else {
+ $fields = array($set);
+ }
+
+ $rows = array();
+
+ foreach ($fields as $fieldname => $field) {
+ $cells = array(
+ 0 => array(
+ 'class' => 'label',
+ 'body' => self::escape($field['label']),
+ ),
+ 1 => array(
+ 'class' => 'value',
+ 'body' => self::form_element($field),
+ ),
+ 2 => array(
+ 'class' => 'description',
+ 'body' => $field['description'],
+ ),
+ );
+ $rows[] = array('cells' => $cells);
+ }
+
+ if (!empty($rows)) {
+ $set_content = self::table(array('body' => $rows, 'class' => 'form'));
+ }
+
+ if ($set_content) {
+ if (isset($set['fields'])) {
+ $content .= "\n" . self::fieldset($set, $set_content);
+ }
+ else {
+ $content .= "\n" . $set_content;
+ }
+ }
+ }
+ }
+
+// foreach ($definition as $
+ return self::form($attribs, $content);
+ }
+
+
+ public static function table($attribs = array(), $content = null)
+ {
+ $table_attribs = array_merge(self::$table_attribs, self::$common_attribs, self::$event_attribs);
+ $table = '<table' . self::attrib_string($attribs, $table_attribs) . '>';
+
+ if ($content) {
+ $table .= $content;
+ }
+ else {
+ if (!empty($attribs['head']) && is_array($attribs['head'])) {
+ $table .= '<thead>';
+ foreach ($attribs['head'] as $row) {
+ $table .= "\n" . self::tr($row, null, true);
+ }
+ $table .= '</thead>';
+ }
+ if (!empty($attribs['body']) && is_array($attribs['body'])) {
+ $table .= '<tbody>';
+ foreach ($attribs['body'] as $row) {
+ $table .= "\n" . self::tr($row);
+ }
+ $table .= '</tbody>';
+ }
+ if (!empty($attribs['foot']) && is_array($attribs['foot'])) {
+ $table .= '<tfoot>';
+ foreach ($attribs['foot'] as $row) {
+ $table .= "\n" . self::tr($row);
+ }
+ $table .= '</tfoot>';
+ }
+ }
+
+ $table .= "\n</table>";
+
+ return $table;
+ }
+
+ public static function tr($attribs = array(), $is_head = false)
+ {
+ $row_attribs = array_merge(self::$tr_attribs, self::$common_attribs, self::$event_attribs);
+ $row = '<tr' . self::attrib_string($attribs, $row_attribs) . '>';
+
+ if (!empty($attribs['cells']) && is_array($attribs['cells'])) {
+ foreach ($attribs['cells'] as $cell) {
+ $row .= "\n" . self::td($cell, $is_head);
+ }
+ }
+
+ $row .= "\n</tr>";
+
+ return $row;
+ }
+
+ public static function td($attribs = array(), $is_head = false)
+ {
+ $cell_attribs = array_merge(self::$td_attribs, self::$common_attribs, self::$event_attribs);
+ $tag = $is_head ? 'th' : 'td';
+ $cell .= '<' . $tag . self::attrib_string($attribs, $cell_attribs) . '>';
+
+ if (isset($attribs['body'])) {
+ $cell .= $attribs['body'];
+ }
+ else if (!empty($attribs['element'])) {
+ $cell .= self::form_element($attribs['element']);
+ }
+
+ $cell .= "</$tag>";
+
+ return $cell;
+ }
+
+ public static function form_element($attribs = array())
+ {
+ $type = isset($attribs['type']) ? $attribs['type'] : 0;
+
+ switch ($type) {
+ case self::INPUT_TEXT:
+ case self::INPUT_PASSWORD:
+ $attribs['type'] = $type == self::INPUT_PASSWORD ? 'password' : 'text';
+ $content = self::input($attribs);
+ break;
+ case self::INPUT_TEXTAREA:
+ $content = self::textarea($attribs);
+ break;
+ case INPUT_NONE:
+ default:
+ if (is_array($attribs)) {
+ $content = isset($attribs['value']) ? $attribs['value'] : '';
+ }
+ else {
+ $content = $attribs;
+ }
+ $content = self::escape($content);
+ }
+
+ return $content;
+ }
+
+ public static function input($attribs = array())
+ {
+ $elem_attribs = array_merge(self::$input_attribs, self::$input_event_attribs,
+ self::$common_attribs, self::$event_attribs);
+
+ return sprintf('<input%s />', self::attrib_string($attribs, $elem_attribs));
+ }
+
+ public static function textarea($attribs = array())
+ {
+ $elem_attribs = array_merge(self::$textarea_attribs, self::$input_event_attribs,
+ self::$common_attribs, self::$event_attribs);
+
+ $value = isset($attribs['value']) ? self::escape($attribs['value']) : '';
+
+ return sprintf('<textarea%s>%s</textarea>',
+ self::attrib_string($attribs, $elem_attribs), $value);
+ }
+
+ public static function select($attribs = array())
+ {
+ $elem_attribs = array_merge(self::$select_attribs, self::$input_event_attribs,
+ self::$common_attribs, self::$event_attribs);
+
+ $content = array();
+ if (!empty($attribs['options']) && is_array($attribs['options'])) {
+ foreach ($attribs['options'] as $option) {
+ $content[] = self::option($option);
+ }
+ }
+
+ return sprintf('<select%s>%s</select>',
+ self::attrib_string($attribs, $elem_attribs), implode("\n", $content));
+ }
+
+ public static function option($attribs = array())
+ {
+ $elem_attribs = array_merge(self::$option_attribs, self::$common_attribs);
+
+ $content = isset($attribs['content']) ? self::escape($attribs['content']) : '';
+
+ return sprintf('<textarea%s>%s</textarea>',
+ self::attrib_string($attribs, $elem_attribs), $content);
+ }
+
+ public static function fieldset($attribs = array(), $content = null)
+ {
+ $elem_attribs = array_merge(self::$common_attribs);
+ $legend = isset($attribs['legend']) ? $attribs['legend'] : $attribs['label'];
+
+ return sprintf('<fieldset%s><legend>%s</legend>%s</fieldset>',
+ self::attrib_string($attribs, $elem_attribs), $legend, $content);
+ }
+
+ public static function a($attribs = array(), $content = null)
+ {
+ $elem_attribs = array_merge(self::$a_attribs, self::$common_attribs, self::$event_attribs);
+
+ return sprintf('<a%s>%s</a>',
+ self::attrib_string($attribs, $elem_attribs), self::escape($content));
+ }
+
+ public static function label($attribs = array(), $content = null)
+ {
+ $elem_attribs = array_merge(self::$label_attribs, self::$common_attribs);
+
+ return sprintf('<label%s>%s</label>',
+ self::attrib_string($attribs, $elem_attribs), self::escape($content));
+ }
+
+ public static function div($attribs = array(), $content = null)
+ {
+ $elem_attribs = array_merge(self::$common_attribs, self::$event_attribs);
+
+ return sprintf('<div%s>%s</div>',
+ self::attrib_string($attribs, $elem_attribs), $content);
+ }
+
+ public static function span($attribs = array(), $content = null)
+ {
+ $elem_attribs = array_merge(self::$common_attribs, self::$event_attribs);
+
+ return sprintf('<span%s>%s</span>',
+ self::attrib_string($attribs, $elem_attribs), $content);
+ }
+
+ public static function form($attribs = array(), $content = null)
+ {
+ $elem_attribs = array_merge(self::$form_attribs, self::$common_attribs, self::$event_attribs);
+
+ return sprintf('<form%s>%s</form>',
+ self::attrib_string($attribs, $elem_attribs), $content);
+ }
+
+ /**
+ * Create string with attributes
+ *
+ * @param array $attrib Associative array with tag attributes
+ * @param array $allowed List of allowed attributes
+ *
+ * @return string Valid attribute string
+ */
+ public static function attrib_string($attrib = array(), $allowed = array())
+ {
+ if (empty($attrib)) {
+ return '';
+ }
+
+ $allowed = array_flip((array)$allowed);
+ $attrib_arr = array();
+
+ foreach ($attrib as $key => $value) {
+ // skip size if not numeric
+ if (($key == 'size' && !is_numeric($value))) {
+ continue;
+ }
+
+ // ignore "internal" or not allowed attributes
+ if ((!empty($allowed) && !isset($allowed[$key])) || $value === null) {
+ continue;
+ }
+
+ // skip empty eventhandlers
+ if (preg_match('/^on[a-z]+/', $key) && !$value) {
+ continue;
+ }
+
+ // boolean attributes
+ if (preg_match('/^(checked|multiple|disabled|selected|readonly)$/', $key)) {
+ if ($value) {
+ $attrib_arr[] = sprintf('%s="%s"', $key, $key);
+ }
+ }
+ // the rest
+ else {
+ $attrib_arr[] = sprintf('%s="%s"', $key, self::escape($value));
+ }
+ }
+
+ return count($attrib_arr) ? ' '.implode(' ', $attrib_arr) : '';
+ }
+
+ public static function escape($value)
+ {
+ return htmlspecialchars($value, null, 'UTF-8');
+ }
+}
diff --git a/public_html/include/kolab_utils.php b/public_html/include/kolab_utils.php
new file mode 100644
index 0000000..4709600
--- /dev/null
+++ b/public_html/include/kolab_utils.php
@@ -0,0 +1,62 @@
+<?php
+
+class kolab_utils
+{
+
+
+ /**
+ * Read a specific HTTP request header
+ *
+ * @param string $name Header name
+ *
+ * @return mixed Header value or null if not available
+ */
+ public static function request_header($name)
+ {
+ if (function_exists('getallheaders')) {
+ $hdrs = array_change_key_case(getallheaders(), CASE_UPPER);
+ $key = strtoupper($name);
+ }
+ else {
+ $key = 'HTTP_' . strtoupper(strtr($name, '-', '_'));
+ $hdrs = array_change_key_case($_SERVER, CASE_UPPER);
+ }
+
+ return $hdrs[$key];
+ }
+
+
+ public static function get_input($name, $type = null, $allow_html = false)
+ {
+ if ($type == 'GET') {
+ $value = isset($_GET[$name]) ? $_GET[$name] : null;
+ }
+ else if ($type == 'POST') {
+ $value = isset($_POST[$name]) ? $_POST[$name] : null;
+ }
+ else {
+ $value = isset($_REQUEST[$name]) ? $_REQUEST[$name] : null;
+ }
+
+ return self::parse_input($value, $allow_html);
+ }
+
+ public static function parse_input($value, $allow_html = false)
+ {
+ if (empty($value)) {
+ return $value;
+ }
+
+ if (is_array($value)) {
+ foreach ($value as $idx => $val) {
+ $value[$idx] = self::parse_input($val, $allow_html);
+ }
+ }
+ // remove HTML tags if not allowed
+ else if (!$allow_html) {
+ $value = strip_tags($value);
+ }
+
+ return $value;
+ }
+}
diff --git a/public_html/include/tasks/about.php b/public_html/include/tasks/about.php
new file mode 100644
index 0000000..2fb2f9c
--- /dev/null
+++ b/public_html/include/tasks/about.php
@@ -0,0 +1,34 @@
+<?php
+
+class kolab_admin_task_about extends kolab_admin_task
+{
+ protected $ajax_only = true;
+
+ protected $menu = array(
+ 'kolab' => 'menu.kolab',
+ 'kolabsys' => 'menu.kolabsys',
+ 'technology' => 'menu.technology',
+ );
+
+ public function action_default()
+ {
+ $this->output->set_object('content', 'about', true);
+ $this->output->set_object('task_navigation', $this->menu());
+ }
+
+ public function action_kolab()
+ {
+ $this->output->set_object('content', 'about_kolab', true);
+ }
+
+ public function action_kolabsys()
+ {
+ $this->output->set_object('content', 'about_kolabsys', true);
+ }
+
+ public function action_technology()
+ {
+ $this->output->set_object('content', 'about_technology', true);
+ }
+
+}
diff --git a/public_html/include/tasks/group.php b/public_html/include/tasks/group.php
new file mode 100644
index 0000000..0082dbc
--- /dev/null
+++ b/public_html/include/tasks/group.php
@@ -0,0 +1,53 @@
+<?php
+
+class kolab_admin_task_group extends kolab_admin_task
+{
+ protected $ajax_only = true;
+
+ protected $menu = array(
+ 'add' => 'group.add',
+ 'list' => 'group.list',
+ );
+
+ public function action_default()
+ {
+ $this->output->set_object('content', '');
+ $this->output->set_object('task_navigation', $this->menu());
+ }
+
+ public function action_list()
+ {
+// $content = 'test output from users.list';
+ $result = $this->api->post('groups.list');
+ $result = (array) $result->get();
+/*
+ foreach ($result as $idx => $item) {
+ if (!is_array($item) || empty($item['uid'])) {
+ unset($result[$idx]);
+ continue;
+ }
+ $result[$idx] = sprintf('<li><a href="#" onclick="kadm.command(\'user.info\', \'%s\')">%s</a></li>',
+ $idx, $item['uid']);
+ }
+
+ $result = '<ul id="userlist">' . implode("\n", $result) . '</ul>';
+ $this->output->set_object('content', $result);
+*/
+ }
+
+ public function action_info()
+ {
+/*
+ $id = $this->get_input('id', 'POST');
+ $result = $this->api->get('user.info', array('user' => $id));
+
+ $user = $result->get($id);
+ $this->output->set_object('content', print_r($user, true));
+*/
+ }
+
+ public function group_add()
+ {
+
+ }
+}
diff --git a/public_html/include/tasks/main.php b/public_html/include/tasks/main.php
new file mode 100644
index 0000000..bd72678
--- /dev/null
+++ b/public_html/include/tasks/main.php
@@ -0,0 +1,24 @@
+<?php
+
+class kolab_admin_task_main extends kolab_admin_task
+{
+ protected $menu = array(
+ 'user.default' => 'menu.users',
+ 'group.default' => 'menu.groups',
+ 'about.default' => 'menu.about',
+ );
+
+
+ public function action_default()
+ {
+ // assign token
+ $this->output->set_env('token', $_SESSION['user']['token']);
+
+ // assign default set of translations
+ $this->output->add_translation('loading', 'servererror');
+
+ $this->output->assign('main_menu', $this->menu());
+ $this->output->assign('user', $_SESSION['user']);
+ }
+
+}
diff --git a/public_html/include/tasks/user.php b/public_html/include/tasks/user.php
new file mode 100644
index 0000000..03cc54c
--- /dev/null
+++ b/public_html/include/tasks/user.php
@@ -0,0 +1,106 @@
+<?php
+
+class kolab_admin_task_user extends kolab_admin_task
+{
+ protected $ajax_only = true;
+
+ protected $menu = array(
+ 'add' => 'user.add',
+ 'list' => 'user.list',
+ );
+
+ public function action_default()
+ {
+ $this->output->set_object('content', 'user', true);
+ $this->output->set_object('task_navigation', $this->menu());
+ }
+
+ public function action_list()
+ {
+ $result = $this->api->post('users.list');
+ $result = (array) $result->get();
+
+ $rows = $head = array();
+ $cols = array('name', 'actions', 'test');
+ $i = 0;
+
+ foreach ($cols as $col) {
+ $body = $col != 'actions' ? $this->translate('user.' . $col) : '';
+ $head[0]['cells'][] = array('class' => $col, 'body' => $body);
+ }
+
+ if (!empty($result)) {
+ foreach ($result as $idx => $item) {
+ if (!is_array($item) || empty($item['uid'])) {
+ continue;
+ }
+
+ $i++;
+ $cells = array();
+ $cells[] = array('class' => 'name', 'body' => kolab_html::escape($item['uid']),
+ 'onclick' => "kadm.command('user.info', '$idx')");
+ $cells[] = array('class' => 'links', 'body' => '<a>test</a>');
+ $cells[] = array('class' => 'links', 'body' => 'test sdf sdf sd fs df sdf sd f');
+ $rows[] = array('id' => $i, 'class' => 'selectable', 'cells' => $cells);
+ }
+ }
+ else {
+ $rows[] = array('cells' => array(
+ 0 => array('class' => 'empty-body', 'colspan' => count($cols),
+ 'body' => $this->translate('user.norecords')
+ )));
+ }
+
+ $table = kolab_html::table(array('id' => 'userlist', 'class' => 'list',
+ 'head' => $head, 'body' => $rows));
+ $this->output->set_object('task_content', $table);
+ }
+
+ public function action_info()
+ {
+ $id = $this->get_input('id', 'POST');
+ $result = $this->api->get('user.info', array('user' => $id));
+
+ $user = $result->get($id);
+
+ $definition = array(
+ 'personal' => array(
+ 'label' => $this->translate('user.personal'),
+ 'fields' => array(
+ 'givenname' => array(
+ 'label' => $this->translate('user.givenname'),
+ 'description' => '',
+ 'type' => '',
+ 'value' => $user['givenname'],
+ ),
+ 'sn' => array(
+ 'label' => $this->translate('user.surname'),
+ 'description' => '',
+ 'type' => '',
+ 'value' => $user['sn'],
+ ),
+ 'mail' => array(
+ 'label' => $this->translate('user.email'),
+ 'description' => 'sdf sdf sd fs sdf s dfsdfsdf sdfsdfsfsfs df',
+ 'type' => '',
+ 'value' => $user['mail'],
+ ),
+ ),
+ ),
+ );
+
+ $form = kolab_html::form_table(null, $definition);
+
+ $this->output->set_object('content', $form);
+ }
+
+ public function user_add()
+ {
+
+ }
+
+ private function user_types()
+ {
+ $result = $this->api->post('user_types.list');
+ }
+}
diff --git a/public_html/index.php b/public_html/index.php
new file mode 100644
index 0000000..66c930c
--- /dev/null
+++ b/public_html/index.php
@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * Kolab Admin Panel
+ *
+ * (C) Copyright 2011 Kolab Systems AG
+ *
+ */
+
+// application constants
+define('KADM_START', microtime(true));
+define('KADM_VERSION', '0.1');
+define('KADM_CHARSET', 'utf-8');
+define('INSTALL_PATH', dirname($_SERVER['SCRIPT_FILENAME']).'/');
+
+// environment initialization
+require_once INSTALL_PATH . '/include/init.php';
+
+// starting task
+$task = kolab_utils::get_input('task', 'GET');
+
+if (!$task) {
+ $task = 'main';
+}
+
+$class = "kolab_admin_task_$task";
+
+$KADM = new $class;
+
+// run actions and send output
+$KADM->run();
+$KADM->send();
diff --git a/public_html/js/jquery.min.js b/public_html/js/jquery.min.js
new file mode 100644
index 0000000..628ed9b
--- /dev/null
+++ b/public_html/js/jquery.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v1.6.4 http://jquery.com/ | http://jquery.org/license */
+(function(a,b){function cu(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cr(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cq(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cp(){cn=b}function co(){setTimeout(cp,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function bZ(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function bY(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bA.test(a)?d(a,e):bY(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)bY(a+"["+e+"]",b[e],c,d);else d(a,b)}function bX(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bW(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bP,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bW(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bW(a,c,d,e,"*",g));return l}function bV(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bL),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function by(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bt:bu;if(d>0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bv(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bl(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bd,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bk(a){f.nodeName(a,"input")?bj(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bj)}function bj(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bi(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bh(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bg(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i<j;i++)f.event.add(b,h+(g[h][i].namespace?".":"")+g[h][i].namespace,g[h][i],g[h][i].data)}}}}function bf(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function V(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(Q.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function U(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function M(a,b){return(a&&a!=="*"?a+".":"")+b.replace(y,"`").replace(z,"&")}function L(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;i<s.length;i++)g=s[i],g.origType.replace(w,"")===a.type?q.push(g.selector):s.splice(i--,1);e=f(a.target).closest(q,a.currentTarget);for(j=0,k=e.length;j<k;j++){m=e[j];for(i=0;i<s.length;i++){g=s[i];if(m.selector===g.selector&&(!n||n.test(g.namespace))&&!m.elem.disabled){h=m.elem,d=null;if(g.preType==="mouseenter"||g.preType==="mouseleave")a.type=g.preType,d=f(a.relatedTarget).closest(g.selector)[0],d&&f.contains(h,d)&&(d=h);(!d||d!==h)&&p.push({elem:h,handleObj:g,level:m.level})}}}for(j=0,k=p.length;j<k;j++){e=p[j];if(c&&e.level>c)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function J(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function D(){return!0}function C(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function K(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(K,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z]|[0-9])/ig,x=/^-ms-/,y=function(a,b){return(b+"").toUpperCase()},z=d.userAgent,A,B,C,D=Object.prototype.toString,E=Object.prototype.hasOwnProperty,F=Array.prototype.push,G=Array.prototype.slice,H=String.prototype.trim,I=Array.prototype.indexOf,J={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.4",length:0,size:function(){return this.length},toArray:function(){return G.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?F.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),B.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(G.apply(this,arguments),"slice",G.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:F,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;B.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!B){B=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",C,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",C),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&K()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):J[D.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!E.call(a,"constructor")&&!E.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||E.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(x,"ms-").replace(w,y)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:H?function(a){return a==null?"":H.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?F.call(c,a):e.merge(c,a)}return c},inArray:function(a,b){if(!b)return-1;if(I)return I.call(b,a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=G.call(arguments,2),g=function(){return a.apply(c,f.concat(G.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=s.exec(a)||t.exec(a)||u.exec(a)||a.indexOf("compatible")<0&&v.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){J["[object "+b+"]"]=b.toLowerCase()}),A=e.uaMatch(z),A.browser&&(e.browser[A.browser]=!0,e.browser.version=A.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?C=function(){c.removeEventListener("DOMContentLoaded",C,!1),e.ready()}:c.attachEvent&&(C=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",C),e.ready())});return e}(),g="done fail isResolved isRejected promise then always pipe".split(" "),h=[].slice;f.extend({_Deferred:function(){var a=[],b,c,d,e={done:function(){if(!d){var c=arguments,g,h,i,j,k;b&&(k=b,b=0);for(g=0,h=c.length;g<h;g++)i=c[g],j=f.type(i),j==="array"?e.done.apply(e,i):j==="function"&&a.push(i);k&&e.resolveWith(k[0],k[1])}return this},resolveWith:function(e,f){if(!d&&!b&&!c){f=f||[],c=1;try{while(a[0])a.shift().apply(e,f)}finally{b=[e,f],c=0}}return this},resolve:function(){e.resolveWith(this,arguments);return this},isResolved:function(){return!!c||!!b},cancel:function(){d=1,a=[];return this}};return e},Deferred:function(a){var b=f._Deferred(),c=f._Deferred(),d;f.extend(b,{then:function(a,c){b.done(a).fail(c);return this},always:function(){return b.done.apply(b,arguments).fail.apply(this,arguments)},fail:c.done,rejectWith:c.resolveWith,reject:c.resolve,isRejected:c.isResolved,pipe:function(a,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[c,"reject"]},function(a,c){var e=c[0],g=c[1],h;f.isFunction(e)?b[a](function(){h=e.apply(this,arguments),h&&f.isFunction(h.promise)?h.promise().then(d.resolve,d.reject):d[g+"With"](this===b?d:this,[h])}):b[a](d[g])})}).promise()},promise:function(a){if(a==null){if(d)return d;d=a={}}var c=g.length;while(c--)a[g[c]]=b[g[c]];return a}}),b.done(c.cancel).fail(b.cancel),delete b.cancel,a&&a.call(b,b);return b},when:function(a){function i(a){return function(c){b[a]=arguments.length>1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c<d;c++)b[c]&&f.isFunction(b[c].promise)?b[c].promise().then(i(c),g.reject):--e;e||g.resolveWith(g,b)}else g!==a&&g.resolveWith(g,d?[a]:[]);return g.promise()}}),f.support=function(){var a=c.createElement("div"),b=c.documentElement,d,e,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;a.setAttribute("className","t"),a.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},m&&f.extend(p,{position:"absolute",left:"-1000px",top:"-1000px"});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i=f.expando,j=typeof c=="string",k=a.nodeType,l=k?f.cache:a,m=k?a[f.expando]:a[f.expando]&&f.expando;if((!m||e&&m&&l[m]&&!l[m][i])&&j&&d===b)return;m||(k?a[f.expando]=m=++f.uuid:m=f.expando),l[m]||(l[m]={},k||(l[m].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?l[m][i]=f.extend(l[m][i],c):l[m]=f.extend(l[m],c);g=l[m],e&&(g[i]||(g[i]={}),g=g[i]),d!==b&&(g[f.camelCase(c)]=d);if(c==="events"&&!g[c])return g[i]&&g[i].events;j?(h=g[c],h==null&&(h=g[f.camelCase(c)])):h=g;return h}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e=f.expando,g=a.nodeType,h=g?f.cache:a,i=g?a[f.expando]:f.expando;if(!h[i])return;if(b){d=c?h[i][e]:h[i];if(d){d[b]||(b=f.camelCase(b)),delete d[b];if(!l(d))return}}if(c){delete h[i][e];if(!l(h[i]))return}var j=h[i][e];f.support.deleteExpando||!h.setInterval?delete h[i]:h[i]=null,j?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=j):g&&(f.support.deleteExpando?delete a[f.expando]:a.removeAttribute?a.removeAttribute(f.expando):a[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h<i;h++)g=e[h].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),k(this[0],g,d[g]))}}return d}if(typeof a=="object")return this.each(function(){f.data(this,a)});var j=a.split(".");j[1]=j[1]?"."+j[1]:"";if(c===b){d=this.triggerHandler("getData"+j[1]+"!",[j[0]]),d===b&&this.length&&(d=f.data(this[0],a),d=k(this[0],a,d));return d===b&&j[1]?this.data(j[0]):d}return this.each(function(){var b=f(this),d=[j[0],c];b.triggerHandler("setData"+j[1]+"!",d),f.data(this,a,c),b.triggerHandler("changeData"+j[1]+"!",d)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,c){a&&(c=(c||"fx")+"mark",f.data(a,c,(f.data(a,c,b,!0)||0)+1,!0))},_unmark:function(a,c,d){a!==!0&&(d=c,c=a,a=!1);if(c){d=d||"fx";var e=d+"mark",g=a?0:(f.data(c,e,b,!0)||1)-1;g?f.data(c,e,g,!0):(f.removeData(c,e,!0),m(c,d,"mark"))}},queue:function(a,c,d){if(a){c=(c||"fx")+"queue";var e=f.data(a,c,b,!0);d&&(!e||f.isArray(d)?e=f.data(a,c,f.makeArray(d),!0):e.push(d));return e||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e;d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),d.call(a,function(){f.dequeue(a,b)})),c.length||(f.removeData(a,b+"queue",!0),m(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(){var c=this;setTimeout(function(){f.dequeue(c,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f._Deferred(),!0))h++,l.done(m);m();return d.promise()}});var n=/[\n\t\r]/g,o=/\s+/,p=/\r/g,q=/^(?:button|input)$/i,r=/^(?:button|input|object|select|textarea)$/i,s=/^a(?:rea)?$/i,t=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,u,v;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(o);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(o);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(n," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(o);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ";for(var c=0,d=this.length;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(n," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h<i;h++){var j=e[h];if(j.selected&&(f.support.optDisabled?!j.disabled:j.getAttribute("disabled")===null)&&(!j.parentNode.disabled||!f.nodeName(j.parentNode,"optgroup"))){b=f(j).val();if(g)return b;d.push(b)}}if(g&&!d.length&&e.length)return f(e[c]).val();return d},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=v:u&&(i=u)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.attr(a,b,""),a.removeAttribute(b),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(u&&f.nodeName(a,"button"))return u.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(u&&f.nodeName(a,"button"))return u.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==null?g:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabIndex=f.propHooks.tabIndex,v={get:function(a,c){var d;return f.prop(a,c)===!0||(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(u=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var w=/\.(.*)$/,x=/^(?:textarea|input|select)$/i,y=/\./g,z=/ /g,A=/[^\w\s.|`]/g,B=function(a){return a.replace(A,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=C;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=C);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),B).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j<p.length;j++){q=p[j];if(l||n.test(q.namespace))f.event.remove(a,r,q.handler,j),p.splice(j--,1)}continue}o=f.event.special[h]||{};for(j=e||0;j<p.length;j++){q=p[j];if(d.guid===q.guid){if(l||n.test(q.namespace))e==null&&p.splice(j--,1),o.remove&&o.remove.call(a,q);if(e!=null)break}}if(p.length===0||e!=null&&p.length===1)(!o.teardown||o.teardown.call(a,m)===!1)&&f.removeEvent(a,h,s.handle),g=null,delete
+t[h]}if(f.isEmptyObject(t)){var u=s.handle;u&&(u.elem=null),delete s.events,delete s.handle,f.isEmptyObject(s)&&f.removeData(a,b,!0)}}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){var h=c.type||c,i=[],j;h.indexOf("!")>=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h<i;h++){var j=d[h];if(e||c.namespace_re.test(j.namespace)){c.handler=j.handler,c.data=j.data,c.handleObj=j;var k=j.handler.apply(this,g);k!==b&&(c.result=k,k===!1&&(c.preventDefault(),c.stopPropagation()));if(c.isImmediatePropagationStopped())break}}return c.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[f.expando])return a;var d=a;a=f.Event(d);for(var e=this.props.length,g;e;)g=this.props[--e],a[g]=d[g];a.target||(a.target=a.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),!a.relatedTarget&&a.fromElement&&(a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement);if(a.pageX==null&&a.clientX!=null){var h=a.target.ownerDocument||c,i=h.documentElement,j=h.body;a.pageX=a.clientX+(i&&i.scrollLeft||j&&j.scrollLeft||0)-(i&&i.clientLeft||j&&j.clientLeft||0),a.pageY=a.clientY+(i&&i.scrollTop||j&&j.scrollTop||0)-(i&&i.clientTop||j&&j.clientTop||0)}a.which==null&&(a.charCode!=null||a.keyCode!=null)&&(a.which=a.charCode!=null?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(a.metaKey=a.ctrlKey),!a.which&&a.button!==b&&(a.which=a.button&1?1:a.button&2?3:a.button&4?2:0);return a},guid:1e8,proxy:f.proxy,special:{ready:{setup:f.bindReady,teardown:f.noop},live:{add:function(a){f.event.add(this,M(a.origType,a.selector),f.extend({},a,{handler:L,guid:a.handler.guid}))},remove:function(a){f.event.remove(this,M(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}}},f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!this.preventDefault)return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?D:C):this.type=a,b&&f.extend(this,b),this.timeStamp=f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=D;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=D;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=D,this.stopPropagation()},isDefaultPrevented:C,isPropagationStopped:C,isImmediatePropagationStopped:C};var E=function(a){var b=a.relatedTarget,c=!1,d=a.type;a.type=a.data,b!==this&&(b&&(c=f.contains(this,b)),c||(f.event.handle.apply(this,arguments),a.type=d))},F=function(a){a.type=a.data,f.event.handle.apply(this,arguments)};f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={setup:function(c){f.event.add(this,b,c&&c.selector?F:E,a)},teardown:function(a){f.event.remove(this,b,a&&a.selector?F:E)}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(a,b){if(!f.nodeName(this,"form"))f.event.add(this,"click.specialSubmit",function(a){var b=a.target,c=f.nodeName(b,"input")||f.nodeName(b,"button")?b.type:"";(c==="submit"||c==="image")&&f(b).closest("form").length&&J("submit",this,arguments)}),f.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,c=f.nodeName(b,"input")||f.nodeName(b,"button")?b.type:"";(c==="text"||c==="password")&&f(b).closest("form").length&&a.keyCode===13&&J("submit",this,arguments)});else return!1},teardown:function(a){f.event.remove(this,".specialSubmit")}});if(!f.support.changeBubbles){var G,H=function(a){var b=f.nodeName(a,"input")?a.type:"",c=a.value;b==="radio"||b==="checkbox"?c=a.checked:b==="select-multiple"?c=a.selectedIndex>-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},I=function(c){var d=c.target,e,g;if(!!x.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=H(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:I,beforedeactivate:I,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&I.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&I.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",H(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in G)f.event.add(this,c+".specialChange",G[c]);return x.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return x.test(this.nodeName)}},G=f.event.special.change.filters,G.focus=G.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i<j;i++)f.event.add(this[i],a,g,d);return this}}),f.fn.extend({unbind:function(a,b){if(typeof a=="object"&&!a.preventDefault)for(var c in a)this.unbind(c,a[c]);else for(var d=0,e=this.length;d<e;d++)f.event.remove(this[d],a,b);return this},delegate:function(a,b,c,d){return this.live(b,c,d,a)},undelegate:function(a,b,c){return arguments.length===0?this.unbind("live"):this.die(b,null,c,a)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f.data(this,"lastToggle"+a.guid)||0)%d;f.data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var K={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};f.each(["live","die"],function(a,c){f.fn[c]=function(a,d,e,g){var h,i=0,j,k,l,m=g||this.selector,n=g?this:f(this.context);if(typeof a=="object"&&!a.preventDefault){for(var o in a)n[c](o,d,a[o],m);return this}if(c==="die"&&!a&&g&&g.charAt(0)==="."){n.unbind(g);return this}if(d===!1||f.isFunction(d))e=d||C,d=b;a=(a||"").split(" ");while((h=a[i++])!=null){j=w.exec(h),k="",j&&(k=j[0],h=h.replace(w,""));if(h==="hover"){a.push("mouseenter"+k,"mouseleave"+k);continue}l=h,K[h]?(a.push(K[h]+k),h=h+k):h=(K[h]||h)+k;if(c==="live")for(var p=0,q=n.length;p<q;p++)f.event.add(n[p],"live."+M(h,m),{data:d,selector:m,handler:e,origType:h,origHandler:e,preType:l});else n.unbind("live."+M(h,m),e)}return this}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}if(i.nodeType===1){f||(i.sizcache=c,i.sizset=g);if(typeof b!="string"){if(i===b){j=!0;break}}else if(k.filter(b,[i]).length>0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}i.nodeType===1&&!f&&(i.sizcache=c,i.sizset=g);if(i.nodeName.toLowerCase()===b){j=i;break}i=i[a]}d[g]=j}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},k.matches=function(a,b){return k(a,null,null,b)},k.matchesSelector=function(a,b){return k(b,null,null,[a]).length>0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e<f;e++){var g,h=l.order[e];if(g=l.leftMatch[h].exec(a)){var j=g[1];g.splice(1,1);if(j.substr(j.length-1)!=="\\"){g[1]=(g[1]||"").replace(i,""),d=l.find[h](g,b,c);if(d!=null){a=a.replace(l.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},k.filter=function(a,c,d,e){var f,g,h=a,i=[],j=c,m=c&&c[0]&&k.isXML(c[0]);while(a&&c.length){for(var n in l.filter)if((f=l.leftMatch[n].exec(a))!=null&&f[2]){var o,p,q=l.filter[n],r=f[1];g=!1,f.splice(1,1);if(r.substr(r.length-1)==="\\")continue;j===i&&(i=[]);if(l.preFilter[n]){f=l.preFilter[n](f,j,d,i,e,m);if(!f)g=o=!0;else if(f===!0)continue}if(f)for(var s=0;(p=j[s])!=null;s++)if(p){o=q(p,f,s,j);var t=e^!!o;d&&o!=null?t?g=!0:j[s]=!1:t&&(i.push(p),g=!0)}if(o!==b){d||(j=i),a=a.replace(l.match[n],"");if(!g)return[];break}}if(a===h)if(g==null)k.error(a);else break;h=a}return j},k.error=function(a){throw"Syntax error, unrecognized expression: "+a};var l=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!j.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&k.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&k.filter(b,a,!0)}},"":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("parentNode",b,f,a,e,c)},"~":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("previousSibling",b,f,a,e,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(i,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}k.error(e)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case"only":case"first":while(d=d.previousSibling)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case"last":while(d=d.nextSibling)if(d.nodeType===1)return!1;return!0;case"nth":var e=b[2],f=b[3];if(e===1&&f===0)return!0;var g=b[0],h=a.parentNode;if(h&&(h.sizcache!==g||!a.nodeIndex)){var i=0;for(d=h.firstChild;d;d=d.nextSibling)d.nodeType===1&&(d.nodeIndex=++i);h.sizcache=g}var j=a.nodeIndex-f;return e===0?j===0:j%e===0&&j/e>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c<f;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var r,s;c.documentElement.compareDocumentPosition?r=function(a,b){if(a===b){g=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(r=function(a,b){if(a===b){g=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],h=a.parentNode,i=b.parentNode,j=h;if(h===i)return s(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return s(e[k],f[k]);return k===c?s(a,f[k],-1):s(e[k],b,1)},s=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),k.getText=function(a){var b="",c;for(var d=0;a[d];d++)c=a[d],c.nodeType===3||c.nodeType===4?b+=c.nodeValue:c.nodeType!==8&&(b+=k.getText(c.childNodes));return b},function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g<h;g++)k(a,f[g],d);return k.filter(e,d)};f.find=k,f.expr=k.selectors,f.expr[":"]=f.expr.filters,f.unique=k.uniqueSort,f.text=k.getText,f.isXMLDoc=k.isXML,f.contains=k.contains}();var N=/Until$/,O=/^(?:parents|prevUntil|prevAll)/,P=/,/,Q=/^.[^:#\[\.,]*$/,R=Array.prototype.slice,S=f.expr.match.POS,T={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(V(this,a,!1),"not",a)},filter:function(a){return this.pushStack(V(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d<e;d++)i=a[d],j[i]||(j[i]=S.test(i)?f(i,b||this.context):i);while(g&&g.ownerDocument&&g!==b){for(i in j)h=j[i],(h.jquery?h.index(g)>-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=S.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(l?l.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(U(c[0])||U(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=R.call(arguments);N.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!T[a]?f.unique(e):e,(this.length>1||P.test(d))&&O.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|object|embed|option|style)/i,bb=/checked\s*(?:[^=]|=\s*.checked.)/i,bc=/\/(java|ecma)script/i,bd=/^\s*<!(?:\[CDATA\[|\-\-)/,be={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};be.optgroup=be.option,be.tbody=be.tfoot=be.colgroup=be.caption=be.thead,be.th=be.td,f.support.htmlSerialize||(be._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!be[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bb.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bf(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bl)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i;b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof a[0]=="string"&&a[0].length<512&&i===c&&a[0].charAt(0)==="<"&&!ba.test(a[0])&&(f.support.checkClone||!bb.test(a[0]))&&(g=!0,h=f.fragments[a[0]],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean
+(a,i,e,d)),g&&(f.fragments[a[0]]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bh(a,d),e=bi(a),g=bi(d);for(h=0;e[h];++h)g[h]&&bh(e[h],g[h])}if(b){bg(a,d);if(c){e=bi(a),g=bi(d);for(h=0;e[h];++h)bg(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=be[l]||be._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bk(k[i]);else bk(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||bc.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.expando,g=f.event.special,h=f.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&f.noData[j.nodeName.toLowerCase()])continue;c=j[f.expando];if(c){b=d[c]&&d[c][e];if(b&&b.events){for(var k in b.events)g[k]?f.event.remove(j,k):f.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[f.expando]:j.removeAttribute&&j.removeAttribute(f.expando),delete d[c]}}}});var bm=/alpha\([^)]*\)/i,bn=/opacity=([^)]*)/,bo=/([A-Z]|^ms)/g,bp=/^-?\d+(?:px)?$/i,bq=/^-?\d/,br=/^([\-+])=([\-+.\de]+)/,bs={position:"absolute",visibility:"hidden",display:"block"},bt=["Left","Right"],bu=["Top","Bottom"],bv,bw,bx;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bv(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=br.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bv)return bv(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return by(a,b,d);f.swap(a,bs,function(){e=by(a,b,d)});return e}},set:function(a,b){if(!bp.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bn.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bm,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bm.test(g)?g.replace(bm,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bv(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bw=function(a,c){var d,e,g;c=c.replace(bo,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bx=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bp.test(d)&&bq.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bv=bw||bx,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bz=/%20/g,bA=/\[\]$/,bB=/\r?\n/g,bC=/#.*$/,bD=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bE=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bF=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bG=/^(?:GET|HEAD)$/,bH=/^\/\//,bI=/\?/,bJ=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bK=/^(?:select|textarea)/i,bL=/\s+/,bM=/([?&])_=[^&]*/,bN=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bO=f.fn.load,bP={},bQ={},bR,bS,bT=["*/"]+["*"];try{bR=e.href}catch(bU){bR=c.createElement("a"),bR.href="",bR=bR.href}bS=bN.exec(bR.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bO)return bO.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bJ,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bK.test(this.nodeName)||bE.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bB,"\r\n")}}):{name:b.name,value:c.replace(bB,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?bX(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),bX(a,b);return a},ajaxSettings:{url:bR,isLocal:bF.test(bS[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bT},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bV(bP),ajaxTransport:bV(bQ),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?bZ(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=b$(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bD.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bC,"").replace(bH,bS[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bL),d.crossDomain==null&&(r=bN.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bS[1]&&r[2]==bS[2]&&(r[3]||(r[1]==="http:"?80:443))==(bS[3]||(bS[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bW(bP,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bG.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bI.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bM,"$1_="+x);d.url=y+(y===d.url?(bI.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bT+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bW(bQ,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){s<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bz,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cq("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cr(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cq("hide",3),a,b,c);for(var d=0,e=this.length;d<e;d++)if(this[d].style){var g=f.css(this[d],"display");g!=="none"&&!f._data(this[d],"olddisplay")&&f._data(this[d],"olddisplay",g)}for(d=0;d<e;d++)this[d].style&&(this[d].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cq("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return this[e.queue===!1?"each":"queue"](function(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(f.support.inlineBlockNeedsLayout?(j=cr(this.nodeName),j==="inline"?this.style.display="inline-block":(this.style.display="inline",this.style.zoom=1)):this.style.display="inline-block"))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)k=new f.fx(this,b,i),h=a[i],cj.test(h)?k[h==="toggle"?d?"show":"hide":h]():(l=ck.exec(h),m=k.cur(),l?(n=parseFloat(l[2]),o=l[3]||(f.cssNumber[i]?"":"px"),o!=="px"&&(f.style(this,i,(n||1)+o),m=(n||1)/k.cur()*m,f.style(this,i,m+o)),l[1]&&(n=(l[1]==="-="?-1:1)*n+m),k.custom(m,n,o)):k.custom(m,h,""));return!0})},stop:function(a,b){a&&this.queue([]),this.each(function(){var a=f.timers,c=a.length;b||f._unmark(!0,this);while(c--)a[c].elem===this&&(b&&a[c](!0),a.splice(c,1))}),b||this.dequeue();return this}}),f.each({slideDown:cq("show",1),slideUp:cq("hide",1),slideToggle:cq("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default,d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue!==!1?f.dequeue(this):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function g(a){return d.step(a)}var d=this,e=f.fx;this.startTime=cn||co(),this.start=a,this.end=b,this.unit=c||this.unit||(f.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,g.elem=this.elem,g()&&f.timers.push(g)&&!cl&&(cl=setInterval(e.tick,e.interval))},show:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=cn||co(),c=!0,d=this.elem,e=this.options,g,h;if(a||b>=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b<a.length;++b)a[b]()||a.splice(b--,1);a.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cl),cl=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cs=/^t(?:able|d|h)$/i,ct=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cu(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);f.offset.initialize();var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.offset.doesNotAddBorder&&(!f.offset.doesAddBorderForTableAndCells||!cs.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={initialize:function(){var a=c.body,b=c.createElement("div"),d,e,g,h,i=parseFloat(f.css(a,"marginTop"))||0,j="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=ct.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!ct.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cu(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cu(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNaN(j)?i:j}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); \ No newline at end of file
diff --git a/public_html/js/kolab_admin.js b/public_html/js/kolab_admin.js
new file mode 100644
index 0000000..b6be2af
--- /dev/null
+++ b/public_html/js/kolab_admin.js
@@ -0,0 +1,347 @@
+
+
+function kolab_admin()
+{
+ var ref = this;
+
+ this.env = {};
+ this.translations = {};
+ this.request_timeout = 300;
+ this.message_time = 4000;
+
+ // set jQuery ajax options
+ $.ajaxSetup({
+ cache: false,
+ error: function(request, status, err) { ref.http_error(request, status, err); },
+ beforeSend: function(xmlhttp) { xmlhttp.setRequestHeader('X-KAP-Request', ref.env.token); }
+ });
+
+
+ /*********************************************************/
+ /********* basic utilities *********/
+ /*********************************************************/
+
+ // set environment variable(s)
+ this.set_env = function(p, value)
+ {
+ if (p != null && typeof p === 'object' && !value)
+ for (var n in p)
+ this.env[n] = p[n];
+ else
+ this.env[p] = value;
+ };
+
+ // add a localized label(s) to the client environment
+ this.tdef = function(p, value)
+ {
+ if (typeof p == 'string')
+ this.translations[p] = value;
+ else if (typeof p == 'object')
+ $.extend(this.translations, p);
+ };
+
+ // return a localized string
+ this.t = function(label)
+ {
+ if (this.translations[label])
+ return this.translations[label];
+ else
+ return label;
+ };
+
+ this.log = function(msg)
+ {
+ if (window.console && console.log)
+ console.log(msg);
+ };
+
+ // execute a specific command on the web client
+ this.command = function(command, props, obj)
+ {
+ if (obj && obj.blur)
+ obj.blur();
+
+ if (this.busy)
+ return false;
+
+ this.set_busy(true, 'loading');
+
+ var ret = undefined,
+ func = command.replace(/[^a-z]/g, '_'),
+ task = command.replace(/\.[a-z-_]+$/g, '');
+
+ if (this[func] && typeof this[func] === 'function') {
+ ret = this[func](props);
+ }
+ else {
+ this.http_post(command, props);
+ }
+
+ // update menu state
+ $('li', $('#navigation')).removeClass('active');
+ $('li.'+task, ('#navigation')).addClass('active');
+
+ return ret === false ? false : obj ? false : true;
+ };
+
+ this.set_busy = function(a, message)
+ {
+ if (a && message) {
+ var msg = this.t(message);
+ if (msg == message)
+ msg = 'Loading...';
+
+ this.display_message(msg, 'loading');
+ }
+ else if (!a) {
+ this.hide_message('loading');
+ }
+
+ this.busy = a;
+
+// if (this.gui_objects.editform)
+ // this.lock_form(this.gui_objects.editform, a);
+
+ // clear pending timer
+ if (this.request_timer)
+ clearTimeout(this.request_timer);
+
+ // set timer for requests
+ if (a && this.env.request_timeout)
+ this.request_timer = window.setTimeout(function() { ref.request_timed_out(); }, this.request_timeout * 1000);
+ };
+
+ // called when a request timed out
+ this.request_timed_out = function()
+ {
+ this.set_busy(false);
+ this.display_message('Request timed out!', 'error');
+ };
+
+ // Add variable to GET string, replace old value if exists
+ this.add_url = function(url, name, value)
+ {
+ value = urlencode(value);
+
+ if (/(\?.*)$/.test(url)) {
+ var urldata = RegExp.$1,
+ datax = RegExp('((\\?|&)'+RegExp.escape(name)+'=[^&]*)');
+
+ if (datax.test(urldata))
+ urldata = urldata.replace(datax, RegExp.$2 + name + '=' + value);
+ else
+ urldata += '&' + name + '=' + value
+
+ return url.replace(/(\?.*)$/, urldata);
+ }
+ else
+ return url + '?' + name + '=' + value;
+ };
+
+
+ /*********************************************************/
+ /********* GUI functionality *********/
+ /*********************************************************/
+
+ // write to the document/window title
+ this.set_pagetitle = function(title)
+ {
+ if (title && document.title)
+ document.title = title;
+ };
+
+ // display a system message (types: loading, notice, error)
+ this.display_message = function(msg, type, timeout)
+ {
+ var obj, ref = this;
+
+ if (!type)
+ type = 'notice';
+ if (msg)
+ msg = this.t(msg);
+
+ if (type == 'loading') {
+ timeout = this.request_timeout * 1000;
+ if (!msg)
+ msg = this.t('loading');
+ }
+ else if (!timeout)
+ timeout = this.message_time * (type == 'error' || type == 'warning' ? 2 : 1);
+
+ obj = $('<div>');
+
+ if (type != 'loading') {
+ msg = '<div><span>' + msg + '</span></div>';
+ obj.addClass(type).click(function() { return ref.hide_message(); });
+ }
+
+ if (timeout > 0)
+ window.setTimeout(function() { ref.hide_message(type, type != 'loading'); }, timeout);
+
+ obj.attr('id', type == 'loading' ? 'loading' : 'message')
+ .appendTo('body').html(msg).show();
+ };
+
+ // make a message to disapear
+ this.hide_message = function(type, fade)
+ {
+ if (type == 'loading')
+ $('#loading').remove();
+ else
+ $('#message').fadeOut('normal', function() { $(this).remove(); });
+ };
+
+
+ /********************************************************/
+ /********* remote request methods *********/
+ /********************************************************/
+
+ // compose a valid url with the given parameters
+ this.url = function(action, query)
+ {
+ var k, param = {},
+ querystring = typeof query === 'string' ? '&' + query : '';
+
+ if (typeof action !== 'string')
+ query = action;
+ else if (!query || typeof query !== 'object')
+ query = {};
+
+ // overwrite task name
+ if (action) {
+ if (action.match(/^([a-z]+)/i))
+ query.task = RegExp.$1;
+ if (action.match(/[^a-z0-9-_]([a-z0-9-_]+)$/i))
+ query.action = RegExp.$1;
+ }
+
+ // remove undefined values
+ for (k in query) {
+ if (query[k] !== undefined && query[k] !== null)
+ param[k] = query[k];
+ }
+
+ return '?' + $.param(param) + querystring;
+ };
+
+ // send a http POST request to the server
+ this.http_post = function(action, postdata)
+ {
+ var url = this.url(action),
+ dt = new Date();
+
+ if (postdata && typeof postdata === 'object')
+ postdata.remote = 1;
+ else
+ postdata += (postdata ? '&' : '') + 'remote=1';
+
+ // send request
+ this.log('HTTP POST: ' + url);
+ this.set_request_time()
+
+ return $.ajax({
+ type: 'POST', url: url, data: postdata, dataType: 'json',
+ success: function(data) { ref.http_response(data); },
+ error: function(o, status, err) { kadm.http_error(o, status, err); }
+ });
+ };
+
+ // handle HTTP response
+ this.http_response = function(response)
+ {
+ var i;
+
+ if (!response)
+ return;
+
+ // set env vars
+ if (response.env)
+ this.set_env(response.env);
+
+ // HTML page elements
+ if (response.objects)
+ for (i in response.objects)
+ $('#'+i).html(response.objects[i]);
+
+ // Update gen. time
+ if (this.env.request_time)
+ $('#request_time').text(((new Date()).getTime() - this.env.request_time)/1000);
+
+ // we have translation labels to add
+ if (typeof response.labels === 'object')
+ this.tdef(response.labels);
+
+ this.set_busy(false);
+
+ // if we get javascript code from server -> execute it
+ if (response.exec)
+ eval(response.exec);
+ };
+
+ // handle HTTP request errors
+ this.http_error = function(request, status, err)
+ {
+ var errmsg = request.statusText;
+
+ this.set_busy(false);
+ request.abort();
+
+ if (request.status && errmsg)
+ this.display_message(this.t('servererror') + ' (' + errmsg + ')', 'error');
+ };
+
+
+ /********************************************************/
+ /********* helper methods *********/
+ /********************************************************/
+
+ // disable/enable all fields of a form
+ this.lock_form = function(form, lock)
+ {
+ if (!form || !form.elements)
+ return;
+
+ var n, len, elm;
+
+ if (lock)
+ this.disabled_form_elements = [];
+
+ for (n=0, len=form.elements.length; n<len; n++) {
+ elm = form.elements[n];
+
+ if (elm.type == 'hidden')
+ continue;
+ // remember which elem was disabled before lock
+ if (lock && elm.disabled)
+ this.disabled_form_elements.push(elm);
+ // check this.disabled_form_elements before inArray() as a workaround for FF5 bug
+ // http://bugs.jquery.com/ticket/9873
+ else if (lock || (this.disabled_form_elements && $.inArray(elm, this.disabled_form_elements)<0))
+ elm.disabled = lock;
+ }
+ };
+
+ this.set_request_time = function()
+ {
+ this.env.request_time = (new Date()).getTime();
+ };
+
+
+ /*********************************************************/
+ /********* client commands *********/
+ /*********************************************************/
+
+ this.main_logout = function()
+ {
+ location.href = '?task=main&action=logout';
+ return false;
+ };
+
+ this.user_info = function(id)
+ {
+ this.http_post('user.info', {id: id});
+ };
+
+};
+
+var kadm = new kolab_admin();
diff --git a/public_html/lib/HTTP/Request2.php b/public_html/lib/HTTP/Request2.php
new file mode 100644
index 0000000..9ff91de
--- /dev/null
+++ b/public_html/lib/HTTP/Request2.php
@@ -0,0 +1,1015 @@
+<?php
+/**
+ * Class representing a HTTP request message
+ *
+ * PHP version 5
+ *
+ * LICENSE:
+ *
+ * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version SVN: $Id: Request2.php 315409 2011-08-24 07:29:23Z avb $
+ * @link http://pear.php.net/package/HTTP_Request2
+ */
+
+/**
+ * A class representing an URL as per RFC 3986.
+ */
+require_once 'Net/URL2.php';
+
+/**
+ * Exception class for HTTP_Request2 package
+ */
+require_once 'HTTP/Request2/Exception.php';
+
+/**
+ * Class representing a HTTP request message
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @version Release: 2.0.0
+ * @link http://tools.ietf.org/html/rfc2616#section-5
+ */
+class HTTP_Request2 implements SplSubject
+{
+ /**#@+
+ * Constants for HTTP request methods
+ *
+ * @link http://tools.ietf.org/html/rfc2616#section-5.1.1
+ */
+ const METHOD_OPTIONS = 'OPTIONS';
+ const METHOD_GET = 'GET';
+ const METHOD_HEAD = 'HEAD';
+ const METHOD_POST = 'POST';
+ const METHOD_PUT = 'PUT';
+ const METHOD_DELETE = 'DELETE';
+ const METHOD_TRACE = 'TRACE';
+ const METHOD_CONNECT = 'CONNECT';
+ /**#@-*/
+
+ /**#@+
+ * Constants for HTTP authentication schemes
+ *
+ * @link http://tools.ietf.org/html/rfc2617
+ */
+ const AUTH_BASIC = 'basic';
+ const AUTH_DIGEST = 'digest';
+ /**#@-*/
+
+ /**
+ * Regular expression used to check for invalid symbols in RFC 2616 tokens
+ * @link http://pear.php.net/bugs/bug.php?id=15630
+ */
+ const REGEXP_INVALID_TOKEN = '![\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]!';
+
+ /**
+ * Regular expression used to check for invalid symbols in cookie strings
+ * @link http://pear.php.net/bugs/bug.php?id=15630
+ * @link http://web.archive.org/web/20080331104521/http://cgi.netscape.com/newsref/std/cookie_spec.html
+ */
+ const REGEXP_INVALID_COOKIE = '/[\s,;]/';
+
+ /**
+ * Fileinfo magic database resource
+ * @var resource
+ * @see detectMimeType()
+ */
+ private static $_fileinfoDb;
+
+ /**
+ * Observers attached to the request (instances of SplObserver)
+ * @var array
+ */
+ protected $observers = array();
+
+ /**
+ * Request URL
+ * @var Net_URL2
+ */
+ protected $url;
+
+ /**
+ * Request method
+ * @var string
+ */
+ protected $method = self::METHOD_GET;
+
+ /**
+ * Authentication data
+ * @var array
+ * @see getAuth()
+ */
+ protected $auth;
+
+ /**
+ * Request headers
+ * @var array
+ */
+ protected $headers = array();
+
+ /**
+ * Configuration parameters
+ * @var array
+ * @see setConfig()
+ */
+ protected $config = array(
+ 'adapter' => 'HTTP_Request2_Adapter_Socket',
+ 'connect_timeout' => 10,
+ 'timeout' => 0,
+ 'use_brackets' => true,
+ 'protocol_version' => '1.1',
+ 'buffer_size' => 16384,
+ 'store_body' => true,
+
+ 'proxy_host' => '',
+ 'proxy_port' => '',
+ 'proxy_user' => '',
+ 'proxy_password' => '',
+ 'proxy_auth_scheme' => self::AUTH_BASIC,
+
+ 'ssl_verify_peer' => true,
+ 'ssl_verify_host' => true,
+ 'ssl_cafile' => null,
+ 'ssl_capath' => null,
+ 'ssl_local_cert' => null,
+ 'ssl_passphrase' => null,
+
+ 'digest_compat_ie' => false,
+
+ 'follow_redirects' => false,
+ 'max_redirects' => 5,
+ 'strict_redirects' => false
+ );
+
+ /**
+ * Last event in request / response handling, intended for observers
+ * @var array
+ * @see getLastEvent()
+ */
+ protected $lastEvent = array(
+ 'name' => 'start',
+ 'data' => null
+ );
+
+ /**
+ * Request body
+ * @var string|resource
+ * @see setBody()
+ */
+ protected $body = '';
+
+ /**
+ * Array of POST parameters
+ * @var array
+ */
+ protected $postParams = array();
+
+ /**
+ * Array of file uploads (for multipart/form-data POST requests)
+ * @var array
+ */
+ protected $uploads = array();
+
+ /**
+ * Adapter used to perform actual HTTP request
+ * @var HTTP_Request2_Adapter
+ */
+ protected $adapter;
+
+ /**
+ * Cookie jar to persist cookies between requests
+ * @var HTTP_Request2_CookieJar
+ */
+ protected $cookieJar = null;
+
+ /**
+ * Constructor. Can set request URL, method and configuration array.
+ *
+ * Also sets a default value for User-Agent header.
+ *
+ * @param string|Net_Url2 Request URL
+ * @param string Request method
+ * @param array Configuration for this Request instance
+ */
+ public function __construct($url = null, $method = self::METHOD_GET, array $config = array())
+ {
+ $this->setConfig($config);
+ if (!empty($url)) {
+ $this->setUrl($url);
+ }
+ if (!empty($method)) {
+ $this->setMethod($method);
+ }
+ $this->setHeader('user-agent', 'HTTP_Request2/2.0.0 ' .
+ '(http://pear.php.net/package/http_request2) ' .
+ 'PHP/' . phpversion());
+ }
+
+ /**
+ * Sets the URL for this request
+ *
+ * If the URL has userinfo part (username & password) these will be removed
+ * and converted to auth data. If the URL does not have a path component,
+ * that will be set to '/'.
+ *
+ * @param string|Net_URL2 Request URL
+ * @return HTTP_Request2
+ * @throws HTTP_Request2_LogicException
+ */
+ public function setUrl($url)
+ {
+ if (is_string($url)) {
+ $url = new Net_URL2(
+ $url, array(Net_URL2::OPTION_USE_BRACKETS => $this->config['use_brackets'])
+ );
+ }
+ if (!$url instanceof Net_URL2) {
+ throw new HTTP_Request2_LogicException(
+ 'Parameter is not a valid HTTP URL',
+ HTTP_Request2_Exception::INVALID_ARGUMENT
+ );
+ }
+ // URL contains username / password?
+ if ($url->getUserinfo()) {
+ $username = $url->getUser();
+ $password = $url->getPassword();
+ $this->setAuth(rawurldecode($username), $password? rawurldecode($password): '');
+ $url->setUserinfo('');
+ }
+ if ('' == $url->getPath()) {
+ $url->setPath('/');
+ }
+ $this->url = $url;
+
+ return $this;
+ }
+
+ /**
+ * Returns the request URL
+ *
+ * @return Net_URL2
+ */
+ public function getUrl()
+ {
+ return $this->url;
+ }
+
+ /**
+ * Sets the request method
+ *
+ * @param string
+ * @return HTTP_Request2
+ * @throws HTTP_Request2_LogicException if the method name is invalid
+ */
+ public function setMethod($method)
+ {
+ // Method name should be a token: http://tools.ietf.org/html/rfc2616#section-5.1.1
+ if (preg_match(self::REGEXP_INVALID_TOKEN, $method)) {
+ throw new HTTP_Request2_LogicException(
+ "Invalid request method '{$method}'",
+ HTTP_Request2_Exception::INVALID_ARGUMENT
+ );
+ }
+ $this->method = $method;
+
+ return $this;
+ }
+
+ /**
+ * Returns the request method
+ *
+ * @return string
+ */
+ public function getMethod()
+ {
+ return $this->method;
+ }
+
+ /**
+ * Sets the configuration parameter(s)
+ *
+ * The following parameters are available:
+ * <ul>
+ * <li> 'adapter' - adapter to use (string)</li>
+ * <li> 'connect_timeout' - Connection timeout in seconds (integer)</li>
+ * <li> 'timeout' - Total number of seconds a request can take.
+ * Use 0 for no limit, should be greater than
+ * 'connect_timeout' if set (integer)</li>
+ * <li> 'use_brackets' - Whether to append [] to array variable names (bool)</li>
+ * <li> 'protocol_version' - HTTP Version to use, '1.0' or '1.1' (string)</li>
+ * <li> 'buffer_size' - Buffer size to use for reading and writing (int)</li>
+ * <li> 'store_body' - Whether to store response body in response object.
+ * Set to false if receiving a huge response and
+ * using an Observer to save it (boolean)</li>
+ * <li> 'proxy_host' - Proxy server host (string)</li>
+ * <li> 'proxy_port' - Proxy server port (integer)</li>
+ * <li> 'proxy_user' - Proxy auth username (string)</li>
+ * <li> 'proxy_password' - Proxy auth password (string)</li>
+ * <li> 'proxy_auth_scheme' - Proxy auth scheme, one of HTTP_Request2::AUTH_* constants (string)</li>
+ * <li> 'ssl_verify_peer' - Whether to verify peer's SSL certificate (bool)</li>
+ * <li> 'ssl_verify_host' - Whether to check that Common Name in SSL
+ * certificate matches host name (bool)</li>
+ * <li> 'ssl_cafile' - Cerificate Authority file to verify the peer
+ * with (use with 'ssl_verify_peer') (string)</li>
+ * <li> 'ssl_capath' - Directory holding multiple Certificate
+ * Authority files (string)</li>
+ * <li> 'ssl_local_cert' - Name of a file containing local cerificate (string)</li>
+ * <li> 'ssl_passphrase' - Passphrase with which local certificate
+ * was encoded (string)</li>
+ * <li> 'digest_compat_ie' - Whether to imitate behaviour of MSIE 5 and 6
+ * in using URL without query string in digest
+ * authentication (boolean)</li>
+ * <li> 'follow_redirects' - Whether to automatically follow HTTP Redirects (boolean)</li>
+ * <li> 'max_redirects' - Maximum number of redirects to follow (integer)</li>
+ * <li> 'strict_redirects' - Whether to keep request method on redirects via status 301 and
+ * 302 (true, needed for compatibility with RFC 2616)
+ * or switch to GET (false, needed for compatibility with most
+ * browsers) (boolean)</li>
+ * </ul>
+ *
+ * @param string|array configuration parameter name or array
+ * ('parameter name' => 'parameter value')
+ * @param mixed parameter value if $nameOrConfig is not an array
+ * @return HTTP_Request2
+ * @throws HTTP_Request2_LogicException If the parameter is unknown
+ */
+ public function setConfig($nameOrConfig, $value = null)
+ {
+ if (is_array($nameOrConfig)) {
+ foreach ($nameOrConfig as $name => $value) {
+ $this->setConfig($name, $value);
+ }
+
+ } else {
+ if (!array_key_exists($nameOrConfig, $this->config)) {
+ throw new HTTP_Request2_LogicException(
+ "Unknown configuration parameter '{$nameOrConfig}'",
+ HTTP_Request2_Exception::INVALID_ARGUMENT
+ );
+ }
+ $this->config[$nameOrConfig] = $value;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns the value(s) of the configuration parameter(s)
+ *
+ * @param string parameter name
+ * @return mixed value of $name parameter, array of all configuration
+ * parameters if $name is not given
+ * @throws HTTP_Request2_LogicException If the parameter is unknown
+ */
+ public function getConfig($name = null)
+ {
+ if (null === $name) {
+ return $this->config;
+ } elseif (!array_key_exists($name, $this->config)) {
+ throw new HTTP_Request2_LogicException(
+ "Unknown configuration parameter '{$name}'",
+ HTTP_Request2_Exception::INVALID_ARGUMENT
+ );
+ }
+ return $this->config[$name];
+ }
+
+ /**
+ * Sets the autentification data
+ *
+ * @param string user name
+ * @param string password
+ * @param string authentication scheme
+ * @return HTTP_Request2
+ */
+ public function setAuth($user, $password = '', $scheme = self::AUTH_BASIC)
+ {
+ if (empty($user)) {
+ $this->auth = null;
+ } else {
+ $this->auth = array(
+ 'user' => (string)$user,
+ 'password' => (string)$password,
+ 'scheme' => $scheme
+ );
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns the authentication data
+ *
+ * The array has the keys 'user', 'password' and 'scheme', where 'scheme'
+ * is one of the HTTP_Request2::AUTH_* constants.
+ *
+ * @return array
+ */
+ public function getAuth()
+ {
+ return $this->auth;
+ }
+
+ /**
+ * Sets request header(s)
+ *
+ * The first parameter may be either a full header string 'header: value' or
+ * header name. In the former case $value parameter is ignored, in the latter
+ * the header's value will either be set to $value or the header will be
+ * removed if $value is null. The first parameter can also be an array of
+ * headers, in that case method will be called recursively.
+ *
+ * Note that headers are treated case insensitively as per RFC 2616.
+ *
+ * <code>
+ * $req->setHeader('Foo: Bar'); // sets the value of 'Foo' header to 'Bar'
+ * $req->setHeader('FoO', 'Baz'); // sets the value of 'Foo' header to 'Baz'
+ * $req->setHeader(array('foo' => 'Quux')); // sets the value of 'Foo' header to 'Quux'
+ * $req->setHeader('FOO'); // removes 'Foo' header from request
+ * </code>
+ *
+ * @param string|array header name, header string ('Header: value')
+ * or an array of headers
+ * @param string|array|null header value if $name is not an array,
+ * header will be removed if value is null
+ * @param bool whether to replace previous header with the
+ * same name or append to its value
+ * @return HTTP_Request2
+ * @throws HTTP_Request2_LogicException
+ */
+ public function setHeader($name, $value = null, $replace = true)
+ {
+ if (is_array($name)) {
+ foreach ($name as $k => $v) {
+ if (is_string($k)) {
+ $this->setHeader($k, $v, $replace);
+ } else {
+ $this->setHeader($v, null, $replace);
+ }
+ }
+ } else {
+ if (null === $value && strpos($name, ':')) {
+ list($name, $value) = array_map('trim', explode(':', $name, 2));
+ }
+ // Header name should be a token: http://tools.ietf.org/html/rfc2616#section-4.2
+ if (preg_match(self::REGEXP_INVALID_TOKEN, $name)) {
+ throw new HTTP_Request2_LogicException(
+ "Invalid header name '{$name}'",
+ HTTP_Request2_Exception::INVALID_ARGUMENT
+ );
+ }
+ // Header names are case insensitive anyway
+ $name = strtolower($name);
+ if (null === $value) {
+ unset($this->headers[$name]);
+
+ } else {
+ if (is_array($value)) {
+ $value = implode(', ', array_map('trim', $value));
+ } elseif (is_string($value)) {
+ $value = trim($value);
+ }
+ if (!isset($this->headers[$name]) || $replace) {
+ $this->headers[$name] = $value;
+ } else {
+ $this->headers[$name] .= ', ' . $value;
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns the request headers
+ *
+ * The array is of the form ('header name' => 'header value'), header names
+ * are lowercased
+ *
+ * @return array
+ */
+ public function getHeaders()
+ {
+ return $this->headers;
+ }
+
+ /**
+ * Adds a cookie to the request
+ *
+ * If the request does not have a CookieJar object set, this method simply
+ * appends a cookie to "Cookie:" header.
+ *
+ * If a CookieJar object is available, the cookie is stored in that object.
+ * Data from request URL will be used for setting its 'domain' and 'path'
+ * parameters, 'expires' and 'secure' will be set to null and false,
+ * respectively. If you need further control, use CookieJar's methods.
+ *
+ * @param string cookie name
+ * @param string cookie value
+ * @return HTTP_Request2
+ * @throws HTTP_Request2_LogicException
+ * @see setCookieJar()
+ */
+ public function addCookie($name, $value)
+ {
+ if (!empty($this->cookieJar)) {
+ $this->cookieJar->store(array('name' => $name, 'value' => $value),
+ $this->url);
+
+ } else {
+ $cookie = $name . '=' . $value;
+ if (preg_match(self::REGEXP_INVALID_COOKIE, $cookie)) {
+ throw new HTTP_Request2_LogicException(
+ "Invalid cookie: '{$cookie}'",
+ HTTP_Request2_Exception::INVALID_ARGUMENT
+ );
+ }
+ $cookies = empty($this->headers['cookie'])? '': $this->headers['cookie'] . '; ';
+ $this->setHeader('cookie', $cookies . $cookie);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Sets the request body
+ *
+ * If you provide file pointer rather than file name, it should support
+ * fstat() and rewind() operations.
+ *
+ * @param string|resource|HTTP_Request2_MultipartBody Either a string
+ * with the body or filename containing body or pointer to
+ * an open file or object with multipart body data
+ * @param bool Whether first parameter is a filename
+ * @return HTTP_Request2
+ * @throws HTTP_Request2_LogicException
+ */
+ public function setBody($body, $isFilename = false)
+ {
+ if (!$isFilename && !is_resource($body)) {
+ if (!$body instanceof HTTP_Request2_MultipartBody) {
+ $this->body = (string)$body;
+ } else {
+ $this->body = $body;
+ }
+ } else {
+ $fileData = $this->fopenWrapper($body, empty($this->headers['content-type']));
+ $this->body = $fileData['fp'];
+ if (empty($this->headers['content-type'])) {
+ $this->setHeader('content-type', $fileData['type']);
+ }
+ }
+ $this->postParams = $this->uploads = array();
+
+ return $this;
+ }
+
+ /**
+ * Returns the request body
+ *
+ * @return string|resource|HTTP_Request2_MultipartBody
+ */
+ public function getBody()
+ {
+ if (self::METHOD_POST == $this->method &&
+ (!empty($this->postParams) || !empty($this->uploads))
+ ) {
+ if (0 === strpos($this->headers['content-type'], 'application/x-www-form-urlencoded')) {
+ $body = http_build_query($this->postParams, '', '&');
+ if (!$this->getConfig('use_brackets')) {
+ $body = preg_replace('/%5B\d+%5D=/', '=', $body);
+ }
+ // support RFC 3986 by not encoding '~' symbol (request #15368)
+ return str_replace('%7E', '~', $body);
+
+ } elseif (0 === strpos($this->headers['content-type'], 'multipart/form-data')) {
+ require_once 'HTTP/Request2/MultipartBody.php';
+ return new HTTP_Request2_MultipartBody(
+ $this->postParams, $this->uploads, $this->getConfig('use_brackets')
+ );
+ }
+ }
+ return $this->body;
+ }
+
+ /**
+ * Adds a file to form-based file upload
+ *
+ * Used to emulate file upload via a HTML form. The method also sets
+ * Content-Type of HTTP request to 'multipart/form-data'.
+ *
+ * If you just want to send the contents of a file as the body of HTTP
+ * request you should use setBody() method.
+ *
+ * If you provide file pointers rather than file names, they should support
+ * fstat() and rewind() operations.
+ *
+ * @param string name of file-upload field
+ * @param string|resource|array full name of local file, pointer to
+ * open file or an array of files
+ * @param string filename to send in the request
+ * @param string content-type of file being uploaded
+ * @return HTTP_Request2
+ * @throws HTTP_Request2_LogicException
+ */
+ public function addUpload($fieldName, $filename, $sendFilename = null,
+ $contentType = null)
+ {
+ if (!is_array($filename)) {
+ $fileData = $this->fopenWrapper($filename, empty($contentType));
+ $this->uploads[$fieldName] = array(
+ 'fp' => $fileData['fp'],
+ 'filename' => !empty($sendFilename)? $sendFilename
+ :(is_string($filename)? basename($filename): 'anonymous.blob') ,
+ 'size' => $fileData['size'],
+ 'type' => empty($contentType)? $fileData['type']: $contentType
+ );
+ } else {
+ $fps = $names = $sizes = $types = array();
+ foreach ($filename as $f) {
+ if (!is_array($f)) {
+ $f = array($f);
+ }
+ $fileData = $this->fopenWrapper($f[0], empty($f[2]));
+ $fps[] = $fileData['fp'];
+ $names[] = !empty($f[1])? $f[1]
+ :(is_string($f[0])? basename($f[0]): 'anonymous.blob');
+ $sizes[] = $fileData['size'];
+ $types[] = empty($f[2])? $fileData['type']: $f[2];
+ }
+ $this->uploads[$fieldName] = array(
+ 'fp' => $fps, 'filename' => $names, 'size' => $sizes, 'type' => $types
+ );
+ }
+ if (empty($this->headers['content-type']) ||
+ 'application/x-www-form-urlencoded' == $this->headers['content-type']
+ ) {
+ $this->setHeader('content-type', 'multipart/form-data');
+ }
+
+ return $this;
+ }
+
+ /**
+ * Adds POST parameter(s) to the request.
+ *
+ * @param string|array parameter name or array ('name' => 'value')
+ * @param mixed parameter value (can be an array)
+ * @return HTTP_Request2
+ */
+ public function addPostParameter($name, $value = null)
+ {
+ if (!is_array($name)) {
+ $this->postParams[$name] = $value;
+ } else {
+ foreach ($name as $k => $v) {
+ $this->addPostParameter($k, $v);
+ }
+ }
+ if (empty($this->headers['content-type'])) {
+ $this->setHeader('content-type', 'application/x-www-form-urlencoded');
+ }
+
+ return $this;
+ }
+
+ /**
+ * Attaches a new observer
+ *
+ * @param SplObserver
+ */
+ public function attach(SplObserver $observer)
+ {
+ foreach ($this->observers as $attached) {
+ if ($attached === $observer) {
+ return;
+ }
+ }
+ $this->observers[] = $observer;
+ }
+
+ /**
+ * Detaches an existing observer
+ *
+ * @param SplObserver
+ */
+ public function detach(SplObserver $observer)
+ {
+ foreach ($this->observers as $key => $attached) {
+ if ($attached === $observer) {
+ unset($this->observers[$key]);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Notifies all observers
+ */
+ public function notify()
+ {
+ foreach ($this->observers as $observer) {
+ $observer->update($this);
+ }
+ }
+
+ /**
+ * Sets the last event
+ *
+ * Adapters should use this method to set the current state of the request
+ * and notify the observers.
+ *
+ * @param string event name
+ * @param mixed event data
+ */
+ public function setLastEvent($name, $data = null)
+ {
+ $this->lastEvent = array(
+ 'name' => $name,
+ 'data' => $data
+ );
+ $this->notify();
+ }
+
+ /**
+ * Returns the last event
+ *
+ * Observers should use this method to access the last change in request.
+ * The following event names are possible:
+ * <ul>
+ * <li>'connect' - after connection to remote server,
+ * data is the destination (string)</li>
+ * <li>'disconnect' - after disconnection from server</li>
+ * <li>'sentHeaders' - after sending the request headers,
+ * data is the headers sent (string)</li>
+ * <li>'sentBodyPart' - after sending a part of the request body,
+ * data is the length of that part (int)</li>
+ * <li>'sentBody' - after sending the whole request body,
+ * data is request body length (int)</li>
+ * <li>'receivedHeaders' - after receiving the response headers,
+ * data is HTTP_Request2_Response object</li>
+ * <li>'receivedBodyPart' - after receiving a part of the response
+ * body, data is that part (string)</li>
+ * <li>'receivedEncodedBodyPart' - as 'receivedBodyPart', but data is still
+ * encoded by Content-Encoding</li>
+ * <li>'receivedBody' - after receiving the complete response
+ * body, data is HTTP_Request2_Response object</li>
+ * </ul>
+ * Different adapters may not send all the event types. Mock adapter does
+ * not send any events to the observers.
+ *
+ * @return array The array has two keys: 'name' and 'data'
+ */
+ public function getLastEvent()
+ {
+ return $this->lastEvent;
+ }
+
+ /**
+ * Sets the adapter used to actually perform the request
+ *
+ * You can pass either an instance of a class implementing HTTP_Request2_Adapter
+ * or a class name. The method will only try to include a file if the class
+ * name starts with HTTP_Request2_Adapter_, it will also try to prepend this
+ * prefix to the class name if it doesn't contain any underscores, so that
+ * <code>
+ * $request->setAdapter('curl');
+ * </code>
+ * will work.
+ *
+ * @param string|HTTP_Request2_Adapter
+ * @return HTTP_Request2
+ * @throws HTTP_Request2_LogicException
+ */
+ public function setAdapter($adapter)
+ {
+ if (is_string($adapter)) {
+ if (!class_exists($adapter, false)) {
+ if (false === strpos($adapter, '_')) {
+ $adapter = 'HTTP_Request2_Adapter_' . ucfirst($adapter);
+ }
+ if (preg_match('/^HTTP_Request2_Adapter_([a-zA-Z0-9]+)$/', $adapter)) {
+ include_once str_replace('_', DIRECTORY_SEPARATOR, $adapter) . '.php';
+ }
+ if (!class_exists($adapter, false)) {
+ throw new HTTP_Request2_LogicException(
+ "Class {$adapter} not found",
+ HTTP_Request2_Exception::MISSING_VALUE
+ );
+ }
+ }
+ $adapter = new $adapter;
+ }
+ if (!$adapter instanceof HTTP_Request2_Adapter) {
+ throw new HTTP_Request2_LogicException(
+ 'Parameter is not a HTTP request adapter',
+ HTTP_Request2_Exception::INVALID_ARGUMENT
+ );
+ }
+ $this->adapter = $adapter;
+
+ return $this;
+ }
+
+ /**
+ * Sets the cookie jar
+ *
+ * A cookie jar is used to maintain cookies across HTTP requests and
+ * responses. Cookies from jar will be automatically added to the request
+ * headers based on request URL.
+ *
+ * @param HTTP_Request2_CookieJar|bool Existing CookieJar object, true to
+ * create a new one, false to remove
+ */
+ public function setCookieJar($jar = true)
+ {
+ if (!class_exists('HTTP_Request2_CookieJar', false)) {
+ require_once 'HTTP/Request2/CookieJar.php';
+ }
+
+ if ($jar instanceof HTTP_Request2_CookieJar) {
+ $this->cookieJar = $jar;
+ } elseif (true === $jar) {
+ $this->cookieJar = new HTTP_Request2_CookieJar();
+ } elseif (!$jar) {
+ $this->cookieJar = null;
+ } else {
+ throw new HTTP_Request2_LogicException(
+ 'Invalid parameter passed to setCookieJar()',
+ HTTP_Request2_Exception::INVALID_ARGUMENT
+ );
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns current CookieJar object or null if none
+ *
+ * @return HTTP_Request2_CookieJar|null
+ */
+ public function getCookieJar()
+ {
+ return $this->cookieJar;
+ }
+
+ /**
+ * Sends the request and returns the response
+ *
+ * @throws HTTP_Request2_Exception
+ * @return HTTP_Request2_Response
+ */
+ public function send()
+ {
+ // Sanity check for URL
+ if (!$this->url instanceof Net_URL2
+ || !$this->url->isAbsolute()
+ || !in_array(strtolower($this->url->getScheme()), array('https', 'http'))
+ ) {
+ throw new HTTP_Request2_LogicException(
+ 'HTTP_Request2 needs an absolute HTTP(S) request URL, '
+ . ($this->url instanceof Net_URL2
+ ? "'" . $this->url->__toString() . "'" : 'none')
+ . ' given',
+ HTTP_Request2_Exception::INVALID_ARGUMENT
+ );
+ }
+ if (empty($this->adapter)) {
+ $this->setAdapter($this->getConfig('adapter'));
+ }
+ // magic_quotes_runtime may break file uploads and chunked response
+ // processing; see bug #4543. Don't use ini_get() here; see bug #16440.
+ if ($magicQuotes = get_magic_quotes_runtime()) {
+ set_magic_quotes_runtime(false);
+ }
+ // force using single byte encoding if mbstring extension overloads
+ // strlen() and substr(); see bug #1781, bug #10605
+ if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) {
+ $oldEncoding = mb_internal_encoding();
+ mb_internal_encoding('iso-8859-1');
+ }
+
+ try {
+ $response = $this->adapter->sendRequest($this);
+ } catch (Exception $e) {
+ }
+ // cleanup in either case (poor man's "finally" clause)
+ if ($magicQuotes) {
+ set_magic_quotes_runtime(true);
+ }
+ if (!empty($oldEncoding)) {
+ mb_internal_encoding($oldEncoding);
+ }
+ // rethrow the exception
+ if (!empty($e)) {
+ throw $e;
+ }
+ return $response;
+ }
+
+ /**
+ * Wrapper around fopen()/fstat() used by setBody() and addUpload()
+ *
+ * @param string|resource file name or pointer to open file
+ * @param bool whether to try autodetecting MIME type of file,
+ * will only work if $file is a filename, not pointer
+ * @return array array('fp' => file pointer, 'size' => file size, 'type' => MIME type)
+ * @throws HTTP_Request2_LogicException
+ */
+ protected function fopenWrapper($file, $detectType = false)
+ {
+ if (!is_string($file) && !is_resource($file)) {
+ throw new HTTP_Request2_LogicException(
+ "Filename or file pointer resource expected",
+ HTTP_Request2_Exception::INVALID_ARGUMENT
+ );
+ }
+ $fileData = array(
+ 'fp' => is_string($file)? null: $file,
+ 'type' => 'application/octet-stream',
+ 'size' => 0
+ );
+ if (is_string($file)) {
+ $track = @ini_set('track_errors', 1);
+ if (!($fileData['fp'] = @fopen($file, 'rb'))) {
+ $e = new HTTP_Request2_LogicException(
+ $php_errormsg, HTTP_Request2_Exception::READ_ERROR
+ );
+ }
+ @ini_set('track_errors', $track);
+ if (isset($e)) {
+ throw $e;
+ }
+ if ($detectType) {
+ $fileData['type'] = self::detectMimeType($file);
+ }
+ }
+ if (!($stat = fstat($fileData['fp']))) {
+ throw new HTTP_Request2_LogicException(
+ "fstat() call failed", HTTP_Request2_Exception::READ_ERROR
+ );
+ }
+ $fileData['size'] = $stat['size'];
+
+ return $fileData;
+ }
+
+ /**
+ * Tries to detect MIME type of a file
+ *
+ * The method will try to use fileinfo extension if it is available,
+ * deprecated mime_content_type() function in the other case. If neither
+ * works, default 'application/octet-stream' MIME type is returned
+ *
+ * @param string filename
+ * @return string file MIME type
+ */
+ protected static function detectMimeType($filename)
+ {
+ // finfo extension from PECL available
+ if (function_exists('finfo_open')) {
+ if (!isset(self::$_fileinfoDb)) {
+ self::$_fileinfoDb = @finfo_open(FILEINFO_MIME);
+ }
+ if (self::$_fileinfoDb) {
+ $info = finfo_file(self::$_fileinfoDb, $filename);
+ }
+ }
+ // (deprecated) mime_content_type function available
+ if (empty($info) && function_exists('mime_content_type')) {
+ return mime_content_type($filename);
+ }
+ return empty($info)? 'application/octet-stream': $info;
+ }
+}
+?> \ No newline at end of file
diff --git a/public_html/lib/HTTP/Request2/Adapter.php b/public_html/lib/HTTP/Request2/Adapter.php
new file mode 100644
index 0000000..56d81a9
--- /dev/null
+++ b/public_html/lib/HTTP/Request2/Adapter.php
@@ -0,0 +1,154 @@
+<?php
+/**
+ * Base class for HTTP_Request2 adapters
+ *
+ * PHP version 5
+ *
+ * LICENSE:
+ *
+ * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version SVN: $Id: Adapter.php 308322 2011-02-14 13:58:03Z avb $
+ * @link http://pear.php.net/package/HTTP_Request2
+ */
+
+/**
+ * Class representing a HTTP response
+ */
+require_once 'HTTP/Request2/Response.php';
+
+/**
+ * Base class for HTTP_Request2 adapters
+ *
+ * HTTP_Request2 class itself only defines methods for aggregating the request
+ * data, all actual work of sending the request to the remote server and
+ * receiving its response is performed by adapters.
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @version Release: 2.0.0
+ */
+abstract class HTTP_Request2_Adapter
+{
+ /**
+ * A list of methods that MUST NOT have a request body, per RFC 2616
+ * @var array
+ */
+ protected static $bodyDisallowed = array('TRACE');
+
+ /**
+ * Methods having defined semantics for request body
+ *
+ * Content-Length header (indicating that the body follows, section 4.3 of
+ * RFC 2616) will be sent for these methods even if no body was added
+ *
+ * @var array
+ * @link http://pear.php.net/bugs/bug.php?id=12900
+ * @link http://pear.php.net/bugs/bug.php?id=14740
+ */
+ protected static $bodyRequired = array('POST', 'PUT');
+
+ /**
+ * Request being sent
+ * @var HTTP_Request2
+ */
+ protected $request;
+
+ /**
+ * Request body
+ * @var string|resource|HTTP_Request2_MultipartBody
+ * @see HTTP_Request2::getBody()
+ */
+ protected $requestBody;
+
+ /**
+ * Length of the request body
+ * @var integer
+ */
+ protected $contentLength;
+
+ /**
+ * Sends request to the remote server and returns its response
+ *
+ * @param HTTP_Request2
+ * @return HTTP_Request2_Response
+ * @throws HTTP_Request2_Exception
+ */
+ abstract public function sendRequest(HTTP_Request2 $request);
+
+ /**
+ * Calculates length of the request body, adds proper headers
+ *
+ * @param array associative array of request headers, this method will
+ * add proper 'Content-Length' and 'Content-Type' headers
+ * to this array (or remove them if not needed)
+ */
+ protected function calculateRequestLength(&$headers)
+ {
+ $this->requestBody = $this->request->getBody();
+
+ if (is_string($this->requestBody)) {
+ $this->contentLength = strlen($this->requestBody);
+ } elseif (is_resource($this->requestBody)) {
+ $stat = fstat($this->requestBody);
+ $this->contentLength = $stat['size'];
+ rewind($this->requestBody);
+ } else {
+ $this->contentLength = $this->requestBody->getLength();
+ $headers['content-type'] = 'multipart/form-data; boundary=' .
+ $this->requestBody->getBoundary();
+ $this->requestBody->rewind();
+ }
+
+ if (in_array($this->request->getMethod(), self::$bodyDisallowed) ||
+ 0 == $this->contentLength
+ ) {
+ // No body: send a Content-Length header nonetheless (request #12900),
+ // but do that only for methods that require a body (bug #14740)
+ if (in_array($this->request->getMethod(), self::$bodyRequired)) {
+ $headers['content-length'] = 0;
+ } else {
+ unset($headers['content-length']);
+ // if the method doesn't require a body and doesn't have a
+ // body, don't send a Content-Type header. (request #16799)
+ unset($headers['content-type']);
+ }
+ } else {
+ if (empty($headers['content-type'])) {
+ $headers['content-type'] = 'application/x-www-form-urlencoded';
+ }
+ $headers['content-length'] = $this->contentLength;
+ }
+ }
+}
+?>
diff --git a/public_html/lib/HTTP/Request2/Adapter/Curl.php b/public_html/lib/HTTP/Request2/Adapter/Curl.php
new file mode 100644
index 0000000..82d227f
--- /dev/null
+++ b/public_html/lib/HTTP/Request2/Adapter/Curl.php
@@ -0,0 +1,560 @@
+<?php
+/**
+ * Adapter for HTTP_Request2 wrapping around cURL extension
+ *
+ * PHP version 5
+ *
+ * LICENSE:
+ *
+ * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version SVN: $Id: Curl.php 310800 2011-05-06 07:29:56Z avb $
+ * @link http://pear.php.net/package/HTTP_Request2
+ */
+
+/**
+ * Base class for HTTP_Request2 adapters
+ */
+require_once 'HTTP/Request2/Adapter.php';
+
+/**
+ * Adapter for HTTP_Request2 wrapping around cURL extension
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @version Release: 2.0.0
+ */
+class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
+{
+ /**
+ * Mapping of header names to cURL options
+ * @var array
+ */
+ protected static $headerMap = array(
+ 'accept-encoding' => CURLOPT_ENCODING,
+ 'cookie' => CURLOPT_COOKIE,
+ 'referer' => CURLOPT_REFERER,
+ 'user-agent' => CURLOPT_USERAGENT
+ );
+
+ /**
+ * Mapping of SSL context options to cURL options
+ * @var array
+ */
+ protected static $sslContextMap = array(
+ 'ssl_verify_peer' => CURLOPT_SSL_VERIFYPEER,
+ 'ssl_cafile' => CURLOPT_CAINFO,
+ 'ssl_capath' => CURLOPT_CAPATH,
+ 'ssl_local_cert' => CURLOPT_SSLCERT,
+ 'ssl_passphrase' => CURLOPT_SSLCERTPASSWD
+ );
+
+ /**
+ * Mapping of CURLE_* constants to Exception subclasses and error codes
+ * @var array
+ */
+ protected static $errorMap = array(
+ CURLE_UNSUPPORTED_PROTOCOL => array('HTTP_Request2_MessageException',
+ HTTP_Request2_Exception::NON_HTTP_REDIRECT),
+ CURLE_COULDNT_RESOLVE_PROXY => array('HTTP_Request2_ConnectionException'),
+ CURLE_COULDNT_RESOLVE_HOST => array('HTTP_Request2_ConnectionException'),
+ CURLE_COULDNT_CONNECT => array('HTTP_Request2_ConnectionException'),
+ // error returned from write callback
+ CURLE_WRITE_ERROR => array('HTTP_Request2_MessageException',
+ HTTP_Request2_Exception::NON_HTTP_REDIRECT),
+ CURLE_OPERATION_TIMEOUTED => array('HTTP_Request2_MessageException',
+ HTTP_Request2_Exception::TIMEOUT),
+ CURLE_HTTP_RANGE_ERROR => array('HTTP_Request2_MessageException'),
+ CURLE_SSL_CONNECT_ERROR => array('HTTP_Request2_ConnectionException'),
+ CURLE_LIBRARY_NOT_FOUND => array('HTTP_Request2_LogicException',
+ HTTP_Request2_Exception::MISCONFIGURATION),
+ CURLE_FUNCTION_NOT_FOUND => array('HTTP_Request2_LogicException',
+ HTTP_Request2_Exception::MISCONFIGURATION),
+ CURLE_ABORTED_BY_CALLBACK => array('HTTP_Request2_MessageException',
+ HTTP_Request2_Exception::NON_HTTP_REDIRECT),
+ CURLE_TOO_MANY_REDIRECTS => array('HTTP_Request2_MessageException',
+ HTTP_Request2_Exception::TOO_MANY_REDIRECTS),
+ CURLE_SSL_PEER_CERTIFICATE => array('HTTP_Request2_ConnectionException'),
+ CURLE_GOT_NOTHING => array('HTTP_Request2_MessageException'),
+ CURLE_SSL_ENGINE_NOTFOUND => array('HTTP_Request2_LogicException',
+ HTTP_Request2_Exception::MISCONFIGURATION),
+ CURLE_SSL_ENGINE_SETFAILED => array('HTTP_Request2_LogicException',
+ HTTP_Request2_Exception::MISCONFIGURATION),
+ CURLE_SEND_ERROR => array('HTTP_Request2_MessageException'),
+ CURLE_RECV_ERROR => array('HTTP_Request2_MessageException'),
+ CURLE_SSL_CERTPROBLEM => array('HTTP_Request2_LogicException',
+ HTTP_Request2_Exception::INVALID_ARGUMENT),
+ CURLE_SSL_CIPHER => array('HTTP_Request2_ConnectionException'),
+ CURLE_SSL_CACERT => array('HTTP_Request2_ConnectionException'),
+ CURLE_BAD_CONTENT_ENCODING => array('HTTP_Request2_MessageException'),
+ );
+
+ /**
+ * Response being received
+ * @var HTTP_Request2_Response
+ */
+ protected $response;
+
+ /**
+ * Whether 'sentHeaders' event was sent to observers
+ * @var boolean
+ */
+ protected $eventSentHeaders = false;
+
+ /**
+ * Whether 'receivedHeaders' event was sent to observers
+ * @var boolean
+ */
+ protected $eventReceivedHeaders = false;
+
+ /**
+ * Position within request body
+ * @var integer
+ * @see callbackReadBody()
+ */
+ protected $position = 0;
+
+ /**
+ * Information about last transfer, as returned by curl_getinfo()
+ * @var array
+ */
+ protected $lastInfo;
+
+ /**
+ * Creates a subclass of HTTP_Request2_Exception from curl error data
+ *
+ * @param resource curl handle
+ * @return HTTP_Request2_Exception
+ */
+ protected static function wrapCurlError($ch)
+ {
+ $nativeCode = curl_errno($ch);
+ $message = 'Curl error: ' . curl_error($ch);
+ if (!isset(self::$errorMap[$nativeCode])) {
+ return new HTTP_Request2_Exception($message, 0, $nativeCode);
+ } else {
+ $class = self::$errorMap[$nativeCode][0];
+ $code = empty(self::$errorMap[$nativeCode][1])
+ ? 0 : self::$errorMap[$nativeCode][1];
+ return new $class($message, $code, $nativeCode);
+ }
+ }
+
+ /**
+ * Sends request to the remote server and returns its response
+ *
+ * @param HTTP_Request2
+ * @return HTTP_Request2_Response
+ * @throws HTTP_Request2_Exception
+ */
+ public function sendRequest(HTTP_Request2 $request)
+ {
+ if (!extension_loaded('curl')) {
+ throw new HTTP_Request2_LogicException(
+ 'cURL extension not available', HTTP_Request2_Exception::MISCONFIGURATION
+ );
+ }
+
+ $this->request = $request;
+ $this->response = null;
+ $this->position = 0;
+ $this->eventSentHeaders = false;
+ $this->eventReceivedHeaders = false;
+
+ try {
+ if (false === curl_exec($ch = $this->createCurlHandle())) {
+ $e = self::wrapCurlError($ch);
+ }
+ } catch (Exception $e) {
+ }
+ if (isset($ch)) {
+ $this->lastInfo = curl_getinfo($ch);
+ curl_close($ch);
+ }
+
+ $response = $this->response;
+ unset($this->request, $this->requestBody, $this->response);
+
+ if (!empty($e)) {
+ throw $e;
+ }
+
+ if ($jar = $request->getCookieJar()) {
+ $jar->addCookiesFromResponse($response, $request->getUrl());
+ }
+
+ if (0 < $this->lastInfo['size_download']) {
+ $request->setLastEvent('receivedBody', $response);
+ }
+ return $response;
+ }
+
+ /**
+ * Returns information about last transfer
+ *
+ * @return array associative array as returned by curl_getinfo()
+ */
+ public function getInfo()
+ {
+ return $this->lastInfo;
+ }
+
+ /**
+ * Creates a new cURL handle and populates it with data from the request
+ *
+ * @return resource a cURL handle, as created by curl_init()
+ * @throws HTTP_Request2_LogicException
+ */
+ protected function createCurlHandle()
+ {
+ $ch = curl_init();
+
+ curl_setopt_array($ch, array(
+ // setup write callbacks
+ CURLOPT_HEADERFUNCTION => array($this, 'callbackWriteHeader'),
+ CURLOPT_WRITEFUNCTION => array($this, 'callbackWriteBody'),
+ // buffer size
+ CURLOPT_BUFFERSIZE => $this->request->getConfig('buffer_size'),
+ // connection timeout
+ CURLOPT_CONNECTTIMEOUT => $this->request->getConfig('connect_timeout'),
+ // save full outgoing headers, in case someone is interested
+ CURLINFO_HEADER_OUT => true,
+ // request url
+ CURLOPT_URL => $this->request->getUrl()->getUrl()
+ ));
+
+ // set up redirects
+ if (!$this->request->getConfig('follow_redirects')) {
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
+ } else {
+ if (!@curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true)) {
+ throw new HTTP_Request2_LogicException(
+ 'Redirect support in curl is unavailable due to open_basedir or safe_mode setting',
+ HTTP_Request2_Exception::MISCONFIGURATION
+ );
+ }
+ curl_setopt($ch, CURLOPT_MAXREDIRS, $this->request->getConfig('max_redirects'));
+ // limit redirects to http(s), works in 5.2.10+
+ if (defined('CURLOPT_REDIR_PROTOCOLS')) {
+ curl_setopt($ch, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
+ }
+ // works in 5.3.2+, http://bugs.php.net/bug.php?id=49571
+ if ($this->request->getConfig('strict_redirects') && defined('CURLOPT_POSTREDIR')) {
+ curl_setopt($ch, CURLOPT_POSTREDIR, 3);
+ }
+ }
+
+ // request timeout
+ if ($timeout = $this->request->getConfig('timeout')) {
+ curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
+ }
+
+ // set HTTP version
+ switch ($this->request->getConfig('protocol_version')) {
+ case '1.0':
+ curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ break;
+ case '1.1':
+ curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ }
+
+ // set request method
+ switch ($this->request->getMethod()) {
+ case HTTP_Request2::METHOD_GET:
+ curl_setopt($ch, CURLOPT_HTTPGET, true);
+ break;
+ case HTTP_Request2::METHOD_POST:
+ curl_setopt($ch, CURLOPT_POST, true);
+ break;
+ case HTTP_Request2::METHOD_HEAD:
+ curl_setopt($ch, CURLOPT_NOBODY, true);
+ break;
+ case HTTP_Request2::METHOD_PUT:
+ curl_setopt($ch, CURLOPT_UPLOAD, true);
+ break;
+ default:
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->request->getMethod());
+ }
+
+ // set proxy, if needed
+ if ($host = $this->request->getConfig('proxy_host')) {
+ if (!($port = $this->request->getConfig('proxy_port'))) {
+ throw new HTTP_Request2_LogicException(
+ 'Proxy port not provided', HTTP_Request2_Exception::MISSING_VALUE
+ );
+ }
+ curl_setopt($ch, CURLOPT_PROXY, $host . ':' . $port);
+ if ($user = $this->request->getConfig('proxy_user')) {
+ curl_setopt($ch, CURLOPT_PROXYUSERPWD, $user . ':' .
+ $this->request->getConfig('proxy_password'));
+ switch ($this->request->getConfig('proxy_auth_scheme')) {
+ case HTTP_Request2::AUTH_BASIC:
+ curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
+ break;
+ case HTTP_Request2::AUTH_DIGEST:
+ curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
+ }
+ }
+ }
+
+ // set authentication data
+ if ($auth = $this->request->getAuth()) {
+ curl_setopt($ch, CURLOPT_USERPWD, $auth['user'] . ':' . $auth['password']);
+ switch ($auth['scheme']) {
+ case HTTP_Request2::AUTH_BASIC:
+ curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+ break;
+ case HTTP_Request2::AUTH_DIGEST:
+ curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
+ }
+ }
+
+ // set SSL options
+ foreach ($this->request->getConfig() as $name => $value) {
+ if ('ssl_verify_host' == $name && null !== $value) {
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $value? 2: 0);
+ } elseif (isset(self::$sslContextMap[$name]) && null !== $value) {
+ curl_setopt($ch, self::$sslContextMap[$name], $value);
+ }
+ }
+
+ $headers = $this->request->getHeaders();
+ // make cURL automagically send proper header
+ if (!isset($headers['accept-encoding'])) {
+ $headers['accept-encoding'] = '';
+ }
+
+ if (($jar = $this->request->getCookieJar())
+ && ($cookies = $jar->getMatching($this->request->getUrl(), true))
+ ) {
+ $headers['cookie'] = (empty($headers['cookie'])? '': $headers['cookie'] . '; ') . $cookies;
+ }
+
+ // set headers having special cURL keys
+ foreach (self::$headerMap as $name => $option) {
+ if (isset($headers[$name])) {
+ curl_setopt($ch, $option, $headers[$name]);
+ unset($headers[$name]);
+ }
+ }
+
+ $this->calculateRequestLength($headers);
+ if (isset($headers['content-length'])) {
+ $this->workaroundPhpBug47204($ch, $headers);
+ }
+
+ // set headers not having special keys
+ $headersFmt = array();
+ foreach ($headers as $name => $value) {
+ $canonicalName = implode('-', array_map('ucfirst', explode('-', $name)));
+ $headersFmt[] = $canonicalName . ': ' . $value;
+ }
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headersFmt);
+
+ return $ch;
+ }
+
+ /**
+ * Workaround for PHP bug #47204 that prevents rewinding request body
+ *
+ * The workaround consists of reading the entire request body into memory
+ * and setting it as CURLOPT_POSTFIELDS, so it isn't recommended for large
+ * file uploads, use Socket adapter instead.
+ *
+ * @param resource cURL handle
+ * @param array Request headers
+ */
+ protected function workaroundPhpBug47204($ch, &$headers)
+ {
+ // no redirects, no digest auth -> probably no rewind needed
+ if (!$this->request->getConfig('follow_redirects')
+ && (!($auth = $this->request->getAuth())
+ || HTTP_Request2::AUTH_DIGEST != $auth['scheme'])
+ ) {
+ curl_setopt($ch, CURLOPT_READFUNCTION, array($this, 'callbackReadBody'));
+
+ // rewind may be needed, read the whole body into memory
+ } else {
+ if ($this->requestBody instanceof HTTP_Request2_MultipartBody) {
+ $this->requestBody = $this->requestBody->__toString();
+
+ } elseif (is_resource($this->requestBody)) {
+ $fp = $this->requestBody;
+ $this->requestBody = '';
+ while (!feof($fp)) {
+ $this->requestBody .= fread($fp, 16384);
+ }
+ }
+ // curl hangs up if content-length is present
+ unset($headers['content-length']);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $this->requestBody);
+ }
+ }
+
+ /**
+ * Callback function called by cURL for reading the request body
+ *
+ * @param resource cURL handle
+ * @param resource file descriptor (not used)
+ * @param integer maximum length of data to return
+ * @return string part of the request body, up to $length bytes
+ */
+ protected function callbackReadBody($ch, $fd, $length)
+ {
+ if (!$this->eventSentHeaders) {
+ $this->request->setLastEvent(
+ 'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT)
+ );
+ $this->eventSentHeaders = true;
+ }
+ if (in_array($this->request->getMethod(), self::$bodyDisallowed) ||
+ 0 == $this->contentLength || $this->position >= $this->contentLength
+ ) {
+ return '';
+ }
+ if (is_string($this->requestBody)) {
+ $string = substr($this->requestBody, $this->position, $length);
+ } elseif (is_resource($this->requestBody)) {
+ $string = fread($this->requestBody, $length);
+ } else {
+ $string = $this->requestBody->read($length);
+ }
+ $this->request->setLastEvent('sentBodyPart', strlen($string));
+ $this->position += strlen($string);
+ return $string;
+ }
+
+ /**
+ * Callback function called by cURL for saving the response headers
+ *
+ * @param resource cURL handle
+ * @param string response header (with trailing CRLF)
+ * @return integer number of bytes saved
+ * @see HTTP_Request2_Response::parseHeaderLine()
+ */
+ protected function callbackWriteHeader($ch, $string)
+ {
+ // we may receive a second set of headers if doing e.g. digest auth
+ if ($this->eventReceivedHeaders || !$this->eventSentHeaders) {
+ // don't bother with 100-Continue responses (bug #15785)
+ if (!$this->eventSentHeaders ||
+ $this->response->getStatus() >= 200
+ ) {
+ $this->request->setLastEvent(
+ 'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT)
+ );
+ }
+ $upload = curl_getinfo($ch, CURLINFO_SIZE_UPLOAD);
+ // if body wasn't read by a callback, send event with total body size
+ if ($upload > $this->position) {
+ $this->request->setLastEvent(
+ 'sentBodyPart', $upload - $this->position
+ );
+ $this->position = $upload;
+ }
+ if ($upload && (!$this->eventSentHeaders
+ || $this->response->getStatus() >= 200)
+ ) {
+ $this->request->setLastEvent('sentBody', $upload);
+ }
+ $this->eventSentHeaders = true;
+ // we'll need a new response object
+ if ($this->eventReceivedHeaders) {
+ $this->eventReceivedHeaders = false;
+ $this->response = null;
+ }
+ }
+ if (empty($this->response)) {
+ $this->response = new HTTP_Request2_Response(
+ $string, false, curl_getinfo($ch, CURLINFO_EFFECTIVE_URL)
+ );
+ } else {
+ $this->response->parseHeaderLine($string);
+ if ('' == trim($string)) {
+ // don't bother with 100-Continue responses (bug #15785)
+ if (200 <= $this->response->getStatus()) {
+ $this->request->setLastEvent('receivedHeaders', $this->response);
+ }
+
+ if ($this->request->getConfig('follow_redirects') && $this->response->isRedirect()) {
+ $redirectUrl = new Net_URL2($this->response->getHeader('location'));
+
+ // for versions lower than 5.2.10, check the redirection URL protocol
+ if (!defined('CURLOPT_REDIR_PROTOCOLS') && $redirectUrl->isAbsolute()
+ && !in_array($redirectUrl->getScheme(), array('http', 'https'))
+ ) {
+ return -1;
+ }
+
+ if ($jar = $this->request->getCookieJar()) {
+ $jar->addCookiesFromResponse($this->response, $this->request->getUrl());
+ if (!$redirectUrl->isAbsolute()) {
+ $redirectUrl = $this->request->getUrl()->resolve($redirectUrl);
+ }
+ if ($cookies = $jar->getMatching($redirectUrl, true)) {
+ curl_setopt($ch, CURLOPT_COOKIE, $cookies);
+ }
+ }
+ }
+ $this->eventReceivedHeaders = true;
+ }
+ }
+ return strlen($string);
+ }
+
+ /**
+ * Callback function called by cURL for saving the response body
+ *
+ * @param resource cURL handle (not used)
+ * @param string part of the response body
+ * @return integer number of bytes saved
+ * @see HTTP_Request2_Response::appendBody()
+ */
+ protected function callbackWriteBody($ch, $string)
+ {
+ // cURL calls WRITEFUNCTION callback without calling HEADERFUNCTION if
+ // response doesn't start with proper HTTP status line (see bug #15716)
+ if (empty($this->response)) {
+ throw new HTTP_Request2_MessageException(
+ "Malformed response: {$string}",
+ HTTP_Request2_Exception::MALFORMED_RESPONSE
+ );
+ }
+ if ($this->request->getConfig('store_body')) {
+ $this->response->appendBody($string);
+ }
+ $this->request->setLastEvent('receivedBodyPart', $string);
+ return strlen($string);
+ }
+}
+?>
diff --git a/public_html/lib/HTTP/Request2/Adapter/Mock.php b/public_html/lib/HTTP/Request2/Adapter/Mock.php
new file mode 100644
index 0000000..6e9f827
--- /dev/null
+++ b/public_html/lib/HTTP/Request2/Adapter/Mock.php
@@ -0,0 +1,171 @@
+<?php
+/**
+ * Mock adapter intended for testing
+ *
+ * PHP version 5
+ *
+ * LICENSE:
+ *
+ * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version SVN: $Id: Mock.php 308322 2011-02-14 13:58:03Z avb $
+ * @link http://pear.php.net/package/HTTP_Request2
+ */
+
+/**
+ * Base class for HTTP_Request2 adapters
+ */
+require_once 'HTTP/Request2/Adapter.php';
+
+/**
+ * Mock adapter intended for testing
+ *
+ * Can be used to test applications depending on HTTP_Request2 package without
+ * actually performing any HTTP requests. This adapter will return responses
+ * previously added via addResponse()
+ * <code>
+ * $mock = new HTTP_Request2_Adapter_Mock();
+ * $mock->addResponse("HTTP/1.1 ... ");
+ *
+ * $request = new HTTP_Request2();
+ * $request->setAdapter($mock);
+ *
+ * // This will return the response set above
+ * $response = $req->send();
+ * </code>
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @version Release: 2.0.0
+ */
+class HTTP_Request2_Adapter_Mock extends HTTP_Request2_Adapter
+{
+ /**
+ * A queue of responses to be returned by sendRequest()
+ * @var array
+ */
+ protected $responses = array();
+
+ /**
+ * Returns the next response from the queue built by addResponse()
+ *
+ * If the queue is empty it will return default empty response with status 400,
+ * if an Exception object was added to the queue it will be thrown.
+ *
+ * @param HTTP_Request2
+ * @return HTTP_Request2_Response
+ * @throws Exception
+ */
+ public function sendRequest(HTTP_Request2 $request)
+ {
+ if (count($this->responses) > 0) {
+ $response = array_shift($this->responses);
+ if ($response instanceof HTTP_Request2_Response) {
+ return $response;
+ } else {
+ // rethrow the exception
+ $class = get_class($response);
+ $message = $response->getMessage();
+ $code = $response->getCode();
+ throw new $class($message, $code);
+ }
+ } else {
+ return self::createResponseFromString("HTTP/1.1 400 Bad Request\r\n\r\n");
+ }
+ }
+
+ /**
+ * Adds response to the queue
+ *
+ * @param mixed either a string, a pointer to an open file,
+ * an instance of HTTP_Request2_Response or Exception
+ * @throws HTTP_Request2_Exception
+ */
+ public function addResponse($response)
+ {
+ if (is_string($response)) {
+ $response = self::createResponseFromString($response);
+ } elseif (is_resource($response)) {
+ $response = self::createResponseFromFile($response);
+ } elseif (!$response instanceof HTTP_Request2_Response &&
+ !$response instanceof Exception
+ ) {
+ throw new HTTP_Request2_Exception('Parameter is not a valid response');
+ }
+ $this->responses[] = $response;
+ }
+
+ /**
+ * Creates a new HTTP_Request2_Response object from a string
+ *
+ * @param string
+ * @return HTTP_Request2_Response
+ * @throws HTTP_Request2_Exception
+ */
+ public static function createResponseFromString($str)
+ {
+ $parts = preg_split('!(\r?\n){2}!m', $str, 2);
+ $headerLines = explode("\n", $parts[0]);
+ $response = new HTTP_Request2_Response(array_shift($headerLines));
+ foreach ($headerLines as $headerLine) {
+ $response->parseHeaderLine($headerLine);
+ }
+ $response->parseHeaderLine('');
+ if (isset($parts[1])) {
+ $response->appendBody($parts[1]);
+ }
+ return $response;
+ }
+
+ /**
+ * Creates a new HTTP_Request2_Response object from a file
+ *
+ * @param resource file pointer returned by fopen()
+ * @return HTTP_Request2_Response
+ * @throws HTTP_Request2_Exception
+ */
+ public static function createResponseFromFile($fp)
+ {
+ $response = new HTTP_Request2_Response(fgets($fp));
+ do {
+ $headerLine = fgets($fp);
+ $response->parseHeaderLine($headerLine);
+ } while ('' != trim($headerLine));
+
+ while (!feof($fp)) {
+ $response->appendBody(fread($fp, 8192));
+ }
+ return $response;
+ }
+}
+?> \ No newline at end of file
diff --git a/public_html/lib/HTTP/Request2/Adapter/Socket.php b/public_html/lib/HTTP/Request2/Adapter/Socket.php
new file mode 100644
index 0000000..05cac6e
--- /dev/null
+++ b/public_html/lib/HTTP/Request2/Adapter/Socket.php
@@ -0,0 +1,1084 @@
+<?php
+/**
+ * Socket-based adapter for HTTP_Request2
+ *
+ * PHP version 5
+ *
+ * LICENSE:
+ *
+ * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version SVN: $Id: Socket.php 309921 2011-04-03 16:43:02Z avb $
+ * @link http://pear.php.net/package/HTTP_Request2
+ */
+
+/**
+ * Base class for HTTP_Request2 adapters
+ */
+require_once 'HTTP/Request2/Adapter.php';
+
+/**
+ * Socket-based adapter for HTTP_Request2
+ *
+ * This adapter uses only PHP sockets and will work on almost any PHP
+ * environment. Code is based on original HTTP_Request PEAR package.
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @version Release: 2.0.0
+ */
+class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
+{
+ /**
+ * Regular expression for 'token' rule from RFC 2616
+ */
+ const REGEXP_TOKEN = '[^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+';
+
+ /**
+ * Regular expression for 'quoted-string' rule from RFC 2616
+ */
+ const REGEXP_QUOTED_STRING = '"(?:\\\\.|[^\\\\"])*"';
+
+ /**
+ * Connected sockets, needed for Keep-Alive support
+ * @var array
+ * @see connect()
+ */
+ protected static $sockets = array();
+
+ /**
+ * Data for digest authentication scheme
+ *
+ * The keys for the array are URL prefixes.
+ *
+ * The values are associative arrays with data (realm, nonce, nonce-count,
+ * opaque...) needed for digest authentication. Stored here to prevent making
+ * duplicate requests to digest-protected resources after we have already
+ * received the challenge.
+ *
+ * @var array
+ */
+ protected static $challenges = array();
+
+ /**
+ * Connected socket
+ * @var resource
+ * @see connect()
+ */
+ protected $socket;
+
+ /**
+ * Challenge used for server digest authentication
+ * @var array
+ */
+ protected $serverChallenge;
+
+ /**
+ * Challenge used for proxy digest authentication
+ * @var array
+ */
+ protected $proxyChallenge;
+
+ /**
+ * Sum of start time and global timeout, exception will be thrown if request continues past this time
+ * @var integer
+ */
+ protected $deadline = null;
+
+ /**
+ * Remaining length of the current chunk, when reading chunked response
+ * @var integer
+ * @see readChunked()
+ */
+ protected $chunkLength = 0;
+
+ /**
+ * Remaining amount of redirections to follow
+ *
+ * Starts at 'max_redirects' configuration parameter and is reduced on each
+ * subsequent redirect. An Exception will be thrown once it reaches zero.
+ *
+ * @var integer
+ */
+ protected $redirectCountdown = null;
+
+ /**
+ * Sends request to the remote server and returns its response
+ *
+ * @param HTTP_Request2
+ * @return HTTP_Request2_Response
+ * @throws HTTP_Request2_Exception
+ */
+ public function sendRequest(HTTP_Request2 $request)
+ {
+ $this->request = $request;
+
+ // Use global request timeout if given, see feature requests #5735, #8964
+ if ($timeout = $request->getConfig('timeout')) {
+ $this->deadline = time() + $timeout;
+ } else {
+ $this->deadline = null;
+ }
+
+ try {
+ $keepAlive = $this->connect();
+ $headers = $this->prepareHeaders();
+ if (false === @fwrite($this->socket, $headers, strlen($headers))) {
+ throw new HTTP_Request2_MessageException('Error writing request');
+ }
+ // provide request headers to the observer, see request #7633
+ $this->request->setLastEvent('sentHeaders', $headers);
+ $this->writeBody();
+
+ if ($this->deadline && time() > $this->deadline) {
+ throw new HTTP_Request2_MessageException(
+ 'Request timed out after ' .
+ $request->getConfig('timeout') . ' second(s)',
+ HTTP_Request2_Exception::TIMEOUT
+ );
+ }
+
+ $response = $this->readResponse();
+
+ if ($jar = $request->getCookieJar()) {
+ $jar->addCookiesFromResponse($response, $request->getUrl());
+ }
+
+ if (!$this->canKeepAlive($keepAlive, $response)) {
+ $this->disconnect();
+ }
+
+ if ($this->shouldUseProxyDigestAuth($response)) {
+ return $this->sendRequest($request);
+ }
+ if ($this->shouldUseServerDigestAuth($response)) {
+ return $this->sendRequest($request);
+ }
+ if ($authInfo = $response->getHeader('authentication-info')) {
+ $this->updateChallenge($this->serverChallenge, $authInfo);
+ }
+ if ($proxyInfo = $response->getHeader('proxy-authentication-info')) {
+ $this->updateChallenge($this->proxyChallenge, $proxyInfo);
+ }
+
+ } catch (Exception $e) {
+ $this->disconnect();
+ }
+
+ unset($this->request, $this->requestBody);
+
+ if (!empty($e)) {
+ $this->redirectCountdown = null;
+ throw $e;
+ }
+
+ if (!$request->getConfig('follow_redirects') || !$response->isRedirect()) {
+ $this->redirectCountdown = null;
+ return $response;
+ } else {
+ return $this->handleRedirect($request, $response);
+ }
+ }
+
+ /**
+ * Connects to the remote server
+ *
+ * @return bool whether the connection can be persistent
+ * @throws HTTP_Request2_Exception
+ */
+ protected function connect()
+ {
+ $secure = 0 == strcasecmp($this->request->getUrl()->getScheme(), 'https');
+ $tunnel = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod();
+ $headers = $this->request->getHeaders();
+ $reqHost = $this->request->getUrl()->getHost();
+ if (!($reqPort = $this->request->getUrl()->getPort())) {
+ $reqPort = $secure? 443: 80;
+ }
+
+ if ($host = $this->request->getConfig('proxy_host')) {
+ if (!($port = $this->request->getConfig('proxy_port'))) {
+ throw new HTTP_Request2_LogicException(
+ 'Proxy port not provided',
+ HTTP_Request2_Exception::MISSING_VALUE
+ );
+ }
+ $proxy = true;
+ } else {
+ $host = $reqHost;
+ $port = $reqPort;
+ $proxy = false;
+ }
+
+ if ($tunnel && !$proxy) {
+ throw new HTTP_Request2_LogicException(
+ "Trying to perform CONNECT request without proxy",
+ HTTP_Request2_Exception::MISSING_VALUE
+ );
+ }
+ if ($secure && !in_array('ssl', stream_get_transports())) {
+ throw new HTTP_Request2_LogicException(
+ 'Need OpenSSL support for https:// requests',
+ HTTP_Request2_Exception::MISCONFIGURATION
+ );
+ }
+
+ // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive
+ // connection token to a proxy server...
+ if ($proxy && !$secure &&
+ !empty($headers['connection']) && 'Keep-Alive' == $headers['connection']
+ ) {
+ $this->request->setHeader('connection');
+ }
+
+ $keepAlive = ('1.1' == $this->request->getConfig('protocol_version') &&
+ empty($headers['connection'])) ||
+ (!empty($headers['connection']) &&
+ 'Keep-Alive' == $headers['connection']);
+ $host = ((!$secure || $proxy)? 'tcp://': 'ssl://') . $host;
+
+ $options = array();
+ if ($secure || $tunnel) {
+ foreach ($this->request->getConfig() as $name => $value) {
+ if ('ssl_' == substr($name, 0, 4) && null !== $value) {
+ if ('ssl_verify_host' == $name) {
+ if ($value) {
+ $options['CN_match'] = $reqHost;
+ }
+ } else {
+ $options[substr($name, 4)] = $value;
+ }
+ }
+ }
+ ksort($options);
+ }
+
+ // Changing SSL context options after connection is established does *not*
+ // work, we need a new connection if options change
+ $remote = $host . ':' . $port;
+ $socketKey = $remote . (($secure && $proxy)? "->{$reqHost}:{$reqPort}": '') .
+ (empty($options)? '': ':' . serialize($options));
+ unset($this->socket);
+
+ // We use persistent connections and have a connected socket?
+ // Ensure that the socket is still connected, see bug #16149
+ if ($keepAlive && !empty(self::$sockets[$socketKey]) &&
+ !feof(self::$sockets[$socketKey])
+ ) {
+ $this->socket =& self::$sockets[$socketKey];
+
+ } elseif ($secure && $proxy && !$tunnel) {
+ $this->establishTunnel();
+ $this->request->setLastEvent(
+ 'connect', "ssl://{$reqHost}:{$reqPort} via {$host}:{$port}"
+ );
+ self::$sockets[$socketKey] =& $this->socket;
+
+ } else {
+ // Set SSL context options if doing HTTPS request or creating a tunnel
+ $context = stream_context_create();
+ foreach ($options as $name => $value) {
+ if (!stream_context_set_option($context, 'ssl', $name, $value)) {
+ throw new HTTP_Request2_LogicException(
+ "Error setting SSL context option '{$name}'"
+ );
+ }
+ }
+ $track = @ini_set('track_errors', 1);
+ $this->socket = @stream_socket_client(
+ $remote, $errno, $errstr,
+ $this->request->getConfig('connect_timeout'),
+ STREAM_CLIENT_CONNECT, $context
+ );
+ if (!$this->socket) {
+ $e = new HTTP_Request2_ConnectionException(
+ "Unable to connect to {$remote}. Error: "
+ . (empty($errstr)? $php_errormsg: $errstr), 0, $errno
+ );
+ }
+ @ini_set('track_errors', $track);
+ if (isset($e)) {
+ throw $e;
+ }
+ $this->request->setLastEvent('connect', $remote);
+ self::$sockets[$socketKey] =& $this->socket;
+ }
+ return $keepAlive;
+ }
+
+ /**
+ * Establishes a tunnel to a secure remote server via HTTP CONNECT request
+ *
+ * This method will fail if 'ssl_verify_peer' is enabled. Probably because PHP
+ * sees that we are connected to a proxy server (duh!) rather than the server
+ * that presents its certificate.
+ *
+ * @link http://tools.ietf.org/html/rfc2817#section-5.2
+ * @throws HTTP_Request2_Exception
+ */
+ protected function establishTunnel()
+ {
+ $donor = new self;
+ $connect = new HTTP_Request2(
+ $this->request->getUrl(), HTTP_Request2::METHOD_CONNECT,
+ array_merge($this->request->getConfig(),
+ array('adapter' => $donor))
+ );
+ $response = $connect->send();
+ // Need any successful (2XX) response
+ if (200 > $response->getStatus() || 300 <= $response->getStatus()) {
+ throw new HTTP_Request2_ConnectionException(
+ 'Failed to connect via HTTPS proxy. Proxy response: ' .
+ $response->getStatus() . ' ' . $response->getReasonPhrase()
+ );
+ }
+ $this->socket = $donor->socket;
+
+ $modes = array(
+ STREAM_CRYPTO_METHOD_TLS_CLIENT,
+ STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
+ STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
+ STREAM_CRYPTO_METHOD_SSLv2_CLIENT
+ );
+
+ foreach ($modes as $mode) {
+ if (stream_socket_enable_crypto($this->socket, true, $mode)) {
+ return;
+ }
+ }
+ throw new HTTP_Request2_ConnectionException(
+ 'Failed to enable secure connection when connecting through proxy'
+ );
+ }
+
+ /**
+ * Checks whether current connection may be reused or should be closed
+ *
+ * @param boolean whether connection could be persistent
+ * in the first place
+ * @param HTTP_Request2_Response response object to check
+ * @return boolean
+ */
+ protected function canKeepAlive($requestKeepAlive, HTTP_Request2_Response $response)
+ {
+ // Do not close socket on successful CONNECT request
+ if (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() &&
+ 200 <= $response->getStatus() && 300 > $response->getStatus()
+ ) {
+ return true;
+ }
+
+ $lengthKnown = 'chunked' == strtolower($response->getHeader('transfer-encoding'))
+ || null !== $response->getHeader('content-length')
+ // no body possible for such responses, see also request #17031
+ || HTTP_Request2::METHOD_HEAD == $this->request->getMethod()
+ || in_array($response->getStatus(), array(204, 304));
+ $persistent = 'keep-alive' == strtolower($response->getHeader('connection')) ||
+ (null === $response->getHeader('connection') &&
+ '1.1' == $response->getVersion());
+ return $requestKeepAlive && $lengthKnown && $persistent;
+ }
+
+ /**
+ * Disconnects from the remote server
+ */
+ protected function disconnect()
+ {
+ if (is_resource($this->socket)) {
+ fclose($this->socket);
+ $this->socket = null;
+ $this->request->setLastEvent('disconnect');
+ }
+ }
+
+ /**
+ * Handles HTTP redirection
+ *
+ * This method will throw an Exception if redirect to a non-HTTP(S) location
+ * is attempted, also if number of redirects performed already is equal to
+ * 'max_redirects' configuration parameter.
+ *
+ * @param HTTP_Request2 Original request
+ * @param HTTP_Request2_Response Response containing redirect
+ * @return HTTP_Request2_Response Response from a new location
+ * @throws HTTP_Request2_Exception
+ */
+ protected function handleRedirect(HTTP_Request2 $request,
+ HTTP_Request2_Response $response)
+ {
+ if (is_null($this->redirectCountdown)) {
+ $this->redirectCountdown = $request->getConfig('max_redirects');
+ }
+ if (0 == $this->redirectCountdown) {
+ $this->redirectCountdown = null;
+ // Copying cURL behaviour
+ throw new HTTP_Request2_MessageException (
+ 'Maximum (' . $request->getConfig('max_redirects') . ') redirects followed',
+ HTTP_Request2_Exception::TOO_MANY_REDIRECTS
+ );
+ }
+ $redirectUrl = new Net_URL2(
+ $response->getHeader('location'),
+ array(Net_URL2::OPTION_USE_BRACKETS => $request->getConfig('use_brackets'))
+ );
+ // refuse non-HTTP redirect
+ if ($redirectUrl->isAbsolute()
+ && !in_array($redirectUrl->getScheme(), array('http', 'https'))
+ ) {
+ $this->redirectCountdown = null;
+ throw new HTTP_Request2_MessageException(
+ 'Refusing to redirect to a non-HTTP URL ' . $redirectUrl->__toString(),
+ HTTP_Request2_Exception::NON_HTTP_REDIRECT
+ );
+ }
+ // Theoretically URL should be absolute (see http://tools.ietf.org/html/rfc2616#section-14.30),
+ // but in practice it is often not
+ if (!$redirectUrl->isAbsolute()) {
+ $redirectUrl = $request->getUrl()->resolve($redirectUrl);
+ }
+ $redirect = clone $request;
+ $redirect->setUrl($redirectUrl);
+ if (303 == $response->getStatus() || (!$request->getConfig('strict_redirects')
+ && in_array($response->getStatus(), array(301, 302)))
+ ) {
+ $redirect->setMethod(HTTP_Request2::METHOD_GET);
+ $redirect->setBody('');
+ }
+
+ if (0 < $this->redirectCountdown) {
+ $this->redirectCountdown--;
+ }
+ return $this->sendRequest($redirect);
+ }
+
+ /**
+ * Checks whether another request should be performed with server digest auth
+ *
+ * Several conditions should be satisfied for it to return true:
+ * - response status should be 401
+ * - auth credentials should be set in the request object
+ * - response should contain WWW-Authenticate header with digest challenge
+ * - there is either no challenge stored for this URL or new challenge
+ * contains stale=true parameter (in other case we probably just failed
+ * due to invalid username / password)
+ *
+ * The method stores challenge values in $challenges static property
+ *
+ * @param HTTP_Request2_Response response to check
+ * @return boolean whether another request should be performed
+ * @throws HTTP_Request2_Exception in case of unsupported challenge parameters
+ */
+ protected function shouldUseServerDigestAuth(HTTP_Request2_Response $response)
+ {
+ // no sense repeating a request if we don't have credentials
+ if (401 != $response->getStatus() || !$this->request->getAuth()) {
+ return false;
+ }
+ if (!$challenge = $this->parseDigestChallenge($response->getHeader('www-authenticate'))) {
+ return false;
+ }
+
+ $url = $this->request->getUrl();
+ $scheme = $url->getScheme();
+ $host = $scheme . '://' . $url->getHost();
+ if ($port = $url->getPort()) {
+ if ((0 == strcasecmp($scheme, 'http') && 80 != $port) ||
+ (0 == strcasecmp($scheme, 'https') && 443 != $port)
+ ) {
+ $host .= ':' . $port;
+ }
+ }
+
+ if (!empty($challenge['domain'])) {
+ $prefixes = array();
+ foreach (preg_split('/\\s+/', $challenge['domain']) as $prefix) {
+ // don't bother with different servers
+ if ('/' == substr($prefix, 0, 1)) {
+ $prefixes[] = $host . $prefix;
+ }
+ }
+ }
+ if (empty($prefixes)) {
+ $prefixes = array($host . '/');
+ }
+
+ $ret = true;
+ foreach ($prefixes as $prefix) {
+ if (!empty(self::$challenges[$prefix]) &&
+ (empty($challenge['stale']) || strcasecmp('true', $challenge['stale']))
+ ) {
+ // probably credentials are invalid
+ $ret = false;
+ }
+ self::$challenges[$prefix] =& $challenge;
+ }
+ return $ret;
+ }
+
+ /**
+ * Checks whether another request should be performed with proxy digest auth
+ *
+ * Several conditions should be satisfied for it to return true:
+ * - response status should be 407
+ * - proxy auth credentials should be set in the request object
+ * - response should contain Proxy-Authenticate header with digest challenge
+ * - there is either no challenge stored for this proxy or new challenge
+ * contains stale=true parameter (in other case we probably just failed
+ * due to invalid username / password)
+ *
+ * The method stores challenge values in $challenges static property
+ *
+ * @param HTTP_Request2_Response response to check
+ * @return boolean whether another request should be performed
+ * @throws HTTP_Request2_Exception in case of unsupported challenge parameters
+ */
+ protected function shouldUseProxyDigestAuth(HTTP_Request2_Response $response)
+ {
+ if (407 != $response->getStatus() || !$this->request->getConfig('proxy_user')) {
+ return false;
+ }
+ if (!($challenge = $this->parseDigestChallenge($response->getHeader('proxy-authenticate')))) {
+ return false;
+ }
+
+ $key = 'proxy://' . $this->request->getConfig('proxy_host') .
+ ':' . $this->request->getConfig('proxy_port');
+
+ if (!empty(self::$challenges[$key]) &&
+ (empty($challenge['stale']) || strcasecmp('true', $challenge['stale']))
+ ) {
+ $ret = false;
+ } else {
+ $ret = true;
+ }
+ self::$challenges[$key] = $challenge;
+ return $ret;
+ }
+
+ /**
+ * Extracts digest method challenge from (WWW|Proxy)-Authenticate header value
+ *
+ * There is a problem with implementation of RFC 2617: several of the parameters
+ * are defined as quoted-string there and thus may contain backslash escaped
+ * double quotes (RFC 2616, section 2.2). However, RFC 2617 defines unq(X) as
+ * just value of quoted-string X without surrounding quotes, it doesn't speak
+ * about removing backslash escaping.
+ *
+ * Now realm parameter is user-defined and human-readable, strange things
+ * happen when it contains quotes:
+ * - Apache allows quotes in realm, but apparently uses realm value without
+ * backslashes for digest computation
+ * - Squid allows (manually escaped) quotes there, but it is impossible to
+ * authorize with either escaped or unescaped quotes used in digest,
+ * probably it can't parse the response (?)
+ * - Both IE and Firefox display realm value with backslashes in
+ * the password popup and apparently use the same value for digest
+ *
+ * HTTP_Request2 follows IE and Firefox (and hopefully RFC 2617) in
+ * quoted-string handling, unfortunately that means failure to authorize
+ * sometimes
+ *
+ * @param string value of WWW-Authenticate or Proxy-Authenticate header
+ * @return mixed associative array with challenge parameters, false if
+ * no challenge is present in header value
+ * @throws HTTP_Request2_NotImplementedException in case of unsupported challenge parameters
+ */
+ protected function parseDigestChallenge($headerValue)
+ {
+ $authParam = '(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' .
+ self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')';
+ $challenge = "!(?<=^|\\s|,)Digest ({$authParam}\\s*(,\\s*|$))+!";
+ if (!preg_match($challenge, $headerValue, $matches)) {
+ return false;
+ }
+
+ preg_match_all('!' . $authParam . '!', $matches[0], $params);
+ $paramsAry = array();
+ $knownParams = array('realm', 'domain', 'nonce', 'opaque', 'stale',
+ 'algorithm', 'qop');
+ for ($i = 0; $i < count($params[0]); $i++) {
+ // section 3.2.1: Any unrecognized directive MUST be ignored.
+ if (in_array($params[1][$i], $knownParams)) {
+ if ('"' == substr($params[2][$i], 0, 1)) {
+ $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1);
+ } else {
+ $paramsAry[$params[1][$i]] = $params[2][$i];
+ }
+ }
+ }
+ // we only support qop=auth
+ if (!empty($paramsAry['qop']) &&
+ !in_array('auth', array_map('trim', explode(',', $paramsAry['qop'])))
+ ) {
+ throw new HTTP_Request2_NotImplementedException(
+ "Only 'auth' qop is currently supported in digest authentication, " .
+ "server requested '{$paramsAry['qop']}'"
+ );
+ }
+ // we only support algorithm=MD5
+ if (!empty($paramsAry['algorithm']) && 'MD5' != $paramsAry['algorithm']) {
+ throw new HTTP_Request2_NotImplementedException(
+ "Only 'MD5' algorithm is currently supported in digest authentication, " .
+ "server requested '{$paramsAry['algorithm']}'"
+ );
+ }
+
+ return $paramsAry;
+ }
+
+ /**
+ * Parses [Proxy-]Authentication-Info header value and updates challenge
+ *
+ * @param array challenge to update
+ * @param string value of [Proxy-]Authentication-Info header
+ * @todo validate server rspauth response
+ */
+ protected function updateChallenge(&$challenge, $headerValue)
+ {
+ $authParam = '!(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' .
+ self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')!';
+ $paramsAry = array();
+
+ preg_match_all($authParam, $headerValue, $params);
+ for ($i = 0; $i < count($params[0]); $i++) {
+ if ('"' == substr($params[2][$i], 0, 1)) {
+ $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1);
+ } else {
+ $paramsAry[$params[1][$i]] = $params[2][$i];
+ }
+ }
+ // for now, just update the nonce value
+ if (!empty($paramsAry['nextnonce'])) {
+ $challenge['nonce'] = $paramsAry['nextnonce'];
+ $challenge['nc'] = 1;
+ }
+ }
+
+ /**
+ * Creates a value for [Proxy-]Authorization header when using digest authentication
+ *
+ * @param string user name
+ * @param string password
+ * @param string request URL
+ * @param array digest challenge parameters
+ * @return string value of [Proxy-]Authorization request header
+ * @link http://tools.ietf.org/html/rfc2617#section-3.2.2
+ */
+ protected function createDigestResponse($user, $password, $url, &$challenge)
+ {
+ if (false !== ($q = strpos($url, '?')) &&
+ $this->request->getConfig('digest_compat_ie')
+ ) {
+ $url = substr($url, 0, $q);
+ }
+
+ $a1 = md5($user . ':' . $challenge['realm'] . ':' . $password);
+ $a2 = md5($this->request->getMethod() . ':' . $url);
+
+ if (empty($challenge['qop'])) {
+ $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $a2);
+ } else {
+ $challenge['cnonce'] = 'Req2.' . rand();
+ if (empty($challenge['nc'])) {
+ $challenge['nc'] = 1;
+ }
+ $nc = sprintf('%08x', $challenge['nc']++);
+ $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $nc . ':' .
+ $challenge['cnonce'] . ':auth:' . $a2);
+ }
+ return 'Digest username="' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $user) . '", ' .
+ 'realm="' . $challenge['realm'] . '", ' .
+ 'nonce="' . $challenge['nonce'] . '", ' .
+ 'uri="' . $url . '", ' .
+ 'response="' . $digest . '"' .
+ (!empty($challenge['opaque'])?
+ ', opaque="' . $challenge['opaque'] . '"':
+ '') .
+ (!empty($challenge['qop'])?
+ ', qop="auth", nc=' . $nc . ', cnonce="' . $challenge['cnonce'] . '"':
+ '');
+ }
+
+ /**
+ * Adds 'Authorization' header (if needed) to request headers array
+ *
+ * @param array request headers
+ * @param string request host (needed for digest authentication)
+ * @param string request URL (needed for digest authentication)
+ * @throws HTTP_Request2_NotImplementedException
+ */
+ protected function addAuthorizationHeader(&$headers, $requestHost, $requestUrl)
+ {
+ if (!($auth = $this->request->getAuth())) {
+ return;
+ }
+ switch ($auth['scheme']) {
+ case HTTP_Request2::AUTH_BASIC:
+ $headers['authorization'] =
+ 'Basic ' . base64_encode($auth['user'] . ':' . $auth['password']);
+ break;
+
+ case HTTP_Request2::AUTH_DIGEST:
+ unset($this->serverChallenge);
+ $fullUrl = ('/' == $requestUrl[0])?
+ $this->request->getUrl()->getScheme() . '://' .
+ $requestHost . $requestUrl:
+ $requestUrl;
+ foreach (array_keys(self::$challenges) as $key) {
+ if ($key == substr($fullUrl, 0, strlen($key))) {
+ $headers['authorization'] = $this->createDigestResponse(
+ $auth['user'], $auth['password'],
+ $requestUrl, self::$challenges[$key]
+ );
+ $this->serverChallenge =& self::$challenges[$key];
+ break;
+ }
+ }
+ break;
+
+ default:
+ throw new HTTP_Request2_NotImplementedException(
+ "Unknown HTTP authentication scheme '{$auth['scheme']}'"
+ );
+ }
+ }
+
+ /**
+ * Adds 'Proxy-Authorization' header (if needed) to request headers array
+ *
+ * @param array request headers
+ * @param string request URL (needed for digest authentication)
+ * @throws HTTP_Request2_NotImplementedException
+ */
+ protected function addProxyAuthorizationHeader(&$headers, $requestUrl)
+ {
+ if (!$this->request->getConfig('proxy_host') ||
+ !($user = $this->request->getConfig('proxy_user')) ||
+ (0 == strcasecmp('https', $this->request->getUrl()->getScheme()) &&
+ HTTP_Request2::METHOD_CONNECT != $this->request->getMethod())
+ ) {
+ return;
+ }
+
+ $password = $this->request->getConfig('proxy_password');
+ switch ($this->request->getConfig('proxy_auth_scheme')) {
+ case HTTP_Request2::AUTH_BASIC:
+ $headers['proxy-authorization'] =
+ 'Basic ' . base64_encode($user . ':' . $password);
+ break;
+
+ case HTTP_Request2::AUTH_DIGEST:
+ unset($this->proxyChallenge);
+ $proxyUrl = 'proxy://' . $this->request->getConfig('proxy_host') .
+ ':' . $this->request->getConfig('proxy_port');
+ if (!empty(self::$challenges[$proxyUrl])) {
+ $headers['proxy-authorization'] = $this->createDigestResponse(
+ $user, $password,
+ $requestUrl, self::$challenges[$proxyUrl]
+ );
+ $this->proxyChallenge =& self::$challenges[$proxyUrl];
+ }
+ break;
+
+ default:
+ throw new HTTP_Request2_NotImplementedException(
+ "Unknown HTTP authentication scheme '" .
+ $this->request->getConfig('proxy_auth_scheme') . "'"
+ );
+ }
+ }
+
+
+ /**
+ * Creates the string with the Request-Line and request headers
+ *
+ * @return string
+ * @throws HTTP_Request2_Exception
+ */
+ protected function prepareHeaders()
+ {
+ $headers = $this->request->getHeaders();
+ $url = $this->request->getUrl();
+ $connect = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod();
+ $host = $url->getHost();
+
+ $defaultPort = 0 == strcasecmp($url->getScheme(), 'https')? 443: 80;
+ if (($port = $url->getPort()) && $port != $defaultPort || $connect) {
+ $host .= ':' . (empty($port)? $defaultPort: $port);
+ }
+ // Do not overwrite explicitly set 'Host' header, see bug #16146
+ if (!isset($headers['host'])) {
+ $headers['host'] = $host;
+ }
+
+ if ($connect) {
+ $requestUrl = $host;
+
+ } else {
+ if (!$this->request->getConfig('proxy_host') ||
+ 0 == strcasecmp($url->getScheme(), 'https')
+ ) {
+ $requestUrl = '';
+ } else {
+ $requestUrl = $url->getScheme() . '://' . $host;
+ }
+ $path = $url->getPath();
+ $query = $url->getQuery();
+ $requestUrl .= (empty($path)? '/': $path) . (empty($query)? '': '?' . $query);
+ }
+
+ if ('1.1' == $this->request->getConfig('protocol_version') &&
+ extension_loaded('zlib') && !isset($headers['accept-encoding'])
+ ) {
+ $headers['accept-encoding'] = 'gzip, deflate';
+ }
+ if (($jar = $this->request->getCookieJar())
+ && ($cookies = $jar->getMatching($this->request->getUrl(), true))
+ ) {
+ $headers['cookie'] = (empty($headers['cookie'])? '': $headers['cookie'] . '; ') . $cookies;
+ }
+
+ $this->addAuthorizationHeader($headers, $host, $requestUrl);
+ $this->addProxyAuthorizationHeader($headers, $requestUrl);
+ $this->calculateRequestLength($headers);
+
+ $headersStr = $this->request->getMethod() . ' ' . $requestUrl . ' HTTP/' .
+ $this->request->getConfig('protocol_version') . "\r\n";
+ foreach ($headers as $name => $value) {
+ $canonicalName = implode('-', array_map('ucfirst', explode('-', $name)));
+ $headersStr .= $canonicalName . ': ' . $value . "\r\n";
+ }
+ return $headersStr . "\r\n";
+ }
+
+ /**
+ * Sends the request body
+ *
+ * @throws HTTP_Request2_MessageException
+ */
+ protected function writeBody()
+ {
+ if (in_array($this->request->getMethod(), self::$bodyDisallowed) ||
+ 0 == $this->contentLength
+ ) {
+ return;
+ }
+
+ $position = 0;
+ $bufferSize = $this->request->getConfig('buffer_size');
+ while ($position < $this->contentLength) {
+ if (is_string($this->requestBody)) {
+ $str = substr($this->requestBody, $position, $bufferSize);
+ } elseif (is_resource($this->requestBody)) {
+ $str = fread($this->requestBody, $bufferSize);
+ } else {
+ $str = $this->requestBody->read($bufferSize);
+ }
+ if (false === @fwrite($this->socket, $str, strlen($str))) {
+ throw new HTTP_Request2_MessageException('Error writing request');
+ }
+ // Provide the length of written string to the observer, request #7630
+ $this->request->setLastEvent('sentBodyPart', strlen($str));
+ $position += strlen($str);
+ }
+ $this->request->setLastEvent('sentBody', $this->contentLength);
+ }
+
+ /**
+ * Reads the remote server's response
+ *
+ * @return HTTP_Request2_Response
+ * @throws HTTP_Request2_Exception
+ */
+ protected function readResponse()
+ {
+ $bufferSize = $this->request->getConfig('buffer_size');
+
+ do {
+ $response = new HTTP_Request2_Response(
+ $this->readLine($bufferSize), true, $this->request->getUrl()
+ );
+ do {
+ $headerLine = $this->readLine($bufferSize);
+ $response->parseHeaderLine($headerLine);
+ } while ('' != $headerLine);
+ } while (in_array($response->getStatus(), array(100, 101)));
+
+ $this->request->setLastEvent('receivedHeaders', $response);
+
+ // No body possible in such responses
+ if (HTTP_Request2::METHOD_HEAD == $this->request->getMethod() ||
+ (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() &&
+ 200 <= $response->getStatus() && 300 > $response->getStatus()) ||
+ in_array($response->getStatus(), array(204, 304))
+ ) {
+ return $response;
+ }
+
+ $chunked = 'chunked' == $response->getHeader('transfer-encoding');
+ $length = $response->getHeader('content-length');
+ $hasBody = false;
+ if ($chunked || null === $length || 0 < intval($length)) {
+ // RFC 2616, section 4.4:
+ // 3. ... If a message is received with both a
+ // Transfer-Encoding header field and a Content-Length header field,
+ // the latter MUST be ignored.
+ $toRead = ($chunked || null === $length)? null: $length;
+ $this->chunkLength = 0;
+
+ while (!feof($this->socket) && (is_null($toRead) || 0 < $toRead)) {
+ if ($chunked) {
+ $data = $this->readChunked($bufferSize);
+ } elseif (is_null($toRead)) {
+ $data = $this->fread($bufferSize);
+ } else {
+ $data = $this->fread(min($toRead, $bufferSize));
+ $toRead -= strlen($data);
+ }
+ if ('' == $data && (!$this->chunkLength || feof($this->socket))) {
+ break;
+ }
+
+ $hasBody = true;
+ if ($this->request->getConfig('store_body')) {
+ $response->appendBody($data);
+ }
+ if (!in_array($response->getHeader('content-encoding'), array('identity', null))) {
+ $this->request->setLastEvent('receivedEncodedBodyPart', $data);
+ } else {
+ $this->request->setLastEvent('receivedBodyPart', $data);
+ }
+ }
+ }
+
+ if ($hasBody) {
+ $this->request->setLastEvent('receivedBody', $response);
+ }
+ return $response;
+ }
+
+ /**
+ * Reads until either the end of the socket or a newline, whichever comes first
+ *
+ * Strips the trailing newline from the returned data, handles global
+ * request timeout. Method idea borrowed from Net_Socket PEAR package.
+ *
+ * @param int buffer size to use for reading
+ * @return Available data up to the newline (not including newline)
+ * @throws HTTP_Request2_MessageException In case of timeout
+ */
+ protected function readLine($bufferSize)
+ {
+ $line = '';
+ while (!feof($this->socket)) {
+ if ($this->deadline) {
+ stream_set_timeout($this->socket, max($this->deadline - time(), 1));
+ }
+ $line .= @fgets($this->socket, $bufferSize);
+ $info = stream_get_meta_data($this->socket);
+ if ($info['timed_out'] || $this->deadline && time() > $this->deadline) {
+ $reason = $this->deadline
+ ? 'after ' . $this->request->getConfig('timeout') . ' second(s)'
+ : 'due to default_socket_timeout php.ini setting';
+ throw new HTTP_Request2_MessageException(
+ "Request timed out {$reason}", HTTP_Request2_Exception::TIMEOUT
+ );
+ }
+ if (substr($line, -1) == "\n") {
+ return rtrim($line, "\r\n");
+ }
+ }
+ return $line;
+ }
+
+ /**
+ * Wrapper around fread(), handles global request timeout
+ *
+ * @param int Reads up to this number of bytes
+ * @return Data read from socket
+ * @throws HTTP_Request2_MessageException In case of timeout
+ */
+ protected function fread($length)
+ {
+ if ($this->deadline) {
+ stream_set_timeout($this->socket, max($this->deadline - time(), 1));
+ }
+ $data = fread($this->socket, $length);
+ $info = stream_get_meta_data($this->socket);
+ if ($info['timed_out'] || $this->deadline && time() > $this->deadline) {
+ $reason = $this->deadline
+ ? 'after ' . $this->request->getConfig('timeout') . ' second(s)'
+ : 'due to default_socket_timeout php.ini setting';
+ throw new HTTP_Request2_MessageException(
+ "Request timed out {$reason}", HTTP_Request2_Exception::TIMEOUT
+ );
+ }
+ return $data;
+ }
+
+ /**
+ * Reads a part of response body encoded with chunked Transfer-Encoding
+ *
+ * @param int buffer size to use for reading
+ * @return string
+ * @throws HTTP_Request2_MessageException
+ */
+ protected function readChunked($bufferSize)
+ {
+ // at start of the next chunk?
+ if (0 == $this->chunkLength) {
+ $line = $this->readLine($bufferSize);
+ if (!preg_match('/^([0-9a-f]+)/i', $line, $matches)) {
+ throw new HTTP_Request2_MessageException(
+ "Cannot decode chunked response, invalid chunk length '{$line}'",
+ HTTP_Request2_Exception::DECODE_ERROR
+ );
+ } else {
+ $this->chunkLength = hexdec($matches[1]);
+ // Chunk with zero length indicates the end
+ if (0 == $this->chunkLength) {
+ $this->readLine($bufferSize);
+ return '';
+ }
+ }
+ }
+ $data = $this->fread(min($this->chunkLength, $bufferSize));
+ $this->chunkLength -= strlen($data);
+ if (0 == $this->chunkLength) {
+ $this->readLine($bufferSize); // Trailing CRLF
+ }
+ return $data;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/HTTP/Request2/CookieJar.php b/public_html/lib/HTTP/Request2/CookieJar.php
new file mode 100644
index 0000000..af7534f
--- /dev/null
+++ b/public_html/lib/HTTP/Request2/CookieJar.php
@@ -0,0 +1,499 @@
+<?php
+/**
+ * Stores cookies and passes them between HTTP requests
+ *
+ * PHP version 5
+ *
+ * LICENSE:
+ *
+ * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version SVN: $Id: CookieJar.php 308629 2011-02-24 17:34:24Z avb $
+ * @link http://pear.php.net/package/HTTP_Request2
+ */
+
+/** Class representing a HTTP request message */
+require_once 'HTTP/Request2.php';
+
+/**
+ * Stores cookies and passes them between HTTP requests
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @version Release: @package_version@
+ */
+class HTTP_Request2_CookieJar implements Serializable
+{
+ /**
+ * Array of stored cookies
+ *
+ * The array is indexed by domain, path and cookie name
+ * .example.com
+ * /
+ * some_cookie => cookie data
+ * /subdir
+ * other_cookie => cookie data
+ * .example.org
+ * ...
+ *
+ * @var array
+ */
+ protected $cookies = array();
+
+ /**
+ * Whether session cookies should be serialized when serializing the jar
+ * @var bool
+ */
+ protected $serializeSession = false;
+
+ /**
+ * Whether Public Suffix List should be used for domain matching
+ * @var bool
+ */
+ protected $useList = true;
+
+ /**
+ * Array with Public Suffix List data
+ * @var array
+ * @link http://publicsuffix.org/
+ */
+ protected static $psl = array();
+
+ /**
+ * Class constructor, sets various options
+ *
+ * @param bool Controls serializing session cookies, see {@link serializeSessionCookies()}
+ * @param bool Controls using Public Suffix List, see {@link usePublicSuffixList()}
+ */
+ public function __construct($serializeSessionCookies = false, $usePublicSuffixList = true)
+ {
+ $this->serializeSessionCookies($serializeSessionCookies);
+ $this->usePublicSuffixList($usePublicSuffixList);
+ }
+
+ /**
+ * Returns current time formatted in ISO-8601 at UTC timezone
+ *
+ * @return string
+ */
+ protected function now()
+ {
+ $dt = new DateTime();
+ $dt->setTimezone(new DateTimeZone('UTC'));
+ return $dt->format(DateTime::ISO8601);
+ }
+
+ /**
+ * Checks cookie array for correctness, possibly updating its 'domain', 'path' and 'expires' fields
+ *
+ * The checks are as follows:
+ * - cookie array should contain 'name' and 'value' fields;
+ * - name and value should not contain disallowed symbols;
+ * - 'expires' should be either empty parseable by DateTime;
+ * - 'domain' and 'path' should be either not empty or an URL where
+ * cookie was set should be provided.
+ * - if $setter is provided, then document at that URL should be allowed
+ * to set a cookie for that 'domain'. If $setter is not provided,
+ * then no domain checks will be made.
+ *
+ * 'expires' field will be converted to ISO8601 format from COOKIE format,
+ * 'domain' and 'path' will be set from setter URL if empty.
+ *
+ * @param array cookie data, as returned by {@link HTTP_Request2_Response::getCookies()}
+ * @param Net_URL2 URL of the document that sent Set-Cookie header
+ * @return array Updated cookie array
+ * @throws HTTP_Request2_LogicException
+ * @throws HTTP_Request2_MessageException
+ */
+ protected function checkAndUpdateFields(array $cookie, Net_URL2 $setter = null)
+ {
+ if ($missing = array_diff(array('name', 'value'), array_keys($cookie))) {
+ throw new HTTP_Request2_LogicException(
+ "Cookie array should contain 'name' and 'value' fields",
+ HTTP_Request2_Exception::MISSING_VALUE
+ );
+ }
+ if (preg_match(HTTP_Request2::REGEXP_INVALID_COOKIE, $cookie['name'])) {
+ throw new HTTP_Request2_LogicException(
+ "Invalid cookie name: '{$cookie['name']}'",
+ HTTP_Request2_Exception::INVALID_ARGUMENT
+ );
+ }
+ if (preg_match(HTTP_Request2::REGEXP_INVALID_COOKIE, $cookie['value'])) {
+ throw new HTTP_Request2_LogicException(
+ "Invalid cookie value: '{$cookie['value']}'",
+ HTTP_Request2_Exception::INVALID_ARGUMENT
+ );
+ }
+ $cookie += array('domain' => '', 'path' => '', 'expires' => null, 'secure' => false);
+
+ // Need ISO-8601 date @ UTC timezone
+ if (!empty($cookie['expires'])
+ && !preg_match('/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+0000$/', $cookie['expires'])
+ ) {
+ try {
+ $dt = new DateTime($cookie['expires']);
+ $dt->setTimezone(new DateTimeZone('UTC'));
+ $cookie['expires'] = $dt->format(DateTime::ISO8601);
+ } catch (Exception $e) {
+ throw new HTTP_Request2_LogicException($e->getMessage());
+ }
+ }
+
+ if (empty($cookie['domain']) || empty($cookie['path'])) {
+ if (!$setter) {
+ throw new HTTP_Request2_LogicException(
+ 'Cookie misses domain and/or path component, cookie setter URL needed',
+ HTTP_Request2_Exception::MISSING_VALUE
+ );
+ }
+ if (empty($cookie['domain'])) {
+ if ($host = $setter->getHost()) {
+ $cookie['domain'] = $host;
+ } else {
+ throw new HTTP_Request2_LogicException(
+ 'Setter URL does not contain host part, can\'t set cookie domain',
+ HTTP_Request2_Exception::MISSING_VALUE
+ );
+ }
+ }
+ if (empty($cookie['path'])) {
+ $path = $setter->getPath();
+ $cookie['path'] = empty($path)? '/': substr($path, 0, strrpos($path, '/') + 1);
+ }
+ }
+
+ if ($setter && !$this->domainMatch($setter->getHost(), $cookie['domain'])) {
+ throw new HTTP_Request2_MessageException(
+ "Domain " . $setter->getHost() . " cannot set cookies for "
+ . $cookie['domain']
+ );
+ }
+
+ return $cookie;
+ }
+
+ /**
+ * Stores a cookie in the jar
+ *
+ * @param array cookie data, as returned by {@link HTTP_Request2_Response::getCookies()}
+ * @param Net_URL2 URL of the document that sent Set-Cookie header
+ * @throws HTTP_Request2_Exception
+ */
+ public function store(array $cookie, Net_URL2 $setter = null)
+ {
+ $cookie = $this->checkAndUpdateFields($cookie, $setter);
+
+ if (strlen($cookie['value'])
+ && (is_null($cookie['expires']) || $cookie['expires'] > $this->now())
+ ) {
+ if (!isset($this->cookies[$cookie['domain']])) {
+ $this->cookies[$cookie['domain']] = array();
+ }
+ if (!isset($this->cookies[$cookie['domain']][$cookie['path']])) {
+ $this->cookies[$cookie['domain']][$cookie['path']] = array();
+ }
+ $this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']] = $cookie;
+
+ } elseif (isset($this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']])) {
+ unset($this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']]);
+ }
+ }
+
+ /**
+ * Adds cookies set in HTTP response to the jar
+ *
+ * @param HTTP_Request2_Response response
+ * @param Net_URL2 original request URL, needed for setting
+ * default domain/path
+ */
+ public function addCookiesFromResponse(HTTP_Request2_Response $response, Net_URL2 $setter)
+ {
+ foreach ($response->getCookies() as $cookie) {
+ $this->store($cookie, $setter);
+ }
+ }
+
+ /**
+ * Returns all cookies matching a given request URL
+ *
+ * The following checks are made:
+ * - cookie domain should match request host
+ * - cookie path should be a prefix for request path
+ * - 'secure' cookies will only be sent for HTTPS requests
+ *
+ * @param Net_URL2
+ * @param bool Whether to return cookies as string for "Cookie: " header
+ * @return array
+ */
+ public function getMatching(Net_URL2 $url, $asString = false)
+ {
+ $host = $url->getHost();
+ $path = $url->getPath();
+ $secure = 0 == strcasecmp($url->getScheme(), 'https');
+
+ $matched = $ret = array();
+ foreach (array_keys($this->cookies) as $domain) {
+ if ($this->domainMatch($host, $domain)) {
+ foreach (array_keys($this->cookies[$domain]) as $cPath) {
+ if (0 === strpos($path, $cPath)) {
+ foreach ($this->cookies[$domain][$cPath] as $name => $cookie) {
+ if (!$cookie['secure'] || $secure) {
+ $matched[$name][strlen($cookie['path'])] = $cookie;
+ }
+ }
+ }
+ }
+ }
+ }
+ foreach ($matched as $cookies) {
+ krsort($cookies);
+ $ret = array_merge($ret, $cookies);
+ }
+ if (!$asString) {
+ return $ret;
+ } else {
+ $str = '';
+ foreach ($ret as $c) {
+ $str .= (empty($str)? '': '; ') . $c['name'] . '=' . $c['value'];
+ }
+ return $str;
+ }
+ }
+
+ /**
+ * Returns all cookies stored in a jar
+ *
+ * @return array
+ */
+ public function getAll()
+ {
+ $cookies = array();
+ foreach (array_keys($this->cookies) as $domain) {
+ foreach (array_keys($this->cookies[$domain]) as $path) {
+ foreach ($this->cookies[$domain][$path] as $name => $cookie) {
+ $cookies[] = $cookie;
+ }
+ }
+ }
+ return $cookies;
+ }
+
+ /**
+ * Sets whether session cookies should be serialized when serializing the jar
+ *
+ * @param boolean
+ */
+ public function serializeSessionCookies($serialize)
+ {
+ $this->serializeSession = (bool)$serialize;
+ }
+
+ /**
+ * Sets whether Public Suffix List should be used for restricting cookie-setting
+ *
+ * Without PSL {@link domainMatch()} will only prevent setting cookies for
+ * top-level domains like '.com' or '.org'. However, it will not prevent
+ * setting a cookie for '.co.uk' even though only third-level registrations
+ * are possible in .uk domain.
+ *
+ * With the List it is possible to find the highest level at which a domain
+ * may be registered for a particular top-level domain and consequently
+ * prevent cookies set for '.co.uk' or '.msk.ru'. The same list is used by
+ * Firefox, Chrome and Opera browsers to restrict cookie setting.
+ *
+ * Note that PSL is licensed differently to HTTP_Request2 package (refer to
+ * the license information in public-suffix-list.php), so you can disable
+ * its use if this is an issue for you.
+ *
+ * @param boolean
+ * @link http://publicsuffix.org/learn/
+ */
+ public function usePublicSuffixList($useList)
+ {
+ $this->useList = (bool)$useList;
+ }
+
+ /**
+ * Returns string representation of object
+ *
+ * @return string
+ * @see Serializable::serialize()
+ */
+ public function serialize()
+ {
+ $cookies = $this->getAll();
+ if (!$this->serializeSession) {
+ for ($i = count($cookies) - 1; $i >= 0; $i--) {
+ if (empty($cookies[$i]['expires'])) {
+ unset($cookies[$i]);
+ }
+ }
+ }
+ return serialize(array(
+ 'cookies' => $cookies,
+ 'serializeSession' => $this->serializeSession,
+ 'useList' => $this->useList
+ ));
+ }
+
+ /**
+ * Constructs the object from serialized string
+ *
+ * @param string string representation
+ * @see Serializable::unserialize()
+ */
+ public function unserialize($serialized)
+ {
+ $data = unserialize($serialized);
+ $now = $this->now();
+ $this->serializeSessionCookies($data['serializeSession']);
+ $this->usePublicSuffixList($data['useList']);
+ foreach ($data['cookies'] as $cookie) {
+ if (!empty($cookie['expires']) && $cookie['expires'] <= $now) {
+ continue;
+ }
+ if (!isset($this->cookies[$cookie['domain']])) {
+ $this->cookies[$cookie['domain']] = array();
+ }
+ if (!isset($this->cookies[$cookie['domain']][$cookie['path']])) {
+ $this->cookies[$cookie['domain']][$cookie['path']] = array();
+ }
+ $this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']] = $cookie;
+ }
+ }
+
+ /**
+ * Checks whether a cookie domain matches a request host.
+ *
+ * The method is used by {@link store()} to check for whether a document
+ * at given URL can set a cookie with a given domain attribute and by
+ * {@link getMatching()} to find cookies matching the request URL.
+ *
+ * @param string request host
+ * @param string cookie domain
+ * @return bool match success
+ */
+ public function domainMatch($requestHost, $cookieDomain)
+ {
+ if ($requestHost == $cookieDomain) {
+ return true;
+ }
+ // IP address, we require exact match
+ if (preg_match('/^(?:\d{1,3}\.){3}\d{1,3}$/', $requestHost)) {
+ return false;
+ }
+ if ('.' != $cookieDomain[0]) {
+ $cookieDomain = '.' . $cookieDomain;
+ }
+ // prevents setting cookies for '.com' and similar domains
+ if (!$this->useList && substr_count($cookieDomain, '.') < 2
+ || $this->useList && !self::getRegisteredDomain($cookieDomain)
+ ) {
+ return false;
+ }
+ return substr('.' . $requestHost, -strlen($cookieDomain)) == $cookieDomain;
+ }
+
+ /**
+ * Removes subdomains to get the registered domain (the first after top-level)
+ *
+ * The method will check Public Suffix List to find out where top-level
+ * domain ends and registered domain starts. It will remove domain parts
+ * to the left of registered one.
+ *
+ * @param string domain name
+ * @return string|bool registered domain, will return false if $domain is
+ * either invalid or a TLD itself
+ */
+ public static function getRegisteredDomain($domain)
+ {
+ $domainParts = explode('.', ltrim($domain, '.'));
+
+ // load the list if needed
+ if (empty(self::$psl)) {
+ $path = '@data_dir@' . DIRECTORY_SEPARATOR . 'HTTP_Request2';
+ if (0 === strpos($path, '@' . 'data_dir@')) {
+ $path = realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..'
+ . DIRECTORY_SEPARATOR . 'data');
+ }
+ self::$psl = include_once $path . DIRECTORY_SEPARATOR . 'public-suffix-list.php';
+ }
+
+ if (!($result = self::checkDomainsList($domainParts, self::$psl))) {
+ // known TLD, invalid domain name
+ return false;
+ }
+
+ // unknown TLD
+ if (!strpos($result, '.')) {
+ // fallback to checking that domain "has at least two dots"
+ if (2 > ($count = count($domainParts))) {
+ return false;
+ }
+ return $domainParts[$count - 2] . '.' . $domainParts[$count - 1];
+ }
+ return $result;
+ }
+
+ /**
+ * Recursive helper method for {@link getRegisteredDomain()}
+ *
+ * @param array remaining domain parts
+ * @param mixed node in {@link HTTP_Request2_CookieJar::$psl} to check
+ * @return string|null concatenated domain parts, null in case of error
+ */
+ protected static function checkDomainsList(array $domainParts, $listNode)
+ {
+ $sub = array_pop($domainParts);
+ $result = null;
+
+ if (!is_array($listNode) || is_null($sub)
+ || array_key_exists('!' . $sub, $listNode)
+ ) {
+ return $sub;
+
+ } elseif (array_key_exists($sub, $listNode)) {
+ $result = self::checkDomainsList($domainParts, $listNode[$sub]);
+
+ } elseif (array_key_exists('*', $listNode)) {
+ $result = self::checkDomainsList($domainParts, $listNode['*']);
+
+ } else {
+ return $sub;
+ }
+
+ return (strlen($result) > 0) ? ($result . '.' . $sub) : null;
+ }
+}
+?> \ No newline at end of file
diff --git a/public_html/lib/HTTP/Request2/Exception.php b/public_html/lib/HTTP/Request2/Exception.php
new file mode 100644
index 0000000..34256c2
--- /dev/null
+++ b/public_html/lib/HTTP/Request2/Exception.php
@@ -0,0 +1,160 @@
+<?php
+/**
+ * Exception classes for HTTP_Request2 package
+ *
+ * PHP version 5
+ *
+ * LICENSE:
+ *
+ * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version SVN: $Id: Exception.php 308629 2011-02-24 17:34:24Z avb $
+ * @link http://pear.php.net/package/HTTP_Request2
+ */
+
+/**
+ * Base class for exceptions in PEAR
+ */
+require_once 'PEAR/Exception.php';
+
+/**
+ * Base exception class for HTTP_Request2 package
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @version Release: 2.0.0
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=132
+ */
+class HTTP_Request2_Exception extends PEAR_Exception
+{
+ /** An invalid argument was passed to a method */
+ const INVALID_ARGUMENT = 1;
+ /** Some required value was not available */
+ const MISSING_VALUE = 2;
+ /** Request cannot be processed due to errors in PHP configuration */
+ const MISCONFIGURATION = 3;
+ /** Error reading the local file */
+ const READ_ERROR = 4;
+
+ /** Server returned a response that does not conform to HTTP protocol */
+ const MALFORMED_RESPONSE = 10;
+ /** Failure decoding Content-Encoding or Transfer-Encoding of response */
+ const DECODE_ERROR = 20;
+ /** Operation timed out */
+ const TIMEOUT = 30;
+ /** Number of redirects exceeded 'max_redirects' configuration parameter */
+ const TOO_MANY_REDIRECTS = 40;
+ /** Redirect to a protocol other than http(s):// */
+ const NON_HTTP_REDIRECT = 50;
+
+ /**
+ * Native error code
+ * @var int
+ */
+ private $_nativeCode;
+
+ /**
+ * Constructor, can set package error code and native error code
+ *
+ * @param string exception message
+ * @param int package error code, one of class constants
+ * @param int error code from underlying PHP extension
+ */
+ public function __construct($message = null, $code = null, $nativeCode = null)
+ {
+ parent::__construct($message, $code);
+ $this->_nativeCode = $nativeCode;
+ }
+
+ /**
+ * Returns error code produced by underlying PHP extension
+ *
+ * For Socket Adapter this may contain error number returned by
+ * stream_socket_client(), for Curl Adapter this will contain error number
+ * returned by curl_errno()
+ *
+ * @return integer
+ */
+ public function getNativeCode()
+ {
+ return $this->_nativeCode;
+ }
+}
+
+/**
+ * Exception thrown in case of missing features
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @version Release: 2.0.0
+ */
+class HTTP_Request2_NotImplementedException extends HTTP_Request2_Exception {}
+
+/**
+ * Exception that represents error in the program logic
+ *
+ * This exception usually implies a programmer's error, like passing invalid
+ * data to methods or trying to use PHP extensions that weren't installed or
+ * enabled. Usually exceptions of this kind will be thrown before request even
+ * starts.
+ *
+ * The exception will usually contain a package error code.
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @version Release: 2.0.0
+ */
+class HTTP_Request2_LogicException extends HTTP_Request2_Exception {}
+
+/**
+ * Exception thrown when connection to a web or proxy server fails
+ *
+ * The exception will not contain a package error code, but will contain
+ * native error code, as returned by stream_socket_client() or curl_errno().
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @version Release: 2.0.0
+ */
+class HTTP_Request2_ConnectionException extends HTTP_Request2_Exception {}
+
+/**
+ * Exception thrown when sending or receiving HTTP message fails
+ *
+ * The exception may contain both package error code and native error code.
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @version Release: 2.0.0
+ */
+class HTTP_Request2_MessageException extends HTTP_Request2_Exception {}
+?> \ No newline at end of file
diff --git a/public_html/lib/HTTP/Request2/MultipartBody.php b/public_html/lib/HTTP/Request2/MultipartBody.php
new file mode 100644
index 0000000..021a199
--- /dev/null
+++ b/public_html/lib/HTTP/Request2/MultipartBody.php
@@ -0,0 +1,274 @@
+<?php
+/**
+ * Helper class for building multipart/form-data request body
+ *
+ * PHP version 5
+ *
+ * LICENSE:
+ *
+ * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version SVN: $Id: MultipartBody.php 308322 2011-02-14 13:58:03Z avb $
+ * @link http://pear.php.net/package/HTTP_Request2
+ */
+
+/**
+ * Class for building multipart/form-data request body
+ *
+ * The class helps to reduce memory consumption by streaming large file uploads
+ * from disk, it also allows monitoring of upload progress (see request #7630)
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @version Release: 2.0.0
+ * @link http://tools.ietf.org/html/rfc1867
+ */
+class HTTP_Request2_MultipartBody
+{
+ /**
+ * MIME boundary
+ * @var string
+ */
+ private $_boundary;
+
+ /**
+ * Form parameters added via {@link HTTP_Request2::addPostParameter()}
+ * @var array
+ */
+ private $_params = array();
+
+ /**
+ * File uploads added via {@link HTTP_Request2::addUpload()}
+ * @var array
+ */
+ private $_uploads = array();
+
+ /**
+ * Header for parts with parameters
+ * @var string
+ */
+ private $_headerParam = "--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n";
+
+ /**
+ * Header for parts with uploads
+ * @var string
+ */
+ private $_headerUpload = "--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\nContent-Type: %s\r\n\r\n";
+
+ /**
+ * Current position in parameter and upload arrays
+ *
+ * First number is index of "current" part, second number is position within
+ * "current" part
+ *
+ * @var array
+ */
+ private $_pos = array(0, 0);
+
+
+ /**
+ * Constructor. Sets the arrays with POST data.
+ *
+ * @param array values of form fields set via {@link HTTP_Request2::addPostParameter()}
+ * @param array file uploads set via {@link HTTP_Request2::addUpload()}
+ * @param bool whether to append brackets to array variable names
+ */
+ public function __construct(array $params, array $uploads, $useBrackets = true)
+ {
+ $this->_params = self::_flattenArray('', $params, $useBrackets);
+ foreach ($uploads as $fieldName => $f) {
+ if (!is_array($f['fp'])) {
+ $this->_uploads[] = $f + array('name' => $fieldName);
+ } else {
+ for ($i = 0; $i < count($f['fp']); $i++) {
+ $upload = array(
+ 'name' => ($useBrackets? $fieldName . '[' . $i . ']': $fieldName)
+ );
+ foreach (array('fp', 'filename', 'size', 'type') as $key) {
+ $upload[$key] = $f[$key][$i];
+ }
+ $this->_uploads[] = $upload;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the length of the body to use in Content-Length header
+ *
+ * @return integer
+ */
+ public function getLength()
+ {
+ $boundaryLength = strlen($this->getBoundary());
+ $headerParamLength = strlen($this->_headerParam) - 4 + $boundaryLength;
+ $headerUploadLength = strlen($this->_headerUpload) - 8 + $boundaryLength;
+ $length = $boundaryLength + 6;
+ foreach ($this->_params as $p) {
+ $length += $headerParamLength + strlen($p[0]) + strlen($p[1]) + 2;
+ }
+ foreach ($this->_uploads as $u) {
+ $length += $headerUploadLength + strlen($u['name']) + strlen($u['type']) +
+ strlen($u['filename']) + $u['size'] + 2;
+ }
+ return $length;
+ }
+
+ /**
+ * Returns the boundary to use in Content-Type header
+ *
+ * @return string
+ */
+ public function getBoundary()
+ {
+ if (empty($this->_boundary)) {
+ $this->_boundary = '--' . md5('PEAR-HTTP_Request2-' . microtime());
+ }
+ return $this->_boundary;
+ }
+
+ /**
+ * Returns next chunk of request body
+ *
+ * @param integer Amount of bytes to read
+ * @return string Up to $length bytes of data, empty string if at end
+ */
+ public function read($length)
+ {
+ $ret = '';
+ $boundary = $this->getBoundary();
+ $paramCount = count($this->_params);
+ $uploadCount = count($this->_uploads);
+ while ($length > 0 && $this->_pos[0] <= $paramCount + $uploadCount) {
+ $oldLength = $length;
+ if ($this->_pos[0] < $paramCount) {
+ $param = sprintf($this->_headerParam, $boundary,
+ $this->_params[$this->_pos[0]][0]) .
+ $this->_params[$this->_pos[0]][1] . "\r\n";
+ $ret .= substr($param, $this->_pos[1], $length);
+ $length -= min(strlen($param) - $this->_pos[1], $length);
+
+ } elseif ($this->_pos[0] < $paramCount + $uploadCount) {
+ $pos = $this->_pos[0] - $paramCount;
+ $header = sprintf($this->_headerUpload, $boundary,
+ $this->_uploads[$pos]['name'],
+ $this->_uploads[$pos]['filename'],
+ $this->_uploads[$pos]['type']);
+ if ($this->_pos[1] < strlen($header)) {
+ $ret .= substr($header, $this->_pos[1], $length);
+ $length -= min(strlen($header) - $this->_pos[1], $length);
+ }
+ $filePos = max(0, $this->_pos[1] - strlen($header));
+ if ($length > 0 && $filePos < $this->_uploads[$pos]['size']) {
+ $ret .= fread($this->_uploads[$pos]['fp'], $length);
+ $length -= min($length, $this->_uploads[$pos]['size'] - $filePos);
+ }
+ if ($length > 0) {
+ $start = $this->_pos[1] + ($oldLength - $length) -
+ strlen($header) - $this->_uploads[$pos]['size'];
+ $ret .= substr("\r\n", $start, $length);
+ $length -= min(2 - $start, $length);
+ }
+
+ } else {
+ $closing = '--' . $boundary . "--\r\n";
+ $ret .= substr($closing, $this->_pos[1], $length);
+ $length -= min(strlen($closing) - $this->_pos[1], $length);
+ }
+ if ($length > 0) {
+ $this->_pos = array($this->_pos[0] + 1, 0);
+ } else {
+ $this->_pos[1] += $oldLength;
+ }
+ }
+ return $ret;
+ }
+
+ /**
+ * Sets the current position to the start of the body
+ *
+ * This allows reusing the same body in another request
+ */
+ public function rewind()
+ {
+ $this->_pos = array(0, 0);
+ foreach ($this->_uploads as $u) {
+ rewind($u['fp']);
+ }
+ }
+
+ /**
+ * Returns the body as string
+ *
+ * Note that it reads all file uploads into memory so it is a good idea not
+ * to use this method with large file uploads and rely on read() instead.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $this->rewind();
+ return $this->read($this->getLength());
+ }
+
+
+ /**
+ * Helper function to change the (probably multidimensional) associative array
+ * into the simple one.
+ *
+ * @param string name for item
+ * @param mixed item's values
+ * @param bool whether to append [] to array variables' names
+ * @return array array with the following items: array('item name', 'item value');
+ */
+ private static function _flattenArray($name, $values, $useBrackets)
+ {
+ if (!is_array($values)) {
+ return array(array($name, $values));
+ } else {
+ $ret = array();
+ foreach ($values as $k => $v) {
+ if (empty($name)) {
+ $newName = $k;
+ } elseif ($useBrackets) {
+ $newName = $name . '[' . $k . ']';
+ } else {
+ $newName = $name;
+ }
+ $ret = array_merge($ret, self::_flattenArray($newName, $v, $useBrackets));
+ }
+ return $ret;
+ }
+ }
+}
+?>
diff --git a/public_html/lib/HTTP/Request2/Observer/Log.php b/public_html/lib/HTTP/Request2/Observer/Log.php
new file mode 100644
index 0000000..dd59859
--- /dev/null
+++ b/public_html/lib/HTTP/Request2/Observer/Log.php
@@ -0,0 +1,215 @@
+<?php
+/**
+ * An observer useful for debugging / testing.
+ *
+ * PHP version 5
+ *
+ * LICENSE:
+ *
+ * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author David Jean Louis <izi@php.net>
+ * @author Alexey Borzov <avb@php.net>
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version SVN: $Id: Log.php 308680 2011-02-25 17:40:17Z avb $
+ * @link http://pear.php.net/package/HTTP_Request2
+ */
+
+/**
+ * Exception class for HTTP_Request2 package
+ */
+require_once 'HTTP/Request2/Exception.php';
+
+/**
+ * A debug observer useful for debugging / testing.
+ *
+ * This observer logs to a log target data corresponding to the various request
+ * and response events, it logs by default to php://output but can be configured
+ * to log to a file or via the PEAR Log package.
+ *
+ * A simple example:
+ * <code>
+ * require_once 'HTTP/Request2.php';
+ * require_once 'HTTP/Request2/Observer/Log.php';
+ *
+ * $request = new HTTP_Request2('http://www.example.com');
+ * $observer = new HTTP_Request2_Observer_Log();
+ * $request->attach($observer);
+ * $request->send();
+ * </code>
+ *
+ * A more complex example with PEAR Log:
+ * <code>
+ * require_once 'HTTP/Request2.php';
+ * require_once 'HTTP/Request2/Observer/Log.php';
+ * require_once 'Log.php';
+ *
+ * $request = new HTTP_Request2('http://www.example.com');
+ * // we want to log with PEAR log
+ * $observer = new HTTP_Request2_Observer_Log(Log::factory('console'));
+ *
+ * // we only want to log received headers
+ * $observer->events = array('receivedHeaders');
+ *
+ * $request->attach($observer);
+ * $request->send();
+ * </code>
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author David Jean Louis <izi@php.net>
+ * @author Alexey Borzov <avb@php.net>
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 2.0.0
+ * @link http://pear.php.net/package/HTTP_Request2
+ */
+class HTTP_Request2_Observer_Log implements SplObserver
+{
+ // properties {{{
+
+ /**
+ * The log target, it can be a a resource or a PEAR Log instance.
+ *
+ * @var resource|Log $target
+ */
+ protected $target = null;
+
+ /**
+ * The events to log.
+ *
+ * @var array $events
+ */
+ public $events = array(
+ 'connect',
+ 'sentHeaders',
+ 'sentBody',
+ 'receivedHeaders',
+ 'receivedBody',
+ 'disconnect',
+ );
+
+ // }}}
+ // __construct() {{{
+
+ /**
+ * Constructor.
+ *
+ * @param mixed $target Can be a file path (default: php://output), a resource,
+ * or an instance of the PEAR Log class.
+ * @param array $events Array of events to listen to (default: all events)
+ *
+ * @return void
+ */
+ public function __construct($target = 'php://output', array $events = array())
+ {
+ if (!empty($events)) {
+ $this->events = $events;
+ }
+ if (is_resource($target) || $target instanceof Log) {
+ $this->target = $target;
+ } elseif (false === ($this->target = @fopen($target, 'ab'))) {
+ throw new HTTP_Request2_Exception("Unable to open '{$target}'");
+ }
+ }
+
+ // }}}
+ // update() {{{
+
+ /**
+ * Called when the request notifies us of an event.
+ *
+ * @param HTTP_Request2 $subject The HTTP_Request2 instance
+ *
+ * @return void
+ */
+ public function update(SplSubject $subject)
+ {
+ $event = $subject->getLastEvent();
+ if (!in_array($event['name'], $this->events)) {
+ return;
+ }
+
+ switch ($event['name']) {
+ case 'connect':
+ $this->log('* Connected to ' . $event['data']);
+ break;
+ case 'sentHeaders':
+ $headers = explode("\r\n", $event['data']);
+ array_pop($headers);
+ foreach ($headers as $header) {
+ $this->log('> ' . $header);
+ }
+ break;
+ case 'sentBody':
+ $this->log('> ' . $event['data'] . ' byte(s) sent');
+ break;
+ case 'receivedHeaders':
+ $this->log(sprintf('< HTTP/%s %s %s',
+ $event['data']->getVersion(),
+ $event['data']->getStatus(),
+ $event['data']->getReasonPhrase()));
+ $headers = $event['data']->getHeader();
+ foreach ($headers as $key => $val) {
+ $this->log('< ' . $key . ': ' . $val);
+ }
+ $this->log('< ');
+ break;
+ case 'receivedBody':
+ $this->log($event['data']->getBody());
+ break;
+ case 'disconnect':
+ $this->log('* Disconnected');
+ break;
+ }
+ }
+
+ // }}}
+ // log() {{{
+
+ /**
+ * Logs the given message to the configured target.
+ *
+ * @param string $message Message to display
+ *
+ * @return void
+ */
+ protected function log($message)
+ {
+ if ($this->target instanceof Log) {
+ $this->target->debug($message);
+ } elseif (is_resource($this->target)) {
+ fwrite($this->target, $message . "\r\n");
+ }
+ }
+
+ // }}}
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/HTTP/Request2/Response.php b/public_html/lib/HTTP/Request2/Response.php
new file mode 100644
index 0000000..6e0f659
--- /dev/null
+++ b/public_html/lib/HTTP/Request2/Response.php
@@ -0,0 +1,643 @@
+<?php
+/**
+ * Class representing a HTTP response
+ *
+ * PHP version 5
+ *
+ * LICENSE:
+ *
+ * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version SVN: $Id: Response.php 317591 2011-10-01 08:37:49Z avb $
+ * @link http://pear.php.net/package/HTTP_Request2
+ */
+
+/**
+ * Exception class for HTTP_Request2 package
+ */
+require_once 'HTTP/Request2/Exception.php';
+
+/**
+ * Class representing a HTTP response
+ *
+ * The class is designed to be used in "streaming" scenario, building the
+ * response as it is being received:
+ * <code>
+ * $statusLine = read_status_line();
+ * $response = new HTTP_Request2_Response($statusLine);
+ * do {
+ * $headerLine = read_header_line();
+ * $response->parseHeaderLine($headerLine);
+ * } while ($headerLine != '');
+ *
+ * while ($chunk = read_body()) {
+ * $response->appendBody($chunk);
+ * }
+ *
+ * var_dump($response->getHeader(), $response->getCookies(), $response->getBody());
+ * </code>
+ *
+ *
+ * @category HTTP
+ * @package HTTP_Request2
+ * @author Alexey Borzov <avb@php.net>
+ * @version Release: 2.0.0
+ * @link http://tools.ietf.org/html/rfc2616#section-6
+ */
+class HTTP_Request2_Response
+{
+ /**
+ * HTTP protocol version (e.g. 1.0, 1.1)
+ * @var string
+ */
+ protected $version;
+
+ /**
+ * Status code
+ * @var integer
+ * @link http://tools.ietf.org/html/rfc2616#section-6.1.1
+ */
+ protected $code;
+
+ /**
+ * Reason phrase
+ * @var string
+ * @link http://tools.ietf.org/html/rfc2616#section-6.1.1
+ */
+ protected $reasonPhrase;
+
+ /**
+ * Effective URL (may be different from original request URL in case of redirects)
+ * @var string
+ */
+ protected $effectiveUrl;
+
+ /**
+ * Associative array of response headers
+ * @var array
+ */
+ protected $headers = array();
+
+ /**
+ * Cookies set in the response
+ * @var array
+ */
+ protected $cookies = array();
+
+ /**
+ * Name of last header processed by parseHederLine()
+ *
+ * Used to handle the headers that span multiple lines
+ *
+ * @var string
+ */
+ protected $lastHeader = null;
+
+ /**
+ * Response body
+ * @var string
+ */
+ protected $body = '';
+
+ /**
+ * Whether the body is still encoded by Content-Encoding
+ *
+ * cURL provides the decoded body to the callback; if we are reading from
+ * socket the body is still gzipped / deflated
+ *
+ * @var bool
+ */
+ protected $bodyEncoded;
+
+ /**
+ * Associative array of HTTP status code / reason phrase.
+ *
+ * @var array
+ * @link http://tools.ietf.org/html/rfc2616#section-10
+ */
+ protected static $phrases = array(
+
+ // 1xx: Informational - Request received, continuing process
+ 100 => 'Continue',
+ 101 => 'Switching Protocols',
+
+ // 2xx: Success - The action was successfully received, understood and
+ // accepted
+ 200 => 'OK',
+ 201 => 'Created',
+ 202 => 'Accepted',
+ 203 => 'Non-Authoritative Information',
+ 204 => 'No Content',
+ 205 => 'Reset Content',
+ 206 => 'Partial Content',
+
+ // 3xx: Redirection - Further action must be taken in order to complete
+ // the request
+ 300 => 'Multiple Choices',
+ 301 => 'Moved Permanently',
+ 302 => 'Found', // 1.1
+ 303 => 'See Other',
+ 304 => 'Not Modified',
+ 305 => 'Use Proxy',
+ 307 => 'Temporary Redirect',
+
+ // 4xx: Client Error - The request contains bad syntax or cannot be
+ // fulfilled
+ 400 => 'Bad Request',
+ 401 => 'Unauthorized',
+ 402 => 'Payment Required',
+ 403 => 'Forbidden',
+ 404 => 'Not Found',
+ 405 => 'Method Not Allowed',
+ 406 => 'Not Acceptable',
+ 407 => 'Proxy Authentication Required',
+ 408 => 'Request Timeout',
+ 409 => 'Conflict',
+ 410 => 'Gone',
+ 411 => 'Length Required',
+ 412 => 'Precondition Failed',
+ 413 => 'Request Entity Too Large',
+ 414 => 'Request-URI Too Long',
+ 415 => 'Unsupported Media Type',
+ 416 => 'Requested Range Not Satisfiable',
+ 417 => 'Expectation Failed',
+
+ // 5xx: Server Error - The server failed to fulfill an apparently
+ // valid request
+ 500 => 'Internal Server Error',
+ 501 => 'Not Implemented',
+ 502 => 'Bad Gateway',
+ 503 => 'Service Unavailable',
+ 504 => 'Gateway Timeout',
+ 505 => 'HTTP Version Not Supported',
+ 509 => 'Bandwidth Limit Exceeded',
+
+ );
+
+ /**
+ * Returns the default reason phrase for the given code or all reason phrases
+ *
+ * @param int $code Response code
+ * @return string|array|null Default reason phrase for $code if $code is given
+ * (null if no phrase is available), array of all
+ * reason phrases if $code is null
+ * @link http://pear.php.net/bugs/18716
+ */
+ public static function getDefaultReasonPhrase($code = null)
+ {
+ if (null === $code) {
+ return self::$phrases;
+ } else {
+ return isset(self::$phrases[$code]) ? self::$phrases[$code] : null;
+ }
+ }
+
+ /**
+ * Constructor, parses the response status line
+ *
+ * @param string Response status line (e.g. "HTTP/1.1 200 OK")
+ * @param bool Whether body is still encoded by Content-Encoding
+ * @param string Effective URL of the response
+ * @throws HTTP_Request2_MessageException if status line is invalid according to spec
+ */
+ public function __construct($statusLine, $bodyEncoded = true, $effectiveUrl = null)
+ {
+ if (!preg_match('!^HTTP/(\d\.\d) (\d{3})(?: (.+))?!', $statusLine, $m)) {
+ throw new HTTP_Request2_MessageException(
+ "Malformed response: {$statusLine}",
+ HTTP_Request2_Exception::MALFORMED_RESPONSE
+ );
+ }
+ $this->version = $m[1];
+ $this->code = intval($m[2]);
+ $this->reasonPhrase = !empty($m[3]) ? trim($m[3]) : self::getDefaultReasonPhrase($this->code);
+ $this->bodyEncoded = (bool)$bodyEncoded;
+ $this->effectiveUrl = (string)$effectiveUrl;
+ }
+
+ /**
+ * Parses the line from HTTP response filling $headers array
+ *
+ * The method should be called after reading the line from socket or receiving
+ * it into cURL callback. Passing an empty string here indicates the end of
+ * response headers and triggers additional processing, so be sure to pass an
+ * empty string in the end.
+ *
+ * @param string Line from HTTP response
+ */
+ public function parseHeaderLine($headerLine)
+ {
+ $headerLine = trim($headerLine, "\r\n");
+
+ // empty string signals the end of headers, process the received ones
+ if ('' == $headerLine) {
+ if (!empty($this->headers['set-cookie'])) {
+ $cookies = is_array($this->headers['set-cookie'])?
+ $this->headers['set-cookie']:
+ array($this->headers['set-cookie']);
+ foreach ($cookies as $cookieString) {
+ $this->parseCookie($cookieString);
+ }
+ unset($this->headers['set-cookie']);
+ }
+ foreach (array_keys($this->headers) as $k) {
+ if (is_array($this->headers[$k])) {
+ $this->headers[$k] = implode(', ', $this->headers[$k]);
+ }
+ }
+
+ // string of the form header-name: header value
+ } elseif (preg_match('!^([^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+):(.+)$!', $headerLine, $m)) {
+ $name = strtolower($m[1]);
+ $value = trim($m[2]);
+ if (empty($this->headers[$name])) {
+ $this->headers[$name] = $value;
+ } else {
+ if (!is_array($this->headers[$name])) {
+ $this->headers[$name] = array($this->headers[$name]);
+ }
+ $this->headers[$name][] = $value;
+ }
+ $this->lastHeader = $name;
+
+ // continuation of a previous header
+ } elseif (preg_match('!^\s+(.+)$!', $headerLine, $m) && $this->lastHeader) {
+ if (!is_array($this->headers[$this->lastHeader])) {
+ $this->headers[$this->lastHeader] .= ' ' . trim($m[1]);
+ } else {
+ $key = count($this->headers[$this->lastHeader]) - 1;
+ $this->headers[$this->lastHeader][$key] .= ' ' . trim($m[1]);
+ }
+ }
+ }
+
+ /**
+ * Parses a Set-Cookie header to fill $cookies array
+ *
+ * @param string value of Set-Cookie header
+ * @link http://web.archive.org/web/20080331104521/http://cgi.netscape.com/newsref/std/cookie_spec.html
+ */
+ protected function parseCookie($cookieString)
+ {
+ $cookie = array(
+ 'expires' => null,
+ 'domain' => null,
+ 'path' => null,
+ 'secure' => false
+ );
+
+ // Only a name=value pair
+ if (!strpos($cookieString, ';')) {
+ $pos = strpos($cookieString, '=');
+ $cookie['name'] = trim(substr($cookieString, 0, $pos));
+ $cookie['value'] = trim(substr($cookieString, $pos + 1));
+
+ // Some optional parameters are supplied
+ } else {
+ $elements = explode(';', $cookieString);
+ $pos = strpos($elements[0], '=');
+ $cookie['name'] = trim(substr($elements[0], 0, $pos));
+ $cookie['value'] = trim(substr($elements[0], $pos + 1));
+
+ for ($i = 1; $i < count($elements); $i++) {
+ if (false === strpos($elements[$i], '=')) {
+ $elName = trim($elements[$i]);
+ $elValue = null;
+ } else {
+ list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i]));
+ }
+ $elName = strtolower($elName);
+ if ('secure' == $elName) {
+ $cookie['secure'] = true;
+ } elseif ('expires' == $elName) {
+ $cookie['expires'] = str_replace('"', '', $elValue);
+ } elseif ('path' == $elName || 'domain' == $elName) {
+ $cookie[$elName] = urldecode($elValue);
+ } else {
+ $cookie[$elName] = $elValue;
+ }
+ }
+ }
+ $this->cookies[] = $cookie;
+ }
+
+ /**
+ * Appends a string to the response body
+ * @param string
+ */
+ public function appendBody($bodyChunk)
+ {
+ $this->body .= $bodyChunk;
+ }
+
+ /**
+ * Returns the effective URL of the response
+ *
+ * This may be different from the request URL if redirects were followed.
+ *
+ * @return string
+ * @link http://pear.php.net/bugs/bug.php?id=18412
+ */
+ public function getEffectiveUrl()
+ {
+ return $this->effectiveUrl;
+ }
+
+ /**
+ * Returns the status code
+ * @return integer
+ */
+ public function getStatus()
+ {
+ return $this->code;
+ }
+
+ /**
+ * Returns the reason phrase
+ * @return string
+ */
+ public function getReasonPhrase()
+ {
+ return $this->reasonPhrase;
+ }
+
+ /**
+ * Whether response is a redirect that can be automatically handled by HTTP_Request2
+ * @return bool
+ */
+ public function isRedirect()
+ {
+ return in_array($this->code, array(300, 301, 302, 303, 307))
+ && isset($this->headers['location']);
+ }
+
+ /**
+ * Returns either the named header or all response headers
+ *
+ * @param string Name of header to return
+ * @return string|array Value of $headerName header (null if header is
+ * not present), array of all response headers if
+ * $headerName is null
+ */
+ public function getHeader($headerName = null)
+ {
+ if (null === $headerName) {
+ return $this->headers;
+ } else {
+ $headerName = strtolower($headerName);
+ return isset($this->headers[$headerName])? $this->headers[$headerName]: null;
+ }
+ }
+
+ /**
+ * Returns cookies set in response
+ *
+ * @return array
+ */
+ public function getCookies()
+ {
+ return $this->cookies;
+ }
+
+ /**
+ * Returns the body of the response
+ *
+ * @return string
+ * @throws HTTP_Request2_Exception if body cannot be decoded
+ */
+ public function getBody()
+ {
+ if (0 == strlen($this->body) || !$this->bodyEncoded ||
+ !in_array(strtolower($this->getHeader('content-encoding')), array('gzip', 'deflate'))
+ ) {
+ return $this->body;
+
+ } else {
+ if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) {
+ $oldEncoding = mb_internal_encoding();
+ mb_internal_encoding('iso-8859-1');
+ }
+
+ try {
+ switch (strtolower($this->getHeader('content-encoding'))) {
+ case 'gzip':
+ $decoded = self::decodeGzip($this->body);
+ break;
+ case 'deflate':
+ $decoded = self::decodeDeflate($this->body);
+ }
+ } catch (Exception $e) {
+ }
+
+ if (!empty($oldEncoding)) {
+ mb_internal_encoding($oldEncoding);
+ }
+ if (!empty($e)) {
+ throw $e;
+ }
+ return $decoded;
+ }
+ }
+
+ /**
+ * Get the HTTP version of the response
+ *
+ * @return string
+ */
+ public function getVersion()
+ {
+ return $this->version;
+ }
+
+ /**
+ * Decodes the message-body encoded by gzip
+ *
+ * The real decoding work is done by gzinflate() built-in function, this
+ * method only parses the header and checks data for compliance with
+ * RFC 1952
+ *
+ * @param string gzip-encoded data
+ * @return string decoded data
+ * @throws HTTP_Request2_LogicException
+ * @throws HTTP_Request2_MessageException
+ * @link http://tools.ietf.org/html/rfc1952
+ */
+ public static function decodeGzip($data)
+ {
+ $length = strlen($data);
+ // If it doesn't look like gzip-encoded data, don't bother
+ if (18 > $length || strcmp(substr($data, 0, 2), "\x1f\x8b")) {
+ return $data;
+ }
+ if (!function_exists('gzinflate')) {
+ throw new HTTP_Request2_LogicException(
+ 'Unable to decode body: gzip extension not available',
+ HTTP_Request2_Exception::MISCONFIGURATION
+ );
+ }
+ $method = ord(substr($data, 2, 1));
+ if (8 != $method) {
+ throw new HTTP_Request2_MessageException(
+ 'Error parsing gzip header: unknown compression method',
+ HTTP_Request2_Exception::DECODE_ERROR
+ );
+ }
+ $flags = ord(substr($data, 3, 1));
+ if ($flags & 224) {
+ throw new HTTP_Request2_MessageException(
+ 'Error parsing gzip header: reserved bits are set',
+ HTTP_Request2_Exception::DECODE_ERROR
+ );
+ }
+
+ // header is 10 bytes minimum. may be longer, though.
+ $headerLength = 10;
+ // extra fields, need to skip 'em
+ if ($flags & 4) {
+ if ($length - $headerLength - 2 < 8) {
+ throw new HTTP_Request2_MessageException(
+ 'Error parsing gzip header: data too short',
+ HTTP_Request2_Exception::DECODE_ERROR
+ );
+ }
+ $extraLength = unpack('v', substr($data, 10, 2));
+ if ($length - $headerLength - 2 - $extraLength[1] < 8) {
+ throw new HTTP_Request2_MessageException(
+ 'Error parsing gzip header: data too short',
+ HTTP_Request2_Exception::DECODE_ERROR
+ );
+ }
+ $headerLength += $extraLength[1] + 2;
+ }
+ // file name, need to skip that
+ if ($flags & 8) {
+ if ($length - $headerLength - 1 < 8) {
+ throw new HTTP_Request2_MessageException(
+ 'Error parsing gzip header: data too short',
+ HTTP_Request2_Exception::DECODE_ERROR
+ );
+ }
+ $filenameLength = strpos(substr($data, $headerLength), chr(0));
+ if (false === $filenameLength || $length - $headerLength - $filenameLength - 1 < 8) {
+ throw new HTTP_Request2_MessageException(
+ 'Error parsing gzip header: data too short',
+ HTTP_Request2_Exception::DECODE_ERROR
+ );
+ }
+ $headerLength += $filenameLength + 1;
+ }
+ // comment, need to skip that also
+ if ($flags & 16) {
+ if ($length - $headerLength - 1 < 8) {
+ throw new HTTP_Request2_MessageException(
+ 'Error parsing gzip header: data too short',
+ HTTP_Request2_Exception::DECODE_ERROR
+ );
+ }
+ $commentLength = strpos(substr($data, $headerLength), chr(0));
+ if (false === $commentLength || $length - $headerLength - $commentLength - 1 < 8) {
+ throw new HTTP_Request2_MessageException(
+ 'Error parsing gzip header: data too short',
+ HTTP_Request2_Exception::DECODE_ERROR
+ );
+ }
+ $headerLength += $commentLength + 1;
+ }
+ // have a CRC for header. let's check
+ if ($flags & 2) {
+ if ($length - $headerLength - 2 < 8) {
+ throw new HTTP_Request2_MessageException(
+ 'Error parsing gzip header: data too short',
+ HTTP_Request2_Exception::DECODE_ERROR
+ );
+ }
+ $crcReal = 0xffff & crc32(substr($data, 0, $headerLength));
+ $crcStored = unpack('v', substr($data, $headerLength, 2));
+ if ($crcReal != $crcStored[1]) {
+ throw new HTTP_Request2_MessageException(
+ 'Header CRC check failed',
+ HTTP_Request2_Exception::DECODE_ERROR
+ );
+ }
+ $headerLength += 2;
+ }
+ // unpacked data CRC and size at the end of encoded data
+ $tmp = unpack('V2', substr($data, -8));
+ $dataCrc = $tmp[1];
+ $dataSize = $tmp[2];
+
+ // finally, call the gzinflate() function
+ // don't pass $dataSize to gzinflate, see bugs #13135, #14370
+ $unpacked = gzinflate(substr($data, $headerLength, -8));
+ if (false === $unpacked) {
+ throw new HTTP_Request2_MessageException(
+ 'gzinflate() call failed',
+ HTTP_Request2_Exception::DECODE_ERROR
+ );
+ } elseif ($dataSize != strlen($unpacked)) {
+ throw new HTTP_Request2_MessageException(
+ 'Data size check failed',
+ HTTP_Request2_Exception::DECODE_ERROR
+ );
+ } elseif ((0xffffffff & $dataCrc) != (0xffffffff & crc32($unpacked))) {
+ throw new HTTP_Request2_Exception(
+ 'Data CRC check failed',
+ HTTP_Request2_Exception::DECODE_ERROR
+ );
+ }
+ return $unpacked;
+ }
+
+ /**
+ * Decodes the message-body encoded by deflate
+ *
+ * @param string deflate-encoded data
+ * @return string decoded data
+ * @throws HTTP_Request2_LogicException
+ */
+ public static function decodeDeflate($data)
+ {
+ if (!function_exists('gzuncompress')) {
+ throw new HTTP_Request2_LogicException(
+ 'Unable to decode body: gzip extension not available',
+ HTTP_Request2_Exception::MISCONFIGURATION
+ );
+ }
+ // RFC 2616 defines 'deflate' encoding as zlib format from RFC 1950,
+ // while many applications send raw deflate stream from RFC 1951.
+ // We should check for presence of zlib header and use gzuncompress() or
+ // gzinflate() as needed. See bug #15305
+ $header = unpack('n', substr($data, 0, 2));
+ return (0 == $header[1] % 31)? gzuncompress($data): gzinflate($data);
+ }
+}
+?> \ No newline at end of file
diff --git a/public_html/lib/Net/URL2.php b/public_html/lib/Net/URL2.php
new file mode 100755
index 0000000..9989404
--- /dev/null
+++ b/public_html/lib/Net/URL2.php
@@ -0,0 +1,942 @@
+<?php
+/**
+ * Net_URL2, a class representing a URL as per RFC 3986.
+ *
+ * PHP version 5
+ *
+ * LICENSE:
+ *
+ * Copyright (c) 2007-2009, Peytz & Co. A/S
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Net_URL2 nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Networking
+ * @package Net_URL2
+ * @author Christian Schmidt <schmidt@php.net>
+ * @copyright 2007-2009 Peytz & Co. A/S
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: URL2.php 309223 2011-03-14 14:26:32Z till $
+ * @link http://www.rfc-editor.org/rfc/rfc3986.txt
+ */
+
+/**
+ * Represents a URL as per RFC 3986.
+ *
+ * @category Networking
+ * @package Net_URL2
+ * @author Christian Schmidt <schmidt@php.net>
+ * @copyright 2007-2009 Peytz & Co. A/S
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Net_URL2
+ */
+class Net_URL2
+{
+ /**
+ * Do strict parsing in resolve() (see RFC 3986, section 5.2.2). Default
+ * is true.
+ */
+ const OPTION_STRICT = 'strict';
+
+ /**
+ * Represent arrays in query using PHP's [] notation. Default is true.
+ */
+ const OPTION_USE_BRACKETS = 'use_brackets';
+
+ /**
+ * URL-encode query variable keys. Default is true.
+ */
+ const OPTION_ENCODE_KEYS = 'encode_keys';
+
+ /**
+ * Query variable separators when parsing the query string. Every character
+ * is considered a separator. Default is "&".
+ */
+ const OPTION_SEPARATOR_INPUT = 'input_separator';
+
+ /**
+ * Query variable separator used when generating the query string. Default
+ * is "&".
+ */
+ const OPTION_SEPARATOR_OUTPUT = 'output_separator';
+
+ /**
+ * Default options corresponds to how PHP handles $_GET.
+ */
+ private $_options = array(
+ self::OPTION_STRICT => true,
+ self::OPTION_USE_BRACKETS => true,
+ self::OPTION_ENCODE_KEYS => true,
+ self::OPTION_SEPARATOR_INPUT => '&',
+ self::OPTION_SEPARATOR_OUTPUT => '&',
+ );
+
+ /**
+ * @var string|bool
+ */
+ private $_scheme = false;
+
+ /**
+ * @var string|bool
+ */
+ private $_userinfo = false;
+
+ /**
+ * @var string|bool
+ */
+ private $_host = false;
+
+ /**
+ * @var string|bool
+ */
+ private $_port = false;
+
+ /**
+ * @var string
+ */
+ private $_path = '';
+
+ /**
+ * @var string|bool
+ */
+ private $_query = false;
+
+ /**
+ * @var string|bool
+ */
+ private $_fragment = false;
+
+ /**
+ * Constructor.
+ *
+ * @param string $url an absolute or relative URL
+ * @param array $options an array of OPTION_xxx constants
+ *
+ * @return $this
+ * @uses self::parseUrl()
+ */
+ public function __construct($url, array $options = array())
+ {
+ foreach ($options as $optionName => $value) {
+ if (array_key_exists($optionName, $this->_options)) {
+ $this->_options[$optionName] = $value;
+ }
+ }
+
+ $this->parseUrl($url);
+ }
+
+ /**
+ * Magic Setter.
+ *
+ * This method will magically set the value of a private variable ($var)
+ * with the value passed as the args
+ *
+ * @param string $var The private variable to set.
+ * @param mixed $arg An argument of any type.
+ * @return void
+ */
+ public function __set($var, $arg)
+ {
+ $method = 'set' . $var;
+ if (method_exists($this, $method)) {
+ $this->$method($arg);
+ }
+ }
+
+ /**
+ * Magic Getter.
+ *
+ * This is the magic get method to retrieve the private variable
+ * that was set by either __set() or it's setter...
+ *
+ * @param string $var The property name to retrieve.
+ * @return mixed $this->$var Either a boolean false if the
+ * property is not set or the value
+ * of the private property.
+ */
+ public function __get($var)
+ {
+ $method = 'get' . $var;
+ if (method_exists($this, $method)) {
+ return $this->$method();
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the scheme, e.g. "http" or "urn", or false if there is no
+ * scheme specified, i.e. if this is a relative URL.
+ *
+ * @return string|bool
+ */
+ public function getScheme()
+ {
+ return $this->_scheme;
+ }
+
+ /**
+ * Sets the scheme, e.g. "http" or "urn". Specify false if there is no
+ * scheme specified, i.e. if this is a relative URL.
+ *
+ * @param string|bool $scheme e.g. "http" or "urn", or false if there is no
+ * scheme specified, i.e. if this is a relative
+ * URL
+ *
+ * @return $this
+ * @see getScheme()
+ */
+ public function setScheme($scheme)
+ {
+ $this->_scheme = $scheme;
+ return $this;
+ }
+
+ /**
+ * Returns the user part of the userinfo part (the part preceding the first
+ * ":"), or false if there is no userinfo part.
+ *
+ * @return string|bool
+ */
+ public function getUser()
+ {
+ return $this->_userinfo !== false
+ ? preg_replace('@:.*$@', '', $this->_userinfo)
+ : false;
+ }
+
+ /**
+ * Returns the password part of the userinfo part (the part after the first
+ * ":"), or false if there is no userinfo part (i.e. the URL does not
+ * contain "@" in front of the hostname) or the userinfo part does not
+ * contain ":".
+ *
+ * @return string|bool
+ */
+ public function getPassword()
+ {
+ return $this->_userinfo !== false
+ ? substr(strstr($this->_userinfo, ':'), 1)
+ : false;
+ }
+
+ /**
+ * Returns the userinfo part, or false if there is none, i.e. if the
+ * authority part does not contain "@".
+ *
+ * @return string|bool
+ */
+ public function getUserinfo()
+ {
+ return $this->_userinfo;
+ }
+
+ /**
+ * Sets the userinfo part. If two arguments are passed, they are combined
+ * in the userinfo part as username ":" password.
+ *
+ * @param string|bool $userinfo userinfo or username
+ * @param string|bool $password optional password, or false
+ *
+ * @return $this
+ */
+ public function setUserinfo($userinfo, $password = false)
+ {
+ $this->_userinfo = $userinfo;
+ if ($password !== false) {
+ $this->_userinfo .= ':' . $password;
+ }
+ return $this;
+ }
+
+ /**
+ * Returns the host part, or false if there is no authority part, e.g.
+ * relative URLs.
+ *
+ * @return string|bool a hostname, an IP address, or false
+ */
+ public function getHost()
+ {
+ return $this->_host;
+ }
+
+ /**
+ * Sets the host part. Specify false if there is no authority part, e.g.
+ * relative URLs.
+ *
+ * @param string|bool $host a hostname, an IP address, or false
+ *
+ * @return $this
+ */
+ public function setHost($host)
+ {
+ $this->_host = $host;
+ return $this;
+ }
+
+ /**
+ * Returns the port number, or false if there is no port number specified,
+ * i.e. if the default port is to be used.
+ *
+ * @return string|bool
+ */
+ public function getPort()
+ {
+ return $this->_port;
+ }
+
+ /**
+ * Sets the port number. Specify false if there is no port number specified,
+ * i.e. if the default port is to be used.
+ *
+ * @param string|bool $port a port number, or false
+ *
+ * @return $this
+ */
+ public function setPort($port)
+ {
+ $this->_port = $port;
+ return $this;
+ }
+
+ /**
+ * Returns the authority part, i.e. [ userinfo "@" ] host [ ":" port ], or
+ * false if there is no authority.
+ *
+ * @return string|bool
+ */
+ public function getAuthority()
+ {
+ if (!$this->_host) {
+ return false;
+ }
+
+ $authority = '';
+
+ if ($this->_userinfo !== false) {
+ $authority .= $this->_userinfo . '@';
+ }
+
+ $authority .= $this->_host;
+
+ if ($this->_port !== false) {
+ $authority .= ':' . $this->_port;
+ }
+
+ return $authority;
+ }
+
+ /**
+ * Sets the authority part, i.e. [ userinfo "@" ] host [ ":" port ]. Specify
+ * false if there is no authority.
+ *
+ * @param string|false $authority a hostname or an IP addresse, possibly
+ * with userinfo prefixed and port number
+ * appended, e.g. "foo:bar@example.org:81".
+ *
+ * @return $this
+ */
+ public function setAuthority($authority)
+ {
+ $this->_userinfo = false;
+ $this->_host = false;
+ $this->_port = false;
+ if (preg_match('@^(([^\@]*)\@)?([^:]+)(:(\d*))?$@', $authority, $reg)) {
+ if ($reg[1]) {
+ $this->_userinfo = $reg[2];
+ }
+
+ $this->_host = $reg[3];
+ if (isset($reg[5])) {
+ $this->_port = $reg[5];
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * Returns the path part (possibly an empty string).
+ *
+ * @return string
+ */
+ public function getPath()
+ {
+ return $this->_path;
+ }
+
+ /**
+ * Sets the path part (possibly an empty string).
+ *
+ * @param string $path a path
+ *
+ * @return $this
+ */
+ public function setPath($path)
+ {
+ $this->_path = $path;
+ return $this;
+ }
+
+ /**
+ * Returns the query string (excluding the leading "?"), or false if "?"
+ * is not present in the URL.
+ *
+ * @return string|bool
+ * @see self::getQueryVariables()
+ */
+ public function getQuery()
+ {
+ return $this->_query;
+ }
+
+ /**
+ * Sets the query string (excluding the leading "?"). Specify false if "?"
+ * is not present in the URL.
+ *
+ * @param string|bool $query a query string, e.g. "foo=1&bar=2"
+ *
+ * @return $this
+ * @see self::setQueryVariables()
+ */
+ public function setQuery($query)
+ {
+ $this->_query = $query;
+ return $this;
+ }
+
+ /**
+ * Returns the fragment name, or false if "#" is not present in the URL.
+ *
+ * @return string|bool
+ */
+ public function getFragment()
+ {
+ return $this->_fragment;
+ }
+
+ /**
+ * Sets the fragment name. Specify false if "#" is not present in the URL.
+ *
+ * @param string|bool $fragment a fragment excluding the leading "#", or
+ * false
+ *
+ * @return $this
+ */
+ public function setFragment($fragment)
+ {
+ $this->_fragment = $fragment;
+ return $this;
+ }
+
+ /**
+ * Returns the query string like an array as the variables would appear in
+ * $_GET in a PHP script. If the URL does not contain a "?", an empty array
+ * is returned.
+ *
+ * @return array
+ */
+ public function getQueryVariables()
+ {
+ $pattern = '/[' .
+ preg_quote($this->getOption(self::OPTION_SEPARATOR_INPUT), '/') .
+ ']/';
+ $parts = preg_split($pattern, $this->_query, -1, PREG_SPLIT_NO_EMPTY);
+ $return = array();
+
+ foreach ($parts as $part) {
+ if (strpos($part, '=') !== false) {
+ list($key, $value) = explode('=', $part, 2);
+ } else {
+ $key = $part;
+ $value = null;
+ }
+
+ if ($this->getOption(self::OPTION_ENCODE_KEYS)) {
+ $key = rawurldecode($key);
+ }
+ $value = rawurldecode($value);
+
+ if ($this->getOption(self::OPTION_USE_BRACKETS) &&
+ preg_match('#^(.*)\[([0-9a-z_-]*)\]#i', $key, $matches)) {
+
+ $key = $matches[1];
+ $idx = $matches[2];
+
+ // Ensure is an array
+ if (empty($return[$key]) || !is_array($return[$key])) {
+ $return[$key] = array();
+ }
+
+ // Add data
+ if ($idx === '') {
+ $return[$key][] = $value;
+ } else {
+ $return[$key][$idx] = $value;
+ }
+ } elseif (!$this->getOption(self::OPTION_USE_BRACKETS)
+ && !empty($return[$key])
+ ) {
+ $return[$key] = (array) $return[$key];
+ $return[$key][] = $value;
+ } else {
+ $return[$key] = $value;
+ }
+ }
+
+ return $return;
+ }
+
+ /**
+ * Sets the query string to the specified variable in the query string.
+ *
+ * @param array $array (name => value) array
+ *
+ * @return $this
+ */
+ public function setQueryVariables(array $array)
+ {
+ if (!$array) {
+ $this->_query = false;
+ } else {
+ $this->_query = $this->buildQuery(
+ $array,
+ $this->getOption(self::OPTION_SEPARATOR_OUTPUT)
+ );
+ }
+ return $this;
+ }
+
+ /**
+ * Sets the specified variable in the query string.
+ *
+ * @param string $name variable name
+ * @param mixed $value variable value
+ *
+ * @return $this
+ */
+ public function setQueryVariable($name, $value)
+ {
+ $array = $this->getQueryVariables();
+ $array[$name] = $value;
+ $this->setQueryVariables($array);
+ return $this;
+ }
+
+ /**
+ * Removes the specifed variable from the query string.
+ *
+ * @param string $name a query string variable, e.g. "foo" in "?foo=1"
+ *
+ * @return void
+ */
+ public function unsetQueryVariable($name)
+ {
+ $array = $this->getQueryVariables();
+ unset($array[$name]);
+ $this->setQueryVariables($array);
+ }
+
+ /**
+ * Returns a string representation of this URL.
+ *
+ * @return string
+ */
+ public function getURL()
+ {
+ // See RFC 3986, section 5.3
+ $url = "";
+
+ if ($this->_scheme !== false) {
+ $url .= $this->_scheme . ':';
+ }
+
+ $authority = $this->getAuthority();
+ if ($authority !== false) {
+ $url .= '//' . $authority;
+ }
+ $url .= $this->_path;
+
+ if ($this->_query !== false) {
+ $url .= '?' . $this->_query;
+ }
+
+ if ($this->_fragment !== false) {
+ $url .= '#' . $this->_fragment;
+ }
+
+ return $url;
+ }
+
+ /**
+ * Returns a string representation of this URL.
+ *
+ * @return string
+ * @see toString()
+ */
+ public function __toString()
+ {
+ return $this->getURL();
+ }
+
+ /**
+ * Returns a normalized string representation of this URL. This is useful
+ * for comparison of URLs.
+ *
+ * @return string
+ */
+ public function getNormalizedURL()
+ {
+ $url = clone $this;
+ $url->normalize();
+ return $url->getUrl();
+ }
+
+ /**
+ * Returns a normalized Net_URL2 instance.
+ *
+ * @return Net_URL2
+ */
+ public function normalize()
+ {
+ // See RFC 3886, section 6
+
+ // Schemes are case-insensitive
+ if ($this->_scheme) {
+ $this->_scheme = strtolower($this->_scheme);
+ }
+
+ // Hostnames are case-insensitive
+ if ($this->_host) {
+ $this->_host = strtolower($this->_host);
+ }
+
+ // Remove default port number for known schemes (RFC 3986, section 6.2.3)
+ if ($this->_port &&
+ $this->_scheme &&
+ $this->_port == getservbyname($this->_scheme, 'tcp')) {
+
+ $this->_port = false;
+ }
+
+ // Normalize case of %XX percentage-encodings (RFC 3986, section 6.2.2.1)
+ foreach (array('_userinfo', '_host', '_path') as $part) {
+ if ($this->$part) {
+ $this->$part = preg_replace('/%[0-9a-f]{2}/ie',
+ 'strtoupper("\0")',
+ $this->$part);
+ }
+ }
+
+ // Path segment normalization (RFC 3986, section 6.2.2.3)
+ $this->_path = self::removeDotSegments($this->_path);
+
+ // Scheme based normalization (RFC 3986, section 6.2.3)
+ if ($this->_host && !$this->_path) {
+ $this->_path = '/';
+ }
+ }
+
+ /**
+ * Returns whether this instance represents an absolute URL.
+ *
+ * @return bool
+ */
+ public function isAbsolute()
+ {
+ return (bool) $this->_scheme;
+ }
+
+ /**
+ * Returns an Net_URL2 instance representing an absolute URL relative to
+ * this URL.
+ *
+ * @param Net_URL2|string $reference relative URL
+ *
+ * @return Net_URL2
+ */
+ public function resolve($reference)
+ {
+ if (!$reference instanceof Net_URL2) {
+ $reference = new self($reference);
+ }
+ if (!$this->isAbsolute()) {
+ throw new Exception('Base-URL must be absolute');
+ }
+
+ // A non-strict parser may ignore a scheme in the reference if it is
+ // identical to the base URI's scheme.
+ if (!$this->getOption(self::OPTION_STRICT) && $reference->_scheme == $this->_scheme) {
+ $reference->_scheme = false;
+ }
+
+ $target = new self('');
+ if ($reference->_scheme !== false) {
+ $target->_scheme = $reference->_scheme;
+ $target->setAuthority($reference->getAuthority());
+ $target->_path = self::removeDotSegments($reference->_path);
+ $target->_query = $reference->_query;
+ } else {
+ $authority = $reference->getAuthority();
+ if ($authority !== false) {
+ $target->setAuthority($authority);
+ $target->_path = self::removeDotSegments($reference->_path);
+ $target->_query = $reference->_query;
+ } else {
+ if ($reference->_path == '') {
+ $target->_path = $this->_path;
+ if ($reference->_query !== false) {
+ $target->_query = $reference->_query;
+ } else {
+ $target->_query = $this->_query;
+ }
+ } else {
+ if (substr($reference->_path, 0, 1) == '/') {
+ $target->_path = self::removeDotSegments($reference->_path);
+ } else {
+ // Merge paths (RFC 3986, section 5.2.3)
+ if ($this->_host !== false && $this->_path == '') {
+ $target->_path = '/' . $this->_path;
+ } else {
+ $i = strrpos($this->_path, '/');
+ if ($i !== false) {
+ $target->_path = substr($this->_path, 0, $i + 1);
+ }
+ $target->_path .= $reference->_path;
+ }
+ $target->_path = self::removeDotSegments($target->_path);
+ }
+ $target->_query = $reference->_query;
+ }
+ $target->setAuthority($this->getAuthority());
+ }
+ $target->_scheme = $this->_scheme;
+ }
+
+ $target->_fragment = $reference->_fragment;
+
+ return $target;
+ }
+
+ /**
+ * Removes dots as described in RFC 3986, section 5.2.4, e.g.
+ * "/foo/../bar/baz" => "/bar/baz"
+ *
+ * @param string $path a path
+ *
+ * @return string a path
+ */
+ public static function removeDotSegments($path)
+ {
+ $output = '';
+
+ // Make sure not to be trapped in an infinite loop due to a bug in this
+ // method
+ $j = 0;
+ while ($path && $j++ < 100) {
+ if (substr($path, 0, 2) == './') {
+ // Step 2.A
+ $path = substr($path, 2);
+ } elseif (substr($path, 0, 3) == '../') {
+ // Step 2.A
+ $path = substr($path, 3);
+ } elseif (substr($path, 0, 3) == '/./' || $path == '/.') {
+ // Step 2.B
+ $path = '/' . substr($path, 3);
+ } elseif (substr($path, 0, 4) == '/../' || $path == '/..') {
+ // Step 2.C
+ $path = '/' . substr($path, 4);
+ $i = strrpos($output, '/');
+ $output = $i === false ? '' : substr($output, 0, $i);
+ } elseif ($path == '.' || $path == '..') {
+ // Step 2.D
+ $path = '';
+ } else {
+ // Step 2.E
+ $i = strpos($path, '/');
+ if ($i === 0) {
+ $i = strpos($path, '/', 1);
+ }
+ if ($i === false) {
+ $i = strlen($path);
+ }
+ $output .= substr($path, 0, $i);
+ $path = substr($path, $i);
+ }
+ }
+
+ return $output;
+ }
+
+ /**
+ * Percent-encodes all non-alphanumeric characters except these: _ . - ~
+ * Similar to PHP's rawurlencode(), except that it also encodes ~ in PHP
+ * 5.2.x and earlier.
+ *
+ * @param $raw the string to encode
+ * @return string
+ */
+ public static function urlencode($string)
+ {
+ $encoded = rawurlencode($string);
+
+ // This is only necessary in PHP < 5.3.
+ $encoded = str_replace('%7E', '~', $encoded);
+ return $encoded;
+ }
+
+ /**
+ * Returns a Net_URL2 instance representing the canonical URL of the
+ * currently executing PHP script.
+ *
+ * @return string
+ */
+ public static function getCanonical()
+ {
+ if (!isset($_SERVER['REQUEST_METHOD'])) {
+ // ALERT - no current URL
+ throw new Exception('Script was not called through a webserver');
+ }
+
+ // Begin with a relative URL
+ $url = new self($_SERVER['PHP_SELF']);
+ $url->_scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http';
+ $url->_host = $_SERVER['SERVER_NAME'];
+ $port = $_SERVER['SERVER_PORT'];
+ if ($url->_scheme == 'http' && $port != 80 ||
+ $url->_scheme == 'https' && $port != 443) {
+
+ $url->_port = $port;
+ }
+ return $url;
+ }
+
+ /**
+ * Returns the URL used to retrieve the current request.
+ *
+ * @return string
+ */
+ public static function getRequestedURL()
+ {
+ return self::getRequested()->getUrl();
+ }
+
+ /**
+ * Returns a Net_URL2 instance representing the URL used to retrieve the
+ * current request.
+ *
+ * @return Net_URL2
+ */
+ public static function getRequested()
+ {
+ if (!isset($_SERVER['REQUEST_METHOD'])) {
+ // ALERT - no current URL
+ throw new Exception('Script was not called through a webserver');
+ }
+
+ // Begin with a relative URL
+ $url = new self($_SERVER['REQUEST_URI']);
+ $url->_scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http';
+ // Set host and possibly port
+ $url->setAuthority($_SERVER['HTTP_HOST']);
+ return $url;
+ }
+
+ /**
+ * Returns the value of the specified option.
+ *
+ * @param string $optionName The name of the option to retrieve
+ *
+ * @return mixed
+ */
+ public function getOption($optionName)
+ {
+ return isset($this->_options[$optionName])
+ ? $this->_options[$optionName] : false;
+ }
+
+ /**
+ * A simple version of http_build_query in userland. The encoded string is
+ * percentage encoded according to RFC 3986.
+ *
+ * @param array $data An array, which has to be converted into
+ * QUERY_STRING. Anything is possible.
+ * @param string $seperator See {@link self::OPTION_SEPARATOR_OUTPUT}
+ * @param string $key For stacked values (arrays in an array).
+ *
+ * @return string
+ */
+ protected function buildQuery(array $data, $separator, $key = null)
+ {
+ $query = array();
+ foreach ($data as $name => $value) {
+ if ($this->getOption(self::OPTION_ENCODE_KEYS) === true) {
+ $name = rawurlencode($name);
+ }
+ if ($key !== null) {
+ if ($this->getOption(self::OPTION_USE_BRACKETS) === true) {
+ $name = $key . '[' . $name . ']';
+ } else {
+ $name = $key;
+ }
+ }
+ if (is_array($value)) {
+ $query[] = $this->buildQuery($value, $separator, $name);
+ } else {
+ $query[] = $name . '=' . rawurlencode($value);
+ }
+ }
+ return implode($separator, $query);
+ }
+
+ /**
+ * This method uses a funky regex to parse the url into the designated parts.
+ *
+ * @param string $url
+ *
+ * @return void
+ * @uses self::$_scheme, self::setAuthority(), self::$_path, self::$_query,
+ * self::$_fragment
+ * @see self::__construct()
+ */
+ protected function parseUrl($url)
+ {
+ // The regular expression is copied verbatim from RFC 3986, appendix B.
+ // The expression does not validate the URL but matches any string.
+ preg_match('!^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?!',
+ $url,
+ $matches);
+
+ // "path" is always present (possibly as an empty string); the rest
+ // are optional.
+ $this->_scheme = !empty($matches[1]) ? $matches[2] : false;
+ $this->setAuthority(!empty($matches[3]) ? $matches[4] : false);
+ $this->_path = $matches[5];
+ $this->_query = !empty($matches[6]) ? $matches[7] : false;
+ $this->_fragment = !empty($matches[8]) ? $matches[9] : false;
+ }
+}
diff --git a/public_html/lib/Smarty/Smarty.class.php b/public_html/lib/Smarty/Smarty.class.php
new file mode 100644
index 0000000..467aa73
--- /dev/null
+++ b/public_html/lib/Smarty/Smarty.class.php
@@ -0,0 +1,1473 @@
+<?php
+/**
+* Project: Smarty: the PHP compiling template engine
+* File: Smarty.class.php
+* SVN: $Id: Smarty.class.php 4478 2011-11-24 21:08:26Z uwe.tews@googlemail.com $
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+* For questions, help, comments, discussion, etc., please join the
+* Smarty mailing list. Send a blank e-mail to
+* smarty-discussion-subscribe@googlegroups.com
+*
+* @link http://www.smarty.net/
+* @copyright 2008 New Digital Group, Inc.
+* @author Monte Ohrt <monte at ohrt dot com>
+* @author Uwe Tews
+* @author Rodney Rehm
+* @package Smarty
+* @version 3.1.6
+*/
+
+/**
+* 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_strlen'));
+}
+if (!defined('SMARTY_RESOURCE_CHAR_SET')) {
+ // UTF-8 can only be done properly when mbstring is available!
+ define('SMARTY_RESOURCE_CHAR_SET', SMARTY_MBSTRING ? 'UTF-8' : 'ISO-8859-1');
+}
+if (!defined('SMARTY_RESOURCE_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.6';
+
+ /**
+ * 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 compile check modes
+ */
+ const COMPILECHECK_OFF = 0;
+ const COMPILECHECK_ON = 1;
+ const COMPILECHECK_CACHEMISS = 2;
+ /**
+ * modes for handling of "<?php ... ?>" 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();
+
+ /**#@+
+ * 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.
+ * <ul>
+ * <li>NONE => no debugging control allowed</li>
+ * <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
+ * </ul>
+ * @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_RESOURCE_CHAR_SET);
+ }
+ $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
+ }
+
+ /**
+ * <<magic>> set selfpointer on cloned object
+ */
+ public function __clone()
+ {
+ $this->smarty = $this;
+ }
+
+
+ /**
+ * <<magic>> 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);
+ }
+ }
+
+ /**
+ * <<magic>> 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
+ */
+ 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";
+
+ // 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 (($file = Smarty_Internal_Get_Include_Path::getIncludePath($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($extention = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null)
+ {
+ return Smarty_Internal_Utility::compileAllTemplates($extention, $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($extention = '.conf', $force_compile = false, $time_limit = 0, $max_errors = null)
+ {
+ return Smarty_Internal_Utility::compileAllConfig($extention, $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);
+ 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);
+ $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();
+ }
+}
+
+/**
+* Smarty exception class
+* @package Smarty
+*/
+class SmartyException extends Exception {
+}
+
+/**
+* Smarty compiler exception class
+* @package Smarty
+*/
+class SmartyCompilerException extends SmartyException {
+}
+
+/**
+* Autoloader
+*/
+function smartyAutoload($class)
+{
+ $_class = strtolower($class);
+ $_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/public_html/lib/Smarty/plugins/block.t.php b/public_html/lib/Smarty/plugins/block.t.php
new file mode 100644
index 0000000..3e3ae46
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/block.t.php
@@ -0,0 +1,12 @@
+<?php
+
+function smarty_block_t($params, $content, $template, &$repeat)
+{
+ if (!empty($content)) {
+
+ array_unshift($params, $content);
+ $content = kolab_admin_task::translate($params);
+
+ return trim($content);
+ }
+}
diff --git a/public_html/lib/Smarty/plugins/block.textformat.php b/public_html/lib/Smarty/plugins/block.textformat.php
new file mode 100644
index 0000000..bdd8067
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/block.textformat.php
@@ -0,0 +1,113 @@
+<?php
+/**
+ * Smarty plugin to format text blocks
+ *
+ * @package Smarty
+ * @subpackage PluginsBlock
+ */
+
+/**
+ * Smarty {textformat}{/textformat} block plugin
+ *
+ * Type: block function<br>
+ * Name: textformat<br>
+ * Purpose: format text a certain way with preset styles
+ * or custom wrap/indent settings<br>
+ * Params:
+ * <pre>
+ * - style - string (email)
+ * - indent - integer (0)
+ * - wrap - integer (80)
+ * - wrap_char - string ("\n")
+ * - indent_char - string (" ")
+ * - wrap_boundary - boolean (true)
+ * </pre>
+ *
+ * @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 <monte at ohrt dot com>
+ */
+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+!u', '!(^\s+)|(\s+$)!u'), array(' ', ''), $_paragraph);
+ // indent first line
+ if ($indent_first > 0) {
+ $_paragraph = str_repeat($indent_char, $indent_first) . $_paragraph;
+ }
+ // wordwrap sentences
+ if (SMARTY_MBSTRING /* ^phpunit */&&empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ 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;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/function.counter.php b/public_html/lib/Smarty/plugins/function.counter.php
new file mode 100644
index 0000000..3906bad
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/function.counter.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {counter} function plugin
+ *
+ * Type: function<br>
+ * Name: counter<br>
+ * Purpose: print out a counter value
+ *
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @link http://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;
+
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/function.cycle.php b/public_html/lib/Smarty/plugins/function.cycle.php
new file mode 100644
index 0000000..1778ffb
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/function.cycle.php
@@ -0,0 +1,106 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {cycle} function plugin
+ *
+ * Type: function<br>
+ * Name: cycle<br>
+ * Date: May 3, 2002<br>
+ * Purpose: cycle through given values<br>
+ * Params:
+ * <pre>
+ * - 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.
+ * </pre>
+ * Examples:<br>
+ * <pre>
+ * {cycle values="#eeeeee,#d0d0d0d"}
+ * {cycle name=row values="one,two,three" reset=true}
+ * {cycle name=row}
+ * </pre>
+ *
+ * @link http://www.smarty.net/manual/en/language.function.cycle.php {cycle}
+ * (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author credit to Mark Priatel <mpriatel@rogers.com>
+ * @author credit to Gerard <gerard@interfold.com>
+ * @author credit to Jason Sweat <jsweat_php@yahoo.com>
+ * @version 1.3
+ * @param array $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;
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/function.fetch.php b/public_html/lib/Smarty/plugins/function.fetch.php
new file mode 100644
index 0000000..cde98d2
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/function.fetch.php
@@ -0,0 +1,216 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {fetch} plugin
+ *
+ * Type: function<br>
+ * Name: fetch<br>
+ * 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 <monte at ohrt dot com>
+ * @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;
+ }
+
+ $content = '';
+ if (isset($template->smarty->security_policy) && !preg_match('!^(http|ftp)://!i', $params['file'])) {
+ if(!$template->smarty->security_policy->isTrustedResourceDir($params['file'])) {
+ return;
+ }
+
+ // fetch the file
+ if($fp = @fopen($params['file'],'r')) {
+ while(!feof($fp)) {
+ $content .= fgets ($fp,4096);
+ }
+ fclose($fp);
+ } else {
+ trigger_error('[plugin] fetch cannot read file \'' . $params['file'] . '\'',E_USER_NOTICE);
+ 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::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 {
+ // ftp fetch
+ if($fp = @fopen($params['file'],'r')) {
+ while(!feof($fp)) {
+ $content .= fgets ($fp,4096);
+ }
+ fclose($fp);
+ } else {
+ trigger_error('[plugin] fetch cannot read file \'' . $params['file'] .'\'',E_USER_NOTICE);
+ return;
+ }
+ }
+
+ }
+
+
+ if (!empty($params['assign'])) {
+ $template->assign($params['assign'],$content);
+ } else {
+ return $content;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/function.gentime.php b/public_html/lib/Smarty/plugins/function.gentime.php
new file mode 100644
index 0000000..b4fbffb
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/function.gentime.php
@@ -0,0 +1,7 @@
+<?php
+
+function smarty_function_gentime($params, $template)
+{
+ $time = microtime(true);
+ return sprintf('%.4f', $time - KADM_START);
+}
diff --git a/public_html/lib/Smarty/plugins/function.html_checkboxes.php b/public_html/lib/Smarty/plugins/function.html_checkboxes.php
new file mode 100644
index 0000000..4251369
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/function.html_checkboxes.php
@@ -0,0 +1,216 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {html_checkboxes} function plugin
+ *
+ * File: function.html_checkboxes.php<br>
+ * Type: function<br>
+ * Name: html_checkboxes<br>
+ * Date: 24.Feb.2003<br>
+ * Purpose: Prints out a list of checkbox input types<br>
+ * Examples:
+ * <pre>
+ * {html_checkboxes values=$ids output=$names}
+ * {html_checkboxes values=$ids name='box' separator='<br>' output=$names}
+ * {html_checkboxes values=$ids checked=$checked separator='<br>' output=$names}
+ * </pre>
+ * Params:
+ * <pre>
+ * - name (optional) - string default "checkbox"
+ * - values (required) - array
+ * - options (optional) - associative array
+ * - checked (optional) - array default not set
+ * - separator (optional) - ie <br> or &nbsp;
+ * - output (optional) - the output next to each checkbox
+ * - assign (optional) - assign the output as an array to this variable
+ * - escape (optional) - escape the content (not value), defaults to true
+ * </pre>
+ *
+ * @link http://www.smarty.net/manual/en/language.function.html.checkboxes.php {html_checkboxes}
+ * (Smarty online manual)
+ * @author Christopher Kvarme <christopher.kvarme@flashjab.com>
+ * @author credits to Monte Ohrt <monte at ohrt dot com>
+ * @version 1.0
+ * @param array $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;
+
+ 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\-\.]!u', '_', $name . '_' . $value));
+ $_output .= '<label for="' . $_id . '">';
+ } else {
+ $_output .= '<label>';
+ }
+ }
+
+ $name = smarty_function_escape_special_chars($name);
+ $value = smarty_function_escape_special_chars($value);
+ if ($escape) {
+ $output = smarty_function_escape_special_chars($output);
+ }
+
+ $_output .= '<input type="checkbox" name="' . $name . '[]" value="' . $value . '"';
+
+ if ($labels && $label_ids) {
+ $_output .= ' id="' . $_id . '"';
+ }
+
+ if (is_array($selected)) {
+ if (isset($selected[$value])) {
+ $_output .= ' checked="checked"';
+ }
+ } elseif ($value === $selected) {
+ $_output .= ' checked="checked"';
+ }
+
+ $_output .= $extra . ' />' . $output;
+ if ($labels) {
+ $_output .= '</label>';
+ }
+
+ $_output .= $separator;
+ return $_output;
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/function.html_image.php b/public_html/lib/Smarty/plugins/function.html_image.php
new file mode 100644
index 0000000..2f1ef64
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/function.html_image.php
@@ -0,0 +1,138 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {html_image} function plugin
+ *
+ * Type: function<br>
+ * Name: html_image<br>
+ * Date: Feb 24, 2003<br>
+ * Purpose: format HTML tags for the image<br>
+ * Examples: {html_image file="/images/masthead.gif"}<br>
+ * Output: <img src="/images/masthead.gif" width=400 height=23><br>
+ * Params:
+ * <pre>
+ * - file - (required) - file (and path) of image
+ * - height - (optional) - image height (default actual height)
+ * - width - (optional) - image width (default actual width)
+ * - basedir - (optional) - base directory for absolute paths, default is environment variable DOCUMENT_ROOT
+ * - path_prefix - prefix for path output (optional, default empty)
+ * </pre>
+ *
+ * @link http://www.smarty.net/manual/en/language.function.html.image.php {html_image}
+ * (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author credits to Duda <duda@big.hu>
+ * @version 1.0
+ * @param array $params parameters
+ * @param Smarty_Internal_Template $template template object
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_image($params, $template)
+{
+ require_once(SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php');
+
+ $alt = '';
+ $file = '';
+ $height = '';
+ $width = '';
+ $extra = '';
+ $prefix = '';
+ $suffix = '';
+ $path_prefix = '';
+ $server_vars = $_SERVER;
+ $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 {
+ throw new SmartyException ("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+ }
+ break;
+
+ case 'link':
+ case 'href':
+ $prefix = '<a href="' . $_val . '">';
+ $suffix = '</a>';
+ break;
+
+ default:
+ if (!is_array($_val)) {
+ $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"';
+ } else {
+ throw new SmartyException ("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+ }
+ break;
+ }
+ }
+
+ if (empty($file)) {
+ 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)) {
+ trigger_error("html_image: unable to find '$_image_path'", E_USER_NOTICE);
+ return;
+ } else if (!is_readable($_image_path)) {
+ trigger_error("html_image: unable to read '$_image_path'", E_USER_NOTICE);
+ return;
+ } else {
+ trigger_error("html_image: '$_image_path' is not a valid image file", E_USER_NOTICE);
+ return;
+ }
+ }
+ if (isset($template->smarty->security_policy)) {
+ if (!$template->smarty->security_policy->isTrustedResourceDir($_image_path)) {
+ return;
+ }
+ }
+
+ if (!isset($params['width'])) {
+ $width = $_image_data[0];
+ }
+ if (!isset($params['height'])) {
+ $height = $_image_data[1];
+ }
+ }
+
+ if (isset($params['dpi'])) {
+ if (strstr($server_vars['HTTP_USER_AGENT'], 'Mac')) {
+ $dpi_default = 72;
+ } else {
+ $dpi_default = 96;
+ }
+ $_resize = $dpi_default / $params['dpi'];
+ $width = round($width * $_resize);
+ $height = round($height * $_resize);
+ }
+
+ return $prefix . '<img src="' . $path_prefix . $file . '" alt="' . $alt . '" width="' . $width . '" height="' . $height . '"' . $extra . ' />' . $suffix;
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/function.html_options.php b/public_html/lib/Smarty/plugins/function.html_options.php
new file mode 100644
index 0000000..86266e2
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/function.html_options.php
@@ -0,0 +1,174 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {html_options} function plugin
+ *
+ * Type: function<br>
+ * Name: html_options<br>
+ * Purpose: Prints the list of <option> tags generated from
+ * the passed parameters<br>
+ * Params:
+ * <pre>
+ * - 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
+ * - id (optional) - string default not set
+ * - class (optional) - string default not set
+ * </pre>
+ *
+ * @link http://www.smarty.net/manual/en/language.function.html.options.php {html_image}
+ * (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author Ralf Strehle (minor optimization) <ralf dot strehle at yahoo dot de>
+ * @param array $params parameters
+ * @param Smarty_Internal_Template $template template object
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_options($params, $template)
+{
+ require_once(SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php');
+
+ $name = null;
+ $values = null;
+ $options = null;
+ $selected = null;
+ $output = null;
+ $id = null;
+ $class = null;
+
+ $extra = '';
+
+ foreach ($params as $_key => $_val) {
+ switch ($_key) {
+ case 'name':
+ case 'class':
+ case 'id':
+ $$_key = (string) $_val;
+ break;
+
+ case 'options':
+ $options = (array) $_val;
+ break;
+
+ case 'values':
+ case 'output':
+ $$_key = array_values((array) $_val);
+ break;
+
+ 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_options: 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_options: 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;
+
+ default:
+ if (!is_array($_val)) {
+ $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"';
+ } else {
+ trigger_error("html_options: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+ }
+ break;
+ }
+ }
+
+ if (!isset($options) && !isset($values)) {
+ /* raise error here? */
+ return '';
+ }
+
+ $_html_result = '';
+ $_idx = 0;
+
+ if (isset($options)) {
+ foreach ($options as $_key => $_val) {
+ $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected, $id, $class, $_idx);
+ }
+ } else {
+ foreach ($values as $_i => $_key) {
+ $_val = isset($output[$_i]) ? $output[$_i] : '';
+ $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected, $id, $class, $_idx);
+ }
+ }
+
+ if (!empty($name)) {
+ $_html_class = !empty($class) ? ' class="'.$class.'"' : '';
+ $_html_id = !empty($id) ? ' id="'.$id.'"' : '';
+ $_html_result = '<select name="' . $name . '"' . $_html_class . $_html_id . $extra . '>' . "\n" . $_html_result . '</select>' . "\n";
+ }
+
+ return $_html_result;
+}
+
+function smarty_function_html_options_optoutput($key, $value, $selected, $id, $class, &$idx)
+{
+ if (!is_array($value)) {
+ $_key = smarty_function_escape_special_chars($key);
+ $_html_result = '<option value="' . $_key . '"';
+ if (is_array($selected)) {
+ if (isset($selected[$_key])) {
+ $_html_result .= ' selected="selected"';
+ }
+ } elseif ($_key === $selected) {
+ $_html_result .= ' selected="selected"';
+ }
+ $_html_class = !empty($class) ? ' class="'.$class.' option"' : '';
+ $_html_id = !empty($id) ? ' id="'.$id.'-'.$idx.'"' : '';
+ if (is_object($value)) {
+ if (method_exists($value, "__toString")) {
+ $value = smarty_function_escape_special_chars((string) $value->__toString());
+ } else {
+ trigger_error("html_options: value is an object of class '". get_class($value) ."' without __toString() method", E_USER_NOTICE);
+ return '';
+ }
+ }
+ $_html_result .= $_html_class . $_html_id . '>' . $value . '</option>' . "\n";
+ $idx++;
+ } else {
+ $_idx = 0;
+ $_html_result = smarty_function_html_options_optgroup($key, $value, $selected, !empty($id) ? ($id.'-'.$idx) : null, $class, $_idx);
+ $idx++;
+ }
+ return $_html_result;
+}
+
+function smarty_function_html_options_optgroup($key, $values, $selected, $id, $class, &$idx)
+{
+ $optgroup_html = '<optgroup label="' . smarty_function_escape_special_chars($key) . '">' . "\n";
+ foreach ($values as $key => $value) {
+ $optgroup_html .= smarty_function_html_options_optoutput($key, $value, $selected, $id, $class, $idx);
+ }
+ $optgroup_html .= "</optgroup>\n";
+ return $optgroup_html;
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/function.html_radios.php b/public_html/lib/Smarty/plugins/function.html_radios.php
new file mode 100644
index 0000000..12deb42
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/function.html_radios.php
@@ -0,0 +1,200 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {html_radios} function plugin
+ *
+ * File: function.html_radios.php<br>
+ * Type: function<br>
+ * Name: html_radios<br>
+ * Date: 24.Feb.2003<br>
+ * Purpose: Prints out a list of radio input types<br>
+ * Params:
+ * <pre>
+ * - name (optional) - string default "radio"
+ * - values (required) - array
+ * - options (required) - associative array
+ * - checked (optional) - array default not set
+ * - separator (optional) - ie <br> or &nbsp;
+ * - output (optional) - the output next to each radio button
+ * - assign (optional) - assign the output as an array to this variable
+ * - escape (optional) - escape the content (not value), defaults to true
+ * </pre>
+ * Examples:
+ * <pre>
+ * {html_radios values=$ids output=$names}
+ * {html_radios values=$ids name='box' separator='<br>' output=$names}
+ * {html_radios values=$ids checked=$checked separator='<br>' output=$names}
+ * </pre>
+ *
+ * @link http://smarty.php.net/manual/en/language.function.html.radios.php {html_radios}
+ * (Smarty online manual)
+ * @author Christopher Kvarme <christopher.kvarme@flashjab.com>
+ * @author credits to Monte Ohrt <monte at ohrt dot com>
+ * @version 1.0
+ * @param array $params parameters
+ * @param Smarty_Internal_Template $template template object
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_radios($params, $template)
+{
+ require_once(SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php');
+
+ $name = 'radio';
+ $values = null;
+ $options = null;
+ $selected = null;
+ $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 'checked':
+ case 'selected':
+ if (is_array($_val)) {
+ trigger_error('html_radios: the "' . $_key . '" attribute cannot be an array', E_USER_WARNING);
+ } elseif (is_object($_val)) {
+ if (method_exists($_val, "__toString")) {
+ $selected = smarty_function_escape_special_chars((string) $_val->__toString());
+ } else {
+ trigger_error("html_radios: selected attribute is an object of class '". get_class($_val) ."' without __toString() method", E_USER_NOTICE);
+ }
+ } else {
+ $selected = (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 'radios':
+ trigger_error('html_radios: the use of the "radios" attribute is deprecated, use "options" instead', E_USER_WARNING);
+ $options = (array) $_val;
+ break;
+
+ case 'assign':
+ break;
+
+ default:
+ if (!is_array($_val)) {
+ $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"';
+ } else {
+ trigger_error("html_radios: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+ }
+ break;
+ }
+ }
+
+ if (!isset($options) && !isset($values)) {
+ /* raise error here? */
+ return '';
+ }
+
+ $_html_result = array();
+
+ if (isset($options)) {
+ foreach ($options as $_key => $_val) {
+ $_html_result[] = smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids, $escape);
+ }
+ } else {
+ foreach ($values as $_i => $_key) {
+ $_val = isset($output[$_i]) ? $output[$_i] : '';
+ $_html_result[] = smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids, $escape);
+ }
+ }
+
+ if (!empty($params['assign'])) {
+ $template->assign($params['assign'], $_html_result);
+ } else {
+ return implode("\n", $_html_result);
+ }
+}
+
+function smarty_function_html_radios_output($name, $value, $output, $selected, $extra, $separator, $labels, $label_ids, $escape)
+{
+ $_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\-\.]!u', '_', $name . '_' . $value));
+ $_output .= '<label for="' . $_id . '">';
+ } else {
+ $_output .= '<label>';
+ }
+ }
+
+ $name = smarty_function_escape_special_chars($name);
+ $value = smarty_function_escape_special_chars($value);
+ if ($escape) {
+ $output = smarty_function_escape_special_chars($output);
+ }
+
+ $_output .= '<input type="radio" name="' . $name . '" value="' . $value . '"';
+
+ if ($labels && $label_ids) {
+ $_output .= ' id="' . $_id . '"';
+ }
+
+ if ($value === $selected) {
+ $_output .= ' checked="checked"';
+ }
+
+ $_output .= $extra . ' />' . $output;
+ if ($labels) {
+ $_output .= '</label>';
+ }
+
+ $_output .= $separator;
+ return $_output;
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/function.html_select_date.php b/public_html/lib/Smarty/plugins/function.html_select_date.php
new file mode 100644
index 0000000..13c5003
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/function.html_select_date.php
@@ -0,0 +1,394 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * @ignore
+ */
+require_once(SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php');
+/**
+ * @ignore
+ */
+require_once(SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php');
+
+/**
+ * Smarty {html_select_date} plugin
+ *
+ * Type: function<br>
+ * Name: html_select_date<br>
+ * Purpose: Prints the dropdowns for date selection.
+ *
+ * ChangeLog:
+ * <pre>
+ * - 1.0 initial release
+ * - 1.1 added support for +/- N syntax for begin
+ * and end year values. (Monte)
+ * - 1.2 added support for yyyy-mm-dd syntax for
+ * time value. (Jan Rosier)
+ * - 1.3 added support for choosing format for
+ * month values (Gary Loescher)
+ * - 1.3.1 added support for choosing format for
+ * day values (Marcus Bointon)
+ * - 1.3.2 support negative timestamps, force year
+ * dropdown to include given date unless explicitly set (Monte)
+ * - 1.3.4 fix behaviour of 0000-00-00 00:00:00 dates to match that
+ * of 0000-00-00 dates (cybot, boots)
+ * - 2.0 complete rewrite for performance,
+ * added attributes month_names, *_id
+ * </pre>
+ *
+ * @link http://www.smarty.net/manual/en/language.function.html.select.date.php {html_select_date}
+ * (Smarty online manual)
+ * @version 2.0
+ * @author Andrei Zmievski
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author Rodney Rehm
+ * @param array $params parameters
+ * @param Smarty_Internal_Template $template template object
+ * @return string
+ */
+function smarty_function_html_select_date($params, $template)
+{
+ // generate timestamps used for month names only
+ static $_month_timestamps = null;
+ static $_current_year = null;
+ if ($_month_timestamps === null) {
+ $_current_year = date('Y');
+ $_month_timestamps = array();
+ for ($i = 1; $i <= 12; $i++) {
+ $_month_timestamps[$i] = mktime(0, 0, 0, $i, 1, 2000);
+ }
+ }
+
+ /* Default values. */
+ $prefix = "Date_";
+ $start_year = null;
+ $end_year = null;
+ $display_days = true;
+ $display_months = true;
+ $display_years = true;
+ $month_format = "%B";
+ /* Write months as numbers by default GL */
+ $month_value_format = "%m";
+ $day_format = "%02d";
+ /* Write day values using this format MB */
+ $day_value_format = "%d";
+ $year_as_text = false;
+ /* Display years in reverse order? Ie. 2000,1999,.... */
+ $reverse_years = false;
+ /* Should the select boxes be part of an array when returned from PHP?
+ e.g. setting it to "birthday", would create "birthday[Day]",
+ "birthday[Month]" & "birthday[Year]". Can be combined with prefix */
+ $field_array = null;
+ /* <select size>'s of the different <select> tags.
+ If not set, uses default dropdown. */
+ $day_size = null;
+ $month_size = null;
+ $year_size = null;
+ /* Unparsed attributes common to *ALL* the <select>/<input> tags.
+ An example might be in the template: all_extra ='class ="foo"'. */
+ $all_extra = null;
+ /* Separate attributes for the tags. */
+ $day_extra = null;
+ $month_extra = null;
+ $year_extra = null;
+ /* Order in which to display the fields.
+ "D" -> day, "M" -> month, "Y" -> year. */
+ $field_order = 'MDY';
+ /* String printed between the different fields. */
+ $field_separator = "\n";
+ $option_separator = "\n";
+ $time = null;
+ // $all_empty = null;
+ // $day_empty = null;
+ // $month_empty = null;
+ // $year_empty = null;
+ $extra_attrs = '';
+ $all_id = null;
+ $day_id = null;
+ $month_id = null;
+ $year_id = null;
+
+ foreach ($params as $_key => $_value) {
+ switch ($_key) {
+ case 'time':
+ if (!is_array($_value) && $_value !== null) {
+ $time = smarty_make_timestamp($_value);
+ }
+ break;
+
+ case 'month_names':
+ if (is_array($_value) && count($_value) == 12) {
+ $$_key = $_value;
+ } else {
+ trigger_error("html_select_date: month_names must be an array of 12 strings", E_USER_NOTICE);
+ }
+ break;
+
+ case 'prefix':
+ case 'field_array':
+ case 'start_year':
+ case 'end_year':
+ case 'day_format':
+ case 'day_value_format':
+ case 'month_format':
+ case 'month_value_format':
+ case 'day_size':
+ case 'month_size':
+ case 'year_size':
+ case 'all_extra':
+ case 'day_extra':
+ case 'month_extra':
+ case 'year_extra':
+ case 'field_order':
+ case 'field_separator':
+ case 'option_separator':
+ case 'all_empty':
+ case 'month_empty':
+ case 'day_empty':
+ case 'year_empty':
+ case 'all_id':
+ case 'month_id':
+ case 'day_id':
+ case 'year_id':
+ $$_key = (string)$_value;
+ break;
+
+ case 'display_days':
+ case 'display_months':
+ case 'display_years':
+ case 'year_as_text':
+ case 'reverse_years':
+ $$_key = (bool)$_value;
+ break;
+
+ default:
+ if (!is_array($_value)) {
+ $extra_attrs .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_value) . '"';
+ } else {
+ trigger_error("html_select_date: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+ }
+ break;
+ }
+ }
+
+ // Note: date() is faster than strftime()
+ // Note: explode(date()) is faster than date() date() date()
+ if (isset($params['time']) && is_array($params['time'])) {
+ if (isset($params['time'][$prefix . 'Year'])) {
+ // $_REQUEST[$field_array] given
+ foreach (array('Y' => 'Year', 'm' => 'Month', 'd' => 'Day') as $_elementKey => $_elementName) {
+ $_variableName = '_' . strtolower($_elementName);
+ $$_variableName = isset($params['time'][$prefix . $_elementName])
+ ? $params['time'][$prefix . $_elementName]
+ : date($_elementKey);
+ }
+ $time = mktime(0, 0, 0, $_month, $_day, $_year);
+ } elseif (isset($params['time'][$field_array][$prefix . 'Year'])) {
+ // $_REQUEST given
+ foreach (array('Y' => 'Year', 'm' => 'Month', 'd' => 'Day') as $_elementKey => $_elementName) {
+ $_variableName = '_' . strtolower($_elementName);
+ $$_variableName = isset($params['time'][$field_array][$prefix . $_elementName])
+ ? $params['time'][$field_array][$prefix . $_elementName]
+ : date($_elementKey);
+ }
+ $time = mktime(0, 0, 0, $_month, $_day, $_year);
+ } else {
+ // no date found, use NOW
+ list($_year, $_month, $_day) = $time = explode('-', date('Y-m-d'));
+ }
+ } elseif ($time === null) {
+ if (array_key_exists('time', $params)) {
+ $_year = $_month = $_day = $time = null;
+ } else {
+ list($_year, $_month, $_day) = $time = explode('-', date('Y-m-d'));
+ }
+ } else {
+ list($_year, $_month, $_day) = $time = explode('-', date('Y-m-d', $time));
+ }
+
+ // make syntax "+N" or "-N" work with $start_year and $end_year
+ // Note preg_match('!^(\+|\-)\s*(\d+)$!', $end_year, $match) is slower than trim+substr
+ foreach (array('start', 'end') as $key) {
+ $key .= '_year';
+ $t = $$key;
+ if ($t === null) {
+ $$key = (int)$_current_year;
+ } else if ($t[0] == '+') {
+ $$key = (int)($_current_year + trim(substr($t, 1)));
+ } else if ($t[0] == '-') {
+ $$key = (int)($_current_year - trim(substr($t, 1)));
+ } else {
+ $$key = (int)$$key;
+ }
+ }
+
+ // flip for ascending or descending
+ if (($start_year > $end_year && !$reverse_years) || ($start_year < $end_year && $reverse_years)) {
+ $t = $end_year;
+ $end_year = $start_year;
+ $start_year = $t;
+ }
+
+ // generate year <select> or <input>
+ if ($display_years) {
+ $_html_years = '';
+ $_extra = '';
+ $_name = $field_array ? ($field_array . '[' . $prefix . 'Year]') : ($prefix . 'Year');
+ if ($all_extra) {
+ $_extra .= ' ' . $all_extra;
+ }
+ if ($year_extra) {
+ $_extra .= ' ' . $year_extra;
+ }
+
+ if ($year_as_text) {
+ $_html_years = '<input type="text" name="' . $_name . '" value="' . $_year . '" size="4" maxlength="4"' . $_extra . $extra_attrs . ' />';
+ } else {
+ $_html_years = '<select name="' . $_name . '"';
+ if ($year_id !== null || $all_id !== null) {
+ $_html_years .= ' id="' . smarty_function_escape_special_chars(
+ $year_id !== null ? ( $year_id ? $year_id : $_name ) : ( $all_id ? ($all_id . $_name) : $_name )
+ ) . '"';
+ }
+ if ($year_size) {
+ $_html_years .= ' size="' . $year_size . '"';
+ }
+ $_html_years .= $_extra . $extra_attrs . '>' . $option_separator;
+
+ if (isset($year_empty) || isset($all_empty)) {
+ $_html_years .= '<option value="">' . ( isset($year_empty) ? $year_empty : $all_empty ) . '</option>' . $option_separator;
+ }
+
+ $op = $start_year > $end_year ? -1 : 1;
+ for ($i=$start_year; $op > 0 ? $i <= $end_year : $i >= $end_year; $i += $op) {
+ $_html_years .= '<option value="' . $i . '"'
+ . ($_year == $i ? ' selected="selected"' : '')
+ . '>' . $i . '</option>' . $option_separator;
+ }
+
+ $_html_years .= '</select>';
+ }
+ }
+
+ // generate month <select> or <input>
+ if ($display_months) {
+ $_html_month = '';
+ $_extra = '';
+ $_name = $field_array ? ($field_array . '[' . $prefix . 'Month]') : ($prefix . 'Month');
+ if ($all_extra) {
+ $_extra .= ' ' . $all_extra;
+ }
+ if ($month_extra) {
+ $_extra .= ' ' . $month_extra;
+ }
+
+ $_html_months = '<select name="' . $_name . '"';
+ if ($month_id !== null || $all_id !== null) {
+ $_html_months .= ' id="' . smarty_function_escape_special_chars(
+ $month_id !== null ? ( $month_id ? $month_id : $_name ) : ( $all_id ? ($all_id . $_name) : $_name )
+ ) . '"';
+ }
+ if ($month_size) {
+ $_html_months .= ' size="' . $month_size . '"';
+ }
+ $_html_months .= $_extra . $extra_attrs . '>' . $option_separator;
+
+ if (isset($month_empty) || isset($all_empty)) {
+ $_html_months .= '<option value="">' . ( isset($month_empty) ? $month_empty : $all_empty ) . '</option>' . $option_separator;
+ }
+
+ for ($i = 1; $i <= 12; $i++) {
+ $_val = sprintf('%02d', $i);
+ $_text = isset($month_names) ? smarty_function_escape_special_chars($month_names[$i]) : ($month_format == "%m" ? $_val : strftime($month_format, $_month_timestamps[$i]));
+ $_value = $month_value_format == "%m" ? $_val : strftime($month_value_format, $_month_timestamps[$i]);
+ $_html_months .= '<option value="' . $_value . '"'
+ . ($_val == $_month ? ' selected="selected"' : '')
+ . '>' . $_text . '</option>' . $option_separator;
+ }
+
+ $_html_months .= '</select>';
+ }
+
+ // generate day <select> or <input>
+ if ($display_days) {
+ $_html_day = '';
+ $_extra = '';
+ $_name = $field_array ? ($field_array . '[' . $prefix . 'Day]') : ($prefix . 'Day');
+ if ($all_extra) {
+ $_extra .= ' ' . $all_extra;
+ }
+ if ($day_extra) {
+ $_extra .= ' ' . $day_extra;
+ }
+
+ $_html_days = '<select name="' . $_name . '"';
+ if ($day_id !== null || $all_id !== null) {
+ $_html_days .= ' id="' . smarty_function_escape_special_chars(
+ $day_id !== null ? ( $day_id ? $day_id : $_name ) : ( $all_id ? ($all_id . $_name) : $_name )
+ ) . '"';
+ }
+ if ($day_size) {
+ $_html_days .= ' size="' . $day_size . '"';
+ }
+ $_html_days .= $_extra . $extra_attrs . '>' . $option_separator;
+
+ if (isset($day_empty) || isset($all_empty)) {
+ $_html_days .= '<option value="">' . ( isset($day_empty) ? $day_empty : $all_empty ) . '</option>' . $option_separator;
+ }
+
+ for ($i = 1; $i <= 31; $i++) {
+ $_val = sprintf('%02d', $i);
+ $_text = $day_format == '%02d' ? $_val : sprintf($day_format, $i);
+ $_value = $day_value_format == '%02d' ? $_val : sprintf($day_value_format, $i);
+ $_html_days .= '<option value="' . $_value . '"'
+ . ($_val == $_day ? ' selected="selected"' : '')
+ . '>' . $_text . '</option>' . $option_separator;
+ }
+
+ $_html_days .= '</select>';
+ }
+
+ // order the fields for output
+ $_html = '';
+ for ($i=0; $i <= 2; $i++) {
+ switch ($field_order[$i]) {
+ case 'Y':
+ case 'y':
+ if (isset($_html_years)) {
+ if ($_html) {
+ $_html .= $field_separator;
+ }
+ $_html .= $_html_years;
+ }
+ break;
+
+ case 'm':
+ case 'M':
+ if (isset($_html_months)) {
+ if ($_html) {
+ $_html .= $field_separator;
+ }
+ $_html .= $_html_months;
+ }
+ break;
+
+ case 'd':
+ case 'D':
+ if (isset($_html_days)) {
+ if ($_html) {
+ $_html .= $field_separator;
+ }
+ $_html .= $_html_days;
+ }
+ break;
+ }
+ }
+ return $_html;
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/function.html_select_time.php b/public_html/lib/Smarty/plugins/function.html_select_time.php
new file mode 100644
index 0000000..9fb8038
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/function.html_select_time.php
@@ -0,0 +1,366 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * @ignore
+ */
+require_once(SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php');
+/**
+ * @ignore
+ */
+require_once(SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php');
+
+/**
+ * Smarty {html_select_time} function plugin
+ *
+ * Type: function<br>
+ * Name: html_select_time<br>
+ * Purpose: Prints the dropdowns for time selection
+ *
+ * @link http://www.smarty.net/manual/en/language.function.html.select.time.php {html_select_time}
+ * (Smarty online manual)
+ * @author Roberto Berto <roberto@berto.net>
+ * @author Monte Ohrt <monte AT ohrt DOT com>
+ * @param array $params parameters
+ * @param Smarty_Internal_Template $template template object
+ * @return string
+ * @uses smarty_make_timestamp()
+ */
+function smarty_function_html_select_time($params, $template)
+{
+ $prefix = "Time_";
+ $field_array = null;
+ $field_separator = "\n";
+ $option_separator = "\n";
+ $time = null;
+
+ $display_hours = true;
+ $display_minutes = true;
+ $display_seconds = true;
+ $display_meridian = true;
+
+ $hour_format = '%02d';
+ $hour_value_format = '%02d';
+ $minute_format = '%02d';
+ $minute_value_format = '%02d';
+ $second_format = '%02d';
+ $second_value_format = '%02d';
+
+ $hour_size = null;
+ $minute_size = null;
+ $second_size = null;
+ $meridian_size = null;
+
+ $all_empty = null;
+ $hour_empty = null;
+ $minute_empty = null;
+ $second_empty = null;
+ $meridian_empty = null;
+
+ $all_id = null;
+ $hour_id = null;
+ $minute_id = null;
+ $second_id = null;
+ $meridian_id = null;
+
+ $use_24_hours = true;
+ $minute_interval = 1;
+ $second_interval = 1;
+
+ $extra_attrs = '';
+ $all_extra = null;
+ $hour_extra = null;
+ $minute_extra = null;
+ $second_extra = null;
+ $meridian_extra = null;
+
+ foreach ($params as $_key => $_value) {
+ switch ($_key) {
+ case 'time':
+ if (!is_array($_value) && $_value !== null) {
+ $time = smarty_make_timestamp($_value);
+ }
+ break;
+
+ case 'prefix':
+ case 'field_array':
+
+ case 'field_separator':
+ case 'option_separator':
+
+ case 'all_extra':
+ case 'hour_extra':
+ case 'minute_extra':
+ case 'second_extra':
+ case 'meridian_extra':
+
+ case 'all_empty':
+ case 'hour_empty':
+ case 'minute_empty':
+ case 'second_empty':
+ case 'meridian_empty':
+
+ case 'all_id':
+ case 'hour_id':
+ case 'minute_id':
+ case 'second_id':
+ case 'meridian_id':
+
+ case 'hour_format':
+ case 'hour_value_format':
+ case 'minute_format':
+ case 'minute_value_format':
+ case 'second_format':
+ case 'second_value_format':
+ $$_key = (string)$_value;
+ break;
+
+ case 'display_hours':
+ case 'display_minutes':
+ case 'display_seconds':
+ case 'display_meridian':
+ case 'use_24_hours':
+ $$_key = (bool)$_value;
+ break;
+
+ case 'minute_interval':
+ case 'second_interval':
+
+ case 'hour_size':
+ case 'minute_size':
+ case 'second_size':
+ case 'meridian_size':
+ $$_key = (int)$_value;
+ break;
+
+ default:
+ if (!is_array($_value)) {
+ $extra_attrs .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_value) . '"';
+ } else {
+ trigger_error("html_select_date: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+ }
+ break;
+ }
+ }
+
+ if (isset($params['time']) && is_array($params['time'])) {
+ if (isset($params['time'][$prefix . 'Hour'])) {
+ // $_REQUEST[$field_array] given
+ foreach (array('H' => 'Hour', 'i' => 'Minute', 's' => 'Second') as $_elementKey => $_elementName) {
+ $_variableName = '_' . strtolower($_elementName);
+ $$_variableName = isset($params['time'][$prefix . $_elementName])
+ ? $params['time'][$prefix . $_elementName]
+ : date($_elementKey);
+ }
+ $_meridian = isset($params['time'][$prefix . 'Meridian'])
+ ? (' ' . $params['time'][$prefix . 'Meridian'])
+ : '';
+ $time = strtotime( $_hour . ':' . $_minute . ':' . $_second . $_meridian );
+ list($_hour, $_minute, $_second) = $time = explode('-', date('H-i-s', $time));
+ } elseif (isset($params['time'][$field_array][$prefix . 'Hour'])) {
+ // $_REQUEST given
+ foreach (array('H' => 'Hour', 'i' => 'Minute', 's' => 'Second') as $_elementKey => $_elementName) {
+ $_variableName = '_' . strtolower($_elementName);
+ $$_variableName = isset($params['time'][$field_array][$prefix . $_elementName])
+ ? $params['time'][$field_array][$prefix . $_elementName]
+ : date($_elementKey);
+ }
+ $_meridian = isset($params['time'][$field_array][$prefix . 'Meridian'])
+ ? (' ' . $params['time'][$field_array][$prefix . 'Meridian'])
+ : '';
+ $time = strtotime( $_hour . ':' . $_minute . ':' . $_second . $_meridian );
+ list($_hour, $_minute, $_second) = $time = explode('-', date('H-i-s', $time));
+ } else {
+ // no date found, use NOW
+ list($_year, $_month, $_day) = $time = explode('-', date('Y-m-d'));
+ }
+ } elseif ($time === null) {
+ if (array_key_exists('time', $params)) {
+ $_hour = $_minute = $_second = $time = null;
+ } else {
+ list($_hour, $_minute, $_second) = $time = explode('-', date('H-i-s'));
+ }
+ } else {
+ list($_hour, $_minute, $_second) = $time = explode('-', date('H-i-s', $time));
+ }
+
+ // generate hour <select>
+ if ($display_hours) {
+ $_html_hours = '';
+ $_extra = '';
+ $_name = $field_array ? ($field_array . '[' . $prefix . 'Hour]') : ($prefix . 'Hour');
+ if ($all_extra) {
+ $_extra .= ' ' . $all_extra;
+ }
+ if ($hour_extra) {
+ $_extra .= ' ' . $hour_extra;
+ }
+
+ $_html_hours = '<select name="' . $_name . '"';
+ if ($hour_id !== null || $all_id !== null) {
+ $_html_hours .= ' id="' . smarty_function_escape_special_chars(
+ $hour_id !== null ? ( $hour_id ? $hour_id : $_name ) : ( $all_id ? ($all_id . $_name) : $_name )
+ ) . '"';
+ }
+ if ($hour_size) {
+ $_html_hours .= ' size="' . $hour_size . '"';
+ }
+ $_html_hours .= $_extra . $extra_attrs . '>' . $option_separator;
+
+ if (isset($hour_empty) || isset($all_empty)) {
+ $_html_hours .= '<option value="">' . ( isset($hour_empty) ? $hour_empty : $all_empty ) . '</option>' . $option_separator;
+ }
+
+ $start = $use_24_hours ? 0 : 1;
+ $end = $use_24_hours ? 23 : 12;
+ for ($i=$start; $i <= $end; $i++) {
+ $_val = sprintf('%02d', $i);
+ $_text = $hour_format == '%02d' ? $_val : sprintf($hour_format, $i);
+ $_value = $hour_value_format == '%02d' ? $_val : sprintf($hour_value_format, $i);
+
+ if (!$use_24_hours) {
+ $_hour12 = $_hour == 0
+ ? 12
+ : ($_hour <= 12 ? $_hour : $_hour -12);
+ }
+
+ $selected = $_hour !== null ? ($use_24_hours ? $_hour == $_val : $_hour12 == $_val) : null;
+ $_html_hours .= '<option value="' . $_value . '"'
+ . ($selected ? ' selected="selected"' : '')
+ . '>' . $_text . '</option>' . $option_separator;
+ }
+
+ $_html_hours .= '</select>';
+ }
+
+ // generate minute <select>
+ if ($display_minutes) {
+ $_html_minutes = '';
+ $_extra = '';
+ $_name = $field_array ? ($field_array . '[' . $prefix . 'Minute]') : ($prefix . 'Minute');
+ if ($all_extra) {
+ $_extra .= ' ' . $all_extra;
+ }
+ if ($minute_extra) {
+ $_extra .= ' ' . $minute_extra;
+ }
+
+ $_html_minutes = '<select name="' . $_name . '"';
+ if ($minute_id !== null || $all_id !== null) {
+ $_html_minutes .= ' id="' . smarty_function_escape_special_chars(
+ $minute_id !== null ? ( $minute_id ? $minute_id : $_name ) : ( $all_id ? ($all_id . $_name) : $_name )
+ ) . '"';
+ }
+ if ($minute_size) {
+ $_html_minutes .= ' size="' . $minute_size . '"';
+ }
+ $_html_minutes .= $_extra . $extra_attrs . '>' . $option_separator;
+
+ if (isset($minute_empty) || isset($all_empty)) {
+ $_html_minutes .= '<option value="">' . ( isset($minute_empty) ? $minute_empty : $all_empty ) . '</option>' . $option_separator;
+ }
+
+ $selected = $_minute !== null ? ($_minute - $_minute % $minute_interval) : null;
+ for ($i=0; $i <= 59; $i += $minute_interval) {
+ $_val = sprintf('%02d', $i);
+ $_text = $minute_format == '%02d' ? $_val : sprintf($minute_format, $i);
+ $_value = $minute_value_format == '%02d' ? $_val : sprintf($minute_value_format, $i);
+ $_html_minutes .= '<option value="' . $_value . '"'
+ . ($selected === $i ? ' selected="selected"' : '')
+ . '>' . $_text . '</option>' . $option_separator;
+ }
+
+ $_html_minutes .= '</select>';
+ }
+
+ // generate second <select>
+ if ($display_seconds) {
+ $_html_seconds = '';
+ $_extra = '';
+ $_name = $field_array ? ($field_array . '[' . $prefix . 'Second]') : ($prefix . 'Second');
+ if ($all_extra) {
+ $_extra .= ' ' . $all_extra;
+ }
+ if ($second_extra) {
+ $_extra .= ' ' . $second_extra;
+ }
+
+ $_html_seconds = '<select name="' . $_name . '"';
+ if ($second_id !== null || $all_id !== null) {
+ $_html_seconds .= ' id="' . smarty_function_escape_special_chars(
+ $second_id !== null ? ( $second_id ? $second_id : $_name ) : ( $all_id ? ($all_id . $_name) : $_name )
+ ) . '"';
+ }
+ if ($second_size) {
+ $_html_seconds .= ' size="' . $second_size . '"';
+ }
+ $_html_seconds .= $_extra . $extra_attrs . '>' . $option_separator;
+
+ if (isset($second_empty) || isset($all_empty)) {
+ $_html_seconds .= '<option value="">' . ( isset($second_empty) ? $second_empty : $all_empty ) . '</option>' . $option_separator;
+ }
+
+ $selected = $_second !== null ? ($_second - $_second % $second_interval) : null;
+ for ($i=0; $i <= 59; $i += $second_interval) {
+ $_val = sprintf('%02d', $i);
+ $_text = $second_format == '%02d' ? $_val : sprintf($second_format, $i);
+ $_value = $second_value_format == '%02d' ? $_val : sprintf($second_value_format, $i);
+ $_html_seconds .= '<option value="' . $_value . '"'
+ . ($selected === $i ? ' selected="selected"' : '')
+ . '>' . $_text . '</option>' . $option_separator;
+ }
+
+ $_html_seconds .= '</select>';
+ }
+
+ // generate meridian <select>
+ if ($display_meridian && !$use_24_hours) {
+ $_html_meridian = '';
+ $_extra = '';
+ $_name = $field_array ? ($field_array . '[' . $prefix . 'Meridian]') : ($prefix . 'Meridian');
+ if ($all_extra) {
+ $_extra .= ' ' . $all_extra;
+ }
+ if ($meridian_extra) {
+ $_extra .= ' ' . $meridian_extra;
+ }
+
+ $_html_meridian = '<select name="' . $_name . '"';
+ if ($meridian_id !== null || $all_id !== null) {
+ $_html_meridian .= ' id="' . smarty_function_escape_special_chars(
+ $meridian_id !== null ? ( $meridian_id ? $meridian_id : $_name ) : ( $all_id ? ($all_id . $_name) : $_name )
+ ) . '"';
+ }
+ if ($meridian_size) {
+ $_html_meridian .= ' size="' . $meridian_size . '"';
+ }
+ $_html_meridian .= $_extra . $extra_attrs . '>' . $option_separator;
+
+ if (isset($meridian_empty) || isset($all_empty)) {
+ $_html_meridian .= '<option value="">' . ( isset($meridian_empty) ? $meridian_empty : $all_empty ) . '</option>' . $option_separator;
+ }
+
+ $_html_meridian .= '<option value="am"'. ($_hour < 12 ? ' selected="selected"' : '') .'>AM</option>' . $option_separator
+ . '<option value="pm"'. ($_hour < 12 ? '' : ' selected="selected"') .'>PM</option>' . $option_separator
+ . '</select>';
+ }
+
+ $_html = '';
+ foreach (array('_html_hours', '_html_minutes', '_html_seconds', '_html_meridian') as $k) {
+ if (isset($$k)) {
+ if ($_html) {
+ $_html .= $field_separator;
+ }
+ $_html .= $$k;
+ }
+ }
+
+ return $_html;
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/function.html_table.php b/public_html/lib/Smarty/plugins/function.html_table.php
new file mode 100644
index 0000000..6b9cb9d
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/function.html_table.php
@@ -0,0 +1,177 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {html_table} function plugin
+ *
+ * Type: function<br>
+ * Name: html_table<br>
+ * Date: Feb 17, 2003<br>
+ * Purpose: make an html table from an array of data<br>
+ * Params:
+ * <pre>
+ * - loop - array to loop through
+ * - cols - number of columns, comma separated list of column names
+ * or array of column names
+ * - rows - number of rows
+ * - table_attr - table attributes
+ * - th_attr - table heading attributes (arrays are cycled)
+ * - tr_attr - table row attributes (arrays are cycled)
+ * - td_attr - table cell attributes (arrays are cycled)
+ * - trailpad - value to pad trailing cells with
+ * - caption - text for caption element
+ * - vdir - vertical direction (default: "down", means top-to-bottom)
+ * - hdir - horizontal direction (default: "right", means left-to-right)
+ * - inner - inner loop (default "cols": print $loop line by line,
+ * $loop will be printed column by column otherwise)
+ * </pre>
+ * Examples:
+ * <pre>
+ * {table loop=$data}
+ * {table loop=$data cols=4 tr_attr='"bgcolor=red"'}
+ * {table loop=$data cols="first,second,third" tr_attr=$colors}
+ * </pre>
+ *
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author credit to Messju Mohr <messju at lammfellpuschen dot de>
+ * @author credit to boots <boots dot smarty at yahoo dot com>
+ * @version 1.1
+ * @link http://www.smarty.net/manual/en/language.function.html.table.php {html_table}
+ * (Smarty online manual)
+ * @param array $params parameters
+ * @param Smarty_Internal_Template $template template object
+ * @return string
+ */
+function smarty_function_html_table($params, $template)
+{
+ $table_attr = 'border="1"';
+ $tr_attr = '';
+ $th_attr = '';
+ $td_attr = '';
+ $cols = $cols_count = 3;
+ $rows = 3;
+ $trailpad = '&nbsp;';
+ $vdir = 'down';
+ $hdir = 'right';
+ $inner = 'cols';
+ $caption = '';
+ $loop = null;
+
+ if (!isset($params['loop'])) {
+ trigger_error("html_table: missing 'loop' parameter",E_USER_WARNING);
+ return;
+ }
+
+ foreach ($params as $_key => $_value) {
+ switch ($_key) {
+ case 'loop':
+ $$_key = (array)$_value;
+ break;
+
+ case 'cols':
+ if (is_array($_value) && !empty($_value)) {
+ $cols = $_value;
+ $cols_count = count($_value);
+ } elseif (!is_numeric($_value) && is_string($_value) && !empty($_value)) {
+ $cols = explode(',', $_value);
+ $cols_count = count($cols);
+ } elseif (!empty($_value)) {
+ $cols_count = (int)$_value;
+ } else {
+ $cols_count = $cols;
+ }
+ break;
+
+ case 'rows':
+ $$_key = (int)$_value;
+ break;
+
+ case 'table_attr':
+ case 'trailpad':
+ case 'hdir':
+ case 'vdir':
+ case 'inner':
+ case 'caption':
+ $$_key = (string)$_value;
+ break;
+
+ case 'tr_attr':
+ case 'td_attr':
+ case 'th_attr':
+ $$_key = $_value;
+ break;
+ }
+ }
+
+ $loop_count = count($loop);
+ if (empty($params['rows'])) {
+ /* no rows specified */
+ $rows = ceil($loop_count / $cols_count);
+ } elseif (empty($params['cols'])) {
+ if (!empty($params['rows'])) {
+ /* no cols specified, but rows */
+ $cols_count = ceil($loop_count / $rows);
+ }
+ }
+
+ $output = "<table $table_attr>\n";
+
+ if (!empty($caption)) {
+ $output .= '<caption>' . $caption . "</caption>\n";
+ }
+
+ if (is_array($cols)) {
+ $cols = ($hdir == 'right') ? $cols : array_reverse($cols);
+ $output .= "<thead><tr>\n";
+
+ for ($r = 0; $r < $cols_count; $r++) {
+ $output .= '<th' . smarty_function_html_table_cycle('th', $th_attr, $r) . '>';
+ $output .= $cols[$r];
+ $output .= "</th>\n";
+ }
+ $output .= "</tr></thead>\n";
+ }
+
+ $output .= "<tbody>\n";
+ for ($r = 0; $r < $rows; $r++) {
+ $output .= "<tr" . smarty_function_html_table_cycle('tr', $tr_attr, $r) . ">\n";
+ $rx = ($vdir == 'down') ? $r * $cols_count : ($rows-1 - $r) * $cols_count;
+
+ for ($c = 0; $c < $cols_count; $c++) {
+ $x = ($hdir == 'right') ? $rx + $c : $rx + $cols_count-1 - $c;
+ if ($inner != 'cols') {
+ /* shuffle x to loop over rows*/
+ $x = floor($x / $cols_count) + ($x % $cols_count) * $rows;
+ }
+
+ if ($x < $loop_count) {
+ $output .= "<td" . smarty_function_html_table_cycle('td', $td_attr, $c) . ">" . $loop[$x] . "</td>\n";
+ } else {
+ $output .= "<td" . smarty_function_html_table_cycle('td', $td_attr, $c) . ">$trailpad</td>\n";
+ }
+ }
+ $output .= "</tr>\n";
+ }
+ $output .= "</tbody>\n";
+ $output .= "</table>\n";
+
+ return $output;
+}
+
+function smarty_function_html_table_cycle($name, $var, $no)
+{
+ if (!is_array($var)) {
+ $ret = $var;
+ } else {
+ $ret = $var[$no % count($var)];
+ }
+
+ return ($ret) ? ' ' . $ret : '';
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/function.mailto.php b/public_html/lib/Smarty/plugins/function.mailto.php
new file mode 100644
index 0000000..c61cf2d
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/function.mailto.php
@@ -0,0 +1,152 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {mailto} function plugin
+ *
+ * Type: function<br>
+ * Name: mailto<br>
+ * Date: May 21, 2002
+ * Purpose: automate mailto address link creation, and optionally encode them.<br>
+ * Params:
+ * <pre>
+ * - address - (required) - e-mail address
+ * - text - (optional) - text to display, default is address
+ * - encode - (optional) - can be one of:
+ * * none : no encoding (default)
+ * * javascript : encode with javascript
+ * * javascript_charcode : encode with javascript charcode
+ * * hex : encode with hexidecimal (no javascript)
+ * - cc - (optional) - address(es) to carbon copy
+ * - bcc - (optional) - address(es) to blind carbon copy
+ * - subject - (optional) - e-mail subject
+ * - newsgroups - (optional) - newsgroup(s) to post to
+ * - followupto - (optional) - address(es) to follow up to
+ * - extra - (optional) - extra tags for the href link
+ * </pre>
+ * Examples:
+ * <pre>
+ * {mailto address="me@domain.com"}
+ * {mailto address="me@domain.com" encode="javascript"}
+ * {mailto address="me@domain.com" encode="hex"}
+ * {mailto address="me@domain.com" subject="Hello to you!"}
+ * {mailto address="me@domain.com" cc="you@domain.com,they@domain.com"}
+ * {mailto address="me@domain.com" extra='class="mailto"'}
+ * </pre>
+ *
+ * @link http://www.smarty.net/manual/en/language.function.mailto.php {mailto}
+ * (Smarty online manual)
+ * @version 1.2
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author credits to Jason Sweat (added cc, bcc and subject functionality)
+ * @param array $params parameters
+ * @param Smarty_Internal_Template $template template object
+ * @return string
+ */
+function smarty_function_mailto($params, $template)
+{
+ static $_allowed_encoding = array('javascript' => true, 'javascript_charcode' => true, 'hex' => true, 'none' => true);
+ $extra = '';
+
+ if (empty($params['address'])) {
+ trigger_error("mailto: missing 'address' parameter",E_USER_WARNING);
+ return;
+ } else {
+ $address = $params['address'];
+ }
+
+ $text = $address;
+ // netscape and mozilla do not decode %40 (@) in BCC field (bug?)
+ // so, don't encode it.
+ $search = array('%40', '%2C');
+ $replace = array('@', ',');
+ $mail_parms = array();
+ foreach ($params as $var => $value) {
+ switch ($var) {
+ case 'cc':
+ case 'bcc':
+ case 'followupto':
+ if (!empty($value))
+ $mail_parms[] = $var . '=' . str_replace($search, $replace, rawurlencode($value));
+ break;
+
+ case 'subject':
+ case 'newsgroups':
+ $mail_parms[] = $var . '=' . rawurlencode($value);
+ break;
+
+ case 'extra':
+ case 'text':
+ $$var = $value;
+
+ default:
+ }
+ }
+
+ if ($mail_parms) {
+ $address .= '?' . join('&', $mail_parms);
+ }
+
+ $encode = (empty($params['encode'])) ? 'none' : $params['encode'];
+ if (!isset($_allowed_encoding[$encode])) {
+ trigger_error("mailto: 'encode' parameter must be none, javascript, javascript_charcode or hex", E_USER_WARNING);
+ return;
+ }
+ // FIXME: (rodneyrehm) document.write() excues me what? 1998 has passed!
+ if ($encode == 'javascript') {
+ $string = 'document.write(\'<a href="mailto:' . $address . '" ' . $extra . '>' . $text . '</a>\');';
+
+ $js_encode = '';
+ for ($x = 0, $_length = strlen($string); $x < $_length; $x++) {
+ $js_encode .= '%' . bin2hex($string[$x]);
+ }
+
+ return '<script type="text/javascript">eval(unescape(\'' . $js_encode . '\'))</script>';
+ } elseif ($encode == 'javascript_charcode') {
+ $string = '<a href="mailto:' . $address . '" ' . $extra . '>' . $text . '</a>';
+
+ for($x = 0, $y = strlen($string); $x < $y; $x++) {
+ $ord[] = ord($string[$x]);
+ }
+
+ $_ret = "<script type=\"text/javascript\" language=\"javascript\">\n"
+ . "{document.write(String.fromCharCode("
+ . implode(',', $ord)
+ . "))"
+ . "}\n"
+ . "</script>\n";
+
+ return $_ret;
+ } elseif ($encode == 'hex') {
+ preg_match('!^(.*)(\?.*)$!', $address, $match);
+ if (!empty($match[2])) {
+ trigger_error("mailto: hex encoding does not work with extra attributes. Try javascript.",E_USER_WARNING);
+ return;
+ }
+ $address_encode = '';
+ for ($x = 0, $_length = strlen($address); $x < $_length; $x++) {
+ if (preg_match('!\w!u', $address[$x])) {
+ $address_encode .= '%' . bin2hex($address[$x]);
+ } else {
+ $address_encode .= $address[$x];
+ }
+ }
+ $text_encode = '';
+ for ($x = 0, $_length = strlen($text); $x < $_length; $x++) {
+ $text_encode .= '&#x' . bin2hex($text[$x]) . ';';
+ }
+
+ $mailto = "&#109;&#97;&#105;&#108;&#116;&#111;&#58;";
+ return '<a href="' . $mailto . $address_encode . '" ' . $extra . '>' . $text_encode . '</a>';
+ } else {
+ // no encoding
+ return '<a href="mailto:' . $address . '" ' . $extra . '>' . $text . '</a>';
+ }
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/function.math.php b/public_html/lib/Smarty/plugins/function.math.php
new file mode 100644
index 0000000..f4d3f05
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/function.math.php
@@ -0,0 +1,87 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * This plugin is only for Smarty2 BC
+ * @package Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {math} function plugin
+ *
+ * Type: function<br>
+ * Name: math<br>
+ * Purpose: handle math computations in template
+ *
+ * @link http://www.smarty.net/manual/en/language.function.math.php {math}
+ * (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @param array $params parameters
+ * @param Smarty_Internal_Template $template template object
+ * @return string|null
+ */
+function smarty_function_math($params, $template)
+{
+ static $_allowed_funcs = array(
+ 'int' => true, 'abs' => true, 'ceil' => true, 'cos' => true, 'exp' => true, 'floor' => true,
+ 'log' => true, 'log10' => true, 'max' => true, 'min' => true, 'pi' => true, 'pow' => true,
+ 'rand' => true, 'round' => true, 'sin' => true, 'sqrt' => true, 'srand' => true ,'tan' => true
+ );
+ // be sure equation parameter is present
+ if (empty($params['equation'])) {
+ trigger_error("math: missing equation parameter",E_USER_WARNING);
+ return;
+ }
+
+ $equation = $params['equation'];
+
+ // make sure parenthesis are balanced
+ if (substr_count($equation,"(") != substr_count($equation,")")) {
+ trigger_error("math: unbalanced parenthesis",E_USER_WARNING);
+ return;
+ }
+
+ // match all vars in equation, make sure all are passed
+ preg_match_all("!(?:0x[a-fA-F0-9]+)|([a-zA-Z][a-zA-Z0-9_]*)!",$equation, $match);
+
+ foreach($match[1] as $curr_var) {
+ if ($curr_var && !isset($params[$curr_var]) && !isset($_allowed_funcs[$curr_var])) {
+ trigger_error("math: function call $curr_var not allowed",E_USER_WARNING);
+ return;
+ }
+ }
+
+ foreach($params as $key => $val) {
+ if ($key != "equation" && $key != "format" && $key != "assign") {
+ // make sure value is not empty
+ if (strlen($val)==0) {
+ trigger_error("math: parameter $key is empty",E_USER_WARNING);
+ return;
+ }
+ if (!is_numeric($val)) {
+ trigger_error("math: parameter $key: is not numeric",E_USER_WARNING);
+ return;
+ }
+ $equation = preg_replace("/\b$key\b/", " \$params['$key'] ", $equation);
+ }
+ }
+ $smarty_math_result = null;
+ eval("\$smarty_math_result = ".$equation.";");
+
+ if (empty($params['format'])) {
+ if (empty($params['assign'])) {
+ return $smarty_math_result;
+ } else {
+ $template->assign($params['assign'],$smarty_math_result);
+ }
+ } else {
+ if (empty($params['assign'])){
+ printf($params['format'],$smarty_math_result);
+ } else {
+ $template->assign($params['assign'],sprintf($params['format'],$smarty_math_result));
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifier.capitalize.php b/public_html/lib/Smarty/plugins/modifier.capitalize.php
new file mode 100644
index 0000000..1e19909
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifier.capitalize.php
@@ -0,0 +1,65 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifier
+ */
+
+/**
+ * Smarty capitalize modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: capitalize<br>
+ * Purpose: capitalize words in the string
+ *
+ * {@internal {$string|capitalize:true:true} is the fastest option for MBString enabled systems }}
+ *
+ * @param string $string string to capitalize
+ * @param boolean $uc_digits also capitalize "x123" to "X123"
+ * @param boolean $lc_rest capitalize first letters, lowercase all following letters "aAa" to "Aaa"
+ * @return string capitalized string
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author Rodney Rehm
+ */
+function smarty_modifier_capitalize($string, $uc_digits = false, $lc_rest = false)
+{
+ if (SMARTY_MBSTRING /* ^phpunit */&&empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ if ($lc_rest) {
+ // uppercase (including hyphenated words)
+ $upper_string = mb_convert_case( $string, MB_CASE_TITLE, SMARTY_RESOURCE_CHAR_SET );
+ } else {
+ // uppercase word breaks
+ $upper_string = preg_replace("!(^|[^\p{L}'])([\p{Ll}])!ueS", "stripslashes('\\1').mb_convert_case(stripslashes('\\2'),MB_CASE_UPPER, SMARTY_RESOURCE_CHAR_SET)", $string);
+ }
+ // check uc_digits case
+ if (!$uc_digits) {
+ if (preg_match_all("!\b([\p{L}]*[\p{N}]+[\p{L}]*)\b!u", $string, $matches, PREG_OFFSET_CAPTURE)) {
+ foreach($matches[1] as $match) {
+ $upper_string = substr_replace($upper_string, mb_strtolower($match[0], SMARTY_RESOURCE_CHAR_SET), $match[1], strlen($match[0]));
+ }
+ }
+ }
+ $upper_string = preg_replace("!((^|\s)['\"])(\w)!ue", "stripslashes('\\1').mb_convert_case(stripslashes('\\3'),MB_CASE_UPPER, SMARTY_RESOURCE_CHAR_SET)", $upper_string);
+ return $upper_string;
+ }
+
+ // lowercase first
+ if ($lc_rest) {
+ $string = strtolower($string);
+ }
+ // uppercase (including hyphenated words)
+ $upper_string = preg_replace("!(^|[^\p{L}'])([\p{Ll}])!ueS", "stripslashes('\\1').ucfirst(stripslashes('\\2'))", $string);
+ // check uc_digits case
+ if (!$uc_digits) {
+ if (preg_match_all("!\b([\p{L}]*[\p{N}]+[\p{L}]*)\b!u", $string, $matches, PREG_OFFSET_CAPTURE)) {
+ foreach($matches[1] as $match) {
+ $upper_string = substr_replace($upper_string, strtolower($match[0]), $match[1], strlen($match[0]));
+ }
+ }
+ }
+ $upper_string = preg_replace("!((^|\s)['\"])(\w)!ue", "stripslashes('\\1').strtoupper(stripslashes('\\3'))", $upper_string);
+ return $upper_string;
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifier.date_format.php b/public_html/lib/Smarty/plugins/modifier.date_format.php
new file mode 100644
index 0000000..729322b
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifier.date_format.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifier
+ */
+
+/**
+ * Smarty date_format modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: date_format<br>
+ * Purpose: format datestamps via strftime<br>
+ * Input:<br>
+ * - string: input date string
+ * - format: strftime format for output
+ * - default_date: default date if $string is empty
+ *
+ * @link http://www.smarty.net/manual/en/language.modifier.date.format.php date_format (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @param string $string input date string
+ * @param string $format strftime format for output
+ * @param string $default_date default date if $string is empty
+ * @param string $formatter either 'strftime' or 'auto'
+ * @return string |void
+ * @uses smarty_make_timestamp()
+ */
+function smarty_modifier_date_format($string, $format = SMARTY_RESOURCE_DATE_FORMAT, $default_date = '',$formatter='auto')
+{
+ /**
+ * Include the {@link shared.make_timestamp.php} plugin
+ */
+ require_once(SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php');
+ if ($string != '') {
+ $timestamp = smarty_make_timestamp($string);
+ } elseif ($default_date != '') {
+ $timestamp = smarty_make_timestamp($default_date);
+ } else {
+ return;
+ }
+ if($formatter=='strftime'||($formatter=='auto'&&strpos($format,'%')!==false)) {
+ if (DS == '\\') {
+ $_win_from = array('%D', '%h', '%n', '%r', '%R', '%t', '%T');
+ $_win_to = array('%m/%d/%y', '%b', "\n", '%I:%M:%S %p', '%H:%M', "\t", '%H:%M:%S');
+ if (strpos($format, '%e') !== false) {
+ $_win_from[] = '%e';
+ $_win_to[] = sprintf('%\' 2d', date('j', $timestamp));
+ }
+ if (strpos($format, '%l') !== false) {
+ $_win_from[] = '%l';
+ $_win_to[] = sprintf('%\' 2d', date('h', $timestamp));
+ }
+ $format = str_replace($_win_from, $_win_to, $format);
+ }
+ return strftime($format, $timestamp);
+ } else {
+ return date($format, $timestamp);
+ }
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifier.debug_print_var.php b/public_html/lib/Smarty/plugins/modifier.debug_print_var.php
new file mode 100644
index 0000000..747c87f
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifier.debug_print_var.php
@@ -0,0 +1,105 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage Debug
+ */
+
+/**
+ * Smarty debug_print_var modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: debug_print_var<br>
+ * Purpose: formats variable contents for display in the console
+ *
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @param array|object $var variable to be formatted
+ * @param integer $depth maximum recursion depth if $var is an array
+ * @param integer $length maximum string length if $var is a string
+ * @return string
+ */
+function smarty_modifier_debug_print_var ($var, $depth = 0, $length = 40)
+{
+ $_replace = array("\n" => '<i>\n</i>',
+ "\r" => '<i>\r</i>',
+ "\t" => '<i>\t</i>'
+ );
+
+ switch (gettype($var)) {
+ case 'array' :
+ $results = '<b>Array (' . count($var) . ')</b>';
+ foreach ($var as $curr_key => $curr_val) {
+ $results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
+ . '<b>' . strtr($curr_key, $_replace) . '</b> =&gt; '
+ . smarty_modifier_debug_print_var($curr_val, ++$depth, $length);
+ $depth--;
+ }
+ break;
+
+ case 'object' :
+ $object_vars = get_object_vars($var);
+ $results = '<b>' . get_class($var) . ' Object (' . count($object_vars) . ')</b>';
+ foreach ($object_vars as $curr_key => $curr_val) {
+ $results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
+ . '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '
+ . smarty_modifier_debug_print_var($curr_val, ++$depth, $length);
+ $depth--;
+ }
+ break;
+
+ case 'boolean' :
+ case 'NULL' :
+ case 'resource' :
+ if (true === $var) {
+ $results = 'true';
+ } elseif (false === $var) {
+ $results = 'false';
+ } elseif (null === $var) {
+ $results = 'null';
+ } else {
+ $results = htmlspecialchars((string) $var);
+ }
+ $results = '<i>' . $results . '</i>';
+ break;
+
+ case 'integer' :
+ case 'float' :
+ $results = htmlspecialchars((string) $var);
+ break;
+
+ case 'string' :
+ $results = strtr($var, $_replace);
+ if (SMARTY_MBSTRING /* ^phpunit */&&empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ if (mb_strlen($var, SMARTY_RESOURCE_CHAR_SET) > $length) {
+ $results = mb_substr($var, 0, $length - 3, SMARTY_RESOURCE_CHAR_SET) . '...';
+ }
+ } else {
+ if (isset($var[$length])) {
+ $results = substr($var, 0, $length - 3) . '...';
+ }
+ }
+
+ $results = htmlspecialchars('"' . $results . '"');
+ break;
+
+ case 'unknown type' :
+ default :
+ $results = strtr((string) $var, $_replace);
+ if (SMARTY_MBSTRING /* ^phpunit */&&empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ if (mb_strlen($results, SMARTY_RESOURCE_CHAR_SET) > $length) {
+ $results = mb_substr($results, 0, $length - 3, SMARTY_RESOURCE_CHAR_SET) . '...';
+ }
+ } else {
+ if (strlen($results) > $length) {
+ $results = substr($results, 0, $length - 3) . '...';
+ }
+ }
+
+ $results = htmlspecialchars($results);
+ }
+
+ return $results;
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifier.escape.php b/public_html/lib/Smarty/plugins/modifier.escape.php
new file mode 100644
index 0000000..5e865a8
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifier.escape.php
@@ -0,0 +1,143 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifier
+ */
+
+/**
+ * Smarty escape modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: escape<br>
+ * Purpose: escape string for output
+ *
+ * @link http://www.smarty.net/manual/en/language.modifier.count.characters.php count_characters (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @param string $string input string
+ * @param string $esc_type escape type
+ * @param string $char_set character set, used for htmlspecialchars() or htmlentities()
+ * @param boolean $double_encode encode already encoded entitites again, used for htmlspecialchars() or htmlentities()
+ * @return string escaped input string
+ */
+function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $double_encode = true)
+{
+ if (!$char_set) {
+ $char_set = SMARTY_RESOURCE_CHAR_SET;
+ }
+
+ switch ($esc_type) {
+ case 'html':
+ return htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode);
+
+ case 'htmlall':
+ if (SMARTY_MBSTRING /* ^phpunit */ && empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ // mb_convert_encoding ignores htmlspecialchars()
+ $string = htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode);
+ // htmlentities() won't convert everything, so use mb_convert_encoding
+ return mb_convert_encoding($string, 'HTML-ENTITIES', $char_set);
+ }
+
+ // no MBString fallback
+ return htmlentities($string, ENT_QUOTES, $char_set, $double_encode);
+
+ case 'url':
+ return rawurlencode($string);
+
+ case 'urlpathinfo':
+ return str_replace('%2F', '/', rawurlencode($string));
+
+ case 'quotes':
+ // escape unescaped single quotes
+ return preg_replace("%(?<!\\\\)'%", "\\'", $string);
+
+ case 'hex':
+ // escape every byte into hex
+ // Note that the UTF-8 encoded character ä will be represented as %c3%a4
+ $return = '';
+ $_length = strlen($string);
+ for ($x = 0; $x < $_length; $x++) {
+ $return .= '%' . bin2hex($string[$x]);
+ }
+ return $return;
+
+ case 'hexentity':
+ $return = '';
+ if (SMARTY_MBSTRING /* ^phpunit */ && empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ require_once(SMARTY_PLUGINS_DIR . 'shared.mb_unicode.php');
+ $return = '';
+ foreach (smarty_mb_to_unicode($string, SMARTY_RESOURCE_CHAR_SET) as $unicode) {
+ $return .= '&#x' . strtoupper(dechex($unicode)) . ';';
+ }
+ return $return;
+ }
+ // no MBString fallback
+ $_length = strlen($string);
+ for ($x = 0; $x < $_length; $x++) {
+ $return .= '&#x' . bin2hex($string[$x]) . ';';
+ }
+ return $return;
+
+ case 'decentity':
+ $return = '';
+ if (SMARTY_MBSTRING /* ^phpunit */ && empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ require_once(SMARTY_PLUGINS_DIR . 'shared.mb_unicode.php');
+ $return = '';
+ foreach (smarty_mb_to_unicode($string, SMARTY_RESOURCE_CHAR_SET) as $unicode) {
+ $return .= '&#' . $unicode . ';';
+ }
+ return $return;
+ }
+ // no MBString fallback
+ $_length = strlen($string);
+ for ($x = 0; $x < $_length; $x++) {
+ $return .= '&#' . ord($string[$x]) . ';';
+ }
+ return $return;
+
+ case 'javascript':
+ // escape quotes and backslashes, newlines, etc.
+ return strtr($string, array('\\' => '\\\\', "'" => "\\'", '"' => '\\"', "\r" => '\\r', "\n" => '\\n', '</' => '<\/'));
+
+ case 'mail':
+ if (SMARTY_MBSTRING /* ^phpunit */ && empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ require_once(SMARTY_PLUGINS_DIR . 'shared.mb_str_replace.php');
+ return smarty_mb_str_replace(array('@', '.'), array(' [AT] ', ' [DOT] '), $string);
+ }
+ // no MBString fallback
+ return str_replace(array('@', '.'), array(' [AT] ', ' [DOT] '), $string);
+
+ case 'nonstd':
+ // escape non-standard chars, such as ms document quotes
+ $return = '';
+ if (SMARTY_MBSTRING /* ^phpunit */ && empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ require_once(SMARTY_PLUGINS_DIR . 'shared.mb_unicode.php');
+ foreach (smarty_mb_to_unicode($string, SMARTY_RESOURCE_CHAR_SET) as $unicode) {
+ if ($unicode >= 126) {
+ $return .= '&#' . $unicode . ';';
+ } else {
+ $return .= chr($unicode);
+ }
+ }
+ return $return;
+ }
+
+ $_length = strlen($string);
+ for ($_i = 0; $_i < $_length; $_i++) {
+ $_ord = ord(substr($string, $_i, 1));
+ // non-standard char, escape it
+ if ($_ord >= 126) {
+ $return .= '&#' . $_ord . ';';
+ } else {
+ $return .= substr($string, $_i, 1);
+ }
+ }
+ return $return;
+
+ default:
+ return $string;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifier.regex_replace.php b/public_html/lib/Smarty/plugins/modifier.regex_replace.php
new file mode 100644
index 0000000..f9fd5fa
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifier.regex_replace.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifier
+ */
+
+/**
+ * Smarty regex_replace modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: regex_replace<br>
+ * Purpose: regular expression search/replace
+ *
+ * @link http://smarty.php.net/manual/en/language.modifier.regex.replace.php
+ * regex_replace (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @param string $string input string
+ * @param string|array $search regular expression(s) to search for
+ * @param string|array $replace string(s) that should be replaced
+ * @return string
+ */
+function smarty_modifier_regex_replace($string, $search, $replace)
+{
+ if(is_array($search)) {
+ foreach($search as $idx => $s) {
+ $search[$idx] = _smarty_regex_replace_check($s);
+ }
+ } else {
+ $search = _smarty_regex_replace_check($search);
+ }
+ return preg_replace($search, $replace, $string);
+}
+
+/**
+ * @param string $search string(s) that should be replaced
+ * @return string
+ * @ignore
+ */
+function _smarty_regex_replace_check($search)
+{
+ // null-byte injection detection
+ // anything behind the first null-byte is ignored
+ if (($pos = strpos($search,"\0")) !== false) {
+ $search = substr($search,0,$pos);
+ }
+ // remove eval-modifier from $search
+ if (preg_match('!([a-zA-Z\s]+)$!s', $search, $match) && (strpos($match[1], 'e') !== false)) {
+ $search = substr($search, 0, -strlen($match[1])) . preg_replace('![e\s]+!', '', $match[1]);
+ }
+ return $search;
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifier.replace.php b/public_html/lib/Smarty/plugins/modifier.replace.php
new file mode 100644
index 0000000..ce671b1
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifier.replace.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage PluginsModifier
+ */
+
+/**
+ * Smarty replace modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: replace<br>
+ * Purpose: simple search/replace
+ *
+ * @link http://smarty.php.net/manual/en/language.modifier.replace.php replace (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author Uwe Tews
+ * @param string $string input string
+ * @param string $search text to search for
+ * @param string $replace replacement text
+ * @return string
+ */
+function smarty_modifier_replace($string, $search, $replace)
+{
+ if (SMARTY_MBSTRING /* ^phpunit */&&empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ require_once(SMARTY_PLUGINS_DIR . 'shared.mb_str_replace.php');
+ return smarty_mb_str_replace($search, $replace, $string);
+ }
+
+ return str_replace($search, $replace, $string);
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifier.spacify.php b/public_html/lib/Smarty/plugins/modifier.spacify.php
new file mode 100644
index 0000000..f7985ad
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifier.spacify.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage PluginsModifier
+ */
+
+/**
+ * Smarty spacify modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: spacify<br>
+ * Purpose: add spaces between characters in a string
+ *
+ * @link http://smarty.php.net/manual/en/language.modifier.spacify.php spacify (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @param string $string input string
+ * @param string $spacify_char string to insert between characters.
+ * @return string
+ */
+function smarty_modifier_spacify($string, $spacify_char = ' ')
+{
+ // well… what about charsets besides latin and UTF-8?
+ return implode($spacify_char, preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY));
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifier.truncate.php b/public_html/lib/Smarty/plugins/modifier.truncate.php
new file mode 100644
index 0000000..99ae543
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifier.truncate.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifier
+ */
+
+/**
+ * Smarty truncate modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: truncate<br>
+ * Purpose: Truncate a string to a certain length if necessary,
+ * optionally splitting in the middle of a word, and
+ * appending the $etc string or inserting $etc into the middle.
+ *
+ * @link http://smarty.php.net/manual/en/language.modifier.truncate.php truncate (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @param string $string input string
+ * @param integer $length length of truncated text
+ * @param string $etc end string
+ * @param boolean $break_words truncate at word boundary
+ * @param boolean $middle truncate in the middle of text
+ * @return string truncated string
+ */
+function smarty_modifier_truncate($string, $length = 80, $etc = '...', $break_words = false, $middle = false) {
+ if ($length == 0)
+ return '';
+
+ if (SMARTY_MBSTRING /* ^phpunit */&&empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ if (mb_strlen($string, SMARTY_RESOURCE_CHAR_SET) > $length) {
+ $length -= min($length, mb_strlen($etc, SMARTY_RESOURCE_CHAR_SET));
+ if (!$break_words && !$middle) {
+ $string = preg_replace('/\s+?(\S+)?$/u', '', mb_substr($string, 0, $length + 1, SMARTY_RESOURCE_CHAR_SET));
+ }
+ if (!$middle) {
+ return mb_substr($string, 0, $length, SMARTY_RESOURCE_CHAR_SET) . $etc;
+ }
+ return mb_substr($string, 0, $length / 2, SMARTY_RESOURCE_CHAR_SET) . $etc . mb_substr($string, - $length / 2, $length, SMARTY_RESOURCE_CHAR_SET);
+ }
+ return $string;
+ }
+
+ // no MBString fallback
+ if (isset($string[$length])) {
+ $length -= min($length, strlen($etc));
+ if (!$break_words && !$middle) {
+ $string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length + 1));
+ }
+ if (!$middle) {
+ return substr($string, 0, $length) . $etc;
+ }
+ return substr($string, 0, $length / 2) . $etc . substr($string, - $length / 2);
+ }
+ return $string;
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.cat.php b/public_html/lib/Smarty/plugins/modifiercompiler.cat.php
new file mode 100644
index 0000000..1cfe630
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.cat.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty cat modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: cat<br>
+ * Date: Feb 24, 2003<br>
+ * Purpose: catenate a value to a variable<br>
+ * Input: string to catenate<br>
+ * Example: {$var|cat:"foo"}
+ *
+ * @link http://smarty.php.net/manual/en/language.modifier.cat.php cat
+ * (Smarty online manual)
+ * @author Uwe Tews
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_cat($params, $compiler)
+{
+ return '('.implode(').(', $params).')';
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.count_characters.php b/public_html/lib/Smarty/plugins/modifiercompiler.count_characters.php
new file mode 100644
index 0000000..ae95fda
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.count_characters.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty count_characters modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: count_characteres<br>
+ * Purpose: count the number of characters in a text
+ *
+ * @link http://www.smarty.net/manual/en/language.modifier.count.characters.php count_characters (Smarty online manual)
+ * @author Uwe Tews
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_count_characters($params, $compiler)
+{
+ if (!isset($params[1]) || $params[1] != 'true') {
+ return 'preg_match_all(\'/[^\s]/u\',' . $params[0] . ', $tmp)';
+ }
+ if (SMARTY_MBSTRING /* ^phpunit */&&empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ return 'mb_strlen(' . $params[0] . ', SMARTY_RESOURCE_CHAR_SET)';
+ }
+ // no MBString fallback
+ return 'strlen(' . $params[0] . ')';
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.count_paragraphs.php b/public_html/lib/Smarty/plugins/modifiercompiler.count_paragraphs.php
new file mode 100644
index 0000000..0e1b0af
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.count_paragraphs.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty count_paragraphs modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: count_paragraphs<br>
+ * Purpose: count the number of paragraphs in a text
+ *
+ * @link http://www.smarty.net/manual/en/language.modifier.count.paragraphs.php
+ * count_paragraphs (Smarty online manual)
+ * @author Uwe Tews
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_count_paragraphs($params, $compiler)
+{
+ // count \r or \n characters
+ return '(preg_match_all(\'#[\r\n]+#\', ' . $params[0] . ', $tmp)+1)';
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.count_sentences.php b/public_html/lib/Smarty/plugins/modifiercompiler.count_sentences.php
new file mode 100644
index 0000000..7f48a3e
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.count_sentences.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty count_sentences modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: count_sentences
+ * Purpose: count the number of sentences in a text
+ *
+ * @link http://www.smarty.net/manual/en/language.modifier.count.paragraphs.php
+ * count_sentences (Smarty online manual)
+ * @author Uwe Tews
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_count_sentences($params, $compiler)
+{
+ // find periods, question marks, exclamation marks with a word before but not after.
+ return 'preg_match_all("#\w[\.\?\!](\W|$)#uS", ' . $params[0] . ', $tmp)';
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.count_words.php b/public_html/lib/Smarty/plugins/modifiercompiler.count_words.php
new file mode 100644
index 0000000..cd9ae5b
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.count_words.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty count_words modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: count_words<br>
+ * Purpose: count the number of words in a text
+ *
+ * @link http://www.smarty.net/manual/en/language.modifier.count.words.php count_words (Smarty online manual)
+ * @author Uwe Tews
+ * @param array $params parameters
+ * @return string with compiled code
+*/
+function smarty_modifiercompiler_count_words($params, $compiler)
+{
+ if (SMARTY_MBSTRING /* ^phpunit */&&empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ // return 'preg_match_all(\'#[\w\pL]+#u\', ' . $params[0] . ', $tmp)';
+ // expression taken from http://de.php.net/manual/en/function.str-word-count.php#85592
+ return 'preg_match_all(\'/\p{L}[\p{L}\p{Mn}\p{Pd}\\\'\x{2019}]*/u\', ' . $params[0] . ', $tmp)';
+ }
+ // no MBString fallback
+ return 'str_word_count(' . $params[0] . ')';
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.default.php b/public_html/lib/Smarty/plugins/modifiercompiler.default.php
new file mode 100644
index 0000000..4f831a5
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.default.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty default modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: default<br>
+ * Purpose: designate default value for empty variables
+ *
+ * @link http://www.smarty.net/manual/en/language.modifier.default.php default (Smarty online manual)
+ * @author Uwe Tews
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_default ($params, $compiler)
+{
+ $output = $params[0];
+ if (!isset($params[1])) {
+ $params[1] = "''";
+ }
+
+ array_shift($params);
+ foreach ($params as $param) {
+ $output = '(($tmp = @' . $output . ')===null||$tmp===\'\' ? ' . $param . ' : $tmp)';
+ }
+ return $output;
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.escape.php b/public_html/lib/Smarty/plugins/modifiercompiler.escape.php
new file mode 100644
index 0000000..c536d5f
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.escape.php
@@ -0,0 +1,90 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * @ignore
+ */
+require_once( SMARTY_PLUGINS_DIR .'shared.literal_compiler_param.php' );
+
+/**
+ * Smarty escape modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: escape<br>
+ * Purpose: escape string for output
+ *
+ * @link http://www.smarty.net/docsv2/en/language.modifier.escape count_characters (Smarty online manual)
+ * @author Rodney Rehm
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_escape($params, $compiler)
+{
+ try {
+ $esc_type = smarty_literal_compiler_param($params, 1, 'html');
+ $char_set = smarty_literal_compiler_param($params, 2, SMARTY_RESOURCE_CHAR_SET);
+ $double_encode = smarty_literal_compiler_param($params, 3, true);
+
+ if (!$char_set) {
+ $char_set = SMARTY_RESOURCE_CHAR_SET;
+ }
+
+ switch ($esc_type) {
+ case 'html':
+ return 'htmlspecialchars('
+ . $params[0] .', ENT_QUOTES, '
+ . var_export($char_set, true) . ', '
+ . var_export($double_encode, true) . ')';
+
+ case 'htmlall':
+ if (SMARTY_MBSTRING /* ^phpunit */&&empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ return 'mb_convert_encoding(htmlspecialchars('
+ . $params[0] .', ENT_QUOTES, '
+ . var_export($char_set, true) . ', '
+ . var_export($double_encode, true)
+ . '), "HTML-ENTITIES", '
+ . var_export($char_set, true) . ')';
+ }
+
+ // no MBString fallback
+ return 'htmlentities('
+ . $params[0] .', ENT_QUOTES, '
+ . var_export($char_set, true) . ', '
+ . var_export($double_encode, true) . ')';
+
+ case 'url':
+ return 'rawurlencode(' . $params[0] . ')';
+
+ case 'urlpathinfo':
+ return 'str_replace("%2F", "/", rawurlencode(' . $params[0] . '))';
+
+ case 'quotes':
+ // escape unescaped single quotes
+ return 'preg_replace("%(?<!\\\\\\\\)\'%", "\\\'",' . $params[0] . ')';
+
+ case 'javascript':
+ // escape quotes and backslashes, newlines, etc.
+ return 'strtr(' . $params[0] . ', array("\\\\" => "\\\\\\\\", "\'" => "\\\\\'", "\"" => "\\\\\"", "\\r" => "\\\\r", "\\n" => "\\\n", "</" => "<\/" ))';
+
+ }
+ } catch(SmartyException $e) {
+ // pass through to regular plugin fallback
+ }
+
+ // could not optimize |escape call, so fallback to regular plugin
+ if ($compiler->tag_nocache | $compiler->nocache) {
+ $compiler->template->required_plugins['nocache']['escape']['modifier']['file'] = SMARTY_PLUGINS_DIR .'modifier.escape.php';
+ $compiler->template->required_plugins['nocache']['escape']['modifier']['function'] = 'smarty_modifier_escape';
+ } else {
+ $compiler->template->required_plugins['compiled']['escape']['modifier']['file'] = SMARTY_PLUGINS_DIR .'modifier.escape.php';
+ $compiler->template->required_plugins['compiled']['escape']['modifier']['function'] = 'smarty_modifier_escape';
+ }
+ return 'smarty_modifier_escape(' . join( ', ', $params ) . ')';
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.from_charset.php b/public_html/lib/Smarty/plugins/modifiercompiler.from_charset.php
new file mode 100644
index 0000000..1561fbc
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.from_charset.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty from_charset modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: from_charset<br>
+ * Purpose: convert character encoding from $charset to internal encoding
+ *
+ * @author Rodney Rehm
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_from_charset($params, $compiler)
+{
+ if (!SMARTY_MBSTRING /* ^phpunit */&&empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ // FIXME: (rodneyrehm) shouldn't this throw an error?
+ return $params[0];
+ }
+
+ if (!isset($params[1])) {
+ $params[1] = '"ISO-8859-1"';
+ }
+
+ return 'mb_convert_encoding(' . $params[0] . ', SMARTY_RESOURCE_CHAR_SET, ' . $params[1] . ')';
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.indent.php b/public_html/lib/Smarty/plugins/modifiercompiler.indent.php
new file mode 100644
index 0000000..020c4fd
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.indent.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty indent modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: indent<br>
+ * Purpose: indent lines of text
+ *
+ * @link http://www.smarty.net/manual/en/language.modifier.indent.php indent (Smarty online manual)
+ * @author Uwe Tews
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+
+function smarty_modifiercompiler_indent($params, $compiler)
+{
+ if (!isset($params[1])) {
+ $params[1] = 4;
+ }
+ if (!isset($params[2])) {
+ $params[2] = "' '";
+ }
+ return 'preg_replace(\'!^!m\',str_repeat(' . $params[2] . ',' . $params[1] . '),' . $params[0] . ')';
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.lower.php b/public_html/lib/Smarty/plugins/modifiercompiler.lower.php
new file mode 100644
index 0000000..1744158
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.lower.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty lower modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: lower<br>
+ * Purpose: convert string to lowercase
+ *
+ * @link http://www.smarty.net/manual/en/language.modifier.lower.php lower (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author Uwe Tews
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+
+function smarty_modifiercompiler_lower($params, $compiler)
+{
+ if (SMARTY_MBSTRING /* ^phpunit */&&empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ return 'mb_strtolower(' . $params[0] . ',SMARTY_RESOURCE_CHAR_SET)' ;
+ }
+ // no MBString fallback
+ return 'strtolower(' . $params[0] . ')';
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.noprint.php b/public_html/lib/Smarty/plugins/modifiercompiler.noprint.php
new file mode 100644
index 0000000..3ca2657
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.noprint.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty noprint modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: noprint<br>
+ * Purpose: return an empty string
+ *
+ * @author Uwe Tews
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_noprint($params, $compiler)
+{
+ return "''";
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.string_format.php b/public_html/lib/Smarty/plugins/modifiercompiler.string_format.php
new file mode 100644
index 0000000..8334597
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.string_format.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty string_format modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: string_format<br>
+ * Purpose: format strings via sprintf
+ *
+ * @link http://www.smarty.net/manual/en/language.modifier.string.format.php string_format (Smarty online manual)
+ * @author Uwe Tews
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_string_format($params, $compiler)
+{
+ return 'sprintf(' . $params[1] . ',' . $params[0] . ')';
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.strip.php b/public_html/lib/Smarty/plugins/modifiercompiler.strip.php
new file mode 100644
index 0000000..2a2d9d0
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.strip.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty strip modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: strip<br>
+ * Purpose: Replace all repeated spaces, newlines, tabs
+ * with a single space or supplied replacement string.<br>
+ * Example: {$var|strip} {$var|strip:"&nbsp;"}<br>
+ * Date: September 25th, 2002
+ *
+ * @link http://www.smarty.net/manual/en/language.modifier.strip.php strip (Smarty online manual)
+ * @author Uwe Tews
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+
+function smarty_modifiercompiler_strip($params, $compiler)
+{
+ if (!isset($params[1])) {
+ $params[1] = "' '";
+ }
+ return "preg_replace('!\s+!u', {$params[1]},{$params[0]})";
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.strip_tags.php b/public_html/lib/Smarty/plugins/modifiercompiler.strip_tags.php
new file mode 100644
index 0000000..296a3a2
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.strip_tags.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty strip_tags modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: strip_tags<br>
+ * Purpose: strip html tags from text
+ *
+ * @link http://www.smarty.net/manual/en/language.modifier.strip.tags.php strip_tags (Smarty online manual)
+ * @author Uwe Tews
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_strip_tags($params, $compiler)
+{
+ if (!isset($params[1])) {
+ $params[1] = true;
+ }
+ if ($params[1] === true) {
+ return "preg_replace('!<[^>]*?>!', ' ', {$params[0]})";
+ } else {
+ return 'strip_tags(' . $params[0] . ')';
+ }
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.to_charset.php b/public_html/lib/Smarty/plugins/modifiercompiler.to_charset.php
new file mode 100644
index 0000000..e0877b7
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.to_charset.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty to_charset modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: to_charset<br>
+ * Purpose: convert character encoding from internal encoding to $charset
+ *
+ * @author Rodney Rehm
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_to_charset($params, $compiler)
+{
+ if (!SMARTY_MBSTRING /* ^phpunit */&&empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ // FIXME: (rodneyrehm) shouldn't this throw an error?
+ return $params[0];
+ }
+
+ if (!isset($params[1])) {
+ $params[1] = '"ISO-8859-1"';
+ }
+
+ return 'mb_convert_encoding(' . $params[0] . ', ' . $params[1] . ', SMARTY_RESOURCE_CHAR_SET)';
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.unescape.php b/public_html/lib/Smarty/plugins/modifiercompiler.unescape.php
new file mode 100644
index 0000000..7e77cb4
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.unescape.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty unescape modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: unescape<br>
+ * Purpose: unescape html entities
+ *
+ * @author Rodney Rehm
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_unescape($params, $compiler)
+{
+ if (!isset($params[1])) {
+ $params[1] = 'html';
+ }
+ if (!isset($params[2])) {
+ $params[2] = "SMARTY_RESOURCE_CHAR_SET";
+ } else {
+ $params[2] = "'" . $params[2] . "'";
+ }
+
+ switch (trim($params[1], '"\'')) {
+ case 'entity':
+ return 'mb_convert_encoding(' . $params[0] . ', ' . $params[2] . ', \'HTML-ENTITIES\')';
+ case 'htmlall':
+ if (SMARTY_MBSTRING /* ^phpunit */&&empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ return 'mb_convert_encoding(' . $params[0] . ', ' . $params[2] . ', \'HTML-ENTITIES\')';
+ }
+ return 'html_entity_decode(' . $params[0] . ', ENT_QUOTES, ' . $params[2] . ')';
+
+ case 'html':
+ return 'htmlspecialchars_decode(' . $params[0] . ', ENT_QUOTES)';
+
+ default:
+ return $params[0];
+ }
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.upper.php b/public_html/lib/Smarty/plugins/modifiercompiler.upper.php
new file mode 100644
index 0000000..739057c
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.upper.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty upper modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: lower<br>
+ * Purpose: convert string to uppercase
+ *
+ * @link http://smarty.php.net/manual/en/language.modifier.upper.php lower (Smarty online manual)
+ * @author Uwe Tews
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_upper($params, $compiler)
+{
+ if (SMARTY_MBSTRING /* ^phpunit */&&empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ return 'mb_strtoupper(' . $params[0] . ',SMARTY_RESOURCE_CHAR_SET)' ;
+ }
+ // no MBString fallback
+ return 'strtoupper(' . $params[0] . ')';
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/modifiercompiler.wordwrap.php b/public_html/lib/Smarty/plugins/modifiercompiler.wordwrap.php
new file mode 100644
index 0000000..577135a
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/modifiercompiler.wordwrap.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty wordwrap modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: wordwrap<br>
+ * Purpose: wrap a string of text at a given length
+ *
+ * @link http://smarty.php.net/manual/en/language.modifier.wordwrap.php wordwrap (Smarty online manual)
+ * @author Uwe Tews
+ * @param array $params parameters
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_wordwrap($params, $compiler)
+{
+ if (!isset($params[1])) {
+ $params[1] = 80;
+ }
+ if (!isset($params[2])) {
+ $params[2] = '"\n"';
+ }
+ if (!isset($params[3])) {
+ $params[3] = 'false';
+ }
+ $function = 'wordwrap';
+ if (SMARTY_MBSTRING /* ^phpunit */&&empty($_SERVER['SMARTY_PHPUNIT_DISABLE_MBSTRING'])/* phpunit$ */) {
+ if ($compiler->tag_nocache | $compiler->nocache) {
+ $compiler->template->required_plugins['nocache']['wordwrap']['modifier']['file'] = SMARTY_PLUGINS_DIR .'shared.mb_wordwrap.php';
+ $compiler->template->required_plugins['nocache']['wordwrap']['modifier']['function'] = 'smarty_mb_wordwrap';
+ } else {
+ $compiler->template->required_plugins['compiled']['wordwrap']['modifier']['file'] = SMARTY_PLUGINS_DIR .'shared.mb_wordwrap.php';
+ $compiler->template->required_plugins['compiled']['wordwrap']['modifier']['function'] = 'smarty_mb_wordwrap';
+ }
+ $function = 'smarty_mb_wordwrap';
+ }
+ return $function . '(' . $params[0] . ',' . $params[1] . ',' . $params[2] . ',' . $params[3] . ')';
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/outputfilter.trimwhitespace.php b/public_html/lib/Smarty/plugins/outputfilter.trimwhitespace.php
new file mode 100644
index 0000000..41828e1
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/outputfilter.trimwhitespace.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsFilter
+ */
+
+/**
+ * Smarty trimwhitespace outputfilter plugin
+ *
+ * Trim unnecessary whitespace from HTML markup.
+ *
+ * @author Rodney Rehm
+ * @param string $source input string
+ * @param Smarty_Internal_Template $smarty Smarty object
+ * @return string filtered output
+ */
+function smarty_outputfilter_trimwhitespace($source, Smarty_Internal_Template $smarty)
+{
+ $store = array();
+ $_store = 0;
+ $_offset = 0;
+
+ // Unify Line-Breaks to \n
+ $source = preg_replace("/\015\012|\015|\012/", "\n", $source);
+
+ // capture Internet Explorer Conditional Comments
+ if (preg_match_all('#<!--\[[^\]]+\]>.*?<!\[[^\]]+\]-->#is', $source, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
+ foreach ($matches as $match) {
+ $store[] = $match[0][0];
+ $_length = strlen($match[0][0]);
+ $replace = '@!@SMARTY:' . $_store . ':SMARTY@!@';
+ $source = substr_replace($source, $replace, $match[0][1] - $_offset, $_length);
+
+ $_offset += $_length - strlen($replace);
+ $_store++;
+ }
+ }
+
+ // Strip all HTML-Comments
+ $source = preg_replace( '#<!--.*?-->#ms', '', $source );
+
+ // capture html elements not to be messed with
+ $_offset = 0;
+ if (preg_match_all('#<(script|pre|textarea)[^>]*>.*?</\\1>#is', $source, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
+ foreach ($matches as $match) {
+ $store[] = $match[0][0];
+ $_length = strlen($match[0][0]);
+ $replace = '@!@SMARTY:' . $_store . ':SMARTY@!@';
+ $source = substr_replace($source, $replace, $match[0][1] - $_offset, $_length);
+
+ $_offset += $_length - strlen($replace);
+ $_store++;
+ }
+ }
+
+ $expressions = array(
+ // replace multiple spaces between tags by a single space
+ // can't remove them entirely, becaue that might break poorly implemented CSS display:inline-block elements
+ '#(:SMARTY@!@|>)\s+(?=@!@SMARTY:|<)#s' => '\1 \2',
+ // remove spaces between attributes (but not in attribute values!)
+ '#(([a-z0-9]\s*=\s*(["\'])[^\3]*?\3)|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \4',
+ // note: for some very weird reason trim() seems to remove spaces inside attributes.
+ // maybe a \0 byte or something is interfering?
+ '#^\s+<#Ss' => '<',
+ '#>\s+$#Ss' => '>',
+ );
+
+ $source = preg_replace( array_keys($expressions), array_values($expressions), $source );
+ // note: for some very weird reason trim() seems to remove spaces inside attributes.
+ // maybe a \0 byte or something is interfering?
+ // $source = trim( $source );
+
+ // capture html elements not to be messed with
+ $_offset = 0;
+ if (preg_match_all('#@!@SMARTY:([0-9]+):SMARTY@!@#is', $source, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
+ foreach ($matches as $match) {
+ $store[] = $match[0][0];
+ $_length = strlen($match[0][0]);
+ $replace = array_shift($store);
+ $source = substr_replace($source, $replace, $match[0][1] + $_offset, $_length);
+
+ $_offset += strlen($replace) - $_length;
+ $_store++;
+ }
+ }
+
+ return $source;
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/shared.escape_special_chars.php b/public_html/lib/Smarty/plugins/shared.escape_special_chars.php
new file mode 100644
index 0000000..c087be1
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/shared.escape_special_chars.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Smarty shared plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsShared
+ */
+
+if (version_compare(PHP_VERSION, '5.2.3', '>=')) {
+ /**
+ * escape_special_chars common function
+ *
+ * Function: smarty_function_escape_special_chars<br>
+ * Purpose: used by other smarty functions to escape
+ * special chars except for already escaped ones
+ *
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @param string $string text that should by escaped
+ * @return string
+ */
+ function smarty_function_escape_special_chars($string)
+ {
+ if (!is_array($string)) {
+ $string = htmlspecialchars($string, ENT_COMPAT, SMARTY_RESOURCE_CHAR_SET, false);
+ }
+ return $string;
+ }
+} else {
+ /**
+ * escape_special_chars common function
+ *
+ * Function: smarty_function_escape_special_chars<br>
+ * Purpose: used by other smarty functions to escape
+ * special chars except for already escaped ones
+ *
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @param string $string text that should by escaped
+ * @return string
+ */
+ function smarty_function_escape_special_chars($string)
+ {
+ if (!is_array($string)) {
+ $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string);
+ $string = htmlspecialchars($string);
+ $string = str_replace(array('%%%SMARTY_START%%%', '%%%SMARTY_END%%%'), array('&', ';'), $string);
+ }
+ return $string;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/shared.literal_compiler_param.php b/public_html/lib/Smarty/plugins/shared.literal_compiler_param.php
new file mode 100644
index 0000000..dbcd937
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/shared.literal_compiler_param.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsShared
+ */
+
+/**
+ * evaluate compiler parameter
+ *
+ * @param array $params parameter array as given to the compiler function
+ * @param integer $index array index of the parameter to convert
+ * @param mixed $default value to be returned if the parameter is not present
+ * @return mixed evaluated value of parameter or $default
+ * @throws SmartyException if parameter is not a literal (but an expression, variable, …)
+ * @author Rodney Rehm
+ */
+function smarty_literal_compiler_param($params, $index, $default=null)
+{
+ // not set, go default
+ if (!isset($params[$index])) {
+ return $default;
+ }
+ // test if param is a literal
+ if (!preg_match('/^([\'"]?)[a-zA-Z0-9]+(\\1)$/', $params[$index])) {
+ throw new SmartyException('$param[' . $index . '] is not a literal and is thus not evaluatable at compile time');
+ }
+
+ $t = null;
+ eval("\$t = " . $params[$index] . ";");
+ return $t;
+}
diff --git a/public_html/lib/Smarty/plugins/shared.make_timestamp.php b/public_html/lib/Smarty/plugins/shared.make_timestamp.php
new file mode 100644
index 0000000..5d7c97e
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/shared.make_timestamp.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Smarty shared plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsShared
+ */
+
+/**
+ * Function: smarty_make_timestamp<br>
+ * Purpose: used by other smarty functions to make a timestamp from a string.
+ *
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @param DateTime|int|string $string date object, timestamp or string that can be converted using strtotime()
+ * @return int
+ */
+function smarty_make_timestamp($string)
+{
+ if (empty($string)) {
+ // use "now":
+ return time();
+ } elseif ($string instanceof DateTime) {
+ return $string->getTimestamp();
+ } elseif (strlen($string) == 14 && ctype_digit($string)) {
+ // it is mysql timestamp format of YYYYMMDDHHMMSS?
+ return mktime(substr($string, 8, 2),substr($string, 10, 2),substr($string, 12, 2),
+ substr($string, 4, 2),substr($string, 6, 2),substr($string, 0, 4));
+ } elseif (is_numeric($string)) {
+ // it is a numeric string, we handle it as timestamp
+ return (int) $string;
+ } else {
+ // strtotime should handle it
+ $time = strtotime($string);
+ if ($time == -1 || $time === false) {
+ // strtotime() was not able to parse $string, use "now":
+ return time();
+ }
+ return $time;
+ }
+}
+
+?>
diff --git a/public_html/lib/Smarty/plugins/shared.mb_str_replace.php b/public_html/lib/Smarty/plugins/shared.mb_str_replace.php
new file mode 100644
index 0000000..ecafeb7
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/shared.mb_str_replace.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Smarty shared plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsShared
+ */
+if (!function_exists('smarty_mb_str_replace')) {
+
+ /**
+ * Multibyte string replace
+ *
+ * @param string $search the string to be searched
+ * @param string $replace the replacement string
+ * @param string $subject the source string
+ * @param int &$count number of matches found
+ * @return string replaced string
+ * @author Rodney Rehm
+ */
+ function smarty_mb_str_replace($search, $replace, $subject, &$count=0)
+ {
+ if (!is_array($search) && is_array($replace)) {
+ return false;
+ }
+ if (is_array($subject)) {
+ // call mb_replace for each single string in $subject
+ foreach ($subject as &$string) {
+ $string = &smarty_mb_str_replace($search, $replace, $string, $c);
+ $count += $c;
+ }
+ } elseif (is_array($search)) {
+ if (!is_array($replace)) {
+ foreach ($search as &$string) {
+ $subject = smarty_mb_str_replace($string, $replace, $subject, $c);
+ $count += $c;
+ }
+ } else {
+ $n = max(count($search), count($replace));
+ while ($n--) {
+ $subject = smarty_mb_str_replace(current($search), current($replace), $subject, $c);
+ $count += $c;
+ next($search);
+ next($replace);
+ }
+ }
+ } else {
+ $parts = mb_split(preg_quote($search), $subject);
+ $count = count($parts) - 1;
+ $subject = implode($replace, $parts);
+ }
+ return $subject;
+ }
+
+}
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/shared.mb_unicode.php b/public_html/lib/Smarty/plugins/shared.mb_unicode.php
new file mode 100644
index 0000000..e7f839e
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/shared.mb_unicode.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Smarty shared plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsShared
+ */
+
+/**
+ * convert characters to their decimal unicode equivalents
+ *
+ * @link http://www.ibm.com/developerworks/library/os-php-unicode/index.html#listing3 for inspiration
+ * @param string $string characters to calculate unicode of
+ * @param string $encoding encoding of $string, if null mb_internal_encoding() is used
+ * @return array sequence of unicodes
+ * @author Rodney Rehm
+ */
+function smarty_mb_to_unicode($string, $encoding=null) {
+ if ($encoding) {
+ $expanded = mb_convert_encoding($string, "UTF-32BE", $encoding);
+ } else {
+ $expanded = mb_convert_encoding($string, "UTF-32BE");
+ }
+ return unpack("N*", $expanded);
+}
+
+/**
+ * convert unicodes to the character of given encoding
+ *
+ * @link http://www.ibm.com/developerworks/library/os-php-unicode/index.html#listing3 for inspiration
+ * @param integer|array $unicode single unicode or list of unicodes to convert
+ * @param string $encoding encoding of returned string, if null mb_internal_encoding() is used
+ * @return string unicode as character sequence in given $encoding
+ * @author Rodney Rehm
+ */
+function smarty_mb_from_unicode($unicode, $encoding=null) {
+ $t = '';
+ if (!$encoding) {
+ $encoding = mb_internal_encoding();
+ }
+ foreach((array) $unicode as $utf32be) {
+ $character = pack("N*", $utf32be);
+ $t .= mb_convert_encoding($character, $encoding, "UTF-32BE");
+ }
+ return $t;
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/shared.mb_wordwrap.php b/public_html/lib/Smarty/plugins/shared.mb_wordwrap.php
new file mode 100644
index 0000000..89e8fbf
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/shared.mb_wordwrap.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Smarty shared plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsShared
+ */
+
+if(!function_exists('smarty_mb_wordwrap')) {
+
+ /**
+ * Wrap a string to a given number of characters
+ *
+ * @link http://php.net/manual/en/function.wordwrap.php for similarity
+ * @param string $str the string to wrap
+ * @param int $width the width of the output
+ * @param string $break the character used to break the line
+ * @param boolean $cut ignored parameter, just for the sake of
+ * @return string wrapped string
+ * @author Rodney Rehm
+ */
+ function smarty_mb_wordwrap($str, $width=75, $break="\n", $cut=false)
+ {
+ // break words into tokens using white space as a delimiter
+ $tokens = preg_split('!(\s)!uS', $str, -1, PREG_SPLIT_NO_EMPTY + PREG_SPLIT_DELIM_CAPTURE);
+ $length = 0;
+ $t = '';
+ $_previous = false;
+
+ foreach ($tokens as $_token) {
+ $token_length = mb_strlen($_token, SMARTY_RESOURCE_CHAR_SET);
+ $_tokens = array($_token);
+ if ($token_length > $width) {
+ // remove last space
+ $t = mb_substr($t, 0, -1, SMARTY_RESOURCE_CHAR_SET);
+ $_previous = false;
+ $length = 0;
+
+ if ($cut) {
+ $_tokens = preg_split('!(.{' . $width . '})!uS', $_token, -1, PREG_SPLIT_NO_EMPTY + PREG_SPLIT_DELIM_CAPTURE);
+ // broken words go on a new line
+ $t .= $break;
+ }
+ }
+
+ foreach ($_tokens as $token) {
+ $_space = !!preg_match('!^\s$!uS', $token);
+ $token_length = mb_strlen($token, SMARTY_RESOURCE_CHAR_SET);
+ $length += $token_length;
+
+ if ($length > $width) {
+ // remove space before inserted break
+ if ($_previous && $token_length < $width) {
+ $t = mb_substr($t, 0, -1, SMARTY_RESOURCE_CHAR_SET);
+ }
+
+ // add the break before the token
+ $t .= $break;
+ $length = $token_length;
+
+ // skip space after inserting a break
+ if ($_space) {
+ $length = 0;
+ continue;
+ }
+ } else if ($token == "\n") {
+ // hard break must reset counters
+ $_previous = 0;
+ $length = 0;
+ } else {
+ // remember if we had a space or not
+ $_previous = $_space;
+ }
+ // add the token
+ $t .= $token;
+ }
+ }
+
+ return $t;
+ }
+
+}
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/plugins/variablefilter.htmlspecialchars.php b/public_html/lib/Smarty/plugins/variablefilter.htmlspecialchars.php
new file mode 100644
index 0000000..aeaeb60
--- /dev/null
+++ b/public_html/lib/Smarty/plugins/variablefilter.htmlspecialchars.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package Smarty
+ * @subpackage PluginsFilter
+ */
+
+/**
+ * Smarty htmlspecialchars variablefilter plugin
+ *
+ * @param string $source input string
+ * @param Smarty_Internal_Template $smarty Smarty object
+ * @return string filtered output
+ */
+function smarty_variablefilter_htmlspecialchars($source, $smarty)
+{
+ return htmlspecialchars($source, ENT_QUOTES, SMARTY_RESOURCE_CHAR_SET);
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/sysplugins/smarty_cacheresource.php b/public_html/lib/Smarty/sysplugins/smarty_cacheresource.php
new file mode 100644
index 0000000..ca18add
--- /dev/null
+++ b/public_html/lib/Smarty/sysplugins/smarty_cacheresource.php
@@ -0,0 +1,381 @@
+<?php
+/**
+* Smarty Internal Plugin
+*
+* @package Smarty
+* @subpackage Cacher
+*/
+
+/**
+* Cache Handler API
+*
+* @package Smarty
+* @subpackage Cacher
+* @author Rodney Rehm
+*/
+abstract class Smarty_CacheResource {
+ /**
+ * cache for Smarty_CacheResource instances
+ * @var array
+ */
+ public static $resources = array();
+
+ /**
+ * resource types provided by the core
+ * @var array
+ */
+ protected static $sysplugins = array(
+ 'file' => true,
+ );
+
+ /**
+ * populate Cached Object with meta data from Resource
+ *
+ * @param Smarty_Template_Cached $cached cached object
+ * @param Smarty_Internal_Template $_template template object
+ * @return void
+ */
+ public abstract function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template);
+
+ /**
+ * populate Cached Object with timestamp and exists from Resource
+ *
+ * @param Smarty_Template_Cached $source cached object
+ * @return void
+ */
+ public abstract function populateTimestamp(Smarty_Template_Cached $cached);
+
+ /**
+ * Read the cached template and process header
+ *
+ * @param Smarty_Internal_Template $_template template object
+ * @param Smarty_Template_Cached $cached cached object
+ * @return booelan true or false if the cached content does not exist
+ */
+ public abstract function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached=null);
+
+ /**
+ * Write the rendered template output to cache
+ *
+ * @param Smarty_Internal_Template $_template template object
+ * @param string $content content to cache
+ * @return boolean success
+ */
+ public abstract function writeCachedContent(Smarty_Internal_Template $_template, $content);
+
+ /**
+ * Return cached content
+ *
+ * @param Smarty_Internal_Template $_template template object
+ * @param string $content content of cache
+ */
+ public function getCachedContent(Smarty_Internal_Template $_template)
+ {
+ if ($_template->cached->handler->process($_template)) {
+ ob_start();
+ $_template->properties['unifunc']($_template);
+ return ob_get_clean();
+ }
+ return null;
+ }
+
+ /**
+ * Empty cache
+ *
+ * @param Smarty $smarty Smarty object
+ * @param integer $exp_time expiration time (number of seconds, not timestamp)
+ * @return integer number of cache files deleted
+ */
+ public abstract function clearAll(Smarty $smarty, $exp_time=null);
+
+ /**
+ * Empty cache for a specific template
+ *
+ * @param Smarty $smarty Smarty object
+ * @param string $resource_name template name
+ * @param string $cache_id cache id
+ * @param string $compile_id compile id
+ * @param integer $exp_time expiration time (number of seconds, not timestamp)
+ * @return integer number of cache files deleted
+ */
+ public abstract function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time);
+
+
+ public function locked(Smarty $smarty, Smarty_Template_Cached $cached)
+ {
+ // theoretically locking_timeout should be checked against time_limit (max_execution_time)
+ $start = microtime(true);
+ $hadLock = null;
+ while ($this->hasLock($smarty, $cached)) {
+ $hadLock = true;
+ if (microtime(true) - $start > $smarty->locking_timeout) {
+ // abort waiting for lock release
+ return false;
+ }
+ sleep(1);
+ }
+ return $hadLock;
+ }
+
+ public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached)
+ {
+ // check if lock exists
+ return false;
+ }
+
+ public function acquireLock(Smarty $smarty, Smarty_Template_Cached $cached)
+ {
+ // create lock
+ return true;
+ }
+
+ public function releaseLock(Smarty $smarty, Smarty_Template_Cached $cached)
+ {
+ // release lock
+ return true;
+ }
+
+
+ /**
+ * Load Cache Resource Handler
+ *
+ * @param Smarty $smarty Smarty object
+ * @param string $type name of the cache resource
+ * @return Smarty_CacheResource Cache Resource Handler
+ */
+ public static function load(Smarty $smarty, $type = null)
+ {
+ if (!isset($type)) {
+ $type = $smarty->caching_type;
+ }
+
+ // try smarty's cache
+ if (isset($smarty->_cacheresource_handlers[$type])) {
+ return $smarty->_cacheresource_handlers[$type];
+ }
+
+ // try registered resource
+ if (isset($smarty->registered_cache_resources[$type])) {
+ // do not cache these instances as they may vary from instance to instance
+ return $smarty->_cacheresource_handlers[$type] = $smarty->registered_cache_resources[$type];
+ }
+ // try sysplugins dir
+ if (isset(self::$sysplugins[$type])) {
+ if (!isset(self::$resources[$type])) {
+ $cache_resource_class = 'Smarty_Internal_CacheResource_' . ucfirst($type);
+ self::$resources[$type] = new $cache_resource_class();
+ }
+ return $smarty->_cacheresource_handlers[$type] = self::$resources[$type];
+ }
+ // try plugins dir
+ $cache_resource_class = 'Smarty_CacheResource_' . ucfirst($type);
+ if ($smarty->loadPlugin($cache_resource_class)) {
+ if (!isset(self::$resources[$type])) {
+ self::$resources[$type] = new $cache_resource_class();
+ }
+ return $smarty->_cacheresource_handlers[$type] = self::$resources[$type];
+ }
+ // give up
+ throw new SmartyException("Unable to load cache resource '{$type}'");
+ }
+
+ /**
+ * Invalid Loaded Cache Files
+ *
+ * @param Smarty $smarty Smarty object
+ */
+ public static function invalidLoadedCache(Smarty $smarty)
+ {
+ foreach ($smarty->template_objects as $tpl) {
+ if (isset($tpl->cached)) {
+ $tpl->cached->valid = false;
+ $tpl->cached->processed = false;
+ }
+ }
+ }
+}
+
+/**
+* Smarty Resource Data Object
+*
+* Cache Data Container for Template Files
+*
+* @package Smarty
+* @subpackage TemplateResources
+* @author Rodney Rehm
+*/
+class Smarty_Template_Cached {
+ /**
+ * Source Filepath
+ * @var string
+ */
+ public $filepath = false;
+
+ /**
+ * Source Content
+ * @var string
+ */
+ public $content = null;
+
+ /**
+ * Source Timestamp
+ * @var integer
+ */
+ public $timestamp = false;
+
+ /**
+ * Source Existance
+ * @var boolean
+ */
+ public $exists = false;
+
+ /**
+ * Cache Is Valid
+ * @var boolean
+ */
+ public $valid = false;
+
+ /**
+ * Cache was processed
+ * @var boolean
+ */
+ public $processed = false;
+
+ /**
+ * CacheResource Handler
+ * @var Smarty_CacheResource
+ */
+ public $handler = null;
+
+ /**
+ * Template Compile Id (Smarty_Internal_Template::$compile_id)
+ * @var string
+ */
+ public $compile_id = null;
+
+ /**
+ * Template Cache Id (Smarty_Internal_Template::$cache_id)
+ * @var string
+ */
+ public $cache_id = null;
+
+ /**
+ * Id for cache locking
+ * @var string
+ */
+ public $lock_id = null;
+
+ /**
+ * flag that cache is locked by this instance
+ * @var bool
+ */
+ public $is_locked = false;
+
+ /**
+ * Source Object
+ * @var Smarty_Template_Source
+ */
+ public $source = null;
+
+ /**
+ * create Cached Object container
+ *
+ * @param Smarty_Internal_Template $_template template object
+ */
+ public function __construct(Smarty_Internal_Template $_template)
+ {
+ $this->compile_id = $_template->compile_id;
+ $this->cache_id = $_template->cache_id;
+ $this->source = $_template->source;
+ $_template->cached = $this;
+ $smarty = $_template->smarty;
+
+ //
+ // load resource handler
+ //
+ $this->handler = $handler = Smarty_CacheResource::load($smarty); // Note: prone to circular references
+
+ //
+ // check if cache is valid
+ //
+ if (!($_template->caching == Smarty::CACHING_LIFETIME_CURRENT || $_template->caching == Smarty::CACHING_LIFETIME_SAVED) || $_template->source->recompiled) {
+ $handler->populate($this, $_template);
+ return;
+ }
+ while (true) {
+ while (true) {
+ $handler->populate($this, $_template);
+ if ($this->timestamp === false || $smarty->force_compile || $smarty->force_cache) {
+ $this->valid = false;
+ } else {
+ $this->valid = true;
+ }
+ if ($this->valid && $_template->caching == Smarty::CACHING_LIFETIME_CURRENT && $_template->cache_lifetime >= 0 && time() > ($this->timestamp + $_template->cache_lifetime)) {
+ // lifetime expired
+ $this->valid = false;
+ }
+ if ($this->valid || !$_template->smarty->cache_locking) {
+ break;
+ }
+ if (!$this->handler->locked($_template->smarty, $this)) {
+ $this->handler->acquireLock($_template->smarty, $this);
+ break 2;
+ }
+ }
+ if ($this->valid) {
+ if (!$_template->smarty->cache_locking || $this->handler->locked($_template->smarty, $this) === null) {
+ // load cache file for the following checks
+ if ($smarty->debugging) {
+ Smarty_Internal_Debug::start_cache($_template);
+ }
+ if($handler->process($_template, $this) === false) {
+ $this->valid = false;
+ } else {
+ $this->processed = true;
+ }
+ if ($smarty->debugging) {
+ Smarty_Internal_Debug::end_cache($_template);
+ }
+ } else {
+ continue;
+ }
+ } else {
+ return;
+ }
+ if ($this->valid && $_template->caching === Smarty::CACHING_LIFETIME_SAVED && $_template->properties['cache_lifetime'] >= 0 && (time() > ($_template->cached->timestamp + $_template->properties['cache_lifetime']))) {
+ $this->valid = false;
+ }
+ if (!$this->valid && $_template->smarty->cache_locking) {
+ $this->handler->acquireLock($_template->smarty, $this);
+ return;
+ } else {
+ return;
+ }
+ }
+ }
+
+ /**
+ * Write this cache object to handler
+ *
+ * @param Smarty_Internal_Template $_template template object
+ * @param string $content content to cache
+ * @return boolean success
+ */
+ public function write(Smarty_Internal_Template $_template, $content)
+ {
+ if (!$_template->source->recompiled) {
+ if ($this->handler->writeCachedContent($_template, $content)) {
+ $this->timestamp = time();
+ $this->exists = true;
+ $this->valid = true;
+ if ($_template->smarty->cache_locking) {
+ $this->handler->releaseLock($_template->smarty, $this);
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/sysplugins/smarty_cacheresource_custom.php b/public_html/lib/Smarty/sysplugins/smarty_cacheresource_custom.php
new file mode 100644
index 0000000..16fe72e
--- /dev/null
+++ b/public_html/lib/Smarty/sysplugins/smarty_cacheresource_custom.php
@@ -0,0 +1,238 @@
+<?php
+/**
+ * Smarty Internal Plugin
+ *
+ * @package Smarty
+ * @subpackage Cacher
+ */
+
+/**
+ * Cache Handler API
+ *
+ * @package Smarty
+ * @subpackage Cacher
+ * @author Rodney Rehm
+ */
+abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource {
+
+ /**
+ * fetch cached content and its modification time from data source
+ *
+ * @param string $id unique cache content identifier
+ * @param string $name template name
+ * @param string $cache_id cache id
+ * @param string $compile_id compile id
+ * @param string $content cached content
+ * @param integer $mtime cache modification timestamp (epoch)
+ * @return void
+ */
+ protected abstract function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime);
+
+ /**
+ * Fetch cached content's modification timestamp from data source
+ *
+ * {@internal implementing this method is optional.
+ * Only implement it if modification times can be accessed faster than loading the complete cached content.}}
+ *
+ * @param string $id unique cache content identifier
+ * @param string $name template name
+ * @param string $cache_id cache id
+ * @param string $compile_id compile id
+ * @return integer|boolean timestamp (epoch) the template was modified, or false if not found
+ */
+ protected function fetchTimestamp($id, $name, $cache_id, $compile_id)
+ {
+ return null;
+ }
+
+ /**
+ * Save content to cache
+ *
+ * @param string $id unique cache content identifier
+ * @param string $name template name
+ * @param string $cache_id cache id
+ * @param string $compile_id compile id
+ * @param integer|null $exp_time seconds till expiration or null
+ * @param string $content content to cache
+ * @return boolean success
+ */
+ protected abstract function save($id, $name, $cache_id, $compile_id, $exp_time, $content);
+
+ /**
+ * Delete content from cache
+ *
+ * @param string $name template name
+ * @param string $cache_id cache id
+ * @param string $compile_id compile id
+ * @param integer|null $exp_time seconds till expiration time in seconds or null
+ * @return integer number of deleted caches
+ */
+ protected abstract function delete($name, $cache_id, $compile_id, $exp_time);
+
+ /**
+ * populate Cached Object with meta data from Resource
+ *
+ * @param Smarty_Template_Cached $cached cached object
+ * @param Smarty_Internal_Template $_template template object
+ * @return void
+ */
+ public function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template)
+ {
+ $_cache_id = isset($cached->cache_id) ? preg_replace('![^\w\|]+!', '_', $cached->cache_id) : null;
+ $_compile_id = isset($cached->compile_id) ? preg_replace('![^\w\|]+!', '_', $cached->compile_id) : null;
+
+ $cached->filepath = sha1($cached->source->filepath . $_cache_id . $_compile_id);
+ $this->populateTimestamp($cached);
+ }
+
+ /**
+ * populate Cached Object with timestamp and exists from Resource
+ *
+ * @param Smarty_Template_Cached $source cached object
+ * @return void
+ */
+ public function populateTimestamp(Smarty_Template_Cached $cached)
+ {
+ $mtime = $this->fetchTimestamp($cached->filepath, $cached->source->name, $cached->cache_id, $cached->compile_id);
+ if ($mtime !== null) {
+ $cached->timestamp = $mtime;
+ $cached->exists = !!$cached->timestamp;
+ return;
+ }
+ $timestamp = null;
+ $this->fetch($cached->filepath, $cached->source->name, $cached->cache_id, $cached->compile_id, $cached->content, $timestamp);
+ $cached->timestamp = isset($timestamp) ? $timestamp : false;
+ $cached->exists = !!$cached->timestamp;
+ }
+
+ /**
+ * Read the cached template and process the header
+ *
+ * @param Smarty_Internal_Template $_template template object
+ * @param Smarty_Template_Cached $cached cached object
+ * @return booelan true or false if the cached content does not exist
+ */
+ public function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached=null)
+ {
+ if (!$cached) {
+ $cached = $_template->cached;
+ }
+ $content = $cached->content ? $cached->content : null;
+ $timestamp = $cached->timestamp ? $cached->timestamp : null;
+ if ($content === null || !$timestamp) {
+ $this->fetch(
+ $_template->cached->filepath,
+ $_template->source->name,
+ $_template->cache_id,
+ $_template->compile_id,
+ $content,
+ $timestamp
+ );
+ }
+ if (isset($content)) {
+ $_smarty_tpl = $_template;
+ eval("?>" . $content);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Write the rendered template output to cache
+ *
+ * @param Smarty_Internal_Template $_template template object
+ * @param string $content content to cache
+ * @return boolean success
+ */
+ public function writeCachedContent(Smarty_Internal_Template $_template, $content)
+ {
+ return $this->save(
+ $_template->cached->filepath,
+ $_template->source->name,
+ $_template->cache_id,
+ $_template->compile_id,
+ $_template->properties['cache_lifetime'],
+ $content
+ );
+ }
+
+ /**
+ * Empty cache
+ *
+ * @param Smarty $smarty Smarty object
+ * @param integer $exp_time expiration time (number of seconds, not timestamp)
+ * @return integer number of cache files deleted
+ */
+ public function clearAll(Smarty $smarty, $exp_time=null)
+ {
+ $this->cache = array();
+ return $this->delete(null, null, null, $exp_time);
+ }
+
+ /**
+ * Empty cache for a specific template
+ *
+ * @param Smarty $smarty Smarty object
+ * @param string $resource_name template name
+ * @param string $cache_id cache id
+ * @param string $compile_id compile id
+ * @param integer $exp_time expiration time (number of seconds, not timestamp)
+ * @return integer number of cache files deleted
+ */
+ public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time)
+ {
+ $this->cache = array();
+ return $this->delete($resource_name, $cache_id, $compile_id, $exp_time);
+ }
+
+ /**
+ * Check is cache is locked for this template
+ *
+ * @param Smarty $smarty Smarty object
+ * @param Smarty_Template_Cached $cached cached object
+ * @return booelan true or false if cache is locked
+ */
+ public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached)
+ {
+ $id = $cached->filepath;
+ $name = $cached->source->name . '.lock';
+
+ $mtime = $this->fetchTimestamp($id, $name, null, null);
+ if ($mtime === null) {
+ $this->fetch($id, $name, null, null, $content, $mtime);
+ }
+
+ return $mtime && time() - $mtime < $smarty->locking_timeout;
+ }
+
+ /**
+ * Lock cache for this template
+ *
+ * @param Smarty $smarty Smarty object
+ * @param Smarty_Template_Cached $cached cached object
+ */
+ public function acquireLock(Smarty $smarty, Smarty_Template_Cached $cached)
+ {
+ $cached->is_locked = true;
+
+ $id = $cached->filepath;
+ $name = $cached->source->name . '.lock';
+ $this->save($id, $name, null, null, $smarty->locking_timeout, '');
+ }
+
+ /**
+ * Unlock cache for this template
+ *
+ * @param Smarty $smarty Smarty object
+ * @param Smarty_Template_Cached $cached cached object
+ */
+ public function releaseLock(Smarty $smarty, Smarty_Template_Cached $cached)
+ {
+ $cached->is_locked = false;
+
+ $id = $cached->filepath;
+ $name = $cached->source->name . '.lock';
+ $this->delete($name, null, null, null);
+ }
+}
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/sysplugins/smarty_cacheresource_keyvaluestore.php b/public_html/lib/Smarty/sysplugins/smarty_cacheresource_keyvaluestore.php
new file mode 100644
index 0000000..dff9b65
--- /dev/null
+++ b/public_html/lib/Smarty/sysplugins/smarty_cacheresource_keyvaluestore.php
@@ -0,0 +1,463 @@
+<?php
+/**
+ * Smarty Internal Plugin
+ *
+ * @package Smarty
+ * @subpackage Cacher
+ */
+
+/**
+ * Smarty Cache Handler Base for Key/Value Storage Implementations
+ *
+ * This class implements the functionality required to use simple key/value stores
+ * for hierarchical cache groups. key/value stores like memcache or APC do not support
+ * wildcards in keys, therefore a cache group cannot be cleared like "a|*" - which
+ * is no problem to filesystem and RDBMS implementations.
+ *
+ * This implementation is based on the concept of invalidation. While one specific cache
+ * can be identified and cleared, any range of caches cannot be identified. For this reason
+ * each level of the cache group hierarchy can have its own value in the store. These values
+ * are nothing but microtimes, telling us when a particular cache group was cleared for the
+ * last time. These keys are evaluated for every cache read to determine if the cache has
+ * been invalidated since it was created and should hence be treated as inexistent.
+ *
+ * Although deep hierarchies are possible, they are not recommended. Try to keep your
+ * cache groups as shallow as possible. Anything up 3-5 parents should be ok. So
+ * »a|b|c« is a good depth where »a|b|c|d|e|f|g|h|i|j|k« isn't. Try to join correlating
+ * cache groups: if your cache groups look somewhat like »a|b|$page|$items|$whatever«
+ * consider using »a|b|c|$page-$items-$whatever« instead.
+ *
+ * @package Smarty
+ * @subpackage Cacher
+ * @author Rodney Rehm
+ */
+abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource {
+
+ /**
+ * cache for contents
+ * @var array
+ */
+ protected $contents = array();
+ /**
+ * cache for timestamps
+ * @var array
+ */
+ protected $timestamps = array();
+
+ /**
+ * populate Cached Object with meta data from Resource
+ *
+ * @param Smarty_Template_Cached $cached cached object
+ * @param Smarty_Internal_Template $_template template object
+ * @return void
+ */
+ public function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template)
+ {
+ $cached->filepath = $_template->source->uid
+ . '#' . $this->sanitize($cached->source->name)
+ . '#' . $this->sanitize($cached->cache_id)
+ . '#' . $this->sanitize($cached->compile_id);
+
+ $this->populateTimestamp($cached);
+ }
+
+ /**
+ * populate Cached Object with timestamp and exists from Resource
+ *
+ * @param Smarty_Template_Cached $cached cached object
+ * @return void
+ */
+ public function populateTimestamp(Smarty_Template_Cached $cached)
+ {
+ if (!$this->fetch($cached->filepath, $cached->source->name, $cached->cache_id, $cached->compile_id, $content, $timestamp, $cached->source->uid)) {
+ return;
+ }
+ $cached->content = $content;
+ $cached->timestamp = (int) $timestamp;
+ $cached->exists = $cached->timestamp;
+ }
+
+ /**
+ * Read the cached template and process the header
+ *
+ * @param Smarty_Internal_Template $_template template object
+ * @param Smarty_Template_Cached $cached cached object
+ * @return booelan true or false if the cached content does not exist
+ */
+ public function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached=null)
+ {
+ if (!$cached) {
+ $cached = $_template->cached;
+ }
+ $content = $cached->content ? $cached->content : null;
+ $timestamp = $cached->timestamp ? $cached->timestamp : null;
+ if ($content === null || !$timestamp) {
+ if (!$this->fetch($_template->cached->filepath, $_template->source->name, $_template->cache_id, $_template->compile_id, $content, $timestamp, $_template->source->uid)) {
+ return false;
+ }
+ }
+ if (isset($content)) {
+ $_smarty_tpl = $_template;
+ eval("?>" . $content);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Write the rendered template output to cache
+ *
+ * @param Smarty_Internal_Template $_template template object
+ * @param string $content content to cache
+ * @return boolean success
+ */
+ public function writeCachedContent(Smarty_Internal_Template $_template, $content)
+ {
+ $this->addMetaTimestamp($content);
+ return $this->write(array($_template->cached->filepath => $content), $_template->properties['cache_lifetime']);
+ }
+
+ /**
+ * Empty cache
+ *
+ * {@internal the $exp_time argument is ignored altogether }}
+ *
+ * @param Smarty $smarty Smarty object
+ * @param integer $exp_time expiration time [being ignored]
+ * @return integer number of cache files deleted [always -1]
+ * @uses purge() to clear the whole store
+ * @uses invalidate() to mark everything outdated if purge() is inapplicable
+ */
+ public function clearAll(Smarty $smarty, $exp_time=null)
+ {
+ if (!$this->purge()) {
+ $this->invalidate(null);
+ }
+ return -1;
+ }
+
+ /**
+ * Empty cache for a specific template
+ *
+ * {@internal the $exp_time argument is ignored altogether}}
+ *
+ * @param Smarty $smarty Smarty object
+ * @param string $resource_name template name
+ * @param string $cache_id cache id
+ * @param string $compile_id compile id
+ * @param integer $exp_time expiration time [being ignored]
+ * @return integer number of cache files deleted [always -1]
+ * @uses buildCachedFilepath() to generate the CacheID
+ * @uses invalidate() to mark CacheIDs parent chain as outdated
+ * @uses delete() to remove CacheID from cache
+ */
+ public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time)
+ {
+ $uid = $this->getTemplateUid($smarty, $resource_name, $cache_id, $compile_id);
+ $cid = $uid . '#' . $this->sanitize($resource_name) . '#' . $this->sanitize($cache_id) . '#' . $this->sanitize($compile_id);
+ $this->delete(array($cid));
+ $this->invalidate($cid, $resource_name, $cache_id, $compile_id, $uid);
+ return -1;
+ }
+ /**
+ * Get template's unique ID
+ *
+ * @param Smarty $smarty Smarty object
+ * @param string $resource_name template name
+ * @param string $cache_id cache id
+ * @param string $compile_id compile id
+ * @return string filepath of cache file
+ */
+ protected function getTemplateUid(Smarty $smarty, $resource_name, $cache_id, $compile_id)
+ {
+ $uid = '';
+ if (isset($resource_name)) {
+ $tpl = new $smarty->template_class($resource_name, $smarty);
+ if ($tpl->source->exists) {
+ $uid = $tpl->source->uid;
+ }
+
+ // remove from template cache
+ if ($smarty->allow_ambiguous_resources) {
+ $_templateId = $tpl->source->unique_resource . $tpl->cache_id . $tpl->compile_id;
+ } else {
+ $_templateId = $smarty->joined_template_dir . '#' . $resource_name . $tpl->cache_id . $tpl->compile_id;
+ }
+ if (isset($_templateId[150])) {
+ $_templateId = sha1($_templateId);
+ }
+ unset($smarty->template_objects[$_templateId]);
+ }
+ return $uid;
+ }
+
+ /**
+ * Sanitize CacheID components
+ *
+ * @param string $string CacheID component to sanitize
+ * @return string sanitized CacheID component
+ */
+ protected function sanitize($string)
+ {
+ // some poeple smoke bad weed
+ $string = trim($string, '|');
+ if (!$string) {
+ return null;
+ }
+ return preg_replace('#[^\w\|]+#S', '_', $string);
+ }
+
+ /**
+ * Fetch and prepare a cache object.
+ *
+ * @param string $cid CacheID to fetch
+ * @param string $resource_name template name
+ * @param string $cache_id cache id
+ * @param string $compile_id compile id
+ * @param string $content cached content
+ * @param integer &$timestamp cached timestamp (epoch)
+ * @param string $resource_uid resource's uid
+ * @return boolean success
+ */
+ protected function fetch($cid, $resource_name = null, $cache_id = null, $compile_id = null, &$content = null, &$timestamp = null, $resource_uid = null)
+ {
+ $t = $this->read(array($cid));
+ $content = !empty($t[$cid]) ? $t[$cid] : null;
+ $timestamp = null;
+
+ if ($content && ($timestamp = $this->getMetaTimestamp($content))) {
+ $invalidated = $this->getLatestInvalidationTimestamp($cid, $resource_name, $cache_id, $compile_id, $resource_uid);
+ if ($invalidated > $timestamp) {
+ $timestamp = null;
+ $content = null;
+ }
+ }
+
+ return !!$content;
+ }
+
+ /**
+ * Add current microtime to the beginning of $cache_content
+ *
+ * {@internal the header uses 8 Bytes, the first 4 Bytes are the seconds, the second 4 Bytes are the microseconds}}
+ *
+ * @param string &$content the content to be cached
+ */
+ protected function addMetaTimestamp(&$content)
+ {
+ $mt = explode(" ", microtime());
+ $ts = pack("NN", $mt[1], (int) ($mt[0] * 100000000));
+ $content = $ts . $content;
+ }
+
+ /**
+ * Extract the timestamp the $content was cached
+ *
+ * @param string &$content the cached content
+ * @return float the microtime the content was cached
+ */
+ protected function getMetaTimestamp(&$content)
+ {
+ $s = unpack("N", substr($content, 0, 4));
+ $m = unpack("N", substr($content, 4, 4));
+ $content = substr($content, 8);
+ return $s[1] + ($m[1] / 100000000);
+ }
+
+ /**
+ * Invalidate CacheID
+ *
+ * @param string $cid CacheID
+ * @param string $resource_name template name
+ * @param string $cache_id cache id
+ * @param string $compile_id compile id
+ * @param string $resource_uid source's uid
+ * @return void
+ */
+ protected function invalidate($cid = null, $resource_name = null, $cache_id = null, $compile_id = null, $resource_uid = null)
+ {
+ $now = microtime(true);
+ $key = null;
+ // invalidate everything
+ if (!$resource_name && !$cache_id && !$compile_id) {
+ $key = 'IVK#ALL';
+ }
+ // invalidate all caches by template
+ else if ($resource_name && !$cache_id && !$compile_id) {
+ $key = 'IVK#TEMPLATE#' . $resource_uid . '#' . $this->sanitize($resource_name);
+ }
+ // invalidate all caches by cache group
+ else if (!$resource_name && $cache_id && !$compile_id) {
+ $key = 'IVK#CACHE#' . $this->sanitize($cache_id);
+ }
+ // invalidate all caches by compile id
+ else if (!$resource_name && !$cache_id && $compile_id) {
+ $key = 'IVK#COMPILE#' . $this->sanitize($compile_id);
+ }
+ // invalidate by combination
+ else {
+ $key = 'IVK#CID#' . $cid;
+ }
+ $this->write(array($key => $now));
+ }
+
+ /**
+ * Determine the latest timestamp known to the invalidation chain
+ *
+ * @param string $cid CacheID to determine latest invalidation timestamp of
+ * @param string $resource_name template name
+ * @param string $cache_id cache id
+ * @param string $compile_id compile id
+ * @param string $resource_uid source's filepath
+ * @return float the microtime the CacheID was invalidated
+ */
+ protected function getLatestInvalidationTimestamp($cid, $resource_name = null, $cache_id = null, $compile_id = null, $resource_uid = null)
+ {
+ // abort if there is no CacheID
+ if (false && !$cid) {
+ return 0;
+ }
+ // abort if there are no InvalidationKeys to check
+ if (!($_cid = $this->listInvalidationKeys($cid, $resource_name, $cache_id, $compile_id, $resource_uid))) {
+ return 0;
+ }
+
+ // there are no InValidationKeys
+ if (!($values = $this->read($_cid))) {
+ return 0;
+ }
+ // make sure we're dealing with floats
+ $values = array_map('floatval', $values);
+ return max($values);
+ }
+
+ /**
+ * Translate a CacheID into the list of applicable InvalidationKeys.
+ *
+ * Splits "some|chain|into|an|array" into array( '#clearAll#', 'some', 'some|chain', 'some|chain|into', ... )
+ *
+ * @param string $cid CacheID to translate
+ * @param string $resource_name template name
+ * @param string $cache_id cache id
+ * @param string $compile_id compile id
+ * @param string $resource_uid source's filepath
+ * @return array list of InvalidationKeys
+ * @uses $invalidationKeyPrefix to prepend to each InvalidationKey
+ */
+ protected function listInvalidationKeys($cid, $resource_name = null, $cache_id = null, $compile_id = null, $resource_uid = null)
+ {
+ $t = array('IVK#ALL');
+ $_name = $_compile = '#';
+ if ($resource_name) {
+ $_name .= $resource_uid . '#' . $this->sanitize($resource_name);
+ $t[] = 'IVK#TEMPLATE' . $_name;
+ }
+ if ($compile_id) {
+ $_compile .= $this->sanitize($compile_id);
+ $t[] = 'IVK#COMPILE' . $_compile;
+ }
+ $_name .= '#';
+ // some poeple smoke bad weed
+ $cid = trim($cache_id, '|');
+ if (!$cid) {
+ return $t;
+ }
+ $i = 0;
+ while (true) {
+ // determine next delimiter position
+ $i = strpos($cid, '|', $i);
+ // add complete CacheID if there are no more delimiters
+ if ($i === false) {
+ $t[] = 'IVK#CACHE#' . $cid;
+ $t[] = 'IVK#CID' . $_name . $cid . $_compile;
+ $t[] = 'IVK#CID' . $_name . $_compile;
+ break;
+ }
+ $part = substr($cid, 0, $i);
+ // add slice to list
+ $t[] = 'IVK#CACHE#' . $part;
+ $t[] = 'IVK#CID' . $_name . $part . $_compile;
+ // skip past delimiter position
+ $i++;
+ }
+ return $t;
+ }
+
+ /**
+ * Check is cache is locked for this template
+ *
+ * @param Smarty $smarty Smarty object
+ * @param Smarty_Template_Cached $cached cached object
+ * @return booelan true or false if cache is locked
+ */
+ public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached)
+ {
+ $key = 'LOCK#' . $cached->filepath;
+ $data = $this->read(array($key));
+ return $data && time() - $data[$key] < $smarty->locking_timeout;
+ }
+
+ /**
+ * Lock cache for this template
+ *
+ * @param Smarty $smarty Smarty object
+ * @param Smarty_Template_Cached $cached cached object
+ */
+ public function acquireLock(Smarty $smarty, Smarty_Template_Cached $cached)
+ {
+ $cached->is_locked = true;
+ $key = 'LOCK#' . $cached->filepath;
+ $this->write(array($key => time()), $smarty->locking_timeout);
+ }
+
+ /**
+ * Unlock cache for this template
+ *
+ * @param Smarty $smarty Smarty object
+ * @param Smarty_Template_Cached $cached cached object
+ */
+ public function releaseLock(Smarty $smarty, Smarty_Template_Cached $cached)
+ {
+ $cached->is_locked = false;
+ $key = 'LOCK#' . $cached->filepath;
+ $this->delete(array($key));
+ }
+
+ /**
+ * Read values for a set of keys from cache
+ *
+ * @param array $keys list of keys to fetch
+ * @return array list of values with the given keys used as indexes
+ */
+ protected abstract function read(array $keys);
+
+ /**
+ * Save values for a set of keys to cache
+ *
+ * @param array $keys list of values to save
+ * @param int $expire expiration time
+ * @return boolean true on success, false on failure
+ */
+ protected abstract function write(array $keys, $expire=null);
+
+ /**
+ * Remove values from cache
+ *
+ * @param array $keys list of keys to delete
+ * @return boolean true on success, false on failure
+ */
+ protected abstract function delete(array $keys);
+
+ /**
+ * Remove *all* values from cache
+ *
+ * @return boolean true on success, false on failure
+ */
+ protected function purge()
+ {
+ return false;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/sysplugins/smarty_config_source.php b/public_html/lib/Smarty/sysplugins/smarty_config_source.php
new file mode 100644
index 0000000..043ff13
--- /dev/null
+++ b/public_html/lib/Smarty/sysplugins/smarty_config_source.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Smarty Internal Plugin
+ *
+ * @package Smarty
+ * @subpackage TemplateResources
+ */
+
+/**
+ * Smarty Resource Data Object
+ *
+ * Meta Data Container for Config Files
+ *
+ * @package Smarty
+ * @subpackage TemplateResources
+ * @author Rodney Rehm
+ *
+ * @property string $content
+ * @property int $timestamp
+ * @property bool $exists
+ */
+class Smarty_Config_Source extends Smarty_Template_Source {
+
+ /**
+ * create Config Object container
+ *
+ * @param Smarty_Resource $handler Resource Handler this source object communicates with
+ * @param Smarty $smarty Smarty instance this source object belongs to
+ * @param string $resource full config_resource
+ * @param string $type type of resource
+ * @param string $name resource name
+ * @param string $unique_resource unqiue resource name
+ */
+ public function __construct(Smarty_Resource $handler, Smarty $smarty, $resource, $type, $name, $unique_resource)
+ {
+ $this->handler = $handler; // Note: prone to circular references
+
+ // Note: these may be ->config_compiler_class etc in the future
+ //$this->config_compiler_class = $handler->config_compiler_class;
+ //$this->config_lexer_class = $handler->config_lexer_class;
+ //$this->config_parser_class = $handler->config_parser_class;
+
+ $this->smarty = $smarty;
+ $this->resource = $resource;
+ $this->type = $type;
+ $this->name = $name;
+ $this->unique_resource = $unique_resource;
+ }
+
+ /**
+ * <<magic>> Generic setter.
+ *
+ * @param string $property_name valid: content, timestamp, exists
+ * @param mixed $value newly assigned value (not check for correct type)
+ * @throws SmartyException when the given property name is not valid
+ */
+ public function __set($property_name, $value)
+ {
+ switch ($property_name) {
+ case 'content':
+ case 'timestamp':
+ case 'exists':
+ $this->$property_name = $value;
+ break;
+
+ default:
+ throw new SmartyException("invalid config property '$property_name'.");
+ }
+ }
+
+ /**
+ * <<magic>> Generic getter.
+ *
+ * @param string $property_name valid: content, timestamp, exists
+ * @throws SmartyException when the given property name is not valid
+ */
+ public function __get($property_name)
+ {
+ switch ($property_name) {
+ case 'timestamp':
+ case 'exists':
+ $this->handler->populateTimestamp($this);
+ return $this->$property_name;
+
+ case 'content':
+ return $this->content = $this->handler->getContent($this);
+
+ default:
+ throw new SmartyException("config property '$property_name' does not exist.");
+ }
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/public_html/lib/Smarty/sysplugins/smarty_internal_cacheresource_file.php b/public_html/lib/Smarty/sysplugins/smarty_internal_cacheresource_file.php
new file mode 100644
index 0000000..2519541
--- /dev/null
+++ b/public_html/lib/Smarty/sysplugins/smarty_internal_cacheresource_file.php
@@ -0,0 +1,264 @@
+<?php
+/**
+ * Smarty Internal Plugin CacheResource File
+ *
+ * @package Smarty
+ * @subpackage Cacher
+ * @author Uwe Tews
+ * @author Rodney Rehm
+ */
+
+/**
+ * This class does contain all necessary methods for the HTML cache on file system
+ *
+ * Implements the file system as resource for the HTML cache Version ussing nocache inserts.
+ *
+ * @package Smarty
+ * @subpackage Cacher
+ */
+class Smarty_Internal_CacheResource_File extends Smarty_CacheResource {
+
+ /**
+ * populate Cached Object with meta data from Resource
+ *
+ * @param Smarty_Template_Cached $cached cached object
+ * @param Smarty_Internal_Template $_template template object
+ * @return void
+ */
+ public function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template)
+ {
+ $_source_file_path = str_replace(':', '.', $_template->source->filepath);
+ $_cache_id = isset($_template->cache_id) ? preg_replace('![^\w\|]+!', '_', $_template->cache_id) : null;
+ $_compile_id = isset($_template->compile_id) ? preg_replace('![^\w\|]+!', '_', $_template->compile_id) : null;
+ $_filepath = $_template->source->uid;
+ // if use_sub_dirs, break file into directories
+ if ($_template->smarty->use_sub_dirs) {
+ $_filepath = substr($_filepath, 0, 2) . DS
+ . substr($_filepath, 2, 2) . DS
+ . substr($_filepath, 4, 2) . DS
+ . $_filepath;
+ }
+ $_compile_dir_sep = $_template->smarty->use_sub_dirs ? DS : '^';
+ if (isset($_cache_id)) {
+ $_cache_id = str_replace('|', $_compile_dir_sep, $_cache_id) . $_compile_dir_sep;
+ } else {
+ $_cache_id = '';
+ }
+ if (isset($_compile_id)) {
+ $_compile_id = $_compile_id . $_compile_dir_sep;
+ } else {
+ $_compile_id = '';
+ }
+ $_cache_dir = $_template->smarty->getCacheDir();
+ if ($_template->smarty->cache_locking) {
+ // create locking file name
+ // relative file name?
+ if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_cache_dir)) {
+ $_lock_dir = rtrim(getcwd(), '/\\') . DS . $_cache_dir;
+ } else {
+ $_lock_dir = $_cache_dir;
+ }
+ $cached->lock_id = $_lock_dir.sha1($_cache_id.$_compile_id.$_template->source->uid).'.lock';
+ }
+ $cached->filepath = $_cache_dir . $_cache_id . $_compile_id . $_filepath . '.' . basename($_source_file_path) . '.php';
+ $cached->timestamp = @filemtime($cached->filepath);
+ $cached->exists = !!$cached->timestamp;
+ }
+
+ /**
+ * populate Cached Object with timestamp and exists from Resource
+ *
+ * @param Smarty_Template_Cached $cached cached object
+ * @return void
+ */
+ public function populateTimestamp(Smarty_Template_Cached $cached)
+ {
+ $cached->timestamp = @filemtime($cached->filepath);
+ $cached->exists = !!$cached->timestamp;
+ }
+
+ /**
+ * Read the cached template and process its header
+ *
+ * @param Smarty_Internal_Template $_template template object
+ * @param Smarty_Template_Cached $cached cached object
+ * @return booelan true or false if the cached content does not exist
+ */
+ public function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached=null)
+ {
+ $_smarty_tpl = $_template;
+ return @include $_template->cached->filepath;
+ }
+
+ /**
+ * Write the rendered template output to cache
+ *
+ * @param Smarty_Internal_Template $_template template object
+ * @param string $content content to cache
+ * @return boolean success
+ */
+ public function writeCachedContent(Smarty_Internal_Template $_template, $content)
+ {
+ if (Smarty_Internal_Write_File::writeFile($_template->cached->filepath, $content, $_template->smarty) === true) {
+ $_template->cached->timestamp = filemtime($_template->cached->filepath);
+ $_template->cached->exists = !!$_template->cached->timestamp;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Empty cache
+ *
+ * @param Smarty_Internal_Template $_template template object
+ * @param integer $exp_time expiration time (number of seconds, not timestamp)
+ * @return integer number of cache files deleted
+ */
+ public function clearAll(Smarty $smarty, $exp_time = null)
+ {
+ return $this->clear($smarty, null, null, null, $exp_time);
+ }
+
+ /**
+ * Empty cache for a specific template
+ *
+ * @param Smarty $_template template object
+ * @param string $resource_name template name
+ * @param string $cache_id cache id
+ * @param string $compile_id compile id
+ * @param integer $exp_time expiration time (number of seconds, not timestamp)
+ * @return integer number of cache files deleted
+ */
+ public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time)
+ {
+ $_cache_id = isset($cache_id) ? preg_replace('![^\w\|]+!', '_', $cache_id) : null;
+ $_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null;
+ $_dir_sep = $smarty->use_sub_dirs ? '/' : '^';
+ $_compile_id_offset = $smarty->use_sub_dirs ? 3 : 0;
+ $_dir = $smarty->getCacheDir();
+ $_dir_length = strlen($_dir);
+ if (isset($_cache_id)) {
+ $_cache_id_parts = explode('|', $_cache_id);
+ $_cache_id_parts_count = count($_cache_id_parts);
+ if ($smarty->use_sub_dirs) {
+ foreach ($_cache_id_parts as $id_part) {
+ $_dir .= $id_part . DS;
+ }
+ }
+ }
+ if (isset($resource_name)) {
+ $_save_stat = $smarty->caching;
+ $smarty->caching = true;
+ $tpl = new $smarty->template_class($resource_name, $smarty);
+ $smarty->caching = $_save_stat;
+
+ // remove from template cache
+ $tpl->source; // have the template registered before unset()
+ if ($smarty->allow_ambiguous_resources) {
+ $_templateId = $tpl->source->unique_resource . $tpl->cache_id . $tpl->compile_id;
+ } else {
+ $_templateId = $smarty->joined_template_dir . '#' . $resource_name . $tpl->cache_id . $tpl->compile_id;
+ }
+ if (isset($_templateId[150])) {
+ $_templateId = sha1($_templateId);
+ }
+ unset($smarty->template_objects[$_templateId]);
+
+ if ($tpl->source->exists) {
+ $_resourcename_parts = basename(str_replace('^', '/', $tpl->cached->filepath));
+ } else {
+ return 0;
+ }
+ }
+ $_count = 0;