[
  {
    "path": ".gitignore",
    "content": "lib/config.php\ndata/*\n"
  },
  {
    "path": "README.md",
    "content": "# DEPRECATED\nPlease note that this project is no longer maintained.\n\n# Hammock\n=========\n\nHammock is a standalone webapp for running [Slack](https://slack.com) integrations.\nThis allows you to modify existing integrations, write new custom integrations, or use \ncertain integrations inside your firewall.\n\nIntegrations written for Hammock use the same API as Slack itself, so contributing\nnew Integrations here will allow them to be added to the main Slack integrations list.\n\n\n## Requirements\n\nHammock requires a webserver running a recent version of PHP.  \nFor integrations that require polling, `cron` is also required\n(or `at`/`schtasks` on Windows).\n\n\n## Installation\n\n* Make a clone of this git repository onto your web server\n* Copy `lib/config.php.example` to `lib/config.php`\n* Open `lib/config.php` in a text editor and follow the instructions inside\n* Make sure `data/` is writable by your web server\n* Visit `index.php` in your browser and start configuring\n\n\n## Heroku\n\nYou can run Hammock on Heroku using the following commands (you'll need  to have installed\nthe Heroku toolbelt already):\n\n    cd hammock\n    heroku create\n    heroku config:set BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-php.git#redis\n    heroku config:set HAMMOCK_ROOT=http://{URL-TO-APP}/\n    heroku config:set HAMMOCK_CLIENT_ID={YOUR-CLIENT-ID}\n    heroku config:set HAMMOCK_CLIENT_SECRET={YOUR-CLIENT-SECRET}\n    heroku addons:add redistogo\n    git push heroku master\n\nAll config options are loaded from the environment variables and data is stored in Redis.\n\n\n## Adding integrations\n\nTo create your own integrations [read the service docs](docs/services.md).\n\nYou can also check the [full service reference documentation](docs/services_ref.md).\n\n\n## Roadmap\n\nThis version of Hammock is pretty barebones, designed to support simple webhook-to-Slack\nstyle integrations first. To better support this, we'll be adding a replay-debugger for \ncapturing incoming webhooks and being able to replay them in a read-only mode while \ndeveloping.\n\nFuture plugins will be able to provide cross-plugin authentication, so that e.g. a GitHub\nintegration can auth you against GitHub once and then allow you to add multiple different\nintegrations for code, issues, gists, etc. and share the credentials. This will be supported\nby a different subclass of plugins.\n\nThe visual appearance of Hammock somewhat matches the Slack services pages, but this will\nbe changed to more closely match, have building blocks for commmon UI elements, and switch\nthe the planned tabbed interface for integration config.\n\nFor integrations that require some kind of polling, Hammock will support polling callbacks\nand handle some API call diffing behavior automatically. Using this mechanism, an integration\ncan register a method to be called when the results of an external API call change.\n\nWe also plan to support integrations that are triggered from within Slack, via slash commands\nand other user-initiated actions.\n"
  },
  {
    "path": "TODO",
    "content": "* Style config pages to match current slack.com (somewhat done)\n* Log all incoming webhooks and what we sent as a result (and allow replays)\n* Plugins provide icons & default bot usernames\n* Add 'Hammock' as a Slack service for bidi hooks\n* Tab the service config pages probably (Summary, Settings, plugin-defined)\n* Do the cron stuff\n"
  },
  {
    "path": "add.php",
    "content": "<?php\n\t$dir = dirname(__FILE__);\n\tinclude(\"$dir/lib/init.php\");\n\t\n\tverify_auth();\n\n\tload_plugins();\n\n\tif ($_POST['done']){\n\n\t\t$instance = createPluginInstance($_POST['plugin']);\n\t\t$instance->iid = $_POST['uid'];\n\n\t\t$instance->onParentInit();\n\t\t$instance->onInit();\n\n\t\t$instance->icfg['created'] = time();\n\t\t$instance->icfg['creator_id'] = $GLOBALS['cfg']['user']['user_id'];\n\n\t\t$instance->saveConfig();\n\n\t\theader(\"location: view.php?id={$instance->iid}\");\n\t\texit;\n\t}\n\n\n\t$id = $_GET['id'];\n\tif (!isset($plugins[$id])) die(\"plugin not found\");\n\n\t$instance = createPluginInstance($id);\n\t$instance->createInstanceId();\n\n\t$instance->checkRequirements();\n\n\t$smarty->assign('instance', $instance);\n\n\t$smarty->display('page_add.txt');\n"
  },
  {
    "path": "auth.php",
    "content": "<?php\n\t$dir = dirname(__FILE__);\n\tinclude(\"$dir/lib/init.php\");\n\n\tload_plugins();\n\n\t$instance = getAuthPlugin($_GET['id']);\n\tif (!is_object($instance)) die(\"instance not found\");\n\n\n\t$html = $instance->configPage();\n\n\t$smarty->assign('html', $html);\n\t$smarty->assign('instance', $instance);\n\n\t$smarty->display('page_auth.txt');\n"
  },
  {
    "path": "docs/services.md",
    "content": "# Creating your own integration service\n\nThis document describes how to create new Slack integrations. If you're just \nlooking to install an existing integration, copy the directory into the `plugins/`\ndirectory.\n\nIf reading docs isn't your thing, take a look at the `github_commits` for a\nsimple webhook-to-message example.\n\nThe [full reference documentation](services_ref.md) lists everything your plugin \ncan take advantage of.\n\n\n## Bare bones\n\nCreate a new sub-directory inside `plugins/`. This will be the name of your service\nplugin's class, so don't use any dashes (or anything fancy). Inside the directory,\ncreate a file called `plugin.php` and enter some code:\n\n\t<?php\n\n\tclass my_service extends SlackServicePlugin {\n\t}\n\nThis is the simplest service you can build. Load up the index page of your Hammock\ninstall and you should see your new service listed. For now, it doesn't have a name\nor description, so we'll fix that first:\n\n\tclass my_service extends SlackServicePlugin {\n\n\t\tpublic $name = \"My Awesome Service\";\n\t\tpublic $desc = \"This is what it does, yo\";\n\nAfter that, it should show up correctly in the services list. If you create an \ninstance of it, you'll find it has \"No information\" to display. To display any \ninformation, instructions or settings you'll need to start providing some methods:\n\n\tfunction onView(){\n\t\treturn \"<p>this is my service</p>\";\n\t}\n\nBuilding HTML in code is tedious and fragile, so Hammock includes Smarty for \ntemplating. Create a sub-directory in your plugin called `templates` and then create\n`view.txt` inside that:\n\n\t<p>This is my service!</p>\n\n\t<p><a href=\"{$this->getEditUrl()}\" class=\"btn\">Edit settings</a></p>\n\nWe can then use this template from the PHP class:\n\n\tfunction onView(){\n\t\treturn $this->smarty->fetch('view.txt');\n\t}\n\nEach service object has a `$this->smarty` property which contains a pre-configured\nSmarty instance.\n\nService plugins currently provide a 'view' and an 'edit' page. This will likely turn \ninto a tabbed and combined view/edit page with custom tabs in the future.\n\n\n## Webhooks\n\nThe simplest form of service plugin is to handle incoming webhooks. If you're going \nto provide a webhook URL, you should set this config property on your class:\n\n\tpublic $cfg = array(\n\t\t'has_token'        => true,\n\t);\n\nThis ensures that a randomized token is initialized for the service.\n\nIn your view template, present `{$this->getHookUrl()}` to users as the URL to use for\nthe inbound hook. When the hook is run, the class's `onHook` method will be called,\npassing in information about the request:\n\n\tfunction onHook($req){\n\n\t\t# GET vars      : $req['get']\n\t\t# POST vars     : $req['post']\n\t\t# Raw POST body : $req['post_body']\n\t\t# HTTP headers  : $req['headers']\n\t}\n\nYour code should _only_ use the data passed in `$req` and not use superglobals like\n`$_GET` - hook code can be called by the replay-debugger in which case superglobals\nwill not be present.\n\nAnything returned from the `onHook()` handler will be logged for later debugging, so\nreturning a simple text status about different conditions encountered can be very \nhelpful.\n\nOnce you've processed the incoming data, you'll probably want to send a message into \nSlack. This can be done via the `postToChannel()` method:\n\n\tfunction onHook($req){\n\n\t\t$this->postToChannel($req['get']['text']);\n\n\t\t$this->postToChannel(\"hello\", array(\n\t\t\t'channel'\t=> 'C12398612345',\n\t\t\t'username'\t=> 'Testbot',\n\t\t));\n\t}\n\nThe first argument is the text to post, while the optional second argument contains\na hash of options.\n\nFor a full list of all properties, methods and events, check the \n[full reference documentation](services_ref.md).\n\n"
  },
  {
    "path": "docs/services_ref.md",
    "content": "# Service Plugin Reference\n\nThis documentation lists all of the currently available properties and methods\nfor custom `SlackServicePlugin` classes. This will be expanded as more are added.\n\n\n## Properties\n\nThere are 6 core properties for services:\n\n\t$this->id;   # class name\n\t$this->iid;  # unique instance ID \n\n\t$this->cfg;  # static class config\n\t$this->icfg; # instance config\n\n\t$this->name; # service name\n\t$this->desc; # service description\n\nYou'll never set the `id` and `iid` props, but they are sometimes useful.\n\nThe `cfg` hash is used to toggle on certain functionality. The only currently\nsupported flag is `has_token` which makes sure `icfg->token` is populated and\nprovides a UI for resetting the token.\n\nThe `icfg` hash is where you store instance properties. You'll need to call\n`$this->saveConfig();` to save any changes you make here (except in `onInit`).\n\nThe `name` and `desc` props should not be changed at run time.\n\nEach plugin is also provided with a Smarty instance at `$this->smarty`. It is \nconfigured to use templates from the `templates` sub-directory of your plugin.\nIt already hs the plugin instance assigned as `$this`.\n\nSince UI methods expect HTML to be returned rather than output directly, be\nsure to use `->fetch()` rather than `->display()`.\n\n\n## Methods to override\n\n### onInit()\n\nThis is called when a new instance of a plugin is created. This is the place to\npopulate `$this->icfg` with any default values. You _don't_ need to call\n`$this->saveConfig();` to save these changes (that happens automatically).\n\nAny `$cfg` based options will have been applied before this method is called,\nso (for example) `$icfg->token` will have already been set.\n\n### onView()\n\nCalled when a user clicks on an instance of the service. Should return informational\nHTML, optionally with a link to the 'edit' view.\n\n### onEdit()\n\nCalled for editing the service config.\n\n### onHook($req)\n\nCalled when the service's webhook URL is requested, or by the replay-debugger.\n\n### getLabel()\n\nShould return a user-friendly description of the service instance, based on config \ninformation. For example, a service that posts Github commits to a channel might \nreturn a line of text describing the source repo and the target channel (e.g. \"Post \ncommits from Hammock to #hammock\").\n\n\n## Methods to call\n\n### getViewUrl() / getEditUrl() / getHookUrl()\n\nReturns the various URLs for the service instance. Never try and build these yourself.\n\n### dump()\n\nDump the contents of the service instance as HTML. Use this rather than calling `print_r`\non the object since this method first disconnects the Smarty object to avoid recursive \nloops.\n\n### saveConfig()\n\nMake sure that changes to `$this->icfg` are persisted. Your should call this after \nmodifying the instance config in onView, onEdit or onHook.\n\n### postToChannel($text, $extra)\n\nSend a message to a Slack channel. This method currently expects your messages to be \n[properly escaped](https://api.slack.com/docs/formatting), but this will be optional\nin the future.\n\nThe first argument is the message to post. The second optional array argument can \ncontain a `channel` to post to and a `username` to post as.\n\nTo add [attachments](https://api.slack.com/docs/attachments) to a message, simply \npass an array of attachment hashes as `$extra['attachments']`:\n\n\t$extra['attachments'] = array(\n\t\tarray(\n\t\t\t\"text\" => \"Attachment 1\",\n\t\t\t\"color\" => \"#ff0000\",\n\t\t),\n\t\tarray(\n\t\t\t\"text\" => \"Attachment 2\",\n\t\t\t\"color\" => \"#0000ff\",\n\t\t),\n\t);\n\nThe optional `unfurl_links`, `icon_url` & `icon_emoji` properties match that of the\n`chat.postMessage` [API method](https://api.slack.com/methods/chat.postMessage).\n\n### escapeText($str)\n\nTakes any text string and returns one escaped to display as-is in Slack\n\n### escapeLink($url, $label)\n\nTakes a URL and (optionally) a label and makes a valid Slack link.\n\n### getChannelsList()\n\nReturns a hash of `{ID -> Name}` for public channels in your Slack instance. This can\nbe used to present a list of channels to choose from when configuring an instance.\n\n"
  },
  {
    "path": "edit.php",
    "content": "<?php\n\t$dir = dirname(__FILE__);\n\tinclude(\"$dir/lib/init.php\");\n\t\n\tverify_auth();\n\n\tload_plugins();\n\n\t$instance = getPluginInstance($_GET['id']);\n\tif (!is_object($instance)) die(\"instance not found\");\n\n\t$instance->checkRequirements();\n\n\t$smarty->assign('instance', $instance);\n\t$smarty->assign('html', $instance->onEdit());\n\n\t$smarty->display('page_edit.txt');\n\n"
  },
  {
    "path": "hook.php",
    "content": "<?php\n\t$dir = dirname(__FILE__);\n\tinclude(\"$dir/lib/init.php\");\n\n\n\t#\n\t# build request object\n\t#\n\n\t$headers = array();\n\tforeach ($_SERVER as $k => $v){\n\t\tif (substr($k, 0, 5) == 'HTTP_'){\n\t\t\t$k = substr($k, 5);\n\t\t\t$k = StrToLower($k);\n\t\t\t$k = preg_replace_callback('!(^|_)([a-z])!', 'local_replace_header', $k);\n\t\t\t$k = str_replace('_', '-', $k);\n\t\t\t$headers[$k] = $v;\n\t\t}\n\t}\n\n\tfunction local_replace_header($m){\n\t\treturn $m[1].StrToUpper($m[2]);\n\t}\n\n\t$req = array(\n\t\t'headers'\t=> $headers,\n\t\t'get'\t\t=> $_GET,\n\t\t'post'\t\t=> $_POST,\n\t);\n\n\t\n\t#\n\t# if the body has been posted as something other than 'application/x-www-form-urlencoded'\n\t# or 'multipart/form-data', capture the entire post body as a string\n\t#\n\n\tif (!count($_POST)){\n\n\t\t$body = file_get_contents(\"php://input\");\n\t\tif (strlen($body)) $req['post_body'] = $body;\n\t}\n\n\n\t#\n\t# log to a file (this is temporary)\n\t#\n\n\t$log = HAMMOCK_ROOT.'/data/hook_'.uniqid().'.log';\n\t$fh = fopen($log, 'w');\n\tfwrite($fh, '<'.'? $req = '.var_export($req, true).';');\n\tfclose($fh);\n\n\n\t#\n\t# see if we can find a plugin to handle it\n\t#\n\n\tload_plugins();\n\n\t$instance = getPluginInstance($_GET['id']);\n\tif (is_object($instance)){\n\n\t\t$ret = $instance->onLiveHook($req);\n\t\t$out = $instance->getLog();\n\n\t\t$uid = uniqid('', true);\n\n\t\t$data->set('hooks', $uid, array(\n\t\t\t'ts' => time(),\n\t\t\t'req' => $req,\n\t\t\t'ret' => $ret,\n\t\t\t'out' => $out,\n\t\t));\n\n\t\t$list = $data->get('hook_lists', $instance->iid);\n\t\t$list[] = $uid;\n\t\t$data->set('hook_lists', $instance->iid, $list);\n\t}\n\n\techo \"ok\\n\";\n"
  },
  {
    "path": "index.php",
    "content": "<?php\r\n\t$dir = dirname(__FILE__);\r\n\tinclude(\"$dir/lib/init.php\");\r\n\r\n\tverify_auth();\r\n\r\n\tload_plugins();\r\n\r\n\r\n\t#\r\n\t# if we have no service instances, redirect to new.php\r\n\t#\r\n\r\n\t$instance_data = $data->get_all('instances');\r\n\r\n\tif (!count($instance_data)){\r\n\t\theader(\"location: new.php\");\r\n\t\texit;\r\n\t}\r\n\r\n\r\n\t#\r\n\t# get instances and group by service\r\n\t#\r\n\r\n\t$instance_groups = array();\r\n\r\n\tforeach ($instance_data as $k => $instance){\r\n\t\t$inst = getPluginInstance($k);\r\n\t\t$inst->icon_48 = $inst->iconUrl(48);\r\n\r\n\t\tif ($inst->icfg['creator_id']){\r\n\t\t\t$u = $GLOBALS['data']->get('users', $inst->icfg['creator_id']);\r\n\t\t\t$inst->icfg['creator_name'] = $u['user'];\r\n\t\t\t$inst->icfg['creator_url'] = \"{$u['url']}team/{$u['user']}\";\r\n\t\t}\r\n\r\n\t\t$instance_groups[$inst->id]['plugin'] = $inst;\r\n\t\t$instance_groups[$inst->id]['instances'][] = $inst;\r\n\t}\r\n\r\n\tusort($instance_groups, 'local_sort');\r\n\r\n\tfunction local_sort($a, $b){\r\n\t\treturn strcasecmp($a['plugin']->name, $b['plugin']->name);\r\n\t}\r\n\r\n\t$smarty->assign('instances', $instance_groups);\r\n\r\n\r\n\t#\r\n\t# output\r\n\t#\r\n\r\n\t$smarty->display('page_index.txt');\r\n"
  },
  {
    "path": "lib/auth.php",
    "content": "<?php\n\n\tclass SlackAuthPlugin {\n\n\t\tfunction saveConfig(){\n\t\t\t$GLOBALS['data']->set('auth', $this->id, $this->cfg);\n\t\t}\n\n\t\tfunction isUserAuthed(){\n\n\t\t\treturn false;\n\t\t}\n\n\t\tfunction getConfigUrl(){\n\n\t\t\treturn $GLOBALS['cfg']['root_url'] . 'auth.php?id=' . $this->id;\n\t\t}\n\t}\n"
  },
  {
    "path": "lib/config.php.example",
    "content": "<?php\n\t$cfg = array();\n\n\t# This URL should point to your Hammock install.\n\t# It must end in a slash.\n\n\t$cfg['root_url'] = 'http://myserver.com/hammock/';\n\n\n\t# The details of your OAuth application.\n\t# You can create it here: https://api.slack.com/applications\n\t# Make sure to set the OAuth URL to the same as 'root_url' above\n\n        $cfg['client_id'] = '123456.7890';\n        $cfg['client_secret'] = 'abcdefg';\n\n\n\t# Where we should store cookies\n\t# NOTE: the domain must contain a dot. if you want to use localhost,\n\t# try `127.0.0.1`, or set up an alias in your /etc/hosts file.\n\t# If running from a subdirectory, make sure to change 'cookie_path'\n\n        $cfg['cookie_domain'] = 'myserver.com';\n        $cfg['cookie_path'] = '/';\n        $cfg['cookie_name'] = 'hammock-auth';\n\n\n\t# Base URL for Slack.\n\t# Leave this as-is unless you're using Slack-in-a-box\n\n\t$cfg['slack_root'] = \"https://slack.com/\";\n"
  },
  {
    "path": "lib/config_env.php",
    "content": "<?php\n\t$cfg = array();\n\n\t# This ENV var must point to your app's root\n\n\t$cfg['root_url'] = $_ENV['HAMMOCK_ROOT'];\n\n\tif (!strlen($cfg['root_url'])) die(\"No HAMMOCK_ROOT set\");\n\n\n\t# OAuth config\n\n\t$cfg['client_id']\t= $_ENV['HAMMOCK_CLIENT_ID'];\n\t$cfg['client_secret']\t= $_ENV['HAMMOCK_CLIENT_SECRET'];\n\n\n\t# Defaults\n\n\t$url_bits = parse_url($cfg['root_url']);\n\n\t$cfg['cookie_domain']\t= $url_bits['host'];\n\t$cfg['cookie_path']\t= $url_bits['path'];\n\t$cfg['cookie_name']\t= 'hammock-auth';\n\t$cfg['slack_root']\t= \"https://slack.com/\";\n\n\t# Heroku specific\n\n\tif ($_ENV['REDISTOGO_URL']){\n\t\t$cfg['data_provider'] = 'redis';\n\t\t$cfg['redis_url'] = $_ENV['REDISTOGO_URL'];\n\t}\n\n\n\t# Allow some settings to be overridden\n\n\t$allow_override = array(\n\t\t'cookie_domain',\n\t\t'cookie_path',\n\t\t'cookie_name',\n\t\t'slack_root',\n\t);\n\n\tforeach ($allow_override as $opt){\n\t\t$opte = 'HAMMOCK_'.strtoupper($opt);\n\t\tif (isset($_ENV[$opte])) $cfg[$opt] = $_ENV[$opte];\n\t}\n"
  },
  {
    "path": "lib/data.php",
    "content": "<?php\n\t# this is the abstract class for data storage.\n\t# actual implementations will override it.\n\n\tclass SlackData {\n\n\t\tfunction get($table, $key){\n\t\t\treturn array();\n\t\t}\n\n\t\tfunction get_all($table){\n\t\t\treturn array();\n\t\t}\n\n\t\tfunction set($table, $key, $value){\n\t\t\treturn true;\n\t\t}\n\n\t\tfunction del($table, $key){\n\t\t\treturn true;\n\t\t}\n\n\t\tfunction clear($table){\n\t\t\treturn true;\n\t\t}\n\t}\n\n"
  },
  {
    "path": "lib/data_files.php",
    "content": "<?php\n\tclass SlackDataFiles extends SlackData {\n\n\t\tprivate $cache = array();\n\n\t\tfunction get($table, $key){\n\n\t\t\tif (!isset($this->cache[$table])){\n\t\t\t\t$this->cache[$table] = $this->load($table);\n\t\t\t}\n\n\t\t\treturn $this->cache[$table] ? $this->cache[$table][$key] : null;\n\t\t}\n\n\t\tfunction get_all($table){\n\n\t\t\tif (!isset($this->cache[$table])){\n\t\t\t\t$this->cache[$table] = $this->load($table);\n\t\t\t}\n\n\t\t\treturn $this->cache[$table];\n\t\t}\n\n\t\tfunction set($table, $key, $value){\n\n\t\t\t$this->cache[$table] = $this->load($table);\n\t\t\t$this->cache[$table][$key] = $value;\n\t\t\t$this->save($table, $this->cache[$table]);\n\t\t\treturn true;\n\t\t}\n\n\t\tfunction del($table, $key){\n\n\t\t\t$this->cache[$table] = $this->load($table);\n\t\t\tunset($this->cache[$table][$key]);\n\t\t\t$this->save($table, $this->cache[$table]);\n\t\t\treturn true;\n\t\t}\n\n\t\tfunction clear($table){\n\t\t\t$this->cache[$table] = array();\n\t\t\t$this->save($table, $this->cache[$table]);\n\t\t\treturn true;\n\t\t}\n\n\t\t###\n\n\t\tprivate function load($table){\n\n\t\t\t$table_enc = urlencode($table);\n\t\t\t$path = HAMMOCK_ROOT.\"/data/data_{$table_enc}.php\";\n\n\t\t\t$data = array();\n\t\t\tif (file_exists($path)){\n\t\t\t\t$fh = fopen($path, 'r');\n\t\t\t\tif (!$fh) die(\"Failed to open data file for reading\");\n\n\t\t\t\t$flag = 0;\n\t\t\t\t$ok = flock($fh, LOCK_SH);\n\t\t\t\tif (!$ok) die(\"Failed to locl data file for reading\");\n\n\t\t\t\tinclude($path);\n\t\t\t\tflock($fh, LOCK_UN);\n\t\t\t\tfclose($fh);\n\n\t\t\t\tif (!is_array($data)) $data = array();\n\t\t\t}\n\t\t\treturn $data;\n\t\t}\n\n\t\tprivate function save($table, $data){\n\n\t\t\t$table_enc = urlencode($table);\n\t\t\t$path = HAMMOCK_ROOT.\"/data/data_{$table_enc}.php\";\n\n\t\t\t$fh = fopen($path, 'c');\n\t\t\tif (!$fh) die(\"Failed to open data file for writing\");\n\n\t\t\t$retries = 5;\n\t\t\tfor ($i=0; $i<$retries; $i++){\n\t\t\t\t$flag = 0;\n\t\t\t\t$ok = flock($fh, LOCK_EX | LOCK_NB, $flag);\n\t\t\t\tif ($ok) break;\n\t\t\t\tif (!$flag) die(\"Failed to lock data file\");\n\t\t\t\tsleep(1);\n\t\t\t}\n\t                if (!$ok) die(\"Failed to lock data file\");\n\n\t\t\tftruncate($fh, 0);\n\t\t\tfwrite($fh, \"<\".\"?php \\$data = \".var_export($data, true).';');\n\n\t\t\tflock($fh, LOCK_UN);\n\t\t\tfclose($fh);\n\t\t}\n\t}\n\n\t$GLOBALS['data'] = new SlackDataFiles();\n"
  },
  {
    "path": "lib/data_redis.php",
    "content": "<?php\n\tclass SlackDataRedis extends SlackData {\n\n\t\tfunction SlackDataRedis(){\n\n\t\t\t$this->redis = new Redis();\n\n\t\t\t$url = parse_url($GLOBALS['cfg']['redis_url']);\n\n\t\t\t$this->redis->connect($url['host'], $url['port']);\n\n\t\t\tif ($url['pass']) $this->redis->auth($url['pass']);\n\t\t}\n\n\t\tfunction get($table, $key){\n\n\t\t\t$ret = $this->redis->get(\"{$table}.{$key}\");\n\t\t\treturn $ret ? json_decode($ret, true) : null;\n\t\t}\n\n\t\tfunction get_all($table){\n\n\t\t\t$keys = $this->redis->keys(\"{$table}.*\");\n\n\t\t\t$out = array();\n\t\t\t$pl = strlen($table)+1;\n\n\t\t\tforeach ($keys as $key){\n\t\t\t\t$rec_key = substr($key, $pl);\n\t\t\t\t$out[$rec_key] = $this->get($table, $rec_key);\n\t\t\t}\n\t\t\treturn $out;\n\t\t}\n\n\t\tfunction set($table, $key, $value){\n\n\t\t\t$this->redis->set(\"{$table}.{$key}\", json_encode($value));\n\t\t\treturn true;\n\t\t}\n\n\t\tfunction del($table, $key){\n\n\t\t\t$this->redis->del(\"{$table}.{$key}\");\n\t\t\treturn true;\n\t\t}\n\n\t\tfunction clear($table){\n\t\t\t$keys = $this->redis->keys(\"{$table}.*\");\n\t\t\t$this->redis->del($keys);\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t$GLOBALS['data'] = new SlackDataRedis();\n"
  },
  {
    "path": "lib/http.php",
    "content": "<?php\n\tclass SlackHTTP {\n\n\t\tpublic static function get($url, $headers=array()){\n\n\t\t\t$ch = curl_init();\n\t\t\tcurl_setopt_array($ch, array(\n\t\t\t\tCURLOPT_URL            => $url,\n\t\t\t\tCURLOPT_HTTPHEADER     => SlackHTTP::prepare_outgoing_headers($headers),\n\t\t\t\tCURLOPT_RETURNTRANSFER => true,\n\t\t\t\tCURLOPT_SSL_VERIFYPEER => false,\n\t\t\t\tCURLINFO_HEADER_OUT    => true,\n\t\t\t\tCURLOPT_HEADER         => true\n\t\t\t));\n\n\t\t\t$raw = curl_exec($ch);\n\t\t\t$info = curl_getinfo($ch);\n\n\t\t\tcurl_close($ch);\n\n\t\t\treturn SlackHTTP::parse_response($raw, $info);\n\t\t}\n\n\t\tpublic static function post($url, $params=array(), $headers=array()){\n\n\t\t\t$ch = curl_init();\n\t\t\tcurl_setopt_array($ch, array(\n\t\t\t\tCURLOPT_URL            => $url,\n\t\t\t\tCURLOPT_HTTPHEADER     => SlackHTTP::prepare_outgoing_headers($headers),\n\t\t\t\tCURLOPT_RETURNTRANSFER => true,\n\t\t\t\tCURLOPT_SSL_VERIFYPEER => false,\n\t\t\t\tCURLINFO_HEADER_OUT    => true,\n\t\t\t\tCURLOPT_HEADER         => true,\n\t\t\t\tCURLOPT_POST           => true,\n\t\t\t\tCURLOPT_POSTFIELDS     => $params\n\t\t\t));\n\n\t\t\t$raw = curl_exec($ch);\n\t\t\t$info = curl_getinfo($ch);\n\n\t\t\tcurl_close($ch);\n\n\t\t\treturn SlackHTTP::parse_response($raw, $info);\n\t\t}\n\n\t\tprivate static function parse_response($raw, $info){\n\n\t\t\tlist($head, $body) = explode(\"\\r\\n\\r\\n\", $raw, 2);\n\t\t\tlist($head_out, $body_out) = explode(\"\\r\\n\\r\\n\", $info['request_header'], 2);\n\t\t\tunset($info['request_header']);\n\n\t\t\t$headers_in = SlackHTTP::parse_headers($head, '_status');\n\t\t\t$headers_out = SlackHTTP::parse_headers($head_out, '_request');\n\n\t\t\tpreg_match(\"/^([A-Z]+)\\s/\", $headers_out['_request'], $m);\n\t\t\t$method = $m[1];\n\n\t\t\t# log_notice(\"http\", \"{$method} {$url}\", $end-$start);\n\n\t\t\t# http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2\n\t\t\t# http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_Success (note HTTP 207 WTF)\n\n\t\t\t$status = $info['http_code'];\n\n\t\t\tif (($status < 200) || ($status > 299)){\n\n\t\t\t\treturn array(\n\t\t\t\t\t'ok'\t\t=> false,\n\t\t\t\t\t'error'\t\t=> 'http_failed',\n\t\t\t\t\t'code'\t\t=> $info['http_code'],\n\t\t\t\t\t'method'\t=> $method,\n\t\t\t\t\t'url'\t\t=> $info['url'],\n\t\t\t\t\t'info'\t\t=> $info,\n\t\t\t\t\t'req_headers'\t=> $headers_out,\n\t\t\t\t\t'headers'\t=> $headers_in,\n\t\t\t\t\t'body'\t\t=> $body,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn array(\n\t\t\t\t'ok'\t\t=> true,\n\t\t\t\t'code'\t\t=> $info['http_code'],\n\t\t\t\t'method'\t=> $method,\n\t\t\t\t'url'\t\t=> $info['url'],\n\t\t\t\t'info'\t\t=> $info,\n\t\t\t\t'req_headers'\t=> $headers_out,\n\t\t\t\t'headers'\t=> $headers_in,\n\t\t\t\t'body'\t\t=> $body,\n\t\t\t);\n\t\t}\n\n\t\tprivate static function parse_headers($raw, $first){\n\n\t\t\t#\n\t\t\t# first, deal with folded lines\n\t\t\t#\n\n\t\t\t$raw_lines = explode(\"\\r\\n\", $raw);\n\n\t\t\t$lines = array();\n\t\t\t$lines[] = array_shift($raw_lines);\n\n\t\t\tforeach ($raw_lines as $line){\n\t\t\t\tif (preg_match(\"!^[ \\t]!\", $line)){\n\t\t\t\t\t$lines[count($lines)-1] .= ' '.trim($line);\n\t\t\t\t}else{\n\t\t\t\t\t$lines[] = trim($line);\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\t#\n\t\t\t# now split them out\n\t\t\t#\n\n\t\t\t$out = array(\n\t\t\t\t$first => array_shift($lines),\n\t\t\t);\n\n\t\t\tforeach ($lines as $line){\n\t\t\t\tlist($k, $v) = explode(':', $line, 2);\n\t\t\t\t$out[StrToLower($k)] = trim($v);\n\t\t\t}\n\n\t\t\treturn $out;\n\t\t}\n\n\t\tprivate static function prepare_outgoing_headers($headers=array()){\n\n\t\t\t$prepped = array();\n\n\t\t\tif (!isset($headers['Expect'])){\n\t\t\t\t$headers['Expect'] = '';\t# Get around error 417\n\t\t\t}\n\n\t\t\tforeach ($headers as $key => $value){\n\t\t\t\t$prepped[] = \"{$key}: {$value}\";\n\t\t\t}\n\n\t\t\treturn $prepped;\n\t\t}\n\n\t}\n"
  },
  {
    "path": "lib/init.php",
    "content": "<?php\n\terror_reporting((E_ALL | E_STRICT) ^ E_NOTICE);\n\n\tdefine('HAMMOCK_ROOT', realpath(dirname(__FILE__).\"/..\"));\n\n\tif ($_ENV['HAMMOCK_ROOT']){\n\t\tinclude(HAMMOCK_ROOT.\"/lib/config_env.php\");\n\t}else{\n\t\tinclude(HAMMOCK_ROOT.\"/lib/config.php\");\n\t}\n\n\tinclude(HAMMOCK_ROOT.\"/lib/data.php\");\n\tif ($cfg['data_provider'] == 'redis'){\n\t\tinclude(HAMMOCK_ROOT.\"/lib/data_redis.php\");\n\t}else{\n\t\tinclude(HAMMOCK_ROOT.\"/lib/data_files.php\");\n\t}\n\n\tinclude(HAMMOCK_ROOT.\"/lib/http.php\");\n\tinclude(HAMMOCK_ROOT.\"/lib/service.php\");\n\tinclude(HAMMOCK_ROOT.\"/lib/auth.php\");\n\n\tinclude(HAMMOCK_ROOT.\"/lib/smarty/Smarty.class.php\");\n\n\tif (!file_exists(HAMMOCK_ROOT.\"/data/templates_c\")){\n\t\tmkdir(HAMMOCK_ROOT.\"/data/templates_c\", 0777, true);\n\t}\n\n\t$smarty = new Smarty();\n\t$smarty->template_dir = HAMMOCK_ROOT.\"/templates\";\n\t$smarty->compile_dir = HAMMOCK_ROOT.\"/data/templates_c\";\n\t$smarty->assign_by_ref('cfg', $cfg);\n\n\tfunction load_plugins(){\n\n\t\t$GLOBALS['plugins'] = array();\n\n\t\t$dir = HAMMOCK_ROOT.\"/plugins\";\n\n\t\tif ($dh = opendir($dir)){\n\t\t\twhile (($file = readdir($dh)) !== false){\n\n\t\t\t\tif (is_dir(\"{$dir}/{$file}\") && is_file(\"{$dir}/{$file}/plugin.php\")){\n\n\t\t\t\t\tif ((include(\"{$dir}/{$file}/plugin.php\"))){\n\n\t\t\t\t\t\t$GLOBALS['plugins'][$file] = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tclosedir($dh);\n\t\t}\n\n\t\t$GLOBALS['plugins_services'] = array();\n\t\t$GLOBALS['plugins_auth'    ] = array();\n\n\t\tforeach ($GLOBALS['plugins'] as $k => $v){\n\t\t\tif (is_subclass_of($k, 'SlackServicePlugin')) $GLOBALS['plugins_services'][$k] = 1;\n\t\t\tif (is_subclass_of($k, 'SlackAuthPlugin'   )) $GLOBALS['plugins_auth'    ][$k] = 1;\n\t\t}\n\t}\n\n\tfunction createPluginInstance($class_name){\n\t\t$obj = new $class_name();\n\t\t$obj->id = $class_name;\n\n\t\t$obj->smarty = new Smarty();\n\t\t$obj->smarty->compile_id = \"plugins|{$class_name}\";\n\t\t$obj->smarty->template_dir = HAMMOCK_ROOT.\"/plugins/{$class_name}/templates\";\n\t\t$obj->smarty->compile_dir = HAMMOCK_ROOT.\"/data/templates_c\";\n\t\t$obj->smarty->assign_by_ref('this', $obj);\n\n\t\treturn $obj;\n\t}\n\n\tfunction getPluginInstance($iid){\n\n\t\t$icfg = $GLOBALS['data']->get('instances', $iid);\n\n\t\tif (!isset($icfg)) return null;\n\n\t\t$plugin = $icfg['plugin'];\n\t\tunset($icfg['plugin']);\n\n\t\t$instance = createPluginInstance($plugin);\n\t\t$instance->setInstanceConfig($iid, $icfg);\n\n\t\treturn $instance;\n\t}\n\n\tfunction getAuthPlugin($id){\n\n\t\tif (!isset($GLOBALS['plugins_auth'][$id])) return null;\n\n\t\t$instance = createPluginInstance($id);\n\n\t\t$cfg = $GLOBALS['data']->get('auth', $id);\n\t\t$instance->cfg = $cfg ? $cfg : array();\n\n\t\treturn $instance;\n\t}\n\n\n\tfunction dumper($foo){\n\n\t\techo \"<pre style=\\\"text-align: left;\\\">\";\n\t\tif (is_resource($foo)){\n\t\t\tvar_dump($foo);\n\t\t}else{\n\t\t\techo HtmlSpecialChars(var_export($foo, 1));\n\t\t}\n\t\techo \"</pre>\\n\";\n\t}\n\n\tfunction api_call($method, $args = array()){\n\n\t\t$team = $GLOBALS['data']->get('metadata', 'team');\n\n\t\t$url = $GLOBALS['cfg']['slack_root'].\"api/\".$method.\"?token=\".$team['token'];\n\n\t\tforeach ($args as $k => $v) $url .= '&'.urlencode($k).'='.urlencode($v);\n\n\t\t$ret = SlackHTTP::get($url);\n\n\t\tif ($ret['ok'] && $ret['code'] == '200'){\n\t\t\treturn array(\n\t\t\t\t'ok'\t=> true,\n\t\t\t\t'data'\t=> json_decode($ret['body'], true),\n\t\t\t);\n\t\t}\n\n\t\treturn $ret;\n\t}\n\n\tfunction api_channels_list(){\n\n\t\t$ret = api_call('channels.list');\n\t\t$channels = array();\n\t\tforeach ($ret['data']['channels'] as $row){\n\t\t\tif (!$row['is_archived']) $channels[$row['id']] = '#'.$row['name'];\n\t\t}\n\n\t\treturn $channels;\n\t}\n\n\n\tfunction verify_auth(){\n\n\t\t$v = $_COOKIE[$GLOBALS['cfg']['cookie_name']];\n\n\t\tif ($v){\n\t\t\tlist($id, $secret) = explode('-', $v);\n\n\t\t\t$u = $GLOBALS['data']->get('users', $id);\n\n\t\t\tif (is_array($u) && $u['secret'] == $secret){\n\n\t\t\t\t$GLOBALS['cfg']['user'] = $u;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t$oauth_url = $GLOBALS['cfg']['slack_root'].\"oauth/authorize\";\n\t\t$oauth_url .= \"?client_id=\".$GLOBALS['cfg']['client_id'];\n\t\t$oauth_url .= \"&redirect_uri={$GLOBALS['cfg']['root_url']}oauth.php\";\n\n\t\t$team = $GLOBALS['data']->get('metadata', 'team');\n\t\tif ($team['id']){\n\n\t\t\t$oauth_url .= \"&team={$team['id']}\";\n\t\t}else{\n\t\t\t$GLOBALS['smarty']->assign('first_time', 1);\n\t\t}\n\n\t\tif (!strpos($GLOBALS['cfg']['cookie_domain'], '.')){\n\t\t\t$GLOBALS['smarty']->assign('bad_cookie_domain', 1);\n\t\t}\n\n\t\t$GLOBALS['smarty']->assign('oauth_url', $oauth_url);\n\t\t$GLOBALS['smarty']->display('page_login.txt');\n\t\texit;\n\t}\n\n\tfunction split_sets($in, $size){\n\t\t$out = array();\n\t\twhile (count($in)){\n\t\t\t$out[] = array_slice($in, 0, $size);\n\t\t\t$in = array_slice($in, $size);\n\t\t}\n\t\treturn $out;\n        }\n\n"
  },
  {
    "path": "lib/service.php",
    "content": "<?php\n\tclass SlackServicePlugin {\n\n\t\tpublic $name = \"NO NAME\";\n\t\tpublic $desc = \"NO DESC\";\n\n\t\tpublic $id;\t# class ID\n\t\tpublic $iid;\t# instance ID\n\n\t\tpublic $cfg;\t# class config\n\t\tpublic $icfg;\t# instance config\n\n\t\tprivate $log = array();\n\n\t\tfunction SlackServicePlugin(){\n\t\t\tif ($this->name == \"NO NAME\"){\n\t\t\t\t$cn = get_class($this);\n\t\t\t\t$this->name = \"Unnamed ({$cn})\";\n\t\t\t}\n\t\t}\n\n\t\tfunction createInstanceId(){\n\t\t\t$this->iid = uniqid();\n\t\t}\n\n\t\tfunction setInstanceConfig($iid, $icfg){\n\t\t\t$this->iid = $iid;\n\t\t\t$this->icfg = $icfg;\n\t\t}\n\n\t\tfunction checkRequirements(){\n\n\t\t\tif ($this->cfg['requires_auth']){\n\t\t\t\t$auth_plugin = $this->cfg['requires_auth'];\n\t\t\t\t$auth = getAuthPlugin($auth_plugin);\n\t\t\t\tif (!$auth->isConfigured()) die(\"This plugin requires auth be configured - {$auth_plugin}\");\n\t\t\t\tif (!$auth->isUserAuthed()) die(\"You need to authenticate before continuing\");\n\t\t\t}\n\t\t}\n\n\t\tfunction getHookUrl(){\n\n\t\t\t$url =  $GLOBALS['cfg']['root_url'] . 'hook.php?id=' . $this->iid;\n\n\t\t\tif ($this->cfg['has_token']) $url .= \"&token={$this->icfg['token']}\";\n\n\t\t\treturn $url;\n\t\t}\n\n\t\tfunction getEditUrl(){\n\n\t\t\treturn $GLOBALS['cfg']['root_url'] . 'edit.php?id=' . $this->iid;\n\t\t}\n\n\t\tfunction getViewUrl(){\n\n\t\t\treturn $GLOBALS['cfg']['root_url'] . 'view.php?id=' . $this->iid;\n\t\t}\n\n\t\tfunction dump(){\n\t\t\t$s = $this->smarty;\n\t\t\tunset($this->smarty);\n\t\t\tdumper($this);\n\t\t\t$this->smarty = $s;\n\t\t}\n\n                function saveConfig(){\n\t\t\t$cfg = $this->icfg;\n\t\t\t$cfg['plugin'] = $this->id;\n\t\t\t$GLOBALS['data']->set('instances', $this->iid, $cfg);\n\t\t}\n\n\t\tfunction deleteMe(){\n\t\t\t$cfg = $GLOBALS['data']->get('instances', $this->iid);\n\t\t\t$GLOBALS['data']->set('deleted_instances', $this->iid, $cfg);\n\t\t\t$GLOBALS['data']->del('instances', $this->iid);\n\t\t}\n\n\t\tfunction postToChannel($text, $extra){\n\n\t\t\t$this->log[] = array(\n\t\t\t\t'type' => 'message_post',\n\t\t\t\t'text' => $text,\n\t\t\t\t'extra' => $extra,\n\t\t\t);\n\n\t\t\t$params = array(\n\t\t\t\t'text'\t\t=> $text,\n\t\t\t\t'parse'\t\t=> 'none',\n\t\t\t\t'channel'\t=> '#general',\n\t\t\t\t'icon_url'\t=> $this->iconUrl(48, true),\n\t\t\t);\n\n\t\t\t$map_params = array(\n\t\t\t\t'channel',\n\t\t\t\t'username',\n\t\t\t\t'attachments',\n\t\t\t\t'unfurl_links',\n\t\t\t\t'icon_url',\n\t\t\t\t'icon_emoji',\n\t\t\t);\n\n\t\t\tforeach ($map_params as $p){\n\t\t\t\tif (isset($extra[$p])){\n\t\t\t\t\tif ($p == 'attachments'){\n\t\t\t\t\t\t$params[$p] = json_encode($extra[$p]);\n\t\t\t\t\t}else{\n\t\t\t\t\t\t$params[$p] = $extra[$p];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$ret = api_call('chat.postMessage', $params);\n\n\t\t\treturn $ret;\n\t\t}\n\n\t\tfunction getLog(){\n\t\t\treturn $this->log;\n\t\t}\n\n\t\tfunction escapeText($str){\n\t\t\treturn HtmlSpecialChars($str, ENT_NOQUOTES);\n\t\t}\n\n\t\tfunction escapeLink($url, $label=null){\n\t\t\t$url = trim($url);\n\n\t\t\t$url = $this->escapeText($url);\n\t\t\t$url = str_replace('|', '%7C', $url);\n\n\t\t\tif (strlen($label)){\n\n\t\t\t\t$label = $this->escapeText($label);\n\n\t\t\t\treturn \"<{$url}|{$label}>\";\n\t\t\t}\n\n\t\t\treturn \"<{$url}>\";\n\t\t}\n\n\t\tfunction onParentInit(){\n\n\t\t\tif ($this->cfg['has_token']){\n\t\t\t\t$this->regenToken();\n\t\t\t}\n\t\t}\n\n\t\tfunction regenToken(){\n\n\t\t\t$this->icfg['token'] = substr(sha1(rand()), 1, 10);\n\t\t}\n\n\t\tfunction getChannelsList(){\n\n\t\t\treturn api_channels_list();\n\t\t}\n\n\t\tfunction onLiveHook($req){\n\n\t\t\tif ($this->cfg['has_token']){\n\t\t\t\tif ($req['get']['token'] != $this->icfg['token']){\n\t\t\t\t\treturn array(\n\t\t\t\t\t\t'ok'\t\t=> false,\n\t\t\t\t\t\t'error'\t\t=> 'bad_token',\n\t\t\t\t\t\t'sent'\t\t=> $req['get']['token'],\n\t\t\t\t\t\t'expected'\t=> $this->icfg['token'],\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn $this->onHook($req);\n\t\t}\n\n\n\t\t# things to override\n\n\t\tfunction onView(){\n\n\t\t\treturn \"<p>No information for this plugin.</p>\";\n\t\t}\n\n\t\tfunction onEdit(){\n\n\t\t\treturn \"<p>No config for this plugin.</p>\";\n\t\t}\n\n\t\tfunction getLabel(){\n\n\t\t\treturn \"No label ({$this->iid})\";\n\t\t}\n\n\t\tfunction onInit(){\n\t\t\t# set default options in $this->icfg here\n\t\t}\n\n\t\tfunction onHook($request){\n\t\t\t# handle an incoming hook here\n\t\t\treturn array(\n\t\t\t\t'ok'\t=> false,\n\t\t\t\t'error'\t=> 'onHook not implemented',\n\t\t\t);\n\t\t}\n\n\t\tfunction iconUrl($size=32, $abs=false){\n\t\t\tif (!in_array($size, array(32,48,64,128))) $size = 32;\n\t\t\t$pre = $abs ? $GLOBALS['cfg']['root_url'] : '';\n\t\t\treturn \"{$pre}plugins/{$this->id}/icon_{$size}.png\";\n\t\t}\n\t}\n\n"
  },
  {
    "path": "lib/smarty/Config_File.class.php",
    "content": "<?php\n\n/**\n * Config_File class.\n *\n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n * For questions, help, comments, discussion, etc., please join the\n * Smarty mailing list. Send a blank e-mail to\n * smarty-discussion-subscribe@googlegroups.com \n *\n * @link http://www.smarty.net/\n * @version 2.6.25-dev\n * @copyright Copyright: 2001-2005 New Digital Group, Inc.\n * @author Andrei Zmievski <andrei@php.net>\n * @access public\n * @package Smarty\n */\n\n/* $Id: Config_File.class.php 3149 2009-05-23 20:59:25Z monte.ohrt $ */\n\n/**\n * Config file reading class\n * @package Smarty\n */\nclass Config_File {\n    /**#@+\n     * Options\n     * @var boolean\n     */\n    /**\n     * Controls whether variables with the same name overwrite each other.\n     */\n    var $overwrite        =    true;\n\n    /**\n     * Controls whether config values of on/true/yes and off/false/no get\n     * converted to boolean values automatically.\n     */\n    var $booleanize        =    true;\n\n    /**\n     * Controls whether hidden config sections/vars are read from the file.\n     */\n    var $read_hidden     =    true;\n\n    /**\n     * Controls whether or not to fix mac or dos formatted newlines.\n     * If set to true, \\r or \\r\\n will be changed to \\n.\n     */\n    var $fix_newlines =    true;\n    /**#@-*/\n\n    /** @access private */\n    var $_config_path    = \"\";\n    var $_config_data    = array();\n    /**#@-*/\n\n    /**\n     * Constructs a new config file class.\n     *\n     * @param string $config_path (optional) path to the config files\n     */\n    function Config_File($config_path = NULL)\n    {\n        if (isset($config_path))\n            $this->set_path($config_path);\n    }\n\n\n    /**\n     * Set the path where configuration files can be found.\n     *\n     * @param string $config_path path to the config files\n     */\n    function set_path($config_path)\n    {\n        if (!empty($config_path)) {\n            if (!is_string($config_path) || !file_exists($config_path) || !is_dir($config_path)) {\n                $this->_trigger_error_msg(\"Bad config file path '$config_path'\");\n                return;\n            }\n            if(substr($config_path, -1) != DIRECTORY_SEPARATOR) {\n                $config_path .= DIRECTORY_SEPARATOR;\n            }\n\n            $this->_config_path = $config_path;\n        }\n    }\n\n\n    /**\n     * Retrieves config info based on the file, section, and variable name.\n     *\n     * @param string $file_name config file to get info for\n     * @param string $section_name (optional) section to get info for\n     * @param string $var_name (optional) variable to get info for\n     * @return string|array a value or array of values\n     */\n    function get($file_name, $section_name = NULL, $var_name = NULL)\n    {\n        if (empty($file_name)) {\n            $this->_trigger_error_msg('Empty config file name');\n            return;\n        } else {\n            $file_name = $this->_config_path . $file_name;\n            if (!isset($this->_config_data[$file_name]))\n                $this->load_file($file_name, false);\n        }\n\n        if (!empty($var_name)) {\n            if (empty($section_name)) {\n                return $this->_config_data[$file_name][\"vars\"][$var_name];\n            } else {\n                if(isset($this->_config_data[$file_name][\"sections\"][$section_name][\"vars\"][$var_name]))\n                    return $this->_config_data[$file_name][\"sections\"][$section_name][\"vars\"][$var_name];\n                else\n                    return array();\n            }\n        } else {\n            if (empty($section_name)) {\n                return (array)$this->_config_data[$file_name][\"vars\"];\n            } else {\n                if(isset($this->_config_data[$file_name][\"sections\"][$section_name][\"vars\"]))\n                    return (array)$this->_config_data[$file_name][\"sections\"][$section_name][\"vars\"];\n                else\n                    return array();\n            }\n        }\n    }\n\n\n    /**\n     * Retrieves config info based on the key.\n     *\n     * @param $file_name string config key (filename/section/var)\n     * @return string|array same as get()\n     * @uses get() retrieves information from config file and returns it\n     */\n    function &get_key($config_key)\n    {\n        list($file_name, $section_name, $var_name) = explode('/', $config_key, 3);\n        $result = &$this->get($file_name, $section_name, $var_name);\n        return $result;\n    }\n\n    /**\n     * Get all loaded config file names.\n     *\n     * @return array an array of loaded config file names\n     */\n    function get_file_names()\n    {\n        return array_keys($this->_config_data);\n    }\n\n\n    /**\n     * Get all section names from a loaded file.\n     *\n     * @param string $file_name config file to get section names from\n     * @return array an array of section names from the specified file\n     */\n    function get_section_names($file_name)\n    {\n        $file_name = $this->_config_path . $file_name;\n        if (!isset($this->_config_data[$file_name])) {\n            $this->_trigger_error_msg(\"Unknown config file '$file_name'\");\n            return;\n        }\n\n        return array_keys($this->_config_data[$file_name][\"sections\"]);\n    }\n\n\n    /**\n     * Get all global or section variable names.\n     *\n     * @param string $file_name config file to get info for\n     * @param string $section_name (optional) section to get info for\n     * @return array an array of variables names from the specified file/section\n     */\n    function get_var_names($file_name, $section = NULL)\n    {\n        if (empty($file_name)) {\n            $this->_trigger_error_msg('Empty config file name');\n            return;\n        } else if (!isset($this->_config_data[$file_name])) {\n            $this->_trigger_error_msg(\"Unknown config file '$file_name'\");\n            return;\n        }\n\n        if (empty($section))\n            return array_keys($this->_config_data[$file_name][\"vars\"]);\n        else\n            return array_keys($this->_config_data[$file_name][\"sections\"][$section][\"vars\"]);\n    }\n\n\n    /**\n     * Clear loaded config data for a certain file or all files.\n     *\n     * @param string $file_name file to clear config data for\n     */\n    function clear($file_name = NULL)\n    {\n        if ($file_name === NULL)\n            $this->_config_data = array();\n        else if (isset($this->_config_data[$file_name]))\n            $this->_config_data[$file_name] = array();\n    }\n\n\n    /**\n     * Load a configuration file manually.\n     *\n     * @param string $file_name file name to load\n     * @param boolean $prepend_path whether current config path should be\n     *                              prepended to the filename\n     */\n    function load_file($file_name, $prepend_path = true)\n    {\n        if ($prepend_path && $this->_config_path != \"\")\n            $config_file = $this->_config_path . $file_name;\n        else\n            $config_file = $file_name;\n\n        ini_set('track_errors', true);\n        $fp = @fopen($config_file, \"r\");\n        if (!is_resource($fp)) {\n            $this->_trigger_error_msg(\"Could not open config file '$config_file'\");\n            return false;\n        }\n\n        $contents = ($size = filesize($config_file)) ? fread($fp, $size) : '';\n        fclose($fp);\n\n        $this->_config_data[$config_file] = $this->parse_contents($contents);\n        return true;\n    }\n\n    /**\n     * Store the contents of a file manually.\n     *\n     * @param string $config_file file name of the related contents\n     * @param string $contents the file-contents to parse\n     */\n    function set_file_contents($config_file, $contents)\n    {\n        $this->_config_data[$config_file] = $this->parse_contents($contents);\n        return true;\n    }\n\n    /**\n     * parse the source of a configuration file manually.\n     *\n     * @param string $contents the file-contents to parse\n     */\n    function parse_contents($contents)\n    {\n        if($this->fix_newlines) {\n            // fix mac/dos formatted newlines\n            $contents = preg_replace('!\\r\\n?!', \"\\n\", $contents);\n        }\n\n        $config_data = array();\n        $config_data['sections'] = array();\n        $config_data['vars'] = array();\n\n        /* reference to fill with data */\n        $vars =& $config_data['vars'];\n\n        /* parse file line by line */\n        preg_match_all('!^.*\\r?\\n?!m', $contents, $match);\n        $lines = $match[0];\n        for ($i=0, $count=count($lines); $i<$count; $i++) {\n            $line = $lines[$i];\n            if (empty($line)) continue;\n\n            if ( substr($line, 0, 1) == '[' && preg_match('!^\\[(.*?)\\]!', $line, $match) ) {\n                /* section found */\n                if (substr($match[1], 0, 1) == '.') {\n                    /* hidden section */\n                    if ($this->read_hidden) {\n                        $section_name = substr($match[1], 1);\n                    } else {\n                        /* break reference to $vars to ignore hidden section */\n                        unset($vars);\n                        $vars = array();\n                        continue;\n                    }\n                } else {                    \n                    $section_name = $match[1];\n                }\n                if (!isset($config_data['sections'][$section_name]))\n                    $config_data['sections'][$section_name] = array('vars' => array());\n                $vars =& $config_data['sections'][$section_name]['vars'];\n                continue;\n            }\n\n            if (preg_match('/^\\s*(\\.?\\w+)\\s*=\\s*(.*)/s', $line, $match)) {\n                /* variable found */\n                $var_name = rtrim($match[1]);\n                if (strpos($match[2], '\"\"\"') === 0) {\n                    /* handle multiline-value */\n                    $lines[$i] = substr($match[2], 3);\n                    $var_value = '';\n                    while ($i<$count) {\n                        if (($pos = strpos($lines[$i], '\"\"\"')) === false) {\n                            $var_value .= $lines[$i++];\n                        } else {\n                            /* end of multiline-value */\n                            $var_value .= substr($lines[$i], 0, $pos);\n                            break;\n                        }\n                    }\n                    $booleanize = false;\n\n                } else {\n                    /* handle simple value */\n                    $var_value = preg_replace('/^([\\'\"])(.*)\\1$/', '\\2', rtrim($match[2]));\n                    $booleanize = $this->booleanize;\n\n                }\n                $this->_set_config_var($vars, $var_name, $var_value, $booleanize);\n            }\n            /* else unparsable line / means it is a comment / means ignore it */\n        }\n        return $config_data;\n    }\n\n    /**#@+ @access private */\n    /**\n     * @param array &$container\n     * @param string $var_name\n     * @param mixed $var_value\n     * @param boolean $booleanize determines whether $var_value is converted to\n     *                            to true/false\n     */\n    function _set_config_var(&$container, $var_name, $var_value, $booleanize)\n    {\n        if (substr($var_name, 0, 1) == '.') {\n            if (!$this->read_hidden)\n                return;\n            else\n                $var_name = substr($var_name, 1);\n        }\n\n        if (!preg_match(\"/^[a-zA-Z_]\\w*$/\", $var_name)) {\n            $this->_trigger_error_msg(\"Bad variable name '$var_name'\");\n            return;\n        }\n\n        if ($booleanize) {\n            if (preg_match(\"/^(on|true|yes)$/i\", $var_value))\n                $var_value = true;\n            else if (preg_match(\"/^(off|false|no)$/i\", $var_value))\n                $var_value = false;\n        }\n\n        if (!isset($container[$var_name]) || $this->overwrite)\n            $container[$var_name] = $var_value;\n        else {\n            settype($container[$var_name], 'array');\n            $container[$var_name][] = $var_value;\n        }\n    }\n\n    /**\n     * @uses trigger_error() creates a PHP warning/error\n     * @param string $error_msg\n     * @param integer $error_type one of\n     */\n    function _trigger_error_msg($error_msg, $error_type = E_USER_WARNING)\n    {\n        trigger_error(\"Config_File error: $error_msg\", $error_type);\n    }\n    /**#@-*/\n}\n\n?>\n"
  },
  {
    "path": "lib/smarty/Smarty.class.php",
    "content": "<?php\n\n/**\n * Project:     Smarty: the PHP compiling template engine\n * File:        Smarty.class.php\n *\n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n * For questions, help, comments, discussion, etc., please join the\n * Smarty mailing list. Send a blank e-mail to\n * smarty-discussion-subscribe@googlegroups.com\n *\n * @link http://www.smarty.net/\n * @copyright 2001-2005 New Digital Group, Inc.\n * @author Monte Ohrt <monte at ohrt dot com>\n * @author Andrei Zmievski <andrei@php.net>\n * @package Smarty\n * @version 2.6.28\n */\n\n/* $Id: Smarty.class.php 4660 2012-09-24 20:05:15Z uwe.tews@googlemail.com $ */\n\n/**\n * DIR_SEP isn't used anymore, but third party apps might\n */\nif(!defined('DIR_SEP')) {\n    define('DIR_SEP', DIRECTORY_SEPARATOR);\n}\n\n/**\n * set SMARTY_DIR to absolute path to Smarty library files.\n * if not defined, include_path will be used. Sets SMARTY_DIR only if user\n * application has not already defined it.\n */\n\nif (!defined('SMARTY_DIR')) {\n    define('SMARTY_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR);\n}\n\nif (!defined('SMARTY_CORE_DIR')) {\n    define('SMARTY_CORE_DIR', SMARTY_DIR . 'internals' . DIRECTORY_SEPARATOR);\n}\n\ndefine('SMARTY_PHP_PASSTHRU',   0);\ndefine('SMARTY_PHP_QUOTE',      1);\ndefine('SMARTY_PHP_REMOVE',     2);\ndefine('SMARTY_PHP_ALLOW',      3);\n\n/**\n * @package Smarty\n */\nclass Smarty\n{\n    /**#@+\n     * Smarty Configuration Section\n     */\n\n    /**\n     * The name of the directory where templates are located.\n     *\n     * @var string\n     */\n    var $template_dir    =  'templates';\n\n    /**\n     * The directory where compiled templates are located.\n     *\n     * @var string\n     */\n    var $compile_dir     =  'templates_c';\n\n    /**\n     * The directory where config files are located.\n     *\n     * @var string\n     */\n    var $config_dir      =  'configs';\n\n    /**\n     * An array of directories searched for plugins.\n     *\n     * @var array\n     */\n    var $plugins_dir     =  array('plugins');\n\n    /**\n     * If debugging is enabled, a debug console window will display\n     * when the page loads (make sure your browser allows unrequested\n     * popup windows)\n     *\n     * @var boolean\n     */\n    var $debugging       =  false;\n\n    /**\n     * When set, smarty does uses this value as error_reporting-level.\n     *\n     * @var integer\n     */\n    var $error_reporting  =  null;\n\n    /**\n     * This is the path to the debug console template. If not set,\n     * the default one will be used.\n     *\n     * @var string\n     */\n    var $debug_tpl       =  '';\n\n    /**\n     * This determines if debugging is enable-able from the browser.\n     * <ul>\n     *  <li>NONE => no debugging control allowed</li>\n     *  <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>\n     * </ul>\n     * @link http://www.foo.dom/index.php?SMARTY_DEBUG\n     * @var string\n     */\n    var $debugging_ctrl  =  'NONE';\n\n    /**\n     * This tells Smarty whether to check for recompiling or not. Recompiling\n     * does not need to happen unless a template or config file is changed.\n     * Typically you enable this during development, and disable for\n     * production.\n     *\n     * @var boolean\n     */\n    var $compile_check   =  true;\n\n    /**\n     * This forces templates to compile every time. Useful for development\n     * or debugging.\n     *\n     * @var boolean\n     */\n    var $force_compile   =  false;\n\n    /**\n     * This enables template caching.\n     * <ul>\n     *  <li>0 = no caching</li>\n     *  <li>1 = use class cache_lifetime value</li>\n     *  <li>2 = use cache_lifetime in cache file</li>\n     * </ul>\n     * @var integer\n     */\n    var $caching         =  0;\n\n    /**\n     * The name of the directory for cache files.\n     *\n     * @var string\n     */\n    var $cache_dir       =  'cache';\n\n    /**\n     * This is the number of seconds cached content will persist.\n     * <ul>\n     *  <li>0 = always regenerate cache</li>\n     *  <li>-1 = never expires</li>\n     * </ul>\n     *\n     * @var integer\n     */\n    var $cache_lifetime  =  3600;\n\n    /**\n     * Only used when $caching is enabled. If true, then If-Modified-Since headers\n     * are respected with cached content, and appropriate HTTP headers are sent.\n     * This way repeated hits to a cached page do not send the entire page to the\n     * client every time.\n     *\n     * @var boolean\n     */\n    var $cache_modified_check = false;\n\n    /**\n     * This determines how Smarty handles \"<?php ... ?>\" tags in templates.\n     * possible values:\n     * <ul>\n     *  <li>SMARTY_PHP_PASSTHRU -> print tags as plain text</li>\n     *  <li>SMARTY_PHP_QUOTE    -> escape tags as entities</li>\n     *  <li>SMARTY_PHP_REMOVE   -> remove php tags</li>\n     *  <li>SMARTY_PHP_ALLOW    -> execute php tags</li>\n     * </ul>\n     *\n     * @var integer\n     */\n    var $php_handling    =  SMARTY_PHP_PASSTHRU;\n\n    /**\n     * This enables template security. When enabled, many things are restricted\n     * in the templates that normally would go unchecked. This is useful when\n     * untrusted parties are editing templates and you want a reasonable level\n     * of security. (no direct execution of PHP in templates for example)\n     *\n     * @var boolean\n     */\n    var $security       =   false;\n\n    /**\n     * This is the list of template directories that are considered secure. This\n     * is used only if {@link $security} is enabled. One directory per array\n     * element.  {@link $template_dir} is in this list implicitly.\n     *\n     * @var array\n     */\n    var $secure_dir     =   array();\n\n    /**\n     * These are the security settings for Smarty. They are used only when\n     * {@link $security} is enabled.\n     *\n     * @var array\n     */\n    var $security_settings  = array(\n                                    'PHP_HANDLING'    => false,\n                                    'IF_FUNCS'        => array('array', 'list',\n                                                               'isset', 'empty',\n                                                               'count', 'sizeof',\n                                                               'in_array', 'is_array',\n                                                               'true', 'false', 'null'),\n                                    'INCLUDE_ANY'     => false,\n                                    'PHP_TAGS'        => false,\n                                    'MODIFIER_FUNCS'  => array('count'),\n                                    'ALLOW_CONSTANTS'  => false,\n                                    'ALLOW_SUPER_GLOBALS' => true\n                                   );\n\n    /**\n     * This is an array of directories where trusted php scripts reside.\n     * {@link $security} is disabled during their inclusion/execution.\n     *\n     * @var array\n     */\n    var $trusted_dir        = array();\n\n    /**\n     * The left delimiter used for the template tags.\n     *\n     * @var string\n     */\n    var $left_delimiter  =  '{';\n\n    /**\n     * The right delimiter used for the template tags.\n     *\n     * @var string\n     */\n    var $right_delimiter =  '}';\n\n    /**\n     * The order in which request variables are registered, similar to\n     * variables_order in php.ini E = Environment, G = GET, P = POST,\n     * C = Cookies, S = Server\n     *\n     * @var string\n     */\n    var $request_vars_order    = 'EGPCS';\n\n    /**\n     * Indicates wether $HTTP_*_VARS[] (request_use_auto_globals=false)\n     * are uses as request-vars or $_*[]-vars. note: if\n     * request_use_auto_globals is true, then $request_vars_order has\n     * no effect, but the php-ini-value \"gpc_order\"\n     *\n     * @var boolean\n     */\n    var $request_use_auto_globals      = true;\n\n    /**\n     * Set this if you want different sets of compiled files for the same\n     * templates. This is useful for things like different languages.\n     * Instead of creating separate sets of templates per language, you\n     * set different compile_ids like 'en' and 'de'.\n     *\n     * @var string\n     */\n    var $compile_id            = null;\n\n    /**\n     * This tells Smarty whether or not to use sub dirs in the cache/ and\n     * templates_c/ directories. sub directories better organized, but\n     * may not work well with PHP safe mode enabled.\n     *\n     * @var boolean\n     *\n     */\n    var $use_sub_dirs          = false;\n\n    /**\n     * This is a list of the modifiers to apply to all template variables.\n     * Put each modifier in a separate array element in the order you want\n     * them applied. example: <code>array('escape:\"htmlall\"');</code>\n     *\n     * @var array\n     */\n    var $default_modifiers        = array();\n\n    /**\n     * This is the resource type to be used when not specified\n     * at the beginning of the resource path. examples:\n     * $smarty->display('file:index.tpl');\n     * $smarty->display('db:index.tpl');\n     * $smarty->display('index.tpl'); // will use default resource type\n     * {include file=\"file:index.tpl\"}\n     * {include file=\"db:index.tpl\"}\n     * {include file=\"index.tpl\"} {* will use default resource type *}\n     *\n     * @var array\n     */\n    var $default_resource_type    = 'file';\n\n    /**\n     * The function used for cache file handling. If not set, built-in caching is used.\n     *\n     * @var null|string function name\n     */\n    var $cache_handler_func   = null;\n\n    /**\n     * This indicates which filters are automatically loaded into Smarty.\n     *\n     * @var array array of filter names\n     */\n    var $autoload_filters = array();\n\n    /**#@+\n     * @var boolean\n     */\n    /**\n     * This tells if config file vars of the same name overwrite each other or not.\n     * if disabled, same name variables are accumulated in an array.\n     */\n    var $config_overwrite = true;\n\n    /**\n     * This tells whether or not to automatically booleanize config file variables.\n     * If enabled, then the strings \"on\", \"true\", and \"yes\" are treated as boolean\n     * true, and \"off\", \"false\" and \"no\" are treated as boolean false.\n     */\n    var $config_booleanize = true;\n\n    /**\n     * This tells whether hidden sections [.foobar] are readable from the\n     * tempalates or not. Normally you would never allow this since that is\n     * the point behind hidden sections: the application can access them, but\n     * the templates cannot.\n     */\n    var $config_read_hidden = false;\n\n    /**\n     * This tells whether or not automatically fix newlines in config files.\n     * It basically converts \\r (mac) or \\r\\n (dos) to \\n\n     */\n    var $config_fix_newlines = true;\n    /**#@-*/\n\n    /**\n     * If a template cannot be found, this PHP function will be executed.\n     * Useful for creating templates on-the-fly or other special action.\n     *\n     * @var string function name\n     */\n    var $default_template_handler_func = '';\n\n    /**\n     * The file that contains the compiler class. This can a full\n     * pathname, or relative to the php_include path.\n     *\n     * @var string\n     */\n    var $compiler_file        =    'Smarty_Compiler.class.php';\n\n    /**\n     * The class used for compiling templates.\n     *\n     * @var string\n     */\n    var $compiler_class        =   'Smarty_Compiler';\n\n    /**\n     * The class used to load config vars.\n     *\n     * @var string\n     */\n    var $config_class          =   'Config_File';\n\n/**#@+\n * END Smarty Configuration Section\n * There should be no need to touch anything below this line.\n * @access private\n */\n    /**\n     * where assigned template vars are kept\n     *\n     * @var array\n     */\n    var $_tpl_vars             = array();\n\n    /**\n     * stores run-time $smarty.* vars\n     *\n     * @var null|array\n     */\n    var $_smarty_vars          = null;\n\n    /**\n     * keeps track of sections\n     *\n     * @var array\n     */\n    var $_sections             = array();\n\n    /**\n     * keeps track of foreach blocks\n     *\n     * @var array\n     */\n    var $_foreach              = array();\n\n    /**\n     * keeps track of tag hierarchy\n     *\n     * @var array\n     */\n    var $_tag_stack            = array();\n\n    /**\n     * configuration object\n     *\n     * @var Config_file\n     */\n    var $_conf_obj             = null;\n\n    /**\n     * loaded configuration settings\n     *\n     * @var array\n     */\n    var $_config               = array(array('vars'  => array(), 'files' => array()));\n\n    /**\n     * md5 checksum of the string 'Smarty'\n     *\n     * @var string\n     */\n    var $_smarty_md5           = 'f8d698aea36fcbead2b9d5359ffca76f';\n\n    /**\n     * Smarty version number\n     *\n     * @var string\n     */\n    var $_version              = '2.6.28';\n\n    /**\n     * current template inclusion depth\n     *\n     * @var integer\n     */\n    var $_inclusion_depth      = 0;\n\n    /**\n     * for different compiled templates\n     *\n     * @var string\n     */\n    var $_compile_id           = null;\n\n    /**\n     * text in URL to enable debug mode\n     *\n     * @var string\n     */\n    var $_smarty_debug_id      = 'SMARTY_DEBUG';\n\n    /**\n     * debugging information for debug console\n     *\n     * @var array\n     */\n    var $_smarty_debug_info    = array();\n\n    /**\n     * info that makes up a cache file\n     *\n     * @var array\n     */\n    var $_cache_info           = array();\n\n    /**\n     * default file permissions\n     *\n     * @var integer\n     */\n    var $_file_perms           = 0644;\n\n    /**\n     * default dir permissions\n     *\n     * @var integer\n     */\n    var $_dir_perms               = 0771;\n\n    /**\n     * registered objects\n     *\n     * @var array\n     */\n    var $_reg_objects           = array();\n\n    /**\n     * table keeping track of plugins\n     *\n     * @var array\n     */\n    var $_plugins              = array(\n                                       'modifier'      => array(),\n                                       'function'      => array(),\n                                       'block'         => array(),\n                                       'compiler'      => array(),\n                                       'prefilter'     => array(),\n                                       'postfilter'    => array(),\n                                       'outputfilter'  => array(),\n                                       'resource'      => array(),\n                                       'insert'        => array());\n\n\n    /**\n     * cache serials\n     *\n     * @var array\n     */\n    var $_cache_serials = array();\n\n    /**\n     * name of optional cache include file\n     *\n     * @var string\n     */\n    var $_cache_include = null;\n\n    /**\n     * indicate if the current code is used in a compiled\n     * include\n     *\n     * @var string\n     */\n    var $_cache_including = false;\n\n    /**#@-*/\n    /**\n     * The class constructor.\n     */\n    function Smarty()\n    {\n      $this->assign('SCRIPT_NAME', isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME']\n                    : @$GLOBALS['HTTP_SERVER_VARS']['SCRIPT_NAME']);\n    }\n\n    /**\n     * assigns values to template variables\n     *\n     * @param array|string $tpl_var the template variable name(s)\n     * @param mixed $value the value to assign\n     */\n    function assign($tpl_var, $value = null)\n    {\n        if (is_array($tpl_var)){\n            foreach ($tpl_var as $key => $val) {\n                if ($key != '') {\n                    $this->_tpl_vars[$key] = $val;\n                }\n            }\n        } else {\n            if ($tpl_var != '')\n                $this->_tpl_vars[$tpl_var] = $value;\n        }\n    }\n\n    /**\n     * assigns values to template variables by reference\n     *\n     * @param string $tpl_var the template variable name\n     * @param mixed $value the referenced value to assign\n     */\n    function assign_by_ref($tpl_var, &$value)\n    {\n        if ($tpl_var != '')\n            $this->_tpl_vars[$tpl_var] = &$value;\n    }\n\n    /**\n     * appends values to template variables\n     *\n     * @param array|string $tpl_var the template variable name(s)\n     * @param mixed $value the value to append\n     */\n    function append($tpl_var, $value=null, $merge=false)\n    {\n        if (is_array($tpl_var)) {\n            // $tpl_var is an array, ignore $value\n            foreach ($tpl_var as $_key => $_val) {\n                if ($_key != '') {\n                    if(!@is_array($this->_tpl_vars[$_key])) {\n                        settype($this->_tpl_vars[$_key],'array');\n                    }\n                    if($merge && is_array($_val)) {\n                        foreach($_val as $_mkey => $_mval) {\n                            $this->_tpl_vars[$_key][$_mkey] = $_mval;\n                        }\n                    } else {\n                        $this->_tpl_vars[$_key][] = $_val;\n                    }\n                }\n            }\n        } else {\n            if ($tpl_var != '' && isset($value)) {\n                if(!@is_array($this->_tpl_vars[$tpl_var])) {\n                    settype($this->_tpl_vars[$tpl_var],'array');\n                }\n                if($merge && is_array($value)) {\n                    foreach($value as $_mkey => $_mval) {\n                        $this->_tpl_vars[$tpl_var][$_mkey] = $_mval;\n                    }\n                } else {\n                    $this->_tpl_vars[$tpl_var][] = $value;\n                }\n            }\n        }\n    }\n\n    /**\n     * appends values to template variables by reference\n     *\n     * @param string $tpl_var the template variable name\n     * @param mixed $value the referenced value to append\n     */\n    function append_by_ref($tpl_var, &$value, $merge=false)\n    {\n        if ($tpl_var != '' && isset($value)) {\n            if(!@is_array($this->_tpl_vars[$tpl_var])) {\n             settype($this->_tpl_vars[$tpl_var],'array');\n            }\n            if ($merge && is_array($value)) {\n                foreach($value as $_key => $_val) {\n                    $this->_tpl_vars[$tpl_var][$_key] = &$value[$_key];\n                }\n            } else {\n                $this->_tpl_vars[$tpl_var][] = &$value;\n            }\n        }\n    }\n\n\n    /**\n     * clear the given assigned template variable.\n     *\n     * @param string $tpl_var the template variable to clear\n     */\n    function clear_assign($tpl_var)\n    {\n        if (is_array($tpl_var))\n            foreach ($tpl_var as $curr_var)\n                unset($this->_tpl_vars[$curr_var]);\n        else\n            unset($this->_tpl_vars[$tpl_var]);\n    }\n\n\n    /**\n     * Registers custom function to be used in templates\n     *\n     * @param string $function the name of the template function\n     * @param string $function_impl the name of the PHP function to register\n     */\n    function register_function($function, $function_impl, $cacheable=true, $cache_attrs=null)\n    {\n        $this->_plugins['function'][$function] =\n            array($function_impl, null, null, false, $cacheable, $cache_attrs);\n\n    }\n\n    /**\n     * Unregisters custom function\n     *\n     * @param string $function name of template function\n     */\n    function unregister_function($function)\n    {\n        unset($this->_plugins['function'][$function]);\n    }\n\n    /**\n     * Registers object to be used in templates\n     *\n     * @param string $object name of template object\n     * @param object &$object_impl the referenced PHP object to register\n     * @param null|array $allowed list of allowed methods (empty = all)\n     * @param boolean $smarty_args smarty argument format, else traditional\n     * @param null|array $block_functs list of methods that are block format\n     */\n    function register_object($object, &$object_impl, $allowed = array(), $smarty_args = true, $block_methods = array())\n    {\n        settype($allowed, 'array');\n        settype($smarty_args, 'boolean');\n        $this->_reg_objects[$object] =\n            array(&$object_impl, $allowed, $smarty_args, $block_methods);\n    }\n\n    /**\n     * Unregisters object\n     *\n     * @param string $object name of template object\n     */\n    function unregister_object($object)\n    {\n        unset($this->_reg_objects[$object]);\n    }\n\n\n    /**\n     * Registers block function to be used in templates\n     *\n     * @param string $block name of template block\n     * @param string $block_impl PHP function to register\n     */\n    function register_block($block, $block_impl, $cacheable=true, $cache_attrs=null)\n    {\n        $this->_plugins['block'][$block] =\n            array($block_impl, null, null, false, $cacheable, $cache_attrs);\n    }\n\n    /**\n     * Unregisters block function\n     *\n     * @param string $block name of template function\n     */\n    function unregister_block($block)\n    {\n        unset($this->_plugins['block'][$block]);\n    }\n\n    /**\n     * Registers compiler function\n     *\n     * @param string $function name of template function\n     * @param string $function_impl name of PHP function to register\n     */\n    function register_compiler_function($function, $function_impl, $cacheable=true)\n    {\n        $this->_plugins['compiler'][$function] =\n            array($function_impl, null, null, false, $cacheable);\n    }\n\n    /**\n     * Unregisters compiler function\n     *\n     * @param string $function name of template function\n     */\n    function unregister_compiler_function($function)\n    {\n        unset($this->_plugins['compiler'][$function]);\n    }\n\n    /**\n     * Registers modifier to be used in templates\n     *\n     * @param string $modifier name of template modifier\n     * @param string $modifier_impl name of PHP function to register\n     */\n    function register_modifier($modifier, $modifier_impl)\n    {\n        $this->_plugins['modifier'][$modifier] =\n            array($modifier_impl, null, null, false);\n    }\n\n    /**\n     * Unregisters modifier\n     *\n     * @param string $modifier name of template modifier\n     */\n    function unregister_modifier($modifier)\n    {\n        unset($this->_plugins['modifier'][$modifier]);\n    }\n\n    /**\n     * Registers a resource to fetch a template\n     *\n     * @param string $type name of resource\n     * @param array $functions array of functions to handle resource\n     */\n    function register_resource($type, $functions)\n    {\n        if (count($functions)==4) {\n            $this->_plugins['resource'][$type] =\n                array($functions, false);\n\n        } elseif (count($functions)==5) {\n            $this->_plugins['resource'][$type] =\n                array(array(array(&$functions[0], $functions[1])\n                            ,array(&$functions[0], $functions[2])\n                            ,array(&$functions[0], $functions[3])\n                            ,array(&$functions[0], $functions[4]))\n                      ,false);\n\n        } else {\n            $this->trigger_error(\"malformed function-list for '$type' in register_resource\");\n\n        }\n    }\n\n    /**\n     * Unregisters a resource\n     *\n     * @param string $type name of resource\n     */\n    function unregister_resource($type)\n    {\n        unset($this->_plugins['resource'][$type]);\n    }\n\n    /**\n     * Registers a prefilter function to apply\n     * to a template before compiling\n     *\n     * @param callback $function\n     */\n    function register_prefilter($function)\n    {\n        $this->_plugins['prefilter'][$this->_get_filter_name($function)]\n            = array($function, null, null, false);\n    }\n\n    /**\n     * Unregisters a prefilter function\n     *\n     * @param callback $function\n     */\n    function unregister_prefilter($function)\n    {\n        unset($this->_plugins['prefilter'][$this->_get_filter_name($function)]);\n    }\n\n    /**\n     * Registers a postfilter function to apply\n     * to a compiled template after compilation\n     *\n     * @param callback $function\n     */\n    function register_postfilter($function)\n    {\n        $this->_plugins['postfilter'][$this->_get_filter_name($function)]\n            = array($function, null, null, false);\n    }\n\n    /**\n     * Unregisters a postfilter function\n     *\n     * @param callback $function\n     */\n    function unregister_postfilter($function)\n    {\n        unset($this->_plugins['postfilter'][$this->_get_filter_name($function)]);\n    }\n\n    /**\n     * Registers an output filter function to apply\n     * to a template output\n     *\n     * @param callback $function\n     */\n    function register_outputfilter($function)\n    {\n        $this->_plugins['outputfilter'][$this->_get_filter_name($function)]\n            = array($function, null, null, false);\n    }\n\n    /**\n     * Unregisters an outputfilter function\n     *\n     * @param callback $function\n     */\n    function unregister_outputfilter($function)\n    {\n        unset($this->_plugins['outputfilter'][$this->_get_filter_name($function)]);\n    }\n\n    /**\n     * load a filter of specified type and name\n     *\n     * @param string $type filter type\n     * @param string $name filter name\n     */\n    function load_filter($type, $name)\n    {\n        switch ($type) {\n            case 'output':\n                $_params = array('plugins' => array(array($type . 'filter', $name, null, null, false)));\n                require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');\n                smarty_core_load_plugins($_params, $this);\n                break;\n\n            case 'pre':\n            case 'post':\n                if (!isset($this->_plugins[$type . 'filter'][$name]))\n                    $this->_plugins[$type . 'filter'][$name] = false;\n                break;\n        }\n    }\n\n    /**\n     * clear cached content for the given template and cache id\n     *\n     * @param string $tpl_file name of template file\n     * @param string $cache_id name of cache_id\n     * @param string $compile_id name of compile_id\n     * @param string $exp_time expiration time\n     * @return boolean\n     */\n    function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null)\n    {\n\n        if (!isset($compile_id))\n            $compile_id = $this->compile_id;\n\n        if (!isset($tpl_file))\n            $compile_id = null;\n\n        $_auto_id = $this->_get_auto_id($cache_id, $compile_id);\n\n        if (!empty($this->cache_handler_func)) {\n            return call_user_func_array($this->cache_handler_func,\n                                  array('clear', &$this, &$dummy, $tpl_file, $cache_id, $compile_id, $exp_time));\n        } else {\n            $_params = array('auto_base' => $this->cache_dir,\n                            'auto_source' => $tpl_file,\n                            'auto_id' => $_auto_id,\n                            'exp_time' => $exp_time);\n            require_once(SMARTY_CORE_DIR . 'core.rm_auto.php');\n            return smarty_core_rm_auto($_params, $this);\n        }\n\n    }\n\n\n    /**\n     * clear the entire contents of cache (all templates)\n     *\n     * @param string $exp_time expire time\n     * @return boolean results of {@link smarty_core_rm_auto()}\n     */\n    function clear_all_cache($exp_time = null)\n    {\n        return $this->clear_cache(null, null, null, $exp_time);\n    }\n\n\n    /**\n     * test to see if valid cache exists for this template\n     *\n     * @param string $tpl_file name of template file\n     * @param string $cache_id\n     * @param string $compile_id\n     * @return string|false results of {@link _read_cache_file()}\n     */\n    function is_cached($tpl_file, $cache_id = null, $compile_id = null)\n    {\n        if (!$this->caching)\n            return false;\n\n        if (!isset($compile_id))\n            $compile_id = $this->compile_id;\n\n        $_params = array(\n            'tpl_file' => $tpl_file,\n            'cache_id' => $cache_id,\n            'compile_id' => $compile_id\n        );\n        require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php');\n        return smarty_core_read_cache_file($_params, $this);\n    }\n\n\n    /**\n     * clear all the assigned template variables.\n     *\n     */\n    function clear_all_assign()\n    {\n        $this->_tpl_vars = array();\n    }\n\n    /**\n     * clears compiled version of specified template resource,\n     * or all compiled template files if one is not specified.\n     * This function is for advanced use only, not normally needed.\n     *\n     * @param string $tpl_file\n     * @param string $compile_id\n     * @param string $exp_time\n     * @return boolean results of {@link smarty_core_rm_auto()}\n     */\n    function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp_time = null)\n    {\n        if (!isset($compile_id)) {\n            $compile_id = $this->compile_id;\n        }\n        $_params = array('auto_base' => $this->compile_dir,\n                        'auto_source' => $tpl_file,\n                        'auto_id' => $compile_id,\n                        'exp_time' => $exp_time,\n                        'extensions' => array('.inc', '.php'));\n        require_once(SMARTY_CORE_DIR . 'core.rm_auto.php');\n        return smarty_core_rm_auto($_params, $this);\n    }\n\n    /**\n     * Checks whether requested template exists.\n     *\n     * @param string $tpl_file\n     * @return boolean\n     */\n    function template_exists($tpl_file)\n    {\n        $_params = array('resource_name' => $tpl_file, 'quiet'=>true, 'get_source'=>false);\n        return $this->_fetch_resource_info($_params);\n    }\n\n    /**\n     * Returns an array containing template variables\n     *\n     * @param string $name\n     * @param string $type\n     * @return array\n     */\n    function &get_template_vars($name=null)\n    {\n        if(!isset($name)) {\n            return $this->_tpl_vars;\n        } elseif(isset($this->_tpl_vars[$name])) {\n            return $this->_tpl_vars[$name];\n        } else {\n            // var non-existant, return valid reference\n            $_tmp = null;\n            return $_tmp;\n        }\n    }\n\n    /**\n     * Returns an array containing config variables\n     *\n     * @param string $name\n     * @param string $type\n     * @return array\n     */\n    function &get_config_vars($name=null)\n    {\n        if(!isset($name) && is_array($this->_config[0])) {\n            return $this->_config[0]['vars'];\n        } else if(isset($this->_config[0]['vars'][$name])) {\n            return $this->_config[0]['vars'][$name];\n        } else {\n            // var non-existant, return valid reference\n            $_tmp = null;\n            return $_tmp;\n        }\n    }\n\n    /**\n     * trigger Smarty error\n     *\n     * @param string $error_msg\n     * @param integer $error_type\n     */\n    function trigger_error($error_msg, $error_type = E_USER_WARNING)\n    {\n        $msg = htmlentities($error_msg);\n        trigger_error(\"Smarty error: $msg\", $error_type);\n    }\n\n\n    /**\n     * executes & displays the template results\n     *\n     * @param string $resource_name\n     * @param string $cache_id\n     * @param string $compile_id\n     */\n    function display($resource_name, $cache_id = null, $compile_id = null)\n    {\n        $this->fetch($resource_name, $cache_id, $compile_id, true);\n    }\n\n    /**\n     * executes & returns or displays the template results\n     *\n     * @param string $resource_name\n     * @param string $cache_id\n     * @param string $compile_id\n     * @param boolean $display\n     */\n    function fetch($resource_name, $cache_id = null, $compile_id = null, $display = false)\n    {\n        static $_cache_info = array();\n\n        $_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(isset($this->error_reporting)\n               ? $this->error_reporting : error_reporting() & ~E_NOTICE);\n\n        if (!$this->debugging && $this->debugging_ctrl == 'URL') {\n            $_query_string = $this->request_use_auto_globals ? $_SERVER['QUERY_STRING'] : $GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING'];\n            if (@strstr($_query_string, $this->_smarty_debug_id)) {\n                if (@strstr($_query_string, $this->_smarty_debug_id . '=on')) {\n                    // enable debugging for this browser session\n                    @setcookie('SMARTY_DEBUG', true);\n                    $this->debugging = true;\n                } elseif (@strstr($_query_string, $this->_smarty_debug_id . '=off')) {\n                    // disable debugging for this browser session\n                    @setcookie('SMARTY_DEBUG', false);\n                    $this->debugging = false;\n                } else {\n                    // enable debugging for this page\n                    $this->debugging = true;\n                }\n            } else {\n                $this->debugging = (bool)($this->request_use_auto_globals ? @$_COOKIE['SMARTY_DEBUG'] : @$GLOBALS['HTTP_COOKIE_VARS']['SMARTY_DEBUG']);\n            }\n        }\n\n        if ($this->debugging) {\n            // capture time for debugging info\n            $_params = array();\n            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');\n            $_debug_start_time = smarty_core_get_microtime($_params, $this);\n            $this->_smarty_debug_info[] = array('type'      => 'template',\n                                                'filename'  => $resource_name,\n                                                'depth'     => 0);\n            $_included_tpls_idx = count($this->_smarty_debug_info) - 1;\n        }\n\n        if (!isset($compile_id)) {\n            $compile_id = $this->compile_id;\n        }\n\n        $this->_compile_id = $compile_id;\n        $this->_inclusion_depth = 0;\n\n        if ($this->caching) {\n            // save old cache_info, initialize cache_info\n            array_push($_cache_info, $this->_cache_info);\n            $this->_cache_info = array();\n            $_params = array(\n                'tpl_file' => $resource_name,\n                'cache_id' => $cache_id,\n                'compile_id' => $compile_id,\n                'results' => null\n            );\n            require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php');\n            if (smarty_core_read_cache_file($_params, $this)) {\n                $_smarty_results = $_params['results'];\n                if (!empty($this->_cache_info['insert_tags'])) {\n                    $_params = array('plugins' => $this->_cache_info['insert_tags']);\n                    require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');\n                    smarty_core_load_plugins($_params, $this);\n                    $_params = array('results' => $_smarty_results);\n                    require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php');\n                    $_smarty_results = smarty_core_process_cached_inserts($_params, $this);\n                }\n                if (!empty($this->_cache_info['cache_serials'])) {\n                    $_params = array('results' => $_smarty_results);\n                    require_once(SMARTY_CORE_DIR . 'core.process_compiled_include.php');\n                    $_smarty_results = smarty_core_process_compiled_include($_params, $this);\n                }\n\n\n                if ($display) {\n                    if ($this->debugging)\n                    {\n                        // capture time for debugging info\n                        $_params = array();\n                        require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');\n                        $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $_debug_start_time;\n                        require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php');\n                        $_smarty_results .= smarty_core_display_debug_console($_params, $this);\n                    }\n                    if ($this->cache_modified_check) {\n                        $_server_vars = ($this->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];\n                        $_last_modified_date = @substr($_server_vars['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_server_vars['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3);\n                        $_gmt_mtime = gmdate('D, d M Y H:i:s', $this->_cache_info['timestamp']).' GMT';\n                        if (@count($this->_cache_info['insert_tags']) == 0\n                            && !$this->_cache_serials\n                            && $_gmt_mtime == $_last_modified_date) {\n                            if (php_sapi_name()=='cgi')\n                                header('Status: 304 Not Modified');\n                            else\n                                header('HTTP/1.1 304 Not Modified');\n\n                        } else {\n                            header('Last-Modified: '.$_gmt_mtime);\n                            echo $_smarty_results;\n                        }\n                    } else {\n                            echo $_smarty_results;\n                    }\n                    error_reporting($_smarty_old_error_level);\n                    // restore initial cache_info\n                    $this->_cache_info = array_pop($_cache_info);\n                    return true;\n                } else {\n                    error_reporting($_smarty_old_error_level);\n                    // restore initial cache_info\n                    $this->_cache_info = array_pop($_cache_info);\n                    return $_smarty_results;\n                }\n            } else {\n                $this->_cache_info['template'][$resource_name] = true;\n                if ($this->cache_modified_check && $display) {\n                    header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');\n                }\n            }\n        }\n\n        // load filters that are marked as autoload\n        if (count($this->autoload_filters)) {\n            foreach ($this->autoload_filters as $_filter_type => $_filters) {\n                foreach ($_filters as $_filter) {\n                    $this->load_filter($_filter_type, $_filter);\n                }\n            }\n        }\n\n        $_smarty_compile_path = $this->_get_compile_path($resource_name);\n\n        // if we just need to display the results, don't perform output\n        // buffering - for speed\n        $_cache_including = $this->_cache_including;\n        $this->_cache_including = false;\n        if ($display && !$this->caching && count($this->_plugins['outputfilter']) == 0) {\n            if ($this->_is_compiled($resource_name, $_smarty_compile_path)\n                    || $this->_compile_resource($resource_name, $_smarty_compile_path))\n            {\n                include($_smarty_compile_path);\n            }\n        } else {\n            ob_start();\n            if ($this->_is_compiled($resource_name, $_smarty_compile_path)\n                    || $this->_compile_resource($resource_name, $_smarty_compile_path))\n            {\n                include($_smarty_compile_path);\n            }\n            $_smarty_results = ob_get_contents();\n            ob_end_clean();\n\n            foreach ((array)$this->_plugins['outputfilter'] as $_output_filter) {\n                $_smarty_results = call_user_func_array($_output_filter[0], array($_smarty_results, &$this));\n            }\n        }\n\n        if ($this->caching) {\n            $_params = array('tpl_file' => $resource_name,\n                        'cache_id' => $cache_id,\n                        'compile_id' => $compile_id,\n                        'results' => $_smarty_results);\n            require_once(SMARTY_CORE_DIR . 'core.write_cache_file.php');\n            smarty_core_write_cache_file($_params, $this);\n            require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php');\n            $_smarty_results = smarty_core_process_cached_inserts($_params, $this);\n\n            if ($this->_cache_serials) {\n                // strip nocache-tags from output\n                $_smarty_results = preg_replace('!(\\{/?nocache\\:[0-9a-f]{32}#\\d+\\})!s'\n                                                ,''\n                                                ,$_smarty_results);\n            }\n            // restore initial cache_info\n            $this->_cache_info = array_pop($_cache_info);\n        }\n        $this->_cache_including = $_cache_including;\n\n        if ($display) {\n            if (isset($_smarty_results)) { echo $_smarty_results; }\n            if ($this->debugging) {\n                // capture time for debugging info\n                $_params = array();\n                require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');\n                $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = (smarty_core_get_microtime($_params, $this) - $_debug_start_time);\n                require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php');\n                echo smarty_core_display_debug_console($_params, $this);\n            }\n            error_reporting($_smarty_old_error_level);\n            return;\n        } else {\n            error_reporting($_smarty_old_error_level);\n            if (isset($_smarty_results)) { return $_smarty_results; }\n        }\n    }\n\n    /**\n     * load configuration values\n     *\n     * @param string $file\n     * @param string $section\n     * @param string $scope\n     */\n    function config_load($file, $section = null, $scope = 'global')\n    {\n        require_once($this->_get_plugin_filepath('function', 'config_load'));\n        smarty_function_config_load(array('file' => $file, 'section' => $section, 'scope' => $scope), $this);\n    }\n\n    /**\n     * return a reference to a registered object\n     *\n     * @param string $name\n     * @return object\n     */\n    function &get_registered_object($name) {\n        if (!isset($this->_reg_objects[$name]))\n        $this->_trigger_fatal_error(\"'$name' is not a registered object\");\n\n        if (!is_object($this->_reg_objects[$name][0]))\n        $this->_trigger_fatal_error(\"registered '$name' is not an object\");\n\n        return $this->_reg_objects[$name][0];\n    }\n\n    /**\n     * clear configuration values\n     *\n     * @param string $var\n     */\n    function clear_config($var = null)\n    {\n        if(!isset($var)) {\n            // clear all values\n            $this->_config = array(array('vars'  => array(),\n                                         'files' => array()));\n        } else {\n            unset($this->_config[0]['vars'][$var]);\n        }\n    }\n\n    /**\n     * get filepath of requested plugin\n     *\n     * @param string $type\n     * @param string $name\n     * @return string|false\n     */\n    function _get_plugin_filepath($type, $name)\n    {\n        $_params = array('type' => $type, 'name' => $name);\n        require_once(SMARTY_CORE_DIR . 'core.assemble_plugin_filepath.php');\n        return smarty_core_assemble_plugin_filepath($_params, $this);\n    }\n\n   /**\n     * test if resource needs compiling\n     *\n     * @param string $resource_name\n     * @param string $compile_path\n     * @return boolean\n     */\n    function _is_compiled($resource_name, $compile_path)\n    {\n        if (!$this->force_compile && file_exists($compile_path)) {\n            if (!$this->compile_check) {\n                // no need to check compiled file\n                return true;\n            } else {\n                // get file source and timestamp\n                $_params = array('resource_name' => $resource_name, 'get_source'=>false);\n                if (!$this->_fetch_resource_info($_params)) {\n                    return false;\n                }\n                if ($_params['resource_timestamp'] <= filemtime($compile_path)) {\n                    // template not expired, no recompile\n                    return true;\n                } else {\n                    // compile template\n                    return false;\n                }\n            }\n        } else {\n            // compiled template does not exist, or forced compile\n            return false;\n        }\n    }\n\n   /**\n     * compile the template\n     *\n     * @param string $resource_name\n     * @param string $compile_path\n     * @return boolean\n     */\n    function _compile_resource($resource_name, $compile_path)\n    {\n\n        $_params = array('resource_name' => $resource_name);\n        if (!$this->_fetch_resource_info($_params)) {\n            return false;\n        }\n\n        $_source_content = $_params['source_content'];\n        $_cache_include    = substr($compile_path, 0, -4).'.inc';\n\n        if ($this->_compile_source($resource_name, $_source_content, $_compiled_content, $_cache_include)) {\n            // if a _cache_serial was set, we also have to write an include-file:\n            if ($this->_cache_include_info) {\n                require_once(SMARTY_CORE_DIR . 'core.write_compiled_include.php');\n                smarty_core_write_compiled_include(array_merge($this->_cache_include_info, array('compiled_content'=>$_compiled_content, 'resource_name'=>$resource_name)),  $this);\n            }\n\n            $_params = array('compile_path'=>$compile_path, 'compiled_content' => $_compiled_content);\n            require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php');\n            smarty_core_write_compiled_resource($_params, $this);\n\n            return true;\n        } else {\n            return false;\n        }\n\n    }\n\n   /**\n     * compile the given source\n     *\n     * @param string $resource_name\n     * @param string $source_content\n     * @param string $compiled_content\n     * @return boolean\n     */\n    function _compile_source($resource_name, &$source_content, &$compiled_content, $cache_include_path=null)\n    {\n        if (file_exists(SMARTY_DIR . $this->compiler_file)) {\n            require_once(SMARTY_DIR . $this->compiler_file);\n        } else {\n            // use include_path\n            require_once($this->compiler_file);\n        }\n\n\n        $smarty_compiler = new $this->compiler_class;\n\n        $smarty_compiler->template_dir      = $this->template_dir;\n        $smarty_compiler->compile_dir       = $this->compile_dir;\n        $smarty_compiler->plugins_dir       = $this->plugins_dir;\n        $smarty_compiler->config_dir        = $this->config_dir;\n        $smarty_compiler->force_compile     = $this->force_compile;\n        $smarty_compiler->caching           = $this->caching;\n        $smarty_compiler->php_handling      = $this->php_handling;\n        $smarty_compiler->left_delimiter    = $this->left_delimiter;\n        $smarty_compiler->right_delimiter   = $this->right_delimiter;\n        $smarty_compiler->_version          = $this->_version;\n        $smarty_compiler->security          = $this->security;\n        $smarty_compiler->secure_dir        = $this->secure_dir;\n        $smarty_compiler->security_settings = $this->security_settings;\n        $smarty_compiler->trusted_dir       = $this->trusted_dir;\n        $smarty_compiler->use_sub_dirs      = $this->use_sub_dirs;\n        $smarty_compiler->_reg_objects      = &$this->_reg_objects;\n        $smarty_compiler->_plugins          = &$this->_plugins;\n        $smarty_compiler->_tpl_vars         = &$this->_tpl_vars;\n        $smarty_compiler->default_modifiers = $this->default_modifiers;\n        $smarty_compiler->compile_id        = $this->_compile_id;\n        $smarty_compiler->_config            = $this->_config;\n        $smarty_compiler->request_use_auto_globals  = $this->request_use_auto_globals;\n\n        if (isset($cache_include_path) && isset($this->_cache_serials[$cache_include_path])) {\n            $smarty_compiler->_cache_serial = $this->_cache_serials[$cache_include_path];\n        }\n        $smarty_compiler->_cache_include = $cache_include_path;\n\n\n        $_results = $smarty_compiler->_compile_file($resource_name, $source_content, $compiled_content);\n\n        if ($smarty_compiler->_cache_serial) {\n            $this->_cache_include_info = array(\n                'cache_serial'=>$smarty_compiler->_cache_serial\n                ,'plugins_code'=>$smarty_compiler->_plugins_code\n                ,'include_file_path' => $cache_include_path);\n\n        } else {\n            $this->_cache_include_info = null;\n\n        }\n\n        return $_results;\n    }\n\n    /**\n     * Get the compile path for this resource\n     *\n     * @param string $resource_name\n     * @return string results of {@link _get_auto_filename()}\n     */\n    function _get_compile_path($resource_name)\n    {\n        return $this->_get_auto_filename($this->compile_dir, $resource_name,\n                                         $this->_compile_id) . '.php';\n    }\n\n    /**\n     * fetch the template info. Gets timestamp, and source\n     * if get_source is true\n     *\n     * sets $source_content to the source of the template, and\n     * $resource_timestamp to its time stamp\n     * @param string $resource_name\n     * @param string $source_content\n     * @param integer $resource_timestamp\n     * @param boolean $get_source\n     * @param boolean $quiet\n     * @return boolean\n     */\n\n    function _fetch_resource_info(&$params)\n    {\n        if(!isset($params['get_source'])) { $params['get_source'] = true; }\n        if(!isset($params['quiet'])) { $params['quiet'] = false; }\n\n        $_return = false;\n        $_params = array('resource_name' => $params['resource_name']) ;\n        if (isset($params['resource_base_path']))\n            $_params['resource_base_path'] = $params['resource_base_path'];\n        else\n            $_params['resource_base_path'] = $this->template_dir;\n\n        if ($this->_parse_resource_name($_params)) {\n            $_resource_type = $_params['resource_type'];\n            $_resource_name = $_params['resource_name'];\n            switch ($_resource_type) {\n                case 'file':\n                    if ($params['get_source']) {\n                        $params['source_content'] = $this->_read_file($_resource_name);\n                    }\n                    $params['resource_timestamp'] = filemtime($_resource_name);\n                    $_return = is_file($_resource_name) && is_readable($_resource_name);\n                    break;\n\n                default:\n                    // call resource functions to fetch the template source and timestamp\n                    if ($params['get_source']) {\n                        $_source_return = isset($this->_plugins['resource'][$_resource_type]) &&\n                            call_user_func_array($this->_plugins['resource'][$_resource_type][0][0],\n                                                 array($_resource_name, &$params['source_content'], &$this));\n                    } else {\n                        $_source_return = true;\n                    }\n\n                    $_timestamp_return = isset($this->_plugins['resource'][$_resource_type]) &&\n                        call_user_func_array($this->_plugins['resource'][$_resource_type][0][1],\n                                             array($_resource_name, &$params['resource_timestamp'], &$this));\n\n                    $_return = $_source_return && $_timestamp_return;\n                    break;\n            }\n        }\n\n        if (!$_return) {\n            // see if we can get a template with the default template handler\n            if (!empty($this->default_template_handler_func)) {\n                if (!is_callable($this->default_template_handler_func)) {\n                    $this->trigger_error(\"default template handler function \\\"$this->default_template_handler_func\\\" doesn't exist.\");\n                } else {\n                    $_return = call_user_func_array(\n                        $this->default_template_handler_func,\n                        array($_params['resource_type'], $_params['resource_name'], &$params['source_content'], &$params['resource_timestamp'], &$this));\n                }\n            }\n        }\n\n        if (!$_return) {\n            if (!$params['quiet']) {\n                $this->trigger_error('unable to read resource: \"' . $params['resource_name'] . '\"');\n            }\n        } else if ($_return && $this->security) {\n            require_once(SMARTY_CORE_DIR . 'core.is_secure.php');\n            if (!smarty_core_is_secure($_params, $this)) {\n                if (!$params['quiet'])\n                    $this->trigger_error('(secure mode) accessing \"' . $params['resource_name'] . '\" is not allowed');\n                $params['source_content'] = null;\n                $params['resource_timestamp'] = null;\n                return false;\n            }\n        }\n        return $_return;\n    }\n\n\n    /**\n     * parse out the type and name from the resource\n     *\n     * @param string $resource_base_path\n     * @param string $resource_name\n     * @param string $resource_type\n     * @param string $resource_name\n     * @return boolean\n     */\n\n    function _parse_resource_name(&$params)\n    {\n\n        // split tpl_path by the first colon\n        $_resource_name_parts = explode(':', $params['resource_name'], 2);\n\n        if (count($_resource_name_parts) == 1) {\n            // no resource type given\n            $params['resource_type'] = $this->default_resource_type;\n            $params['resource_name'] = $_resource_name_parts[0];\n        } else {\n            if(strlen($_resource_name_parts[0]) == 1) {\n                // 1 char is not resource type, but part of filepath\n                $params['resource_type'] = $this->default_resource_type;\n                $params['resource_name'] = $params['resource_name'];\n            } else {\n                $params['resource_type'] = $_resource_name_parts[0];\n                $params['resource_name'] = $_resource_name_parts[1];\n            }\n        }\n\n        if ($params['resource_type'] == 'file') {\n            if (!preg_match('/^([\\/\\\\\\\\]|[a-zA-Z]:[\\/\\\\\\\\])/', $params['resource_name'])) {\n                // relative pathname to $params['resource_base_path']\n                // use the first directory where the file is found\n                foreach ((array)$params['resource_base_path'] as $_curr_path) {\n                    $_fullpath = $_curr_path . DIRECTORY_SEPARATOR . $params['resource_name'];\n                    if (file_exists($_fullpath) && is_file($_fullpath)) {\n                        $params['resource_name'] = $_fullpath;\n                        return true;\n                    }\n                    // didn't find the file, try include_path\n                    $_params = array('file_path' => $_fullpath);\n                    require_once(SMARTY_CORE_DIR . 'core.get_include_path.php');\n                    if(smarty_core_get_include_path($_params, $this)) {\n                        $params['resource_name'] = $_params['new_file_path'];\n                        return true;\n                    }\n                }\n                return false;\n            } else {\n                /* absolute path */\n                return file_exists($params['resource_name']);\n            }\n        } elseif (empty($this->_plugins['resource'][$params['resource_type']])) {\n            $_params = array('type' => $params['resource_type']);\n            require_once(SMARTY_CORE_DIR . 'core.load_resource_plugin.php');\n            smarty_core_load_resource_plugin($_params, $this);\n        }\n\n        return true;\n    }\n\n\n    /**\n     * Handle modifiers\n     *\n     * @param string|null $modifier_name\n     * @param array|null $map_array\n     * @return string result of modifiers\n     */\n    function _run_mod_handler()\n    {\n        $_args = func_get_args();\n        list($_modifier_name, $_map_array) = array_splice($_args, 0, 2);\n        list($_func_name, $_tpl_file, $_tpl_line) =\n            $this->_plugins['modifier'][$_modifier_name];\n\n        $_var = $_args[0];\n        foreach ($_var as $_key => $_val) {\n            $_args[0] = $_val;\n            $_var[$_key] = call_user_func_array($_func_name, $_args);\n        }\n        return $_var;\n    }\n\n    /**\n     * Remove starting and ending quotes from the string\n     *\n     * @param string $string\n     * @return string\n     */\n    function _dequote($string)\n    {\n        if ((substr($string, 0, 1) == \"'\" || substr($string, 0, 1) == '\"') &&\n            substr($string, -1) == substr($string, 0, 1))\n            return substr($string, 1, -1);\n        else\n            return $string;\n    }\n\n\n    /**\n     * read in a file\n     *\n     * @param string $filename\n     * @return string\n     */\n    function _read_file($filename)\n    {\n        if ( file_exists($filename) && is_readable($filename) && ($fd = @fopen($filename, 'rb')) ) {\n            $contents = '';\n            while (!feof($fd)) {\n                $contents .= fread($fd, 8192);\n            }\n            fclose($fd);\n            return $contents;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * get a concrete filename for automagically created content\n     *\n     * @param string $auto_base\n     * @param string $auto_source\n     * @param string $auto_id\n     * @return string\n     * @staticvar string|null\n     * @staticvar string|null\n     */\n    function _get_auto_filename($auto_base, $auto_source = null, $auto_id = null)\n    {\n        $_compile_dir_sep =  $this->use_sub_dirs ? DIRECTORY_SEPARATOR : '^';\n        $_return = $auto_base . DIRECTORY_SEPARATOR;\n\n        if(isset($auto_id)) {\n            // make auto_id safe for directory names\n            $auto_id = str_replace('%7C',$_compile_dir_sep,(urlencode($auto_id)));\n            // split into separate directories\n            $_return .= $auto_id . $_compile_dir_sep;\n        }\n\n        if(isset($auto_source)) {\n            // make source name safe for filename\n            $_filename = urlencode(basename($auto_source));\n            $_crc32 = sprintf('%08X', crc32($auto_source));\n            // prepend %% to avoid name conflicts with\n            // with $params['auto_id'] names\n            $_crc32 = substr($_crc32, 0, 2) . $_compile_dir_sep .\n                      substr($_crc32, 0, 3) . $_compile_dir_sep . $_crc32;\n            $_return .= '%%' . $_crc32 . '%%' . $_filename;\n        }\n\n        return $_return;\n    }\n\n    /**\n     * unlink a file, possibly using expiration time\n     *\n     * @param string $resource\n     * @param integer $exp_time\n     */\n    function _unlink($resource, $exp_time = null)\n    {\n        if(isset($exp_time)) {\n            if(time() - @filemtime($resource) >= $exp_time) {\n                return @unlink($resource);\n            }\n        } else {\n            return @unlink($resource);\n        }\n    }\n\n    /**\n     * returns an auto_id for auto-file-functions\n     *\n     * @param string $cache_id\n     * @param string $compile_id\n     * @return string|null\n     */\n    function _get_auto_id($cache_id=null, $compile_id=null) {\n    if (isset($cache_id))\n        return (isset($compile_id)) ? $cache_id . '|' . $compile_id  : $cache_id;\n    elseif(isset($compile_id))\n        return $compile_id;\n    else\n        return null;\n    }\n\n    /**\n     * trigger Smarty plugin error\n     *\n     * @param string $error_msg\n     * @param string $tpl_file\n     * @param integer $tpl_line\n     * @param string $file\n     * @param integer $line\n     * @param integer $error_type\n     */\n    function _trigger_fatal_error($error_msg, $tpl_file = null, $tpl_line = null,\n            $file = null, $line = null, $error_type = E_USER_ERROR)\n    {\n        if(isset($file) && isset($line)) {\n            $info = ' ('.basename($file).\", line $line)\";\n        } else {\n            $info = '';\n        }\n        if (isset($tpl_line) && isset($tpl_file)) {\n            $this->trigger_error('[in ' . $tpl_file . ' line ' . $tpl_line . \"]: $error_msg$info\", $error_type);\n        } else {\n            $this->trigger_error($error_msg . $info, $error_type);\n        }\n    }\n\n\n    /**\n     * callback function for preg_replace, to call a non-cacheable block\n     * @return string\n     */\n    function _process_compiled_include_callback($match) {\n        $_func = '_smarty_tplfunc_'.$match[2].'_'.$match[3];\n        ob_start();\n        $_func($this);\n        $_ret = ob_get_contents();\n        ob_end_clean();\n        return $_ret;\n    }\n\n\n    /**\n     * called for included templates\n     *\n     * @param string $_smarty_include_tpl_file\n     * @param string $_smarty_include_vars\n     */\n\n    // $_smarty_include_tpl_file, $_smarty_include_vars\n\n    function _smarty_include($params)\n    {\n        if ($this->debugging) {\n            $_params = array();\n            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');\n            $debug_start_time = smarty_core_get_microtime($_params, $this);\n            $this->_smarty_debug_info[] = array('type'      => 'template',\n                                                  'filename'  => $params['smarty_include_tpl_file'],\n                                                  'depth'     => ++$this->_inclusion_depth);\n            $included_tpls_idx = count($this->_smarty_debug_info) - 1;\n        }\n\n        $this->_tpl_vars = array_merge($this->_tpl_vars, $params['smarty_include_vars']);\n\n        // config vars are treated as local, so push a copy of the\n        // current ones onto the front of the stack\n        array_unshift($this->_config, $this->_config[0]);\n\n        $_smarty_compile_path = $this->_get_compile_path($params['smarty_include_tpl_file']);\n\n\n        if ($this->_is_compiled($params['smarty_include_tpl_file'], $_smarty_compile_path)\n            || $this->_compile_resource($params['smarty_include_tpl_file'], $_smarty_compile_path))\n        {\n            include($_smarty_compile_path);\n        }\n\n        // pop the local vars off the front of the stack\n        array_shift($this->_config);\n\n        $this->_inclusion_depth--;\n\n        if ($this->debugging) {\n            // capture time for debugging info\n            $_params = array();\n            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');\n            $this->_smarty_debug_info[$included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $debug_start_time;\n        }\n\n        if ($this->caching) {\n            $this->_cache_info['template'][$params['smarty_include_tpl_file']] = true;\n        }\n    }\n\n\n    /**\n     * get or set an array of cached attributes for function that is\n     * not cacheable\n     * @return array\n     */\n    function &_smarty_cache_attrs($cache_serial, $count) {\n        $_cache_attrs =& $this->_cache_info['cache_attrs'][$cache_serial][$count];\n\n        if ($this->_cache_including) {\n            /* return next set of cache_attrs */\n            $_return = current($_cache_attrs);\n            next($_cache_attrs);\n            return $_return;\n\n        } else {\n            /* add a reference to a new set of cache_attrs */\n            $_cache_attrs[] = array();\n            return $_cache_attrs[count($_cache_attrs)-1];\n\n        }\n\n    }\n\n\n    /**\n     * wrapper for include() retaining $this\n     * @return mixed\n     */\n    function _include($filename, $once=false, $params=null)\n    {\n        if ($once) {\n            return include_once($filename);\n        } else {\n            return include($filename);\n        }\n    }\n\n\n    /**\n     * wrapper for eval() retaining $this\n     * @return mixed\n     */\n    function _eval($code, $params=null)\n    {\n        return eval($code);\n    }\n\n    /**\n     * Extracts the filter name from the given callback\n     *\n     * @param callback $function\n     * @return string\n     */\n\tfunction _get_filter_name($function)\n\t{\n\t\tif (is_array($function)) {\n\t\t\t$_class_name = (is_object($function[0]) ?\n\t\t\t\tget_class($function[0]) : $function[0]);\n\t\t\treturn $_class_name . '_' . $function[1];\n\t\t}\n\t\telse {\n\t\t\treturn $function;\n\t\t}\n\t}\n\n    /**#@-*/\n\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/Smarty_Compiler.class.php",
    "content": "<?php\n\n/**\n * Project:     Smarty: the PHP compiling template engine\n * File:        Smarty_Compiler.class.php\n *\n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n * @link http://smarty.php.net/\n * @author Monte Ohrt <monte at ohrt dot com>\n * @author Andrei Zmievski <andrei@php.net>\n * @version 2.6.25-dev\n * @copyright 2001-2005 New Digital Group, Inc.\n * @package Smarty\n */\n\n/* $Id: Smarty_Compiler.class.php 4779 2013-09-30 19:14:32Z Uwe.Tews@googlemail.com $ */\n\n/**\n * Template compiling class\n * @package Smarty\n */\nclass Smarty_Compiler extends Smarty {\n\n    // internal vars\n    /**#@+\n     * @access private\n     */\n    var $_folded_blocks         =   array();    // keeps folded template blocks\n    var $_current_file          =   null;       // the current template being compiled\n    var $_current_line_no       =   1;          // line number for error messages\n    var $_capture_stack         =   array();    // keeps track of nested capture buffers\n    var $_plugin_info           =   array();    // keeps track of plugins to load\n    var $_init_smarty_vars      =   false;\n    var $_permitted_tokens      =   array('true','false','yes','no','on','off','null');\n    var $_db_qstr_regexp        =   null;        // regexps are setup in the constructor\n    var $_si_qstr_regexp        =   null;\n    var $_qstr_regexp           =   null;\n    var $_func_regexp           =   null;\n    var $_reg_obj_regexp        =   null;\n    var $_var_bracket_regexp    =   null;\n    var $_num_const_regexp      =   null;\n    var $_dvar_guts_regexp      =   null;\n    var $_dvar_regexp           =   null;\n    var $_cvar_regexp           =   null;\n    var $_svar_regexp           =   null;\n    var $_avar_regexp           =   null;\n    var $_mod_regexp            =   null;\n    var $_var_regexp            =   null;\n    var $_parenth_param_regexp  =   null;\n    var $_func_call_regexp      =   null;\n    var $_obj_ext_regexp        =   null;\n    var $_obj_start_regexp      =   null;\n    var $_obj_params_regexp     =   null;\n    var $_obj_call_regexp       =   null;\n    var $_cacheable_state       =   0;\n    var $_cache_attrs_count     =   0;\n    var $_nocache_count         =   0;\n    var $_cache_serial          =   null;\n    var $_cache_include         =   null;\n\n    var $_strip_depth           =   0;\n    var $_additional_newline    =   \"\\n\";\n\n    /**#@-*/\n    /**\n     * The class constructor.\n     */\n    function Smarty_Compiler()\n    {\n        // matches double quoted strings:\n        // \"foobar\"\n        // \"foo\\\"bar\"\n        $this->_db_qstr_regexp = '\"[^\"\\\\\\\\]*(?:\\\\\\\\.[^\"\\\\\\\\]*)*\"';\n\n        // matches single quoted strings:\n        // 'foobar'\n        // 'foo\\'bar'\n        $this->_si_qstr_regexp = '\\'[^\\'\\\\\\\\]*(?:\\\\\\\\.[^\\'\\\\\\\\]*)*\\'';\n\n        // matches single or double quoted strings\n        $this->_qstr_regexp = '(?:' . $this->_db_qstr_regexp . '|' . $this->_si_qstr_regexp . ')';\n\n        // matches bracket portion of vars\n        // [0]\n        // [foo]\n        // [$bar]\n        $this->_var_bracket_regexp = '\\[\\$?[\\w\\.]+\\]';\n\n        // matches numerical constants\n        // 30\n        // -12\n        // 13.22\n        $this->_num_const_regexp = '(?:\\-?\\d+(?:\\.\\d+)?)';\n\n        // matches $ vars (not objects):\n        // $foo\n        // $foo.bar\n        // $foo.bar.foobar\n        // $foo[0]\n        // $foo[$bar]\n        // $foo[5][blah]\n        // $foo[5].bar[$foobar][4]\n        $this->_dvar_math_regexp = '(?:[\\+\\*\\/\\%]|(?:-(?!>)))';\n        $this->_dvar_math_var_regexp = '[\\$\\w\\.\\+\\-\\*\\/\\%\\d\\>\\[\\]]';\n        $this->_dvar_guts_regexp = '\\w+(?:' . $this->_var_bracket_regexp\n                . ')*(?:\\.\\$?\\w+(?:' . $this->_var_bracket_regexp . ')*)*(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?';\n        $this->_dvar_regexp = '\\$' . $this->_dvar_guts_regexp;\n\n        // matches config vars:\n        // #foo#\n        // #foobar123_foo#\n        $this->_cvar_regexp = '\\#\\w+\\#';\n\n        // matches section vars:\n        // %foo.bar%\n        $this->_svar_regexp = '\\%\\w+\\.\\w+\\%';\n\n        // matches all valid variables (no quotes, no modifiers)\n        $this->_avar_regexp = '(?:' . $this->_dvar_regexp . '|'\n           . $this->_cvar_regexp . '|' . $this->_svar_regexp . ')';\n\n        // matches valid variable syntax:\n        // $foo\n        // $foo\n        // #foo#\n        // #foo#\n        // \"text\"\n        // \"text\"\n        $this->_var_regexp = '(?:' . $this->_avar_regexp . '|' . $this->_qstr_regexp . ')';\n\n        // matches valid object call (one level of object nesting allowed in parameters):\n        // $foo->bar\n        // $foo->bar()\n        // $foo->bar(\"text\")\n        // $foo->bar($foo, $bar, \"text\")\n        // $foo->bar($foo, \"foo\")\n        // $foo->bar->foo()\n        // $foo->bar->foo->bar()\n        // $foo->bar($foo->bar)\n        // $foo->bar($foo->bar())\n        // $foo->bar($foo->bar($blah,$foo,44,\"foo\",$foo[0].bar))\n        $this->_obj_ext_regexp = '\\->(?:\\$?' . $this->_dvar_guts_regexp . ')';\n        $this->_obj_restricted_param_regexp = '(?:'\n                . '(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')(?:' . $this->_obj_ext_regexp . '(?:\\((?:(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')'\n                . '(?:\\s*,\\s*(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . '))*)?\\))?)*)';\n        $this->_obj_single_param_regexp = '(?:\\w+|' . $this->_obj_restricted_param_regexp . '(?:\\s*,\\s*(?:(?:\\w+|'\n                . $this->_var_regexp . $this->_obj_restricted_param_regexp . ')))*)';\n        $this->_obj_params_regexp = '\\((?:' . $this->_obj_single_param_regexp\n                . '(?:\\s*,\\s*' . $this->_obj_single_param_regexp . ')*)?\\)';\n        $this->_obj_start_regexp = '(?:' . $this->_dvar_regexp . '(?:' . $this->_obj_ext_regexp . ')+)';\n        $this->_obj_call_regexp = '(?:' . $this->_obj_start_regexp . '(?:' . $this->_obj_params_regexp . ')?(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?)';\n        \n        // matches valid modifier syntax:\n        // |foo\n        // |@foo\n        // |foo:\"bar\"\n        // |foo:$bar\n        // |foo:\"bar\":$foobar\n        // |foo|bar\n        // |foo:$foo->bar\n        $this->_mod_regexp = '(?:\\|@?\\w+(?::(?:\\w+|' . $this->_num_const_regexp . '|'\n           . $this->_obj_call_regexp . '|' . $this->_avar_regexp . '|' . $this->_qstr_regexp .'))*)';\n\n        // matches valid function name:\n        // foo123\n        // _foo_bar\n        $this->_func_regexp = '[a-zA-Z_]\\w*';\n\n        // matches valid registered object:\n        // foo->bar\n        $this->_reg_obj_regexp = '[a-zA-Z_]\\w*->[a-zA-Z_]\\w*';\n\n        // matches valid parameter values:\n        // true\n        // $foo\n        // $foo|bar\n        // #foo#\n        // #foo#|bar\n        // \"text\"\n        // \"text\"|bar\n        // $foo->bar\n        $this->_param_regexp = '(?:\\s*(?:' . $this->_obj_call_regexp . '|'\n           . $this->_var_regexp . '|' . $this->_num_const_regexp  . '|\\w+)(?>' . $this->_mod_regexp . '*)\\s*)';\n\n        // matches valid parenthesised function parameters:\n        //\n        // \"text\"\n        //    $foo, $bar, \"text\"\n        // $foo|bar, \"foo\"|bar, $foo->bar($foo)|bar\n        $this->_parenth_param_regexp = '(?:\\((?:\\w+|'\n                . $this->_param_regexp . '(?:\\s*,\\s*(?:(?:\\w+|'\n                . $this->_param_regexp . ')))*)?\\))';\n\n        // matches valid function call:\n        // foo()\n        // foo_bar($foo)\n        // _foo_bar($foo,\"bar\")\n        // foo123($foo,$foo->bar(),\"foo\")\n        $this->_func_call_regexp = '(?:' . $this->_func_regexp . '\\s*(?:'\n           . $this->_parenth_param_regexp . '))';\n    }\n\n    /**\n     * compile a resource\n     *\n     * sets $compiled_content to the compiled source\n     * @param string $resource_name\n     * @param string $source_content\n     * @param string $compiled_content\n     * @return true\n     */\n    function _compile_file($resource_name, $source_content, &$compiled_content)\n    {\n\n        if ($this->security) {\n            // do not allow php syntax to be executed unless specified\n            if ($this->php_handling == SMARTY_PHP_ALLOW &&\n                !$this->security_settings['PHP_HANDLING']) {\n                $this->php_handling = SMARTY_PHP_PASSTHRU;\n            }\n        }\n\n        $this->_load_filters();\n\n        $this->_current_file = $resource_name;\n        $this->_current_line_no = 1;\n        $ldq = preg_quote($this->left_delimiter, '~');\n        $rdq = preg_quote($this->right_delimiter, '~');\n\n        // run template source through prefilter functions\n        if (count($this->_plugins['prefilter']) > 0) {\n            foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) {\n                if ($prefilter === false) continue;\n                if ($prefilter[3] || is_callable($prefilter[0])) {\n                    $source_content = call_user_func_array($prefilter[0],\n                                                            array($source_content, &$this));\n                    $this->_plugins['prefilter'][$filter_name][3] = true;\n                } else {\n                    $this->_trigger_fatal_error(\"[plugin] prefilter '$filter_name' is not implemented\");\n                }\n            }\n        }\n\n        /* fetch all special blocks */\n        $search = \"~{$ldq}\\*(.*?)\\*{$rdq}|{$ldq}\\s*literal\\s*{$rdq}(.*?){$ldq}\\s*/literal\\s*{$rdq}|{$ldq}\\s*php\\s*{$rdq}(.*?){$ldq}\\s*/php\\s*{$rdq}~s\";\n\n        preg_match_all($search, $source_content, $match,  PREG_SET_ORDER);\n        $this->_folded_blocks = $match;\n        reset($this->_folded_blocks);\n\n        /* replace special blocks by \"{php}\" */\n        $source_content = preg_replace_callback($search, create_function ('$matches', \"return '\"\n                                       . $this->_quote_replace($this->left_delimiter) . 'php'\n                                       . \"' . str_repeat(\\\"\\n\\\", substr_count('\\$matches[1]', \\\"\\n\\\")) .'\"\n                                       . $this->_quote_replace($this->right_delimiter)\n                                       . \"';\")\n                                       , $source_content);\n\n        /* Gather all template tags. */\n        preg_match_all(\"~{$ldq}\\s*(.*?)\\s*{$rdq}~s\", $source_content, $_match);\n        $template_tags = $_match[1];\n        /* Split content by template tags to obtain non-template content. */\n        $text_blocks = preg_split(\"~{$ldq}.*?{$rdq}~s\", $source_content);\n\n        /* loop through text blocks */\n        for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) {\n            /* match anything resembling php tags */\n            if (preg_match_all('~(<\\?(?:\\w+|=)?|\\?>|language\\s*=\\s*[\\\"\\']?\\s*php\\s*[\\\"\\']?)~is', $text_blocks[$curr_tb], $sp_match)) {\n                /* replace tags with placeholders to prevent recursive replacements */\n                $sp_match[1] = array_unique($sp_match[1]);\n                usort($sp_match[1], '_smarty_sort_length');\n                for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {\n                    $text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],'%%%SMARTYSP'.$curr_sp.'%%%',$text_blocks[$curr_tb]);\n                }\n                /* process each one */\n                for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {\n                    if ($this->php_handling == SMARTY_PHP_PASSTHRU) {\n                        /* echo php contents */\n                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '<?php echo \\''.str_replace(\"'\", \"\\'\", $sp_match[1][$curr_sp]).'\\'; ?>'.\"\\n\", $text_blocks[$curr_tb]);\n                    } else if ($this->php_handling == SMARTY_PHP_QUOTE) {\n                        /* quote php tags */\n                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', htmlspecialchars($sp_match[1][$curr_sp]), $text_blocks[$curr_tb]);\n                    } else if ($this->php_handling == SMARTY_PHP_REMOVE) {\n                        /* remove php tags */\n                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '', $text_blocks[$curr_tb]);\n                    } else {\n                        /* SMARTY_PHP_ALLOW, but echo non php starting tags */\n                        $sp_match[1][$curr_sp] = preg_replace('~(<\\?(?!php|=|$))~i', '<?php echo \\'\\\\1\\'?>'.\"\\n\", $sp_match[1][$curr_sp]);\n                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', $sp_match[1][$curr_sp], $text_blocks[$curr_tb]);\n                    }\n                }\n            }\n        }\n        \n        /* Compile the template tags into PHP code. */\n        $compiled_tags = array();\n        for ($i = 0, $for_max = count($template_tags); $i < $for_max; $i++) {\n            $this->_current_line_no += substr_count($text_blocks[$i], \"\\n\");\n            $compiled_tags[] = $this->_compile_tag($template_tags[$i]);\n            $this->_current_line_no += substr_count($template_tags[$i], \"\\n\");\n        }\n        if (count($this->_tag_stack)>0) {\n            list($_open_tag, $_line_no) = end($this->_tag_stack);\n            $this->_syntax_error(\"unclosed tag \\{$_open_tag} (opened line $_line_no).\", E_USER_ERROR, __FILE__, __LINE__);\n            return;\n        }\n\n        /* Reformat $text_blocks between 'strip' and '/strip' tags,\n           removing spaces, tabs and newlines. */\n        $strip = false;\n        for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {\n            if ($compiled_tags[$i] == '{strip}') {\n                $compiled_tags[$i] = '';\n                $strip = true;\n                /* remove leading whitespaces */\n                $text_blocks[$i + 1] = ltrim($text_blocks[$i + 1]);\n            }\n            if ($strip) {\n                /* strip all $text_blocks before the next '/strip' */\n                for ($j = $i + 1; $j < $for_max; $j++) {\n                    /* remove leading and trailing whitespaces of each line */\n                    $text_blocks[$j] = preg_replace('![\\t ]*[\\r\\n]+[\\t ]*!', '', $text_blocks[$j]);\n                    if ($compiled_tags[$j] == '{/strip}') {                       \n                        /* remove trailing whitespaces from the last text_block */\n                        $text_blocks[$j] = rtrim($text_blocks[$j]);\n                    }\n                    $text_blocks[$j] = \"<?php echo '\" . strtr($text_blocks[$j], array(\"'\"=>\"\\'\", \"\\\\\"=>\"\\\\\\\\\")) . \"'; ?>\";\n                    if ($compiled_tags[$j] == '{/strip}') {\n                        $compiled_tags[$j] = \"\\n\"; /* slurped by php, but necessary\n                                    if a newline is following the closing strip-tag */\n                        $strip = false;\n                        $i = $j;\n                        break;\n                    }\n                }\n            }\n        }\n        $compiled_content = '';\n        \n        $tag_guard = '%%%SMARTYOTG' . md5(uniqid(rand(), true)) . '%%%';\n        \n        /* Interleave the compiled contents and text blocks to get the final result. */\n        for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {\n            if ($compiled_tags[$i] == '') {\n                // tag result empty, remove first newline from following text block\n                $text_blocks[$i+1] = preg_replace('~^(\\r\\n|\\r|\\n)~', '', $text_blocks[$i+1]);\n            }\n            // replace legit PHP tags with placeholder\n            $text_blocks[$i] = str_replace('<?', $tag_guard, $text_blocks[$i]);\n            $compiled_tags[$i] = str_replace('<?', $tag_guard, $compiled_tags[$i]);\n            \n            $compiled_content .= $text_blocks[$i] . $compiled_tags[$i];\n        }\n        $compiled_content .= str_replace('<?', $tag_guard, $text_blocks[$i]);\n\n        // escape php tags created by interleaving\n        $compiled_content = str_replace('<?', \"<?php echo '<?' ?>\\n\", $compiled_content);\n        $compiled_content = preg_replace(\"~(?<!')language\\s*=\\s*[\\\"\\']?\\s*php\\s*[\\\"\\']?~\", \"<?php echo 'language=php' ?>\\n\", $compiled_content);\n\n        // recover legit tags\n        $compiled_content = str_replace($tag_guard, '<?', $compiled_content); \n        \n        // remove \\n from the end of the file, if any\n        if (strlen($compiled_content) && (substr($compiled_content, -1) == \"\\n\") ) {\n            $compiled_content = substr($compiled_content, 0, -1);\n        }\n\n        if (!empty($this->_cache_serial)) {\n            $compiled_content = \"<?php \\$this->_cache_serials['\".$this->_cache_include.\"'] = '\".$this->_cache_serial.\"'; ?>\" . $compiled_content;\n        }\n\n        // run compiled template through postfilter functions\n        if (count($this->_plugins['postfilter']) > 0) {\n            foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) {\n                if ($postfilter === false) continue;\n                if ($postfilter[3] || is_callable($postfilter[0])) {\n                    $compiled_content = call_user_func_array($postfilter[0],\n                                                              array($compiled_content, &$this));\n                    $this->_plugins['postfilter'][$filter_name][3] = true;\n                } else {\n                    $this->_trigger_fatal_error(\"Smarty plugin error: postfilter '$filter_name' is not implemented\");\n                }\n            }\n        }\n\n        // put header at the top of the compiled template\n        $template_header = \"<?php /* Smarty version \".$this->_version.\", created on \".strftime(\"%Y-%m-%d %H:%M:%S\").\"\\n\";\n        $template_header .= \"         compiled from \".strtr(urlencode($resource_name), array('%2F'=>'/', '%3A'=>':')).\" */ ?>\\n\";\n\n        /* Emit code to load needed plugins. */\n        $this->_plugins_code = '';\n        if (count($this->_plugin_info)) {\n            $_plugins_params = \"array('plugins' => array(\";\n            foreach ($this->_plugin_info as $plugin_type => $plugins) {\n                foreach ($plugins as $plugin_name => $plugin_info) {\n                    $_plugins_params .= \"array('$plugin_type', '$plugin_name', '\" . strtr($plugin_info[0], array(\"'\" => \"\\\\'\", \"\\\\\" => \"\\\\\\\\\")) . \"', $plugin_info[1], \";\n                    $_plugins_params .= $plugin_info[2] ? 'true),' : 'false),';\n                }\n            }\n            $_plugins_params .= '))';\n            $plugins_code = \"<?php require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');\\nsmarty_core_load_plugins($_plugins_params, \\$this); ?>\\n\";\n            $template_header .= $plugins_code;\n            $this->_plugin_info = array();\n            $this->_plugins_code = $plugins_code;\n        }\n\n        if ($this->_init_smarty_vars) {\n            $template_header .= \"<?php require_once(SMARTY_CORE_DIR . 'core.assign_smarty_interface.php');\\nsmarty_core_assign_smarty_interface(null, \\$this); ?>\\n\";\n            $this->_init_smarty_vars = false;\n        }\n\n        $compiled_content = $template_header . $compiled_content;\n        return true;\n    }\n\n    /**\n     * Compile a template tag\n     *\n     * @param string $template_tag\n     * @return string\n     */\n    function _compile_tag($template_tag)\n    {\n        /* Matched comment. */\n        if (substr($template_tag, 0, 1) == '*' && substr($template_tag, -1) == '*')\n            return '';\n        \n        /* Split tag into two three parts: command, command modifiers and the arguments. */\n        if(! preg_match('~^(?:(' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp\n                . '|\\/?' . $this->_reg_obj_regexp . '|\\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*))\n                      (?:\\s+(.*))?$\n                    ~xs', $template_tag, $match)) {\n            $this->_syntax_error(\"unrecognized tag: $template_tag\", E_USER_ERROR, __FILE__, __LINE__);\n        }\n        \n        $tag_command = $match[1];\n        $tag_modifier = isset($match[2]) ? $match[2] : null;\n        $tag_args = isset($match[3]) ? $match[3] : null;\n\n        if (preg_match('~^' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$~', $tag_command)) {\n            /* tag name is a variable or object */\n            $_return = $this->_parse_var_props($tag_command . $tag_modifier);\n            return \"<?php echo $_return; ?>\" . $this->_additional_newline;\n        }\n\n        /* If the tag name is a registered object, we process it. */\n        if (preg_match('~^\\/?' . $this->_reg_obj_regexp . '$~', $tag_command)) {\n            return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier);\n        }\n\n        switch ($tag_command) {\n            case 'include':\n                return $this->_compile_include_tag($tag_args);\n\n            case 'include_php':\n                return $this->_compile_include_php_tag($tag_args);\n\n            case 'if':\n                $this->_push_tag('if');\n                return $this->_compile_if_tag($tag_args);\n\n            case 'else':\n                list($_open_tag) = end($this->_tag_stack);\n                if ($_open_tag != 'if' && $_open_tag != 'elseif')\n                    $this->_syntax_error('unexpected {else}', E_USER_ERROR, __FILE__, __LINE__);\n                else\n                    $this->_push_tag('else');\n                return '<?php else: ?>';\n\n            case 'elseif':\n                list($_open_tag) = end($this->_tag_stack);\n                if ($_open_tag != 'if' && $_open_tag != 'elseif')\n                    $this->_syntax_error('unexpected {elseif}', E_USER_ERROR, __FILE__, __LINE__);\n                if ($_open_tag == 'if')\n                    $this->_push_tag('elseif');\n                return $this->_compile_if_tag($tag_args, true);\n\n            case '/if':\n                $this->_pop_tag('if');\n                return '<?php endif; ?>';\n\n            case 'capture':\n                return $this->_compile_capture_tag(true, $tag_args);\n\n            case '/capture':\n                return $this->_compile_capture_tag(false);\n\n            case 'ldelim':\n                return $this->left_delimiter;\n\n            case 'rdelim':\n                return $this->right_delimiter;\n\n            case 'section':\n                $this->_push_tag('section');\n                return $this->_compile_section_start($tag_args);\n\n            case 'sectionelse':\n                $this->_push_tag('sectionelse');\n                return \"<?php endfor; else: ?>\";\n                break;\n\n            case '/section':\n                $_open_tag = $this->_pop_tag('section');\n                if ($_open_tag == 'sectionelse')\n                    return \"<?php endif; ?>\";\n                else\n                    return \"<?php endfor; endif; ?>\";\n\n            case 'foreach':\n                $this->_push_tag('foreach');\n                return $this->_compile_foreach_start($tag_args);\n                break;\n\n            case 'foreachelse':\n                $this->_push_tag('foreachelse');\n                return \"<?php endforeach; else: ?>\";\n\n            case '/foreach':\n                $_open_tag = $this->_pop_tag('foreach');\n                if ($_open_tag == 'foreachelse')\n                    return \"<?php endif; unset(\\$_from); ?>\";\n                else\n                    return \"<?php endforeach; endif; unset(\\$_from); ?>\";\n                break;\n\n            case 'strip':\n            case '/strip':\n                if (substr($tag_command, 0, 1)=='/') {\n                    $this->_pop_tag('strip');\n                    if (--$this->_strip_depth==0) { /* outermost closing {/strip} */\n                        $this->_additional_newline = \"\\n\";\n                        return '{' . $tag_command . '}';\n                    }\n                } else {\n                    $this->_push_tag('strip');\n                    if ($this->_strip_depth++==0) { /* outermost opening {strip} */\n                        $this->_additional_newline = \"\";\n                        return '{' . $tag_command . '}';\n                    }\n                }\n                return '';\n\n            case 'php':\n                /* handle folded tags replaced by {php} */\n                list(, $block) = each($this->_folded_blocks);\n                $this->_current_line_no += substr_count($block[0], \"\\n\");\n                /* the number of matched elements in the regexp in _compile_file()\n                   determins the type of folded tag that was found */\n                switch (count($block)) {\n                    case 2: /* comment */\n                        return '';\n\n                    case 3: /* literal */\n                        return \"<?php echo '\" . strtr($block[2], array(\"'\"=>\"\\'\", \"\\\\\"=>\"\\\\\\\\\")) . \"'; ?>\" . $this->_additional_newline;\n\n                    case 4: /* php */\n                        if ($this->security && !$this->security_settings['PHP_TAGS']) {\n                            $this->_syntax_error(\"(secure mode) php tags not permitted\", E_USER_WARNING, __FILE__, __LINE__);\n                            return;\n                        }\n                        return '<?php ' . $block[3] .' ?>';\n                }\n                break;\n\n            case 'insert':\n                return $this->_compile_insert_tag($tag_args);\n\n            default:\n                if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) {\n                    return $output;\n                } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) {\n                    return $output;\n                } else if ($this->_compile_custom_tag($tag_command, $tag_args, $tag_modifier, $output)) {\n                    return $output;                    \n                } else {\n                    $this->_syntax_error(\"unrecognized tag '$tag_command'\", E_USER_ERROR, __FILE__, __LINE__);\n                }\n\n        }\n    }\n\n\n    /**\n     * compile the custom compiler tag\n     *\n     * sets $output to the compiled custom compiler tag\n     * @param string $tag_command\n     * @param string $tag_args\n     * @param string $output\n     * @return boolean\n     */\n    function _compile_compiler_tag($tag_command, $tag_args, &$output)\n    {\n        $found = false;\n        $have_function = true;\n\n        /*\n         * First we check if the compiler function has already been registered\n         * or loaded from a plugin file.\n         */\n        if (isset($this->_plugins['compiler'][$tag_command])) {\n            $found = true;\n            $plugin_func = $this->_plugins['compiler'][$tag_command][0];\n            if (!is_callable($plugin_func)) {\n                $message = \"compiler function '$tag_command' is not implemented\";\n                $have_function = false;\n            }\n        }\n        /*\n         * Otherwise we need to load plugin file and look for the function\n         * inside it.\n         */\n        else if ($plugin_file = $this->_get_plugin_filepath('compiler', $tag_command)) {\n            $found = true;\n\n            include_once $plugin_file;\n\n            $plugin_func = 'smarty_compiler_' . $tag_command;\n            if (!is_callable($plugin_func)) {\n                $message = \"plugin function $plugin_func() not found in $plugin_file\\n\";\n                $have_function = false;\n            } else {\n                $this->_plugins['compiler'][$tag_command] = array($plugin_func, null, null, null, true);\n            }\n        }\n\n        /*\n         * True return value means that we either found a plugin or a\n         * dynamically registered function. False means that we didn't and the\n         * compiler should now emit code to load custom function plugin for this\n         * tag.\n         */\n        if ($found) {\n            if ($have_function) {\n                $output = call_user_func_array($plugin_func, array($tag_args, &$this));\n                if($output != '') {\n                $output = '<?php ' . $this->_push_cacheable_state('compiler', $tag_command)\n                                   . $output\n                                   . $this->_pop_cacheable_state('compiler', $tag_command) . ' ?>';\n                }\n            } else {\n                $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);\n            }\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n\n    /**\n     * compile block function tag\n     *\n     * sets $output to compiled block function tag\n     * @param string $tag_command\n     * @param string $tag_args\n     * @param string $tag_modifier\n     * @param string $output\n     * @return boolean\n     */\n    function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$output)\n    {\n        if (substr($tag_command, 0, 1) == '/') {\n            $start_tag = false;\n            $tag_command = substr($tag_command, 1);\n        } else\n            $start_tag = true;\n\n        $found = false;\n        $have_function = true;\n\n        /*\n         * First we check if the block function has already been registered\n         * or loaded from a plugin file.\n         */\n        if (isset($this->_plugins['block'][$tag_command])) {\n            $found = true;\n            $plugin_func = $this->_plugins['block'][$tag_command][0];\n            if (!is_callable($plugin_func)) {\n                $message = \"block function '$tag_command' is not implemented\";\n                $have_function = false;\n            }\n        }\n        /*\n         * Otherwise we need to load plugin file and look for the function\n         * inside it.\n         */\n        else if ($plugin_file = $this->_get_plugin_filepath('block', $tag_command)) {\n            $found = true;\n\n            include_once $plugin_file;\n\n            $plugin_func = 'smarty_block_' . $tag_command;\n            if (!function_exists($plugin_func)) {\n                $message = \"plugin function $plugin_func() not found in $plugin_file\\n\";\n                $have_function = false;\n            } else {\n                $this->_plugins['block'][$tag_command] = array($plugin_func, null, null, null, true);\n\n            }\n        }\n\n        if (!$found) {\n            return false;\n        } else if (!$have_function) {\n            $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);\n            return true;\n        }\n\n        /*\n         * Even though we've located the plugin function, compilation\n         * happens only once, so the plugin will still need to be loaded\n         * at runtime for future requests.\n         */\n        $this->_add_plugin('block', $tag_command);\n\n        if ($start_tag)\n            $this->_push_tag($tag_command);\n        else\n            $this->_pop_tag($tag_command);\n\n        if ($start_tag) {\n            $output = '<?php ' . $this->_push_cacheable_state('block', $tag_command);\n            $attrs = $this->_parse_attrs($tag_args);\n            $_cache_attrs='';\n            $arg_list = $this->_compile_arg_list('block', $tag_command, $attrs, $_cache_attrs);\n            $output .= \"$_cache_attrs\\$this->_tag_stack[] = array('$tag_command', array(\".implode(',', $arg_list).')); ';\n            $output .= '$_block_repeat=true;' . $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], null, $this, $_block_repeat);';\n            $output .= 'while ($_block_repeat) { ob_start(); ?>';\n        } else {\n            $output = '<?php $_block_content = ob_get_contents(); ob_end_clean(); ';\n            $_out_tag_text = $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], $_block_content, $this, $_block_repeat)';\n            if ($tag_modifier != '') {\n                $this->_parse_modifiers($_out_tag_text, $tag_modifier);\n            }\n            $output .= '$_block_repeat=false;echo ' . $_out_tag_text . '; } ';\n            $output .= \" array_pop(\\$this->_tag_stack); \" . $this->_pop_cacheable_state('block', $tag_command) . '?>';\n        }\n\n        return true;\n    }\n\n\n    /**\n     * compile custom function tag\n     *\n     * @param string $tag_command\n     * @param string $tag_args\n     * @param string $tag_modifier\n     * @return string\n     */\n    function _compile_custom_tag($tag_command, $tag_args, $tag_modifier, &$output)\n    {\n        $found = false;\n        $have_function = true;\n\n        /*\n         * First we check if the custom function has already been registered\n         * or loaded from a plugin file.\n         */\n        if (isset($this->_plugins['function'][$tag_command])) {\n            $found = true;\n            $plugin_func = $this->_plugins['function'][$tag_command][0];\n            if (!is_callable($plugin_func)) {\n                $message = \"custom function '$tag_command' is not implemented\";\n                $have_function = false;\n            }\n        }\n        /*\n         * Otherwise we need to load plugin file and look for the function\n         * inside it.\n         */\n        else if ($plugin_file = $this->_get_plugin_filepath('function', $tag_command)) {\n            $found = true;\n\n            include_once $plugin_file;\n\n            $plugin_func = 'smarty_function_' . $tag_command;\n            if (!function_exists($plugin_func)) {\n                $message = \"plugin function $plugin_func() not found in $plugin_file\\n\";\n                $have_function = false;\n            } else {\n                $this->_plugins['function'][$tag_command] = array($plugin_func, null, null, null, true);\n\n            }\n        }\n\n        if (!$found) {\n            return false;\n        } else if (!$have_function) {\n            $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);\n            return true;\n        }\n\n        /* declare plugin to be loaded on display of the template that\n           we compile right now */\n        $this->_add_plugin('function', $tag_command);\n\n        $_cacheable_state = $this->_push_cacheable_state('function', $tag_command);\n        $attrs = $this->_parse_attrs($tag_args);\n        $_cache_attrs = '';\n        $arg_list = $this->_compile_arg_list('function', $tag_command, $attrs, $_cache_attrs);\n\n        $output = $this->_compile_plugin_call('function', $tag_command).'(array('.implode(',', $arg_list).\"), \\$this)\";\n        if($tag_modifier != '') {\n            $this->_parse_modifiers($output, $tag_modifier);\n        }\n\n        if($output != '') {\n            $output =  '<?php ' . $_cacheable_state . $_cache_attrs . 'echo ' . $output . ';'\n                . $this->_pop_cacheable_state('function', $tag_command) . \"?>\" . $this->_additional_newline;\n        }\n\n        return true;\n    }\n\n    /**\n     * compile a registered object tag\n     *\n     * @param string $tag_command\n     * @param array $attrs\n     * @param string $tag_modifier\n     * @return string\n     */\n    function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier)\n    {\n        if (substr($tag_command, 0, 1) == '/') {\n            $start_tag = false;\n            $tag_command = substr($tag_command, 1);\n        } else {\n            $start_tag = true;\n        }\n\n        list($object, $obj_comp) = explode('->', $tag_command);\n\n        $arg_list = array();\n        if(count($attrs)) {\n            $_assign_var = false;\n            foreach ($attrs as $arg_name => $arg_value) {\n                if($arg_name == 'assign') {\n                    $_assign_var = $arg_value;\n                    unset($attrs['assign']);\n                    continue;\n                }\n                if (is_bool($arg_value))\n                    $arg_value = $arg_value ? 'true' : 'false';\n                $arg_list[] = \"'$arg_name' => $arg_value\";\n            }\n        }\n\n        if($this->_reg_objects[$object][2]) {\n            // smarty object argument format\n            $args = \"array(\".implode(',', (array)$arg_list).\"), \\$this\";\n        } else {\n            // traditional argument format\n            $args = implode(',', array_values($attrs));\n            if (empty($args)) {\n                $args = '';\n            }\n        }\n\n        $prefix = '';\n        $postfix = '';\n        $newline = '';\n        if(!is_object($this->_reg_objects[$object][0])) {\n            $this->_trigger_fatal_error(\"registered '$object' is not an object\" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);\n        } elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) {\n            $this->_trigger_fatal_error(\"'$obj_comp' is not a registered component of object '$object'\", $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);\n        } elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) {\n            // method\n            if(in_array($obj_comp, $this->_reg_objects[$object][3])) {\n                // block method\n                if ($start_tag) {\n                    $prefix = \"\\$this->_tag_stack[] = array('$obj_comp', $args); \";\n                    $prefix .= \"\\$_block_repeat=true; \\$this->_reg_objects['$object'][0]->$obj_comp(\\$this->_tag_stack[count(\\$this->_tag_stack)-1][1], null, \\$this, \\$_block_repeat); \";\n                    $prefix .= \"while (\\$_block_repeat) { ob_start();\";\n                    $return = null;\n                    $postfix = '';\n                } else {\n                    $prefix = \"\\$_obj_block_content = ob_get_contents(); ob_end_clean(); \\$_block_repeat=false;\";\n                    $return = \"\\$this->_reg_objects['$object'][0]->$obj_comp(\\$this->_tag_stack[count(\\$this->_tag_stack)-1][1], \\$_obj_block_content, \\$this, \\$_block_repeat)\";\n                    $postfix = \"} array_pop(\\$this->_tag_stack);\";\n                }\n            } else {\n                // non-block method\n                $return = \"\\$this->_reg_objects['$object'][0]->$obj_comp($args)\";\n            }\n        } else {\n            // property\n            $return = \"\\$this->_reg_objects['$object'][0]->$obj_comp\";\n        }\n\n        if($return != null) {\n            if($tag_modifier != '') {\n                $this->_parse_modifiers($return, $tag_modifier);\n            }\n\n            if(!empty($_assign_var)) {\n                $output = \"\\$this->assign('\" . $this->_dequote($_assign_var) .\"',  $return);\";\n            } else {\n                $output = 'echo ' . $return . ';';\n                $newline = $this->_additional_newline;\n            }\n        } else {\n            $output = '';\n        }\n\n        return '<?php ' . $prefix . $output . $postfix . \"?>\" . $newline;\n    }\n\n    /**\n     * Compile {insert ...} tag\n     *\n     * @param string $tag_args\n     * @return string\n     */\n    function _compile_insert_tag($tag_args)\n    {\n        $attrs = $this->_parse_attrs($tag_args);\n        $name = $this->_dequote($attrs['name']);\n\n        if (empty($name)) {\n            return $this->_syntax_error(\"missing insert name\", E_USER_ERROR, __FILE__, __LINE__);\n        }\n        \n        if (!preg_match('~^\\w+$~', $name)) {\n            return $this->_syntax_error(\"'insert: 'name' must be an insert function name\", E_USER_ERROR, __FILE__, __LINE__);\n        }\n\n        if (!empty($attrs['script'])) {\n            $delayed_loading = true;\n        } else {\n            $delayed_loading = false;\n        }\n\n        foreach ($attrs as $arg_name => $arg_value) {\n            if (is_bool($arg_value))\n                $arg_value = $arg_value ? 'true' : 'false';\n            $arg_list[] = \"'$arg_name' => $arg_value\";\n        }\n\n        $this->_add_plugin('insert', $name, $delayed_loading);\n\n        $_params = \"array('args' => array(\".implode(', ', (array)$arg_list).\"))\";\n\n        return \"<?php require_once(SMARTY_CORE_DIR . 'core.run_insert_handler.php');\\necho smarty_core_run_insert_handler($_params, \\$this); ?>\" . $this->_additional_newline;\n    }\n\n    /**\n     * Compile {include ...} tag\n     *\n     * @param string $tag_args\n     * @return string\n     */\n    function _compile_include_tag($tag_args)\n    {\n        $attrs = $this->_parse_attrs($tag_args);\n        $arg_list = array();\n\n        if (empty($attrs['file'])) {\n            $this->_syntax_error(\"missing 'file' attribute in include tag\", E_USER_ERROR, __FILE__, __LINE__);\n        }\n\n        foreach ($attrs as $arg_name => $arg_value) {\n            if ($arg_name == 'file') {\n                $include_file = $arg_value;\n                continue;\n            } else if ($arg_name == 'assign') {\n                $assign_var = $arg_value;\n                continue;\n            }\n            if (is_bool($arg_value))\n                $arg_value = $arg_value ? 'true' : 'false';\n            $arg_list[] = \"'$arg_name' => $arg_value\";\n        }\n\n        $output = '<?php ';\n\n        if (isset($assign_var)) {\n            $output .= \"ob_start();\\n\";\n        }\n\n        $output .=\n            \"\\$_smarty_tpl_vars = \\$this->_tpl_vars;\\n\";\n\n\n        $_params = \"array('smarty_include_tpl_file' => \" . $include_file . \", 'smarty_include_vars' => array(\".implode(',', (array)$arg_list).\"))\";\n        $output .= \"\\$this->_smarty_include($_params);\\n\" .\n        \"\\$this->_tpl_vars = \\$_smarty_tpl_vars;\\n\" .\n        \"unset(\\$_smarty_tpl_vars);\\n\";\n\n        if (isset($assign_var)) {\n            $output .= \"\\$this->assign(\" . $assign_var . \", ob_get_contents()); ob_end_clean();\\n\";\n        }\n\n        $output .= ' ?>';\n\n        return $output;\n\n    }\n\n    /**\n     * Compile {include ...} tag\n     *\n     * @param string $tag_args\n     * @return string\n     */\n    function _compile_include_php_tag($tag_args)\n    {\n        $attrs = $this->_parse_attrs($tag_args);\n\n        if (empty($attrs['file'])) {\n            $this->_syntax_error(\"missing 'file' attribute in include_php tag\", E_USER_ERROR, __FILE__, __LINE__);\n        }\n\n        $assign_var = (empty($attrs['assign'])) ? '' : $this->_dequote($attrs['assign']);\n        $once_var = (empty($attrs['once']) || $attrs['once']=='false') ? 'false' : 'true';\n\n        $arg_list = array();\n        foreach($attrs as $arg_name => $arg_value) {\n            if($arg_name != 'file' AND $arg_name != 'once' AND $arg_name != 'assign') {\n                if(is_bool($arg_value))\n                    $arg_value = $arg_value ? 'true' : 'false';\n                $arg_list[] = \"'$arg_name' => $arg_value\";\n            }\n        }\n\n        $_params = \"array('smarty_file' => \" . $attrs['file'] . \", 'smarty_assign' => '$assign_var', 'smarty_once' => $once_var, 'smarty_include_vars' => array(\".implode(',', $arg_list).\"))\";\n\n        return \"<?php require_once(SMARTY_CORE_DIR . 'core.smarty_include_php.php');\\nsmarty_core_smarty_include_php($_params, \\$this); ?>\" . $this->_additional_newline;\n    }\n\n\n    /**\n     * Compile {section ...} tag\n     *\n     * @param string $tag_args\n     * @return string\n     */\n    function _compile_section_start($tag_args)\n    {\n        $attrs = $this->_parse_attrs($tag_args);\n        $arg_list = array();\n\n        $output = '<?php ';\n        $section_name = $attrs['name'];\n        if (empty($section_name)) {\n            $this->_syntax_error(\"missing section name\", E_USER_ERROR, __FILE__, __LINE__);\n        }\n\n        $output .= \"unset(\\$this->_sections[$section_name]);\\n\";\n        $section_props = \"\\$this->_sections[$section_name]\";\n\n        foreach ($attrs as $attr_name => $attr_value) {\n            switch ($attr_name) {\n                case 'loop':\n                    $output .= \"{$section_props}['loop'] = is_array(\\$_loop=$attr_value) ? count(\\$_loop) : max(0, (int)\\$_loop); unset(\\$_loop);\\n\";\n                    break;\n\n                case 'show':\n                    if (is_bool($attr_value))\n                        $show_attr_value = $attr_value ? 'true' : 'false';\n                    else\n                        $show_attr_value = \"(bool)$attr_value\";\n                    $output .= \"{$section_props}['show'] = $show_attr_value;\\n\";\n                    break;\n\n                case 'name':\n                    $output .= \"{$section_props}['$attr_name'] = $attr_value;\\n\";\n                    break;\n\n                case 'max':\n                case 'start':\n                    $output .= \"{$section_props}['$attr_name'] = (int)$attr_value;\\n\";\n                    break;\n\n                case 'step':\n                    $output .= \"{$section_props}['$attr_name'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\\n\";\n                    break;\n\n                default:\n                    $this->_syntax_error(\"unknown section attribute - '$attr_name'\", E_USER_ERROR, __FILE__, __LINE__);\n                    break;\n            }\n        }\n\n        if (!isset($attrs['show']))\n            $output .= \"{$section_props}['show'] = true;\\n\";\n\n        if (!isset($attrs['loop']))\n            $output .= \"{$section_props}['loop'] = 1;\\n\";\n\n        if (!isset($attrs['max']))\n            $output .= \"{$section_props}['max'] = {$section_props}['loop'];\\n\";\n        else\n            $output .= \"if ({$section_props}['max'] < 0)\\n\" .\n                       \"    {$section_props}['max'] = {$section_props}['loop'];\\n\";\n\n        if (!isset($attrs['step']))\n            $output .= \"{$section_props}['step'] = 1;\\n\";\n\n        if (!isset($attrs['start']))\n            $output .= \"{$section_props}['start'] = {$section_props}['step'] > 0 ? 0 : {$section_props}['loop']-1;\\n\";\n        else {\n            $output .= \"if ({$section_props}['start'] < 0)\\n\" .\n                       \"    {$section_props}['start'] = max({$section_props}['step'] > 0 ? 0 : -1, {$section_props}['loop'] + {$section_props}['start']);\\n\" .\n                       \"else\\n\" .\n                       \"    {$section_props}['start'] = min({$section_props}['start'], {$section_props}['step'] > 0 ? {$section_props}['loop'] : {$section_props}['loop']-1);\\n\";\n        }\n\n        $output .= \"if ({$section_props}['show']) {\\n\";\n        if (!isset($attrs['start']) && !isset($attrs['step']) && !isset($attrs['max'])) {\n            $output .= \"    {$section_props}['total'] = {$section_props}['loop'];\\n\";\n        } else {\n            $output .= \"    {$section_props}['total'] = min(ceil(({$section_props}['step'] > 0 ? {$section_props}['loop'] - {$section_props}['start'] : {$section_props}['start']+1)/abs({$section_props}['step'])), {$section_props}['max']);\\n\";\n        }\n        $output .= \"    if ({$section_props}['total'] == 0)\\n\" .\n                   \"        {$section_props}['show'] = false;\\n\" .\n                   \"} else\\n\" .\n                   \"    {$section_props}['total'] = 0;\\n\";\n\n        $output .= \"if ({$section_props}['show']):\\n\";\n        $output .= \"\n            for ({$section_props}['index'] = {$section_props}['start'], {$section_props}['iteration'] = 1;\n                 {$section_props}['iteration'] <= {$section_props}['total'];\n                 {$section_props}['index'] += {$section_props}['step'], {$section_props}['iteration']++):\\n\";\n        $output .= \"{$section_props}['rownum'] = {$section_props}['iteration'];\\n\";\n        $output .= \"{$section_props}['index_prev'] = {$section_props}['index'] - {$section_props}['step'];\\n\";\n        $output .= \"{$section_props}['index_next'] = {$section_props}['index'] + {$section_props}['step'];\\n\";\n        $output .= \"{$section_props}['first']      = ({$section_props}['iteration'] == 1);\\n\";\n        $output .= \"{$section_props}['last']       = ({$section_props}['iteration'] == {$section_props}['total']);\\n\";\n\n        $output .= \"?>\";\n\n        return $output;\n    }\n\n\n    /**\n     * Compile {foreach ...} tag.\n     *\n     * @param string $tag_args\n     * @return string\n     */\n    function _compile_foreach_start($tag_args)\n    {\n        $attrs = $this->_parse_attrs($tag_args);\n        $arg_list = array();\n\n        if (empty($attrs['from'])) {\n            return $this->_syntax_error(\"foreach: missing 'from' attribute\", E_USER_ERROR, __FILE__, __LINE__);\n        }\n        $from = $attrs['from'];\n\n        if (empty($attrs['item'])) {\n            return $this->_syntax_error(\"foreach: missing 'item' attribute\", E_USER_ERROR, __FILE__, __LINE__);\n        }\n        $item = $this->_dequote($attrs['item']);\n        if (!preg_match('~^\\w+$~', $item)) {\n            return $this->_syntax_error(\"foreach: 'item' must be a variable name (literal string)\", E_USER_ERROR, __FILE__, __LINE__);\n        }\n\n        if (isset($attrs['key'])) {\n            $key  = $this->_dequote($attrs['key']);\n            if (!preg_match('~^\\w+$~', $key)) {\n                return $this->_syntax_error(\"foreach: 'key' must to be a variable name (literal string)\", E_USER_ERROR, __FILE__, __LINE__);\n            }\n            $key_part = \"\\$this->_tpl_vars['$key'] => \";\n        } else {\n            $key = null;\n            $key_part = '';\n        }\n\n        if (isset($attrs['name'])) {\n            $name = $attrs['name'];\n        } else {\n            $name = null;\n        }\n\n        $output = '<?php ';\n        $output .= \"\\$_from = $from; if (!is_array(\\$_from) && !is_object(\\$_from)) { settype(\\$_from, 'array'); }\";\n        if (isset($name)) {\n            $foreach_props = \"\\$this->_foreach[$name]\";\n            $output .= \"{$foreach_props} = array('total' => count(\\$_from), 'iteration' => 0);\\n\";\n            $output .= \"if ({$foreach_props}['total'] > 0):\\n\";\n            $output .= \"    foreach (\\$_from as $key_part\\$this->_tpl_vars['$item']):\\n\";\n            $output .= \"        {$foreach_props}['iteration']++;\\n\";\n        } else {\n            $output .= \"if (count(\\$_from)):\\n\";\n            $output .= \"    foreach (\\$_from as $key_part\\$this->_tpl_vars['$item']):\\n\";\n        }\n        $output .= '?>';\n\n        return $output;\n    }\n\n\n    /**\n     * Compile {capture} .. {/capture} tags\n     *\n     * @param boolean $start true if this is the {capture} tag\n     * @param string $tag_args\n     * @return string\n     */\n\n    function _compile_capture_tag($start, $tag_args = '')\n    {\n        $attrs = $this->_parse_attrs($tag_args);\n\n        if ($start) {\n            $buffer = isset($attrs['name']) ? $attrs['name'] : \"'default'\";\n            $assign = isset($attrs['assign']) ? $attrs['assign'] : null;\n            $append = isset($attrs['append']) ? $attrs['append'] : null;\n            \n            $output = \"<?php ob_start(); ?>\";\n            $this->_capture_stack[] = array($buffer, $assign, $append);\n        } else {\n            list($buffer, $assign, $append) = array_pop($this->_capture_stack);\n            $output = \"<?php \\$this->_smarty_vars['capture'][$buffer] = ob_get_contents(); \";\n            if (isset($assign)) {\n                $output .= \" \\$this->assign($assign, ob_get_contents());\";\n            }\n            if (isset($append)) {\n                $output .= \" \\$this->append($append, ob_get_contents());\";\n            }\n            $output .= \"ob_end_clean(); ?>\";\n        }\n\n        return $output;\n    }\n\n    /**\n     * Compile {if ...} tag\n     *\n     * @param string $tag_args\n     * @param boolean $elseif if true, uses elseif instead of if\n     * @return string\n     */\n    function _compile_if_tag($tag_args, $elseif = false)\n    {\n\n        /* Tokenize args for 'if' tag. */\n        preg_match_all('~(?>\n                ' . $this->_obj_call_regexp . '(?:' . $this->_mod_regexp . '*)? | # valid object call\n                ' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)?    | # var or quoted string\n                \\-?0[xX][0-9a-fA-F]+|\\-?\\d+(?:\\.\\d+)?|\\.\\d+|!==|===|==|!=|<>|<<|>>|<=|>=|\\&\\&|\\|\\||\\(|\\)|,|\\!|\\^|=|\\&|\\~|<|>|\\||\\%|\\+|\\-|\\/|\\*|\\@    | # valid non-word token\n                \\b\\w+\\b                                                        | # valid word token\n                \\S+                                                           # anything else\n                )~x', $tag_args, $match);\n\n        $tokens = $match[0];\n\n        if(empty($tokens)) {\n            $_error_msg = $elseif ? \"'elseif'\" : \"'if'\";\n            $_error_msg .= ' statement requires arguments'; \n            $this->_syntax_error($_error_msg, E_USER_ERROR, __FILE__, __LINE__);\n        }\n            \n                \n        // make sure we have balanced parenthesis\n        $token_count = array_count_values($tokens);\n        if(isset($token_count['(']) && $token_count['('] != $token_count[')']) {\n            $this->_syntax_error(\"unbalanced parenthesis in if statement\", E_USER_ERROR, __FILE__, __LINE__);\n        }\n\n        $is_arg_stack = array();\n\n        for ($i = 0; $i < count($tokens); $i++) {\n\n            $token = &$tokens[$i];\n\n            switch (strtolower($token)) {\n                case '!':\n                case '%':\n                case '!==':\n                case '==':\n                case '===':\n                case '>':\n                case '<':\n                case '!=':\n                case '<>':\n                case '<<':\n                case '>>':\n                case '<=':\n                case '>=':\n                case '&&':\n                case '||':\n                case '|':\n                case '^':\n                case '&':\n                case '~':\n                case ')':\n                case ',':\n                case '+':\n                case '-':\n                case '*':\n                case '/':\n                case '@':\n                    break;\n\n                case 'eq':\n                    $token = '==';\n                    break;\n\n                case 'ne':\n                case 'neq':\n                    $token = '!=';\n                    break;\n\n                case 'lt':\n                    $token = '<';\n                    break;\n\n                case 'le':\n                case 'lte':\n                    $token = '<=';\n                    break;\n\n                case 'gt':\n                    $token = '>';\n                    break;\n\n                case 'ge':\n                case 'gte':\n                    $token = '>=';\n                    break;\n\n                case 'and':\n                    $token = '&&';\n                    break;\n\n                case 'or':\n                    $token = '||';\n                    break;\n\n                case 'not':\n                    $token = '!';\n                    break;\n\n                case 'mod':\n                    $token = '%';\n                    break;\n\n                case '(':\n                    array_push($is_arg_stack, $i);\n                    break;\n\n                case 'is':\n                    /* If last token was a ')', we operate on the parenthesized\n                       expression. The start of the expression is on the stack.\n                       Otherwise, we operate on the last encountered token. */\n                    if ($tokens[$i-1] == ')') {\n                        $is_arg_start = array_pop($is_arg_stack);\n                        if ($is_arg_start != 0) {\n                            if (preg_match('~^' . $this->_func_regexp . '$~', $tokens[$is_arg_start-1])) {\n                                $is_arg_start--;\n                            } \n                        } \n                    } else\n                        $is_arg_start = $i-1;\n                    /* Construct the argument for 'is' expression, so it knows\n                       what to operate on. */\n                    $is_arg = implode(' ', array_slice($tokens, $is_arg_start, $i - $is_arg_start));\n\n                    /* Pass all tokens from next one until the end to the\n                       'is' expression parsing function. The function will\n                       return modified tokens, where the first one is the result\n                       of the 'is' expression and the rest are the tokens it\n                       didn't touch. */\n                    $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1));\n\n                    /* Replace the old tokens with the new ones. */\n                    array_splice($tokens, $is_arg_start, count($tokens), $new_tokens);\n\n                    /* Adjust argument start so that it won't change from the\n                       current position for the next iteration. */\n                    $i = $is_arg_start;\n                    break;\n\n                default:\n                    if(preg_match('~^' . $this->_func_regexp . '$~', $token) ) {\n                            // function call\n                            if($this->security &&\n                               !in_array($token, $this->security_settings['IF_FUNCS'])) {\n                                $this->_syntax_error(\"(secure mode) '$token' not allowed in if statement\", E_USER_ERROR, __FILE__, __LINE__);\n                            }\n                    } elseif(preg_match('~^' . $this->_var_regexp . '$~', $token) && (strpos('+-*/^%&|', substr($token, -1)) === false) && isset($tokens[$i+1]) && $tokens[$i+1] == '(') {\n                        // variable function call\n                        $this->_syntax_error(\"variable function call '$token' not allowed in if statement\", E_USER_ERROR, __FILE__, __LINE__);                      \n                    } elseif(preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)$~', $token)) {\n                        // object or variable\n                        $token = $this->_parse_var_props($token);\n                    } elseif(is_numeric($token)) {\n                        // number, skip it\n                    } else {\n                        $this->_syntax_error(\"unidentified token '$token'\", E_USER_ERROR, __FILE__, __LINE__);\n                    }\n                    break;\n            }\n        }\n\n        if ($elseif)\n            return '<?php elseif ('.implode(' ', $tokens).'): ?>';\n        else\n            return '<?php if ('.implode(' ', $tokens).'): ?>';\n    }\n\n\n    function _compile_arg_list($type, $name, $attrs, &$cache_code) {\n        $arg_list = array();\n\n        if (isset($type) && isset($name)\n            && isset($this->_plugins[$type])\n            && isset($this->_plugins[$type][$name])\n            && empty($this->_plugins[$type][$name][4])\n            && is_array($this->_plugins[$type][$name][5])\n            ) {\n            /* we have a list of parameters that should be cached */\n            $_cache_attrs = $this->_plugins[$type][$name][5];\n            $_count = $this->_cache_attrs_count++;\n            $cache_code = \"\\$_cache_attrs =& \\$this->_smarty_cache_attrs('$this->_cache_serial','$_count');\";\n\n        } else {\n            /* no parameters are cached */\n            $_cache_attrs = null;\n        }\n\n        foreach ($attrs as $arg_name => $arg_value) {\n            if (is_bool($arg_value))\n                $arg_value = $arg_value ? 'true' : 'false';\n            if (is_null($arg_value))\n                $arg_value = 'null';\n            if ($_cache_attrs && in_array($arg_name, $_cache_attrs)) {\n                $arg_list[] = \"'$arg_name' => (\\$this->_cache_including) ? \\$_cache_attrs['$arg_name'] : (\\$_cache_attrs['$arg_name']=$arg_value)\";\n            } else {\n                $arg_list[] = \"'$arg_name' => $arg_value\";\n            }\n        }\n        return $arg_list;\n    }\n\n    /**\n     * Parse is expression\n     *\n     * @param string $is_arg\n     * @param array $tokens\n     * @return array\n     */\n    function _parse_is_expr($is_arg, $tokens)\n    {\n        $expr_end = 0;\n        $negate_expr = false;\n\n        if (($first_token = array_shift($tokens)) == 'not') {\n            $negate_expr = true;\n            $expr_type = array_shift($tokens);\n        } else\n            $expr_type = $first_token;\n\n        switch ($expr_type) {\n            case 'even':\n                if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') {\n                    $expr_end++;\n                    $expr_arg = $tokens[$expr_end++];\n                    $expr = \"!(1 & ($is_arg / \" . $this->_parse_var_props($expr_arg) . \"))\";\n                } else\n                    $expr = \"!(1 & $is_arg)\";\n                break;\n\n            case 'odd':\n                if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') {\n                    $expr_end++;\n                    $expr_arg = $tokens[$expr_end++];\n                    $expr = \"(1 & ($is_arg / \" . $this->_parse_var_props($expr_arg) . \"))\";\n                } else\n                    $expr = \"(1 & $is_arg)\";\n                break;\n\n            case 'div':\n                if (@$tokens[$expr_end] == 'by') {\n                    $expr_end++;\n                    $expr_arg = $tokens[$expr_end++];\n                    $expr = \"!($is_arg % \" . $this->_parse_var_props($expr_arg) . \")\";\n                } else {\n                    $this->_syntax_error(\"expecting 'by' after 'div'\", E_USER_ERROR, __FILE__, __LINE__);\n                }\n                break;\n\n            default:\n                $this->_syntax_error(\"unknown 'is' expression - '$expr_type'\", E_USER_ERROR, __FILE__, __LINE__);\n                break;\n        }\n\n        if ($negate_expr) {\n            $expr = \"!($expr)\";\n        }\n\n        array_splice($tokens, 0, $expr_end, $expr);\n\n        return $tokens;\n    }\n\n\n    /**\n     * Parse attribute string\n     *\n     * @param string $tag_args\n     * @return array\n     */\n    function _parse_attrs($tag_args)\n    {\n\n        /* Tokenize tag attributes. */\n        preg_match_all('~(?:' . $this->_obj_call_regexp . '|' . $this->_qstr_regexp . ' | (?>[^\"\\'=\\s]+)\n                         )+ |\n                         [=]\n                        ~x', $tag_args, $match);\n        $tokens       = $match[0];\n\n        $attrs = array();\n        /* Parse state:\n            0 - expecting attribute name\n            1 - expecting '='\n            2 - expecting attribute value (not '=') */\n        $state = 0;\n\n        foreach ($tokens as $token) {\n            switch ($state) {\n                case 0:\n                    /* If the token is a valid identifier, we set attribute name\n                       and go to state 1. */\n                    if (preg_match('~^\\w+$~', $token)) {\n                        $attr_name = $token;\n                        $state = 1;\n                    } else\n                        $this->_syntax_error(\"invalid attribute name: '$token'\", E_USER_ERROR, __FILE__, __LINE__);\n                    break;\n\n                case 1:\n                    /* If the token is '=', then we go to state 2. */\n                    if ($token == '=') {\n                        $state = 2;\n                    } else\n                        $this->_syntax_error(\"expecting '=' after attribute name '$last_token'\", E_USER_ERROR, __FILE__, __LINE__);\n                    break;\n\n                case 2:\n                    /* If token is not '=', we set the attribute value and go to\n                       state 0. */\n                    if ($token != '=') {\n                        /* We booleanize the token if it's a non-quoted possible\n                           boolean value. */\n                        if (preg_match('~^(on|yes|true)$~', $token)) {\n                            $token = 'true';\n                        } else if (preg_match('~^(off|no|false)$~', $token)) {\n                            $token = 'false';\n                        } else if ($token == 'null') {\n                            $token = 'null';\n                        } else if (preg_match('~^' . $this->_num_const_regexp . '|0[xX][0-9a-fA-F]+$~', $token)) {\n                            /* treat integer literally */\n                        } else if (!preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . ')*$~', $token)) {\n                            /* treat as a string, double-quote it escaping quotes */\n                            $token = '\"'.addslashes($token).'\"';\n                        }\n\n                        $attrs[$attr_name] = $token;\n                        $state = 0;\n                    } else\n                        $this->_syntax_error(\"'=' cannot be an attribute value\", E_USER_ERROR, __FILE__, __LINE__);\n                    break;\n            }\n            $last_token = $token;\n        }\n\n        if($state != 0) {\n            if($state == 1) {\n                $this->_syntax_error(\"expecting '=' after attribute name '$last_token'\", E_USER_ERROR, __FILE__, __LINE__);\n            } else {\n                $this->_syntax_error(\"missing attribute value\", E_USER_ERROR, __FILE__, __LINE__);\n            }\n        }\n\n        $this->_parse_vars_props($attrs);\n\n        return $attrs;\n    }\n\n    /**\n     * compile multiple variables and section properties tokens into\n     * PHP code\n     *\n     * @param array $tokens\n     */\n    function _parse_vars_props(&$tokens)\n    {\n        foreach($tokens as $key => $val) {\n            $tokens[$key] = $this->_parse_var_props($val);\n        }\n    }\n\n    /**\n     * compile single variable and section properties token into\n     * PHP code\n     *\n     * @param string $val\n     * @param string $tag_attrs\n     * @return string\n     */\n    function _parse_var_props($val)\n    {\n        $val = trim($val);\n\n        if(preg_match('~^(' . $this->_obj_call_regexp . '|' . $this->_dvar_regexp . ')(' . $this->_mod_regexp . '*)$~', $val, $match)) {\n            // $ variable or object\n            $return = $this->_parse_var($match[1]);\n            $modifiers = $match[2];\n            if (!empty($this->default_modifiers) && !preg_match('~(^|\\|)smarty:nodefaults($|\\|)~',$modifiers)) {\n                $_default_mod_string = implode('|',(array)$this->default_modifiers);\n                $modifiers = empty($modifiers) ? $_default_mod_string : $_default_mod_string . '|' . $modifiers;\n            }\n            $this->_parse_modifiers($return, $modifiers);\n            return $return;\n        } elseif (preg_match('~^' . $this->_db_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {\n                // double quoted text\n                preg_match('~^(' . $this->_db_qstr_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);\n                $return = $this->_expand_quoted_text($match[1]);\n                if($match[2] != '') {\n                    $this->_parse_modifiers($return, $match[2]);\n                }\n                return $return;\n            }\n        elseif(preg_match('~^' . $this->_num_const_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {\n                // numerical constant\n                preg_match('~^(' . $this->_num_const_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);\n                if($match[2] != '') {\n                    $this->_parse_modifiers($match[1], $match[2]);\n                    return $match[1];\n                }\n            }\n        elseif(preg_match('~^' . $this->_si_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {\n                // single quoted text\n                preg_match('~^(' . $this->_si_qstr_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);\n                if($match[2] != '') {\n                    $this->_parse_modifiers($match[1], $match[2]);\n                    return $match[1];\n                }\n            }\n        elseif(preg_match('~^' . $this->_cvar_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {\n                // config var\n                return $this->_parse_conf_var($val);\n            }\n        elseif(preg_match('~^' . $this->_svar_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {\n                // section var\n                return $this->_parse_section_prop($val);\n            }\n        elseif(!in_array($val, $this->_permitted_tokens) && !is_numeric($val)) {\n            // literal string\n            return $this->_expand_quoted_text('\"' . strtr($val, array('\\\\' => '\\\\\\\\', '\"' => '\\\\\"')) .'\"');\n        }\n        return $val;\n    }\n\n    /**\n     * expand quoted text with embedded variables\n     *\n     * @param string $var_expr\n     * @return string\n     */\n    function _expand_quoted_text($var_expr)\n    {\n        // if contains unescaped $, expand it\n        if(preg_match_all('~(?:\\`(?<!\\\\\\\\)\\$' . $this->_dvar_guts_regexp . '(?:' . $this->_obj_ext_regexp . ')*\\`)|(?:(?<!\\\\\\\\)\\$\\w+(\\[[a-zA-Z0-9]+\\])*)~', $var_expr, $_match)) {\n            $_match = $_match[0];\n            $_replace = array();\n            foreach($_match as $_var) {\n                $_replace[$_var] = '\".(' . $this->_parse_var(str_replace('`','',$_var)) . ').\"';\n            }\n            $var_expr = strtr($var_expr, $_replace);\n            $_return = preg_replace('~\\.\"\"|(?<!\\\\\\\\)\"\"\\.~', '', $var_expr);\n        } else {\n            $_return = $var_expr;\n        }\n        // replace double quoted literal string with single quotes\n        $_return = preg_replace('~^\"([\\s\\w]+)\"$~',\"'\\\\1'\",$_return);\n        return $_return;\n    }\n\n    /**\n     * parse variable expression into PHP code\n     *\n     * @param string $var_expr\n     * @param string $output\n     * @return string\n     */\n    function _parse_var($var_expr)\n    {\n        $_has_math = false;\n        $_math_vars = preg_split('~('.$this->_dvar_math_regexp.'|'.$this->_qstr_regexp.')~', $var_expr, -1, PREG_SPLIT_DELIM_CAPTURE);\n\n        if(count($_math_vars) > 1) {\n            $_first_var = \"\";\n            $_complete_var = \"\";\n            $_output = \"\";\n            // simple check if there is any math, to stop recursion (due to modifiers with \"xx % yy\" as parameter)\n            foreach($_math_vars as $_k => $_math_var) {\n                $_math_var = $_math_vars[$_k];\n\n                if(!empty($_math_var) || is_numeric($_math_var)) {\n                    // hit a math operator, so process the stuff which came before it\n                    if(preg_match('~^' . $this->_dvar_math_regexp . '$~', $_math_var)) {\n                        $_has_math = true;\n                        if(!empty($_complete_var) || is_numeric($_complete_var)) {\n                            $_output .= $this->_parse_var($_complete_var);\n                        }\n\n                        // just output the math operator to php\n                        $_output .= $_math_var;\n\n                        if(empty($_first_var))\n                            $_first_var = $_complete_var;\n\n                        $_complete_var = \"\";\n                    } else {\n                        $_complete_var .= $_math_var;\n                    }\n                }\n            }\n            if($_has_math) {\n                if(!empty($_complete_var) || is_numeric($_complete_var))\n                    $_output .= $this->_parse_var($_complete_var);\n\n                // get the modifiers working (only the last var from math + modifier is left)\n                $var_expr = $_complete_var;\n            }\n        }\n\n        // prevent cutting of first digit in the number (we _definitly_ got a number if the first char is a digit)\n        if(is_numeric(substr($var_expr, 0, 1)))\n            $_var_ref = $var_expr;\n        else\n            $_var_ref = substr($var_expr, 1);\n        \n        if(!$_has_math) {\n            \n            // get [foo] and .foo and ->foo and (...) pieces\n            preg_match_all('~(?:^\\w+)|' . $this->_obj_params_regexp . '|(?:' . $this->_var_bracket_regexp . ')|->\\$?\\w+|\\.\\$?\\w+|\\S+~', $_var_ref, $match);\n                        \n            $_indexes = $match[0];\n            $_var_name = array_shift($_indexes);\n\n            /* Handle $smarty.* variable references as a special case. */\n            if ($_var_name == 'smarty') {\n                /*\n                 * If the reference could be compiled, use the compiled output;\n                 * otherwise, fall back on the $smarty variable generated at\n                 * run-time.\n                 */\n                if (($smarty_ref = $this->_compile_smarty_ref($_indexes)) !== null) {\n                    $_output = $smarty_ref;\n                } else {\n                    $_var_name = substr(array_shift($_indexes), 1);\n                    $_output = \"\\$this->_smarty_vars['$_var_name']\";\n                }\n            } elseif(is_numeric($_var_name) && is_numeric(substr($var_expr, 0, 1))) {\n                // because . is the operator for accessing arrays thru inidizes we need to put it together again for floating point numbers\n                if(count($_indexes) > 0)\n                {\n                    $_var_name .= implode(\"\", $_indexes);\n                    $_indexes = array();\n                }\n                $_output = $_var_name;\n            } else {\n                $_output = \"\\$this->_tpl_vars['$_var_name']\";\n            }\n\n            foreach ($_indexes as $_index) {\n                if (substr($_index, 0, 1) == '[') {\n                    $_index = substr($_index, 1, -1);\n                    if (is_numeric($_index)) {\n                        $_output .= \"[$_index]\";\n                    } elseif (substr($_index, 0, 1) == '$') {\n                        if (strpos($_index, '.') !== false) {\n                            $_output .= '[' . $this->_parse_var($_index) . ']';\n                        } else {\n                            $_output .= \"[\\$this->_tpl_vars['\" . substr($_index, 1) . \"']]\";\n                        }\n                    } else {\n                        $_var_parts = explode('.', $_index);\n                        $_var_section = $_var_parts[0];\n                        $_var_section_prop = isset($_var_parts[1]) ? $_var_parts[1] : 'index';\n                        $_output .= \"[\\$this->_sections['$_var_section']['$_var_section_prop']]\";\n                    }\n                } else if (substr($_index, 0, 1) == '.') {\n                    if (substr($_index, 1, 1) == '$')\n                        $_output .= \"[\\$this->_tpl_vars['\" . substr($_index, 2) . \"']]\";\n                    else\n                        $_output .= \"['\" . substr($_index, 1) . \"']\";\n                } else if (substr($_index,0,2) == '->') {\n                    if(substr($_index,2,2) == '__') {\n                        $this->_syntax_error('call to internal object members is not allowed', E_USER_ERROR, __FILE__, __LINE__);\n                    } elseif($this->security && substr($_index, 2, 1) == '_') {\n                        $this->_syntax_error('(secure) call to private object member is not allowed', E_USER_ERROR, __FILE__, __LINE__);\n                    } elseif (substr($_index, 2, 1) == '$') {\n                        if ($this->security) {\n                            $this->_syntax_error('(secure) call to dynamic object member is not allowed', E_USER_ERROR, __FILE__, __LINE__);\n                        } else {\n                            $_output .= '->{(($_var=$this->_tpl_vars[\\''.substr($_index,3).'\\']) && substr($_var,0,2)!=\\'__\\') ? $_var : $this->trigger_error(\"cannot access property \\\\\"$_var\\\\\"\")}';\n                        }\n                    } else {\n                        $_output .= $_index;\n                    }\n                } elseif (substr($_index, 0, 1) == '(') {\n                    $_index = $this->_parse_parenth_args($_index);\n                    $_output .= $_index;\n                } else {\n                    $_output .= $_index;\n                }\n            }\n        }\n\n        return $_output;\n    }\n\n    /**\n     * parse arguments in function call parenthesis\n     *\n     * @param string $parenth_args\n     * @return string\n     */\n    function _parse_parenth_args($parenth_args)\n    {\n        preg_match_all('~' . $this->_param_regexp . '~',$parenth_args, $match);\n        $orig_vals = $match = $match[0];\n        $this->_parse_vars_props($match);\n        $replace = array();\n        for ($i = 0, $count = count($match); $i < $count; $i++) {\n            $replace[$orig_vals[$i]] = $match[$i];\n        }\n        return strtr($parenth_args, $replace);\n    }\n\n    /**\n     * parse configuration variable expression into PHP code\n     *\n     * @param string $conf_var_expr\n     */\n    function _parse_conf_var($conf_var_expr)\n    {\n        $parts = explode('|', $conf_var_expr, 2);\n        $var_ref = $parts[0];\n        $modifiers = isset($parts[1]) ? $parts[1] : '';\n\n        $var_name = substr($var_ref, 1, -1);\n\n        $output = \"\\$this->_config[0]['vars']['$var_name']\";\n\n        $this->_parse_modifiers($output, $modifiers);\n\n        return $output;\n    }\n\n    /**\n     * parse section property expression into PHP code\n     *\n     * @param string $section_prop_expr\n     * @return string\n     */\n    function _parse_section_prop($section_prop_expr)\n    {\n        $parts = explode('|', $section_prop_expr, 2);\n        $var_ref = $parts[0];\n        $modifiers = isset($parts[1]) ? $parts[1] : '';\n\n        preg_match('!%(\\w+)\\.(\\w+)%!', $var_ref, $match);\n        $section_name = $match[1];\n        $prop_name = $match[2];\n\n        $output = \"\\$this->_sections['$section_name']['$prop_name']\";\n\n        $this->_parse_modifiers($output, $modifiers);\n\n        return $output;\n    }\n\n\n    /**\n     * parse modifier chain into PHP code\n     *\n     * sets $output to parsed modified chain\n     * @param string $output\n     * @param string $modifier_string\n     */\n    function _parse_modifiers(&$output, $modifier_string)\n    {\n        preg_match_all('~\\|(@?\\w+)((?>:(?:'. $this->_qstr_regexp . '|[^|]+))*)~', '|' . $modifier_string, $_match);\n        list(, $_modifiers, $modifier_arg_strings) = $_match;\n\n        for ($_i = 0, $_for_max = count($_modifiers); $_i < $_for_max; $_i++) {\n            $_modifier_name = $_modifiers[$_i];\n\n            if($_modifier_name == 'smarty') {\n                // skip smarty modifier\n                continue;\n            }\n\n            preg_match_all('~:(' . $this->_qstr_regexp . '|[^:]+)~', $modifier_arg_strings[$_i], $_match);\n            $_modifier_args = $_match[1];\n\n            if (substr($_modifier_name, 0, 1) == '@') {\n                $_map_array = false;\n                $_modifier_name = substr($_modifier_name, 1);\n            } else {\n                $_map_array = true;\n            }\n\n            if (empty($this->_plugins['modifier'][$_modifier_name])\n                && !$this->_get_plugin_filepath('modifier', $_modifier_name)\n                && function_exists($_modifier_name)) {\n                if ($this->security && !in_array($_modifier_name, $this->security_settings['MODIFIER_FUNCS'])) {\n                    $this->_trigger_fatal_error(\"[plugin] (secure mode) modifier '$_modifier_name' is not allowed\" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);\n                } else {\n                    $this->_plugins['modifier'][$_modifier_name] = array($_modifier_name,  null, null, false);\n                }\n            }\n            $this->_add_plugin('modifier', $_modifier_name);\n\n            $this->_parse_vars_props($_modifier_args);\n\n            if($_modifier_name == 'default') {\n                // supress notifications of default modifier vars and args\n                if(substr($output, 0, 1) == '$') {\n                    $output = '@' . $output;\n                }\n                if(isset($_modifier_args[0]) && substr($_modifier_args[0], 0, 1) == '$') {\n                    $_modifier_args[0] = '@' . $_modifier_args[0];\n                }\n            }\n            if (count($_modifier_args) > 0)\n                $_modifier_args = ', '.implode(', ', $_modifier_args);\n            else\n                $_modifier_args = '';\n\n            if ($_map_array) {\n                $output = \"((is_array(\\$_tmp=$output)) ? \\$this->_run_mod_handler('$_modifier_name', true, \\$_tmp$_modifier_args) : \" . $this->_compile_plugin_call('modifier', $_modifier_name) . \"(\\$_tmp$_modifier_args))\";\n\n            } else {\n\n                $output = $this->_compile_plugin_call('modifier', $_modifier_name).\"($output$_modifier_args)\";\n\n            }\n        }\n    }\n\n\n    /**\n     * add plugin\n     *\n     * @param string $type\n     * @param string $name\n     * @param boolean? $delayed_loading\n     */\n    function _add_plugin($type, $name, $delayed_loading = null)\n    {\n        if (!isset($this->_plugin_info[$type])) {\n            $this->_plugin_info[$type] = array();\n        }\n        if (!isset($this->_plugin_info[$type][$name])) {\n            $this->_plugin_info[$type][$name] = array($this->_current_file,\n                                                      $this->_current_line_no,\n                                                      $delayed_loading);\n        }\n    }\n\n\n    /**\n     * Compiles references of type $smarty.foo\n     *\n     * @param string $indexes\n     * @return string\n     */\n    function _compile_smarty_ref(&$indexes)\n    {\n        /* Extract the reference name. */\n        $_ref = substr($indexes[0], 1);\n        foreach($indexes as $_index_no=>$_index) {\n            if (substr($_index, 0, 1) != '.' && $_index_no<2 || !preg_match('~^(\\.|\\[|->)~', $_index)) {\n                $this->_syntax_error('$smarty' . implode('', array_slice($indexes, 0, 2)) . ' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__);\n            }\n        }\n\n        switch ($_ref) {\n            case 'now':\n                $compiled_ref = 'time()';\n                $_max_index = 1;\n                break;\n\n            case 'foreach':\n                array_shift($indexes);\n                $_var = $this->_parse_var_props(substr($indexes[0], 1));\n                $_propname = substr($indexes[1], 1);\n                $_max_index = 1;\n                switch ($_propname) {\n                    case 'index':\n                        array_shift($indexes);\n                        $compiled_ref = \"(\\$this->_foreach[$_var]['iteration']-1)\";\n                        break;\n                        \n                    case 'first':\n                        array_shift($indexes);\n                        $compiled_ref = \"(\\$this->_foreach[$_var]['iteration'] <= 1)\";\n                        break;\n\n                    case 'last':\n                        array_shift($indexes);\n                        $compiled_ref = \"(\\$this->_foreach[$_var]['iteration'] == \\$this->_foreach[$_var]['total'])\";\n                        break;\n                        \n                    case 'show':\n                        array_shift($indexes);\n                        $compiled_ref = \"(\\$this->_foreach[$_var]['total'] > 0)\";\n                        break;\n                        \n                    default:\n                        unset($_max_index);\n                        $compiled_ref = \"\\$this->_foreach[$_var]\";\n                }\n                break;\n\n            case 'section':\n                array_shift($indexes);\n                $_var = $this->_parse_var_props(substr($indexes[0], 1));\n                $compiled_ref = \"\\$this->_sections[$_var]\";\n                break;\n\n            case 'get':\n                if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {\n                    $this->_syntax_error(\"(secure mode) super global access not permitted\",\n                                         E_USER_WARNING, __FILE__, __LINE__);\n                    return;\n                }\n                $compiled_ref = \"\\$_GET\";\n                break;\n\n            case 'post':\n                if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {\n                    $this->_syntax_error(\"(secure mode) super global access not permitted\",\n                                         E_USER_WARNING, __FILE__, __LINE__);\n                    return;\n                }\n                $compiled_ref = \"\\$_POST\";\n                break;\n\n            case 'cookies':\n                if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {\n                    $this->_syntax_error(\"(secure mode) super global access not permitted\",\n                                         E_USER_WARNING, __FILE__, __LINE__);\n                    return;\n                }\n                $compiled_ref = \"\\$_COOKIE\";\n                break;\n\n            case 'env':\n                if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {\n                    $this->_syntax_error(\"(secure mode) super global access not permitted\",\n                                         E_USER_WARNING, __FILE__, __LINE__);\n                    return;\n                }\n                $compiled_ref = \"\\$_ENV\";\n                break;\n\n            case 'server':\n                if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {\n                    $this->_syntax_error(\"(secure mode) super global access not permitted\",\n                                         E_USER_WARNING, __FILE__, __LINE__);\n                    return;\n                }\n                $compiled_ref = \"\\$_SERVER\";\n                break;\n\n            case 'session':\n                if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {\n                    $this->_syntax_error(\"(secure mode) super global access not permitted\",\n                                         E_USER_WARNING, __FILE__, __LINE__);\n                    return;\n                }\n                $compiled_ref = \"\\$_SESSION\";\n                break;\n\n            /*\n             * These cases are handled either at run-time or elsewhere in the\n             * compiler.\n             */\n            case 'request':\n                if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {\n                    $this->_syntax_error(\"(secure mode) super global access not permitted\",\n                                         E_USER_WARNING, __FILE__, __LINE__);\n                    return;\n                }\n                if ($this->request_use_auto_globals) {\n                    $compiled_ref = \"\\$_REQUEST\";\n                    break;\n                } else {\n                    $this->_init_smarty_vars = true;\n                }\n                return null;\n\n            case 'capture':\n                return null;\n\n            case 'template':\n                $compiled_ref = \"'\" . addslashes($this->_current_file) . \"'\";\n                $_max_index = 1;\n                break;\n\n            case 'version':\n                $compiled_ref = \"'$this->_version'\";\n                $_max_index = 1;\n                break;\n\n            case 'const':\n                if ($this->security && !$this->security_settings['ALLOW_CONSTANTS']) {\n                    $this->_syntax_error(\"(secure mode) constants not permitted\",\n                                         E_USER_WARNING, __FILE__, __LINE__);\n                    return;\n                }\n                array_shift($indexes);\n                if (preg_match('!^\\.\\w+$!', $indexes[0])) {\n                    $compiled_ref = '@' . substr($indexes[0], 1);\n                } else {\n                    $_val = $this->_parse_var_props(substr($indexes[0], 1));\n                    $compiled_ref = '@constant(' . $_val . ')';\n                }\n                $_max_index = 1;\n                break;\n\n            case 'config':\n                $compiled_ref = \"\\$this->_config[0]['vars']\";\n                $_max_index = 3;\n                break;\n\n            case 'ldelim':\n                $compiled_ref = \"'$this->left_delimiter'\";\n                break;\n\n            case 'rdelim':\n                $compiled_ref = \"'$this->right_delimiter'\";\n                break;\n                \n            default:\n                $this->_syntax_error('$smarty.' . $_ref . ' is an unknown reference', E_USER_ERROR, __FILE__, __LINE__);\n                break;\n        }\n\n        if (isset($_max_index) && count($indexes) > $_max_index) {\n            $this->_syntax_error('$smarty' . implode('', $indexes) .' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__);\n        }\n\n        array_shift($indexes);\n        return $compiled_ref;\n    }\n\n    /**\n     * compiles call to plugin of type $type with name $name\n     * returns a string containing the function-name or method call\n     * without the paramter-list that would have follow to make the\n     * call valid php-syntax\n     *\n     * @param string $type\n     * @param string $name\n     * @return string\n     */\n    function _compile_plugin_call($type, $name) {\n        if (isset($this->_plugins[$type][$name])) {\n            /* plugin loaded */\n            if (is_array($this->_plugins[$type][$name][0])) {\n                return ((is_object($this->_plugins[$type][$name][0][0])) ?\n                        \"\\$this->_plugins['$type']['$name'][0][0]->\"    /* method callback */\n                        : (string)($this->_plugins[$type][$name][0][0]).'::'    /* class callback */\n                       ). $this->_plugins[$type][$name][0][1];\n\n            } else {\n                /* function callback */\n                return $this->_plugins[$type][$name][0];\n\n            }\n        } else {\n            /* plugin not loaded -> auto-loadable-plugin */\n            return 'smarty_'.$type.'_'.$name;\n\n        }\n    }\n\n    /**\n     * load pre- and post-filters\n     */\n    function _load_filters()\n    {\n        if (count($this->_plugins['prefilter']) > 0) {\n            foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) {\n                if ($prefilter === false) {\n                    unset($this->_plugins['prefilter'][$filter_name]);\n                    $_params = array('plugins' => array(array('prefilter', $filter_name, null, null, false)));\n                    require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');\n                    smarty_core_load_plugins($_params, $this);\n                }\n            }\n        }\n        if (count($this->_plugins['postfilter']) > 0) {\n            foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) {\n                if ($postfilter === false) {\n                    unset($this->_plugins['postfilter'][$filter_name]);\n                    $_params = array('plugins' => array(array('postfilter', $filter_name, null, null, false)));\n                    require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');\n                    smarty_core_load_plugins($_params, $this);\n                }\n            }\n        }\n    }\n\n\n    /**\n     * Quote subpattern references\n     *\n     * @param string $string\n     * @return string\n     */\n    function _quote_replace($string)\n    {\n        return strtr($string, array('\\\\' => '\\\\\\\\', '$' => '\\\\$'));\n    }\n\n    /**\n     * display Smarty syntax error\n     *\n     * @param string $error_msg\n     * @param integer $error_type\n     * @param string $file\n     * @param integer $line\n     */\n    function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=null, $line=null)\n    {\n        $this->_trigger_fatal_error(\"syntax error: $error_msg\", $this->_current_file, $this->_current_line_no, $file, $line, $error_type);\n    }\n\n\n    /**\n     * check if the compilation changes from cacheable to\n     * non-cacheable state with the beginning of the current\n     * plugin. return php-code to reflect the transition.\n     * @return string\n     */\n    function _push_cacheable_state($type, $name) {\n        $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4];\n        if ($_cacheable\n            || 0<$this->_cacheable_state++) return '';\n        if (!isset($this->_cache_serial)) $this->_cache_serial = md5(uniqid('Smarty'));\n        $_ret = 'if ($this->caching && !$this->_cache_including): echo \\'{nocache:'\n            . $this->_cache_serial . '#' . $this->_nocache_count\n            . '}\\'; endif;';\n        return $_ret;\n    }\n\n\n    /**\n     * check if the compilation changes from non-cacheable to\n     * cacheable state with the end of the current plugin return\n     * php-code to reflect the transition.\n     * @return string\n     */\n    function _pop_cacheable_state($type, $name) {\n        $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4];\n        if ($_cacheable\n            || --$this->_cacheable_state>0) return '';\n        return 'if ($this->caching && !$this->_cache_including): echo \\'{/nocache:'\n            . $this->_cache_serial . '#' . ($this->_nocache_count++)\n            . '}\\'; endif;';\n    }\n\n\n    /**\n     * push opening tag-name, file-name and line-number on the tag-stack\n     * @param string the opening tag's name\n     */\n    function _push_tag($open_tag)\n    {\n        array_push($this->_tag_stack, array($open_tag, $this->_current_line_no));\n    }\n\n    /**\n     * pop closing tag-name\n     * raise an error if this stack-top doesn't match with the closing tag\n     * @param string the closing tag's name\n     * @return string the opening tag's name\n     */\n    function _pop_tag($close_tag)\n    {\n        $message = '';\n        if (count($this->_tag_stack)>0) {\n            list($_open_tag, $_line_no) = array_pop($this->_tag_stack);\n            if ($close_tag == $_open_tag) {\n                return $_open_tag;\n            }\n            if ($close_tag == 'if' && ($_open_tag == 'else' || $_open_tag == 'elseif' )) {\n                return $this->_pop_tag($close_tag);\n            }\n            if ($close_tag == 'section' && $_open_tag == 'sectionelse') {\n                $this->_pop_tag($close_tag);\n                return $_open_tag;\n            }\n            if ($close_tag == 'foreach' && $_open_tag == 'foreachelse') {\n                $this->_pop_tag($close_tag);\n                return $_open_tag;\n            }\n            if ($_open_tag == 'else' || $_open_tag == 'elseif') {\n                $_open_tag = 'if';\n            } elseif ($_open_tag == 'sectionelse') {\n                $_open_tag = 'section';\n            } elseif ($_open_tag == 'foreachelse') {\n                $_open_tag = 'foreach';\n            }\n            $message = \" expected {/$_open_tag} (opened line $_line_no).\";\n        }\n        $this->_syntax_error(\"mismatched tag {/$close_tag}.$message\",\n                             E_USER_ERROR, __FILE__, __LINE__);\n    }\n\n}\n\n/**\n * compare to values by their string length\n *\n * @access private\n * @param string $a\n * @param string $b\n * @return 0|-1|1\n */\nfunction _smarty_sort_length($a, $b)\n{\n    if($a == $b)\n        return 0;\n\n    if(strlen($a) == strlen($b))\n        return ($a > $b) ? -1 : 1;\n\n    return (strlen($a) > strlen($b)) ? -1 : 1;\n}\n\n\n/* vim: set et: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/debug.tpl",
    "content": "{* Smarty *}\n{* debug.tpl, last updated version 2.1.0 *}\n{assign_debug_info}\n{capture assign=debug_output}\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n<head>\n    <title>Smarty Debug Console</title>\n{literal}\n<style type=\"text/css\">\n/* <![CDATA[ */\nbody, h1, h2, td, th, p {\n    font-family: sans-serif;\n    font-weight: normal;\n    font-size: 0.9em;\n    margin: 1px;\n    padding: 0;\n}\n\nh1 {\n    margin: 0;\n    text-align: left;\n    padding: 2px;\n    background-color: #f0c040;\n    color:  black;\n    font-weight: bold;\n    font-size: 1.2em;\n }\n\nh2 {\n    background-color: #9B410E;\n    color: white;\n    text-align: left;\n    font-weight: bold;\n    padding: 2px;\n    border-top: 1px solid black;\n}\n\nbody {\n    background: black; \n}\n\np, table, div {\n    background: #f0ead8;\n} \n\np {\n    margin: 0;\n    font-style: italic;\n    text-align: center;\n}\n\ntable {\n    width: 100%;\n}\n\nth, td {\n    font-family: monospace;\n    vertical-align: top;\n    text-align: left;\n    width: 50%;\n}\n\ntd {\n    color: green;\n}\n\n.odd {\n    background-color: #eeeeee;\n}\n\n.even {\n    background-color: #fafafa;\n}\n\n.exectime {\n    font-size: 0.8em;\n    font-style: italic;\n}\n\n#table_assigned_vars th {\n    color: blue;\n}\n\n#table_config_vars th {\n    color: maroon;\n}\n/* ]]> */\n</style>\n{/literal}\n</head>\n<body>\n\n<h1>Smarty Debug Console</h1>\n\n<h2>included templates &amp; config files (load time in seconds)</h2>\n\n<div>\n{section name=templates loop=$_debug_tpls}\n    {section name=indent loop=$_debug_tpls[templates].depth}&nbsp;&nbsp;&nbsp;{/section}\n    <font color={if $_debug_tpls[templates].type eq \"template\"}brown{elseif $_debug_tpls[templates].type eq \"insert\"}black{else}green{/if}>\n        {$_debug_tpls[templates].filename|escape:html}</font>\n    {if isset($_debug_tpls[templates].exec_time)}\n        <span class=\"exectime\">\n        ({$_debug_tpls[templates].exec_time|string_format:\"%.5f\"})\n        {if %templates.index% eq 0}(total){/if}\n        </span>\n    {/if}\n    <br />\n{sectionelse}\n    <p>no templates included</p>\n{/section}\n</div>\n\n<h2>assigned template variables</h2>\n\n<table id=\"table_assigned_vars\">\n    {section name=vars loop=$_debug_keys}\n        <tr class=\"{cycle values=\"odd,even\"}\">\n            <th>{ldelim}${$_debug_keys[vars]|escape:'html'}{rdelim}</th>\n            <td>{$_debug_vals[vars]|@debug_print_var}</td></tr>\n    {sectionelse}\n        <tr><td><p>no template variables assigned</p></td></tr>\n    {/section}\n</table>\n\n<h2>assigned config file variables (outer template scope)</h2>\n\n<table id=\"table_config_vars\">\n    {section name=config_vars loop=$_debug_config_keys}\n        <tr class=\"{cycle values=\"odd,even\"}\">\n            <th>{ldelim}#{$_debug_config_keys[config_vars]|escape:'html'}#{rdelim}</th>\n            <td>{$_debug_config_vals[config_vars]|@debug_print_var}</td></tr>\n    {sectionelse}\n        <tr><td><p>no config vars assigned</p></td></tr>\n    {/section}\n</table>\n</body>\n</html>\n{/capture}\n{if isset($_smarty_debug_output) and $_smarty_debug_output eq \"html\"}\n    {$debug_output}\n{else}\n<script type=\"text/javascript\">\n// <![CDATA[\n    if ( self.name == '' ) {ldelim}\n       var title = 'Console';\n    {rdelim}\n    else {ldelim}\n       var title = 'Console_' + self.name;\n    {rdelim}\n    _smarty_console = window.open(\"\",title.value,\"width=680,height=600,resizable,scrollbars=yes\");\n    _smarty_console.document.write('{$debug_output|escape:'javascript'}');\n    _smarty_console.document.close();\n// ]]>\n</script>\n{/if}"
  },
  {
    "path": "lib/smarty/internals/core.assemble_plugin_filepath.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * assemble filepath of requested plugin\n *\n * @param string $type\n * @param string $name\n * @return string|false\n */\nfunction smarty_core_assemble_plugin_filepath($params, &$smarty)\n{\n    static $_filepaths_cache = array();\n\n    $_plugin_filename = $params['type'] . '.' . $params['name'] . '.php';\n    if (isset($_filepaths_cache[$_plugin_filename])) {\n        return $_filepaths_cache[$_plugin_filename];\n    }\n    $_return = false;\n\n    foreach ((array)$smarty->plugins_dir as $_plugin_dir) {\n\n        $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename;\n\n        // see if path is relative\n        if (!preg_match(\"/^([\\/\\\\\\\\]|[a-zA-Z]:[\\/\\\\\\\\])/\", $_plugin_dir)) {\n            $_relative_paths[] = $_plugin_dir;\n            // relative path, see if it is in the SMARTY_DIR\n            if (@is_readable(SMARTY_DIR . $_plugin_filepath)) {\n                $_return = SMARTY_DIR . $_plugin_filepath;\n                break;\n            }\n        }\n        // try relative to cwd (or absolute)\n        if (@is_readable($_plugin_filepath)) {\n            $_return = $_plugin_filepath;\n            break;\n        }\n    }\n\n    if($_return === false) {\n        // still not found, try PHP include_path\n        if(isset($_relative_paths)) {\n            foreach ((array)$_relative_paths as $_plugin_dir) {\n\n                $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename;\n\n                $_params = array('file_path' => $_plugin_filepath);\n                require_once(SMARTY_CORE_DIR . 'core.get_include_path.php');\n                if(smarty_core_get_include_path($_params, $smarty)) {\n                    $_return = $_params['new_file_path'];\n                    break;\n                }\n            }\n        }\n    }\n    $_filepaths_cache[$_plugin_filename] = $_return;\n    return $_return;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.assign_smarty_interface.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty assign_smarty_interface core plugin\n *\n * Type:     core<br>\n * Name:     assign_smarty_interface<br>\n * Purpose:  assign the $smarty interface variable\n * @param array Format: null\n * @param Smarty\n */\nfunction smarty_core_assign_smarty_interface($params, &$smarty)\n{\n        if (isset($smarty->_smarty_vars) && isset($smarty->_smarty_vars['request'])) {\n            return;\n        }\n\n        $_globals_map = array('g'  => 'HTTP_GET_VARS',\n                             'p'  => 'HTTP_POST_VARS',\n                             'c'  => 'HTTP_COOKIE_VARS',\n                             's'  => 'HTTP_SERVER_VARS',\n                             'e'  => 'HTTP_ENV_VARS');\n\n        $_smarty_vars_request  = array();\n\n        foreach (preg_split('!!', strtolower($smarty->request_vars_order)) as $_c) {\n            if (isset($_globals_map[$_c])) {\n                $_smarty_vars_request = array_merge($_smarty_vars_request, $GLOBALS[$_globals_map[$_c]]);\n            }\n        }\n        $_smarty_vars_request = @array_merge($_smarty_vars_request, $GLOBALS['HTTP_SESSION_VARS']);\n\n        $smarty->_smarty_vars['request'] = $_smarty_vars_request;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.create_dir_structure.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * create full directory structure\n *\n * @param string $dir\n */\n\n// $dir\n\nfunction smarty_core_create_dir_structure($params, &$smarty)\n{\n    if (!file_exists($params['dir'])) {\n        $_open_basedir_ini = ini_get('open_basedir');\n\n        if (DIRECTORY_SEPARATOR=='/') {\n            /* unix-style paths */\n            $_dir = $params['dir'];\n            $_dir_parts = preg_split('!/+!', $_dir, -1, PREG_SPLIT_NO_EMPTY);\n            $_new_dir = (substr($_dir, 0, 1)=='/') ? '/' : getcwd().'/';\n            if($_use_open_basedir = !empty($_open_basedir_ini)) {\n                $_open_basedirs = explode(':', $_open_basedir_ini);\n            }\n\n        } else {\n            /* other-style paths */\n            $_dir = str_replace('\\\\','/', $params['dir']);\n            $_dir_parts = preg_split('!/+!', $_dir, -1, PREG_SPLIT_NO_EMPTY);\n            if (preg_match('!^((//)|([a-zA-Z]:/))!', $_dir, $_root_dir)) {\n                /* leading \"//\" for network volume, or \"[letter]:/\" for full path */\n                $_new_dir = $_root_dir[1];\n                /* remove drive-letter from _dir_parts */\n                if (isset($_root_dir[3])) array_shift($_dir_parts);\n\n            } else {\n                $_new_dir = str_replace('\\\\', '/', getcwd()).'/';\n\n            }\n\n            if($_use_open_basedir = !empty($_open_basedir_ini)) {\n                $_open_basedirs = explode(';', str_replace('\\\\', '/', $_open_basedir_ini));\n            }\n\n        }\n\n        /* all paths use \"/\" only from here */\n        foreach ($_dir_parts as $_dir_part) {\n            $_new_dir .= $_dir_part;\n\n            if ($_use_open_basedir) {\n                // do not attempt to test or make directories outside of open_basedir\n                $_make_new_dir = false;\n                foreach ($_open_basedirs as $_open_basedir) {\n                    if (substr($_new_dir, 0, strlen($_open_basedir)) == $_open_basedir) {\n                        $_make_new_dir = true;\n                        break;\n                    }\n                }\n            } else {\n                $_make_new_dir = true;\n            }\n\n            if ($_make_new_dir && !file_exists($_new_dir) && !@mkdir($_new_dir, $smarty->_dir_perms) && !is_dir($_new_dir)) {\n                $smarty->trigger_error(\"problem creating directory '\" . $_new_dir . \"'\");\n                return false;\n            }\n            $_new_dir .= '/';\n        }\n    }\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.display_debug_console.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty debug_console function plugin\n *\n * Type:     core<br>\n * Name:     display_debug_console<br>\n * Purpose:  display the javascript debug console window\n * @param array Format: null\n * @param Smarty\n */\nfunction smarty_core_display_debug_console($params, &$smarty)\n{\n    // we must force compile the debug template in case the environment\n    // changed between separate applications.\n\n    if(empty($smarty->debug_tpl)) {\n        // set path to debug template from SMARTY_DIR\n        $smarty->debug_tpl = SMARTY_DIR . 'debug.tpl';\n        if($smarty->security && is_file($smarty->debug_tpl)) {\n            $smarty->secure_dir[] = realpath($smarty->debug_tpl);\n        }\n        $smarty->debug_tpl = 'file:' . SMARTY_DIR . 'debug.tpl';\n    }\n\n    $_ldelim_orig = $smarty->left_delimiter;\n    $_rdelim_orig = $smarty->right_delimiter;\n\n    $smarty->left_delimiter = '{';\n    $smarty->right_delimiter = '}';\n\n    $_compile_id_orig = $smarty->_compile_id;\n    $smarty->_compile_id = null;\n\n    $_compile_path = $smarty->_get_compile_path($smarty->debug_tpl);\n    if ($smarty->_compile_resource($smarty->debug_tpl, $_compile_path))\n    {\n        ob_start();\n        $smarty->_include($_compile_path);\n        $_results = ob_get_contents();\n        ob_end_clean();\n    } else {\n        $_results = '';\n    }\n\n    $smarty->_compile_id = $_compile_id_orig;\n\n    $smarty->left_delimiter = $_ldelim_orig;\n    $smarty->right_delimiter = $_rdelim_orig;\n\n    return $_results;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.get_include_path.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Get path to file from include_path\n *\n * @param string $file_path\n * @param string $new_file_path\n * @return boolean\n * @staticvar array|null\n */\n\n//  $file_path, &$new_file_path\n\nfunction smarty_core_get_include_path(&$params, &$smarty)\n{\n    static $_path_array = null;\n\n    if(!isset($_path_array)) {\n        $_ini_include_path = ini_get('include_path');\n\n        if(strstr($_ini_include_path,';')) {\n            // windows pathnames\n            $_path_array = explode(';',$_ini_include_path);\n        } else {\n            $_path_array = explode(':',$_ini_include_path);\n        }\n    }\n    foreach ($_path_array as $_include_path) {\n        if (@is_readable($_include_path . DIRECTORY_SEPARATOR . $params['file_path'])) {\n               $params['new_file_path'] = $_include_path . DIRECTORY_SEPARATOR . $params['file_path'];\n            return true;\n        }\n    }\n    return false;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.get_microtime.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Get seconds and microseconds\n * @return double\n */\nfunction smarty_core_get_microtime($params, &$smarty)\n{\n    $mtime = microtime();\n    $mtime = explode(\" \", $mtime);\n    $mtime = (double)($mtime[1]) + (double)($mtime[0]);\n    return ($mtime);\n}\n\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.get_php_resource.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Retrieves PHP script resource\n *\n * sets $php_resource to the returned resource\n * @param string $resource\n * @param string $resource_type\n * @param  $php_resource\n * @return boolean\n */\n\nfunction smarty_core_get_php_resource(&$params, &$smarty)\n{\n\n    $params['resource_base_path'] = $smarty->trusted_dir;\n    $smarty->_parse_resource_name($params, $smarty);\n\n    /*\n     * Find out if the resource exists.\n     */\n\n    if ($params['resource_type'] == 'file') {\n        $_readable = false;\n        if(file_exists($params['resource_name']) && is_readable($params['resource_name'])) {\n            $_readable = true;\n        } else {\n            // test for file in include_path\n            $_params = array('file_path' => $params['resource_name']);\n            require_once(SMARTY_CORE_DIR . 'core.get_include_path.php');\n            if(smarty_core_get_include_path($_params, $smarty)) {\n                $_include_path = $_params['new_file_path'];\n                $_readable = true;\n            }\n        }\n    } else if ($params['resource_type'] != 'file') {\n        $_template_source = null;\n        $_readable = is_callable($smarty->_plugins['resource'][$params['resource_type']][0][0])\n            && call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][0],\n                                    array($params['resource_name'], &$_template_source, &$smarty));\n    }\n\n    /*\n     * Set the error function, depending on which class calls us.\n     */\n    if (method_exists($smarty, '_syntax_error')) {\n        $_error_funcc = '_syntax_error';\n    } else {\n        $_error_funcc = 'trigger_error';\n    }\n\n    if ($_readable) {\n        if ($smarty->security) {\n            require_once(SMARTY_CORE_DIR . 'core.is_trusted.php');\n            if (!smarty_core_is_trusted($params, $smarty)) {\n                $smarty->$_error_funcc('(secure mode) ' . $params['resource_type'] . ':' . $params['resource_name'] . ' is not trusted');\n                return false;\n            }\n        }\n    } else {\n        $smarty->$_error_funcc($params['resource_type'] . ':' . $params['resource_name'] . ' is not readable');\n        return false;\n    }\n\n    if ($params['resource_type'] == 'file') {\n        $params['php_resource'] = $params['resource_name'];\n    } else {\n        $params['php_resource'] = $_template_source;\n    }\n    return true;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.is_secure.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * determines if a resource is secure or not.\n *\n * @param string $resource_type\n * @param string $resource_name\n * @return boolean\n */\n\n//  $resource_type, $resource_name\n\nfunction smarty_core_is_secure($params, &$smarty)\n{\n    if (!$smarty->security || $smarty->security_settings['INCLUDE_ANY']) {\n        return true;\n    }\n\n    if ($params['resource_type'] == 'file') {\n        $_rp = realpath($params['resource_name']);\n        if (isset($params['resource_base_path'])) {\n            foreach ((array)$params['resource_base_path'] as $curr_dir) {\n                if ( ($_cd = realpath($curr_dir)) !== false &&\n                     strncmp($_rp, $_cd, strlen($_cd)) == 0 &&\n                     substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR ) {\n                    return true;\n                }\n            }\n        }\n        if (!empty($smarty->secure_dir)) {\n            foreach ((array)$smarty->secure_dir as $curr_dir) {\n                if ( ($_cd = realpath($curr_dir)) !== false) {\n                    if($_cd == $_rp) {\n                        return true;\n                    } elseif (strncmp($_rp, $_cd, strlen($_cd)) == 0 &&\n                        substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR) {\n                        return true;\n                    }\n                }\n            }\n        }\n    } else {\n        // resource is not on local file system\n        return call_user_func_array(\n            $smarty->_plugins['resource'][$params['resource_type']][0][2],\n            array($params['resource_name'], &$smarty));\n    }\n\n    return false;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.is_trusted.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * determines if a resource is trusted or not\n *\n * @param string $resource_type\n * @param string $resource_name\n * @return boolean\n */\n\n // $resource_type, $resource_name\n\nfunction smarty_core_is_trusted($params, &$smarty)\n{\n    $_smarty_trusted = false;\n    if ($params['resource_type'] == 'file') {\n        if (!empty($smarty->trusted_dir)) {\n            $_rp = realpath($params['resource_name']);\n            foreach ((array)$smarty->trusted_dir as $curr_dir) {\n                if (!empty($curr_dir) && is_readable ($curr_dir)) {\n                    $_cd = realpath($curr_dir);\n                    if (strncmp($_rp, $_cd, strlen($_cd)) == 0\n                        && substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR ) {\n                        $_smarty_trusted = true;\n                        break;\n                    }\n                }\n            }\n        }\n\n    } else {\n        // resource is not on local file system\n        $_smarty_trusted = call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][3],\n                                                array($params['resource_name'], $smarty));\n    }\n\n    return $_smarty_trusted;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.load_plugins.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Load requested plugins\n *\n * @param array $plugins\n */\n\n// $plugins\n\nfunction smarty_core_load_plugins($params, &$smarty)\n{\n\n    foreach ($params['plugins'] as $_plugin_info) {\n        list($_type, $_name, $_tpl_file, $_tpl_line, $_delayed_loading) = $_plugin_info;\n        $_plugin = &$smarty->_plugins[$_type][$_name];\n\n        /*\n         * We do not load plugin more than once for each instance of Smarty.\n         * The following code checks for that. The plugin can also be\n         * registered dynamically at runtime, in which case template file\n         * and line number will be unknown, so we fill them in.\n         *\n         * The final element of the info array is a flag that indicates\n         * whether the dynamically registered plugin function has been\n         * checked for existence yet or not.\n         */\n        if (isset($_plugin)) {\n            if (empty($_plugin[3])) {\n                if (!is_callable($_plugin[0])) {\n                    $smarty->_trigger_fatal_error(\"[plugin] $_type '$_name' is not implemented\", $_tpl_file, $_tpl_line, __FILE__, __LINE__);\n                } else {\n                    $_plugin[1] = $_tpl_file;\n                    $_plugin[2] = $_tpl_line;\n                    $_plugin[3] = true;\n                    if (!isset($_plugin[4])) $_plugin[4] = true; /* cacheable */\n                }\n            }\n            continue;\n        } else if ($_type == 'insert') {\n            /*\n             * For backwards compatibility, we check for insert functions in\n             * the symbol table before trying to load them as a plugin.\n             */\n            $_plugin_func = 'insert_' . $_name;\n            if (function_exists($_plugin_func)) {\n                $_plugin = array($_plugin_func, $_tpl_file, $_tpl_line, true, false);\n                continue;\n            }\n        }\n\n        $_plugin_file = $smarty->_get_plugin_filepath($_type, $_name);\n\n        if (! $_found = ($_plugin_file != false)) {\n            $_message = \"could not load plugin file '$_type.$_name.php'\\n\";\n        }\n\n        /*\n         * If plugin file is found, it -must- provide the properly named\n         * plugin function. In case it doesn't, simply output the error and\n         * do not fall back on any other method.\n         */\n        if ($_found) {\n            include_once $_plugin_file;\n\n            $_plugin_func = 'smarty_' . $_type . '_' . $_name;\n            if (!function_exists($_plugin_func)) {\n                $smarty->_trigger_fatal_error(\"[plugin] function $_plugin_func() not found in $_plugin_file\", $_tpl_file, $_tpl_line, __FILE__, __LINE__);\n                continue;\n            }\n        }\n        /*\n         * In case of insert plugins, their code may be loaded later via\n         * 'script' attribute.\n         */\n        else if ($_type == 'insert' && $_delayed_loading) {\n            $_plugin_func = 'smarty_' . $_type . '_' . $_name;\n            $_found = true;\n        }\n\n        /*\n         * Plugin specific processing and error checking.\n         */\n        if (!$_found) {\n            if ($_type == 'modifier') {\n                /*\n                 * In case modifier falls back on using PHP functions\n                 * directly, we only allow those specified in the security\n                 * context.\n                 */\n                if ($smarty->security && !in_array($_name, $smarty->security_settings['MODIFIER_FUNCS'])) {\n                    $_message = \"(secure mode) modifier '$_name' is not allowed\";\n                } else {\n                    if (!function_exists($_name)) {\n                        $_message = \"modifier '$_name' is not implemented\";\n                    } else {\n                        $_plugin_func = $_name;\n                        $_found = true;\n                    }\n                }\n            } else if ($_type == 'function') {\n                /*\n                 * This is a catch-all situation.\n                 */\n                $_message = \"unknown tag - '$_name'\";\n            }\n        }\n\n        if ($_found) {\n            $smarty->_plugins[$_type][$_name] = array($_plugin_func, $_tpl_file, $_tpl_line, true, true);\n        } else {\n            // output error\n            $smarty->_trigger_fatal_error('[plugin] ' . $_message, $_tpl_file, $_tpl_line, __FILE__, __LINE__);\n        }\n    }\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.load_resource_plugin.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * load a resource plugin\n *\n * @param string $type\n */\n\n// $type\n\nfunction smarty_core_load_resource_plugin($params, &$smarty)\n{\n    /*\n     * Resource plugins are not quite like the other ones, so they are\n     * handled differently. The first element of plugin info is the array of\n     * functions provided by the plugin, the second one indicates whether\n     * all of them exist or not.\n     */\n\n    $_plugin = &$smarty->_plugins['resource'][$params['type']];\n    if (isset($_plugin)) {\n        if (!$_plugin[1] && count($_plugin[0])) {\n            $_plugin[1] = true;\n            foreach ($_plugin[0] as $_plugin_func) {\n                if (!is_callable($_plugin_func)) {\n                    $_plugin[1] = false;\n                    break;\n                }\n            }\n        }\n\n        if (!$_plugin[1]) {\n            $smarty->_trigger_fatal_error(\"[plugin] resource '\" . $params['type'] . \"' is not implemented\", null, null, __FILE__, __LINE__);\n        }\n\n        return;\n    }\n\n    $_plugin_file = $smarty->_get_plugin_filepath('resource', $params['type']);\n    $_found = ($_plugin_file != false);\n\n    if ($_found) {            /*\n         * If the plugin file is found, it -must- provide the properly named\n         * plugin functions.\n         */\n        include_once($_plugin_file);\n\n        /*\n         * Locate functions that we require the plugin to provide.\n         */\n        $_resource_ops = array('source', 'timestamp', 'secure', 'trusted');\n        $_resource_funcs = array();\n        foreach ($_resource_ops as $_op) {\n            $_plugin_func = 'smarty_resource_' . $params['type'] . '_' . $_op;\n            if (!function_exists($_plugin_func)) {\n                $smarty->_trigger_fatal_error(\"[plugin] function $_plugin_func() not found in $_plugin_file\", null, null, __FILE__, __LINE__);\n                return;\n            } else {\n                $_resource_funcs[] = $_plugin_func;\n            }\n        }\n\n        $smarty->_plugins['resource'][$params['type']] = array($_resource_funcs, true);\n    }\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.process_cached_inserts.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Replace cached inserts with the actual results\n *\n * @param string $results\n * @return string\n */\nfunction smarty_core_process_cached_inserts($params, &$smarty)\n{\n    preg_match_all('!'.$smarty->_smarty_md5.'{insert_cache (.*)}'.$smarty->_smarty_md5.'!Uis',\n                   $params['results'], $match);\n    list($cached_inserts, $insert_args) = $match;\n\n    for ($i = 0, $for_max = count($cached_inserts); $i < $for_max; $i++) {\n        if ($smarty->debugging) {\n            $_params = array();\n            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');\n            $debug_start_time = smarty_core_get_microtime($_params, $smarty);\n        }\n\n        $args = unserialize($insert_args[$i]);\n        $name = $args['name'];\n\n        if (isset($args['script'])) {\n            $_params = array('resource_name' => $smarty->_dequote($args['script']));\n            require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php');\n            if(!smarty_core_get_php_resource($_params, $smarty)) {\n                return false;\n            }\n            $resource_type = $_params['resource_type'];\n            $php_resource = $_params['php_resource'];\n\n\n            if ($resource_type == 'file') {\n                $smarty->_include($php_resource, true);\n            } else {\n                $smarty->_eval($php_resource);\n            }\n        }\n\n        $function_name = $smarty->_plugins['insert'][$name][0];\n        if (empty($args['assign'])) {\n            $replace = $function_name($args, $smarty);\n        } else {\n            $smarty->assign($args['assign'], $function_name($args, $smarty));\n            $replace = '';\n        }\n\n        $params['results'] = substr_replace($params['results'], $replace, strpos($params['results'], $cached_inserts[$i]), strlen($cached_inserts[$i]));\n        if ($smarty->debugging) {\n            $_params = array();\n            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');\n            $smarty->_smarty_debug_info[] = array('type'      => 'insert',\n                                                'filename'  => 'insert_'.$name,\n                                                'depth'     => $smarty->_inclusion_depth,\n                                                'exec_time' => smarty_core_get_microtime($_params, $smarty) - $debug_start_time);\n        }\n    }\n\n    return $params['results'];\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.process_compiled_include.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Replace nocache-tags by results of the corresponding non-cacheable\n * functions and return it\n *\n * @param string $compiled_tpl\n * @param string $cached_source\n * @return string\n */\n\nfunction smarty_core_process_compiled_include($params, &$smarty)\n{\n    $_cache_including = $smarty->_cache_including;\n    $smarty->_cache_including = true;\n\n    $_return = $params['results'];\n\n    foreach ($smarty->_cache_info['cache_serials'] as $_include_file_path=>$_cache_serial) {\n        $smarty->_include($_include_file_path, true);\n    }\n\n    foreach ($smarty->_cache_info['cache_serials'] as $_include_file_path=>$_cache_serial) {\n        $_return = preg_replace_callback('!(\\{nocache\\:('.$_cache_serial.')#(\\d+)\\})!s',\n                                         array(&$smarty, '_process_compiled_include_callback'),\n                                         $_return);\n    }\n    $smarty->_cache_including = $_cache_including;\n    return $_return;\n}\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.read_cache_file.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * read a cache file, determine if it needs to be\n * regenerated or not\n *\n * @param string $tpl_file\n * @param string $cache_id\n * @param string $compile_id\n * @param string $results\n * @return boolean\n */\n\n//  $tpl_file, $cache_id, $compile_id, &$results\n\nfunction smarty_core_read_cache_file(&$params, &$smarty)\n{\n    static  $content_cache = array();\n\n    if ($smarty->force_compile) {\n        // force compile enabled, always regenerate\n        return false;\n    }\n\n    if (isset($content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']])) {\n        list($params['results'], $smarty->_cache_info) = $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']];\n        return true;\n    }\n\n    if (!empty($smarty->cache_handler_func)) {\n        // use cache_handler function\n        call_user_func_array($smarty->cache_handler_func,\n                             array('read', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null));\n    } else {\n        // use local cache file\n        $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']);\n        $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id);\n        $params['results'] = $smarty->_read_file($_cache_file);\n    }\n\n    if (empty($params['results'])) {\n        // nothing to parse (error?), regenerate cache\n        return false;\n    }\n\n    $_contents = $params['results'];\n    $_info_start = strpos($_contents, \"\\n\") + 1;\n    $_info_len = (int)substr($_contents, 0, $_info_start - 1);\n    $_cache_info = unserialize(substr($_contents, $_info_start, $_info_len));\n    $params['results'] = substr($_contents, $_info_start + $_info_len);\n\n    if ($smarty->caching == 2 && isset ($_cache_info['expires'])){\n        // caching by expiration time\n        if ($_cache_info['expires'] > -1 && (time() > $_cache_info['expires'])) {\n            // cache expired, regenerate\n            return false;\n        }\n    } else {\n        // caching by lifetime\n        if ($smarty->cache_lifetime > -1 && (time() - $_cache_info['timestamp'] > $smarty->cache_lifetime)) {\n            // cache expired, regenerate\n            return false;\n        }\n    }\n\n    if ($smarty->compile_check) {\n        $_params = array('get_source' => false, 'quiet'=>true);\n        foreach (array_keys($_cache_info['template']) as $_template_dep) {\n            $_params['resource_name'] = $_template_dep;\n            if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) {\n                // template file has changed, regenerate cache\n                return false;\n            }\n        }\n\n        if (isset($_cache_info['config'])) {\n            $_params = array('resource_base_path' => $smarty->config_dir, 'get_source' => false, 'quiet'=>true);\n            foreach (array_keys($_cache_info['config']) as $_config_dep) {\n                $_params['resource_name'] = $_config_dep;\n                if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) {\n                    // config file has changed, regenerate cache\n                    return false;\n                }\n            }\n        }\n    }\n\n    $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']] = array($params['results'], $_cache_info);\n\n    $smarty->_cache_info = $_cache_info;\n    return true;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.rm_auto.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * delete an automagically created file by name and id\n *\n * @param string $auto_base\n * @param string $auto_source\n * @param string $auto_id\n * @param integer $exp_time\n * @return boolean\n */\n\n// $auto_base, $auto_source = null, $auto_id = null, $exp_time = null\n\nfunction smarty_core_rm_auto($params, &$smarty)\n{\n    if (!@is_dir($params['auto_base']))\n      return false;\n\n    if(!isset($params['auto_id']) && !isset($params['auto_source'])) {\n        $_params = array(\n            'dirname' => $params['auto_base'],\n            'level' => 0,\n            'exp_time' => $params['exp_time']\n        );\n        require_once(SMARTY_CORE_DIR . 'core.rmdir.php');\n        $_res = smarty_core_rmdir($_params, $smarty);\n    } else {\n        $_tname = $smarty->_get_auto_filename($params['auto_base'], $params['auto_source'], $params['auto_id']);\n\n        if(isset($params['auto_source'])) {\n            if (isset($params['extensions'])) {\n                $_res = false;\n                foreach ((array)$params['extensions'] as $_extension)\n                    $_res |= $smarty->_unlink($_tname.$_extension, $params['exp_time']);\n            } else {\n                $_res = $smarty->_unlink($_tname, $params['exp_time']);\n            }\n        } elseif ($smarty->use_sub_dirs) {\n            $_params = array(\n                'dirname' => $_tname,\n                'level' => 1,\n                'exp_time' => $params['exp_time']\n            );\n            require_once(SMARTY_CORE_DIR . 'core.rmdir.php');\n            $_res = smarty_core_rmdir($_params, $smarty);\n        } else {\n            // remove matching file names\n            $_handle = opendir($params['auto_base']);\n            $_res = true;\n            while (false !== ($_filename = readdir($_handle))) {\n                if($_filename == '.' || $_filename == '..') {\n                    continue;\n                } elseif (substr($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, 0, strlen($_tname)) == $_tname) {\n                    $_res &= (bool)$smarty->_unlink($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, $params['exp_time']);\n                }\n            }\n        }\n    }\n\n    return $_res;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.rmdir.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * delete a dir recursively (level=0 -> keep root)\n * WARNING: no tests, it will try to remove what you tell it!\n *\n * @param string $dirname\n * @param integer $level\n * @param integer $exp_time\n * @return boolean\n */\n\n//  $dirname, $level = 1, $exp_time = null\n\nfunction smarty_core_rmdir($params, &$smarty)\n{\n   if(!isset($params['level'])) { $params['level'] = 1; }\n   if(!isset($params['exp_time'])) { $params['exp_time'] = null; }\n\n   if($_handle = @opendir($params['dirname'])) {\n\n        while (false !== ($_entry = readdir($_handle))) {\n            if ($_entry != '.' && $_entry != '..') {\n                if (@is_dir($params['dirname'] . DIRECTORY_SEPARATOR . $_entry)) {\n                    $_params = array(\n                        'dirname' => $params['dirname'] . DIRECTORY_SEPARATOR . $_entry,\n                        'level' => $params['level'] + 1,\n                        'exp_time' => $params['exp_time']\n                    );\n                    smarty_core_rmdir($_params, $smarty);\n                }\n                else {\n                    $smarty->_unlink($params['dirname'] . DIRECTORY_SEPARATOR . $_entry, $params['exp_time']);\n                }\n            }\n        }\n        closedir($_handle);\n   }\n\n   if ($params['level']) {\n       return @rmdir($params['dirname']);\n   }\n   return (bool)$_handle;\n\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.run_insert_handler.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Handle insert tags\n *\n * @param array $args\n * @return string\n */\nfunction smarty_core_run_insert_handler($params, &$smarty)\n{\n\n    require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');\n    if ($smarty->debugging) {\n        $_params = array();\n        $_debug_start_time = smarty_core_get_microtime($_params, $smarty);\n    }\n\n    if ($smarty->caching) {\n        $_arg_string = serialize($params['args']);\n        $_name = $params['args']['name'];\n        if (!isset($smarty->_cache_info['insert_tags'][$_name])) {\n            $smarty->_cache_info['insert_tags'][$_name] = array('insert',\n                                                             $_name,\n                                                             $smarty->_plugins['insert'][$_name][1],\n                                                             $smarty->_plugins['insert'][$_name][2],\n                                                             !empty($params['args']['script']) ? true : false);\n        }\n        return $smarty->_smarty_md5.\"{insert_cache $_arg_string}\".$smarty->_smarty_md5;\n    } else {\n        if (isset($params['args']['script'])) {\n            $_params = array('resource_name' => $smarty->_dequote($params['args']['script']));\n            require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php');\n            if(!smarty_core_get_php_resource($_params, $smarty)) {\n                return false;\n            }\n\n            if ($_params['resource_type'] == 'file') {\n                $smarty->_include($_params['php_resource'], true);\n            } else {\n                $smarty->_eval($_params['php_resource']);\n            }\n            unset($params['args']['script']);\n        }\n\n        $_funcname = $smarty->_plugins['insert'][$params['args']['name']][0];\n        $_content = $_funcname($params['args'], $smarty);\n        if ($smarty->debugging) {\n            $_params = array();\n            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');\n            $smarty->_smarty_debug_info[] = array('type'      => 'insert',\n                                                'filename'  => 'insert_'.$params['args']['name'],\n                                                'depth'     => $smarty->_inclusion_depth,\n                                                'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time);\n        }\n\n        if (!empty($params['args'][\"assign\"])) {\n            $smarty->assign($params['args'][\"assign\"], $_content);\n        } else {\n            return $_content;\n        }\n    }\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.smarty_include_php.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * called for included php files within templates\n *\n * @param string $smarty_file\n * @param string $smarty_assign variable to assign the included template's\n *               output into\n * @param boolean $smarty_once uses include_once if this is true\n * @param array $smarty_include_vars associative array of vars from\n *              {include file=\"blah\" var=$var}\n */\n\n//  $file, $assign, $once, $_smarty_include_vars\n\nfunction smarty_core_smarty_include_php($params, &$smarty)\n{\n    $_params = array('resource_name' => $params['smarty_file']);\n    require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php');\n    smarty_core_get_php_resource($_params, $smarty);\n    $_smarty_resource_type = $_params['resource_type'];\n    $_smarty_php_resource = $_params['php_resource'];\n\n    if (!empty($params['smarty_assign'])) {\n        ob_start();\n        if ($_smarty_resource_type == 'file') {\n            $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']);\n        } else {\n            $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']);\n        }\n        $smarty->assign($params['smarty_assign'], ob_get_contents());\n        ob_end_clean();\n    } else {\n        if ($_smarty_resource_type == 'file') {\n            $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']);\n        } else {\n            $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']);\n        }\n    }\n}\n\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.write_cache_file.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Prepend the cache information to the cache file\n * and write it\n *\n * @param string $tpl_file\n * @param string $cache_id\n * @param string $compile_id\n * @param string $results\n * @return true|null\n */\n\n // $tpl_file, $cache_id, $compile_id, $results\n\nfunction smarty_core_write_cache_file($params, &$smarty)\n{\n\n    // put timestamp in cache header\n    $smarty->_cache_info['timestamp'] = time();\n    if ($smarty->cache_lifetime > -1){\n        // expiration set\n        $smarty->_cache_info['expires'] = $smarty->_cache_info['timestamp'] + $smarty->cache_lifetime;\n    } else {\n        // cache will never expire\n        $smarty->_cache_info['expires'] = -1;\n    }\n\n    // collapse nocache.../nocache-tags\n    if (preg_match_all('!\\{(/?)nocache\\:[0-9a-f]{32}#\\d+\\}!', $params['results'], $match, PREG_PATTERN_ORDER)) {\n        // remove everything between every pair of outermost noache.../nocache-tags\n        // and replace it by a single nocache-tag\n        // this new nocache-tag will be replaced by dynamic contents in\n        // smarty_core_process_compiled_includes() on a cache-read\n        \n        $match_count = count($match[0]);\n        $results = preg_split('!(\\{/?nocache\\:[0-9a-f]{32}#\\d+\\})!', $params['results'], -1, PREG_SPLIT_DELIM_CAPTURE);\n        \n        $level = 0;\n        $j = 0;\n        for ($i=0, $results_count = count($results); $i < $results_count && $j < $match_count; $i++) {\n            if ($results[$i] == $match[0][$j]) {\n                // nocache tag\n                if ($match[1][$j]) { // closing tag\n                    $level--;\n                    unset($results[$i]);\n                } else { // opening tag\n                    if ($level++ > 0) unset($results[$i]);\n                }\n                $j++;\n            } elseif ($level > 0) {\n                unset($results[$i]);\n            }\n        }\n        $params['results'] = implode('', $results);\n    }\n    $smarty->_cache_info['cache_serials'] = $smarty->_cache_serials;\n\n    // prepend the cache header info into cache file\n    $_cache_info = serialize($smarty->_cache_info);\n    $params['results'] = strlen($_cache_info) . \"\\n\" . $_cache_info . $params['results'];\n\n    if (!empty($smarty->cache_handler_func)) {\n        // use cache_handler function\n        call_user_func_array($smarty->cache_handler_func,\n                             array('write', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], $smarty->_cache_info['expires']));\n    } else {\n        // use local cache file\n\n        if(!@is_writable($smarty->cache_dir)) {\n            // cache_dir not writable, see if it exists\n            if(!@is_dir($smarty->cache_dir)) {\n                $smarty->trigger_error('the $cache_dir \\'' . $smarty->cache_dir . '\\' does not exist, or is not a directory.', E_USER_ERROR);\n                return false;\n            }\n            $smarty->trigger_error('unable to write to $cache_dir \\'' . realpath($smarty->cache_dir) . '\\'. Be sure $cache_dir is writable by the web server user.', E_USER_ERROR);\n            return false;\n        }\n\n        $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']);\n        $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id);\n        $_params = array('filename' => $_cache_file, 'contents' => $params['results'], 'create_dirs' => true);\n        require_once(SMARTY_CORE_DIR . 'core.write_file.php');\n        smarty_core_write_file($_params, $smarty);\n        return true;\n    }\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.write_compiled_include.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Extract non-cacheable parts out of compiled template and write it\n *\n * @param string $compile_path\n * @param string $template_compiled\n * @return boolean\n */\n\nfunction smarty_core_write_compiled_include($params, &$smarty)\n{\n    $_tag_start = 'if \\(\\$this->caching && \\!\\$this->_cache_including\\)\\: echo \\'\\{nocache\\:('.$params['cache_serial'].')#(\\d+)\\}\\'; endif;';\n    $_tag_end   = 'if \\(\\$this->caching && \\!\\$this->_cache_including\\)\\: echo \\'\\{/nocache\\:(\\\\2)#(\\\\3)\\}\\'; endif;';\n\n    preg_match_all('!('.$_tag_start.'(.*)'.$_tag_end.')!Us',\n                   $params['compiled_content'], $_match_source, PREG_SET_ORDER);\n    \n    // no nocache-parts found: done\n    if (count($_match_source)==0) return;\n\n    // convert the matched php-code to functions\n    $_include_compiled =  \"<?php /* Smarty version \".$smarty->_version.\", created on \".strftime(\"%Y-%m-%d %H:%M:%S\").\"\\n\";\n    $_include_compiled .= \"         compiled from \" . strtr(urlencode($params['resource_name']), array('%2F'=>'/', '%3A'=>':')) . \" */\\n\\n\";\n\n    $_compile_path = $params['include_file_path'];\n\n    $smarty->_cache_serials[$_compile_path] = $params['cache_serial'];\n    $_include_compiled .= \"\\$this->_cache_serials['\".$_compile_path.\"'] = '\".$params['cache_serial'].\"';\\n\\n?>\";\n\n    $_include_compiled .= $params['plugins_code'];\n    $_include_compiled .= \"<?php\";\n\n    $this_varname = ((double)phpversion() >= 5.0) ? '_smarty' : 'this';\n    for ($_i = 0, $_for_max = count($_match_source); $_i < $_for_max; $_i++) {\n        $_match =& $_match_source[$_i];\n        $source = $_match[4];\n        if ($this_varname == '_smarty') {\n            /* rename $this to $_smarty in the sourcecode */\n            $tokens = token_get_all('<?php ' . $_match[4]);\n\n            /* remove trailing <?php */\n            $open_tag = '';\n            while ($tokens) {\n                $token = array_shift($tokens);\n                if (is_array($token)) {\n                    $open_tag .= $token[1];\n                } else {\n                    $open_tag .= $token;\n                }\n                if ($open_tag == '<?php ') break;\n            }\n\n            for ($i=0, $count = count($tokens); $i < $count; $i++) {\n                if (is_array($tokens[$i])) {\n                    if ($tokens[$i][0] == T_VARIABLE && $tokens[$i][1] == '$this') {\n                        $tokens[$i] = '$' . $this_varname;\n                    } else {\n                        $tokens[$i] = $tokens[$i][1];\n                    }                   \n                }\n            }\n            $source = implode('', $tokens);\n        }\n\n        /* add function to compiled include */\n        $_include_compiled .= \"\nfunction _smarty_tplfunc_$_match[2]_$_match[3](&\\$$this_varname)\n{\n$source\n}\n\n\";\n    }\n    $_include_compiled .= \"\\n\\n?>\\n\";\n\n    $_params = array('filename' => $_compile_path,\n                     'contents' => $_include_compiled, 'create_dirs' => true);\n\n    require_once(SMARTY_CORE_DIR . 'core.write_file.php');\n    smarty_core_write_file($_params, $smarty);\n    return true;\n}\n\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.write_compiled_resource.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * write the compiled resource\n *\n * @param string $compile_path\n * @param string $compiled_content\n * @return true\n */\nfunction smarty_core_write_compiled_resource($params, &$smarty)\n{\n    if(!@is_writable($smarty->compile_dir)) {\n        // compile_dir not writable, see if it exists\n        if(!@is_dir($smarty->compile_dir)) {\n            $smarty->trigger_error('the $compile_dir \\'' . $smarty->compile_dir . '\\' does not exist, or is not a directory.', E_USER_ERROR);\n            return false;\n        }\n        $smarty->trigger_error('unable to write to $compile_dir \\'' . realpath($smarty->compile_dir) . '\\'. Be sure $compile_dir is writable by the web server user.', E_USER_ERROR);\n        return false;\n    }\n\n    $_params = array('filename' => $params['compile_path'], 'contents' => $params['compiled_content'], 'create_dirs' => true);\n    require_once(SMARTY_CORE_DIR . 'core.write_file.php');\n    smarty_core_write_file($_params, $smarty);\n    return true;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/internals/core.write_file.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * write out a file to disk\n *\n * @param string $filename\n * @param string $contents\n * @param boolean $create_dirs\n * @return boolean\n */\nfunction smarty_core_write_file($params, &$smarty)\n{\n    $_dirname = dirname($params['filename']);\n\n    if ($params['create_dirs']) {\n        $_params = array('dir' => $_dirname);\n        require_once(SMARTY_CORE_DIR . 'core.create_dir_structure.php');\n        smarty_core_create_dir_structure($_params, $smarty);\n    }\n\n    // write to tmp file, then rename it to avoid file locking race condition\n    $_tmp_file = tempnam($_dirname, 'wrt');\n\n    if (!($fd = @fopen($_tmp_file, 'wb'))) {\n        $_tmp_file = $_dirname . DIRECTORY_SEPARATOR . uniqid('wrt');\n        if (!($fd = @fopen($_tmp_file, 'wb'))) {\n            $smarty->trigger_error(\"problem writing temporary file '$_tmp_file'\");\n            return false;\n        }\n    }\n\n    fwrite($fd, $params['contents']);\n    fclose($fd);\n\n    if (DIRECTORY_SEPARATOR == '\\\\' || !@rename($_tmp_file, $params['filename'])) {\n        // On platforms and filesystems that cannot overwrite with rename() \n        // delete the file before renaming it -- because windows always suffers\n        // this, it is short-circuited to avoid the initial rename() attempt\n        @unlink($params['filename']);\n        @rename($_tmp_file, $params['filename']);\n    }\n    @chmod($params['filename'], $smarty->_file_perms);\n\n    return true;\n}\n\n/* vim: set expandtab: */\n\n?>"
  },
  {
    "path": "lib/smarty/plugins/block.textformat.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty {textformat}{/textformat} block plugin\n *\n * Type:     block function<br>\n * Name:     textformat<br>\n * Purpose:  format text a certain way with preset styles\n *           or custom wrap/indent settings<br>\n * @link http://smarty.php.net/manual/en/language.function.textformat.php {textformat}\n *       (Smarty online manual)\n * @param array\n * <pre>\n * Params:   style: string (email)\n *           indent: integer (0)\n *           wrap: integer (80)\n *           wrap_char string (\"\\n\")\n *           indent_char: string (\" \")\n *           wrap_boundary: boolean (true)\n * </pre>\n * @author Monte Ohrt <monte at ohrt dot com>\n * @param string contents of the block\n * @param Smarty clever simulation of a method\n * @return string string $content re-formatted\n */\nfunction smarty_block_textformat($params, $content, &$smarty)\n{\n    if (is_null($content)) {\n        return;\n    }\n\n    $style = null;\n    $indent = 0;\n    $indent_first = 0;\n    $indent_char = ' ';\n    $wrap = 80;\n    $wrap_char = \"\\n\";\n    $wrap_cut = false;\n    $assign = null;\n    \n    foreach ($params as $_key => $_val) {\n        switch ($_key) {\n            case 'style':\n            case 'indent_char':\n            case 'wrap_char':\n            case 'assign':\n                $$_key = (string)$_val;\n                break;\n\n            case 'indent':\n            case 'indent_first':\n            case 'wrap':\n                $$_key = (int)$_val;\n                break;\n\n            case 'wrap_cut':\n                $$_key = (bool)$_val;\n                break;\n\n            default:\n                $smarty->trigger_error(\"textformat: unknown attribute '$_key'\");\n        }\n    }\n\n    if ($style == 'email') {\n        $wrap = 72;\n    }\n\n    // split into paragraphs\n    $_paragraphs = preg_split('![\\r\\n][\\r\\n]!',$content);\n    $_output = '';\n\n    for($_x = 0, $_y = count($_paragraphs); $_x < $_y; $_x++) {\n        if ($_paragraphs[$_x] == '') {\n            continue;\n        }\n        // convert mult. spaces & special chars to single space\n        $_paragraphs[$_x] = preg_replace(array('!\\s+!','!(^\\s+)|(\\s+$)!'), array(' ',''), $_paragraphs[$_x]);\n        // indent first line\n        if($indent_first > 0) {\n            $_paragraphs[$_x] = str_repeat($indent_char, $indent_first) . $_paragraphs[$_x];\n        }\n        // wordwrap sentences\n        $_paragraphs[$_x] = wordwrap($_paragraphs[$_x], $wrap - $indent, $wrap_char, $wrap_cut);\n        // indent lines\n        if($indent > 0) {\n            $_paragraphs[$_x] = preg_replace('!^!m', str_repeat($indent_char, $indent), $_paragraphs[$_x]);\n        }\n    }\n    $_output = implode($wrap_char . $wrap_char, $_paragraphs);\n\n    return $assign ? $smarty->assign($assign, $_output) : $_output;\n\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/compiler.assign.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty {assign} compiler function plugin\n *\n * Type:     compiler function<br>\n * Name:     assign<br>\n * Purpose:  assign a value to a template variable\n * @link http://smarty.php.net/manual/en/language.custom.functions.php#LANGUAGE.FUNCTION.ASSIGN {assign}\n *       (Smarty online manual)\n * @author Monte Ohrt <monte at ohrt dot com> (initial author)\n * @author messju mohr <messju at lammfellpuschen dot de> (conversion to compiler function)\n * @param string containing var-attribute and value-attribute\n * @param Smarty_Compiler\n */\nfunction smarty_compiler_assign($tag_attrs, &$compiler)\n{\n    $_params = $compiler->_parse_attrs($tag_attrs);\n\n    if (!isset($_params['var'])) {\n        $compiler->_syntax_error(\"assign: missing 'var' parameter\", E_USER_WARNING);\n        return;\n    }\n\n    if (!isset($_params['value'])) {\n        $compiler->_syntax_error(\"assign: missing 'value' parameter\", E_USER_WARNING);\n        return;\n    }\n\n    return \"\\$this->assign({$_params['var']}, {$_params['value']});\";\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.assign_debug_info.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty {assign_debug_info} function plugin\n *\n * Type:     function<br>\n * Name:     assign_debug_info<br>\n * Purpose:  assign debug info to the template<br>\n * @author Monte Ohrt <monte at ohrt dot com>\n * @param array unused in this plugin, this plugin uses {@link Smarty::$_config},\n *              {@link Smarty::$_tpl_vars} and {@link Smarty::$_smarty_debug_info}\n * @param Smarty\n */\nfunction smarty_function_assign_debug_info($params, &$smarty)\n{\n    $assigned_vars = $smarty->_tpl_vars;\n    ksort($assigned_vars);\n    if (@is_array($smarty->_config[0])) {\n        $config_vars = $smarty->_config[0];\n        ksort($config_vars);\n        $smarty->assign(\"_debug_config_keys\", array_keys($config_vars));\n        $smarty->assign(\"_debug_config_vals\", array_values($config_vars));\n    }\n    \n    $included_templates = $smarty->_smarty_debug_info;\n    \n    $smarty->assign(\"_debug_keys\", array_keys($assigned_vars));\n    $smarty->assign(\"_debug_vals\", array_values($assigned_vars));\n    \n    $smarty->assign(\"_debug_tpls\", $included_templates);\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.config_load.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty {config_load} function plugin\n *\n * Type:     function<br>\n * Name:     config_load<br>\n * Purpose:  load config file vars\n * @link http://smarty.php.net/manual/en/language.function.config.load.php {config_load}\n *       (Smarty online manual)\n * @author Monte Ohrt <monte at ohrt dot com>\n * @author messju mohr <messju at lammfellpuschen dot de> (added use of resources)\n * @param array Format:\n * <pre>\n * array('file' => required config file name,\n *       'section' => optional config file section to load\n *       'scope' => local/parent/global\n *       'global' => overrides scope, setting to parent if true)\n * </pre>\n * @param Smarty\n */\nfunction smarty_function_config_load($params, &$smarty)\n{\n        if ($smarty->debugging) {\n            $_params = array();\n            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');\n            $_debug_start_time = smarty_core_get_microtime($_params, $smarty);\n        }\n\n        $_file = isset($params['file']) ? $smarty->_dequote($params['file']) : null;\n        $_section = isset($params['section']) ? $smarty->_dequote($params['section']) : null;\n        $_scope = isset($params['scope']) ? $smarty->_dequote($params['scope']) : 'global';\n        $_global = isset($params['global']) ? $smarty->_dequote($params['global']) : false;\n\n        if (!isset($_file) || strlen($_file) == 0) {\n            $smarty->trigger_error(\"missing 'file' attribute in config_load tag\", E_USER_ERROR, __FILE__, __LINE__);\n        }\n\n        if (isset($_scope)) {\n            if ($_scope != 'local' &&\n                $_scope != 'parent' &&\n                $_scope != 'global') {\n                $smarty->trigger_error(\"invalid 'scope' attribute value\", E_USER_ERROR, __FILE__, __LINE__);\n            }\n        } else {\n            if ($_global) {\n                $_scope = 'parent';\n            } else {\n                $_scope = 'local';\n            }\n        }\n\n        $_params = array('resource_name' => $_file,\n                         'resource_base_path' => $smarty->config_dir,\n                         'get_source' => false);\n        $smarty->_parse_resource_name($_params);\n        $_file_path = $_params['resource_type'] . ':' . $_params['resource_name'];\n        if (isset($_section))\n            $_compile_file = $smarty->_get_compile_path($_file_path.'|'.$_section);\n        else\n            $_compile_file = $smarty->_get_compile_path($_file_path);\n\n        if($smarty->force_compile || !file_exists($_compile_file)) {\n            $_compile = true;\n        } elseif ($smarty->compile_check) {\n            $_params = array('resource_name' => $_file,\n                             'resource_base_path' => $smarty->config_dir,\n                             'get_source' => false);\n            $_compile = $smarty->_fetch_resource_info($_params) &&\n                $_params['resource_timestamp'] > filemtime($_compile_file);\n        } else {\n            $_compile = false;\n        }\n\n        if($_compile) {\n            // compile config file\n            if(!is_object($smarty->_conf_obj)) {\n                require_once SMARTY_DIR . $smarty->config_class . '.class.php';\n                $smarty->_conf_obj = new $smarty->config_class();\n                $smarty->_conf_obj->overwrite = $smarty->config_overwrite;\n                $smarty->_conf_obj->booleanize = $smarty->config_booleanize;\n                $smarty->_conf_obj->read_hidden = $smarty->config_read_hidden;\n                $smarty->_conf_obj->fix_newlines = $smarty->config_fix_newlines;\n            }\n\n            $_params = array('resource_name' => $_file,\n                             'resource_base_path' => $smarty->config_dir,\n                             $_params['get_source'] = true);\n            if (!$smarty->_fetch_resource_info($_params)) {\n                return;\n            }\n            $smarty->_conf_obj->set_file_contents($_file, $_params['source_content']);\n            $_config_vars = array_merge($smarty->_conf_obj->get($_file),\n                    $smarty->_conf_obj->get($_file, $_section));\n            if(function_exists('var_export')) {\n                $_output = '<?php $_config_vars = ' . var_export($_config_vars, true) . '; ?>';\n            } else {\n                $_output = '<?php $_config_vars = unserialize(\\'' . strtr(serialize($_config_vars),array('\\''=>'\\\\\\'', '\\\\'=>'\\\\\\\\')) . '\\'); ?>';\n            }\n            $_params = (array('compile_path' => $_compile_file, 'compiled_content' => $_output, 'resource_timestamp' => $_params['resource_timestamp']));\n            require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php');\n            smarty_core_write_compiled_resource($_params, $smarty);\n        } else {\n            include($_compile_file);\n        }\n\n        if ($smarty->caching) {\n            $smarty->_cache_info['config'][$_file] = true;\n        }\n\n        $smarty->_config[0]['vars'] = @array_merge($smarty->_config[0]['vars'], $_config_vars);\n        $smarty->_config[0]['files'][$_file] = true;\n\n        if ($_scope == 'parent') {\n                $smarty->_config[1]['vars'] = @array_merge($smarty->_config[1]['vars'], $_config_vars);\n                $smarty->_config[1]['files'][$_file] = true;\n        } else if ($_scope == 'global') {\n            for ($i = 1, $for_max = count($smarty->_config); $i < $for_max; $i++) {\n                $smarty->_config[$i]['vars'] = @array_merge($smarty->_config[$i]['vars'], $_config_vars);\n                $smarty->_config[$i]['files'][$_file] = true;\n            }\n        }\n\n        if ($smarty->debugging) {\n            $_params = array();\n            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');\n            $smarty->_smarty_debug_info[] = array('type'      => 'config',\n                                                'filename'  => $_file.' ['.$_section.'] '.$_scope,\n                                                'depth'     => $smarty->_inclusion_depth,\n                                                'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time);\n        }\n\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.counter.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {counter} function plugin\n *\n * Type:     function<br>\n * Name:     counter<br>\n * Purpose:  print out a counter value\n * @author Monte Ohrt <monte at ohrt dot com>\n * @link http://smarty.php.net/manual/en/language.function.counter.php {counter}\n *       (Smarty online manual)\n * @param array parameters\n * @param Smarty\n * @return string|null\n */\nfunction smarty_function_counter($params, &$smarty)\n{\n    static $counters = array();\n\n    $name = (isset($params['name'])) ? $params['name'] : 'default';\n    if (!isset($counters[$name])) {\n        $counters[$name] = array(\n            'start'=>1,\n            'skip'=>1,\n            'direction'=>'up',\n            'count'=>1\n            );\n    }\n    $counter =& $counters[$name];\n\n    if (isset($params['start'])) {\n        $counter['start'] = $counter['count'] = (int)$params['start'];\n    }\n\n    if (!empty($params['assign'])) {\n        $counter['assign'] = $params['assign'];\n    }\n\n    if (isset($counter['assign'])) {\n        $smarty->assign($counter['assign'], $counter['count']);\n    }\n    \n    if (isset($params['print'])) {\n        $print = (bool)$params['print'];\n    } else {\n        $print = empty($counter['assign']);\n    }\n\n    if ($print) {\n        $retval = $counter['count'];\n    } else {\n        $retval = null;\n    }\n\n    if (isset($params['skip'])) {\n        $counter['skip'] = $params['skip'];\n    }\n    \n    if (isset($params['direction'])) {\n        $counter['direction'] = $params['direction'];\n    }\n\n    if ($counter['direction'] == \"down\")\n        $counter['count'] -= $counter['skip'];\n    else\n        $counter['count'] += $counter['skip'];\n    \n    return $retval;\n    \n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.cycle.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty {cycle} function plugin\n *\n * Type:     function<br>\n * Name:     cycle<br>\n * Date:     May 3, 2002<br>\n * Purpose:  cycle through given values<br>\n * Input:\n *         - name = name of cycle (optional)\n *         - values = comma separated list of values to cycle,\n *                    or an array of values to cycle\n *                    (this can be left out for subsequent calls)\n *         - reset = boolean - resets given var to true\n *         - print = boolean - print var or not. default is true\n *         - advance = boolean - whether or not to advance the cycle\n *         - delimiter = the value delimiter, default is \",\"\n *         - assign = boolean, assigns to template var instead of\n *                    printed.\n *\n * Examples:<br>\n * <pre>\n * {cycle values=\"#eeeeee,#d0d0d0d\"}\n * {cycle name=row values=\"one,two,three\" reset=true}\n * {cycle name=row}\n * </pre>\n * @link http://smarty.php.net/manual/en/language.function.cycle.php {cycle}\n *       (Smarty online manual)\n * @author Monte Ohrt <monte at ohrt dot com>\n * @author credit to Mark Priatel <mpriatel@rogers.com>\n * @author credit to Gerard <gerard@interfold.com>\n * @author credit to Jason Sweat <jsweat_php@yahoo.com>\n * @version  1.3\n * @param array\n * @param Smarty\n * @return string|null\n */\nfunction smarty_function_cycle($params, &$smarty)\n{\n    static $cycle_vars;\n    \n    $name = (empty($params['name'])) ? 'default' : $params['name'];\n    $print = (isset($params['print'])) ? (bool)$params['print'] : true;\n    $advance = (isset($params['advance'])) ? (bool)$params['advance'] : true;\n    $reset = (isset($params['reset'])) ? (bool)$params['reset'] : false;\n            \n    if (!in_array('values', array_keys($params))) {\n        if(!isset($cycle_vars[$name]['values'])) {\n            $smarty->trigger_error(\"cycle: missing 'values' parameter\");\n            return;\n        }\n    } else {\n        if(isset($cycle_vars[$name]['values'])\n            && $cycle_vars[$name]['values'] != $params['values'] ) {\n            $cycle_vars[$name]['index'] = 0;\n        }\n        $cycle_vars[$name]['values'] = $params['values'];\n    }\n\n    if (isset($params['delimiter'])) {\n        $cycle_vars[$name]['delimiter'] = $params['delimiter'];\n    } elseif (!isset($cycle_vars[$name]['delimiter'])) {\n        $cycle_vars[$name]['delimiter'] = ',';       \n    }\n    \n    if(is_array($cycle_vars[$name]['values'])) {\n        $cycle_array = $cycle_vars[$name]['values'];\n    } else {\n        $cycle_array = explode($cycle_vars[$name]['delimiter'],$cycle_vars[$name]['values']);\n    }\n    \n    if(!isset($cycle_vars[$name]['index']) || $reset ) {\n        $cycle_vars[$name]['index'] = 0;\n    }\n    \n    if (isset($params['assign'])) {\n        $print = false;\n        $smarty->assign($params['assign'], $cycle_array[$cycle_vars[$name]['index']]);\n    }\n        \n    if($print) {\n        $retval = $cycle_array[$cycle_vars[$name]['index']];\n    } else {\n        $retval = null;\n    }\n\n    if($advance) {\n        if ( $cycle_vars[$name]['index'] >= count($cycle_array) -1 ) {\n            $cycle_vars[$name]['index'] = 0;\n        } else {\n            $cycle_vars[$name]['index']++;\n        }\n    }\n    \n    return $retval;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.debug.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {debug} function plugin\n *\n * Type:     function<br>\n * Name:     debug<br>\n * Date:     July 1, 2002<br>\n * Purpose:  popup debug window\n * @link http://smarty.php.net/manual/en/language.function.debug.php {debug}\n *       (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @version  1.0\n * @param array\n * @param Smarty\n * @return string output from {@link Smarty::_generate_debug_output()}\n */\nfunction smarty_function_debug($params, &$smarty)\n{\n    if (isset($params['output'])) {\n        $smarty->assign('_smarty_debug_output', $params['output']);\n    }\n    require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php');\n    return smarty_core_display_debug_console(null, $smarty);\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.eval.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {eval} function plugin\n *\n * Type:     function<br>\n * Name:     eval<br>\n * Purpose:  evaluate a template variable as a template<br>\n * @link http://smarty.php.net/manual/en/language.function.eval.php {eval}\n *       (Smarty online manual)\n * @author Monte Ohrt <monte at ohrt dot com>\n * @param array\n * @param Smarty\n */\nfunction smarty_function_eval($params, &$smarty)\n{\n\n    if (!isset($params['var'])) {\n        $smarty->trigger_error(\"eval: missing 'var' parameter\");\n        return;\n    }\n\n    if($params['var'] == '') {\n        return;\n    }\n\n    $smarty->_compile_source('evaluated template', $params['var'], $_var_compiled);\n\n    ob_start();\n    $smarty->_eval('?>' . $_var_compiled);\n    $_contents = ob_get_contents();\n    ob_end_clean();\n\n    if (!empty($params['assign'])) {\n        $smarty->assign($params['assign'], $_contents);\n    } else {\n        return $_contents;\n    }\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.fetch.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {fetch} plugin\n *\n * Type:     function<br>\n * Name:     fetch<br>\n * Purpose:  fetch file, web or ftp data and display results\n * @link http://smarty.php.net/manual/en/language.function.fetch.php {fetch}\n *       (Smarty online manual)\n * @author Monte Ohrt <monte at ohrt dot com>\n * @param array\n * @param Smarty\n * @return string|null if the assign parameter is passed, Smarty assigns the\n *                     result to a template variable\n */\nfunction smarty_function_fetch($params, &$smarty)\n{\n    if (empty($params['file'])) {\n        $smarty->_trigger_fatal_error(\"[plugin] parameter 'file' cannot be empty\");\n        return;\n    }\n\n    $content = '';\n    if ($smarty->security && !preg_match('!^(http|ftp)://!i', $params['file'])) {\n        $_params = array('resource_type' => 'file', 'resource_name' => $params['file']);\n        require_once(SMARTY_CORE_DIR . 'core.is_secure.php');\n        if(!smarty_core_is_secure($_params, $smarty)) {\n            $smarty->_trigger_fatal_error('[plugin] (secure mode) fetch \\'' . $params['file'] . '\\' is not allowed');\n            return;\n        }\n        \n        // fetch the file\n        if($fp = @fopen($params['file'],'r')) {\n            while(!feof($fp)) {\n                $content .= fgets ($fp,4096);\n            }\n            fclose($fp);\n        } else {\n            $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \\'' . $params['file'] . '\\'');\n            return;\n        }\n    } else {\n        // not a local file\n        if(preg_match('!^http://!i',$params['file'])) {\n            // http fetch\n            if($uri_parts = parse_url($params['file'])) {\n                // set defaults\n                $host = $server_name = $uri_parts['host'];\n                $timeout = 30;\n                $accept = \"image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\";\n                $agent = \"Smarty Template Engine \".$smarty->_version;\n                $referer = \"\";\n                $uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/';\n                $uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : '';\n                $_is_proxy = false;\n                if(empty($uri_parts['port'])) {\n                    $port = 80;\n                } else {\n                    $port = $uri_parts['port'];\n                }\n                if(!empty($uri_parts['user'])) {\n                    $user = $uri_parts['user'];\n                }\n                if(!empty($uri_parts['pass'])) {\n                    $pass = $uri_parts['pass'];\n                }\n                // loop through parameters, setup headers\n                foreach($params as $param_key => $param_value) {\n                    switch($param_key) {\n                        case \"file\":\n                        case \"assign\":\n                        case \"assign_headers\":\n                            break;\n                        case \"user\":\n                            if(!empty($param_value)) {\n                                $user = $param_value;\n                            }\n                            break;\n                        case \"pass\":\n                            if(!empty($param_value)) {\n                                $pass = $param_value;\n                            }\n                            break;\n                        case \"accept\":\n                            if(!empty($param_value)) {\n                                $accept = $param_value;\n                            }\n                            break;\n                        case \"header\":\n                            if(!empty($param_value)) {\n                                if(!preg_match('![\\w\\d-]+: .+!',$param_value)) {\n                                    $smarty->_trigger_fatal_error(\"[plugin] invalid header format '\".$param_value.\"'\");\n                                    return;\n                                } else {\n                                    $extra_headers[] = $param_value;\n                                }\n                            }\n                            break;\n                        case \"proxy_host\":\n                            if(!empty($param_value)) {\n                                $proxy_host = $param_value;\n                            }\n                            break;\n                        case \"proxy_port\":\n                            if(!preg_match('!\\D!', $param_value)) {\n                                $proxy_port = (int) $param_value;\n                            } else {\n                                $smarty->_trigger_fatal_error(\"[plugin] invalid value for attribute '\".$param_key.\"'\");\n                                return;\n                            }\n                            break;\n                        case \"agent\":\n                            if(!empty($param_value)) {\n                                $agent = $param_value;\n                            }\n                            break;\n                        case \"referer\":\n                            if(!empty($param_value)) {\n                                $referer = $param_value;\n                            }\n                            break;\n                        case \"timeout\":\n                            if(!preg_match('!\\D!', $param_value)) {\n                                $timeout = (int) $param_value;\n                            } else {\n                                $smarty->_trigger_fatal_error(\"[plugin] invalid value for attribute '\".$param_key.\"'\");\n                                return;\n                            }\n                            break;\n                        default:\n                            $smarty->_trigger_fatal_error(\"[plugin] unrecognized attribute '\".$param_key.\"'\");\n                            return;\n                    }\n                }\n                if(!empty($proxy_host) && !empty($proxy_port)) {\n                    $_is_proxy = true;\n                    $fp = fsockopen($proxy_host,$proxy_port,$errno,$errstr,$timeout);\n                } else {\n                    $fp = fsockopen($server_name,$port,$errno,$errstr,$timeout);\n                }\n\n                if(!$fp) {\n                    $smarty->_trigger_fatal_error(\"[plugin] unable to fetch: $errstr ($errno)\");\n                    return;\n                } else {\n                    if($_is_proxy) {\n                        fputs($fp, 'GET ' . $params['file'] . \" HTTP/1.0\\r\\n\");\n                    } else {\n                        fputs($fp, \"GET $uri HTTP/1.0\\r\\n\");\n                    }\n                    if(!empty($host)) {\n                        fputs($fp, \"Host: $host\\r\\n\");\n                    }\n                    if(!empty($accept)) {\n                        fputs($fp, \"Accept: $accept\\r\\n\");\n                    }\n                    if(!empty($agent)) {\n                        fputs($fp, \"User-Agent: $agent\\r\\n\");\n                    }\n                    if(!empty($referer)) {\n                        fputs($fp, \"Referer: $referer\\r\\n\");\n                    }\n                    if(isset($extra_headers) && is_array($extra_headers)) {\n                        foreach($extra_headers as $curr_header) {\n                            fputs($fp, $curr_header.\"\\r\\n\");\n                        }\n                    }\n                    if(!empty($user) && !empty($pass)) {\n                        fputs($fp, \"Authorization: BASIC \".base64_encode(\"$user:$pass\").\"\\r\\n\");\n                    }\n\n                    fputs($fp, \"\\r\\n\");\n                    while(!feof($fp)) {\n                        $content .= fgets($fp,4096);\n                    }\n                    fclose($fp);\n                    $csplit = preg_split(\"!\\r\\n\\r\\n!\",$content,2);\n\n                    $content = $csplit[1];\n\n                    if(!empty($params['assign_headers'])) {\n                        $smarty->assign($params['assign_headers'],preg_split(\"!\\r\\n!\",$csplit[0]));\n                    }\n                }\n            } else {\n                $smarty->_trigger_fatal_error(\"[plugin] unable to parse URL, check syntax\");\n                return;\n            }\n        } else {\n            // ftp fetch\n            if($fp = @fopen($params['file'],'r')) {\n                while(!feof($fp)) {\n                    $content .= fgets ($fp,4096);\n                }\n                fclose($fp);\n            } else {\n                $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \\'' . $params['file'] .'\\'');\n                return;\n            }\n        }\n\n    }\n\n\n    if (!empty($params['assign'])) {\n        $smarty->assign($params['assign'],$content);\n    } else {\n        return $content;\n    }\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.html_checkboxes.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {html_checkboxes} function plugin\n *\n * File:       function.html_checkboxes.php<br>\n * Type:       function<br>\n * Name:       html_checkboxes<br>\n * Date:       24.Feb.2003<br>\n * Purpose:    Prints out a list of checkbox input types<br>\n * Input:<br>\n *           - name       (optional) - string default \"checkbox\"\n *           - values     (required) - array\n *           - options    (optional) - associative array\n *           - checked    (optional) - array default not set\n *           - separator  (optional) - ie <br> or &nbsp;\n *           - output     (optional) - the output next to each checkbox\n *           - assign     (optional) - assign the output as an array to this variable\n * Examples:\n * <pre>\n * {html_checkboxes values=$ids output=$names}\n * {html_checkboxes values=$ids name='box' separator='<br>' output=$names}\n * {html_checkboxes values=$ids checked=$checked separator='<br>' output=$names}\n * </pre>\n * @link http://smarty.php.net/manual/en/language.function.html.checkboxes.php {html_checkboxes}\n *      (Smarty online manual)\n * @author     Christopher Kvarme <christopher.kvarme@flashjab.com>\n * @author credits to Monte Ohrt <monte at ohrt dot com>\n * @version    1.0\n * @param array\n * @param Smarty\n * @return string\n * @uses smarty_function_escape_special_chars()\n */\nfunction smarty_function_html_checkboxes($params, &$smarty)\n{\n    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');\n\n    $name = 'checkbox';\n    $values = null;\n    $options = null;\n    $selected = null;\n    $separator = '';\n    $labels = true;\n    $output = null;\n\n    $extra = '';\n\n    foreach($params as $_key => $_val) {\n        switch($_key) {\n            case 'name':\n            case 'separator':\n                $$_key = $_val;\n                break;\n\n            case 'labels':\n                $$_key = (bool)$_val;\n                break;\n\n            case 'options':\n                $$_key = (array)$_val;\n                break;\n\n            case 'values':\n            case 'output':\n                $$_key = array_values((array)$_val);\n                break;\n\n            case 'checked':\n            case 'selected':\n                $selected = array_map('strval', array_values((array)$_val));\n                break;\n\n            case 'checkboxes':\n                $smarty->trigger_error('html_checkboxes: the use of the \"checkboxes\" attribute is deprecated, use \"options\" instead', E_USER_WARNING);\n                $options = (array)$_val;\n                break;\n\n            case 'assign':\n                break;\n\n            default:\n                if(!is_array($_val)) {\n                    $extra .= ' '.$_key.'=\"'.smarty_function_escape_special_chars($_val).'\"';\n                } else {\n                    $smarty->trigger_error(\"html_checkboxes: extra attribute '$_key' cannot be an array\", E_USER_NOTICE);\n                }\n                break;\n        }\n    }\n\n    if (!isset($options) && !isset($values))\n        return ''; /* raise error here? */\n\n    settype($selected, 'array');\n    $_html_result = array();\n\n    if (isset($options)) {\n\n        foreach ($options as $_key=>$_val)\n            $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels);\n\n\n    } else {\n        foreach ($values as $_i=>$_key) {\n            $_val = isset($output[$_i]) ? $output[$_i] : '';\n            $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels);\n        }\n\n    }\n\n    if(!empty($params['assign'])) {\n        $smarty->assign($params['assign'], $_html_result);\n    } else {\n        return implode(\"\\n\",$_html_result);\n    }\n\n}\n\nfunction smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels) {\n    $_output = '';\n    if ($labels) $_output .= '<label>';\n    $_output .= '<input type=\"checkbox\" name=\"'\n        . smarty_function_escape_special_chars($name) . '[]\" value=\"'\n        . smarty_function_escape_special_chars($value) . '\"';\n\n    if (in_array((string)$value, $selected)) {\n        $_output .= ' checked=\"checked\"';\n    }\n    $_output .= $extra . ' />' . $output;\n    if ($labels) $_output .= '</label>';\n    $_output .=  $separator;\n\n    return $_output;\n}\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.html_image.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {html_image} function plugin\n *\n * Type:     function<br>\n * Name:     html_image<br>\n * Date:     Feb 24, 2003<br>\n * Purpose:  format HTML tags for the image<br>\n * Input:<br>\n *         - file = file (and path) of image (required)\n *         - height = image height (optional, default actual height)\n *         - width = image width (optional, default actual width)\n *         - basedir = base directory for absolute paths, default\n *                     is environment variable DOCUMENT_ROOT\n *         - path_prefix = prefix for path output (optional, default empty)\n *\n * Examples: {html_image file=\"/images/masthead.gif\"}\n * Output:   <img src=\"/images/masthead.gif\" width=400 height=23>\n * @link http://smarty.php.net/manual/en/language.function.html.image.php {html_image}\n *      (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @author credits to Duda <duda@big.hu> - wrote first image function\n *           in repository, helped with lots of functionality\n * @version  1.0\n * @param array\n * @param Smarty\n * @return string\n * @uses smarty_function_escape_special_chars()\n */\nfunction smarty_function_html_image($params, &$smarty)\n{\n    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');\n    \n    $alt = '';\n    $file = '';\n    $height = '';\n    $width = '';\n    $extra = '';\n    $prefix = '';\n    $suffix = '';\n    $path_prefix = '';\n    $server_vars = ($smarty->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];\n    $basedir = isset($server_vars['DOCUMENT_ROOT']) ? $server_vars['DOCUMENT_ROOT'] : '';\n    foreach($params as $_key => $_val) {\n        switch($_key) {\n            case 'file':\n            case 'height':\n            case 'width':\n            case 'dpi':\n            case 'path_prefix':\n            case 'basedir':\n                $$_key = $_val;\n                break;\n\n            case 'alt':\n                if(!is_array($_val)) {\n                    $$_key = smarty_function_escape_special_chars($_val);\n                } else {\n                    $smarty->trigger_error(\"html_image: extra attribute '$_key' cannot be an array\", E_USER_NOTICE);\n                }\n                break;\n\n            case 'link':\n            case 'href':\n                $prefix = '<a href=\"' . $_val . '\">';\n                $suffix = '</a>';\n                break;\n\n            default:\n                if(!is_array($_val)) {\n                    $extra .= ' '.$_key.'=\"'.smarty_function_escape_special_chars($_val).'\"';\n                } else {\n                    $smarty->trigger_error(\"html_image: extra attribute '$_key' cannot be an array\", E_USER_NOTICE);\n                }\n                break;\n        }\n    }\n\n    if (empty($file)) {\n        $smarty->trigger_error(\"html_image: missing 'file' parameter\", E_USER_NOTICE);\n        return;\n    }\n\n    if (substr($file,0,1) == '/') {\n        $_image_path = $basedir . $file;\n    } else {\n        $_image_path = $file;\n    }\n    \n    if(!isset($params['width']) || !isset($params['height'])) {\n        if(!$_image_data = @getimagesize($_image_path)) {\n            if(!file_exists($_image_path)) {\n                $smarty->trigger_error(\"html_image: unable to find '$_image_path'\", E_USER_NOTICE);\n                return;\n            } else if(!is_readable($_image_path)) {\n                $smarty->trigger_error(\"html_image: unable to read '$_image_path'\", E_USER_NOTICE);\n                return;\n            } else {\n                $smarty->trigger_error(\"html_image: '$_image_path' is not a valid image file\", E_USER_NOTICE);\n                return;\n            }\n        }\n        if ($smarty->security &&\n            ($_params = array('resource_type' => 'file', 'resource_name' => $_image_path)) &&\n            (require_once(SMARTY_CORE_DIR . 'core.is_secure.php')) &&\n            (!smarty_core_is_secure($_params, $smarty)) ) {\n            $smarty->trigger_error(\"html_image: (secure) '$_image_path' not in secure directory\", E_USER_NOTICE);\n        }        \n        \n        if(!isset($params['width'])) {\n            $width = $_image_data[0];\n        }\n        if(!isset($params['height'])) {\n            $height = $_image_data[1];\n        }\n\n    }\n\n    if(isset($params['dpi'])) {\n        if(strstr($server_vars['HTTP_USER_AGENT'], 'Mac')) {\n            $dpi_default = 72;\n        } else {\n            $dpi_default = 96;\n        }\n        $_resize = $dpi_default/$params['dpi'];\n        $width = round($width * $_resize);\n        $height = round($height * $_resize);\n    }\n\n    return $prefix . '<img src=\"'.$path_prefix.$file.'\" alt=\"'.$alt.'\" width=\"'.$width.'\" height=\"'.$height.'\"'.$extra.' />' . $suffix;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.html_options.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {html_options} function plugin\n *\n * Type:     function<br>\n * Name:     html_options<br>\n * Input:<br>\n *           - name       (optional) - string default \"select\"\n *           - values     (required if no options supplied) - array\n *           - options    (required if no values supplied) - associative array\n *           - selected   (optional) - string default not set\n *           - output     (required if not options supplied) - array\n * Purpose:  Prints the list of <option> tags generated from\n *           the passed parameters\n * @link http://smarty.php.net/manual/en/language.function.html.options.php {html_image}\n *      (Smarty online manual)\n * @author Monte Ohrt <monte at ohrt dot com>\n * @param array\n * @param Smarty\n * @return string\n * @uses smarty_function_escape_special_chars()\n */\nfunction smarty_function_html_options($params, &$smarty)\n{\n    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');\n    \n    $name = null;\n    $values = null;\n    $options = null;\n    $selected = array();\n    $output = null;\n    \n    $extra = '';\n    \n    foreach($params as $_key => $_val) {\n        switch($_key) {\n            case 'name':\n                $$_key = (string)$_val;\n                break;\n            \n            case 'options':\n                $$_key = (array)$_val;\n                break;\n                \n            case 'values':\n            case 'output':\n                $$_key = array_values((array)$_val);\n                break;\n\n            case 'selected':\n                $$_key = array_map('strval', array_values((array)$_val));\n                break;\n                \n            default:\n                if(!is_array($_val)) {\n                    $extra .= ' '.$_key.'=\"'.smarty_function_escape_special_chars($_val).'\"';\n                } else {\n                    $smarty->trigger_error(\"html_options: extra attribute '$_key' cannot be an array\", E_USER_NOTICE);\n                }\n                break;\n        }\n    }\n\n    if (!isset($options) && !isset($values))\n        return ''; /* raise error here? */\n\n    $_html_result = '';\n\n    if (isset($options)) {\n        \n        foreach ($options as $_key=>$_val)\n            $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected);\n\n    } else {\n        \n        foreach ($values as $_i=>$_key) {\n            $_val = isset($output[$_i]) ? $output[$_i] : '';\n            $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected);\n        }\n\n    }\n\n    if(!empty($name)) {\n        $_html_result = '<select name=\"' . $name . '\"' . $extra . '>' . \"\\n\" . $_html_result . '</select>' . \"\\n\";\n    }\n\n    return $_html_result;\n\n}\n\nfunction smarty_function_html_options_optoutput($key, $value, $selected) {\n    if(!is_array($value)) {\n        $_html_result = '<option label=\"' . smarty_function_escape_special_chars($value) . '\" value=\"' .\n            smarty_function_escape_special_chars($key) . '\"';\n        if (in_array((string)$key, $selected))\n            $_html_result .= ' selected=\"selected\"';\n        $_html_result .= '>' . smarty_function_escape_special_chars($value) . '</option>' . \"\\n\";\n    } else {\n        $_html_result = smarty_function_html_options_optgroup($key, $value, $selected);\n    }\n    return $_html_result;\n}\n\nfunction smarty_function_html_options_optgroup($key, $values, $selected) {\n    $optgroup_html = '<optgroup label=\"' . smarty_function_escape_special_chars($key) . '\">' . \"\\n\";\n    foreach ($values as $key => $value) {\n        $optgroup_html .= smarty_function_html_options_optoutput($key, $value, $selected);\n    }\n    $optgroup_html .= \"</optgroup>\\n\";\n    return $optgroup_html;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.html_radios.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {html_radios} function plugin\n *\n * File:       function.html_radios.php<br>\n * Type:       function<br>\n * Name:       html_radios<br>\n * Date:       24.Feb.2003<br>\n * Purpose:    Prints out a list of radio input types<br>\n * Input:<br>\n *           - name       (optional) - string default \"radio\"\n *           - values     (required) - array\n *           - options    (optional) - associative array\n *           - checked    (optional) - array default not set\n *           - separator  (optional) - ie <br> or &nbsp;\n *           - output     (optional) - the output next to each radio button\n *           - assign     (optional) - assign the output as an array to this variable\n * Examples:\n * <pre>\n * {html_radios values=$ids output=$names}\n * {html_radios values=$ids name='box' separator='<br>' output=$names}\n * {html_radios values=$ids checked=$checked separator='<br>' output=$names}\n * </pre>\n * @link http://smarty.php.net/manual/en/language.function.html.radios.php {html_radios}\n *      (Smarty online manual)\n * @author     Christopher Kvarme <christopher.kvarme@flashjab.com>\n * @author credits to Monte Ohrt <monte at ohrt dot com>\n * @version    1.0\n * @param array\n * @param Smarty\n * @return string\n * @uses smarty_function_escape_special_chars()\n */\nfunction smarty_function_html_radios($params, &$smarty)\n{\n    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');\n   \n    $name = 'radio';\n    $values = null;\n    $options = null;\n    $selected = null;\n    $separator = '';\n    $labels = true;\n    $label_ids = false;\n    $output = null;\n    $extra = '';\n\n    foreach($params as $_key => $_val) {\n        switch($_key) {\n            case 'name':\n            case 'separator':\n                $$_key = (string)$_val;\n                break;\n\n            case 'checked':\n            case 'selected':\n                if(is_array($_val)) {\n                    $smarty->trigger_error('html_radios: the \"' . $_key . '\" attribute cannot be an array', E_USER_WARNING);\n                } else {\n                    $selected = (string)$_val;\n                }\n                break;\n\n            case 'labels':\n            case 'label_ids':\n                $$_key = (bool)$_val;\n                break;\n\n            case 'options':\n                $$_key = (array)$_val;\n                break;\n\n            case 'values':\n            case 'output':\n                $$_key = array_values((array)$_val);\n                break;\n\n            case 'radios':\n                $smarty->trigger_error('html_radios: the use of the \"radios\" attribute is deprecated, use \"options\" instead', E_USER_WARNING);\n                $options = (array)$_val;\n                break;\n\n            case 'assign':\n                break;\n\n            default:\n                if(!is_array($_val)) {\n                    $extra .= ' '.$_key.'=\"'.smarty_function_escape_special_chars($_val).'\"';\n                } else {\n                    $smarty->trigger_error(\"html_radios: extra attribute '$_key' cannot be an array\", E_USER_NOTICE);\n                }\n                break;\n        }\n    }\n\n    if (!isset($options) && !isset($values))\n        return ''; /* raise error here? */\n\n    $_html_result = array();\n\n    if (isset($options)) {\n\n        foreach ($options as $_key=>$_val)\n            $_html_result[] = smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids);\n\n    } else {\n\n        foreach ($values as $_i=>$_key) {\n            $_val = isset($output[$_i]) ? $output[$_i] : '';\n            $_html_result[] = smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids);\n        }\n\n    }\n\n    if(!empty($params['assign'])) {\n        $smarty->assign($params['assign'], $_html_result);\n    } else {\n        return implode(\"\\n\",$_html_result);\n    }\n\n}\n\nfunction smarty_function_html_radios_output($name, $value, $output, $selected, $extra, $separator, $labels, $label_ids) {\n    $_output = '';\n    if ($labels) {\n      if($label_ids) {\n          $_id = smarty_function_escape_special_chars(preg_replace('![^\\w\\-\\.]!', '_', $name . '_' . $value));\n          $_output .= '<label for=\"' . $_id . '\">';\n      } else {\n          $_output .= '<label>';           \n      }\n   }\n   $_output .= '<input type=\"radio\" name=\"'\n        . smarty_function_escape_special_chars($name) . '\" value=\"'\n        . smarty_function_escape_special_chars($value) . '\"';\n\n   if ($labels && $label_ids) $_output .= ' id=\"' . $_id . '\"';\n\n    if ((string)$value==$selected) {\n        $_output .= ' checked=\"checked\"';\n    }\n    $_output .= $extra . ' />' . $output;\n    if ($labels) $_output .= '</label>';\n    $_output .=  $separator;\n\n    return $_output;\n}\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.html_select_date.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty {html_select_date} plugin\n *\n * Type:     function<br>\n * Name:     html_select_date<br>\n * Purpose:  Prints the dropdowns for date selection.\n *\n * ChangeLog:<br>\n *           - 1.0 initial release\n *           - 1.1 added support for +/- N syntax for begin\n *                and end year values. (Monte)\n *           - 1.2 added support for yyyy-mm-dd syntax for\n *                time value. (Jan Rosier)\n *           - 1.3 added support for choosing format for\n *                month values (Gary Loescher)\n *           - 1.3.1 added support for choosing format for\n *                day values (Marcus Bointon)\n *           - 1.3.2 support negative timestamps, force year\n *             dropdown to include given date unless explicitly set (Monte)\n *           - 1.3.4 fix behaviour of 0000-00-00 00:00:00 dates to match that\n *             of 0000-00-00 dates (cybot, boots)\n * @link http://smarty.php.net/manual/en/language.function.html.select.date.php {html_select_date}\n *      (Smarty online manual)\n * @version 1.3.4\n * @author Andrei Zmievski\n * @author Monte Ohrt <monte at ohrt dot com>\n * @param array\n * @param Smarty\n * @return string\n */\nfunction smarty_function_html_select_date($params, &$smarty)\n{\n    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');\n    require_once $smarty->_get_plugin_filepath('shared','make_timestamp');\n    require_once $smarty->_get_plugin_filepath('function','html_options');\n    /* Default values. */\n    $prefix          = \"Date_\";\n    $start_year      = strftime(\"%Y\");\n    $end_year        = $start_year;\n    $display_days    = true;\n    $display_months  = true;\n    $display_years   = true;\n    $month_format    = \"%B\";\n    /* Write months as numbers by default  GL */\n    $month_value_format = \"%m\";\n    $day_format      = \"%02d\";\n    /* Write day values using this format MB */\n    $day_value_format = \"%d\";\n    $year_as_text    = false;\n    /* Display years in reverse order? Ie. 2000,1999,.... */\n    $reverse_years   = false;\n    /* Should the select boxes be part of an array when returned from PHP?\n       e.g. setting it to \"birthday\", would create \"birthday[Day]\",\n       \"birthday[Month]\" & \"birthday[Year]\". Can be combined with prefix */\n    $field_array     = null;\n    /* <select size>'s of the different <select> tags.\n       If not set, uses default dropdown. */\n    $day_size        = null;\n    $month_size      = null;\n    $year_size       = null;\n    /* Unparsed attributes common to *ALL* the <select>/<input> tags.\n       An example might be in the template: all_extra ='class =\"foo\"'. */\n    $all_extra       = null;\n    /* Separate attributes for the tags. */\n    $day_extra       = null;\n    $month_extra     = null;\n    $year_extra      = null;\n    /* Order in which to display the fields.\n       \"D\" -> day, \"M\" -> month, \"Y\" -> year. */\n    $field_order     = 'MDY';\n    /* String printed between the different fields. */\n    $field_separator = \"\\n\";\n    $time = time();\n    $all_empty       = null;\n    $day_empty       = null;\n    $month_empty     = null;\n    $year_empty      = null;\n    $extra_attrs     = '';\n\n    foreach ($params as $_key=>$_value) {\n        switch ($_key) {\n            case 'prefix':\n            case 'time':\n            case 'start_year':\n            case 'end_year':\n            case 'month_format':\n            case 'day_format':\n            case 'day_value_format':\n            case 'field_array':\n            case 'day_size':\n            case 'month_size':\n            case 'year_size':\n            case 'all_extra':\n            case 'day_extra':\n            case 'month_extra':\n            case 'year_extra':\n            case 'field_order':\n            case 'field_separator':\n            case 'month_value_format':\n            case 'month_empty':\n            case 'day_empty':\n            case 'year_empty':\n                $$_key = (string)$_value;\n                break;\n\n            case 'all_empty':\n                $$_key = (string)$_value;\n                $day_empty = $month_empty = $year_empty = $all_empty;\n                break;\n\n            case 'display_days':\n            case 'display_months':\n            case 'display_years':\n            case 'year_as_text':\n            case 'reverse_years':\n                $$_key = (bool)$_value;\n                break;\n\n            default:\n                if(!is_array($_value)) {\n                    $extra_attrs .= ' '.$_key.'=\"'.smarty_function_escape_special_chars($_value).'\"';\n                } else {\n                    $smarty->trigger_error(\"html_select_date: extra attribute '$_key' cannot be an array\", E_USER_NOTICE);\n                }\n                break;\n        }\n    }\n\n    if (preg_match('!^-\\d+$!', $time)) {\n        // negative timestamp, use date()\n        $time = date('Y-m-d', $time);\n    }\n    // If $time is not in format yyyy-mm-dd\n    if (preg_match('/^(\\d{0,4}-\\d{0,2}-\\d{0,2})/', $time, $found)) {\n        $time = $found[1];\n    } else {\n        // use smarty_make_timestamp to get an unix timestamp and\n        // strftime to make yyyy-mm-dd\n        $time = strftime('%Y-%m-%d', smarty_make_timestamp($time));\n    }\n    // Now split this in pieces, which later can be used to set the select\n    $time = explode(\"-\", $time);\n\n    // make syntax \"+N\" or \"-N\" work with start_year and end_year\n    if (preg_match('!^(\\+|\\-)\\s*(\\d+)$!', $end_year, $match)) {\n        if ($match[1] == '+') {\n            $end_year = strftime('%Y') + $match[2];\n        } else {\n            $end_year = strftime('%Y') - $match[2];\n        }\n    }\n    if (preg_match('!^(\\+|\\-)\\s*(\\d+)$!', $start_year, $match)) {\n        if ($match[1] == '+') {\n            $start_year = strftime('%Y') + $match[2];\n        } else {\n            $start_year = strftime('%Y') - $match[2];\n        }\n    }\n    if (strlen($time[0]) > 0) {\n        if ($start_year > $time[0] && !isset($params['start_year'])) {\n            // force start year to include given date if not explicitly set\n            $start_year = $time[0];\n        }\n        if($end_year < $time[0] && !isset($params['end_year'])) {\n            // force end year to include given date if not explicitly set\n            $end_year = $time[0];\n        }\n    }\n\n    $field_order = strtoupper($field_order);\n\n    $html_result = $month_result = $day_result = $year_result = \"\";\n\n    $field_separator_count = -1;\n    if ($display_months) {\n    \t$field_separator_count++;\n        $month_names = array();\n        $month_values = array();\n        if(isset($month_empty)) {\n            $month_names[''] = $month_empty;\n            $month_values[''] = '';\n        }\n        for ($i = 1; $i <= 12; $i++) {\n            $month_names[$i] = strftime($month_format, mktime(0, 0, 0, $i, 1, 2000));\n            $month_values[$i] = strftime($month_value_format, mktime(0, 0, 0, $i, 1, 2000));\n        }\n\n        $month_result .= '<select name=';\n        if (null !== $field_array){\n            $month_result .= '\"' . $field_array . '[' . $prefix . 'Month]\"';\n        } else {\n            $month_result .= '\"' . $prefix . 'Month\"';\n        }\n        if (null !== $month_size){\n            $month_result .= ' size=\"' . $month_size . '\"';\n        }\n        if (null !== $month_extra){\n            $month_result .= ' ' . $month_extra;\n        }\n        if (null !== $all_extra){\n            $month_result .= ' ' . $all_extra;\n        }\n        $month_result .= $extra_attrs . '>'.\"\\n\";\n\n        $month_result .= smarty_function_html_options(array('output'     => $month_names,\n                                                            'values'     => $month_values,\n                                                            'selected'   => (int)$time[1] ? strftime($month_value_format, mktime(0, 0, 0, (int)$time[1], 1, 2000)) : '',\n                                                            'print_result' => false),\n                                                      $smarty);\n        $month_result .= '</select>';\n    }\n\n    if ($display_days) {\n    \t$field_separator_count++;\n        $days = array();\n        if (isset($day_empty)) {\n            $days[''] = $day_empty;\n            $day_values[''] = '';\n        }\n        for ($i = 1; $i <= 31; $i++) {\n            $days[] = sprintf($day_format, $i);\n            $day_values[] = sprintf($day_value_format, $i);\n        }\n\n        $day_result .= '<select name=';\n        if (null !== $field_array){\n            $day_result .= '\"' . $field_array . '[' . $prefix . 'Day]\"';\n        } else {\n            $day_result .= '\"' . $prefix . 'Day\"';\n        }\n        if (null !== $day_size){\n            $day_result .= ' size=\"' . $day_size . '\"';\n        }\n        if (null !== $all_extra){\n            $day_result .= ' ' . $all_extra;\n        }\n        if (null !== $day_extra){\n            $day_result .= ' ' . $day_extra;\n        }\n        $day_result .= $extra_attrs . '>'.\"\\n\";\n        $day_result .= smarty_function_html_options(array('output'     => $days,\n                                                          'values'     => $day_values,\n                                                          'selected'   => $time[2],\n                                                          'print_result' => false),\n                                                    $smarty);\n        $day_result .= '</select>';\n    }\n\n    if ($display_years) {\n    \t$field_separator_count++;\n        if (null !== $field_array){\n            $year_name = $field_array . '[' . $prefix . 'Year]';\n        } else {\n            $year_name = $prefix . 'Year';\n        }\n        if ($year_as_text) {\n            $year_result .= '<input type=\"text\" name=\"' . $year_name . '\" value=\"' . $time[0] . '\" size=\"4\" maxlength=\"4\"';\n            if (null !== $all_extra){\n                $year_result .= ' ' . $all_extra;\n            }\n            if (null !== $year_extra){\n                $year_result .= ' ' . $year_extra;\n            }\n            $year_result .= ' />';\n        } else {\n            $years = range((int)$start_year, (int)$end_year);\n            if ($reverse_years) {\n                rsort($years, SORT_NUMERIC);\n            } else {\n                sort($years, SORT_NUMERIC);\n            }\n            $yearvals = $years;\n            if(isset($year_empty)) {\n                array_unshift($years, $year_empty);\n                array_unshift($yearvals, '');\n            }\n            $year_result .= '<select name=\"' . $year_name . '\"';\n            if (null !== $year_size){\n                $year_result .= ' size=\"' . $year_size . '\"';\n            }\n            if (null !== $all_extra){\n                $year_result .= ' ' . $all_extra;\n            }\n            if (null !== $year_extra){\n                $year_result .= ' ' . $year_extra;\n            }\n            $year_result .= $extra_attrs . '>'.\"\\n\";\n            $year_result .= smarty_function_html_options(array('output' => $years,\n                                                               'values' => $yearvals,\n                                                               'selected'   => $time[0],\n                                                               'print_result' => false),\n                                                         $smarty);\n            $year_result .= '</select>';\n        }\n    }\n\n    // Loop thru the field_order field\n    for ($i = 0; $i <= 2; $i++){\n        $c = substr($field_order, $i, 1);\n        switch ($c){\n            case 'D':\n                $html_result .= $day_result;\n                break;\n\n            case 'M':\n                $html_result .= $month_result;\n                break;\n\n            case 'Y':\n                $html_result .= $year_result;\n                break;\n        }\n        // Add the field seperator\n        if($i < $field_separator_count) {\n            $html_result .= $field_separator;\n        }\n    }\n\n    return $html_result;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.html_select_time.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {html_select_time} function plugin\n *\n * Type:     function<br>\n * Name:     html_select_time<br>\n * Purpose:  Prints the dropdowns for time selection\n * @link http://smarty.php.net/manual/en/language.function.html.select.time.php {html_select_time}\n *          (Smarty online manual)\n * @author Roberto Berto <roberto@berto.net>\n * @credits Monte Ohrt <monte AT ohrt DOT com>\n * @param array\n * @param Smarty\n * @return string\n * @uses smarty_make_timestamp()\n */\nfunction smarty_function_html_select_time($params, &$smarty)\n{\n    require_once $smarty->_get_plugin_filepath('shared','make_timestamp');\n    require_once $smarty->_get_plugin_filepath('function','html_options');\n    /* Default values. */\n    $prefix             = \"Time_\";\n    $time               = time();\n    $display_hours      = true;\n    $display_minutes    = true;\n    $display_seconds    = true;\n    $display_meridian   = true;\n    $use_24_hours       = true;\n    $minute_interval    = 1;\n    $second_interval    = 1;\n    /* Should the select boxes be part of an array when returned from PHP?\n       e.g. setting it to \"birthday\", would create \"birthday[Hour]\",\n       \"birthday[Minute]\", \"birthday[Seconds]\" & \"birthday[Meridian]\".\n       Can be combined with prefix. */\n    $field_array        = null;\n    $all_extra          = null;\n    $hour_extra         = null;\n    $minute_extra       = null;\n    $second_extra       = null;\n    $meridian_extra     = null;\n\n    foreach ($params as $_key=>$_value) {\n        switch ($_key) {\n            case 'prefix':\n            case 'time':\n            case 'field_array':\n            case 'all_extra':\n            case 'hour_extra':\n            case 'minute_extra':\n            case 'second_extra':\n            case 'meridian_extra':\n                $$_key = (string)$_value;\n                break;\n\n            case 'display_hours':\n            case 'display_minutes':\n            case 'display_seconds':\n            case 'display_meridian':\n            case 'use_24_hours':\n                $$_key = (bool)$_value;\n                break;\n\n            case 'minute_interval':\n            case 'second_interval':\n                $$_key = (int)$_value;\n                break;\n\n            default:\n                $smarty->trigger_error(\"[html_select_time] unknown parameter $_key\", E_USER_WARNING);\n        }\n    }\n\n    $time = smarty_make_timestamp($time);\n\n    $html_result = '';\n\n    if ($display_hours) {\n        $hours       = $use_24_hours ? range(0, 23) : range(1, 12);\n        $hour_fmt = $use_24_hours ? '%H' : '%I';\n        for ($i = 0, $for_max = count($hours); $i < $for_max; $i++)\n            $hours[$i] = sprintf('%02d', $hours[$i]);\n        $html_result .= '<select name=';\n        if (null !== $field_array) {\n            $html_result .= '\"' . $field_array . '[' . $prefix . 'Hour]\"';\n        } else {\n            $html_result .= '\"' . $prefix . 'Hour\"';\n        }\n        if (null !== $hour_extra){\n            $html_result .= ' ' . $hour_extra;\n        }\n        if (null !== $all_extra){\n            $html_result .= ' ' . $all_extra;\n        }\n        $html_result .= '>'.\"\\n\";\n        $html_result .= smarty_function_html_options(array('output'          => $hours,\n                                                           'values'          => $hours,\n                                                           'selected'      => strftime($hour_fmt, $time),\n                                                           'print_result' => false),\n                                                     $smarty);\n        $html_result .= \"</select>\\n\";\n    }\n\n    if ($display_minutes) {\n        $all_minutes = range(0, 59);\n        for ($i = 0, $for_max = count($all_minutes); $i < $for_max; $i+= $minute_interval)\n            $minutes[] = sprintf('%02d', $all_minutes[$i]);\n        $selected = intval(floor(strftime('%M', $time) / $minute_interval) * $minute_interval);\n        $html_result .= '<select name=';\n        if (null !== $field_array) {\n            $html_result .= '\"' . $field_array . '[' . $prefix . 'Minute]\"';\n        } else {\n            $html_result .= '\"' . $prefix . 'Minute\"';\n        }\n        if (null !== $minute_extra){\n            $html_result .= ' ' . $minute_extra;\n        }\n        if (null !== $all_extra){\n            $html_result .= ' ' . $all_extra;\n        }\n        $html_result .= '>'.\"\\n\";\n        \n        $html_result .= smarty_function_html_options(array('output'          => $minutes,\n                                                           'values'          => $minutes,\n                                                           'selected'      => $selected,\n                                                           'print_result' => false),\n                                                     $smarty);\n        $html_result .= \"</select>\\n\";\n    }\n\n    if ($display_seconds) {\n        $all_seconds = range(0, 59);\n        for ($i = 0, $for_max = count($all_seconds); $i < $for_max; $i+= $second_interval)\n            $seconds[] = sprintf('%02d', $all_seconds[$i]);\n        $selected = intval(floor(strftime('%S', $time) / $second_interval) * $second_interval);\n        $html_result .= '<select name=';\n        if (null !== $field_array) {\n            $html_result .= '\"' . $field_array . '[' . $prefix . 'Second]\"';\n        } else {\n            $html_result .= '\"' . $prefix . 'Second\"';\n        }\n        \n        if (null !== $second_extra){\n            $html_result .= ' ' . $second_extra;\n        }\n        if (null !== $all_extra){\n            $html_result .= ' ' . $all_extra;\n        }\n        $html_result .= '>'.\"\\n\";\n        \n        $html_result .= smarty_function_html_options(array('output'          => $seconds,\n                                                           'values'          => $seconds,\n                                                           'selected'      => $selected,\n                                                           'print_result' => false),\n                                                     $smarty);\n        $html_result .= \"</select>\\n\";\n    }\n\n    if ($display_meridian && !$use_24_hours) {\n        $html_result .= '<select name=';\n        if (null !== $field_array) {\n            $html_result .= '\"' . $field_array . '[' . $prefix . 'Meridian]\"';\n        } else {\n            $html_result .= '\"' . $prefix . 'Meridian\"';\n        }\n        \n        if (null !== $meridian_extra){\n            $html_result .= ' ' . $meridian_extra;\n        }\n        if (null !== $all_extra){\n            $html_result .= ' ' . $all_extra;\n        }\n        $html_result .= '>'.\"\\n\";\n        \n        $html_result .= smarty_function_html_options(array('output'          => array('AM', 'PM'),\n                                                           'values'          => array('am', 'pm'),\n                                                           'selected'      => strtolower(strftime('%p', $time)),\n                                                           'print_result' => false),\n                                                     $smarty);\n        $html_result .= \"</select>\\n\";\n    }\n\n    return $html_result;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.html_table.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {html_table} function plugin\n *\n * Type:     function<br>\n * Name:     html_table<br>\n * Date:     Feb 17, 2003<br>\n * Purpose:  make an html table from an array of data<br>\n * Input:<br>\n *         - loop = array to loop through\n *         - cols = number of columns, comma separated list of column names\n *                  or array of column names\n *         - rows = number of rows\n *         - table_attr = table attributes\n *         - th_attr = table heading attributes (arrays are cycled)\n *         - tr_attr = table row attributes (arrays are cycled)\n *         - td_attr = table cell attributes (arrays are cycled)\n *         - trailpad = value to pad trailing cells with\n *         - caption = text for caption element \n *         - vdir = vertical direction (default: \"down\", means top-to-bottom)\n *         - hdir = horizontal direction (default: \"right\", means left-to-right)\n *         - inner = inner loop (default \"cols\": print $loop line by line,\n *                   $loop will be printed column by column otherwise)\n *\n *\n * Examples:\n * <pre>\n * {table loop=$data}\n * {table loop=$data cols=4 tr_attr='\"bgcolor=red\"'}\n * {table loop=$data cols=\"first,second,third\" tr_attr=$colors}\n * </pre>\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @author credit to Messju Mohr <messju at lammfellpuschen dot de>\n * @author credit to boots <boots dot smarty at yahoo dot com>\n * @version  1.1\n * @link http://smarty.php.net/manual/en/language.function.html.table.php {html_table}\n *          (Smarty online manual)\n * @param array\n * @param Smarty\n * @return string\n */\nfunction smarty_function_html_table($params, &$smarty)\n{\n    $table_attr = 'border=\"1\"';\n    $tr_attr = '';\n    $th_attr = '';\n    $td_attr = '';\n    $cols = $cols_count = 3;\n    $rows = 3;\n    $trailpad = '&nbsp;';\n    $vdir = 'down';\n    $hdir = 'right';\n    $inner = 'cols';\n    $caption = '';\n\n    if (!isset($params['loop'])) {\n        $smarty->trigger_error(\"html_table: missing 'loop' parameter\");\n        return;\n    }\n\n    foreach ($params as $_key=>$_value) {\n        switch ($_key) {\n            case 'loop':\n                $$_key = (array)$_value;\n                break;\n\n            case 'cols':\n                if (is_array($_value) && !empty($_value)) {\n                    $cols = $_value;\n                    $cols_count = count($_value);\n                } elseif (!is_numeric($_value) && is_string($_value) && !empty($_value)) {\n                    $cols = explode(',', $_value);\n                    $cols_count = count($cols);\n                } elseif (!empty($_value)) {\n                    $cols_count = (int)$_value;\n                } else {\n                    $cols_count = $cols;\n                }\n                break;\n\n            case 'rows':\n                $$_key = (int)$_value;\n                break;\n\n            case 'table_attr':\n            case 'trailpad':\n            case 'hdir':\n            case 'vdir':\n            case 'inner':\n            case 'caption':\n                $$_key = (string)$_value;\n                break;\n\n            case 'tr_attr':\n            case 'td_attr':\n            case 'th_attr':\n                $$_key = $_value;\n                break;\n        }\n    }\n\n    $loop_count = count($loop);\n    if (empty($params['rows'])) {\n        /* no rows specified */\n        $rows = ceil($loop_count/$cols_count);\n    } elseif (empty($params['cols'])) {\n        if (!empty($params['rows'])) {\n            /* no cols specified, but rows */\n            $cols_count = ceil($loop_count/$rows);\n        }\n    }\n\n    $output = \"<table $table_attr>\\n\";\n\n    if (!empty($caption)) {\n        $output .= '<caption>' . $caption . \"</caption>\\n\";\n    }\n\n    if (is_array($cols)) {\n        $cols = ($hdir == 'right') ? $cols : array_reverse($cols);\n        $output .= \"<thead><tr>\\n\";\n\n        for ($r=0; $r<$cols_count; $r++) {\n            $output .= '<th' . smarty_function_html_table_cycle('th', $th_attr, $r) . '>';\n            $output .= $cols[$r];\n            $output .= \"</th>\\n\";\n        }\n        $output .= \"</tr></thead>\\n\";\n    }\n\n    $output .= \"<tbody>\\n\";\n    for ($r=0; $r<$rows; $r++) {\n        $output .= \"<tr\" . smarty_function_html_table_cycle('tr', $tr_attr, $r) . \">\\n\";\n        $rx =  ($vdir == 'down') ? $r*$cols_count : ($rows-1-$r)*$cols_count;\n\n        for ($c=0; $c<$cols_count; $c++) {\n            $x =  ($hdir == 'right') ? $rx+$c : $rx+$cols_count-1-$c;\n            if ($inner!='cols') {\n                /* shuffle x to loop over rows*/\n                $x = floor($x/$cols_count) + ($x%$cols_count)*$rows;\n            }\n\n            if ($x<$loop_count) {\n                $output .= \"<td\" . smarty_function_html_table_cycle('td', $td_attr, $c) . \">\" . $loop[$x] . \"</td>\\n\";\n            } else {\n                $output .= \"<td\" . smarty_function_html_table_cycle('td', $td_attr, $c) . \">$trailpad</td>\\n\";\n            }\n        }\n        $output .= \"</tr>\\n\";\n    }\n    $output .= \"</tbody>\\n\";\n    $output .= \"</table>\\n\";\n    \n    return $output;\n}\n\nfunction smarty_function_html_table_cycle($name, $var, $no) {\n    if(!is_array($var)) {\n        $ret = $var;\n    } else {\n        $ret = $var[$no % count($var)];\n    }\n    \n    return ($ret) ? ' '.$ret : '';\n}\n\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.mailto.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {mailto} function plugin\n *\n * Type:     function<br>\n * Name:     mailto<br>\n * Date:     May 21, 2002\n * Purpose:  automate mailto address link creation, and optionally\n *           encode them.<br>\n * Input:<br>\n *         - address = e-mail address\n *         - text = (optional) text to display, default is address\n *         - encode = (optional) can be one of:\n *                * none : no encoding (default)\n *                * javascript : encode with javascript\n *                * javascript_charcode : encode with javascript charcode\n *                * hex : encode with hexidecimal (no javascript)\n *         - cc = (optional) address(es) to carbon copy\n *         - bcc = (optional) address(es) to blind carbon copy\n *         - subject = (optional) e-mail subject\n *         - newsgroups = (optional) newsgroup(s) to post to\n *         - followupto = (optional) address(es) to follow up to\n *         - extra = (optional) extra tags for the href link\n *\n * Examples:\n * <pre>\n * {mailto address=\"me@domain.com\"}\n * {mailto address=\"me@domain.com\" encode=\"javascript\"}\n * {mailto address=\"me@domain.com\" encode=\"hex\"}\n * {mailto address=\"me@domain.com\" subject=\"Hello to you!\"}\n * {mailto address=\"me@domain.com\" cc=\"you@domain.com,they@domain.com\"}\n * {mailto address=\"me@domain.com\" extra='class=\"mailto\"'}\n * </pre>\n * @link http://smarty.php.net/manual/en/language.function.mailto.php {mailto}\n *          (Smarty online manual)\n * @version  1.2\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @author   credits to Jason Sweat (added cc, bcc and subject functionality)\n * @param    array\n * @param    Smarty\n * @return   string\n */\nfunction smarty_function_mailto($params, &$smarty)\n{\n    $extra = '';\n\n    if (empty($params['address'])) {\n        $smarty->trigger_error(\"mailto: missing 'address' parameter\");\n        return;\n    } else {\n        $address = $params['address'];\n    }\n\n    $text = $address;\n\n    // netscape and mozilla do not decode %40 (@) in BCC field (bug?)\n    // so, don't encode it.\n    $search = array('%40', '%2C');\n    $replace  = array('@', ',');\n    $mail_parms = array();\n    foreach ($params as $var=>$value) {\n        switch ($var) {\n            case 'cc':\n            case 'bcc':\n            case 'followupto':\n                if (!empty($value))\n                    $mail_parms[] = $var.'='.str_replace($search,$replace,rawurlencode($value));\n                break;\n                \n            case 'subject':\n            case 'newsgroups':\n                $mail_parms[] = $var.'='.rawurlencode($value);\n                break;\n\n            case 'extra':\n            case 'text':\n                $$var = $value;\n\n            default:\n        }\n    }\n\n    $mail_parm_vals = '';\n    for ($i=0; $i<count($mail_parms); $i++) {\n        $mail_parm_vals .= (0==$i) ? '?' : '&';\n        $mail_parm_vals .= $mail_parms[$i];\n    }\n    $address .= $mail_parm_vals;\n\n    $encode = (empty($params['encode'])) ? 'none' : $params['encode'];\n    if (!in_array($encode,array('javascript','javascript_charcode','hex','none')) ) {\n        $smarty->trigger_error(\"mailto: 'encode' parameter must be none, javascript or hex\");\n        return;\n    }\n\n    if ($encode == 'javascript' ) {\n        $string = 'document.write(\\'<a href=\"mailto:'.$address.'\" '.$extra.'>'.$text.'</a>\\');';\n\n        $js_encode = '';\n        for ($x=0; $x < strlen($string); $x++) {\n            $js_encode .= '%' . bin2hex($string[$x]);\n        }\n\n        return '<script type=\"text/javascript\">eval(unescape(\\''.$js_encode.'\\'))</script>';\n\n    } elseif ($encode == 'javascript_charcode' ) {\n        $string = '<a href=\"mailto:'.$address.'\" '.$extra.'>'.$text.'</a>';\n\n        for($x = 0, $y = strlen($string); $x < $y; $x++ ) {\n            $ord[] = ord($string[$x]);   \n        }\n\n        $_ret = \"<script type=\\\"text/javascript\\\" language=\\\"javascript\\\">\\n\";\n        $_ret .= \"<!--\\n\";\n        $_ret .= \"{document.write(String.fromCharCode(\";\n        $_ret .= implode(',',$ord);\n        $_ret .= \"))\";\n        $_ret .= \"}\\n\";\n        $_ret .= \"//-->\\n\";\n        $_ret .= \"</script>\\n\";\n        \n        return $_ret;\n        \n        \n    } elseif ($encode == 'hex') {\n\n        preg_match('!^(.*)(\\?.*)$!',$address,$match);\n        if(!empty($match[2])) {\n            $smarty->trigger_error(\"mailto: hex encoding does not work with extra attributes. Try javascript.\");\n            return;\n        }\n        $address_encode = '';\n        for ($x=0; $x < strlen($address); $x++) {\n            if(preg_match('!\\w!',$address[$x])) {\n                $address_encode .= '%' . bin2hex($address[$x]);\n            } else {\n                $address_encode .= $address[$x];\n            }\n        }\n        $text_encode = '';\n        for ($x=0; $x < strlen($text); $x++) {\n            $text_encode .= '&#x' . bin2hex($text[$x]).';';\n        }\n\n        $mailto = \"&#109;&#97;&#105;&#108;&#116;&#111;&#58;\";\n        return '<a href=\"'.$mailto.$address_encode.'\" '.$extra.'>'.$text_encode.'</a>';\n\n    } else {\n        // no encoding\n        return '<a href=\"mailto:'.$address.'\" '.$extra.'>'.$text.'</a>';\n\n    }\n\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.math.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {math} function plugin\n *\n * Type:     function<br>\n * Name:     math<br>\n * Purpose:  handle math computations in template<br>\n * @link http://smarty.php.net/manual/en/language.function.math.php {math}\n *          (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param array\n * @param Smarty\n * @return string\n */\nfunction smarty_function_math($params, &$smarty)\n{\n    // be sure equation parameter is present\n    if (empty($params['equation'])) {\n        $smarty->trigger_error(\"math: missing equation parameter\");\n        return;\n    }\n\n    // strip out backticks, not necessary for math\n    $equation = str_replace('`','',$params['equation']);\n\n    // make sure parenthesis are balanced\n    if (substr_count($equation,\"(\") != substr_count($equation,\")\")) {\n        $smarty->trigger_error(\"math: unbalanced parenthesis\");\n        return;\n    }\n\n    // match all vars in equation, make sure all are passed\n    preg_match_all(\"!(?:0x[a-fA-F0-9]+)|([a-zA-Z][a-zA-Z0-9_]*)!\",$equation, $match);\n    $allowed_funcs = array('int','abs','ceil','cos','exp','floor','log','log10',\n                           'max','min','pi','pow','rand','round','sin','sqrt','srand','tan');\n    \n    foreach($match[1] as $curr_var) {\n        if ($curr_var && !in_array($curr_var, array_keys($params)) && !in_array($curr_var, $allowed_funcs)) {\n            $smarty->trigger_error(\"math: function call $curr_var not allowed\");\n            return;\n        }\n    }\n\n    foreach($params as $key => $val) {\n        if ($key != \"equation\" && $key != \"format\" && $key != \"assign\") {\n            // make sure value is not empty\n            if (strlen($val)==0) {\n                $smarty->trigger_error(\"math: parameter $key is empty\");\n                return;\n            }\n            if (!is_numeric($val)) {\n                $smarty->trigger_error(\"math: parameter $key: is not numeric\");\n                return;\n            }\n            $equation = preg_replace(\"/\\b$key\\b/\", \" \\$params['$key'] \", $equation);\n        }\n    }\n\n    eval(\"\\$smarty_math_result = \".$equation.\";\");\n\n    if (empty($params['format'])) {\n        if (empty($params['assign'])) {\n            return $smarty_math_result;\n        } else {\n            $smarty->assign($params['assign'],$smarty_math_result);\n        }\n    } else {\n        if (empty($params['assign'])){\n            printf($params['format'],$smarty_math_result);\n        } else {\n            $smarty->assign($params['assign'],sprintf($params['format'],$smarty_math_result));\n        }\n    }\n}\n\n/* vim: set expandtab: */\n\n?>"
  },
  {
    "path": "lib/smarty/plugins/function.popup.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {popup} function plugin\n *\n * Type:     function<br>\n * Name:     popup<br>\n * Purpose:  make text pop up in windows via overlib\n * @link http://smarty.php.net/manual/en/language.function.popup.php {popup}\n *          (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param array\n * @param Smarty\n * @return string\n */\nfunction smarty_function_popup($params, &$smarty)\n{\n    $append = '';\n    foreach ($params as $_key=>$_value) {\n        switch ($_key) {\n            case 'text':\n            case 'trigger':\n            case 'function':\n            case 'inarray':\n                $$_key = (string)$_value;\n                if ($_key == 'function' || $_key == 'inarray')\n                    $append .= ',' . strtoupper($_key) . \",'$_value'\";\n                break;\n\n            case 'caption':\n            case 'closetext':\n            case 'status':\n                $append .= ',' . strtoupper($_key) . \",'\" . str_replace(\"'\",\"\\'\",$_value) . \"'\";\n                break;\n\n            case 'fgcolor':\n            case 'bgcolor':\n            case 'textcolor':\n            case 'capcolor':\n            case 'closecolor':\n            case 'textfont':\n            case 'captionfont':\n            case 'closefont':\n            case 'fgbackground':\n            case 'bgbackground':\n            case 'caparray':\n            case 'capicon':\n            case 'background':\n            case 'frame':\n                $append .= ',' . strtoupper($_key) . \",'$_value'\";\n                break;\n\n            case 'textsize':\n            case 'captionsize':\n            case 'closesize':\n            case 'width':\n            case 'height':\n            case 'border':\n            case 'offsetx':\n            case 'offsety':\n            case 'snapx':\n            case 'snapy':\n            case 'fixx':\n            case 'fixy':\n            case 'padx':\n            case 'pady':\n            case 'timeout':\n            case 'delay':\n                $append .= ',' . strtoupper($_key) . \",$_value\";\n                break;\n\n            case 'sticky':\n            case 'left':\n            case 'right':\n            case 'center':\n            case 'above':\n            case 'below':\n            case 'noclose':\n            case 'autostatus':\n            case 'autostatuscap':\n            case 'fullhtml':\n            case 'hauto':\n            case 'vauto':\n            case 'mouseoff':\n            case 'followmouse':\n            case 'closeclick':\n                if ($_value) $append .= ',' . strtoupper($_key);\n                break;\n\n            default:\n                $smarty->trigger_error(\"[popup] unknown parameter $_key\", E_USER_WARNING);\n        }\n    }\n\n    if (empty($text) && !isset($inarray) && empty($function)) {\n        $smarty->trigger_error(\"overlib: attribute 'text' or 'inarray' or 'function' required\");\n        return false;\n    }\n\n    if (empty($trigger)) { $trigger = \"onmouseover\"; }\n\n    $retval = $trigger . '=\"return overlib(\\''.preg_replace(array(\"!'!\",\"![\\r\\n]!\"),array(\"\\'\",'\\r'),$text).'\\'';\n    $retval .= $append . ');\"';\n    if ($trigger == 'onmouseover')\n       $retval .= ' onmouseout=\"nd();\"';\n\n\n    return $retval;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/function.popup_init.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {popup_init} function plugin\n *\n * Type:     function<br>\n * Name:     popup_init<br>\n * Purpose:  initialize overlib\n * @link http://smarty.php.net/manual/en/language.function.popup.init.php {popup_init}\n *          (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param array\n * @param Smarty\n * @return string\n */\nfunction smarty_function_popup_init($params, &$smarty)\n{\n    $zindex = 1000;\n    \n    if (!empty($params['zindex'])) {\n        $zindex = $params['zindex'];\n    }\n    \n    if (!empty($params['src'])) {\n        return '<div id=\"overDiv\" style=\"position:absolute; visibility:hidden; z-index:'.$zindex.';\"></div>' . \"\\n\"\n         . '<script type=\"text/javascript\" language=\"JavaScript\" src=\"'.$params['src'].'\"></script>' . \"\\n\";\n    } else {\n        $smarty->trigger_error(\"popup_init: missing src parameter\");\n    }\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.capitalize.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty capitalize modifier plugin\n *\n * Type:     modifier<br>\n * Name:     capitalize<br>\n * Purpose:  capitalize words in the string\n * @link http://smarty.php.net/manual/en/language.modifiers.php#LANGUAGE.MODIFIER.CAPITALIZE\n *      capitalize (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @return string\n */\nfunction smarty_modifier_capitalize($string, $uc_digits = false)\n{\n    smarty_modifier_capitalize_ucfirst(null, $uc_digits);\n    return preg_replace_callback('!\\'?\\b\\w(\\w|\\')*\\b!', 'smarty_modifier_capitalize_ucfirst', $string);\n}\n\nfunction smarty_modifier_capitalize_ucfirst($string, $uc_digits = null)\n{\n    static $_uc_digits = false;\n    \n    if(isset($uc_digits)) {\n        $_uc_digits = $uc_digits;\n        return;\n    }\n    \n    if(substr($string[0],0,1) != \"'\" && !preg_match(\"!\\d!\",$string[0]) || $_uc_digits)\n        return ucfirst($string[0]);\n    else\n        return $string[0];\n}\n\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.cat.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty cat modifier plugin\n *\n * Type:     modifier<br>\n * Name:     cat<br>\n * Date:     Feb 24, 2003\n * Purpose:  catenate a value to a variable\n * Input:    string to catenate\n * Example:  {$var|cat:\"foo\"}\n * @link http://smarty.php.net/manual/en/language.modifier.cat.php cat\n *          (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @version 1.0\n * @param string\n * @param string\n * @return string\n */\nfunction smarty_modifier_cat($string, $cat)\n{\n    return $string . $cat;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.count_characters.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty count_characters modifier plugin\n *\n * Type:     modifier<br>\n * Name:     count_characteres<br>\n * Purpose:  count the number of characters in a text\n * @link http://smarty.php.net/manual/en/language.modifier.count.characters.php\n *          count_characters (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @param boolean include whitespace in the character count\n * @return integer\n */\nfunction smarty_modifier_count_characters($string, $include_spaces = false)\n{\n    if ($include_spaces)\n       return(strlen($string));\n\n    return preg_match_all(\"/[^\\s]/\",$string, $match);\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.count_paragraphs.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty count_paragraphs modifier plugin\n *\n * Type:     modifier<br>\n * Name:     count_paragraphs<br>\n * Purpose:  count the number of paragraphs in a text\n * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php\n *          count_paragraphs (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @return integer\n */\nfunction smarty_modifier_count_paragraphs($string)\n{\n    // count \\r or \\n characters\n    return count(preg_split('/[\\r\\n]+/', $string));\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.count_sentences.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty count_sentences modifier plugin\n *\n * Type:     modifier<br>\n * Name:     count_sentences\n * Purpose:  count the number of sentences in a text\n * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php\n *          count_sentences (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @return integer\n */\nfunction smarty_modifier_count_sentences($string)\n{\n    // find periods with a word before but not after.\n    return preg_match_all('/[^\\s]\\.(?!\\w)/', $string, $match);\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.count_words.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty count_words modifier plugin\n *\n * Type:     modifier<br>\n * Name:     count_words<br>\n * Purpose:  count the number of words in a text\n * @link http://smarty.php.net/manual/en/language.modifier.count.words.php\n *          count_words (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @return integer\n */\nfunction smarty_modifier_count_words($string)\n{\n    // split text by ' ',\\r,\\n,\\f,\\t\n    $split_array = preg_split('/\\s+/',$string);\n    // count matches that contain alphanumerics\n    $word_count = preg_grep('/[a-zA-Z0-9\\\\x80-\\\\xff]/', $split_array);\n\n    return count($word_count);\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.date_format.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Include the {@link shared.make_timestamp.php} plugin\n */\nrequire_once $smarty->_get_plugin_filepath('shared', 'make_timestamp');\n/**\n * Smarty date_format modifier plugin\n *\n * Type:     modifier<br>\n * Name:     date_format<br>\n * Purpose:  format datestamps via strftime<br>\n * Input:<br>\n *         - string: input date string\n *         - format: strftime format for output\n *         - default_date: default date if $string is empty\n * @link http://smarty.php.net/manual/en/language.modifier.date.format.php\n *          date_format (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @param string\n * @param string\n * @return string|void\n * @uses smarty_make_timestamp()\n */\nfunction smarty_modifier_date_format($string, $format = '%b %e, %Y', $default_date = '')\n{\n    if ($string != '') {\n        $timestamp = smarty_make_timestamp($string);\n    } elseif ($default_date != '') {\n        $timestamp = smarty_make_timestamp($default_date);\n    } else {\n        return;\n    }\n    if (DIRECTORY_SEPARATOR == '\\\\') {\n        $_win_from = array('%D',       '%h', '%n', '%r',          '%R',    '%t', '%T');\n        $_win_to   = array('%m/%d/%y', '%b', \"\\n\", '%I:%M:%S %p', '%H:%M', \"\\t\", '%H:%M:%S');\n        if (strpos($format, '%e') !== false) {\n            $_win_from[] = '%e';\n            $_win_to[]   = sprintf('%\\' 2d', date('j', $timestamp));\n        }\n        if (strpos($format, '%l') !== false) {\n            $_win_from[] = '%l';\n            $_win_to[]   = sprintf('%\\' 2d', date('h', $timestamp));\n        }\n        $format = str_replace($_win_from, $_win_to, $format);\n    }\n    return strftime($format, $timestamp);\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.debug_print_var.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty debug_print_var modifier plugin\n *\n * Type:     modifier<br>\n * Name:     debug_print_var<br>\n * Purpose:  formats variable contents for display in the console\n * @link http://smarty.php.net/manual/en/language.modifier.debug.print.var.php\n *          debug_print_var (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param array|object\n * @param integer\n * @param integer\n * @return string\n */\nfunction smarty_modifier_debug_print_var($var, $depth = 0, $length = 40)\n{\n    $_replace = array(\n        \"\\n\" => '<i>\\n</i>',\n        \"\\r\" => '<i>\\r</i>',\n        \"\\t\" => '<i>\\t</i>'\n    );\n\n    switch (gettype($var)) {\n        case 'array' :\n            $results = '<b>Array (' . count($var) . ')</b>';\n            foreach ($var as $curr_key => $curr_val) {\n                $results .= '<br>' . str_repeat('&nbsp;', $depth * 2)\n                    . '<b>' . strtr($curr_key, $_replace) . '</b> =&gt; '\n                    . smarty_modifier_debug_print_var($curr_val, ++$depth, $length);\n                    $depth--;\n            }\n            break;\n        case 'object' :\n            $object_vars = get_object_vars($var);\n            $results = '<b>' . get_class($var) . ' Object (' . count($object_vars) . ')</b>';\n            foreach ($object_vars as $curr_key => $curr_val) {\n                $results .= '<br>' . str_repeat('&nbsp;', $depth * 2)\n                    . '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '\n                    . smarty_modifier_debug_print_var($curr_val, ++$depth, $length);\n                    $depth--;\n            }\n            break;\n        case 'boolean' :\n        case 'NULL' :\n        case 'resource' :\n            if (true === $var) {\n                $results = 'true';\n            } elseif (false === $var) {\n                $results = 'false';\n            } elseif (null === $var) {\n                $results = 'null';\n            } else {\n                $results = htmlspecialchars((string) $var);\n            }\n            $results = '<i>' . $results . '</i>';\n            break;\n        case 'integer' :\n        case 'float' :\n            $results = htmlspecialchars((string) $var);\n            break;\n        case 'string' :\n            $results = strtr($var, $_replace);\n            if (strlen($var) > $length ) {\n                $results = substr($var, 0, $length - 3) . '...';\n            }\n            $results = htmlspecialchars('\"' . $results . '\"');\n            break;\n        case 'unknown type' :\n        default :\n            $results = strtr((string) $var, $_replace);\n            if (strlen($results) > $length ) {\n                $results = substr($results, 0, $length - 3) . '...';\n            }\n            $results = htmlspecialchars($results);\n    }\n\n    return $results;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.default.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty default modifier plugin\n *\n * Type:     modifier<br>\n * Name:     default<br>\n * Purpose:  designate default value for empty variables\n * @link http://smarty.php.net/manual/en/language.modifier.default.php\n *          default (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @param string\n * @return string\n */\nfunction smarty_modifier_default($string, $default = '')\n{\n    if (!isset($string) || $string === '')\n        return $default;\n    else\n        return $string;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.escape.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty escape modifier plugin\n *\n * Type:     modifier<br>\n * Name:     escape<br>\n * Purpose:  Escape the string according to escapement type\n * @link http://smarty.php.net/manual/en/language.modifier.escape.php\n *          escape (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @param html|htmlall|url|quotes|hex|hexentity|javascript\n * @return string\n */\nfunction smarty_modifier_escape($string, $esc_type = 'html', $char_set = 'ISO-8859-1')\n{\n    switch ($esc_type) {\n        case 'html':\n            return htmlspecialchars($string, ENT_QUOTES, $char_set);\n\n        case 'htmlall':\n            return htmlentities($string, ENT_QUOTES, $char_set);\n\n        case 'url':\n            return rawurlencode($string);\n\n        case 'urlpathinfo':\n            return str_replace('%2F','/',rawurlencode($string));\n            \n        case 'quotes':\n            // escape unescaped single quotes\n            return preg_replace(\"%(?<!\\\\\\\\)'%\", \"\\\\'\", $string);\n\n        case 'hex':\n            // escape every character into hex\n            $return = '';\n            for ($x=0; $x < strlen($string); $x++) {\n                $return .= '%' . bin2hex($string[$x]);\n            }\n            return $return;\n            \n        case 'hexentity':\n            $return = '';\n            for ($x=0; $x < strlen($string); $x++) {\n                $return .= '&#x' . bin2hex($string[$x]) . ';';\n            }\n            return $return;\n\n        case 'decentity':\n            $return = '';\n            for ($x=0; $x < strlen($string); $x++) {\n                $return .= '&#' . ord($string[$x]) . ';';\n            }\n            return $return;\n\n        case 'javascript':\n            // escape quotes and backslashes, newlines, etc.\n            return strtr($string, array('\\\\'=>'\\\\\\\\',\"'\"=>\"\\\\'\",'\"'=>'\\\\\"',\"\\r\"=>'\\\\r',\"\\n\"=>'\\\\n','</'=>'<\\/'));\n            \n        case 'mail':\n            // safe way to display e-mail address on a web page\n            return str_replace(array('@', '.'),array(' [AT] ', ' [DOT] '), $string);\n            \n        case 'nonstd':\n           // escape non-standard chars, such as ms document quotes\n           $_res = '';\n           for($_i = 0, $_len = strlen($string); $_i < $_len; $_i++) {\n               $_ord = ord(substr($string, $_i, 1));\n               // non-standard char, escape it\n               if($_ord >= 126){\n                   $_res .= '&#' . $_ord . ';';\n               }\n               else {\n                   $_res .= substr($string, $_i, 1);\n               }\n           }\n           return $_res;\n\n        default:\n            return $string;\n    }\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.indent.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty indent modifier plugin\n *\n * Type:     modifier<br>\n * Name:     indent<br>\n * Purpose:  indent lines of text\n * @link http://smarty.php.net/manual/en/language.modifier.indent.php\n *          indent (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @param integer\n * @param string\n * @return string\n */\nfunction smarty_modifier_indent($string,$chars=4,$char=\" \")\n{\n    return preg_replace('!^!m',str_repeat($char,$chars),$string);\n}\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.lower.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty lower modifier plugin\n *\n * Type:     modifier<br>\n * Name:     lower<br>\n * Purpose:  convert string to lowercase\n * @link http://smarty.php.net/manual/en/language.modifier.lower.php\n *          lower (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @return string\n */\nfunction smarty_modifier_lower($string)\n{\n    return strtolower($string);\n}\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.nl2br.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty plugin\n *\n * Type:     modifier<br>\n * Name:     nl2br<br>\n * Date:     Feb 26, 2003\n * Purpose:  convert \\r\\n, \\r or \\n to <<br>>\n * Input:<br>\n *         - contents = contents to replace\n *         - preceed_test = if true, includes preceeding break tags\n *           in replacement\n * Example:  {$text|nl2br}\n * @link http://smarty.php.net/manual/en/language.modifier.nl2br.php\n *          nl2br (Smarty online manual)\n * @version  1.0\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @return string\n */\nfunction smarty_modifier_nl2br($string)\n{\n    return nl2br($string);\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.regex_replace.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty regex_replace modifier plugin\n *\n * Type:     modifier<br>\n * Name:     regex_replace<br>\n * Purpose:  regular expression search/replace\n * @link http://smarty.php.net/manual/en/language.modifier.regex.replace.php\n *          regex_replace (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @param string|array\n * @param string|array\n * @return string\n */\nfunction smarty_modifier_regex_replace($string, $search, $replace)\n{\n    if(is_array($search)) {\n      foreach($search as $idx => $s)\n        $search[$idx] = _smarty_regex_replace_check($s);\n    } else {\n      $search = _smarty_regex_replace_check($search);\n    }       \n\n    return preg_replace($search, $replace, $string);\n}\n\nfunction _smarty_regex_replace_check($search)\n{\n    if (($pos = strpos($search,\"\\0\")) !== false)\n      $search = substr($search,0,$pos);\n    if (preg_match('!([a-zA-Z\\s]+)$!s', $search, $match) && (strpos($match[1], 'e') !== false)) {\n        /* remove eval-modifier from $search */\n        $search = substr($search, 0, -strlen($match[1])) . preg_replace('![e\\s]+!', '', $match[1]);\n    }\n    return $search;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.replace.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty replace modifier plugin\n *\n * Type:     modifier<br>\n * Name:     replace<br>\n * Purpose:  simple search/replace\n * @link http://smarty.php.net/manual/en/language.modifier.replace.php\n *          replace (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @param string\n * @param string\n * @return string\n */\nfunction smarty_modifier_replace($string, $search, $replace)\n{\n    return str_replace($search, $replace, $string);\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.spacify.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty spacify modifier plugin\n *\n * Type:     modifier<br>\n * Name:     spacify<br>\n * Purpose:  add spaces between characters in a string\n * @link http://smarty.php.net/manual/en/language.modifier.spacify.php\n *          spacify (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @param string\n * @return string\n */\nfunction smarty_modifier_spacify($string, $spacify_char = ' ')\n{\n    return implode($spacify_char,\n                   preg_split('//', $string, -1, PREG_SPLIT_NO_EMPTY));\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.string_format.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty string_format modifier plugin\n *\n * Type:     modifier<br>\n * Name:     string_format<br>\n * Purpose:  format strings via sprintf\n * @link http://smarty.php.net/manual/en/language.modifier.string.format.php\n *          string_format (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @param string\n * @return string\n */\nfunction smarty_modifier_string_format($string, $format)\n{\n    return sprintf($format, $string);\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.strip.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty strip modifier plugin\n *\n * Type:     modifier<br>\n * Name:     strip<br>\n * Purpose:  Replace all repeated spaces, newlines, tabs\n *           with a single space or supplied replacement string.<br>\n * Example:  {$var|strip} {$var|strip:\"&nbsp;\"}\n * Date:     September 25th, 2002\n * @link http://smarty.php.net/manual/en/language.modifier.strip.php\n *          strip (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @version  1.0\n * @param string\n * @param string\n * @return string\n */\nfunction smarty_modifier_strip($text, $replace = ' ')\n{\n    return preg_replace('!\\s+!', $replace, $text);\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.strip_tags.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty strip_tags modifier plugin\n *\n * Type:     modifier<br>\n * Name:     strip_tags<br>\n * Purpose:  strip html tags from text\n * @link http://smarty.php.net/manual/en/language.modifier.strip.tags.php\n *          strip_tags (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @param boolean\n * @return string\n */\nfunction smarty_modifier_strip_tags($string, $replace_with_space = true)\n{\n    if ($replace_with_space)\n        return preg_replace('!<[^>]*?>!', ' ', $string);\n    else\n        return strip_tags($string);\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.truncate.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty truncate modifier plugin\n *\n * Type:     modifier<br>\n * Name:     truncate<br>\n * Purpose:  Truncate a string to a certain length if necessary,\n *           optionally splitting in the middle of a word, and\n *           appending the $etc string or inserting $etc into the middle.\n * @link http://smarty.php.net/manual/en/language.modifier.truncate.php\n *          truncate (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @param integer\n * @param string\n * @param boolean\n * @param boolean\n * @return string\n */\nfunction smarty_modifier_truncate($string, $length = 80, $etc = '...',\n                                  $break_words = false, $middle = false)\n{\n    if ($length == 0)\n        return '';\n\n    if (strlen($string) > $length) {\n        $length -= min($length, strlen($etc));\n        if (!$break_words && !$middle) {\n            $string = preg_replace('/\\s+?(\\S+)?$/', '', substr($string, 0, $length+1));\n        }\n        if(!$middle) {\n            return substr($string, 0, $length) . $etc;\n        } else {\n            return substr($string, 0, $length/2) . $etc . substr($string, -$length/2);\n        }\n    } else {\n        return $string;\n    }\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.upper.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty upper modifier plugin\n *\n * Type:     modifier<br>\n * Name:     upper<br>\n * Purpose:  convert string to uppercase\n * @link http://smarty.php.net/manual/en/language.modifier.upper.php\n *          upper (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @return string\n */\nfunction smarty_modifier_upper($string)\n{\n    return strtoupper($string);\n}\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/modifier.wordwrap.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty wordwrap modifier plugin\n *\n * Type:     modifier<br>\n * Name:     wordwrap<br>\n * Purpose:  wrap a string of text at a given length\n * @link http://smarty.php.net/manual/en/language.modifier.wordwrap.php\n *          wordwrap (Smarty online manual)\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @param integer\n * @param string\n * @param boolean\n * @return string\n */\nfunction smarty_modifier_wordwrap($string,$length=80,$break=\"\\n\",$cut=false)\n{\n    return wordwrap($string,$length,$break,$cut);\n}\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/outputfilter.trimwhitespace.php",
    "content": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty trimwhitespace outputfilter plugin\n *\n * File:     outputfilter.trimwhitespace.php<br>\n * Type:     outputfilter<br>\n * Name:     trimwhitespace<br>\n * Date:     Jan 25, 2003<br>\n * Purpose:  trim leading white space and blank lines from\n *           template source after it gets interpreted, cleaning\n *           up code and saving bandwidth. Does not affect\n *           <<PRE>></PRE> and <SCRIPT></SCRIPT> blocks.<br>\n * Install:  Drop into the plugin directory, call\n *           <code>$smarty->load_filter('output','trimwhitespace');</code>\n *           from application.\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @author Contributions from Lars Noschinski <lars@usenet.noschinski.de>\n * @version  1.3\n * @param string\n * @param Smarty\n */\nfunction smarty_outputfilter_trimwhitespace($source, &$smarty)\n{\n    // Pull out the script blocks\n    preg_match_all(\"!<script[^>]*?>.*?</script>!is\", $source, $match);\n    $_script_blocks = $match[0];\n    $source = preg_replace(\"!<script[^>]*?>.*?</script>!is\",\n                           '@@@SMARTY:TRIM:SCRIPT@@@', $source);\n\n    // Pull out the pre blocks\n    preg_match_all(\"!<pre[^>]*?>.*?</pre>!is\", $source, $match);\n    $_pre_blocks = $match[0];\n    $source = preg_replace(\"!<pre[^>]*?>.*?</pre>!is\",\n                           '@@@SMARTY:TRIM:PRE@@@', $source);\n    \n    // Pull out the textarea blocks\n    preg_match_all(\"!<textarea[^>]*?>.*?</textarea>!is\", $source, $match);\n    $_textarea_blocks = $match[0];\n    $source = preg_replace(\"!<textarea[^>]*?>.*?</textarea>!is\",\n                           '@@@SMARTY:TRIM:TEXTAREA@@@', $source);\n\n    // remove all leading spaces, tabs and carriage returns NOT\n    // preceeded by a php close tag.\n    $source = trim(preg_replace('/((?<!\\?>)\\n)[\\s]+/m', '\\1', $source));\n\n    // replace textarea blocks\n    smarty_outputfilter_trimwhitespace_replace(\"@@@SMARTY:TRIM:TEXTAREA@@@\",$_textarea_blocks, $source);\n\n    // replace pre blocks\n    smarty_outputfilter_trimwhitespace_replace(\"@@@SMARTY:TRIM:PRE@@@\",$_pre_blocks, $source);\n\n    // replace script blocks\n    smarty_outputfilter_trimwhitespace_replace(\"@@@SMARTY:TRIM:SCRIPT@@@\",$_script_blocks, $source);\n\n    return $source;\n}\n\nfunction smarty_outputfilter_trimwhitespace_replace($search_str, $replace, &$subject) {\n    $_len = strlen($search_str);\n    $_pos = 0;\n    for ($_i=0, $_count=count($replace); $_i<$_count; $_i++)\n        if (($_pos=strpos($subject, $search_str, $_pos))!==false)\n            $subject = substr_replace($subject, $replace[$_i], $_pos, $_len);\n        else\n            break;\n\n}\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/shared.escape_special_chars.php",
    "content": "<?php\n/**\n * Smarty shared plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * escape_special_chars common function\n *\n * Function: smarty_function_escape_special_chars<br>\n * Purpose:  used by other smarty functions to escape\n *           special chars except for already escaped ones\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @return string\n */\nfunction smarty_function_escape_special_chars($string)\n{\n    if(!is_array($string)) {\n        $string = preg_replace('!&(#?\\w+);!', '%%%SMARTY_START%%%\\\\1%%%SMARTY_END%%%', $string);\n        $string = htmlspecialchars($string);\n        $string = str_replace(array('%%%SMARTY_START%%%','%%%SMARTY_END%%%'), array('&',';'), $string);\n    }\n    return $string;\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "lib/smarty/plugins/shared.make_timestamp.php",
    "content": "<?php\n/**\n * Smarty shared plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Function: smarty_make_timestamp<br>\n * Purpose:  used by other smarty functions to make a timestamp\n *           from a string.\n * @author   Monte Ohrt <monte at ohrt dot com>\n * @param string\n * @return string\n */\nfunction smarty_make_timestamp($string)\n{\n    if(empty($string)) {\n        // use \"now\":\n        $time = time();\n\n    } elseif (preg_match('/^\\d{14}$/', $string)) {\n        // it is mysql timestamp format of YYYYMMDDHHMMSS?            \n        $time = mktime(substr($string, 8, 2),substr($string, 10, 2),substr($string, 12, 2),\n                       substr($string, 4, 2),substr($string, 6, 2),substr($string, 0, 4));\n        \n    } elseif (is_numeric($string)) {\n        // it is a numeric string, we handle it as timestamp\n        $time = (int)$string;\n        \n    } else {\n        // strtotime should handle it\n        $time = strtotime($string);\n        if ($time == -1 || $time === false) {\n            // strtotime() was not able to parse $string, use \"now\":\n            $time = time();\n        }\n    }\n    return $time;\n\n}\n\n/* vim: set expandtab: */\n\n?>\n"
  },
  {
    "path": "logout.php",
    "content": "<?php\n\t$dir = dirname(__FILE__);\n\tinclude(\"$dir/lib/init.php\");\n\n\n\t$expire = time();\n\n\tsetcookie($cfg['cookie_name'], '', $expire, $cfg['cookie_path'], $cfg['cookie_domain']);\n\n\theader(\"location: ./\");\n\texit;\n"
  },
  {
    "path": "new.php",
    "content": "<?php\r\n\t$dir = dirname(__FILE__);\r\n\tinclude(\"$dir/lib/init.php\");\r\n\r\n\tverify_auth();\r\n\r\n\tload_plugins();\r\n\r\n\r\n\t#\r\n\t# get list of services and sort them\r\n\t#\r\n\r\n\t$services = array();\r\n\r\n\tforeach (array_keys($plugins_services) as $k){\r\n\t\t$temp = new $k();\r\n\t\t$temp->id = $k;\r\n\t\t$services[] = $temp;\r\n\t}\r\n\r\n\tusort($services, 'local_sort');\r\n\r\n\tfunction local_sort($a, $b){\r\n\t\treturn strcasecmp($a->name, $b->name);\r\n\t}\r\n\r\n\t$smarty->assign('services', split_sets($services, 3));\r\n\r\n\r\n\t#\r\n\t# load auth services\r\n\t#\r\n\r\n\t$auth = array();\r\n\tforeach (array_keys($plugins_auth) as $k){\r\n\t\t$temp = new $k();\r\n\t\t$temp->id = $k;\r\n\t\t$auth[] = $temp;\r\n\t}\r\n\t$smarty->assign('auth', $auth);\r\n\r\n\r\n\t#\r\n\t# output\r\n\t#\r\n\r\n\t$smarty->display('page_new.txt');\r\n"
  },
  {
    "path": "oauth.php",
    "content": "<?php\n\t$dir = dirname(__FILE__);\n\tinclude(\"$dir/lib/init.php\");\n\n\n\t#\n\t# exchange the code for a token\n\t#\n\n\t$params = array(\n\t\t'client_id'\t=> $cfg['client_id'],\n\t\t'client_secret'\t=> $cfg['client_secret'],\n\t\t'code'\t\t=> $_GET['code'],\n\t\t'redirect_uri'\t=> \"{$cfg['root_url']}oauth.php\",\n\t);\n\n\tif ($_GET['debug']) $params['redirect_uri'] .= '?debug=1';\n\n\t$url = $cfg['slack_root'].\"api/oauth.access\";\n\n\t$ret = SlackHTTP::post($url, $params);\n\n\tif ($ret['ok'] && $ret['code'] == '200'){\n\n\t\t$obj = json_decode($ret['body'], true);\n\t\tif ($obj['ok']){\n\n\t\t\t$token = $obj['access_token'];\n\t\t}else{\n\t\t\techo \"problem with oauth.access call\";\n\t\t\tdumper($obj);\n\t\t\texit;\n\t\t}\n\n\t}else{\n\t\techo \"problem with oauth.access call\";\n\t\tdumper($ret);\n\t\texit;\n\t}\n\n\tif ($_GET['debug']){\n\t\techo \"debug mode:\";\n\t\tdumper($obj);\n\t\texit;\n\t}\n\n\n\t#\n\t# fetch user info\n\t#\n\n\t$url = $cfg['slack_root'].\"api/auth.test?token={$token}\";\n\t$ret = SlackHTTP::get($url);\n\n\tif ($ret['ok'] && $ret['code'] == '200'){\n\n\t\t$obj = json_decode($ret['body'], true);\n\n\t}else{\n\t\techo \"problem with auth.test call\";\n\t\tdumper($ret);\n\t\texit;\n\t}\n\n\t$info = $obj;\n\tunset($info['ok']);\n\n\t$info['access_token'] = $token;\n\t$info['secret'] = substr(md5(rand()), 0, 10);\n\n\t$cookie = $info['user_id'].'-'.$info['secret'];\n\t$expire = time() + (365 * 24 * 60 * 60);\n\n\tsetcookie($cfg['cookie_name'], $cookie, $expire, $cfg['cookie_path'], $cfg['cookie_domain'], isset($_SERVER[\"HTTPS\"]), true);\n\n\t$data->set('users', $info['user_id'], $info);\n\n\n\n\t#\n\t# is this the first use?\n\t#\n\n\t$team = $data->get('metadata', 'team');\n\n\tif (!$team['id']){\n\t\t$data->set('metadata', 'team', array(\n\t\t\t'id'\t=> $info['team_id'],\n\t\t\t'name'\t=> $info['team'],\n\t\t\t'token'\t=> $info['access_token'],\n\t\t));\n\t}\n\n\n\theader(\"location: ./\");\n\texit;\n"
  },
  {
    "path": "plugins/atlassian_stash_commits/plugin.php",
    "content": "<?php\n\nclass atlassian_stash_commits extends SlackServicePlugin {\n\n    public $name = \"Atlassian Stash Commits\";\n    public $desc = \"Source control and code management.\";\n\n    public $cfg = array(\n        'has_token' => true,\n    );\n\n    function onInit() {\n        $channels = $this->getChannelsList();\n\n        foreach ($channels as $k => $v) {\n            if ($v == '#general') {\n                $this->icfg['channel']      = $k;\n                $this->icfg['channel_name'] = $v;\n            }\n        }\n\n        $this->icfg['botname'] = 'stash';\n    }\n\n    function onView() {\n        return $this->smarty->fetch('view.tpl');\n    }\n\n    function onEdit() {\n        $channels = $this->getChannelsList();\n\n        if ($_GET['save']) {\n            $this->icfg['channel']      = $_POST['channel'];\n            $this->icfg['base_url']     = $_POST['base_url'];\n            $this->icfg['botname']      = $_POST['botname'];\n            $this->icfg['channel_name'] = $channels[$_POST['channel']];\n            $this->saveConfig();\n\n            header(\"location: {$this->getViewUrl()}&saved=1\");\n            exit;\n        }\n\n        $this->smarty->assign('channels', $channels);\n\n        return $this->smarty->fetch('edit.tpl');\n    }\n\n    function onHook($req) {\n        global $cfg;\n\n        if (!$this->icfg['channel']) {\n            return array(\n                'ok'    => false,\n                'error' => \"No channel configured\",\n            );\n        }\n\n        $stash_payload = json_decode($req['post_body']);\n\n        if (!$stash_payload || !is_object($stash_payload) || !isset($stash_payload->changesets) || !isset($stash_payload->repository)) {\n            return array(\n                'ok'    => false,\n                'error' => \"No payload received from stash\",\n            );\n        }\n\n\t    $fields  = array();\n\t    $author  = 'Unknown';\n\t    $commits = $stash_payload->changesets->values;\n\t    $project = $this->icfg['base_url'] . '/projects/' . $stash_payload->repository->project->key . '/repos/' . $stash_payload->repository->slug;\n\n\t    foreach($commits as $commit) {\n            $fields[] = array(\n                'text' => sprintf(\n                    '<%s|%s> - %s (%s files changed)',\n                    $project . '/commits/' . $commit->toCommit->id,\n                    $commit->toCommit->displayId,\n                    $commit->toCommit->message,\n                    $commit->changes->size\n                ),\n                'color' => 'good',\n            );\n\n\t\t    $author = $commit->toCommit->author->name;\n\t    }\n\n\t    $message = sprintf(\n\t\t    'New push on <%s|%s> by %s on branch %s (%s Commits)',\n\t\t    $project,\n\t\t    $stash_payload->repository->project->key . '/' . $stash_payload->repository->name,\n\t\t    $author,\n\t\t    str_replace('refs/heads/', '', $stash_payload->refChanges->refId),\n\t\t    count($fields)\n\t    );\n\n        if (count($fields) > 0) {\n            $this->postToChannel($message, array(\n                'channel'     => $this->icfg['channel'],\n                'username'    => $this->icfg['botname'],\n                'icon_url'    => $cfg['root_url'] . 'plugins/atlassian_stash_commits/icon_128.png',\n                'attachments' => array_reverse($fields)\n            ));\n        }\n\n        return array(\n            'ok'     => true,\n            'status' => \"Nothing found to report\",\n        );\n    }\n\n    function getLabel() {\n        return \"Post commits to {$this->icfg['channel_name']} as {$this->icfg['botname']}\";\n    }\n\n}\n"
  },
  {
    "path": "plugins/atlassian_stash_commits/templates/edit.tpl",
    "content": "<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n\n    <p>Channel to post to: <select name=\"channel\">\n        {foreach from=$channels key='chan_id' item='chan_name'}\n            <option value=\"{$chan_id|escape}\"{if $chan_id==$this->icfg.channel} selected{/if}>{$chan_name|escape}</option>\n        {/foreach}\n    </select></p>\n\n    <p>Bot name: <input type=\"text\" name=\"botname\" value=\"{$this->icfg.botname|escape}\" /></p>\n    <p>Base url: <input type=\"text\" name=\"base_url\" value=\"{$this->icfg.base_url|escape}\" /></p>\n\n    <p><input type=\"submit\" value=\"Save Changes\" class=\"btn\" /></p>\n\n</form>"
  },
  {
    "path": "plugins/atlassian_stash_commits/templates/view.tpl",
    "content": "{if $smarty.get.newtoken}\n\t<p class=\"alert\">Your token has been updated - the webhook URL has changed!</p>\n{/if}\n\n<p>Go to your repo's settings page and add this hook URL:</p>\n\n<p><code>{$this->getHookUrl()}</code></p>\n\n<p><b>Post to channel:</b> {$this->icfg.channel_name|escape}</p>\n<p><b>Bot name:</b> {$this->icfg.botname|escape}</p>\n<p><b>Base url:</b> {$this->icfg.base_url|escape}</p>\n\n<p><a href=\"{$this->getEditUrl()}\" class=\"btn\">Edit settings</a></p>"
  },
  {
    "path": "plugins/coveralls/plugin.php",
    "content": "<?php\n\nclass coveralls extends SlackServicePlugin {\n\n    public $name = \"Coveralls\";\n    public $desc = \"Code coverage history and stats\";\n\n    function onView(){\n        return $this->smarty->fetch('view.html');\n    }\n\n    function onEdit(){\n\n        $channels = $this->getChannelsList();\n\n        if ($_GET['save']){\n\n            $this->icfg['channel'] = $_POST['channel'];\n            $this->icfg['channel_name'] = $channels[$_POST['channel']];\n            $this->icfg['botname'] = $_POST['botname'];\n            $this->saveConfig();\n\n            header(\"location: {$this->getViewUrl()}&saved=1\");\n            exit;\n        }\n\n        $this->smarty->assign('channels', $channels);\n\n        return $this->smarty->fetch('edit.html');\n    }\n\n    function onHook($req){\n\n        preg_match('/.*\\/coveralls_(\\d+)\\.png/', $req['post']['badge_url'], $matches);\n        $percentage = $matches[1];\n\n        $text = $this->escapeText(\"Coverage: {$percentage}% | \");\n        //$this->sendMessage($text);\n\n        $text .= $this->escapeText(\"{$req['post']['commit_message']} by {$req['post']['committer_name']}\");\n        $text .= $this->escapeText(\" (\");\n        $text .= $this->escapeLink($req['post']['url']);\n        $text .= $this->escapeText(\" )\");\n        $this->sendMessage($text);\n    }\n\n\n    private function sendMessage($text){\n\n        $ret = $this->postToChannel($text, array(\n                            'channel'       => $this->icfg['channel'],\n                            'username'      => $this->icfg['botname'],\n                    ));\n\n        return array(\n            'ok'        => true,\n            'status'    => \"Sent a message\",\n        );\n    }\n\n}\n"
  },
  {
    "path": "plugins/coveralls/templates/edit.html",
    "content": "\n\n<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n\n<p>Channel to post to: <select name=\"channel\">\n{foreach from=$channels key='chan_id' item='chan_name'}\n\t<option value=\"{$chan_id|escape}\"{if $chan_id==$this->icfg.channel} selected{/if}>{$chan_name|escape}</option>\n{/foreach}\n</select></p>\n\n<p>Bot name: <input type=\"text\" name=\"botname\" value=\"{$this->icfg.botname|escape}\" /></p>\n\n<p><input type=\"submit\" value=\"Save Changes\" class=\"btn\" /></p>\n</form>\n"
  },
  {
    "path": "plugins/coveralls/templates/view.html",
    "content": "<p>In your Coveralls repo, choose \"Notifications\" -&gt; \"Webhook\" and add the following URL:</p>\n\n<p><code>{$this->getHookUrl()}</code></p>\n\n<p><b>Post to channel:</b> {$this->icfg.channel|escape} / {$this->icfg.channel_name|escape}</p>\n<p><b>Bot name:</b> {$this->icfg.botname|escape}</p>\n\n<p><a href=\"{$this->getEditUrl()}\" class=\"btn\">Edit settings</a></p>\n"
  },
  {
    "path": "plugins/dployio/plugin.php",
    "content": "<?php\n\nclass dployio extends SlackServicePlugin {\n\n    public $name = \"Dploy.io deployments\";\n    public $desc = \"Automatic deployments by Dploy.io.\";\n\n    public $cfg = array(\n        'has_token' => true,\n    );\n\n    function onInit() {\n        $channels = $this->getChannelsList();\n\n        foreach ($channels as $k => $v) {\n            if ($v == '#general') {\n                $this->icfg['channel']      = $k;\n                $this->icfg['channel_name'] = $v;\n            }\n        }\n\n        $this->icfg['botname'] = 'dploy.io';\n    }\n\n    function onView() {\n        return $this->smarty->fetch('view.tpl');\n    }\n\n    function onEdit() {\n        $channels = $this->getChannelsList();\n\n        if ($_GET['save']) {\n            $this->icfg['channel']      = $_POST['channel'];\n            $this->icfg['channel_name'] = $channels[$_POST['channel']];\n            $this->icfg['botname']      = $_POST['botname'];\n            $this->saveConfig();\n\n            header(\"location: {$this->getViewUrl()}&saved=1\");\n            exit;\n        }\n\n        $this->smarty->assign('channels', $channels);\n\n        return $this->smarty->fetch('edit.tpl');\n    }\n\n    function onHook($req) {\n        global $cfg;\n\n        if (!$this->icfg['channel']) {\n            return array(\n                'ok'    => false,\n                'error' => \"No channel configured\",\n            );\n        }\n\n        $dploy_payload = json_decode($req['post_body']);\n\n        if (!$dploy_payload || !is_object($dploy_payload)) {\n            return array(\n                'ok'    => false,\n                'error' => \"No payload received from dploy.io\",\n            );\n        }\n\n        if (is_null($dploy_payload->deployed_at)) {\n            $message = '[%s] started deployment to %s environment on %s.';\n        } else {\n            $message = '[%s] was deployed to %s environment on %s.';\n        }\n\n        $message = sprintf(\n            $message,\n            str_replace('.git', '', $dploy_payload->repository),\n            $dploy_payload->environment,\n            $dploy_payload->server\n        );\n\n        $this->postToChannel($message, array(\n            'channel'     => $this->icfg['channel'],\n            'username'    => $this->icfg['botname'],\n            'icon_url'    => $cfg['root_url'] . 'plugins/dployio/icon_128.png'\n        ));\n    }\n\n    function getLabel() {\n        return \"Post commits to {$this->icfg['channel_name']} as {$this->icfg['botname']}\";\n    }\n\n}\n"
  },
  {
    "path": "plugins/dployio/templates/edit.tpl",
    "content": "<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n\n    <p>Channel to post to: <select name=\"channel\">\n        {foreach from=$channels key='chan_id' item='chan_name'}\n            <option value=\"{$chan_id|escape}\"{if $chan_id==$this->icfg.channel} selected{/if}>{$chan_name|escape}</option>\n        {/foreach}\n    </select></p>\n\n    <p>Bot name: <input type=\"text\" name=\"botname\" value=\"{$this->icfg.botname|escape}\" /></p>\n\n    <p><input type=\"submit\" value=\"Save Changes\" class=\"btn\" /></p>\n\n</form>"
  },
  {
    "path": "plugins/dployio/templates/view.tpl",
    "content": "{if $smarty.get.newtoken}\n\t<p class=\"alert\">Your token has been updated - the webhook URL has changed!</p>\n{/if}\n\n<p>Go to your repo's settings page and add this hook URL:</p>\n\n<p><code>{$this->getHookUrl()}</code></p>\n\n<p><b>Post to channel:</b> {$this->icfg.channel_name|escape}</p>\n<p><b>Bot name:</b> {$this->icfg.botname|escape}</p>\n\n<p><a href=\"{$this->getEditUrl()}\" class=\"btn\">Edit settings</a></p>"
  },
  {
    "path": "plugins/fogbugz/plugin.php",
    "content": "<?php\n//\n// FogBugz Case Events Web Hook\n// =============================================================================\n//\n// Post case opening events from FogBugz to a Slack chat room.\n//\n// Author: [Craig Davis](craig@there4development.com)\n//\n// -----------------------------------------------------------------------------\n//\nclass fogbugz extends SlackServicePlugin\n{\n    public $name = 'FogBugz Cases';\n    public $desc = 'Provide case open notifications';\n\n    public $cfg = array(\n        'has_token' => true,\n    );\n\n    public function onInit() {\n        $channels = $this->getChannelsList();\n        foreach ($channels as $channel => $name) {\n            if ($name == '#general') {\n                $this->icfg['channel'     ] = $channel;\n                $this->icfg['channel_name'] = $name;\n            }\n        }\n        $this->icfg['botname']      = 'fogbugz';\n        $this->icfg['fogbugz_host'] = $_POST['fogbugz_host'];\n        $this->icfg['icon_url']     = trim($GLOBALS['cfg']['root_url'], '/') . '/plugins/fogbugz/icon_48.png';\n    }\n\n    public function onView() {\n        return $this->smarty->fetch('view.html');\n    }\n\n    public function getLabel() {\n        return \"Post commits to {$this->icfg['channel_name']} as {$this->icfg['botname']}\";\n    }\n\n    public function onEdit() {\n        var_dump($this->icfg);\n        $channels = $this->getChannelsList();\n\n        if ($_GET['save']) {\n            $this->icfg['channel']       = $_POST['channel'];\n            $this->icfg['channel_name']  = $channels[$_POST['channel']];\n            $this->icfg['botname']       = $_POST['botname'];\n            $this->icfg['fogbugz_host']  = $_POST['fogbugz_host'];\n            $this->icfg['icon_url']      = $_POST['icon_url'];\n            $this->saveConfig();\n\n            header(\"location: {$this->getViewUrl()}&saved=1\");\n            exit;\n        }\n\n        $this->smarty->assign('channels', $channels);\n        return $this->smarty->fetch('edit.html');\n    }\n\n    public function onHook($req) {\n        $chatMessage = '';\n        $linkHref    = trim($this->icfg['fogbugz_host'], '/') . '/default.asp?' . $req['get']['CaseNumber'];\n        $linkText    = $req['get']['CaseNumber'];\n\n        $chatMessage .= $this->escapeText('Opened ');\n        $chatMessage .= $this->escapeLink($linkHref, $linkText);\n        $chatMessage .= $this->escapeText(': ' . $req['get']['Title']);\n\n        $logMessage = sprintf('Opened Case %d', $req['get']['CaseNumber']);\n        $this->sendMessage($chatMessage);\n\n        return $logMessage;\n    }\n\n    private function sendMessage($text) {\n        $ret = $this->postToChannel($text, array(\n            'channel'  => $this->icfg['channel'],\n            'username' => $this->icfg['botname'],\n            'icon_url' => $this->icfg['icon_url'],\n        ));\n\n        return array(\n            'ok'     => true,\n            'status' => 'Sent a message',\n        );\n    }\n}\n\n/* End of file plugin.php */\n"
  },
  {
    "path": "plugins/fogbugz/templates/edit.html",
    "content": "<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n    <p>\n        Channel to post to:\n        <select name=\"channel\">\n    {foreach from=$channels key='chan_id' item='chan_name'}\n            <option value=\"{$chan_id|escape}\"{if $chan_id==$this->icfg.channel} selected{/if}>{$chan_name|escape}</option>\n    {/foreach}\n        </select>\n    </p>\n\n    <p>FogBugz host: <input type=\"text\" name=\"fogbugz_host\" value=\"{$this->icfg.fogbugz_host|escape}\"></p>\n    <p>Bot name: <input type=\"text\" name=\"botname\" value=\"{$this->icfg.botname|escape}\"></p>\n    <p>Bot icon: <input type=\"text\" name=\"icon_url\" size=\"55\" value=\"{$this->icfg.icon_url|escape}\"></p>\n\n    <p>\n        <input type=\"submit\" value=\"Save Changes\" class=\"btn\">\n    </p>\n\n</form>\n"
  },
  {
    "path": "plugins/fogbugz/templates/view.html",
    "content": "\n{if $smarty.get.newtoken}\n<p class=\"alert\">Your token has been updated - the webhook URL has changed!</p>\n{/if}\n\n<h3>Your FogBugz Hook URL</h3>\n<p><code>{$this->getHookUrl()}&CaseNumber={literal}{CaseNumber}&Title={Title}&AreaName={AreaName}{/literal}</code></p>\n\n<h3>Setting up FogBugz</h3>\n<ol>\n    <li>Open FogBugz Admin tools and select 'URL Trigger'</li>\n    <li>Add New Trigger</li>\n    <li>Select the 'CaseOpened' event type</li>\n    <li>Use the hook url above</li>\n    <li>Select 'POST'</li>\n    <li>Name the hook and click 'OK'</li>\n</ol>\n\n<h3>Current Configuration</h3>\n<dl>\n    <dt><strong>Post to channel:</strong></dt>\n    <dd>{$this->icfg.channel|escape} / {$this->icfg.channel_name|escape}</dd>\n\n    <dt><strong>FogBugz host:</strong></dt>\n    <dd>{$this->icfg.fogbugz_host|escape}</dd>\n\n    <dt><strong>Bot name:</strong></dt>\n    <dd>{$this->icfg.botname|escape}</dd>\n\n    <dt><strong>Bot icon:</strong></dt>\n    <dd><img src=\"{$this->icfg.icon_url}\" height=\"48\" width=\"48\" alt=\"bot icon\"></dd>\n</dl>\n\n<p><a href=\"{$this->getEditUrl()}\" class=\"btn\">Edit settings</a></p>\n"
  },
  {
    "path": "plugins/github_commits/plugin.php",
    "content": "<?php\n\n\tclass github_commits extends SlackServicePlugin {\n\n\t\tpublic $name = \"Github Commits\";\n\t\tpublic $desc = \"Source control and code management.\";\n\n\t\tpublic $cfg = array(\n\t\t\t'has_token'\t=> true,\n\t\t);\n\n\t\tfunction onInit(){\n\n\t\t\t$channels = $this->getChannelsList();\n\t\t\tforeach ($channels as $k => $v){\n\t\t\t\tif ($v == '#general'){\n\t\t\t\t\t$this->icfg['channel'] = $k;\n\t\t\t\t\t$this->icfg['channel_name'] = $v;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$this->icfg['branch']\t= '';\n\t\t\t$this->icfg['botname']\t= 'github';\n\t\t}\n\n\t\tfunction onView(){\n\n\t\t\treturn $this->smarty->fetch('view.txt');\n\t\t}\n\n\t\tfunction onEdit(){\n\n\t\t\t$channels = $this->getChannelsList();\n\n\t\t\tif ($_GET['save']){\n\n\t\t\t\t$this->icfg['channel'] = $_POST['channel'];\n\t\t\t\t$this->icfg['channel_name'] = $channels[$_POST['channel']];\n\t\t\t\t$this->icfg['branch'] = $_POST['branch'];\n\t\t\t\t$this->icfg['botname'] = $_POST['botname'];\n\t\t\t\t$this->saveConfig();\n\n\t\t\t\theader(\"location: {$this->getViewUrl()}&saved=1\");\n\t\t\t\texit;\n\t\t\t}\n\n\t\t\t$this->smarty->assign('channels', $channels);\n\n\t\t\treturn $this->smarty->fetch('edit.txt');\n\t\t}\n\n\t\tfunction onHook($req){\n\n\t\t\tif (!$this->icfg['channel']){\n\t\t\t\treturn array(\n\t\t\t\t\t'ok'\t=> false,\n\t\t\t\t\t'error'\t=> \"No channel configured\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t$github_payload = json_decode($req['post']['payload'], true);\n\n\t\t\tif (!$github_payload || !is_array($github_payload)){\n\t\t\t\treturn array(\n\t\t\t\t\t'ok'\t=> false,\n\t\t\t\t\t'error' => \"No payload received from github\",\n\t\t\t\t);\n\t\t\t}\n\n\n\t\t\t#\n\t\t\t# branch filtering\n\t\t\t#\n\n\t\t\t$filter_branches = $this->icfg['branch'] ? explode(',', $this->icfg['branch']) : array();\n\n\t\t\tif ($github_payload['base_ref']){\n\n\t\t\t\t$ref_parts = explode('/', $github_payload['ref']);\n\t\t\t\t$base_ref_parts = explode('/', $github_payload['base_ref']);\n\t\t\t\t$branch = array_pop($base_ref_parts);\n\t\t\t}else{\n\t\t\t\t$ref_parts = explode('/', $github_payload['ref']);\n\t\t\t\t$branch = array_pop($ref_parts);\n\t\t\t}\n\n\t\t\tif (count($filter_branches) && !in_array($branch, $filter_branches)){\n\t\t\t\treturn array(\n\t\t\t\t\t'ok'\t\t=> true,\n\t\t\t\t\t'status'\t=> \"Commit not in tracked branch (in {$branch}, showing {$this->icfg['branch']})\",\n\t\t\t\t);\n\t\t\t}\n\n\n\t\t\t#\n\t\t\t# send some messages\n\t\t\t#\n\n\t\t\tif ($ref_parts[1] == \"tags\"){\n\n\t\t\t\t$text  = $this->escapeText(\"[{$github_payload['repository']['name']}/{$branch}] \");\n\t\t\t\t$text .= $this->escapeText(\"{$github_payload['pusher']['name']} pushed tag \");\n\t\t\t\t$text .= $this->escapeLink($github_payload['compare'], \"{$ref_parts[2]}\");\n\n\t\t\t\treturn $this->sendMessage($text);\n\t\t\t}\n\n\t\t\t$commit_count = count($github_payload['commits']);\n\n\t\t\tif ($commit_count > 1){\n\n\t\t\t\t$text = $this->escapeText(\"[{$github_payload['repository']['name']}/{$branch}] $commit_count new commits:\");\n\n\t\t\t\t$i = 0;\n\t\t\t\tforeach ($github_payload['commits'] as $commit){\n\t\t\t\t\t$short_sha = substr($commit['id'], 0, 12);\n\n\t\t\t\t\t$text .= $this->escapeText(\"\\n[{$github_payload['repository']['name']}/{$branch}] \");\n\t\t\t\t\t$text .= $this->escapeLink($commit['url'], \"{$short_sha}\");\n\t\t\t\t\t$text .= $this->escapeText(\": {$commit['message']} - {$commit['author']['name']}\");\n\t\t\t\t\t\n\t\t\t\t\t$i++;\n\t\t\t\t\tif ($i == 10 && ($commit_count-$i)>1) break;\n\t\t\t\t}\n\n\t\t\t\tif ($i != $commit_count){\n\t\t\t\t\t$text .= \"\\nAnd \".$this->escapeLink($github_payload['compare'], ($commit_count-$i).\" others\");\n\t\t\t\t}\n\n\t\t\t\treturn $this->sendMessage($text);\n\t\t\t}\n\n\t\t\tif ($commit_count){\n\n\t\t\t\t$commit = $github_payload['commits'][0];\n\t\t\t\t$short_sha = substr($commit['id'], 0, 12);\n\n\t\t\t\t$text .= $this->escapeText(\"[{$github_payload['repository']['name']}/{$branch}] \");\n\t\t\t\t$text .= $this->escapeLink($commit['url'], \"{$short_sha}\");\n\t\t\t\t$text .= $this->escapeText(\": {$commit['message']} - {$commit['author']['name']}\");\n\n\t\t\t\treturn $this->sendMessage($text);\n\t\t\t}\n\n\t\t\treturn array(\n\t\t\t\t'ok'\t\t=> true,\n\t\t\t\t'status'\t=> \"Nothing found to report\",\n\t\t\t);\n\t\t}\n\n\t\tfunction getLabel(){\n\t\t\treturn \"Post commits to {$this->icfg['channel_name']} as {$this->icfg['botname']}\";\n\t\t}\n\n\t\tprivate function sendMessage($text){\n\n\t\t\t$ret = $this->postToChannel($text, array(\n                                'channel'       => $this->icfg['channel'],\n                                'username'      => $this->icfg['botname'],\n                        ));\n\n\t\t\treturn array(\n\t\t\t\t'ok'\t\t=> true,\n\t\t\t\t'status'\t=> \"Sent a message\",\n\t\t\t);\n\t\t}\n\t}\n"
  },
  {
    "path": "plugins/github_commits/templates/edit.txt",
    "content": "\n\n<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n\n<p>Channel to post to: <select name=\"channel\">\n{foreach from=$channels key='chan_id' item='chan_name'}\n\t<option value=\"{$chan_id|escape}\"{if $chan_id==$this->icfg.channel} selected{/if}>{$chan_name|escape}</option>\n{/foreach}\n</select></p>\n\n<p>Branches: <input type=\"text\" name=\"branch\" value=\"{$this->icfg.branch|escape}\" /></p>\n\n<p>Bot name: <input type=\"text\" name=\"botname\" value=\"{$this->icfg.botname|escape}\" /></p>\n\n<p><input type=\"submit\" value=\"Save Changes\" class=\"btn\" /></p>\n</form>\n"
  },
  {
    "path": "plugins/github_commits/templates/view.txt",
    "content": "\n{if $smarty.get.newtoken}\n\n\t<p class=\"alert\">Your token has been updated - the webhook URL has changed!</p>\n{/if}\n\n<p>Go to your repo's settings page and add this hook URL:</p>\n\n<p><code>{$this->getHookUrl()}</code></p>\n\n<p><b>Post to channel:</b> {$this->icfg.channel|escape} / {$this->icfg.channel_name|escape}</p>\n<p><b>Branch filter:</b> {$this->icfg.branch|escape|default:'<i>all</i>'}</p>\n<p><b>Bot name:</b> {$this->icfg.botname|escape}</p>\n\n<p><a href=\"{$this->getEditUrl()}\" class=\"btn\">Edit settings</a></p>\n"
  },
  {
    "path": "plugins/gitlab_commits/plugin.php",
    "content": "<?php\n\nclass gitlab_commits extends SlackServicePlugin {\n\n    public $name = \"GitLab Commits\";\n    public $desc = \"Source control and code management.\";\n\n    public $cfg = array(\n        'has_token' => true,\n    );\n\n    function onInit() {\n        $channels = $this->getChannelsList();\n\n        foreach ($channels as $k => $v) {\n            if ($v == '#general') {\n                $this->icfg['channel']      = $k;\n                $this->icfg['channel_name'] = $v;\n            }\n        }\n\n        $this->icfg['botname'] = 'gitlab';\n    }\n\n    function onView() {\n        return $this->smarty->fetch('view.tpl');\n    }\n\n    function onEdit() {\n        $channels = $this->getChannelsList();\n\n        if ($_GET['save']) {\n            $this->icfg['channel']      = $_POST['channel'];\n            $this->icfg['channel_name'] = $channels[$_POST['channel']];\n            $this->icfg['botname']      = $_POST['botname'];\n            $this->saveConfig();\n\n            header(\"location: {$this->getViewUrl()}&saved=1\");\n            exit;\n        }\n\n        $this->smarty->assign('channels', $channels);\n\n        return $this->smarty->fetch('edit.tpl');\n    }\n\n    function onHook($req) {\n        global $cfg;\n\n        if (!$this->icfg['channel']) {\n            return array(\n                'ok'    => false,\n                'error' => \"No channel configured\",\n            );\n        }\n\n        $gitlab_payload = json_decode($req['post_body']);\n\n        if (!$gitlab_payload || !is_object($gitlab_payload) || !isset($gitlab_payload->commits)) {\n            return array(\n                'ok'    => false,\n                'error' => \"No payload received from gitlab\",\n            );\n        }\n\n        $fields = array();\n        foreach ($gitlab_payload->commits as $commit) {\n            $fields[] = array(\n                'text' => sprintf(\n                    '<%s|%s> - %s',\n                    $commit->url,\n                    substr($commit->id, 0, 9),\n                    $commit->message\n                ),\n                'color' => 'good',\n            );\n        }\n\n        $message = sprintf(\n            'New push on <%s|%s> by %s on branch %s (%d Commits)',\n            $gitlab_payload->repository->homepage,\n            $gitlab_payload->repository->name,\n            $gitlab_payload->user_name,\n            str_replace('refs/heads/', '', $gitlab_payload->ref),\n            $gitlab_payload->total_commits_count\n        );\n\n        if (count($fields) > 0) {\n            $this->postToChannel($message, array(\n                'channel'     => $this->icfg['channel'],\n                'username'    => $this->icfg['botname'],\n                'attachments' => $fields,\n                'icon_url'    => $cfg['root_url'] . 'plugins/gitlab_commits/icon_128.png'\n            ));\n        }\n\n        return array(\n            'ok'     => true,\n            'status' => \"Nothing found to report\",\n        );\n    }\n\n    function getLabel() {\n        return \"Post commits to {$this->icfg['channel_name']} as {$this->icfg['botname']}\";\n    }\n\n}\n"
  },
  {
    "path": "plugins/gitlab_commits/templates/edit.tpl",
    "content": "<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n\n    <p>Channel to post to: <select name=\"channel\">\n        {foreach from=$channels key='chan_id' item='chan_name'}\n            <option value=\"{$chan_id|escape}\"{if $chan_id==$this->icfg.channel} selected{/if}>{$chan_name|escape}</option>\n        {/foreach}\n    </select></p>\n\n    <p>Bot name: <input type=\"text\" name=\"botname\" value=\"{$this->icfg.botname|escape}\" /></p>\n\n    <p><input type=\"submit\" value=\"Save Changes\" class=\"btn\" /></p>\n\n</form>"
  },
  {
    "path": "plugins/gitlab_commits/templates/view.tpl",
    "content": "{if $smarty.get.newtoken}\n\t<p class=\"alert\">Your token has been updated - the webhook URL has changed!</p>\n{/if}\n\n<p>Go to your repo's settings page and add this hook URL:</p>\n\n<p><code>{$this->getHookUrl()}</code></p>\n\n<p><b>Post to channel:</b> {$this->icfg.channel_name|escape}</p>\n<p><b>Bot name:</b> {$this->icfg.botname|escape}</p>\n\n<p><a href=\"{$this->getEditUrl()}\" class=\"btn\">Edit settings</a></p>"
  },
  {
    "path": "plugins/kiln/plugin.php",
    "content": "<?php\n//\n// Kiln Commit Integration Web Hook\n// =============================================================================\n//\n// Post commit messages from Kiln to a Slack chat room.\n//\n// Author: [Craig Davis](craig@there4development.com)\n//\n// For more information see:\n// * http://kiln.stackexchange.com/questions/952/\n// * http://kiln.stackexchange.com/questions/1345/\n// * http://help.fogcreek.com/8111/web-hooks-integrating-kiln-with-other-services#Custom_Web_Hooks\n//\n// -----------------------------------------------------------------------------\n//\nclass kiln extends SlackServicePlugin\n{\n    public $name = 'Kiln Commits';\n    public $desc = 'Provide commit summaries from Kiln';\n\n    public $cfg = array(\n        'has_token' => true,\n    );\n\n    public function onInit() {\n        $channels = $this->getChannelsList();\n        foreach ($channels as $channel => $name) {\n            if ($name == '#general') {\n                $this->icfg['channel'     ] = $channel;\n                $this->icfg['channel_name'] = $name;\n            }\n        }\n        $this->icfg['botname']      = 'kiln';\n        $this->icfg['max_messages'] = '5';\n        $this->icfg['icon_url']     = $GLOBALS['cfg']['root_url'] . '/plugins/kiln/icon_48.png';\n    }\n\n    public function onView() {\n        return $this->smarty->fetch('view.html');\n    }\n\n    public function getLabel() {\n        return \"Post commits to {$this->icfg['channel_name']} as {$this->icfg['botname']}\";\n    }\n\n    public function onEdit() {\n        var_dump($this->icfg);\n        $channels = $this->getChannelsList();\n\n        if ($_GET['save']) {\n            $this->icfg['channel']      = $_POST['channel'];\n            $this->icfg['channel_name'] = $channels[$_POST['channel']];\n            $this->icfg['botname']      = $_POST['botname'];\n            $this->icfg['icon_url']     = $_POST['icon_url'];\n            $this->icfg['max_messages'] = $_POST['max_messages'];\n            $this->saveConfig();\n\n            header(\"location: {$this->getViewUrl()}&saved=1\");\n            exit;\n        }\n\n        $this->smarty->assign('channels', $channels);\n        return $this->smarty->fetch('edit.html');\n    }\n\n    public function onHook($req) {\n        $payload        = json_decode($req['post']['payload'], true);\n        $repositoryName = $payload['repository']['name'];\n        $pusherName     = $payload['pusher']['fullName'];\n\n        $commits        = array_reverse($payload['commits']);\n        $commitCount    = count($commits);\n        $commits        = array_slice($commits, 0, $this->icfg['max_messages']);\n\n        $messageCount = 0;\n        foreach ($commits as $commit) {\n            $messageCount++;\n            $commit = (object) $commit;\n\n            // Fix a recent problem where the commit url comes from port 81\n            $commit->url = str_replace(\":81\", \"\", $commit->url);\n\n            // TODO: Handle commit messages with newlines\n            $message = '';\n            $message .= $this->escapeText(\"$pusherName pushed to \");\n            $message .= $this->escapeLink($commit->url, $repositoryName);\n            $message .= $this->escapeText(': ' . $commit->message);\n            $this->sendMessage($message);\n\n            // If this is a merge/merging, just show the first message\n            if (stripos($commit->message, 'merg') !== false) {\n                break;\n            }\n        }\n\n        if ($messageCount > $this->icfg['max_messages']) {\n            $remaining        = $messageCount - $this->icfg['max_messages'];\n            $commitInflection = ($remaining > 1) ? 'commits' : 'commit';\n            $this->sendMessage(\"and $remaining other $commitInflection.\");\n        }\n\n        return $logMessage;\n    }\n\n    private function sendMessage($text) {\n        $ret = $this->postToChannel($text, array(\n            'channel'  => $this->icfg['channel'],\n            'username' => $this->icfg['botname'],\n            'icon_url' => $this->icfg['icon_url']\n        ));\n\n        return array(\n            'ok'     => true,\n            'status' => 'Sent a message',\n        );\n    }\n}\n\n/* End of file plugin.php */\n"
  },
  {
    "path": "plugins/kiln/templates/edit.html",
    "content": "<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n    <p>\n        Channel to post to:\n        <select name=\"channel\">\n    {foreach from=$channels key='chan_id' item='chan_name'}\n            <option value=\"{$chan_id|escape}\"{if $chan_id==$this->icfg.channel} selected{/if}>{$chan_name|escape}</option>\n    {/foreach}\n        </select>\n    </p>\n\n    <p>Max message count: <input type=\"text\" name=\"max_messages\" size=\"55\" value=\"{$this->icfg.max_messages|escape}\"></p>\n    <p>Bot name: <input type=\"text\" name=\"botname\" value=\"{$this->icfg.botname|escape}\"></p>\n    <p>Bot icon: <input type=\"text\" name=\"icon_url\" size=\"55\" value=\"{$this->icfg.icon_url|escape}\"></p>\n    <p>\n        <input type=\"submit\" value=\"Save Changes\" class=\"btn\" />\n    </p>\n\n</form>\n"
  },
  {
    "path": "plugins/kiln/templates/view.html",
    "content": "\n{if $smarty.get.newtoken}\n<p class=\"alert\">Your token has been updated - the webhook URL has changed!</p>\n{/if}\n\n<h3>Your Kiln Hook URL</h3>\n<p><code>{$this->getHookUrl()}</code></p>\n\n<h3>Setting up Kiln</h3>\n<ol>\n    <li>Open Kiln Administration tools and select 'Web Hooks'</li>\n    <li>Select 'Create a new web hook'</li>\n    <li>Select the 'CaseOpened' event type</li>\n    <li>Name the hook, and select 'A custom hook'</li>\n    <li>Provide the URL above</li>\n    <li>Select the repositories for this hook, or select 'All repositories'</li>\n    <li>Click 'Create web hook'</li>\n</ol>\n\n\n<h3>Current Configuration</h3>\n<dl>\n    <dt><strong>Post to channel:</strong></dt>\n    <dd>{$this->icfg.channel|escape} / {$this->icfg.channel_name|escape}</dd>\n\n    <dt><strong>Maximum messages:</strong></dt>\n    <dd>{$this->icfg.max_messages|escape}</dd>\n\n    <dt><strong>Bot name:</strong></dt>\n    <dd>{$this->icfg.botname|escape}</dd>\n\n    <dt><strong>Bot icon:</strong></dt>\n    <dd><img src=\"{$this->icfg.icon_url}\" height=\"48\" width=\"48\" alt=\"bot icon\"></dd>\n</dl>\n\n<p><a href=\"{$this->getEditUrl()}\" class=\"btn\">Edit settings</a></p>\n"
  },
  {
    "path": "plugins/papertrail/plugin.php",
    "content": "<?php\n\n// author: Luka Kladaric luka@tripcommon.com\n// based on github_commits plugin\n\n\tclass papertrail extends SlackServicePlugin {\n\n\t\tpublic $name = \"Papertrail\";\n\t\tpublic $desc = \"Log collection and analysis\";\n\n\t\tpublic $cfg = array(\n\t\t\t'has_token'\t=> true,\n\t\t);\n\n\t\tfunction onInit() {\n\n\t\t\t$channels = $this->getChannelsList();\n\n\t\t\tforeach ($channels as $k => $v) {\n\t\t\t\tif ($v == '#general') {\n\t\t\t\t\t$this->icfg['channel'] = $k;\n\t\t\t\t\t$this->icfg['channel_name'] = $v;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$this->icfg['event_sample'] = 0;\n\t\t\t$this->icfg['botname']\t= 'papertrail';\n\t\t}\n\n\t\tfunction onView() {\n\t\t\treturn $this->smarty->fetch('view.txt');\n\t\t}\n\n\t\tfunction onEdit() {\n\n\t\t\t$channels = $this->getChannelsList();\n\n\t\t\tif ($_GET['save']) {\n\t\t\t\t$this->icfg['channel'] = $_POST['channel'];\n\t\t\t\t$this->icfg['channel_name'] = $channels[$_POST['channel']];\n\t\t\t\t$this->icfg['botname'] = $_POST['botname'];\n\t\t\t\t$this->icfg['event_sample'] = (int)$_POST['event_sample'];\n\t\t\t\t$this->saveConfig();\n\n\t\t\t\theader(\"location: {$this->getViewUrl()}&saved=1\");\n\t\t\t\texit;\n\t\t\t}\n\n\t\t\t$this->smarty->assign('channels', $channels);\n\n\t\t\treturn $this->smarty->fetch('edit.txt');\n\t\t}\n\n\t\tfunction onHook($req) {\n\n\t\t\tif (!$this->icfg['channel']) {\n\t\t\t\treturn array(\n\t\t\t\t\t'ok'\t=> false,\n\t\t\t\t\t'error'\t=> \"No channel configured\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t$payload = json_decode($req['post']['payload'], true);\n\n\t\t\tif (!$payload || !is_array($payload)) {\n\t\t\t\treturn array(\n\t\t\t\t\t'ok'\t=> false,\n\t\t\t\t\t'error' => \"No payload received from papertrail\",\n\t\t\t\t);\n\t\t\t}\n\n\n\t\t\t#\n\t\t\t# send some messages\n\t\t\t#\n\n\t\t\t$search = $payload['saved_search'];\n\n\t\t\t$events = $payload['events'];\n\t\t\t$num_events = count($events);\n\n\t\t\t$sample = $this->icfg['event_sample'];\n\n\t\t\tif ($sample) {\n\t\t\t\t// preserve only the last $event_sample events\n\t\t\t\t$events = array_slice($events, $sample * -1);\n\t\t\t}\n\n\t\t\t$num_sample = count($events);\n\n\t\t\tif ($num_events > 1) {\n\n\t\t\t\t$text = $this->searchLink($search) . $this->escapeText(\"{$num_events} new events\");\n\t\t\t\tif ($sample && $sample < $num_events) {\n\t\t\t\t\t$text .= $this->escapeText(\" (showing the latest {$sample})\");\n\t\t\t\t}\n\t\t\t\t$text .= $this->escapeText(\":\");\n\n\t\t\t\tforeach ($events as $e) {\n\t\t\t\t\t$text .= \"\\n\" . $this->renderEvent($e);\n\t\t\t\t}\n\n\t\t\t\t$num_diff = $num_events - $num_sample;\n\t\t\t\tif ($num_diff) {\n\t\t\t\t\t$text .= $this->escapeText(\"\\nAnd {$num_diff} others\");\n\t\t\t\t}\n\n\t\t\t\treturn $this->sendMessage($text);\n\t\t\t}\n\n\t\t\tif ($num_events) {\n\t\t\t\t$text = $this->searchLink($search) . $this->renderEvent($events[0]);\n\t\t\t\treturn $this->sendMessage($text);\n\t\t\t}\n\n\t\t\treturn array(\n\t\t\t\t'ok'\t\t=> true,\n\t\t\t\t'status'\t=> \"Nothing found to report\",\n\t\t\t);\n\t\t}\n\n\t\tprivate function searchLink($search) {\n\t\t\t$text = $this->escapeText(\"[\");\n\t\t\t$text .= $this->escapeLink($search['html_search_url'], $search['name']);\n\t\t\t$text .= $this->escapeText(\"] \");\n\n\t\t\treturn $text;\n\t\t}\n\n\t\tprivate function renderEvent($e) {\n\t\t\t$text = $this->escapeText(\"[\");\n\t\t\t$text .= $this->escapeLink(\"https://papertrailapp.com/systems/{$e['source_name']}/events?centered_on_id={$e['id']}\", $e['display_received_at']);\n\t\t\t$text .= $this->escapeText(\"] \");\n\t\t\t$text .= $this->escapeText(implode(\" \", array($e['hostname'], $e['program'], $e['message'])));\n\t\t\treturn $text;\n\t\t}\n\n\t\tfunction getLabel() {\n\t\t\treturn \"Post alerts to {$this->icfg['channel_name']} as {$this->icfg['botname']}\";\n\t\t}\n\n\t\tprivate function sendMessage($text) {\n\n\t\t\t$ret = $this->postToChannel($text, array(\n                                'channel'       => $this->icfg['channel'],\n                                'username'      => $this->icfg['botname'],\n                        ));\n\n\t\t\treturn array(\n\t\t\t\t'ok'\t\t=> true,\n\t\t\t\t'status'\t=> \"Sent a message\",\n\t\t\t);\n\t\t}\n\t}\n"
  },
  {
    "path": "plugins/papertrail/templates/edit.txt",
    "content": "\n\n<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n\n<p>Channel to post to: <select name=\"channel\">\n{foreach from=$channels key='chan_id' item='chan_name'}\n\t<option value=\"{$chan_id|escape}\"{if $chan_id==$this->icfg.channel} selected{/if}>{$chan_name|escape}</option>\n{/foreach}\n</select></p>\n\n<p>Bot name: <input type=\"text\" name=\"botname\" value=\"{$this->icfg.botname|escape}\" /></p>\n<p>Event sample: <input type=\"text\" name=\"event_sample\" value=\"{$this->icfg.event_sample|escape}\" /></p>\n\n<p><input type=\"submit\" value=\"Save Changes\" class=\"btn\" /></p>\n</form>\n"
  },
  {
    "path": "plugins/papertrail/templates/view.txt",
    "content": "{if $smarty.get.newtoken}\n\t<p class=\"alert\">Your token has been updated - the webhook URL has changed!</p>\n{/if}\n\n<p>Go to your alert's settings page and add this hook URL:</p>\n\n<p><code>{$this->getHookUrl()}</code></p>\n\n<p><b>Post to channel:</b> {$this->icfg.channel|escape} / {$this->icfg.channel_name|escape}</p>\n<p><b>Bot name:</b> {$this->icfg.botname|escape}</p>\n<p><b>Event sample:</b> {$this->icfg.event_sample|escape}</p>\n\n<p><a href=\"{$this->getEditUrl()}\" class=\"btn\">Edit settings</a></p>\n"
  },
  {
    "path": "plugins/plugins_default/plugin_name.php",
    "content": "<?php\n\n        class MyServicePlugin extends SlackServicePlugin {\n\n                const NAME = \"My Awesome Service\";\n                const DESC = \"This is what it does, yo\";\n                const TOOLTIP = \"It gives you info when you need it?\";\n                const DEFAULT_BOT_NAME = \"MASbot\";\n        }"
  },
  {
    "path": "plugins/plugins_default/templates/description.txt",
    "content": "<p class=\"bold\">{$DESC}</p>\n\n<p>Your detailed description of how this plugin will work should go here.</p>\n"
  },
  {
    "path": "plugins/plugins_default/templates/edit.txt",
    "content": "{if $error}\n        <div class=\"alert alert-error\"><i class=\"fa fa-exclamation-circle small_right_margin\"></i> Oops! That didn't work! Try again.</div>\n{/if}\n\n{include file=\"description.txt\"}\n\n<hr>\n\n<div id=\"service_setup\" class=\"accordion_section\">\n        <a class=\"accordion_expand btn btn-outline btn-small\" onclick=\"TS.web.toggleSection('service_setup');\">{if !$smarty.get.added}Expand{else}Close{/if}</a>\n        <h3><a onclick=\"TS.web.toggleSection('service_setup');\">Setup Instructions</a></h3>\n        <p>We'll guide you through the steps necessary to configure **Your Plugin** so it can start sending data to Slack.</p>\n\n        <div class=\"accordion_subsection\" style=\"{if !$smarty.get.added}display:none;{/if}\">\n                <h4>Step 1</h4>\n                <p>A description of what to do is here.</p>\n                <p class=\"large_bottom_margin\"><img src=\"{$asset}plugin_step1.png\" style=\"border-radius: 0.5rem; border: 1px solid #DDD;\"></p>\n\n        </div>\n</div>\n\n<form method=\"POST\" id=\"service_config\" action=\"{$this->getSaveUrl()}\" class=\"stacked\">\n        {hidden_fields}\n\n        <div id=\"service_settings\" class=\"accordion_section\">\n                <a class=\"accordion_expand btn btn-outline btn-small\" onclick=\"TS.web.toggleSection('service_settings');\">{if $smarty.get.added}Expand{else}Close{/if}</a>\n\n                <h3><a onclick=\"TS.web.toggleSection('service_settings');\">Integration Settings</a></h3>\n                <p>Modify which channel this integration posts to, and customize the bot appearance.</p>\n\n                <div class=\"accordion_subsection\" style=\"{if $smarty.get.added}display:none;{/if}\">\n                        {label}\n                        <p>\n                                <label class=\"block\">Which channel should we post Intercom alerts to?</label>\n                                {channel_select}\n                        </p>\n\n                        {bot_config}\n                </div>\n        </div>\n\n        <span class=\"inline-block\" id=\"add_integration_parent\" data-toggle=\"tooltip\" title=\"You must select a channel.\">\n                <button type=\"submit\" class=\"btn btn-small\" id=\"save_integration\">Save Integration</button>\n        </span>\n</form>\n\n\n"
  },
  {
    "path": "plugins/plugins_default/templates/new.txt",
    "content": "{if $error}\n        <div class=\"alert alert-error\"><i class=\"fa fa-exclamation-circle small_right_margin\"></i> Oops! That didn't work! Try again.</div>\n{/if}\n\n{include file=\"description.txt\"}\n\n<hr>\n\n<form method=\"POST\" id=\"service_config\" action=\"{$this->getSaveUrl()}\" class=\"stacked\">\n        {hidden_fields}\n\n        <p>\n                <label class=\"block\">Start by choosing a channel where **Your Plugin** alerts will be posted</label>\n                {channel_select}\n        </p>\n\n        <hr>\n\n        <span class=\"inline-block\" id=\"add_integration_parent\" data-toggle=\"tooltip\" title=\"You must select a channel.\">\n                <button type=\"submit\" id=\"add_integration\" class=\"btn disabled btn-success\" disabled=\"disabled\">Add Intercom Integration</button>\n        </span>\n</form>\n"
  },
  {
    "path": "plugins/plugins_default/templates/summary.txt",
    "content": "Post alerts to <strong>{$this->getChannelName($this->icfg.channel)|escape|default:'<i>unconfigured</i>'}</strong> as <strong>{$this->icfg.bot_name|escape}</strong>\n"
  },
  {
    "path": "plugins/plugins_default/tests/plugin_tests.php",
    "content": ""
  },
  {
    "path": "plugins/semaphore/plugin.php",
    "content": "<?php\n//\n// Semaphore Build Statuses Web Hook\n// =============================================================================\n//\n// Post Semaphore build status events to a Slack chat room.\n//\n// Author: [Brandon Valentine](brandon@brandonvalentine.com)\n//\n// -----------------------------------------------------------------------------\n//\nclass semaphore extends SlackServicePlugin\n{\n  public $name = \"Semaphore Build Status\";\n  public $desc = \"Process SemaphoreApp.com build status notifications and forward them on to Slack\";\n\n  public $cfg = array(\n    'has_token' => true,\n  );\n\n  public function onInit() {\n    $channels = $this->getChannelsList();\n    foreach ($channels as $channel => $name) {\n      if ($name == '#general') {\n        $this->icfg['channel'     ] = $channel;\n        $this->icfg['channel_name'] = $name;\n      }\n    }\n    $this->icfg['botname']      = 'Semaphore';\n    $this->icfg['icon_url']     = trim($GLOBALS['cfg']['root_url'], '/') . '/plugins/semaphore/icon_48.png';\n  }\n\n  public function onView() {\n    return $this->smarty->fetch('view.html');\n  }\n\n  public function getLabel() {\n    return \"Post build statuses to {$this->icfg['channel_name']} as {$this->icfg['botname']}\";\n  }\n\n  public function onEdit() {\n    var_dump($this->icfg);\n    $channels = $this->getChannelsList();\n\n    if ($_GET['save']) {\n      $this->icfg['channel']       = $_POST['channel'];\n      $this->icfg['channel_name']  = $channels[$_POST['channel']];\n      $this->icfg['botname']       = $_POST['botname'];\n      $this->icfg['icon_url']      = $_POST['icon_url'];\n      $this->saveConfig();\n\n      header(\"location: {$this->getViewUrl()}&saved=1\");\n      exit;\n    }\n\n    $this->smarty->assign('channels', $channels);\n    return $this->smarty->fetch('edit.html');\n  }\n\n  public function onHook($req) {\n    $payload = json_decode(file_get_contents('php://input'), true);\n\n\t\tif (!$payload || !is_array($payload)){\n\t\t\treturn array(\n\t\t\t\t'ok'\t=> false,\n\t\t\t\t'error' => \"No payload received from semaphore\",\n\t\t\t);\n\t\t}\n\n    $chatMessage = '';\n    $chatMessage .= $this->escapeText($payload['result'] === 'failed' ? ':x:' : ':white_check_mark:');\n    $chatMessage .= $this->escapeText('[' . $payload['project_name'] . '] ' . $payload['result'] . ': ');\n    $chatMessage .= $this->escapeText($payload['commit']['message']);\n    $chatMessage .= $this->escapeText(' - ' . $payload['commit']['author_name'] . ' (');\n    $chatMessage .= $this->escapeLink($payload['build_url']);\n    $chatMessage .= $this->escapeText(')');\n\n    $logMessage = 'Posted build status ' . $payload['build_url'];\n    $this->sendMessage($chatMessage);\n\n    return $logMessage;\n  }\n\n  private function sendMessage($text) {\n    $ret = $this->postToChannel($text, array(\n      'channel'  => $this->icfg['channel'],\n      'username' => $this->icfg['botname'],\n      'icon_url' => $this->icfg['icon_url'],\n    ));\n\n    return array(\n      'ok'     => true,\n      'status' => 'Sent a message',\n    );\n  }\n}\n\n/* End of file plugin.php */\n"
  },
  {
    "path": "plugins/semaphore/templates/edit.html",
    "content": "<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n    <p>\n        Channel to post to:\n        <select name=\"channel\">\n    {foreach from=$channels key='chan_id' item='chan_name'}\n            <option value=\"{$chan_id|escape}\"{if $chan_id==$this->icfg.channel} selected{/if}>{$chan_name|escape}</option>\n    {/foreach}\n        </select>\n    </p>\n\n    <p>Bot name: <input type=\"text\" name=\"botname\" value=\"{$this->icfg.botname|escape}\"></p>\n    <p>Bot icon: <input type=\"text\" name=\"icon_url\" size=\"55\" value=\"{$this->icfg.icon_url|escape}\"></p>\n\n    <p>\n        <input type=\"submit\" value=\"Save Changes\" class=\"btn\">\n    </p>\n\n</form>\n"
  },
  {
    "path": "plugins/semaphore/templates/view.html",
    "content": "{if $smarty.get.newtoken}\n<p class=\"alert\">Your token has been updated - the webhook URL has changed!</p>\n{/if}\n\n<h3>Your Semaphore Hook URL</h3>\n<p><code>{$this->getHookUrl()}</code></p>\n\n<h3>Setting up Semaphore</h3>\n<ol>\n    <li>Open Semaphore project settings and select 'Notifications'</li>\n    <li>Select Webhooks</li>\n    <li>Add a new Webhook</li>\n    <li>Use the hook url above</li>\n    <li>Select which events you want to receive notifications for</li>\n    <li>Click 'Save Settings'</li>\n</ol>\n\n<h3>Current Configuration</h3>\n<dl>\n    <dt><strong>Post to channel:</strong></dt>\n    <dd>{$this->icfg.channel|escape} / {$this->icfg.channel_name|escape}</dd>\n\n    <dt><strong>Bot name:</strong></dt>\n    <dd>{$this->icfg.botname|escape}</dd>\n\n    <dt><strong>Bot icon:</strong></dt>\n    <dd><img src=\"{$this->icfg.icon_url}\" height=\"48\" width=\"48\" alt=\"bot icon\"></dd>\n</dl>\n\n<p><a href=\"{$this->getEditUrl()}\" class=\"btn\">Edit settings</a></p>\n"
  },
  {
    "path": "plugins/sentry/plugin.php",
    "content": "<?php\n\nclass sentry extends SlackServicePlugin {\n\n    public $name = \"Sentry\";\n    public $desc = \"Track code exceptions\";\n\n    function onView(){\n        return $this->smarty->fetch('view.html');\n    }\n\n    function onEdit(){\n\n        $channels = $this->getChannelsList();\n\n        if ($_GET['save']){\n\n            $this->icfg['channel'] = $_POST['channel'];\n            $this->icfg['channel_name'] = $channels[$_POST['channel']];\n            $this->icfg['botname'] = $_POST['botname'];\n            $this->saveConfig();\n\n            header(\"location: {$this->getViewUrl()}&saved=1\");\n            exit;\n        }\n\n        $this->smarty->assign('channels', $channels);\n\n        return $this->smarty->fetch('edit.html');\n    }\n\n    function onHook($req){\n\n        $data = json_decode(file_get_contents('php://input'), true);\n        $level = $this->escapeText(strtoupper($data['level']));\n        $project_name = $this->escapeText($data['project_name']);\n        $message = $this->escapeText($data['message']);\n        $url = $this->escapeLink($data['url']);\n\n        $text = \"[{$level}] {$project_name} {$message} [{$url}]\";\n        $this->sendMessage($text);\n    }\n\n\n    private function sendMessage($text){\n\n        $ret = $this->postToChannel($text, array(\n                            'channel'       => $this->icfg['channel'],\n                            'username'      => $this->icfg['botname'],\n                    ));\n\n        return array(\n            'ok'        => true,\n            'status'    => \"Sent a message\",\n        );\n    }\n\n}\n"
  },
  {
    "path": "plugins/sentry/templates/edit.html",
    "content": "\n\n<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n\n<p>Channel to post to: <select name=\"channel\">\n{foreach from=$channels key='chan_id' item='chan_name'}\n\t<option value=\"{$chan_id|escape}\"{if $chan_id==$this->icfg.channel} selected{/if}>{$chan_name|escape}</option>\n{/foreach}\n</select></p>\n\n<p>Bot name: <input type=\"text\" name=\"botname\" value=\"{$this->icfg.botname|escape}\" /></p>\n\n<p><input type=\"submit\" value=\"Save Changes\" class=\"btn\" /></p>\n</form>\n"
  },
  {
    "path": "plugins/sentry/templates/view.html",
    "content": "<p>In your Sentry project, view Integrations and find WebHooks. Add the following URL:</p>\n\n<p><code>{$this->getHookUrl()}</code></p>\n\n<p><b>Post to channel:</b> {$this->icfg.channel|escape} / {$this->icfg.channel_name|escape}</p>\n<p><b>Bot name:</b> {$this->icfg.botname|escape}</p>\n\n<p><a href=\"{$this->getEditUrl()}\" class=\"btn\">Edit settings</a></p>\n"
  },
  {
    "path": "plugins/testflight/plugin.php",
    "content": "<?php\n// TestFlight Integration Hook\n//\nclass testflight extends SlackServicePlugin\n{\n  public $name = 'TestFlight';\n  public $desc = 'Provide Support For TestFlight Webhooks';\n  \n\tpublic $cfg = array(\n\t\t'has_token'\t=> true,\n\t);\n  \n  public function onInit() {\n      $channels = $this->getChannelsList();\n      foreach ($channels as $channel => $name) {\n          if ($name == '#general') {\n              $this->icfg['channel'     ] = $channel;\n              $this->icfg['channel_name'] = $name;\n          }\n      }\n      $this->icfg['botname']      = 'TestFlight';\n      $this->icfg['icon_url']     = trim($GLOBALS['cfg']['root_url'], '/') . '/plugins/testflight/icon_48.png';\n  }\n\n  public function onView() {\n      return $this->smarty->fetch('view.html');\n  }\n\n  public function getLabel() {\n      return \"Post Builds to {$this->icfg['channel_name']} as {$this->icfg['botname']}\";\n  }\n\n  public function onEdit() {\n      var_dump($this->icfg);\n      $channels = $this->getChannelsList();\n\n      if ($_GET['save']) {\n          $this->icfg['channel']       = $_POST['channel'];\n          $this->icfg['channel_name']  = $channels[$_POST['channel']];\n          $this->icfg['botname']       = $_POST['botname'];\n          $this->icfg['icon_url']      = $_POST['icon_url'];\n          $this->saveConfig();\n\n          header(\"location: {$this->getViewUrl()}&saved=1\");\n          exit;\n      }\n\n      $this->smarty->assign('channels', $channels);\n      return $this->smarty->fetch('edit.html');\n  }\n\n  public function onHook($req) {\n      $log_message = '';\n      \n      $tf_payload = json_decode($req['post_body'], true);\n      \n      if ($tf_payload && count($tf_payload)) {\n        # we have a payload\n        $title = trim($tf_payload['title']);\n        $link_href = trim($tf_payload['build']['url_html']);\n\n        $chat_message = sprintf(\"%s \\n Build Number (%d) %s\", $title, $tf_payload['build']['id'], $this->escapeLink($link_href, \"Install Build\"));\n        $this->sendMessage($chat_message);\n      } else {\n        ob_start();\n        var_dump($req);\n        $result = ob_get_clean();\n        return array(\n          'ok' => false,\n          'error' => \"No payload received from TestFlight\",\n          'debug' => $result\n        );\n      }\n      return $log_message;\n  }\n\n  private function sendMessage($text) {\n      $ret = $this->postToChannel($text, array(\n          'channel'  => $this->icfg['channel'],\n          'username' => $this->icfg['botname'],\n          'icon_url' => $this->icfg['icon_url'],\n      ));\n\n      return array(\n          'ok'     => true,\n          'status' => 'Sent a message: ' . $text,\n      );\n  }\n}\n"
  },
  {
    "path": "plugins/testflight/templates/edit.html",
    "content": "<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n    <p>\n        Channel to post to:\n        <select name=\"channel\">\n    {foreach from=$channels key='chan_id' item='chan_name'}\n            <option value=\"{$chan_id|escape}\"{if $chan_id==$this->icfg.channel} selected{/if}>{$chan_name|escape}</option>\n    {/foreach}\n        </select>\n    </p>\n\n    <p>Bot name: <input type=\"text\" name=\"botname\" value=\"{$this->icfg.botname|escape}\"></p>\n    <p>Bot icon: <input type=\"text\" name=\"icon_url\" size=\"55\" value=\"{$this->icfg.icon_url|escape}\"></p>\n\n    <p>\n        <input type=\"submit\" value=\"Save Changes\" class=\"btn\">\n    </p>\n\n</form>\n"
  },
  {
    "path": "plugins/testflight/templates/view.html",
    "content": "\n{if $smarty.get.newtoken}\n<p class=\"alert\">Your token has been updated - the webhook URL has changed!</p>\n{/if}\n\n<h3>Your TestFlight Hook URL</h3>\n<p><code>{$this->getHookUrl()}</code></p>\n\n<h3>Setting up TestFlight</h3>\n<ol>\n  <li>1. Select App To Create Integration For</li>\n  <li>2. Select 'App Integrations' on the left hand pane</li>\n  <li>3. Under the Web Hook section, click add new</li>\n  <li>4. Paste in web hook url and hit save<li>\n</ol>\n\n<h3>Current Configuration</h3>\n<dl>\n    <dt><strong>Post to channel:</strong></dt>\n    <dd>{$this->icfg.channel|escape} / {$this->icfg.channel_name|escape}</dd>\n\n    <dt><strong>Bot name:</strong></dt>\n    <dd>{$this->icfg.botname|escape}</dd>\n\n    <dt><strong>Bot icon:</strong></dt>\n    <dd><img src=\"{$this->icfg.icon_url}\" height=\"48\" width=\"48\" alt=\"bot icon\"></dd>\n</dl>\n\n<p><a href=\"{$this->getEditUrl()}\" class=\"btn\">Edit settings</a></p>"
  },
  {
    "path": "style.css",
    "content": "body {\r\n\tcolor: #555459;\r\n\tfont-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\r\n\tfont-size: 16px;\r\n\tline-height: 1.5rem;\r\n}\r\n\r\n* {\r\n  -ms-box-sizing: border-box;\r\n  -moz-box-sizing: border-box;\r\n  -webkit-box-sizing: border-box;\r\n  box-sizing: border-box;\r\n}\r\n\r\na {\r\n  color: #0088cc;\r\n  text-decoration: none;\r\n}\r\n\r\na:hover,\r\na:focus {\r\n  color: #005580;\r\n  text-decoration: underline;\r\n}\r\n\r\n\r\n#header {\r\nposition: fixed;\r\ntop: 0;\r\nleft: 0;\r\npadding: 0;\r\nbackground: white;\r\nheight: 60px;\r\nwidth: 100%;\r\nmargin-bottom: 2rem;\r\nfont-size: 15px;\r\nz-index: 10;\r\nbackground: #fbfbfb;\r\n-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);\r\n-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);\r\nbox-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n#header-inner {\r\n\twidth: 940px;\r\n\tmargin: 16px auto 10px auto;\r\n}\r\n\r\n#page-inner {\r\n\twidth: 940px;\r\n\tmargin: 80px auto 80px auto;\r\n\txborder: 1px solid black;\r\n\txpadding: 1em;\r\n}\r\n\r\n#slack_icon {\r\nfloat: left;\r\ndisplay: inline-block;\r\nmargin-top: -3px;\r\nmargin-right: 0.4rem;\r\nwidth: 32px;\r\nheight: 32px;\r\n}\r\n\r\nh1, h2, h3, h4 {\r\n\tfont-weight: 900;\r\n\tfont-family: 'Lato', sans-serif;\r\n\tcolor: #555459;\r\n\t-webkit-font-smoothing: antialiased;\r\n\tmargin: 0 0 1rem 0;\r\n}\r\n\r\nh1 a {\r\n\tcolor: #555459;\r\n\ttext-decoration: none;\r\n}\r\n\r\nh1 a:hover {\r\n\tcolor: #4A494D;\r\n}\r\n\r\nh2 {\r\n\tfont-size: 1.5rem;\r\n\tline-height: 2rem;\r\n}\r\n\r\n.alert {\r\n\tfont-size: 0.9rem;\r\n\tcolor: #c09853;\r\n\tpadding: 8px 35px 8px 14px;\r\n\tmargin-bottom: 20px;\r\n\ttext-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\r\n\tbackground-color: #fcf8e3;\r\n\tborder: 1px solid #fbeed5;\r\n\t-webkit-border-radius: 4px;\r\n\t-moz-border-radius: 4px;\r\n\tborder-radius: 4px;\r\n}\r\n\r\n.alert-danger, .alert-error {\r\n\tcolor: #b94a48;\r\n\tbackground-color: #f2dede;\r\n\tborder-color: #eed3d7;\r\n}\r\n\r\n.btn {\r\nbackground: #2a80b9;\r\ncolor: white !important;\r\ntext-shadow: 0 1px rgba(0, 0, 0, 0.2);\r\n-webkit-font-smoothing: antialiased;\r\nfont-family: 'Lato', sans-serif;\r\nline-height: 1.2rem;\r\nfont-weight: 900;\r\n-webkit-user-select: none;\r\n-moz-user-select: none;\r\n-ms-user-select: none;\r\nuser-select: none;\r\ntext-decoration: none;\r\nborder: none;\r\n-webkit-border-radius: 0.25rem;\r\n-moz-border-radius: 0.25rem;\r\nborder-radius: 0.25rem;\r\n-webkit-box-shadow: none;\r\n-moz-box-shadow: none;\r\nbox-shadow: none;\r\nvertical-align: bottom;\r\nwhite-space: nowrap;\r\npadding: 7px 14px 8px;\r\nfont-size: 15px;\r\n}\r\n\r\n.btn:hover, .btn:focus {\r\nbackground: #439fe0;\r\ncolor: white;\r\noutline: none;\r\n}\r\n\r\n.btn:active, .btn.active {\r\nbackground: #439fe0;\r\ncolor: white;\r\n-webkit-box-shadow: inset 0 2px 1px rgba(0, 0, 0, 0.25);\r\n-moz-box-shadow: inset 0 2px 1px rgba(0, 0, 0, 0.25);\r\nbox-shadow: inset 0 2px 1px rgba(0, 0, 0, 0.25);\r\n}\r\n\r\n.btn-danger {\r\n\tbackground: #d00000;\r\n}\r\n\r\n.btn-danger:hover, .btn-danger:focus, .btn-danger:active {\r\n\tbackground: #e60000;\r\n}\r\n\r\n.btn-warning {\r\n\tbackground: #daa038;\r\n}\r\n\r\n.btn-warning:hover, .btn-warning:focus, .btn-warning:active {\r\n\tbackground: #e8ac3c;\r\n}\r\n\r\n.btn-success {\r\n\tbackground: #36a64f;\r\n}\r\n\r\n.btn-success:hover, .btn-success:focus, .btn-success:active {\r\n\tbackground: #3ebd5a;\r\n}\r\n\r\n.godblock {\r\nborder: 1px solid #becccc;\r\n-moz-border-radius: 15px;\r\nborder-radius: 15px;\r\nbackground-image: url(https://slack.global.ssl.fastly.net/5065/img/stripes_bg.gif);\r\npadding: 8px;\r\nposition: relative;\r\ntext-align: left;\r\n}\r\n\r\n.godblock pre {\r\n\tmargin: 0;\r\n}\r\n\r\ncode {\r\nfont-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\r\n-webkit-border-radius: 3px;\r\n-moz-border-radius: 3px;\r\nborder-radius: 3px;\r\npadding: 2px 4px;\r\ncolor: #d14;\r\nbackground-color: #f7f7f9;\r\nborder: 1px solid #e1e1e8;\r\nfont-size: 0.8rem;\r\nwhite-space: normal;\r\n}\r\n\r\nform {\r\n\tmargin: 0;\r\n\tpadding: 0;\r\n}\r\n\r\n.col_left {\r\n  width: 198px;\r\n  margin-right: 2rem;\r\n  padding-right: 0.5rem;\r\n  float: left;\r\n}\r\n.col_right {\r\n  width: 700px;\r\n  float: left;\r\n}\r\n\r\n\r\n/* Add Services Grid */\r\n.service {\r\n  width: 226px;\r\n  float: left;\r\n  margin: 0 0.6rem 0.6rem 0;\r\n  border: 1px solid #DDD;\r\n  -webkit-border-radius: 0.5rem;\r\n  -moz-border-radius: 0.5rem;\r\n  border-radius: 0.5rem;\r\n  -webkit-transitionDISABLED: background 0.1s, color 0.1s 0.2s ease-out;\r\n  -moz-transitionDISABLED: background 0.1s, color 0.1s 0.2s ease-out;\r\n  -o-transitionDISABLED: background 0.1s, color 0.1s 0.2s ease-out;\r\n  transitionDISABLED: background 0.1s, color 0.1s 0.2s ease-out;\r\n  -webkit-transitionDISABLED: background 0.1s, color 0.1s;\r\n  -moz-transitionDISABLED: background 0.1s, color 0.1s;\r\n  -o-transitionDISABLED: background 0.1s, color 0.1s;\r\n  transitionDISABLED: background 0.1s, color 0.1s;\r\n  line-height: 1.25rem;\r\n  color: #555459;\r\n  padding: 0.9rem;\r\n  font-family: 'Lato', sans-serif;\r\n  text-align: center;\r\n}\r\n.service .icon {\r\n  margin: 0 auto 1rem;\r\n  display: block;\r\n  width: 64px;\r\n  height: 64px;\r\n  cursor: pointer;\r\n}\r\n.service:hover {\r\n  cursor: default;\r\n  background: #f1f7fa;\r\n}\r\n.service h4,\r\n.service h4 a {\r\n  color: #555459;\r\n  -webkit-transitionDISABLED: color 0.1s ease-out;\r\n  -moz-transitionDISABLED: color 0.1s ease-out;\r\n  -o-transitionDISABLED: color 0.1s ease-out;\r\n  transitionDISABLED: color 0.1s ease-out;\r\n  cursor: pointer;\r\n}\r\n.service:hover h4,\r\n.service:hover h4 a {\r\n  color: #2a80b9;\r\n}\r\n.service h4:hover {\r\n  text-decoration: underline;\r\n}\r\n.service button,\r\n.service .btn {\r\n  width: 100%;\r\n}\r\n\r\n.no_right_margin {\r\n  margin-right: 0 !important;\r\n}\r\n\r\n\r\nul,\r\nol {\r\n  padding: 0;\r\n  margin: 0 0 10px 25px;\r\n}\r\n\r\nul ul,\r\nul ol,\r\nol ol,\r\nol ul {\r\n  margin-bottom: 0;\r\n}\r\n\r\nli {\r\n  line-height: 20px;\r\n}\r\n\r\nul.unstyled,\r\nol.unstyled {\r\n  margin-left: 0;\r\n  list-style: none;\r\n}\r\n\r\nul.inline,\r\nol.inline {\r\n  margin-left: 0;\r\n  list-style: none;\r\n}\r\n\r\nul.inline > li,\r\nol.inline > li {\r\n  display: inline-block;\r\n  *display: inline;\r\n  padding-right: 5px;\r\n  padding-left: 5px;\r\n  *zoom: 1;\r\n}\r\n\r\n\r\n\r\n/* Sidebar Nav */\r\nul.sidebar_nav {\r\n  list-style-type: none;\r\n  margin: 0 0 1rem;\r\n}\r\nul.sidebar_nav li {\r\n  font-size: 1rem;\r\n  line-height: 1.75rem;\r\n  font-weight: bold;\r\n  font-family: 'Lato', sans-serif;\r\n  color: #555459;\r\n}\r\n.sidebar_nav i {\r\n  width: 1.75rem;\r\n  display: inline-block;\r\n  text-align: center;\r\n  padding: 0 0.5rem 0 0;\r\n  font-size: 18px;\r\n}\r\n.sidebar_nav a:hover i {\r\n  text-decoration: none;\r\n}\r\n\r\n/* Services */\r\n.service_group a {\r\n  color: #555459 !important;\r\n  -webkit-transitionDISABLED: 0.1s 0.2s ease-out;\r\n  -moz-transitionDISABLED: 0.1s 0.2s ease-out;\r\n  -o-transitionDISABLED: 0.1s 0.2s ease-out;\r\n  transitionDISABLED: 0.1s 0.2s ease-out;\r\n  -webkit-transitionDISABLED: 0.1s;\r\n  -moz-transitionDISABLED: 0.1s;\r\n  -o-transitionDISABLED: 0.1s;\r\n  transitionDISABLED: 0.1s;\r\n}\r\n.service_group:hover a {\r\n  color: #2a80b9 !important;\r\n}\r\n.service_group a:hover {\r\n  color: #439fe0 !important;\r\n}\r\n.service_icon {\r\n  margin: 0px 0.5rem 0 0;\r\n  display: block;\r\n  float: left;\r\n  width: 24px;\r\n  height: 24px;\r\n}\r\n.service_summary strong {\r\n  font-weight: 500;\r\n}\r\n\r\n.mini {\r\n  font-size: 0.8rem;\r\n  line-height: 1.2rem;\r\n  color: #666;\r\n}\r\n.block {\r\n  display: block;\r\n}\r\n\r\n.large_bottom_margin {\r\nmargin-bottom: 2rem !important;\r\n}\r\n"
  },
  {
    "path": "templates/inc_foot.txt",
    "content": "</div>\n\n</body>\n</html>\n\n"
  },
  {
    "path": "templates/inc_head.txt",
    "content": "{'Content-Type: text/html; charset=utf-8'|header}<html>\r\n<head>\r\n<meta charset=\"utf-8\">\r\n<title>Hammock</title>\r\n<link id=\"favicon\" rel=\"shortcut icon\" href=\"images/favicon_32.png\" sizes=\"16x16 32x32 48x48\" type=\"image/png\" />\r\n<link href='https://fonts.googleapis.com/css?family=Lato:400,700,900,400italic,700italic,900italic' rel='stylesheet' type='text/css'>\r\n<link href=\"//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css\" rel=\"stylesheet\">\r\n<link href=\"style.css\" rel=\"stylesheet\" type=\"text/css\">\r\n</head>\r\n<body>\r\n\r\n<div id=\"header\">\r\n<div id=\"header-inner\">\r\n{if $cfg.user.user_id}\r\n\t<div style=\"float: right\">\r\n\t\tLogged in as <b>{$cfg.user.user|escape}</b>\r\n\t\t[<a href=\"logout.php\">logout</a>]\r\n\t</div>\r\n{/if}\r\n<h1>\r\n\t<a href=\"./\"><img src=\"./images/logo.png\" id=\"slack_icon\"></a>\r\n\t<a href=\"./\">Hammock</a>\r\n</h1>\r\n</div>\r\n</div>\r\n\r\n<div id=\"page-inner\">\r\n"
  },
  {
    "path": "templates/inc_left.txt",
    "content": "<div class=\"col_left\">\n\n\t<h2>Integrations</h2>\n\n\t<ul class=\"sidebar_nav large_bottom_margin\">\n{if $nav=='new'}\n\t\t<li><i class=\"icon-plus-sign\"></i>Add New Integration</li>\n{else}\n\t\t<li><a href=\"new.php\"><i class=\"icon-plus-sign\"></i>Add New Integration</a></li>\n{/if}\n{if $nav=='index'}\n\t\t<li><i class=\"icon-wrench\"></i>Existing Integrations</li>\n{else}\n\t\t<li><a href=\"./\"><i class=\"icon-wrench\"></i>Existing Integrations</a></li>\n{/if}\n\t</ul>\n\n</div>\n"
  },
  {
    "path": "templates/page_add.txt",
    "content": "{include file='inc_head.txt'}\n\n<h2>Add new service - {$instance->name}</h2>\n\n<p>{$instance->desc}</p>\n\n<form action=\"add.php\" method=\"post\">\n<input type=\"hidden\" name=\"done\" value=\"1\" />\n<input type=\"hidden\" name=\"plugin\" value=\"{$instance->id}\" />\n<input type=\"hidden\" name=\"uid\" value=\"{$instance->iid}\" />\n\n<input type=\"submit\" value=\"Add Service\" class=\"btn btn-success\" />\n</form>\n\n{include file='inc_foot.txt'}\n"
  },
  {
    "path": "templates/page_auth.txt",
    "content": "{include file='inc_head.txt'}\n\n<h2>Auth Plugin - {$instance->name}</h2>\n\n{$html}\n\n{include file='inc_foot.txt'}\n"
  },
  {
    "path": "templates/page_edit.txt",
    "content": "{include file='inc_head.txt'}\n\n<h2>Edit Service</h2>\n\n{*<div class=\"alert\">\n\t<strong>This integration has been disabled.</strong><br />\n\tIt will not process messages or respond to events until it is re-enabled.\n</div>*}\n\n{$html}\n\n{include file='inc_foot.txt'}\n"
  },
  {
    "path": "templates/page_index.txt",
    "content": "{include file='inc_head.txt}\r\n\r\n{include file='inc_left.txt' nav='index'}\r\n\r\n<div class=\"col_right\">\r\n\r\n\t<h2>Existing Integrations</h2>\r\n\r\n{foreach from=$instances item='row'}\r\n\t<div class=\"service_group large_bottom_margin\">\r\n\r\n\t\t<h3 class=\"service_group_name small_bottom_margin\">\r\n\t\t\t<img src=\"{$row.plugin->icon_48}\" width=\"24\" height=\"24\" class=\"service_icon\" />\r\n\t\t\t{$row.plugin->name|escape}\r\n\t\t</h3>\r\n\r\n\t\t<ul>\r\n{foreach from=$row.instances item='obj'}\r\n\t\t\t<li class=\"service_summary small_bottom_margin\">\r\n\t\t\t\t<a href=\"view.php?id={$obj->iid|urlencode}\">{$obj->getLabel()}</a>\r\n{if $obj->icfg.creator_id}\r\n\t\t\t\t<span class=\"service_meta mini block\">\r\n\t\t\t\t\tCreated by <a href=\"{$obj->icfg.creator_url}\" class=\"bold\">{$obj->icfg.creator_name}</a>\r\n\t\t\t\t\ton {'M j, Y'|date:$obj->icfg.created}\r\n\t\t\t\t</span>\r\n{/if}\r\n\t\t\t</li>\r\n{/foreach}\r\n\t\t</ul>\r\n\t</div>\r\n{/foreach}\r\n\r\n{if $auth|@count}\r\n<b>Things to configure</b>\r\n\r\n<ul>\r\n{foreach from=$auth item='k'}\r\n\t<li><a href=\"auth.php?id={$k->id|urlencode}\">{$k->name|escape}</a> - {$k->desc|escape} </li>\r\n{/foreach}\r\n</ul>\r\n{/if}\r\n\r\n</div>\r\n\r\n{include file='inc_foot.txt}\r\n"
  },
  {
    "path": "templates/page_login.txt",
    "content": "{include file='inc_head.txt}\n\n{if $bad_cookie_domain}\n\n\t<p style=\"text-align: center; padding: 2em 0 1em 0\">\n\t\t<code>$cfg.cookie_domain</code> must contain a period.<br />\n\t\tPlease read the note in <code>lib/config.php</code>.\n\t</p>\n\n{elseif $first_time}\n\n\t<p style=\"text-align: center; padding: 2em 0 1em 0\">\n\t\tIt looks like you're setting up Hammock for the first time.\n\t\tYou'll need to authenticate against a Slack account to start adding integrations.\n\t</p>\n\n\t<p style=\"text-align: center; padding: 0 0 2em 0\">\n\t\tOnce you have chosen a Slack team, all users will need to sign into that team.\n\t</p>\n\n\t<p style=\"text-align: center\"><a href=\"{$oauth_url}\" class=\"btn\">Authenticate</a></p>\n\n{else}\n\n\t<p style=\"text-align: center; padding: 2em 0 2em 0\">You'll need to log into your Slack account to continue.</p>\n\n\t<p style=\"text-align: center\"><a href=\"{$oauth_url}\" class=\"btn\">Authenticate</a></p>\n\n{/if}\n\n{include file='inc_foot.txt}\n"
  },
  {
    "path": "templates/page_new.txt",
    "content": "{include file='inc_head.txt}\r\n\r\n{include file='inc_left.txt' nav='new'}\r\n\r\n<div class=\"col_right\">\r\n\r\n\t<h2>Add Service Integrations</h2>\r\n\r\n{foreach from=$services item='set'}\r\n\t<div style=\"clear: left\">\r\n{foreach from=$set item='k' name='inner'}\r\n\t<form method=\"POST\" action=\"add.php?id={$k->id|urlencode}\" class=\"service{if $smarty.foreach.inner.last} no_right_margin{/if}\">\r\n\r\n\t\t<img src=\"plugins/{$k->id|escape}/icon_64.png\" width=\"64\" height=\"64\" class=\"icon\" />\r\n\r\n\t\t<h4>{$k->name|escape}</h4>\r\n\t\t<p>{$k->desc|escape}</p>\r\n\t\r\n\t\t<button type=\"submit\" class=\"btn btn-small btn-primary\"><i class=\"icon-plus-sign\" style=\"margin-right: 0.25rem;\"></i> {$k->name|escape}</button>\r\n\t</form>\r\n{/foreach}\r\n\t</div>\r\n{/foreach}\r\n\r\n{if !$services|@count}\r\n\t<p>You don't have any service plugins installed.</p>\r\n{/if}\r\n\r\n</div>\r\n\r\n{include file='inc_foot.txt}\r\n"
  },
  {
    "path": "templates/page_view.txt",
    "content": "{include file='inc_head.txt'}\n\n<h2>Service Instance</h2>\n\n{*<div class=\"alert\">\n\t<strong>This integration has been disabled.</strong><br />\n\tIt will not process messages or respond to events until it is re-enabled.\n</div>*}\n\n{$html}\n\n<p>&nbsp;</p>\n\n\n{* Change token *}\n\n{if $instance->cfg.has_token}\n\n<div class=\"alert\">\n\tThe current token for this service is <code>{$instance->icfg.token}</code>.<br />\n\n\t<form action=\"{$instance->getViewUrl()}\" method=\"post\">\n\t<input type=\"hidden\" name=\"new-token\" value=\"1\" />\n\t<p style=\"margin: 0\"><input type=\"submit\" value=\"Change token\" class=\"btn btn-warning\" /></p>\n\t</form>\n\n</div>\n\n{/if}\n\n\n{* Delete *}\n\n<div class=\"alert alert-error\">\n\n\t<form action=\"{$instance->getViewUrl()}\" method=\"post\">\n\t<input type=\"hidden\" name=\"delete-instance\" value=\"1\" />\n\t<p style=\"margin: 0\"><input type=\"submit\" value=\"Delete Integration\" class=\"btn btn-danger\" /></p>\n\t</form>\n\n</div>\n\n<div class=\"godblock\">\n\t{$instance->icfg|@dumper}\n</div>\n\n{include file='inc_foot.txt'}\n"
  },
  {
    "path": "view.php",
    "content": "<?php\n\t$dir = dirname(__FILE__);\n\tinclude(\"$dir/lib/init.php\");\n\t\n\tverify_auth();\n\n\tload_plugins();\n\n\t$instance = getPluginInstance($_GET['id']);\n\tif (!is_object($instance)) die(\"instance not found\");\n\n\tif ($_POST['delete-instance']){\n\t\t$instance->deleteMe();\n\t\theader(\"location: ./\");\n\t\texit;\n\t}\n\n\tif ($_POST['new-token']){\n\t\t$instance->regenToken();\n\t\t$instance->saveConfig();\n\t\theader(\"location: {$instance->getViewUrl()}&newtoken=1\");\n                exit;\n\t}\n\n\t$instance->checkRequirements();\n\n\t$smarty->assign('instance', $instance);\n\t$smarty->assign('html', $instance->onView());\n\n\t$smarty->display('page_view.txt');\n\n"
  }
]