Showing preview only (453K chars total). Download the full file or copy to clipboard to get everything.
Repository: tinyspeck/hammock
Branch: master
Commit: c972ac8abdd6
Files: 144
Total size: 415.9 KB
Directory structure:
gitextract_vqbfnmbo/
├── .gitignore
├── README.md
├── TODO
├── add.php
├── auth.php
├── docs/
│ ├── services.md
│ └── services_ref.md
├── edit.php
├── hook.php
├── index.php
├── lib/
│ ├── auth.php
│ ├── config.php.example
│ ├── config_env.php
│ ├── data.php
│ ├── data_files.php
│ ├── data_redis.php
│ ├── http.php
│ ├── init.php
│ ├── service.php
│ └── smarty/
│ ├── Config_File.class.php
│ ├── Smarty.class.php
│ ├── Smarty_Compiler.class.php
│ ├── debug.tpl
│ ├── internals/
│ │ ├── core.assemble_plugin_filepath.php
│ │ ├── core.assign_smarty_interface.php
│ │ ├── core.create_dir_structure.php
│ │ ├── core.display_debug_console.php
│ │ ├── core.get_include_path.php
│ │ ├── core.get_microtime.php
│ │ ├── core.get_php_resource.php
│ │ ├── core.is_secure.php
│ │ ├── core.is_trusted.php
│ │ ├── core.load_plugins.php
│ │ ├── core.load_resource_plugin.php
│ │ ├── core.process_cached_inserts.php
│ │ ├── core.process_compiled_include.php
│ │ ├── core.read_cache_file.php
│ │ ├── core.rm_auto.php
│ │ ├── core.rmdir.php
│ │ ├── core.run_insert_handler.php
│ │ ├── core.smarty_include_php.php
│ │ ├── core.write_cache_file.php
│ │ ├── core.write_compiled_include.php
│ │ ├── core.write_compiled_resource.php
│ │ └── core.write_file.php
│ └── plugins/
│ ├── block.textformat.php
│ ├── compiler.assign.php
│ ├── function.assign_debug_info.php
│ ├── function.config_load.php
│ ├── function.counter.php
│ ├── function.cycle.php
│ ├── function.debug.php
│ ├── function.eval.php
│ ├── function.fetch.php
│ ├── function.html_checkboxes.php
│ ├── function.html_image.php
│ ├── function.html_options.php
│ ├── function.html_radios.php
│ ├── function.html_select_date.php
│ ├── function.html_select_time.php
│ ├── function.html_table.php
│ ├── function.mailto.php
│ ├── function.math.php
│ ├── function.popup.php
│ ├── function.popup_init.php
│ ├── modifier.capitalize.php
│ ├── modifier.cat.php
│ ├── modifier.count_characters.php
│ ├── modifier.count_paragraphs.php
│ ├── modifier.count_sentences.php
│ ├── modifier.count_words.php
│ ├── modifier.date_format.php
│ ├── modifier.debug_print_var.php
│ ├── modifier.default.php
│ ├── modifier.escape.php
│ ├── modifier.indent.php
│ ├── modifier.lower.php
│ ├── modifier.nl2br.php
│ ├── modifier.regex_replace.php
│ ├── modifier.replace.php
│ ├── modifier.spacify.php
│ ├── modifier.string_format.php
│ ├── modifier.strip.php
│ ├── modifier.strip_tags.php
│ ├── modifier.truncate.php
│ ├── modifier.upper.php
│ ├── modifier.wordwrap.php
│ ├── outputfilter.trimwhitespace.php
│ ├── shared.escape_special_chars.php
│ └── shared.make_timestamp.php
├── logout.php
├── new.php
├── oauth.php
├── plugins/
│ ├── atlassian_stash_commits/
│ │ ├── plugin.php
│ │ └── templates/
│ │ ├── edit.tpl
│ │ └── view.tpl
│ ├── coveralls/
│ │ ├── plugin.php
│ │ └── templates/
│ │ ├── edit.html
│ │ └── view.html
│ ├── dployio/
│ │ ├── plugin.php
│ │ └── templates/
│ │ ├── edit.tpl
│ │ └── view.tpl
│ ├── fogbugz/
│ │ ├── plugin.php
│ │ └── templates/
│ │ ├── edit.html
│ │ └── view.html
│ ├── github_commits/
│ │ ├── plugin.php
│ │ └── templates/
│ │ ├── edit.txt
│ │ └── view.txt
│ ├── gitlab_commits/
│ │ ├── plugin.php
│ │ └── templates/
│ │ ├── edit.tpl
│ │ └── view.tpl
│ ├── kiln/
│ │ ├── plugin.php
│ │ └── templates/
│ │ ├── edit.html
│ │ └── view.html
│ ├── papertrail/
│ │ ├── plugin.php
│ │ └── templates/
│ │ ├── edit.txt
│ │ └── view.txt
│ ├── plugins_default/
│ │ ├── plugin_name.php
│ │ ├── templates/
│ │ │ ├── description.txt
│ │ │ ├── edit.txt
│ │ │ ├── new.txt
│ │ │ └── summary.txt
│ │ └── tests/
│ │ └── plugin_tests.php
│ ├── semaphore/
│ │ ├── plugin.php
│ │ └── templates/
│ │ ├── edit.html
│ │ └── view.html
│ ├── sentry/
│ │ ├── plugin.php
│ │ └── templates/
│ │ ├── edit.html
│ │ └── view.html
│ └── testflight/
│ ├── plugin.php
│ └── templates/
│ ├── edit.html
│ └── view.html
├── style.css
├── templates/
│ ├── inc_foot.txt
│ ├── inc_head.txt
│ ├── inc_left.txt
│ ├── page_add.txt
│ ├── page_auth.txt
│ ├── page_edit.txt
│ ├── page_index.txt
│ ├── page_login.txt
│ ├── page_new.txt
│ └── page_view.txt
└── view.php
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
lib/config.php
data/*
================================================
FILE: README.md
================================================
# DEPRECATED
Please note that this project is no longer maintained.
# Hammock
=========
Hammock is a standalone webapp for running [Slack](https://slack.com) integrations.
This allows you to modify existing integrations, write new custom integrations, or use
certain integrations inside your firewall.
Integrations written for Hammock use the same API as Slack itself, so contributing
new Integrations here will allow them to be added to the main Slack integrations list.
## Requirements
Hammock requires a webserver running a recent version of PHP.
For integrations that require polling, `cron` is also required
(or `at`/`schtasks` on Windows).
## Installation
* Make a clone of this git repository onto your web server
* Copy `lib/config.php.example` to `lib/config.php`
* Open `lib/config.php` in a text editor and follow the instructions inside
* Make sure `data/` is writable by your web server
* Visit `index.php` in your browser and start configuring
## Heroku
You can run Hammock on Heroku using the following commands (you'll need to have installed
the Heroku toolbelt already):
cd hammock
heroku create
heroku config:set BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-php.git#redis
heroku config:set HAMMOCK_ROOT=http://{URL-TO-APP}/
heroku config:set HAMMOCK_CLIENT_ID={YOUR-CLIENT-ID}
heroku config:set HAMMOCK_CLIENT_SECRET={YOUR-CLIENT-SECRET}
heroku addons:add redistogo
git push heroku master
All config options are loaded from the environment variables and data is stored in Redis.
## Adding integrations
To create your own integrations [read the service docs](docs/services.md).
You can also check the [full service reference documentation](docs/services_ref.md).
## Roadmap
This version of Hammock is pretty barebones, designed to support simple webhook-to-Slack
style integrations first. To better support this, we'll be adding a replay-debugger for
capturing incoming webhooks and being able to replay them in a read-only mode while
developing.
Future plugins will be able to provide cross-plugin authentication, so that e.g. a GitHub
integration can auth you against GitHub once and then allow you to add multiple different
integrations for code, issues, gists, etc. and share the credentials. This will be supported
by a different subclass of plugins.
The visual appearance of Hammock somewhat matches the Slack services pages, but this will
be changed to more closely match, have building blocks for commmon UI elements, and switch
the the planned tabbed interface for integration config.
For integrations that require some kind of polling, Hammock will support polling callbacks
and handle some API call diffing behavior automatically. Using this mechanism, an integration
can register a method to be called when the results of an external API call change.
We also plan to support integrations that are triggered from within Slack, via slash commands
and other user-initiated actions.
================================================
FILE: TODO
================================================
* Style config pages to match current slack.com (somewhat done)
* Log all incoming webhooks and what we sent as a result (and allow replays)
* Plugins provide icons & default bot usernames
* Add 'Hammock' as a Slack service for bidi hooks
* Tab the service config pages probably (Summary, Settings, plugin-defined)
* Do the cron stuff
================================================
FILE: add.php
================================================
<?php
$dir = dirname(__FILE__);
include("$dir/lib/init.php");
verify_auth();
load_plugins();
if ($_POST['done']){
$instance = createPluginInstance($_POST['plugin']);
$instance->iid = $_POST['uid'];
$instance->onParentInit();
$instance->onInit();
$instance->icfg['created'] = time();
$instance->icfg['creator_id'] = $GLOBALS['cfg']['user']['user_id'];
$instance->saveConfig();
header("location: view.php?id={$instance->iid}");
exit;
}
$id = $_GET['id'];
if (!isset($plugins[$id])) die("plugin not found");
$instance = createPluginInstance($id);
$instance->createInstanceId();
$instance->checkRequirements();
$smarty->assign('instance', $instance);
$smarty->display('page_add.txt');
================================================
FILE: auth.php
================================================
<?php
$dir = dirname(__FILE__);
include("$dir/lib/init.php");
load_plugins();
$instance = getAuthPlugin($_GET['id']);
if (!is_object($instance)) die("instance not found");
$html = $instance->configPage();
$smarty->assign('html', $html);
$smarty->assign('instance', $instance);
$smarty->display('page_auth.txt');
================================================
FILE: docs/services.md
================================================
# Creating your own integration service
This document describes how to create new Slack integrations. If you're just
looking to install an existing integration, copy the directory into the `plugins/`
directory.
If reading docs isn't your thing, take a look at the `github_commits` for a
simple webhook-to-message example.
The [full reference documentation](services_ref.md) lists everything your plugin
can take advantage of.
## Bare bones
Create a new sub-directory inside `plugins/`. This will be the name of your service
plugin's class, so don't use any dashes (or anything fancy). Inside the directory,
create a file called `plugin.php` and enter some code:
<?php
class my_service extends SlackServicePlugin {
}
This is the simplest service you can build. Load up the index page of your Hammock
install and you should see your new service listed. For now, it doesn't have a name
or description, so we'll fix that first:
class my_service extends SlackServicePlugin {
public $name = "My Awesome Service";
public $desc = "This is what it does, yo";
After that, it should show up correctly in the services list. If you create an
instance of it, you'll find it has "No information" to display. To display any
information, instructions or settings you'll need to start providing some methods:
function onView(){
return "<p>this is my service</p>";
}
Building HTML in code is tedious and fragile, so Hammock includes Smarty for
templating. Create a sub-directory in your plugin called `templates` and then create
`view.txt` inside that:
<p>This is my service!</p>
<p><a href="{$this->getEditUrl()}" class="btn">Edit settings</a></p>
We can then use this template from the PHP class:
function onView(){
return $this->smarty->fetch('view.txt');
}
Each service object has a `$this->smarty` property which contains a pre-configured
Smarty instance.
Service plugins currently provide a 'view' and an 'edit' page. This will likely turn
into a tabbed and combined view/edit page with custom tabs in the future.
## Webhooks
The simplest form of service plugin is to handle incoming webhooks. If you're going
to provide a webhook URL, you should set this config property on your class:
public $cfg = array(
'has_token' => true,
);
This ensures that a randomized token is initialized for the service.
In your view template, present `{$this->getHookUrl()}` to users as the URL to use for
the inbound hook. When the hook is run, the class's `onHook` method will be called,
passing in information about the request:
function onHook($req){
# GET vars : $req['get']
# POST vars : $req['post']
# Raw POST body : $req['post_body']
# HTTP headers : $req['headers']
}
Your code should _only_ use the data passed in `$req` and not use superglobals like
`$_GET` - hook code can be called by the replay-debugger in which case superglobals
will not be present.
Anything returned from the `onHook()` handler will be logged for later debugging, so
returning a simple text status about different conditions encountered can be very
helpful.
Once you've processed the incoming data, you'll probably want to send a message into
Slack. This can be done via the `postToChannel()` method:
function onHook($req){
$this->postToChannel($req['get']['text']);
$this->postToChannel("hello", array(
'channel' => 'C12398612345',
'username' => 'Testbot',
));
}
The first argument is the text to post, while the optional second argument contains
a hash of options.
For a full list of all properties, methods and events, check the
[full reference documentation](services_ref.md).
================================================
FILE: docs/services_ref.md
================================================
# Service Plugin Reference
This documentation lists all of the currently available properties and methods
for custom `SlackServicePlugin` classes. This will be expanded as more are added.
## Properties
There are 6 core properties for services:
$this->id; # class name
$this->iid; # unique instance ID
$this->cfg; # static class config
$this->icfg; # instance config
$this->name; # service name
$this->desc; # service description
You'll never set the `id` and `iid` props, but they are sometimes useful.
The `cfg` hash is used to toggle on certain functionality. The only currently
supported flag is `has_token` which makes sure `icfg->token` is populated and
provides a UI for resetting the token.
The `icfg` hash is where you store instance properties. You'll need to call
`$this->saveConfig();` to save any changes you make here (except in `onInit`).
The `name` and `desc` props should not be changed at run time.
Each plugin is also provided with a Smarty instance at `$this->smarty`. It is
configured to use templates from the `templates` sub-directory of your plugin.
It already hs the plugin instance assigned as `$this`.
Since UI methods expect HTML to be returned rather than output directly, be
sure to use `->fetch()` rather than `->display()`.
## Methods to override
### onInit()
This is called when a new instance of a plugin is created. This is the place to
populate `$this->icfg` with any default values. You _don't_ need to call
`$this->saveConfig();` to save these changes (that happens automatically).
Any `$cfg` based options will have been applied before this method is called,
so (for example) `$icfg->token` will have already been set.
### onView()
Called when a user clicks on an instance of the service. Should return informational
HTML, optionally with a link to the 'edit' view.
### onEdit()
Called for editing the service config.
### onHook($req)
Called when the service's webhook URL is requested, or by the replay-debugger.
### getLabel()
Should return a user-friendly description of the service instance, based on config
information. For example, a service that posts Github commits to a channel might
return a line of text describing the source repo and the target channel (e.g. "Post
commits from Hammock to #hammock").
## Methods to call
### getViewUrl() / getEditUrl() / getHookUrl()
Returns the various URLs for the service instance. Never try and build these yourself.
### dump()
Dump the contents of the service instance as HTML. Use this rather than calling `print_r`
on the object since this method first disconnects the Smarty object to avoid recursive
loops.
### saveConfig()
Make sure that changes to `$this->icfg` are persisted. Your should call this after
modifying the instance config in onView, onEdit or onHook.
### postToChannel($text, $extra)
Send a message to a Slack channel. This method currently expects your messages to be
[properly escaped](https://api.slack.com/docs/formatting), but this will be optional
in the future.
The first argument is the message to post. The second optional array argument can
contain a `channel` to post to and a `username` to post as.
To add [attachments](https://api.slack.com/docs/attachments) to a message, simply
pass an array of attachment hashes as `$extra['attachments']`:
$extra['attachments'] = array(
array(
"text" => "Attachment 1",
"color" => "#ff0000",
),
array(
"text" => "Attachment 2",
"color" => "#0000ff",
),
);
The optional `unfurl_links`, `icon_url` & `icon_emoji` properties match that of the
`chat.postMessage` [API method](https://api.slack.com/methods/chat.postMessage).
### escapeText($str)
Takes any text string and returns one escaped to display as-is in Slack
### escapeLink($url, $label)
Takes a URL and (optionally) a label and makes a valid Slack link.
### getChannelsList()
Returns a hash of `{ID -> Name}` for public channels in your Slack instance. This can
be used to present a list of channels to choose from when configuring an instance.
================================================
FILE: edit.php
================================================
<?php
$dir = dirname(__FILE__);
include("$dir/lib/init.php");
verify_auth();
load_plugins();
$instance = getPluginInstance($_GET['id']);
if (!is_object($instance)) die("instance not found");
$instance->checkRequirements();
$smarty->assign('instance', $instance);
$smarty->assign('html', $instance->onEdit());
$smarty->display('page_edit.txt');
================================================
FILE: hook.php
================================================
<?php
$dir = dirname(__FILE__);
include("$dir/lib/init.php");
#
# build request object
#
$headers = array();
foreach ($_SERVER as $k => $v){
if (substr($k, 0, 5) == 'HTTP_'){
$k = substr($k, 5);
$k = StrToLower($k);
$k = preg_replace_callback('!(^|_)([a-z])!', 'local_replace_header', $k);
$k = str_replace('_', '-', $k);
$headers[$k] = $v;
}
}
function local_replace_header($m){
return $m[1].StrToUpper($m[2]);
}
$req = array(
'headers' => $headers,
'get' => $_GET,
'post' => $_POST,
);
#
# if the body has been posted as something other than 'application/x-www-form-urlencoded'
# or 'multipart/form-data', capture the entire post body as a string
#
if (!count($_POST)){
$body = file_get_contents("php://input");
if (strlen($body)) $req['post_body'] = $body;
}
#
# log to a file (this is temporary)
#
$log = HAMMOCK_ROOT.'/data/hook_'.uniqid().'.log';
$fh = fopen($log, 'w');
fwrite($fh, '<'.'? $req = '.var_export($req, true).';');
fclose($fh);
#
# see if we can find a plugin to handle it
#
load_plugins();
$instance = getPluginInstance($_GET['id']);
if (is_object($instance)){
$ret = $instance->onLiveHook($req);
$out = $instance->getLog();
$uid = uniqid('', true);
$data->set('hooks', $uid, array(
'ts' => time(),
'req' => $req,
'ret' => $ret,
'out' => $out,
));
$list = $data->get('hook_lists', $instance->iid);
$list[] = $uid;
$data->set('hook_lists', $instance->iid, $list);
}
echo "ok\n";
================================================
FILE: index.php
================================================
<?php
$dir = dirname(__FILE__);
include("$dir/lib/init.php");
verify_auth();
load_plugins();
#
# if we have no service instances, redirect to new.php
#
$instance_data = $data->get_all('instances');
if (!count($instance_data)){
header("location: new.php");
exit;
}
#
# get instances and group by service
#
$instance_groups = array();
foreach ($instance_data as $k => $instance){
$inst = getPluginInstance($k);
$inst->icon_48 = $inst->iconUrl(48);
if ($inst->icfg['creator_id']){
$u = $GLOBALS['data']->get('users', $inst->icfg['creator_id']);
$inst->icfg['creator_name'] = $u['user'];
$inst->icfg['creator_url'] = "{$u['url']}team/{$u['user']}";
}
$instance_groups[$inst->id]['plugin'] = $inst;
$instance_groups[$inst->id]['instances'][] = $inst;
}
usort($instance_groups, 'local_sort');
function local_sort($a, $b){
return strcasecmp($a['plugin']->name, $b['plugin']->name);
}
$smarty->assign('instances', $instance_groups);
#
# output
#
$smarty->display('page_index.txt');
================================================
FILE: lib/auth.php
================================================
<?php
class SlackAuthPlugin {
function saveConfig(){
$GLOBALS['data']->set('auth', $this->id, $this->cfg);
}
function isUserAuthed(){
return false;
}
function getConfigUrl(){
return $GLOBALS['cfg']['root_url'] . 'auth.php?id=' . $this->id;
}
}
================================================
FILE: lib/config.php.example
================================================
<?php
$cfg = array();
# This URL should point to your Hammock install.
# It must end in a slash.
$cfg['root_url'] = 'http://myserver.com/hammock/';
# The details of your OAuth application.
# You can create it here: https://api.slack.com/applications
# Make sure to set the OAuth URL to the same as 'root_url' above
$cfg['client_id'] = '123456.7890';
$cfg['client_secret'] = 'abcdefg';
# Where we should store cookies
# NOTE: the domain must contain a dot. if you want to use localhost,
# try `127.0.0.1`, or set up an alias in your /etc/hosts file.
# If running from a subdirectory, make sure to change 'cookie_path'
$cfg['cookie_domain'] = 'myserver.com';
$cfg['cookie_path'] = '/';
$cfg['cookie_name'] = 'hammock-auth';
# Base URL for Slack.
# Leave this as-is unless you're using Slack-in-a-box
$cfg['slack_root'] = "https://slack.com/";
================================================
FILE: lib/config_env.php
================================================
<?php
$cfg = array();
# This ENV var must point to your app's root
$cfg['root_url'] = $_ENV['HAMMOCK_ROOT'];
if (!strlen($cfg['root_url'])) die("No HAMMOCK_ROOT set");
# OAuth config
$cfg['client_id'] = $_ENV['HAMMOCK_CLIENT_ID'];
$cfg['client_secret'] = $_ENV['HAMMOCK_CLIENT_SECRET'];
# Defaults
$url_bits = parse_url($cfg['root_url']);
$cfg['cookie_domain'] = $url_bits['host'];
$cfg['cookie_path'] = $url_bits['path'];
$cfg['cookie_name'] = 'hammock-auth';
$cfg['slack_root'] = "https://slack.com/";
# Heroku specific
if ($_ENV['REDISTOGO_URL']){
$cfg['data_provider'] = 'redis';
$cfg['redis_url'] = $_ENV['REDISTOGO_URL'];
}
# Allow some settings to be overridden
$allow_override = array(
'cookie_domain',
'cookie_path',
'cookie_name',
'slack_root',
);
foreach ($allow_override as $opt){
$opte = 'HAMMOCK_'.strtoupper($opt);
if (isset($_ENV[$opte])) $cfg[$opt] = $_ENV[$opte];
}
================================================
FILE: lib/data.php
================================================
<?php
# this is the abstract class for data storage.
# actual implementations will override it.
class SlackData {
function get($table, $key){
return array();
}
function get_all($table){
return array();
}
function set($table, $key, $value){
return true;
}
function del($table, $key){
return true;
}
function clear($table){
return true;
}
}
================================================
FILE: lib/data_files.php
================================================
<?php
class SlackDataFiles extends SlackData {
private $cache = array();
function get($table, $key){
if (!isset($this->cache[$table])){
$this->cache[$table] = $this->load($table);
}
return $this->cache[$table] ? $this->cache[$table][$key] : null;
}
function get_all($table){
if (!isset($this->cache[$table])){
$this->cache[$table] = $this->load($table);
}
return $this->cache[$table];
}
function set($table, $key, $value){
$this->cache[$table] = $this->load($table);
$this->cache[$table][$key] = $value;
$this->save($table, $this->cache[$table]);
return true;
}
function del($table, $key){
$this->cache[$table] = $this->load($table);
unset($this->cache[$table][$key]);
$this->save($table, $this->cache[$table]);
return true;
}
function clear($table){
$this->cache[$table] = array();
$this->save($table, $this->cache[$table]);
return true;
}
###
private function load($table){
$table_enc = urlencode($table);
$path = HAMMOCK_ROOT."/data/data_{$table_enc}.php";
$data = array();
if (file_exists($path)){
$fh = fopen($path, 'r');
if (!$fh) die("Failed to open data file for reading");
$flag = 0;
$ok = flock($fh, LOCK_SH);
if (!$ok) die("Failed to locl data file for reading");
include($path);
flock($fh, LOCK_UN);
fclose($fh);
if (!is_array($data)) $data = array();
}
return $data;
}
private function save($table, $data){
$table_enc = urlencode($table);
$path = HAMMOCK_ROOT."/data/data_{$table_enc}.php";
$fh = fopen($path, 'c');
if (!$fh) die("Failed to open data file for writing");
$retries = 5;
for ($i=0; $i<$retries; $i++){
$flag = 0;
$ok = flock($fh, LOCK_EX | LOCK_NB, $flag);
if ($ok) break;
if (!$flag) die("Failed to lock data file");
sleep(1);
}
if (!$ok) die("Failed to lock data file");
ftruncate($fh, 0);
fwrite($fh, "<"."?php \$data = ".var_export($data, true).';');
flock($fh, LOCK_UN);
fclose($fh);
}
}
$GLOBALS['data'] = new SlackDataFiles();
================================================
FILE: lib/data_redis.php
================================================
<?php
class SlackDataRedis extends SlackData {
function SlackDataRedis(){
$this->redis = new Redis();
$url = parse_url($GLOBALS['cfg']['redis_url']);
$this->redis->connect($url['host'], $url['port']);
if ($url['pass']) $this->redis->auth($url['pass']);
}
function get($table, $key){
$ret = $this->redis->get("{$table}.{$key}");
return $ret ? json_decode($ret, true) : null;
}
function get_all($table){
$keys = $this->redis->keys("{$table}.*");
$out = array();
$pl = strlen($table)+1;
foreach ($keys as $key){
$rec_key = substr($key, $pl);
$out[$rec_key] = $this->get($table, $rec_key);
}
return $out;
}
function set($table, $key, $value){
$this->redis->set("{$table}.{$key}", json_encode($value));
return true;
}
function del($table, $key){
$this->redis->del("{$table}.{$key}");
return true;
}
function clear($table){
$keys = $this->redis->keys("{$table}.*");
$this->redis->del($keys);
return true;
}
}
$GLOBALS['data'] = new SlackDataRedis();
================================================
FILE: lib/http.php
================================================
<?php
class SlackHTTP {
public static function get($url, $headers=array()){
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => SlackHTTP::prepare_outgoing_headers($headers),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLINFO_HEADER_OUT => true,
CURLOPT_HEADER => true
));
$raw = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
return SlackHTTP::parse_response($raw, $info);
}
public static function post($url, $params=array(), $headers=array()){
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => SlackHTTP::prepare_outgoing_headers($headers),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLINFO_HEADER_OUT => true,
CURLOPT_HEADER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $params
));
$raw = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
return SlackHTTP::parse_response($raw, $info);
}
private static function parse_response($raw, $info){
list($head, $body) = explode("\r\n\r\n", $raw, 2);
list($head_out, $body_out) = explode("\r\n\r\n", $info['request_header'], 2);
unset($info['request_header']);
$headers_in = SlackHTTP::parse_headers($head, '_status');
$headers_out = SlackHTTP::parse_headers($head_out, '_request');
preg_match("/^([A-Z]+)\s/", $headers_out['_request'], $m);
$method = $m[1];
# log_notice("http", "{$method} {$url}", $end-$start);
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2
# http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_Success (note HTTP 207 WTF)
$status = $info['http_code'];
if (($status < 200) || ($status > 299)){
return array(
'ok' => false,
'error' => 'http_failed',
'code' => $info['http_code'],
'method' => $method,
'url' => $info['url'],
'info' => $info,
'req_headers' => $headers_out,
'headers' => $headers_in,
'body' => $body,
);
}
return array(
'ok' => true,
'code' => $info['http_code'],
'method' => $method,
'url' => $info['url'],
'info' => $info,
'req_headers' => $headers_out,
'headers' => $headers_in,
'body' => $body,
);
}
private static function parse_headers($raw, $first){
#
# first, deal with folded lines
#
$raw_lines = explode("\r\n", $raw);
$lines = array();
$lines[] = array_shift($raw_lines);
foreach ($raw_lines as $line){
if (preg_match("!^[ \t]!", $line)){
$lines[count($lines)-1] .= ' '.trim($line);
}else{
$lines[] = trim($line);
}
}
#
# now split them out
#
$out = array(
$first => array_shift($lines),
);
foreach ($lines as $line){
list($k, $v) = explode(':', $line, 2);
$out[StrToLower($k)] = trim($v);
}
return $out;
}
private static function prepare_outgoing_headers($headers=array()){
$prepped = array();
if (!isset($headers['Expect'])){
$headers['Expect'] = ''; # Get around error 417
}
foreach ($headers as $key => $value){
$prepped[] = "{$key}: {$value}";
}
return $prepped;
}
}
================================================
FILE: lib/init.php
================================================
<?php
error_reporting((E_ALL | E_STRICT) ^ E_NOTICE);
define('HAMMOCK_ROOT', realpath(dirname(__FILE__)."/.."));
if ($_ENV['HAMMOCK_ROOT']){
include(HAMMOCK_ROOT."/lib/config_env.php");
}else{
include(HAMMOCK_ROOT."/lib/config.php");
}
include(HAMMOCK_ROOT."/lib/data.php");
if ($cfg['data_provider'] == 'redis'){
include(HAMMOCK_ROOT."/lib/data_redis.php");
}else{
include(HAMMOCK_ROOT."/lib/data_files.php");
}
include(HAMMOCK_ROOT."/lib/http.php");
include(HAMMOCK_ROOT."/lib/service.php");
include(HAMMOCK_ROOT."/lib/auth.php");
include(HAMMOCK_ROOT."/lib/smarty/Smarty.class.php");
if (!file_exists(HAMMOCK_ROOT."/data/templates_c")){
mkdir(HAMMOCK_ROOT."/data/templates_c", 0777, true);
}
$smarty = new Smarty();
$smarty->template_dir = HAMMOCK_ROOT."/templates";
$smarty->compile_dir = HAMMOCK_ROOT."/data/templates_c";
$smarty->assign_by_ref('cfg', $cfg);
function load_plugins(){
$GLOBALS['plugins'] = array();
$dir = HAMMOCK_ROOT."/plugins";
if ($dh = opendir($dir)){
while (($file = readdir($dh)) !== false){
if (is_dir("{$dir}/{$file}") && is_file("{$dir}/{$file}/plugin.php")){
if ((include("{$dir}/{$file}/plugin.php"))){
$GLOBALS['plugins'][$file] = 1;
}
}
}
closedir($dh);
}
$GLOBALS['plugins_services'] = array();
$GLOBALS['plugins_auth' ] = array();
foreach ($GLOBALS['plugins'] as $k => $v){
if (is_subclass_of($k, 'SlackServicePlugin')) $GLOBALS['plugins_services'][$k] = 1;
if (is_subclass_of($k, 'SlackAuthPlugin' )) $GLOBALS['plugins_auth' ][$k] = 1;
}
}
function createPluginInstance($class_name){
$obj = new $class_name();
$obj->id = $class_name;
$obj->smarty = new Smarty();
$obj->smarty->compile_id = "plugins|{$class_name}";
$obj->smarty->template_dir = HAMMOCK_ROOT."/plugins/{$class_name}/templates";
$obj->smarty->compile_dir = HAMMOCK_ROOT."/data/templates_c";
$obj->smarty->assign_by_ref('this', $obj);
return $obj;
}
function getPluginInstance($iid){
$icfg = $GLOBALS['data']->get('instances', $iid);
if (!isset($icfg)) return null;
$plugin = $icfg['plugin'];
unset($icfg['plugin']);
$instance = createPluginInstance($plugin);
$instance->setInstanceConfig($iid, $icfg);
return $instance;
}
function getAuthPlugin($id){
if (!isset($GLOBALS['plugins_auth'][$id])) return null;
$instance = createPluginInstance($id);
$cfg = $GLOBALS['data']->get('auth', $id);
$instance->cfg = $cfg ? $cfg : array();
return $instance;
}
function dumper($foo){
echo "<pre style=\"text-align: left;\">";
if (is_resource($foo)){
var_dump($foo);
}else{
echo HtmlSpecialChars(var_export($foo, 1));
}
echo "</pre>\n";
}
function api_call($method, $args = array()){
$team = $GLOBALS['data']->get('metadata', 'team');
$url = $GLOBALS['cfg']['slack_root']."api/".$method."?token=".$team['token'];
foreach ($args as $k => $v) $url .= '&'.urlencode($k).'='.urlencode($v);
$ret = SlackHTTP::get($url);
if ($ret['ok'] && $ret['code'] == '200'){
return array(
'ok' => true,
'data' => json_decode($ret['body'], true),
);
}
return $ret;
}
function api_channels_list(){
$ret = api_call('channels.list');
$channels = array();
foreach ($ret['data']['channels'] as $row){
if (!$row['is_archived']) $channels[$row['id']] = '#'.$row['name'];
}
return $channels;
}
function verify_auth(){
$v = $_COOKIE[$GLOBALS['cfg']['cookie_name']];
if ($v){
list($id, $secret) = explode('-', $v);
$u = $GLOBALS['data']->get('users', $id);
if (is_array($u) && $u['secret'] == $secret){
$GLOBALS['cfg']['user'] = $u;
return;
}
}
$oauth_url = $GLOBALS['cfg']['slack_root']."oauth/authorize";
$oauth_url .= "?client_id=".$GLOBALS['cfg']['client_id'];
$oauth_url .= "&redirect_uri={$GLOBALS['cfg']['root_url']}oauth.php";
$team = $GLOBALS['data']->get('metadata', 'team');
if ($team['id']){
$oauth_url .= "&team={$team['id']}";
}else{
$GLOBALS['smarty']->assign('first_time', 1);
}
if (!strpos($GLOBALS['cfg']['cookie_domain'], '.')){
$GLOBALS['smarty']->assign('bad_cookie_domain', 1);
}
$GLOBALS['smarty']->assign('oauth_url', $oauth_url);
$GLOBALS['smarty']->display('page_login.txt');
exit;
}
function split_sets($in, $size){
$out = array();
while (count($in)){
$out[] = array_slice($in, 0, $size);
$in = array_slice($in, $size);
}
return $out;
}
================================================
FILE: lib/service.php
================================================
<?php
class SlackServicePlugin {
public $name = "NO NAME";
public $desc = "NO DESC";
public $id; # class ID
public $iid; # instance ID
public $cfg; # class config
public $icfg; # instance config
private $log = array();
function SlackServicePlugin(){
if ($this->name == "NO NAME"){
$cn = get_class($this);
$this->name = "Unnamed ({$cn})";
}
}
function createInstanceId(){
$this->iid = uniqid();
}
function setInstanceConfig($iid, $icfg){
$this->iid = $iid;
$this->icfg = $icfg;
}
function checkRequirements(){
if ($this->cfg['requires_auth']){
$auth_plugin = $this->cfg['requires_auth'];
$auth = getAuthPlugin($auth_plugin);
if (!$auth->isConfigured()) die("This plugin requires auth be configured - {$auth_plugin}");
if (!$auth->isUserAuthed()) die("You need to authenticate before continuing");
}
}
function getHookUrl(){
$url = $GLOBALS['cfg']['root_url'] . 'hook.php?id=' . $this->iid;
if ($this->cfg['has_token']) $url .= "&token={$this->icfg['token']}";
return $url;
}
function getEditUrl(){
return $GLOBALS['cfg']['root_url'] . 'edit.php?id=' . $this->iid;
}
function getViewUrl(){
return $GLOBALS['cfg']['root_url'] . 'view.php?id=' . $this->iid;
}
function dump(){
$s = $this->smarty;
unset($this->smarty);
dumper($this);
$this->smarty = $s;
}
function saveConfig(){
$cfg = $this->icfg;
$cfg['plugin'] = $this->id;
$GLOBALS['data']->set('instances', $this->iid, $cfg);
}
function deleteMe(){
$cfg = $GLOBALS['data']->get('instances', $this->iid);
$GLOBALS['data']->set('deleted_instances', $this->iid, $cfg);
$GLOBALS['data']->del('instances', $this->iid);
}
function postToChannel($text, $extra){
$this->log[] = array(
'type' => 'message_post',
'text' => $text,
'extra' => $extra,
);
$params = array(
'text' => $text,
'parse' => 'none',
'channel' => '#general',
'icon_url' => $this->iconUrl(48, true),
);
$map_params = array(
'channel',
'username',
'attachments',
'unfurl_links',
'icon_url',
'icon_emoji',
);
foreach ($map_params as $p){
if (isset($extra[$p])){
if ($p == 'attachments'){
$params[$p] = json_encode($extra[$p]);
}else{
$params[$p] = $extra[$p];
}
}
}
$ret = api_call('chat.postMessage', $params);
return $ret;
}
function getLog(){
return $this->log;
}
function escapeText($str){
return HtmlSpecialChars($str, ENT_NOQUOTES);
}
function escapeLink($url, $label=null){
$url = trim($url);
$url = $this->escapeText($url);
$url = str_replace('|', '%7C', $url);
if (strlen($label)){
$label = $this->escapeText($label);
return "<{$url}|{$label}>";
}
return "<{$url}>";
}
function onParentInit(){
if ($this->cfg['has_token']){
$this->regenToken();
}
}
function regenToken(){
$this->icfg['token'] = substr(sha1(rand()), 1, 10);
}
function getChannelsList(){
return api_channels_list();
}
function onLiveHook($req){
if ($this->cfg['has_token']){
if ($req['get']['token'] != $this->icfg['token']){
return array(
'ok' => false,
'error' => 'bad_token',
'sent' => $req['get']['token'],
'expected' => $this->icfg['token'],
);
}
}
return $this->onHook($req);
}
# things to override
function onView(){
return "<p>No information for this plugin.</p>";
}
function onEdit(){
return "<p>No config for this plugin.</p>";
}
function getLabel(){
return "No label ({$this->iid})";
}
function onInit(){
# set default options in $this->icfg here
}
function onHook($request){
# handle an incoming hook here
return array(
'ok' => false,
'error' => 'onHook not implemented',
);
}
function iconUrl($size=32, $abs=false){
if (!in_array($size, array(32,48,64,128))) $size = 32;
$pre = $abs ? $GLOBALS['cfg']['root_url'] : '';
return "{$pre}plugins/{$this->id}/icon_{$size}.png";
}
}
================================================
FILE: lib/smarty/Config_File.class.php
================================================
<?php
/**
* Config_File class.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* For questions, help, comments, discussion, etc., please join the
* Smarty mailing list. Send a blank e-mail to
* smarty-discussion-subscribe@googlegroups.com
*
* @link http://www.smarty.net/
* @version 2.6.25-dev
* @copyright Copyright: 2001-2005 New Digital Group, Inc.
* @author Andrei Zmievski <andrei@php.net>
* @access public
* @package Smarty
*/
/* $Id: Config_File.class.php 3149 2009-05-23 20:59:25Z monte.ohrt $ */
/**
* Config file reading class
* @package Smarty
*/
class Config_File {
/**#@+
* Options
* @var boolean
*/
/**
* Controls whether variables with the same name overwrite each other.
*/
var $overwrite = true;
/**
* Controls whether config values of on/true/yes and off/false/no get
* converted to boolean values automatically.
*/
var $booleanize = true;
/**
* Controls whether hidden config sections/vars are read from the file.
*/
var $read_hidden = true;
/**
* Controls whether or not to fix mac or dos formatted newlines.
* If set to true, \r or \r\n will be changed to \n.
*/
var $fix_newlines = true;
/**#@-*/
/** @access private */
var $_config_path = "";
var $_config_data = array();
/**#@-*/
/**
* Constructs a new config file class.
*
* @param string $config_path (optional) path to the config files
*/
function Config_File($config_path = NULL)
{
if (isset($config_path))
$this->set_path($config_path);
}
/**
* Set the path where configuration files can be found.
*
* @param string $config_path path to the config files
*/
function set_path($config_path)
{
if (!empty($config_path)) {
if (!is_string($config_path) || !file_exists($config_path) || !is_dir($config_path)) {
$this->_trigger_error_msg("Bad config file path '$config_path'");
return;
}
if(substr($config_path, -1) != DIRECTORY_SEPARATOR) {
$config_path .= DIRECTORY_SEPARATOR;
}
$this->_config_path = $config_path;
}
}
/**
* Retrieves config info based on the file, section, and variable name.
*
* @param string $file_name config file to get info for
* @param string $section_name (optional) section to get info for
* @param string $var_name (optional) variable to get info for
* @return string|array a value or array of values
*/
function get($file_name, $section_name = NULL, $var_name = NULL)
{
if (empty($file_name)) {
$this->_trigger_error_msg('Empty config file name');
return;
} else {
$file_name = $this->_config_path . $file_name;
if (!isset($this->_config_data[$file_name]))
$this->load_file($file_name, false);
}
if (!empty($var_name)) {
if (empty($section_name)) {
return $this->_config_data[$file_name]["vars"][$var_name];
} else {
if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name]))
return $this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name];
else
return array();
}
} else {
if (empty($section_name)) {
return (array)$this->_config_data[$file_name]["vars"];
} else {
if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"]))
return (array)$this->_config_data[$file_name]["sections"][$section_name]["vars"];
else
return array();
}
}
}
/**
* Retrieves config info based on the key.
*
* @param $file_name string config key (filename/section/var)
* @return string|array same as get()
* @uses get() retrieves information from config file and returns it
*/
function &get_key($config_key)
{
list($file_name, $section_name, $var_name) = explode('/', $config_key, 3);
$result = &$this->get($file_name, $section_name, $var_name);
return $result;
}
/**
* Get all loaded config file names.
*
* @return array an array of loaded config file names
*/
function get_file_names()
{
return array_keys($this->_config_data);
}
/**
* Get all section names from a loaded file.
*
* @param string $file_name config file to get section names from
* @return array an array of section names from the specified file
*/
function get_section_names($file_name)
{
$file_name = $this->_config_path . $file_name;
if (!isset($this->_config_data[$file_name])) {
$this->_trigger_error_msg("Unknown config file '$file_name'");
return;
}
return array_keys($this->_config_data[$file_name]["sections"]);
}
/**
* Get all global or section variable names.
*
* @param string $file_name config file to get info for
* @param string $section_name (optional) section to get info for
* @return array an array of variables names from the specified file/section
*/
function get_var_names($file_name, $section = NULL)
{
if (empty($file_name)) {
$this->_trigger_error_msg('Empty config file name');
return;
} else if (!isset($this->_config_data[$file_name])) {
$this->_trigger_error_msg("Unknown config file '$file_name'");
return;
}
if (empty($section))
return array_keys($this->_config_data[$file_name]["vars"]);
else
return array_keys($this->_config_data[$file_name]["sections"][$section]["vars"]);
}
/**
* Clear loaded config data for a certain file or all files.
*
* @param string $file_name file to clear config data for
*/
function clear($file_name = NULL)
{
if ($file_name === NULL)
$this->_config_data = array();
else if (isset($this->_config_data[$file_name]))
$this->_config_data[$file_name] = array();
}
/**
* Load a configuration file manually.
*
* @param string $file_name file name to load
* @param boolean $prepend_path whether current config path should be
* prepended to the filename
*/
function load_file($file_name, $prepend_path = true)
{
if ($prepend_path && $this->_config_path != "")
$config_file = $this->_config_path . $file_name;
else
$config_file = $file_name;
ini_set('track_errors', true);
$fp = @fopen($config_file, "r");
if (!is_resource($fp)) {
$this->_trigger_error_msg("Could not open config file '$config_file'");
return false;
}
$contents = ($size = filesize($config_file)) ? fread($fp, $size) : '';
fclose($fp);
$this->_config_data[$config_file] = $this->parse_contents($contents);
return true;
}
/**
* Store the contents of a file manually.
*
* @param string $config_file file name of the related contents
* @param string $contents the file-contents to parse
*/
function set_file_contents($config_file, $contents)
{
$this->_config_data[$config_file] = $this->parse_contents($contents);
return true;
}
/**
* parse the source of a configuration file manually.
*
* @param string $contents the file-contents to parse
*/
function parse_contents($contents)
{
if($this->fix_newlines) {
// fix mac/dos formatted newlines
$contents = preg_replace('!\r\n?!', "\n", $contents);
}
$config_data = array();
$config_data['sections'] = array();
$config_data['vars'] = array();
/* reference to fill with data */
$vars =& $config_data['vars'];
/* parse file line by line */
preg_match_all('!^.*\r?\n?!m', $contents, $match);
$lines = $match[0];
for ($i=0, $count=count($lines); $i<$count; $i++) {
$line = $lines[$i];
if (empty($line)) continue;
if ( substr($line, 0, 1) == '[' && preg_match('!^\[(.*?)\]!', $line, $match) ) {
/* section found */
if (substr($match[1], 0, 1) == '.') {
/* hidden section */
if ($this->read_hidden) {
$section_name = substr($match[1], 1);
} else {
/* break reference to $vars to ignore hidden section */
unset($vars);
$vars = array();
continue;
}
} else {
$section_name = $match[1];
}
if (!isset($config_data['sections'][$section_name]))
$config_data['sections'][$section_name] = array('vars' => array());
$vars =& $config_data['sections'][$section_name]['vars'];
continue;
}
if (preg_match('/^\s*(\.?\w+)\s*=\s*(.*)/s', $line, $match)) {
/* variable found */
$var_name = rtrim($match[1]);
if (strpos($match[2], '"""') === 0) {
/* handle multiline-value */
$lines[$i] = substr($match[2], 3);
$var_value = '';
while ($i<$count) {
if (($pos = strpos($lines[$i], '"""')) === false) {
$var_value .= $lines[$i++];
} else {
/* end of multiline-value */
$var_value .= substr($lines[$i], 0, $pos);
break;
}
}
$booleanize = false;
} else {
/* handle simple value */
$var_value = preg_replace('/^([\'"])(.*)\1$/', '\2', rtrim($match[2]));
$booleanize = $this->booleanize;
}
$this->_set_config_var($vars, $var_name, $var_value, $booleanize);
}
/* else unparsable line / means it is a comment / means ignore it */
}
return $config_data;
}
/**#@+ @access private */
/**
* @param array &$container
* @param string $var_name
* @param mixed $var_value
* @param boolean $booleanize determines whether $var_value is converted to
* to true/false
*/
function _set_config_var(&$container, $var_name, $var_value, $booleanize)
{
if (substr($var_name, 0, 1) == '.') {
if (!$this->read_hidden)
return;
else
$var_name = substr($var_name, 1);
}
if (!preg_match("/^[a-zA-Z_]\w*$/", $var_name)) {
$this->_trigger_error_msg("Bad variable name '$var_name'");
return;
}
if ($booleanize) {
if (preg_match("/^(on|true|yes)$/i", $var_value))
$var_value = true;
else if (preg_match("/^(off|false|no)$/i", $var_value))
$var_value = false;
}
if (!isset($container[$var_name]) || $this->overwrite)
$container[$var_name] = $var_value;
else {
settype($container[$var_name], 'array');
$container[$var_name][] = $var_value;
}
}
/**
* @uses trigger_error() creates a PHP warning/error
* @param string $error_msg
* @param integer $error_type one of
*/
function _trigger_error_msg($error_msg, $error_type = E_USER_WARNING)
{
trigger_error("Config_File error: $error_msg", $error_type);
}
/**#@-*/
}
?>
================================================
FILE: lib/smarty/Smarty.class.php
================================================
<?php
/**
* Project: Smarty: the PHP compiling template engine
* File: Smarty.class.php
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* For questions, help, comments, discussion, etc., please join the
* Smarty mailing list. Send a blank e-mail to
* smarty-discussion-subscribe@googlegroups.com
*
* @link http://www.smarty.net/
* @copyright 2001-2005 New Digital Group, Inc.
* @author Monte Ohrt <monte at ohrt dot com>
* @author Andrei Zmievski <andrei@php.net>
* @package Smarty
* @version 2.6.28
*/
/* $Id: Smarty.class.php 4660 2012-09-24 20:05:15Z uwe.tews@googlemail.com $ */
/**
* DIR_SEP isn't used anymore, but third party apps might
*/
if(!defined('DIR_SEP')) {
define('DIR_SEP', DIRECTORY_SEPARATOR);
}
/**
* set SMARTY_DIR to absolute path to Smarty library files.
* if not defined, include_path will be used. Sets SMARTY_DIR only if user
* application has not already defined it.
*/
if (!defined('SMARTY_DIR')) {
define('SMARTY_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR);
}
if (!defined('SMARTY_CORE_DIR')) {
define('SMARTY_CORE_DIR', SMARTY_DIR . 'internals' . DIRECTORY_SEPARATOR);
}
define('SMARTY_PHP_PASSTHRU', 0);
define('SMARTY_PHP_QUOTE', 1);
define('SMARTY_PHP_REMOVE', 2);
define('SMARTY_PHP_ALLOW', 3);
/**
* @package Smarty
*/
class Smarty
{
/**#@+
* Smarty Configuration Section
*/
/**
* The name of the directory where templates are located.
*
* @var string
*/
var $template_dir = 'templates';
/**
* The directory where compiled templates are located.
*
* @var string
*/
var $compile_dir = 'templates_c';
/**
* The directory where config files are located.
*
* @var string
*/
var $config_dir = 'configs';
/**
* An array of directories searched for plugins.
*
* @var array
*/
var $plugins_dir = array('plugins');
/**
* If debugging is enabled, a debug console window will display
* when the page loads (make sure your browser allows unrequested
* popup windows)
*
* @var boolean
*/
var $debugging = false;
/**
* When set, smarty does uses this value as error_reporting-level.
*
* @var integer
*/
var $error_reporting = null;
/**
* This is the path to the debug console template. If not set,
* the default one will be used.
*
* @var string
*/
var $debug_tpl = '';
/**
* This determines if debugging is enable-able from the browser.
* <ul>
* <li>NONE => no debugging control allowed</li>
* <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
* </ul>
* @link http://www.foo.dom/index.php?SMARTY_DEBUG
* @var string
*/
var $debugging_ctrl = 'NONE';
/**
* This tells Smarty whether to check for recompiling or not. Recompiling
* does not need to happen unless a template or config file is changed.
* Typically you enable this during development, and disable for
* production.
*
* @var boolean
*/
var $compile_check = true;
/**
* This forces templates to compile every time. Useful for development
* or debugging.
*
* @var boolean
*/
var $force_compile = false;
/**
* This enables template caching.
* <ul>
* <li>0 = no caching</li>
* <li>1 = use class cache_lifetime value</li>
* <li>2 = use cache_lifetime in cache file</li>
* </ul>
* @var integer
*/
var $caching = 0;
/**
* The name of the directory for cache files.
*
* @var string
*/
var $cache_dir = 'cache';
/**
* This is the number of seconds cached content will persist.
* <ul>
* <li>0 = always regenerate cache</li>
* <li>-1 = never expires</li>
* </ul>
*
* @var integer
*/
var $cache_lifetime = 3600;
/**
* Only used when $caching is enabled. If true, then If-Modified-Since headers
* are respected with cached content, and appropriate HTTP headers are sent.
* This way repeated hits to a cached page do not send the entire page to the
* client every time.
*
* @var boolean
*/
var $cache_modified_check = false;
/**
* This determines how Smarty handles "<?php ... ?>" tags in templates.
* possible values:
* <ul>
* <li>SMARTY_PHP_PASSTHRU -> print tags as plain text</li>
* <li>SMARTY_PHP_QUOTE -> escape tags as entities</li>
* <li>SMARTY_PHP_REMOVE -> remove php tags</li>
* <li>SMARTY_PHP_ALLOW -> execute php tags</li>
* </ul>
*
* @var integer
*/
var $php_handling = SMARTY_PHP_PASSTHRU;
/**
* This enables template security. When enabled, many things are restricted
* in the templates that normally would go unchecked. This is useful when
* untrusted parties are editing templates and you want a reasonable level
* of security. (no direct execution of PHP in templates for example)
*
* @var boolean
*/
var $security = false;
/**
* This is the list of template directories that are considered secure. This
* is used only if {@link $security} is enabled. One directory per array
* element. {@link $template_dir} is in this list implicitly.
*
* @var array
*/
var $secure_dir = array();
/**
* These are the security settings for Smarty. They are used only when
* {@link $security} is enabled.
*
* @var array
*/
var $security_settings = array(
'PHP_HANDLING' => false,
'IF_FUNCS' => array('array', 'list',
'isset', 'empty',
'count', 'sizeof',
'in_array', 'is_array',
'true', 'false', 'null'),
'INCLUDE_ANY' => false,
'PHP_TAGS' => false,
'MODIFIER_FUNCS' => array('count'),
'ALLOW_CONSTANTS' => false,
'ALLOW_SUPER_GLOBALS' => true
);
/**
* This is an array of directories where trusted php scripts reside.
* {@link $security} is disabled during their inclusion/execution.
*
* @var array
*/
var $trusted_dir = array();
/**
* The left delimiter used for the template tags.
*
* @var string
*/
var $left_delimiter = '{';
/**
* The right delimiter used for the template tags.
*
* @var string
*/
var $right_delimiter = '}';
/**
* The order in which request variables are registered, similar to
* variables_order in php.ini E = Environment, G = GET, P = POST,
* C = Cookies, S = Server
*
* @var string
*/
var $request_vars_order = 'EGPCS';
/**
* Indicates wether $HTTP_*_VARS[] (request_use_auto_globals=false)
* are uses as request-vars or $_*[]-vars. note: if
* request_use_auto_globals is true, then $request_vars_order has
* no effect, but the php-ini-value "gpc_order"
*
* @var boolean
*/
var $request_use_auto_globals = true;
/**
* Set this if you want different sets of compiled files for the same
* templates. This is useful for things like different languages.
* Instead of creating separate sets of templates per language, you
* set different compile_ids like 'en' and 'de'.
*
* @var string
*/
var $compile_id = null;
/**
* This tells Smarty whether or not to use sub dirs in the cache/ and
* templates_c/ directories. sub directories better organized, but
* may not work well with PHP safe mode enabled.
*
* @var boolean
*
*/
var $use_sub_dirs = false;
/**
* This is a list of the modifiers to apply to all template variables.
* Put each modifier in a separate array element in the order you want
* them applied. example: <code>array('escape:"htmlall"');</code>
*
* @var array
*/
var $default_modifiers = array();
/**
* This is the resource type to be used when not specified
* at the beginning of the resource path. examples:
* $smarty->display('file:index.tpl');
* $smarty->display('db:index.tpl');
* $smarty->display('index.tpl'); // will use default resource type
* {include file="file:index.tpl"}
* {include file="db:index.tpl"}
* {include file="index.tpl"} {* will use default resource type *}
*
* @var array
*/
var $default_resource_type = 'file';
/**
* The function used for cache file handling. If not set, built-in caching is used.
*
* @var null|string function name
*/
var $cache_handler_func = null;
/**
* This indicates which filters are automatically loaded into Smarty.
*
* @var array array of filter names
*/
var $autoload_filters = array();
/**#@+
* @var boolean
*/
/**
* This tells if config file vars of the same name overwrite each other or not.
* if disabled, same name variables are accumulated in an array.
*/
var $config_overwrite = true;
/**
* This tells whether or not to automatically booleanize config file variables.
* If enabled, then the strings "on", "true", and "yes" are treated as boolean
* true, and "off", "false" and "no" are treated as boolean false.
*/
var $config_booleanize = true;
/**
* This tells whether hidden sections [.foobar] are readable from the
* tempalates or not. Normally you would never allow this since that is
* the point behind hidden sections: the application can access them, but
* the templates cannot.
*/
var $config_read_hidden = false;
/**
* This tells whether or not automatically fix newlines in config files.
* It basically converts \r (mac) or \r\n (dos) to \n
*/
var $config_fix_newlines = true;
/**#@-*/
/**
* If a template cannot be found, this PHP function will be executed.
* Useful for creating templates on-the-fly or other special action.
*
* @var string function name
*/
var $default_template_handler_func = '';
/**
* The file that contains the compiler class. This can a full
* pathname, or relative to the php_include path.
*
* @var string
*/
var $compiler_file = 'Smarty_Compiler.class.php';
/**
* The class used for compiling templates.
*
* @var string
*/
var $compiler_class = 'Smarty_Compiler';
/**
* The class used to load config vars.
*
* @var string
*/
var $config_class = 'Config_File';
/**#@+
* END Smarty Configuration Section
* There should be no need to touch anything below this line.
* @access private
*/
/**
* where assigned template vars are kept
*
* @var array
*/
var $_tpl_vars = array();
/**
* stores run-time $smarty.* vars
*
* @var null|array
*/
var $_smarty_vars = null;
/**
* keeps track of sections
*
* @var array
*/
var $_sections = array();
/**
* keeps track of foreach blocks
*
* @var array
*/
var $_foreach = array();
/**
* keeps track of tag hierarchy
*
* @var array
*/
var $_tag_stack = array();
/**
* configuration object
*
* @var Config_file
*/
var $_conf_obj = null;
/**
* loaded configuration settings
*
* @var array
*/
var $_config = array(array('vars' => array(), 'files' => array()));
/**
* md5 checksum of the string 'Smarty'
*
* @var string
*/
var $_smarty_md5 = 'f8d698aea36fcbead2b9d5359ffca76f';
/**
* Smarty version number
*
* @var string
*/
var $_version = '2.6.28';
/**
* current template inclusion depth
*
* @var integer
*/
var $_inclusion_depth = 0;
/**
* for different compiled templates
*
* @var string
*/
var $_compile_id = null;
/**
* text in URL to enable debug mode
*
* @var string
*/
var $_smarty_debug_id = 'SMARTY_DEBUG';
/**
* debugging information for debug console
*
* @var array
*/
var $_smarty_debug_info = array();
/**
* info that makes up a cache file
*
* @var array
*/
var $_cache_info = array();
/**
* default file permissions
*
* @var integer
*/
var $_file_perms = 0644;
/**
* default dir permissions
*
* @var integer
*/
var $_dir_perms = 0771;
/**
* registered objects
*
* @var array
*/
var $_reg_objects = array();
/**
* table keeping track of plugins
*
* @var array
*/
var $_plugins = array(
'modifier' => array(),
'function' => array(),
'block' => array(),
'compiler' => array(),
'prefilter' => array(),
'postfilter' => array(),
'outputfilter' => array(),
'resource' => array(),
'insert' => array());
/**
* cache serials
*
* @var array
*/
var $_cache_serials = array();
/**
* name of optional cache include file
*
* @var string
*/
var $_cache_include = null;
/**
* indicate if the current code is used in a compiled
* include
*
* @var string
*/
var $_cache_including = false;
/**#@-*/
/**
* The class constructor.
*/
function Smarty()
{
$this->assign('SCRIPT_NAME', isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME']
: @$GLOBALS['HTTP_SERVER_VARS']['SCRIPT_NAME']);
}
/**
* assigns values to template variables
*
* @param array|string $tpl_var the template variable name(s)
* @param mixed $value the value to assign
*/
function assign($tpl_var, $value = null)
{
if (is_array($tpl_var)){
foreach ($tpl_var as $key => $val) {
if ($key != '') {
$this->_tpl_vars[$key] = $val;
}
}
} else {
if ($tpl_var != '')
$this->_tpl_vars[$tpl_var] = $value;
}
}
/**
* assigns values to template variables by reference
*
* @param string $tpl_var the template variable name
* @param mixed $value the referenced value to assign
*/
function assign_by_ref($tpl_var, &$value)
{
if ($tpl_var != '')
$this->_tpl_vars[$tpl_var] = &$value;
}
/**
* appends values to template variables
*
* @param array|string $tpl_var the template variable name(s)
* @param mixed $value the value to append
*/
function append($tpl_var, $value=null, $merge=false)
{
if (is_array($tpl_var)) {
// $tpl_var is an array, ignore $value
foreach ($tpl_var as $_key => $_val) {
if ($_key != '') {
if(!@is_array($this->_tpl_vars[$_key])) {
settype($this->_tpl_vars[$_key],'array');
}
if($merge && is_array($_val)) {
foreach($_val as $_mkey => $_mval) {
$this->_tpl_vars[$_key][$_mkey] = $_mval;
}
} else {
$this->_tpl_vars[$_key][] = $_val;
}
}
}
} else {
if ($tpl_var != '' && isset($value)) {
if(!@is_array($this->_tpl_vars[$tpl_var])) {
settype($this->_tpl_vars[$tpl_var],'array');
}
if($merge && is_array($value)) {
foreach($value as $_mkey => $_mval) {
$this->_tpl_vars[$tpl_var][$_mkey] = $_mval;
}
} else {
$this->_tpl_vars[$tpl_var][] = $value;
}
}
}
}
/**
* appends values to template variables by reference
*
* @param string $tpl_var the template variable name
* @param mixed $value the referenced value to append
*/
function append_by_ref($tpl_var, &$value, $merge=false)
{
if ($tpl_var != '' && isset($value)) {
if(!@is_array($this->_tpl_vars[$tpl_var])) {
settype($this->_tpl_vars[$tpl_var],'array');
}
if ($merge && is_array($value)) {
foreach($value as $_key => $_val) {
$this->_tpl_vars[$tpl_var][$_key] = &$value[$_key];
}
} else {
$this->_tpl_vars[$tpl_var][] = &$value;
}
}
}
/**
* clear the given assigned template variable.
*
* @param string $tpl_var the template variable to clear
*/
function clear_assign($tpl_var)
{
if (is_array($tpl_var))
foreach ($tpl_var as $curr_var)
unset($this->_tpl_vars[$curr_var]);
else
unset($this->_tpl_vars[$tpl_var]);
}
/**
* Registers custom function to be used in templates
*
* @param string $function the name of the template function
* @param string $function_impl the name of the PHP function to register
*/
function register_function($function, $function_impl, $cacheable=true, $cache_attrs=null)
{
$this->_plugins['function'][$function] =
array($function_impl, null, null, false, $cacheable, $cache_attrs);
}
/**
* Unregisters custom function
*
* @param string $function name of template function
*/
function unregister_function($function)
{
unset($this->_plugins['function'][$function]);
}
/**
* Registers object to be used in templates
*
* @param string $object name of template object
* @param object &$object_impl the referenced PHP object to register
* @param null|array $allowed list of allowed methods (empty = all)
* @param boolean $smarty_args smarty argument format, else traditional
* @param null|array $block_functs list of methods that are block format
*/
function register_object($object, &$object_impl, $allowed = array(), $smarty_args = true, $block_methods = array())
{
settype($allowed, 'array');
settype($smarty_args, 'boolean');
$this->_reg_objects[$object] =
array(&$object_impl, $allowed, $smarty_args, $block_methods);
}
/**
* Unregisters object
*
* @param string $object name of template object
*/
function unregister_object($object)
{
unset($this->_reg_objects[$object]);
}
/**
* Registers block function to be used in templates
*
* @param string $block name of template block
* @param string $block_impl PHP function to register
*/
function register_block($block, $block_impl, $cacheable=true, $cache_attrs=null)
{
$this->_plugins['block'][$block] =
array($block_impl, null, null, false, $cacheable, $cache_attrs);
}
/**
* Unregisters block function
*
* @param string $block name of template function
*/
function unregister_block($block)
{
unset($this->_plugins['block'][$block]);
}
/**
* Registers compiler function
*
* @param string $function name of template function
* @param string $function_impl name of PHP function to register
*/
function register_compiler_function($function, $function_impl, $cacheable=true)
{
$this->_plugins['compiler'][$function] =
array($function_impl, null, null, false, $cacheable);
}
/**
* Unregisters compiler function
*
* @param string $function name of template function
*/
function unregister_compiler_function($function)
{
unset($this->_plugins['compiler'][$function]);
}
/**
* Registers modifier to be used in templates
*
* @param string $modifier name of template modifier
* @param string $modifier_impl name of PHP function to register
*/
function register_modifier($modifier, $modifier_impl)
{
$this->_plugins['modifier'][$modifier] =
array($modifier_impl, null, null, false);
}
/**
* Unregisters modifier
*
* @param string $modifier name of template modifier
*/
function unregister_modifier($modifier)
{
unset($this->_plugins['modifier'][$modifier]);
}
/**
* Registers a resource to fetch a template
*
* @param string $type name of resource
* @param array $functions array of functions to handle resource
*/
function register_resource($type, $functions)
{
if (count($functions)==4) {
$this->_plugins['resource'][$type] =
array($functions, false);
} elseif (count($functions)==5) {
$this->_plugins['resource'][$type] =
array(array(array(&$functions[0], $functions[1])
,array(&$functions[0], $functions[2])
,array(&$functions[0], $functions[3])
,array(&$functions[0], $functions[4]))
,false);
} else {
$this->trigger_error("malformed function-list for '$type' in register_resource");
}
}
/**
* Unregisters a resource
*
* @param string $type name of resource
*/
function unregister_resource($type)
{
unset($this->_plugins['resource'][$type]);
}
/**
* Registers a prefilter function to apply
* to a template before compiling
*
* @param callback $function
*/
function register_prefilter($function)
{
$this->_plugins['prefilter'][$this->_get_filter_name($function)]
= array($function, null, null, false);
}
/**
* Unregisters a prefilter function
*
* @param callback $function
*/
function unregister_prefilter($function)
{
unset($this->_plugins['prefilter'][$this->_get_filter_name($function)]);
}
/**
* Registers a postfilter function to apply
* to a compiled template after compilation
*
* @param callback $function
*/
function register_postfilter($function)
{
$this->_plugins['postfilter'][$this->_get_filter_name($function)]
= array($function, null, null, false);
}
/**
* Unregisters a postfilter function
*
* @param callback $function
*/
function unregister_postfilter($function)
{
unset($this->_plugins['postfilter'][$this->_get_filter_name($function)]);
}
/**
* Registers an output filter function to apply
* to a template output
*
* @param callback $function
*/
function register_outputfilter($function)
{
$this->_plugins['outputfilter'][$this->_get_filter_name($function)]
= array($function, null, null, false);
}
/**
* Unregisters an outputfilter function
*
* @param callback $function
*/
function unregister_outputfilter($function)
{
unset($this->_plugins['outputfilter'][$this->_get_filter_name($function)]);
}
/**
* load a filter of specified type and name
*
* @param string $type filter type
* @param string $name filter name
*/
function load_filter($type, $name)
{
switch ($type) {
case 'output':
$_params = array('plugins' => array(array($type . 'filter', $name, null, null, false)));
require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
smarty_core_load_plugins($_params, $this);
break;
case 'pre':
case 'post':
if (!isset($this->_plugins[$type . 'filter'][$name]))
$this->_plugins[$type . 'filter'][$name] = false;
break;
}
}
/**
* clear cached content for the given template and cache id
*
* @param string $tpl_file name of template file
* @param string $cache_id name of cache_id
* @param string $compile_id name of compile_id
* @param string $exp_time expiration time
* @return boolean
*/
function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null)
{
if (!isset($compile_id))
$compile_id = $this->compile_id;
if (!isset($tpl_file))
$compile_id = null;
$_auto_id = $this->_get_auto_id($cache_id, $compile_id);
if (!empty($this->cache_handler_func)) {
return call_user_func_array($this->cache_handler_func,
array('clear', &$this, &$dummy, $tpl_file, $cache_id, $compile_id, $exp_time));
} else {
$_params = array('auto_base' => $this->cache_dir,
'auto_source' => $tpl_file,
'auto_id' => $_auto_id,
'exp_time' => $exp_time);
require_once(SMARTY_CORE_DIR . 'core.rm_auto.php');
return smarty_core_rm_auto($_params, $this);
}
}
/**
* clear the entire contents of cache (all templates)
*
* @param string $exp_time expire time
* @return boolean results of {@link smarty_core_rm_auto()}
*/
function clear_all_cache($exp_time = null)
{
return $this->clear_cache(null, null, null, $exp_time);
}
/**
* test to see if valid cache exists for this template
*
* @param string $tpl_file name of template file
* @param string $cache_id
* @param string $compile_id
* @return string|false results of {@link _read_cache_file()}
*/
function is_cached($tpl_file, $cache_id = null, $compile_id = null)
{
if (!$this->caching)
return false;
if (!isset($compile_id))
$compile_id = $this->compile_id;
$_params = array(
'tpl_file' => $tpl_file,
'cache_id' => $cache_id,
'compile_id' => $compile_id
);
require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php');
return smarty_core_read_cache_file($_params, $this);
}
/**
* clear all the assigned template variables.
*
*/
function clear_all_assign()
{
$this->_tpl_vars = array();
}
/**
* clears compiled version of specified template resource,
* or all compiled template files if one is not specified.
* This function is for advanced use only, not normally needed.
*
* @param string $tpl_file
* @param string $compile_id
* @param string $exp_time
* @return boolean results of {@link smarty_core_rm_auto()}
*/
function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp_time = null)
{
if (!isset($compile_id)) {
$compile_id = $this->compile_id;
}
$_params = array('auto_base' => $this->compile_dir,
'auto_source' => $tpl_file,
'auto_id' => $compile_id,
'exp_time' => $exp_time,
'extensions' => array('.inc', '.php'));
require_once(SMARTY_CORE_DIR . 'core.rm_auto.php');
return smarty_core_rm_auto($_params, $this);
}
/**
* Checks whether requested template exists.
*
* @param string $tpl_file
* @return boolean
*/
function template_exists($tpl_file)
{
$_params = array('resource_name' => $tpl_file, 'quiet'=>true, 'get_source'=>false);
return $this->_fetch_resource_info($_params);
}
/**
* Returns an array containing template variables
*
* @param string $name
* @param string $type
* @return array
*/
function &get_template_vars($name=null)
{
if(!isset($name)) {
return $this->_tpl_vars;
} elseif(isset($this->_tpl_vars[$name])) {
return $this->_tpl_vars[$name];
} else {
// var non-existant, return valid reference
$_tmp = null;
return $_tmp;
}
}
/**
* Returns an array containing config variables
*
* @param string $name
* @param string $type
* @return array
*/
function &get_config_vars($name=null)
{
if(!isset($name) && is_array($this->_config[0])) {
return $this->_config[0]['vars'];
} else if(isset($this->_config[0]['vars'][$name])) {
return $this->_config[0]['vars'][$name];
} else {
// var non-existant, return valid reference
$_tmp = null;
return $_tmp;
}
}
/**
* trigger Smarty error
*
* @param string $error_msg
* @param integer $error_type
*/
function trigger_error($error_msg, $error_type = E_USER_WARNING)
{
$msg = htmlentities($error_msg);
trigger_error("Smarty error: $msg", $error_type);
}
/**
* executes & displays the template results
*
* @param string $resource_name
* @param string $cache_id
* @param string $compile_id
*/
function display($resource_name, $cache_id = null, $compile_id = null)
{
$this->fetch($resource_name, $cache_id, $compile_id, true);
}
/**
* executes & returns or displays the template results
*
* @param string $resource_name
* @param string $cache_id
* @param string $compile_id
* @param boolean $display
*/
function fetch($resource_name, $cache_id = null, $compile_id = null, $display = false)
{
static $_cache_info = array();
$_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(isset($this->error_reporting)
? $this->error_reporting : error_reporting() & ~E_NOTICE);
if (!$this->debugging && $this->debugging_ctrl == 'URL') {
$_query_string = $this->request_use_auto_globals ? $_SERVER['QUERY_STRING'] : $GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING'];
if (@strstr($_query_string, $this->_smarty_debug_id)) {
if (@strstr($_query_string, $this->_smarty_debug_id . '=on')) {
// enable debugging for this browser session
@setcookie('SMARTY_DEBUG', true);
$this->debugging = true;
} elseif (@strstr($_query_string, $this->_smarty_debug_id . '=off')) {
// disable debugging for this browser session
@setcookie('SMARTY_DEBUG', false);
$this->debugging = false;
} else {
// enable debugging for this page
$this->debugging = true;
}
} else {
$this->debugging = (bool)($this->request_use_auto_globals ? @$_COOKIE['SMARTY_DEBUG'] : @$GLOBALS['HTTP_COOKIE_VARS']['SMARTY_DEBUG']);
}
}
if ($this->debugging) {
// capture time for debugging info
$_params = array();
require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
$_debug_start_time = smarty_core_get_microtime($_params, $this);
$this->_smarty_debug_info[] = array('type' => 'template',
'filename' => $resource_name,
'depth' => 0);
$_included_tpls_idx = count($this->_smarty_debug_info) - 1;
}
if (!isset($compile_id)) {
$compile_id = $this->compile_id;
}
$this->_compile_id = $compile_id;
$this->_inclusion_depth = 0;
if ($this->caching) {
// save old cache_info, initialize cache_info
array_push($_cache_info, $this->_cache_info);
$this->_cache_info = array();
$_params = array(
'tpl_file' => $resource_name,
'cache_id' => $cache_id,
'compile_id' => $compile_id,
'results' => null
);
require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php');
if (smarty_core_read_cache_file($_params, $this)) {
$_smarty_results = $_params['results'];
if (!empty($this->_cache_info['insert_tags'])) {
$_params = array('plugins' => $this->_cache_info['insert_tags']);
require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
smarty_core_load_plugins($_params, $this);
$_params = array('results' => $_smarty_results);
require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php');
$_smarty_results = smarty_core_process_cached_inserts($_params, $this);
}
if (!empty($this->_cache_info['cache_serials'])) {
$_params = array('results' => $_smarty_results);
require_once(SMARTY_CORE_DIR . 'core.process_compiled_include.php');
$_smarty_results = smarty_core_process_compiled_include($_params, $this);
}
if ($display) {
if ($this->debugging)
{
// capture time for debugging info
$_params = array();
require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
$this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $_debug_start_time;
require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php');
$_smarty_results .= smarty_core_display_debug_console($_params, $this);
}
if ($this->cache_modified_check) {
$_server_vars = ($this->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
$_last_modified_date = @substr($_server_vars['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_server_vars['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3);
$_gmt_mtime = gmdate('D, d M Y H:i:s', $this->_cache_info['timestamp']).' GMT';
if (@count($this->_cache_info['insert_tags']) == 0
&& !$this->_cache_serials
&& $_gmt_mtime == $_last_modified_date) {
if (php_sapi_name()=='cgi')
header('Status: 304 Not Modified');
else
header('HTTP/1.1 304 Not Modified');
} else {
header('Last-Modified: '.$_gmt_mtime);
echo $_smarty_results;
}
} else {
echo $_smarty_results;
}
error_reporting($_smarty_old_error_level);
// restore initial cache_info
$this->_cache_info = array_pop($_cache_info);
return true;
} else {
error_reporting($_smarty_old_error_level);
// restore initial cache_info
$this->_cache_info = array_pop($_cache_info);
return $_smarty_results;
}
} else {
$this->_cache_info['template'][$resource_name] = true;
if ($this->cache_modified_check && $display) {
header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');
}
}
}
// load filters that are marked as autoload
if (count($this->autoload_filters)) {
foreach ($this->autoload_filters as $_filter_type => $_filters) {
foreach ($_filters as $_filter) {
$this->load_filter($_filter_type, $_filter);
}
}
}
$_smarty_compile_path = $this->_get_compile_path($resource_name);
// if we just need to display the results, don't perform output
// buffering - for speed
$_cache_including = $this->_cache_including;
$this->_cache_including = false;
if ($display && !$this->caching && count($this->_plugins['outputfilter']) == 0) {
if ($this->_is_compiled($resource_name, $_smarty_compile_path)
|| $this->_compile_resource($resource_name, $_smarty_compile_path))
{
include($_smarty_compile_path);
}
} else {
ob_start();
if ($this->_is_compiled($resource_name, $_smarty_compile_path)
|| $this->_compile_resource($resource_name, $_smarty_compile_path))
{
include($_smarty_compile_path);
}
$_smarty_results = ob_get_contents();
ob_end_clean();
foreach ((array)$this->_plugins['outputfilter'] as $_output_filter) {
$_smarty_results = call_user_func_array($_output_filter[0], array($_smarty_results, &$this));
}
}
if ($this->caching) {
$_params = array('tpl_file' => $resource_name,
'cache_id' => $cache_id,
'compile_id' => $compile_id,
'results' => $_smarty_results);
require_once(SMARTY_CORE_DIR . 'core.write_cache_file.php');
smarty_core_write_cache_file($_params, $this);
require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php');
$_smarty_results = smarty_core_process_cached_inserts($_params, $this);
if ($this->_cache_serials) {
// strip nocache-tags from output
$_smarty_results = preg_replace('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!s'
,''
,$_smarty_results);
}
// restore initial cache_info
$this->_cache_info = array_pop($_cache_info);
}
$this->_cache_including = $_cache_including;
if ($display) {
if (isset($_smarty_results)) { echo $_smarty_results; }
if ($this->debugging) {
// capture time for debugging info
$_params = array();
require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
$this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = (smarty_core_get_microtime($_params, $this) - $_debug_start_time);
require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php');
echo smarty_core_display_debug_console($_params, $this);
}
error_reporting($_smarty_old_error_level);
return;
} else {
error_reporting($_smarty_old_error_level);
if (isset($_smarty_results)) { return $_smarty_results; }
}
}
/**
* load configuration values
*
* @param string $file
* @param string $section
* @param string $scope
*/
function config_load($file, $section = null, $scope = 'global')
{
require_once($this->_get_plugin_filepath('function', 'config_load'));
smarty_function_config_load(array('file' => $file, 'section' => $section, 'scope' => $scope), $this);
}
/**
* return a reference to a registered object
*
* @param string $name
* @return object
*/
function &get_registered_object($name) {
if (!isset($this->_reg_objects[$name]))
$this->_trigger_fatal_error("'$name' is not a registered object");
if (!is_object($this->_reg_objects[$name][0]))
$this->_trigger_fatal_error("registered '$name' is not an object");
return $this->_reg_objects[$name][0];
}
/**
* clear configuration values
*
* @param string $var
*/
function clear_config($var = null)
{
if(!isset($var)) {
// clear all values
$this->_config = array(array('vars' => array(),
'files' => array()));
} else {
unset($this->_config[0]['vars'][$var]);
}
}
/**
* get filepath of requested plugin
*
* @param string $type
* @param string $name
* @return string|false
*/
function _get_plugin_filepath($type, $name)
{
$_params = array('type' => $type, 'name' => $name);
require_once(SMARTY_CORE_DIR . 'core.assemble_plugin_filepath.php');
return smarty_core_assemble_plugin_filepath($_params, $this);
}
/**
* test if resource needs compiling
*
* @param string $resource_name
* @param string $compile_path
* @return boolean
*/
function _is_compiled($resource_name, $compile_path)
{
if (!$this->force_compile && file_exists($compile_path)) {
if (!$this->compile_check) {
// no need to check compiled file
return true;
} else {
// get file source and timestamp
$_params = array('resource_name' => $resource_name, 'get_source'=>false);
if (!$this->_fetch_resource_info($_params)) {
return false;
}
if ($_params['resource_timestamp'] <= filemtime($compile_path)) {
// template not expired, no recompile
return true;
} else {
// compile template
return false;
}
}
} else {
// compiled template does not exist, or forced compile
return false;
}
}
/**
* compile the template
*
* @param string $resource_name
* @param string $compile_path
* @return boolean
*/
function _compile_resource($resource_name, $compile_path)
{
$_params = array('resource_name' => $resource_name);
if (!$this->_fetch_resource_info($_params)) {
return false;
}
$_source_content = $_params['source_content'];
$_cache_include = substr($compile_path, 0, -4).'.inc';
if ($this->_compile_source($resource_name, $_source_content, $_compiled_content, $_cache_include)) {
// if a _cache_serial was set, we also have to write an include-file:
if ($this->_cache_include_info) {
require_once(SMARTY_CORE_DIR . 'core.write_compiled_include.php');
smarty_core_write_compiled_include(array_merge($this->_cache_include_info, array('compiled_content'=>$_compiled_content, 'resource_name'=>$resource_name)), $this);
}
$_params = array('compile_path'=>$compile_path, 'compiled_content' => $_compiled_content);
require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php');
smarty_core_write_compiled_resource($_params, $this);
return true;
} else {
return false;
}
}
/**
* compile the given source
*
* @param string $resource_name
* @param string $source_content
* @param string $compiled_content
* @return boolean
*/
function _compile_source($resource_name, &$source_content, &$compiled_content, $cache_include_path=null)
{
if (file_exists(SMARTY_DIR . $this->compiler_file)) {
require_once(SMARTY_DIR . $this->compiler_file);
} else {
// use include_path
require_once($this->compiler_file);
}
$smarty_compiler = new $this->compiler_class;
$smarty_compiler->template_dir = $this->template_dir;
$smarty_compiler->compile_dir = $this->compile_dir;
$smarty_compiler->plugins_dir = $this->plugins_dir;
$smarty_compiler->config_dir = $this->config_dir;
$smarty_compiler->force_compile = $this->force_compile;
$smarty_compiler->caching = $this->caching;
$smarty_compiler->php_handling = $this->php_handling;
$smarty_compiler->left_delimiter = $this->left_delimiter;
$smarty_compiler->right_delimiter = $this->right_delimiter;
$smarty_compiler->_version = $this->_version;
$smarty_compiler->security = $this->security;
$smarty_compiler->secure_dir = $this->secure_dir;
$smarty_compiler->security_settings = $this->security_settings;
$smarty_compiler->trusted_dir = $this->trusted_dir;
$smarty_compiler->use_sub_dirs = $this->use_sub_dirs;
$smarty_compiler->_reg_objects = &$this->_reg_objects;
$smarty_compiler->_plugins = &$this->_plugins;
$smarty_compiler->_tpl_vars = &$this->_tpl_vars;
$smarty_compiler->default_modifiers = $this->default_modifiers;
$smarty_compiler->compile_id = $this->_compile_id;
$smarty_compiler->_config = $this->_config;
$smarty_compiler->request_use_auto_globals = $this->request_use_auto_globals;
if (isset($cache_include_path) && isset($this->_cache_serials[$cache_include_path])) {
$smarty_compiler->_cache_serial = $this->_cache_serials[$cache_include_path];
}
$smarty_compiler->_cache_include = $cache_include_path;
$_results = $smarty_compiler->_compile_file($resource_name, $source_content, $compiled_content);
if ($smarty_compiler->_cache_serial) {
$this->_cache_include_info = array(
'cache_serial'=>$smarty_compiler->_cache_serial
,'plugins_code'=>$smarty_compiler->_plugins_code
,'include_file_path' => $cache_include_path);
} else {
$this->_cache_include_info = null;
}
return $_results;
}
/**
* Get the compile path for this resource
*
* @param string $resource_name
* @return string results of {@link _get_auto_filename()}
*/
function _get_compile_path($resource_name)
{
return $this->_get_auto_filename($this->compile_dir, $resource_name,
$this->_compile_id) . '.php';
}
/**
* fetch the template info. Gets timestamp, and source
* if get_source is true
*
* sets $source_content to the source of the template, and
* $resource_timestamp to its time stamp
* @param string $resource_name
* @param string $source_content
* @param integer $resource_timestamp
* @param boolean $get_source
* @param boolean $quiet
* @return boolean
*/
function _fetch_resource_info(&$params)
{
if(!isset($params['get_source'])) { $params['get_source'] = true; }
if(!isset($params['quiet'])) { $params['quiet'] = false; }
$_return = false;
$_params = array('resource_name' => $params['resource_name']) ;
if (isset($params['resource_base_path']))
$_params['resource_base_path'] = $params['resource_base_path'];
else
$_params['resource_base_path'] = $this->template_dir;
if ($this->_parse_resource_name($_params)) {
$_resource_type = $_params['resource_type'];
$_resource_name = $_params['resource_name'];
switch ($_resource_type) {
case 'file':
if ($params['get_source']) {
$params['source_content'] = $this->_read_file($_resource_name);
}
$params['resource_timestamp'] = filemtime($_resource_name);
$_return = is_file($_resource_name) && is_readable($_resource_name);
break;
default:
// call resource functions to fetch the template source and timestamp
if ($params['get_source']) {
$_source_return = isset($this->_plugins['resource'][$_resource_type]) &&
call_user_func_array($this->_plugins['resource'][$_resource_type][0][0],
array($_resource_name, &$params['source_content'], &$this));
} else {
$_source_return = true;
}
$_timestamp_return = isset($this->_plugins['resource'][$_resource_type]) &&
call_user_func_array($this->_plugins['resource'][$_resource_type][0][1],
array($_resource_name, &$params['resource_timestamp'], &$this));
$_return = $_source_return && $_timestamp_return;
break;
}
}
if (!$_return) {
// see if we can get a template with the default template handler
if (!empty($this->default_template_handler_func)) {
if (!is_callable($this->default_template_handler_func)) {
$this->trigger_error("default template handler function \"$this->default_template_handler_func\" doesn't exist.");
} else {
$_return = call_user_func_array(
$this->default_template_handler_func,
array($_params['resource_type'], $_params['resource_name'], &$params['source_content'], &$params['resource_timestamp'], &$this));
}
}
}
if (!$_return) {
if (!$params['quiet']) {
$this->trigger_error('unable to read resource: "' . $params['resource_name'] . '"');
}
} else if ($_return && $this->security) {
require_once(SMARTY_CORE_DIR . 'core.is_secure.php');
if (!smarty_core_is_secure($_params, $this)) {
if (!$params['quiet'])
$this->trigger_error('(secure mode) accessing "' . $params['resource_name'] . '" is not allowed');
$params['source_content'] = null;
$params['resource_timestamp'] = null;
return false;
}
}
return $_return;
}
/**
* parse out the type and name from the resource
*
* @param string $resource_base_path
* @param string $resource_name
* @param string $resource_type
* @param string $resource_name
* @return boolean
*/
function _parse_resource_name(&$params)
{
// split tpl_path by the first colon
$_resource_name_parts = explode(':', $params['resource_name'], 2);
if (count($_resource_name_parts) == 1) {
// no resource type given
$params['resource_type'] = $this->default_resource_type;
$params['resource_name'] = $_resource_name_parts[0];
} else {
if(strlen($_resource_name_parts[0]) == 1) {
// 1 char is not resource type, but part of filepath
$params['resource_type'] = $this->default_resource_type;
$params['resource_name'] = $params['resource_name'];
} else {
$params['resource_type'] = $_resource_name_parts[0];
$params['resource_name'] = $_resource_name_parts[1];
}
}
if ($params['resource_type'] == 'file') {
if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $params['resource_name'])) {
// relative pathname to $params['resource_base_path']
// use the first directory where the file is found
foreach ((array)$params['resource_base_path'] as $_curr_path) {
$_fullpath = $_curr_path . DIRECTORY_SEPARATOR . $params['resource_name'];
if (file_exists($_fullpath) && is_file($_fullpath)) {
$params['resource_name'] = $_fullpath;
return true;
}
// didn't find the file, try include_path
$_params = array('file_path' => $_fullpath);
require_once(SMARTY_CORE_DIR . 'core.get_include_path.php');
if(smarty_core_get_include_path($_params, $this)) {
$params['resource_name'] = $_params['new_file_path'];
return true;
}
}
return false;
} else {
/* absolute path */
return file_exists($params['resource_name']);
}
} elseif (empty($this->_plugins['resource'][$params['resource_type']])) {
$_params = array('type' => $params['resource_type']);
require_once(SMARTY_CORE_DIR . 'core.load_resource_plugin.php');
smarty_core_load_resource_plugin($_params, $this);
}
return true;
}
/**
* Handle modifiers
*
* @param string|null $modifier_name
* @param array|null $map_array
* @return string result of modifiers
*/
function _run_mod_handler()
{
$_args = func_get_args();
list($_modifier_name, $_map_array) = array_splice($_args, 0, 2);
list($_func_name, $_tpl_file, $_tpl_line) =
$this->_plugins['modifier'][$_modifier_name];
$_var = $_args[0];
foreach ($_var as $_key => $_val) {
$_args[0] = $_val;
$_var[$_key] = call_user_func_array($_func_name, $_args);
}
return $_var;
}
/**
* Remove starting and ending quotes from the string
*
* @param string $string
* @return string
*/
function _dequote($string)
{
if ((substr($string, 0, 1) == "'" || substr($string, 0, 1) == '"') &&
substr($string, -1) == substr($string, 0, 1))
return substr($string, 1, -1);
else
return $string;
}
/**
* read in a file
*
* @param string $filename
* @return string
*/
function _read_file($filename)
{
if ( file_exists($filename) && is_readable($filename) && ($fd = @fopen($filename, 'rb')) ) {
$contents = '';
while (!feof($fd)) {
$contents .= fread($fd, 8192);
}
fclose($fd);
return $contents;
} else {
return false;
}
}
/**
* get a concrete filename for automagically created content
*
* @param string $auto_base
* @param string $auto_source
* @param string $auto_id
* @return string
* @staticvar string|null
* @staticvar string|null
*/
function _get_auto_filename($auto_base, $auto_source = null, $auto_id = null)
{
$_compile_dir_sep = $this->use_sub_dirs ? DIRECTORY_SEPARATOR : '^';
$_return = $auto_base . DIRECTORY_SEPARATOR;
if(isset($auto_id)) {
// make auto_id safe for directory names
$auto_id = str_replace('%7C',$_compile_dir_sep,(urlencode($auto_id)));
// split into separate directories
$_return .= $auto_id . $_compile_dir_sep;
}
if(isset($auto_source)) {
// make source name safe for filename
$_filename = urlencode(basename($auto_source));
$_crc32 = sprintf('%08X', crc32($auto_source));
// prepend %% to avoid name conflicts with
// with $params['auto_id'] names
$_crc32 = substr($_crc32, 0, 2) . $_compile_dir_sep .
substr($_crc32, 0, 3) . $_compile_dir_sep . $_crc32;
$_return .= '%%' . $_crc32 . '%%' . $_filename;
}
return $_return;
}
/**
* unlink a file, possibly using expiration time
*
* @param string $resource
* @param integer $exp_time
*/
function _unlink($resource, $exp_time = null)
{
if(isset($exp_time)) {
if(time() - @filemtime($resource) >= $exp_time) {
return @unlink($resource);
}
} else {
return @unlink($resource);
}
}
/**
* returns an auto_id for auto-file-functions
*
* @param string $cache_id
* @param string $compile_id
* @return string|null
*/
function _get_auto_id($cache_id=null, $compile_id=null) {
if (isset($cache_id))
return (isset($compile_id)) ? $cache_id . '|' . $compile_id : $cache_id;
elseif(isset($compile_id))
return $compile_id;
else
return null;
}
/**
* trigger Smarty plugin error
*
* @param string $error_msg
* @param string $tpl_file
* @param integer $tpl_line
* @param string $file
* @param integer $line
* @param integer $error_type
*/
function _trigger_fatal_error($error_msg, $tpl_file = null, $tpl_line = null,
$file = null, $line = null, $error_type = E_USER_ERROR)
{
if(isset($file) && isset($line)) {
$info = ' ('.basename($file).", line $line)";
} else {
$info = '';
}
if (isset($tpl_line) && isset($tpl_file)) {
$this->trigger_error('[in ' . $tpl_file . ' line ' . $tpl_line . "]: $error_msg$info", $error_type);
} else {
$this->trigger_error($error_msg . $info, $error_type);
}
}
/**
* callback function for preg_replace, to call a non-cacheable block
* @return string
*/
function _process_compiled_include_callback($match) {
$_func = '_smarty_tplfunc_'.$match[2].'_'.$match[3];
ob_start();
$_func($this);
$_ret = ob_get_contents();
ob_end_clean();
return $_ret;
}
/**
* called for included templates
*
* @param string $_smarty_include_tpl_file
* @param string $_smarty_include_vars
*/
// $_smarty_include_tpl_file, $_smarty_include_vars
function _smarty_include($params)
{
if ($this->debugging) {
$_params = array();
require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
$debug_start_time = smarty_core_get_microtime($_params, $this);
$this->_smarty_debug_info[] = array('type' => 'template',
'filename' => $params['smarty_include_tpl_file'],
'depth' => ++$this->_inclusion_depth);
$included_tpls_idx = count($this->_smarty_debug_info) - 1;
}
$this->_tpl_vars = array_merge($this->_tpl_vars, $params['smarty_include_vars']);
// config vars are treated as local, so push a copy of the
// current ones onto the front of the stack
array_unshift($this->_config, $this->_config[0]);
$_smarty_compile_path = $this->_get_compile_path($params['smarty_include_tpl_file']);
if ($this->_is_compiled($params['smarty_include_tpl_file'], $_smarty_compile_path)
|| $this->_compile_resource($params['smarty_include_tpl_file'], $_smarty_compile_path))
{
include($_smarty_compile_path);
}
// pop the local vars off the front of the stack
array_shift($this->_config);
$this->_inclusion_depth--;
if ($this->debugging) {
// capture time for debugging info
$_params = array();
require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
$this->_smarty_debug_info[$included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $debug_start_time;
}
if ($this->caching) {
$this->_cache_info['template'][$params['smarty_include_tpl_file']] = true;
}
}
/**
* get or set an array of cached attributes for function that is
* not cacheable
* @return array
*/
function &_smarty_cache_attrs($cache_serial, $count) {
$_cache_attrs =& $this->_cache_info['cache_attrs'][$cache_serial][$count];
if ($this->_cache_including) {
/* return next set of cache_attrs */
$_return = current($_cache_attrs);
next($_cache_attrs);
return $_return;
} else {
/* add a reference to a new set of cache_attrs */
$_cache_attrs[] = array();
return $_cache_attrs[count($_cache_attrs)-1];
}
}
/**
* wrapper for include() retaining $this
* @return mixed
*/
function _include($filename, $once=false, $params=null)
{
if ($once) {
return include_once($filename);
} else {
return include($filename);
}
}
/**
* wrapper for eval() retaining $this
* @return mixed
*/
function _eval($code, $params=null)
{
return eval($code);
}
/**
* Extracts the filter name from the given callback
*
* @param callback $function
* @return string
*/
function _get_filter_name($function)
{
if (is_array($function)) {
$_class_name = (is_object($function[0]) ?
get_class($function[0]) : $function[0]);
return $_class_name . '_' . $function[1];
}
else {
return $function;
}
}
/**#@-*/
}
/* vim: set expandtab: */
?>
================================================
FILE: lib/smarty/Smarty_Compiler.class.php
================================================
<?php
/**
* Project: Smarty: the PHP compiling template engine
* File: Smarty_Compiler.class.php
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* @link http://smarty.php.net/
* @author Monte Ohrt <monte at ohrt dot com>
* @author Andrei Zmievski <andrei@php.net>
* @version 2.6.25-dev
* @copyright 2001-2005 New Digital Group, Inc.
* @package Smarty
*/
/* $Id: Smarty_Compiler.class.php 4779 2013-09-30 19:14:32Z Uwe.Tews@googlemail.com $ */
/**
* Template compiling class
* @package Smarty
*/
class Smarty_Compiler extends Smarty {
// internal vars
/**#@+
* @access private
*/
var $_folded_blocks = array(); // keeps folded template blocks
var $_current_file = null; // the current template being compiled
var $_current_line_no = 1; // line number for error messages
var $_capture_stack = array(); // keeps track of nested capture buffers
var $_plugin_info = array(); // keeps track of plugins to load
var $_init_smarty_vars = false;
var $_permitted_tokens = array('true','false','yes','no','on','off','null');
var $_db_qstr_regexp = null; // regexps are setup in the constructor
var $_si_qstr_regexp = null;
var $_qstr_regexp = null;
var $_func_regexp = null;
var $_reg_obj_regexp = null;
var $_var_bracket_regexp = null;
var $_num_const_regexp = null;
var $_dvar_guts_regexp = null;
var $_dvar_regexp = null;
var $_cvar_regexp = null;
var $_svar_regexp = null;
var $_avar_regexp = null;
var $_mod_regexp = null;
var $_var_regexp = null;
var $_parenth_param_regexp = null;
var $_func_call_regexp = null;
var $_obj_ext_regexp = null;
var $_obj_start_regexp = null;
var $_obj_params_regexp = null;
var $_obj_call_regexp = null;
var $_cacheable_state = 0;
var $_cache_attrs_count = 0;
var $_nocache_count = 0;
var $_cache_serial = null;
var $_cache_include = null;
var $_strip_depth = 0;
var $_additional_newline = "\n";
/**#@-*/
/**
* The class constructor.
*/
function Smarty_Compiler()
{
// matches double quoted strings:
// "foobar"
// "foo\"bar"
$this->_db_qstr_regexp = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"';
// matches single quoted strings:
// 'foobar'
// 'foo\'bar'
$this->_si_qstr_regexp = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'';
// matches single or double quoted strings
$this->_qstr_regexp = '(?:' . $this->_db_qstr_regexp . '|' . $this->_si_qstr_regexp . ')';
// matches bracket portion of vars
// [0]
// [foo]
// [$bar]
$this->_var_bracket_regexp = '\[\$?[\w\.]+\]';
// matches numerical constants
// 30
// -12
// 13.22
$this->_num_const_regexp = '(?:\-?\d+(?:\.\d+)?)';
// matches $ vars (not objects):
// $foo
// $foo.bar
// $foo.bar.foobar
// $foo[0]
// $foo[$bar]
// $foo[5][blah]
// $foo[5].bar[$foobar][4]
$this->_dvar_math_regexp = '(?:[\+\*\/\%]|(?:-(?!>)))';
$this->_dvar_math_var_regexp = '[\$\w\.\+\-\*\/\%\d\>\[\]]';
$this->_dvar_guts_regexp = '\w+(?:' . $this->_var_bracket_regexp
. ')*(?:\.\$?\w+(?:' . $this->_var_bracket_regexp . ')*)*(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?';
$this->_dvar_regexp = '\$' . $this->_dvar_guts_regexp;
// matches config vars:
// #foo#
// #foobar123_foo#
$this->_cvar_regexp = '\#\w+\#';
// matches section vars:
// %foo.bar%
$this->_svar_regexp = '\%\w+\.\w+\%';
// matches all valid variables (no quotes, no modifiers)
$this->_avar_regexp = '(?:' . $this->_dvar_regexp . '|'
. $this->_cvar_regexp . '|' . $this->_svar_regexp . ')';
// matches valid variable syntax:
// $foo
// $foo
// #foo#
// #foo#
// "text"
// "text"
$this->_var_regexp = '(?:' . $this->_avar_regexp . '|' . $this->_qstr_regexp . ')';
// matches valid object call (one level of object nesting allowed in parameters):
// $foo->bar
// $foo->bar()
// $foo->bar("text")
// $foo->bar($foo, $bar, "text")
// $foo->bar($foo, "foo")
// $foo->bar->foo()
// $foo->bar->foo->bar()
// $foo->bar($foo->bar)
// $foo->bar($foo->bar())
// $foo->bar($foo->bar($blah,$foo,44,"foo",$foo[0].bar))
$this->_obj_ext_regexp = '\->(?:\$?' . $this->_dvar_guts_regexp . ')';
$this->_obj_restricted_param_regexp = '(?:'
. '(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')(?:' . $this->_obj_ext_regexp . '(?:\((?:(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')'
. '(?:\s*,\s*(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . '))*)?\))?)*)';
$this->_obj_single_param_regexp = '(?:\w+|' . $this->_obj_restricted_param_regexp . '(?:\s*,\s*(?:(?:\w+|'
. $this->_var_regexp . $this->_obj_restricted_param_regexp . ')))*)';
$this->_obj_params_regexp = '\((?:' . $this->_obj_single_param_regexp
. '(?:\s*,\s*' . $this->_obj_single_param_regexp . ')*)?\)';
$this->_obj_start_regexp = '(?:' . $this->_dvar_regexp . '(?:' . $this->_obj_ext_regexp . ')+)';
$this->_obj_call_regexp = '(?:' . $this->_obj_start_regexp . '(?:' . $this->_obj_params_regexp . ')?(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?)';
// matches valid modifier syntax:
// |foo
// |@foo
// |foo:"bar"
// |foo:$bar
// |foo:"bar":$foobar
// |foo|bar
// |foo:$foo->bar
$this->_mod_regexp = '(?:\|@?\w+(?::(?:\w+|' . $this->_num_const_regexp . '|'
. $this->_obj_call_regexp . '|' . $this->_avar_regexp . '|' . $this->_qstr_regexp .'))*)';
// matches valid function name:
// foo123
// _foo_bar
$this->_func_regexp = '[a-zA-Z_]\w*';
// matches valid registered object:
// foo->bar
$this->_reg_obj_regexp = '[a-zA-Z_]\w*->[a-zA-Z_]\w*';
// matches valid parameter values:
// true
// $foo
// $foo|bar
// #foo#
// #foo#|bar
// "text"
// "text"|bar
// $foo->bar
$this->_param_regexp = '(?:\s*(?:' . $this->_obj_call_regexp . '|'
. $this->_var_regexp . '|' . $this->_num_const_regexp . '|\w+)(?>' . $this->_mod_regexp . '*)\s*)';
// matches valid parenthesised function parameters:
//
// "text"
// $foo, $bar, "text"
// $foo|bar, "foo"|bar, $foo->bar($foo)|bar
$this->_parenth_param_regexp = '(?:\((?:\w+|'
. $this->_param_regexp . '(?:\s*,\s*(?:(?:\w+|'
. $this->_param_regexp . ')))*)?\))';
// matches valid function call:
// foo()
// foo_bar($foo)
// _foo_bar($foo,"bar")
// foo123($foo,$foo->bar(),"foo")
$this->_func_call_regexp = '(?:' . $this->_func_regexp . '\s*(?:'
. $this->_parenth_param_regexp . '))';
}
/**
* compile a resource
*
* sets $compiled_content to the compiled source
* @param string $resource_name
* @param string $source_content
* @param string $compiled_content
* @return true
*/
function _compile_file($resource_name, $source_content, &$compiled_content)
{
if ($this->security) {
// do not allow php syntax to be executed unless specified
if ($this->php_handling == SMARTY_PHP_ALLOW &&
!$this->security_settings['PHP_HANDLING']) {
$this->php_handling = SMARTY_PHP_PASSTHRU;
}
}
$this->_load_filters();
$this->_current_file = $resource_name;
$this->_current_line_no = 1;
$ldq = preg_quote($this->left_delimiter, '~');
$rdq = preg_quote($this->right_delimiter, '~');
// run template source through prefilter functions
if (count($this->_plugins['prefilter']) > 0) {
foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) {
if ($prefilter === false) continue;
if ($prefilter[3] || is_callable($prefilter[0])) {
$source_content = call_user_func_array($prefilter[0],
array($source_content, &$this));
$this->_plugins['prefilter'][$filter_name][3] = true;
} else {
$this->_trigger_fatal_error("[plugin] prefilter '$filter_name' is not implemented");
}
}
}
/* fetch all special blocks */
$search = "~{$ldq}\*(.*?)\*{$rdq}|{$ldq}\s*literal\s*{$rdq}(.*?){$ldq}\s*/literal\s*{$rdq}|{$ldq}\s*php\s*{$rdq}(.*?){$ldq}\s*/php\s*{$rdq}~s";
preg_match_all($search, $source_content, $match, PREG_SET_ORDER);
$this->_folded_blocks = $match;
reset($this->_folded_blocks);
/* replace special blocks by "{php}" */
$source_content = preg_replace_callback($search, create_function ('$matches', "return '"
. $this->_quote_replace($this->left_delimiter) . 'php'
. "' . str_repeat(\"\n\", substr_count('\$matches[1]', \"\n\")) .'"
. $this->_quote_replace($this->right_delimiter)
. "';")
, $source_content);
/* Gather all template tags. */
preg_match_all("~{$ldq}\s*(.*?)\s*{$rdq}~s", $source_content, $_match);
$template_tags = $_match[1];
/* Split content by template tags to obtain non-template content. */
$text_blocks = preg_split("~{$ldq}.*?{$rdq}~s", $source_content);
/* loop through text blocks */
for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) {
/* match anything resembling php tags */
if (preg_match_all('~(<\?(?:\w+|=)?|\?>|language\s*=\s*[\"\']?\s*php\s*[\"\']?)~is', $text_blocks[$curr_tb], $sp_match)) {
/* replace tags with placeholders to prevent recursive replacements */
$sp_match[1] = array_unique($sp_match[1]);
usort($sp_match[1], '_smarty_sort_length');
for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {
$text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],'%%%SMARTYSP'.$curr_sp.'%%%',$text_blocks[$curr_tb]);
}
/* process each one */
for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {
if ($this->php_handling == SMARTY_PHP_PASSTHRU) {
/* echo php contents */
$text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '<?php echo \''.str_replace("'", "\'", $sp_match[1][$curr_sp]).'\'; ?>'."\n", $text_blocks[$curr_tb]);
} else if ($this->php_handling == SMARTY_PHP_QUOTE) {
/* quote php tags */
$text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', htmlspecialchars($sp_match[1][$curr_sp]), $text_blocks[$curr_tb]);
} else if ($this->php_handling == SMARTY_PHP_REMOVE) {
/* remove php tags */
$text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '', $text_blocks[$curr_tb]);
} else {
/* SMARTY_PHP_ALLOW, but echo non php starting tags */
$sp_match[1][$curr_sp] = preg_replace('~(<\?(?!php|=|$))~i', '<?php echo \'\\1\'?>'."\n", $sp_match[1][$curr_sp]);
$text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', $sp_match[1][$curr_sp], $text_blocks[$curr_tb]);
}
}
}
}
/* Compile the template tags into PHP code. */
$compiled_tags = array();
for ($i = 0, $for_max = count($template_tags); $i < $for_max; $i++) {
$this->_current_line_no += substr_count($text_blocks[$i], "\n");
$compiled_tags[] = $this->_compile_tag($template_tags[$i]);
$this->_current_line_no += substr_count($template_tags[$i], "\n");
}
if (count($this->_tag_stack)>0) {
list($_open_tag, $_line_no) = end($this->_tag_stack);
$this->_syntax_error("unclosed tag \{$_open_tag} (opened line $_line_no).", E_USER_ERROR, __FILE__, __LINE__);
return;
}
/* Reformat $text_blocks between 'strip' and '/strip' tags,
removing spaces, tabs and newlines. */
$strip = false;
for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {
if ($compiled_tags[$i] == '{strip}') {
$compiled_tags[$i] = '';
$strip = true;
/* remove leading whitespaces */
$text_blocks[$i + 1] = ltrim($text_blocks[$i + 1]);
}
if ($strip) {
/* strip all $text_blocks before the next '/strip' */
for ($j = $i + 1; $j < $for_max; $j++) {
/* remove leading and trailing whitespaces of each line */
$text_blocks[$j] = preg_replace('![\t ]*[\r\n]+[\t ]*!', '', $text_blocks[$j]);
if ($compiled_tags[$j] == '{/strip}') {
/* remove trailing whitespaces from the last text_block */
$text_blocks[$j] = rtrim($text_blocks[$j]);
}
$text_blocks[$j] = "<?php echo '" . strtr($text_blocks[$j], array("'"=>"\'", "\\"=>"\\\\")) . "'; ?>";
if ($compiled_tags[$j] == '{/strip}') {
$compiled_tags[$j] = "\n"; /* slurped by php, but necessary
if a newline is following the closing strip-tag */
$strip = false;
$i = $j;
break;
}
}
}
}
$compiled_content = '';
$tag_guard = '%%%SMARTYOTG' . md5(uniqid(rand(), true)) . '%%%';
/* Interleave the compiled contents and text blocks to get the final result. */
for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {
if ($compiled_tags[$i] == '') {
// tag result empty, remove first newline from following text block
$text_blocks[$i+1] = preg_replace('~^(\r\n|\r|\n)~', '', $text_blocks[$i+1]);
}
// replace legit PHP tags with placeholder
$text_blocks[$i] = str_replace('<?', $tag_guard, $text_blocks[$i]);
$compiled_tags[$i] = str_replace('<?', $tag_guard, $compiled_tags[$i]);
$compiled_content .= $text_blocks[$i] . $compiled_tags[$i];
}
$compiled_content .= str_replace('<?', $tag_guard, $text_blocks[$i]);
// escape php tags created by interleaving
$compiled_content = str_replace('<?', "<?php echo '<?' ?>\n", $compiled_content);
$compiled_content = preg_replace("~(?<!')language\s*=\s*[\"\']?\s*php\s*[\"\']?~", "<?php echo 'language=php' ?>\n", $compiled_content);
// recover legit tags
$compiled_content = str_replace($tag_guard, '<?', $compiled_content);
// remove \n from the end of the file, if any
if (strlen($compiled_content) && (substr($compiled_content, -1) == "\n") ) {
$compiled_content = substr($compiled_content, 0, -1);
}
if (!empty($this->_cache_serial)) {
$compiled_content = "<?php \$this->_cache_serials['".$this->_cache_include."'] = '".$this->_cache_serial."'; ?>" . $compiled_content;
}
// run compiled template through postfilter functions
if (count($this->_plugins['postfilter']) > 0) {
foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) {
if ($postfilter === false) continue;
if ($postfilter[3] || is_callable($postfilter[0])) {
$compiled_content = call_user_func_array($postfilter[0],
array($compiled_content, &$this));
$this->_plugins['postfilter'][$filter_name][3] = true;
} else {
$this->_trigger_fatal_error("Smarty plugin error: postfilter '$filter_name' is not implemented");
}
}
}
// put header at the top of the compiled template
$template_header = "<?php /* Smarty version ".$this->_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n";
$template_header .= " compiled from ".strtr(urlencode($resource_name), array('%2F'=>'/', '%3A'=>':'))." */ ?>\n";
/* Emit code to load needed plugins. */
$this->_plugins_code = '';
if (count($this->_plugin_info)) {
$_plugins_params = "array('plugins' => array(";
foreach ($this->_plugin_info as $plugin_type => $plugins) {
foreach ($plugins as $plugin_name => $plugin_info) {
$_plugins_params .= "array('$plugin_type', '$plugin_name', '" . strtr($plugin_info[0], array("'" => "\\'", "\\" => "\\\\")) . "', $plugin_info[1], ";
$_plugins_params .= $plugin_info[2] ? 'true),' : 'false),';
}
}
$_plugins_params .= '))';
$plugins_code = "<?php require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');\nsmarty_core_load_plugins($_plugins_params, \$this); ?>\n";
$template_header .= $plugins_code;
$this->_plugin_info = array();
$this->_plugins_code = $plugins_code;
}
if ($this->_init_smarty_vars) {
$template_header .= "<?php require_once(SMARTY_CORE_DIR . 'core.assign_smarty_interface.php');\nsmarty_core_assign_smarty_interface(null, \$this); ?>\n";
$this->_init_smarty_vars = false;
}
$compiled_content = $template_header . $compiled_content;
return true;
}
/**
* Compile a template tag
*
* @param string $template_tag
* @return string
*/
function _compile_tag($template_tag)
{
/* Matched comment. */
if (substr($template_tag, 0, 1) == '*' && substr($template_tag, -1) == '*')
return '';
/* Split tag into two three parts: command, command modifiers and the arguments. */
if(! preg_match('~^(?:(' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp
. '|\/?' . $this->_reg_obj_regexp . '|\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*))
(?:\s+(.*))?$
~xs', $template_tag, $match)) {
$this->_syntax_error("unrecognized tag: $template_tag", E_USER_ERROR, __FILE__, __LINE__);
}
$tag_command = $match[1];
$tag_modifier = isset($match[2]) ? $match[2] : null;
$tag_args = isset($match[3]) ? $match[3] : null;
if (preg_match('~^' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$~', $tag_command)) {
/* tag name is a variable or object */
$_return = $this->_parse_var_props($tag_command . $tag_modifier);
return "<?php echo $_return; ?>" . $this->_additional_newline;
}
/* If the tag name is a registered object, we process it. */
if (preg_match('~^\/?' . $this->_reg_obj_regexp . '$~', $tag_command)) {
return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier);
}
switch ($tag_command) {
case 'include':
return $this->_compile_include_tag($tag_args);
case 'include_php':
return $this->_compile_include_php_tag($tag_args);
case 'if':
$this->_push_tag('if');
return $this->_compile_if_tag($tag_args);
case 'else':
list($_open_tag) = end($this->_tag_stack);
if ($_open_tag != 'if' && $_open_tag != 'elseif')
$this->_syntax_error('unexpected {else}', E_USER_ERROR, __FILE__, __LINE__);
else
$this->_push_tag('else');
return '<?php else: ?>';
case 'elseif':
list($_open_tag) = end($this->_tag_stack);
if ($_open_tag != 'if' && $_open_tag != 'elseif')
$this->_syntax_error('unexpected {elseif}', E_USER_ERROR, __FILE__, __LINE__);
if ($_open_tag == 'if')
$this->_push_tag('elseif');
return $this->_compile_if_tag($tag_args, true);
case '/if':
$this->_pop_tag('if');
return '<?php endif; ?>';
case 'capture':
return $this->_compile_capture_tag(true, $tag_args);
case '/capture':
return $this->_compile_capture_tag(false);
case 'ldelim':
return $this->left_delimiter;
case 'rdelim':
return $this->right_delimiter;
case 'section':
$this->_push_tag('section');
return $this->_compile_section_start($tag_args);
case 'sectionelse':
$this->_push_tag('sectionelse');
return "<?php endfor; else: ?>";
break;
case '/section':
$_open_tag = $this->_pop_tag('section');
if ($_open_tag == 'sectionelse')
return "<?php endif; ?>";
else
return "<?php endfor; endif; ?>";
case 'foreach':
$this->_push_tag('foreach');
return $this->_compile_foreach_start($tag_args);
break;
case 'foreachelse':
$this->_push_tag('foreachelse');
return "<?php endforeach; else: ?>";
case '/foreach':
$_open_tag = $this->_pop_tag('foreach');
if ($_open_tag == 'foreachelse')
return "<?php endif; unset(\$_from); ?>";
else
return "<?php endforeach; endif; unset(\$_from); ?>";
break;
case 'strip':
case '/strip':
if (substr($tag_command, 0, 1)=='/') {
$this->_pop_tag('strip');
if (--$this->_strip_depth==0) { /* outermost closing {/strip} */
$this->_additional_newline = "\n";
return '{' . $tag_command . '}';
}
} else {
$this->_push_tag('strip');
if ($this->_strip_depth++==0) { /* outermost opening {strip} */
$this->_additional_newline = "";
return '{' . $tag_command . '}';
}
}
return '';
case 'php':
/* handle folded tags replaced by {php} */
list(, $block) = each($this->_folded_blocks);
$this->_current_line_no += substr_count($block[0], "\n");
/* the number of matched elements in the regexp in _compile_file()
determins the type of folded tag that was found */
switch (count($block)) {
case 2: /* comment */
return '';
case 3: /* literal */
return "<?php echo '" . strtr($block[2], array("'"=>"\'", "\\"=>"\\\\")) . "'; ?>" . $this->_additional_newline;
case 4: /* php */
if ($this->security && !$this->security_settings['PHP_TAGS']) {
$this->_syntax_error("(secure mode) php tags not permitted", E_USER_WARNING, __FILE__, __LINE__);
return;
}
return '<?php ' . $block[3] .' ?>';
}
break;
case 'insert':
return $this->_compile_insert_tag($tag_args);
default:
if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) {
return $output;
} else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) {
return $output;
} else if ($this->_compile_custom_tag($tag_command, $tag_args, $tag_modifier, $output)) {
return $output;
} else {
$this->_syntax_error("unrecognized tag '$tag_command'", E_USER_ERROR, __FILE__, __LINE__);
}
}
}
/**
* compile the custom compiler tag
*
* sets $output to the compiled custom compiler tag
* @param string $tag_command
* @param string $tag_args
* @param string $output
* @return boolean
*/
function _compile_compiler_tag($tag_command, $tag_args, &$output)
{
$found = false;
$have_function = true;
/*
* First we check if the compiler function has already been registered
* or loaded from a plugin file.
*/
if (isset($this->_plugins['compiler'][$tag_command])) {
$found = true;
$plugin_func = $this->_plugins['compiler'][$tag_command][0];
if (!is_callable($plugin_func)) {
$message = "compiler function '$tag_command' is not implemented";
$have_function = false;
}
}
/*
* Otherwise we need to load plugin file and look for the function
* inside it.
*/
else if ($plugin_file = $this->_get_plugin_filepath('compiler', $tag_command)) {
$found = true;
include_once $plugin_file;
$plugin_func = 'smarty_compiler_' . $tag_command;
if (!is_callable($plugin_func)) {
$message = "plugin function $plugin_func() not found in $plugin_file\n";
$have_function = false;
} else {
$this->_plugins['compiler'][$tag_command] = array($plugin_func, null, null, null, true);
}
}
/*
* True return value means that we either found a plugin or a
* dynamically registered function. False means that we didn't and the
* compiler should now emit code to load custom function plugin for this
* tag.
*/
if ($found) {
if ($have_function) {
$output = call_user_func_array($plugin_func, array($tag_args, &$this));
if($output != '') {
$output = '<?php ' . $this->_push_cacheable_state('compiler', $tag_command)
. $output
. $this->_pop_cacheable_state('compiler', $tag_command) . ' ?>';
}
} else {
$this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
}
return true;
} else {
return false;
}
}
/**
* compile block function tag
*
* sets $output to compiled block function tag
* @param string $tag_command
* @param string $tag_args
* @param string $tag_modifier
* @param string $output
* @return boolean
*/
function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$output)
{
if (substr($tag_command, 0, 1) == '/') {
$start_tag = false;
$tag_command = substr($tag_command, 1);
} else
$start_tag = true;
$found = false;
$have_function = true;
/*
* First we check if the block function has already been registered
* or loaded from a plugin file.
*/
if (isset($this->_plugins['block'][$tag_command])) {
$found = true;
$plugin_func = $this->_plugins['block'][$tag_command][0];
if (!is_callable($plugin_func)) {
$message = "block function '$tag_command' is not implemented";
$have_function = false;
}
}
/*
* Otherwise we need to load plugin file and look for the function
* inside it.
*/
else if ($plugin_file = $this->_get_plugin_filepath('block', $tag_command)) {
$found = true;
include_once $plugin_file;
$plugin_func = 'smarty_block_' . $tag_command;
if (!function_exists($plugin_func)) {
$message = "plugin function $plugin_func() not found in $plugin_file\n";
$have_function = false;
} else {
$this->_plugins['block'][$tag_command] = array($plugin_func, null, null, null, true);
}
}
if (!$found) {
return false;
} else if (!$have_function) {
$this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
return true;
}
/*
* Even though we've located the plugin function, compilation
* happens only once, so the plugin will still need to be loaded
* at runtime for future requests.
*/
$this->_add_plugin('block', $tag_command);
if ($start_tag)
$this->_push_tag($tag_command);
else
$this->_pop_tag($tag_command);
if ($start_tag) {
$output = '<?php ' . $this->_push_cacheable_state('block', $tag_command);
$attrs = $this->_parse_attrs($tag_args);
$_cache_attrs='';
$arg_list = $this->_compile_arg_list('block', $tag_command, $attrs, $_cache_attrs);
$output .= "$_cache_attrs\$this->_tag_stack[] = array('$tag_command', array(".implode(',', $arg_list).')); ';
$output .= '$_block_repeat=true;' . $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], null, $this, $_block_repeat);';
$output .= 'while ($_block_repeat) { ob_start(); ?>';
} else {
$output = '<?php $_block_content = ob_get_contents(); ob_end_clean(); ';
$_out_tag_text = $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], $_block_content, $this, $_block_repeat)';
if ($tag_modifier != '') {
$this->_parse_modifiers($_out_tag_text, $tag_modifier);
}
$output .= '$_block_repeat=false;echo ' . $_out_tag_text . '; } ';
$output .= " array_pop(\$this->_tag_stack); " . $this->_pop_cacheable_state('block', $tag_command) . '?>';
}
return true;
}
/**
* compile custom function tag
*
* @param string $tag_command
* @param string $tag_args
* @param string $tag_modifier
* @return string
*/
function _compile_custom_tag($tag_command, $tag_args, $tag_modifier, &$output)
{
$found = false;
$have_function = true;
/*
* First we check if the custom function has already been registered
* or loaded from a plugin file.
*/
if (isset($this->_plugins['function'][$tag_command])) {
$found = true;
$plugin_func = $this->_plugins['function'][$tag_command][0];
if (!is_callable($plugin_func)) {
$message = "custom function '$tag_command' is not implemented";
$have_function = false;
}
}
/*
* Otherwise we need to load plugin file and look for the function
* inside it.
*/
else if ($plugin_file = $this->_get_plugin_filepath('function', $tag_command)) {
$found = true;
include_once $plugin_file;
$plugin_func = 'smarty_function_' . $tag_command;
if (!function_exists($plugin_func)) {
$message = "plugin function $plugin_func() not found in $plugin_file\n";
$have_function = false;
} else {
$this->_plugins['function'][$tag_command] = array($plugin_func, null, null, null, true);
}
}
if (!$found) {
return false;
} else if (!$have_function) {
$this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
return true;
}
/* declare plugin to be loaded on display of the template that
we compile right now */
$this->_add_plugin('function', $tag_command);
$_cacheable_state = $this->_push_cacheable_state('function', $tag_command);
$attrs = $this->_parse_attrs($tag_args);
$_cache_attrs = '';
$arg_list = $this->_compile_arg_list('function', $tag_command, $attrs, $_cache_attrs);
$output = $this->_compile_plugin_call('function', $tag_command).'(array('.implode(',', $arg_list)."), \$this)";
if($tag_modifier != '') {
$this->_parse_modifiers($output, $tag_modifier);
}
if($output != '') {
$output = '<?php ' . $_cacheable_state . $_cache_attrs . 'echo ' . $output . ';'
. $this->_pop_cacheable_state('function', $tag_command) . "?>" . $this->_additional_newline;
}
return true;
}
/**
* compile a registered object tag
*
* @param string $tag_command
* @param array $attrs
* @param string $tag_modifier
* @return string
*/
function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier)
{
if (substr($tag_command, 0, 1) == '/') {
$start_tag = false;
$tag_command = substr($tag_command, 1);
} else {
$start_tag = true;
}
list($object, $obj_comp) = explode('->', $tag_command);
$arg_list = array();
if(count($attrs)) {
$_assign_var = false;
foreach ($attrs as $arg_name => $arg_value) {
if($arg_name == 'assign') {
$_assign_var = $arg_value;
unset($attrs['assign']);
continue;
}
if (is_bool($arg_value))
$arg_value = $arg_value ? 'true' : 'false';
$arg_list[] = "'$arg_name' => $arg_value";
}
}
if($this->_reg_objects[$object][2]) {
// smarty object argument format
$args = "array(".implode(',', (array)$arg_list)."), \$this";
} else {
// traditional argument format
$args = implode(',', array_values($attrs));
if (empty($args)) {
$args = '';
}
}
$prefix = '';
$postfix = '';
$newline = '';
if(!is_object($this->_reg_objects[$object][0])) {
$this->_trigger_fatal_error("registered '$object' is not an object" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
} elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) {
$this->_trigger_fatal_error("'$obj_comp' is not a registered component of object '$object'", $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
} elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) {
// method
if(in_array($obj_comp, $this->_reg_objects[$object][3])) {
// block method
if ($start_tag) {
$prefix = "\$this->_tag_stack[] = array('$obj_comp', $args); ";
$prefix .= "\$_block_repeat=true; \$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], null, \$this, \$_block_repeat); ";
$prefix .= "while (\$_block_repeat) { ob_start();";
$return = null;
$postfix = '';
} else {
$prefix = "\$_obj_block_content = ob_get_contents(); ob_end_clean(); \$_block_repeat=false;";
$return = "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], \$_obj_block_content, \$this, \$_block_repeat)";
$postfix = "} array_pop(\$this->_tag_stack);";
}
} else {
// non-block method
$return = "\$this->_reg_objects['$object'][0]->$obj_comp($args)";
}
} else {
// property
$return = "\$this->_reg_objects['$object'][0]->$obj_comp";
}
if($return != null) {
if($tag_modifier != '') {
$this->_parse_modifiers($return, $tag_modifier);
}
if(!empty($_assign_var)) {
$output = "\$this->assign('" . $this->_dequote($_assign_var) ."', $return);";
} else {
$output = 'echo ' . $return . ';';
$newline = $this->_additional_newline;
}
} else {
$output = '';
}
return '<?php ' . $prefix . $output . $postfix . "?>" . $newline;
}
/**
* Compile {insert ...} tag
*
* @param string $tag_args
* @return string
*/
function _compile_insert_tag($tag_args)
{
$attrs = $this->_parse_attrs($tag_args);
$name = $this->_dequote($attrs['name']);
if (empty($name)) {
return $this->_syntax_error("missing insert name", E_USER_ERROR, __FILE__, __LINE__);
}
if (!preg_match('~^\w+$~', $name)) {
return $this->_syntax_error("'insert: 'name' must be an insert function name", E_USER_ERROR, __FILE__, __LINE__);
}
if (!empty($attrs['script'])) {
$delayed_loading = true;
} else {
$delayed_loading = false;
}
foreach ($attrs as $arg_name => $arg_value) {
if (is_bool($arg_value))
$arg_value = $arg_value ? 'true' : 'false';
$arg_list[] = "'$arg_name' => $arg_value";
}
$this->_add_plugin('insert', $name, $delayed_loading);
$_params = "array('args' => array(".implode(', ', (array)$arg_list)."))";
return "<?php require_once(SMARTY_CORE_DIR . 'core.run_insert_handler.php');\necho smarty_core_run_insert_handler($_params, \$this); ?>" . $this->_additional_newline;
}
/**
* Compile {include ...} tag
*
* @param string $tag_args
* @return string
*/
function _compile_include_tag($tag_args)
{
$attrs = $this->_parse_attrs($tag_args);
$arg_list = array();
if (empty($attrs['file'])) {
$this->_syntax_error("missing 'file' attribute in include tag", E_USER_ERROR, __FILE__, __LINE__);
}
foreach ($attrs as $arg_name => $arg_value) {
if ($arg_name == 'file') {
$include_file = $arg_value;
continue;
} else if ($arg_name == 'assign') {
$assign_var = $arg_value;
continue;
}
if (is_bool($arg_value))
$arg_value = $arg_value ? 'true' : 'false';
$arg_list[] = "'$arg_name' => $arg_value";
}
$output = '<?php ';
if (isset($assign_var)) {
$output .= "ob_start();\n";
}
$output .=
"\$_smarty_tpl_vars = \$this->_tpl_vars;\n";
$_params = "array('smarty_include_tpl_file' => " . $include_file . ", 'smarty_include_vars' => array(".implode(',', (array)$arg_list)."))";
$output .= "\$this->_smarty_include($_params);\n" .
"\$this->_tpl_vars = \$_smarty_tpl_vars;\n" .
"unset(\$_smarty_tpl_vars);\n";
if (isset($assign_var)) {
$output .= "\$this->assign(" . $assign_var . ", ob_get_contents()); ob_end_clean();\n";
}
$output .= ' ?>';
return $output;
}
/**
* Compile {include ...} tag
*
* @param string $tag_args
* @return string
*/
function _compile_include_php_tag($tag_args)
{
$attrs = $this->_parse_attrs($tag_args);
if (empty($attrs['file'])) {
$this->_syntax_error("missing 'file' attribute in include_php tag", E_USER_ERROR, __FILE__, __LINE__);
}
$assign_var = (empty($attrs['assign'])) ? '' : $this->_dequote($attrs['assign']);
$once_var = (empty($attrs['once']) || $attrs['once']=='false') ? 'false' : 'true';
$arg_list = array();
foreach($attrs as $arg_name => $arg_value) {
if($arg_name != 'file' AND $arg_name != 'once' AND $arg_name != 'assign') {
if(is_bool($arg_value))
$arg_value = $arg_value ? 'true' : 'false';
$arg_list[] = "'$arg_name' => $arg_value";
}
}
$_params = "array('smarty_file' => " . $attrs['file'] . ", 'smarty_assign' => '$assign_var', 'smarty_once' => $once_var, 'smarty_include_vars' => array(".implode(',', $arg_list)."))";
return "<?php require_once(SMARTY_CORE_DIR . 'core.smarty_include_php.php');\nsmarty_core_smarty_include_php($_params, \$this); ?>" . $this->_additional_newline;
}
/**
* Compile {section ...} tag
*
* @param string $tag_args
* @return string
*/
function _compile_section_start($tag_args)
{
$attrs = $this->_parse_attrs($tag_args);
$arg_list = array();
$output = '<?php ';
$section_name = $attrs['name'];
if (empty($section_name)) {
$this->_syntax_error("missing section name", E_USER_ERROR, __FILE__, __LINE__);
}
$output .= "unset(\$this->_sections[$section_name]);\n";
$section_props = "\$this->_sections[$section_name]";
foreach ($attrs as $attr_name => $attr_value) {
switch ($attr_name) {
case 'loop':
$output .= "{$section_props}['loop'] = is_array(\$_loop=$attr_value) ? count(\$_loop) : max(0, (int)\$_loop); unset(\$_loop);\n";
break;
case 'show':
if (is_bool($attr_value))
$show_attr_value = $attr_value ? 'true' : 'false';
else
$show_attr_value = "(bool)$attr_value";
$output .= "{$section_props}['show'] = $show_attr_value;\n";
break;
case 'name':
$output .= "{$section_props}['$attr_name'] = $attr_value;\n";
break;
case 'max':
case 'start':
$output .= "{$section_props}['$attr_name'] = (int)$attr_value;\n";
break;
case 'step':
$output .= "{$section_props}['$attr_name'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\n";
break;
default:
$this->_syntax_error("unknown section attribute - '$attr_name'", E_USER_ERROR, __FILE__, __LINE__);
break;
}
}
if (!isset($attrs['show']))
$output .= "{$section_props}['show'] = true;\n";
if (!isset($attrs['loop']))
$output .= "{$section_props}['loop'] = 1;\n";
if (!isset($attrs['max']))
$output .= "{$section_props}['max'] = {$section_props}['loop'];\n";
else
$output .= "if ({$section_props}['max'] < 0)\n" .
" {$section_props}['max'] = {$section_props}['loop'];\n";
if (!isset($attrs['step']))
$output .= "{$section_props}['step'] = 1;\n";
if (!isset($attrs['start']))
$output .= "{$section_props}['start'] = {$section_props}['step'] > 0 ? 0 : {$section_props}['loop']-1;\n";
else {
$output .= "if ({$section_props}['start'] < 0)\n" .
" {$section_props}['start'] = max({$section_props}['step'] > 0 ? 0 : -1, {$section_props}['loop'] + {$section_props}['start']);\n" .
"else\n" .
" {$section_props}['start'] = min({$section_props}['start'], {$section_props}['step'] > 0 ? {$section_props}['loop'] : {$section_props}['loop']-1);\n";
}
$output .= "if ({$section_props}['show']) {\n";
if (!isset($attrs['start']) && !isset($attrs['step']) && !isset($attrs['max'])) {
$output .= " {$section_props}['total'] = {$section_props}['loop'];\n";
} else {
$output .= " {$section_props}['total'] = min(ceil(({$section_props}['step'] > 0 ? {$section_props}['loop'] - {$section_props}['start'] : {$section_props}['start']+1)/abs({$section_props}['step'])), {$section_props}['max']);\n";
}
$output .= " if ({$section_props}['total'] == 0)\n" .
" {$section_props}['show'] = false;\n" .
"} else\n" .
" {$section_props}['total'] = 0;\n";
$output .= "if ({$section_props}['show']):\n";
$output .= "
for ({$section_props}['index'] = {$section_props}['start'], {$section_props}['iteration'] = 1;
{$section_props}['iteration'] <= {$section_props}['total'];
{$section_props}['index'] += {$section_props}['step'], {$section_props}['iteration']++):\n";
$output .= "{$section_props}['rownum'] = {$section_props}['iteration'];\n";
$output .= "{$section_props}['index_prev'] = {$section_props}['index'] - {$section_props}['step'];\n";
$output .= "{$section_props}['index_next'] = {$section_props}['index'] + {$section_props}['step'];\n";
$output .= "{$section_props}['first'] = ({$section_props}['iteration'] == 1);\n";
$output .= "{$section_props}['last'] = ({$section_props}['iteration'] == {$section_props}['total']);\n";
$output .= "?>";
return $output;
}
/**
* Compile {foreach ...} tag.
*
* @param string $tag_args
* @return string
*/
function _compile_foreach_start($tag_args)
{
$attrs = $this->_parse_attrs($tag_args);
$arg_list = array();
if (empty($attrs['from'])) {
return $this->_syntax_error("foreach: missing 'from' attribute", E_USER_ERROR, __FILE__, __LINE__);
}
$from = $attrs['from'];
if (empty($attrs['item'])) {
return $this->_syntax_error("foreach: missing 'item' attribute", E_USER_ERROR, __FILE__, __LINE__);
}
$item = $this->_dequote($attrs['item']);
if (!preg_match('~^\w+$~', $item)) {
return $this->_syntax_error("foreach: 'item' must be a variable name (literal string)", E_USER_ERROR, __FILE__, __LINE__);
}
if (isset($attrs['key'])) {
$key = $this->_dequote($attrs['key']);
if (!preg_match('~^\w+$~', $key)) {
return $this->_syntax_error("foreach: 'key' must to be a variable name (literal string)", E_USER_ERROR, __FILE__, __LINE__);
}
$key_part = "\$this->_tpl_vars['$key'] => ";
} else {
$key = null;
$key_part = '';
}
if (isset($attrs['name'])) {
$name = $attrs['name'];
} else {
$name = null;
}
$output = '<?php ';
$output .= "\$_from = $from; if (!is_array(\$_from) && !is_object(\$_from)) { settype(\$_from, 'array'); }";
if (isset($name)) {
$foreach_props = "\$this->_foreach[$name]";
$output .= "{$foreach_props} = array('total' => count(\$_from), 'iteration' => 0);\n";
$output .= "if ({$foreach_props}['total'] > 0):\n";
$output .= " foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
$output .= " {$foreach_props}['iteration']++;\n";
} else {
$output .= "if (count(\$_from)):\n";
$output .= " foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
}
$output .= '?>';
return $output;
}
/**
* Compile {capture} .. {/capture} tags
*
* @param boolean $start true if this is the {capture} tag
* @param string $tag_args
* @return string
*/
function _compile_capture_tag($start, $tag_args = '')
{
$attrs = $this->_parse_attrs($tag_args);
if ($start) {
$buffer = isset($attrs['name']) ? $attrs['name'] : "'default'";
$assign = isset($attrs['assign']) ? $attrs['assign'] : null;
$append = isset($attrs['append']) ? $attrs['append'] : null;
$output = "<?php ob_start(); ?>";
$this->_capture_stack[] = array($buffer, $assign, $append);
} else {
list($buffer, $assign, $append) = array_pop($this->_capture_stack);
$output = "<?php \$this->_smarty_vars['capture'][$buffer] = ob_get_contents(); ";
if (isset($assign)) {
$output .= " \$this->assign($assign, ob_get_contents());";
}
if (isset($append)) {
$output .= " \$this->append($append, ob_get_contents());";
}
$output .= "ob_end_clean(); ?>";
}
return $output;
}
/**
* Compile {if ...} tag
*
* @param string $tag_args
* @param boolean $elseif if true, uses elseif instead of if
* @return string
*/
function _compile_if_tag($tag_args, $elseif = false)
{
/* Tokenize args for 'if' tag. */
preg_match_all('~(?>
' . $this->_obj_call_regexp . '(?:' . $this->_mod_regexp . '*)? | # valid object call
' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)? | # var or quoted string
\-?0[xX][0-9a-fA-F]+|\-?\d+(?:\.\d+)?|\.\d+|!==|===|==|!=|<>|<<|>>|<=|>=|\&\&|\|\||\(|\)|,|\!|\^|=|\&|\~|<|>|\||\%|\+|\-|\/|\*|\@ | # valid non-word token
\b\w+\b | # valid word token
\S+ # anything else
)~x', $tag_args, $match);
$tokens = $match[0];
if(empty($tokens)) {
$_error_msg = $elseif ? "'elseif'" : "'if'";
$_error_msg .= ' statement requires arguments';
$this->_syntax_error($_error_msg, E_USER_ERROR, __FILE__, __LINE__);
}
// make sure we have balanced parenthesis
$token_count = array_count_values($tokens);
if(isset($token_count['(']) && $token_count['('] != $token_count[')']) {
$this->_syntax_error("unbalanced parenthesis in if statement", E_USER_ERROR, __FILE__, __LINE__);
}
$is_arg_stack = array();
for ($i = 0; $i < count($tokens); $i++) {
$token = &$tokens[$i];
switch (strtolower($token)) {
case '!':
case '%':
case '!==':
case '==':
case '===':
case '>':
case '<':
case '!=':
case '<>':
case '<<':
case '>>':
case '<=':
case '>=':
case '&&':
case '||':
case '|':
case '^':
case '&':
case '~':
case ')':
case ',':
case '+':
case '-':
case '*':
case '/':
case '@':
break;
case 'eq':
$token = '==';
break;
case 'ne':
case 'neq':
$token = '!=';
break;
case 'lt':
$token = '<';
break;
case 'le':
case 'lte':
$token = '<=';
break;
case 'gt':
$token = '>';
break;
case 'ge':
case 'gte':
$token = '>=';
break;
case 'and':
$token = '&&';
break;
case 'or':
$token = '||';
break;
case 'not':
$token = '!';
break;
case 'mod':
$token = '%';
break;
case '(':
array_push($is_arg_stack, $i);
break;
case 'is':
/* If last token was a ')', we operate on the parenthesized
expression. The start of the expression is on the stack.
Otherwise, we operate on the last encountered token. */
if ($tokens[$i-1] == ')') {
$is_arg_start = array_pop($is_arg_stack);
if ($is_arg_start != 0) {
if (preg_match('~^' . $this->_func_regexp . '$~', $tokens[$is_arg_start-1])) {
$is_arg_start--;
}
}
} else
$is_arg_start = $i-1;
/* Construct the argument for 'is' expression, so it knows
what to operate on. */
$is_arg = implode(' ', array_slice($tokens, $is_arg_start, $i - $is_arg_start));
/* Pass all tokens from next one until the end to the
'is' expression parsing function. The function will
return modified tokens, where the first one is the result
of the 'is' expression and the rest are the tokens it
didn't touch. */
$new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1));
/* Replace the old tokens with the new ones. */
array_splice($tokens, $is_arg_start, count($tokens), $new_tokens);
/* Adjust argument start so that it won't change from the
current position for the next iteration. */
$i = $is_arg_start;
break;
default:
if(preg_match('~^' . $this->_func_regexp . '$~', $token) ) {
// function call
if($this->security &&
!in_array($token, $this->security_settings['IF_FUNCS'])) {
$this->_syntax_error("(secure mode) '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__);
}
} elseif(preg_match('~^' . $this->_var_regexp . '$~', $token) && (strpos('+-*/^%&|', substr($token, -1)) === false) && isset($tokens[$i+1]) && $tokens[$i+1] == '(') {
// variable function call
$this->_syntax_error("variable function call '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__);
} elseif(preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)$~', $token)) {
// object or variable
$token = $this->_parse_var_props($token);
} elseif(is_numeric($token)) {
// number, skip it
} else {
$this->_syntax_error("unidentified token '$token'", E_USER_ERROR, __FILE__, __LINE__);
}
break;
}
}
if ($elseif)
return '<?php elseif ('.implode(' ', $tokens).'): ?>';
else
return '<?php if ('.implode(' ', $tokens).'): ?>';
}
function _compile_arg_list($type, $name, $attrs, &$cache_code) {
$arg_list = array();
if (isset($type) && isset($name)
&& isset($this->_plugins[$type])
&& isset($this->_plugins[$type][$name])
&& empty($this->_plugins[$type][$name][4])
&& is_array($this->_plugins[$type][$name][5])
) {
/* we have a list of parameters that should be cached */
$_cache_attrs = $this->_plugins[$type][$name][5];
$_count = $this->_cache_attrs_count++;
$cache_code = "\$_cache_attrs =& \$this->_smarty_cache_attrs('$this->_cache_serial','$_count');";
} else {
/* no parameters are cached */
$_cache_attrs = null;
}
foreach ($attrs as $arg_name => $arg_value) {
if (is_bool($arg_value))
$arg_value = $arg_value ? 'true' : 'false';
if (is_null($arg_value))
$arg_value = 'null';
if ($_cache_attrs && in_array($arg_name, $_cache_attrs)) {
$arg_list[] = "'$arg_name' => (\$this->_cache_including) ? \$_cache_attrs['$arg_name'] : (\$_cache_attrs['$arg_name']=$arg_value)";
} else {
$arg_list[] = "'$arg_name' => $arg_value";
}
}
return $arg_list;
}
/**
* Parse is expression
*
* @param string $is_arg
* @param array $tokens
* @return array
*/
function _parse_is_expr($is_arg, $tokens)
{
$expr_end = 0;
$negate_expr = false;
if (($first_token = array_shift($tokens)) == 'not') {
$negate_expr = true;
$expr_type = array_shift($tokens);
} else
$expr_type = $first_token;
switch ($expr_type) {
case 'even':
if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') {
$expr_end++;
$expr_arg = $tokens[$expr_end++];
$expr = "!(1 & ($is_arg / " . $this->_parse_var_props($expr_arg) . "))";
} else
$expr = "!(1 & $is_arg)";
break;
case 'odd':
if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') {
$expr_end++;
$expr_arg = $tokens[$expr_end++];
$expr = "(1 & ($is_arg / " . $this->_parse_var_props($expr_arg) . "))";
} else
$expr = "(1 & $is_arg)";
break;
case 'div':
if (@$tokens[$expr_end] == 'by') {
$expr_end++;
$expr_arg = $tokens[$expr_end++];
$expr = "!($is_arg % " . $this->_parse_var_props($expr_arg) . ")";
} else {
$this->_syntax_error("expecting 'by' after 'div'", E_USER_ERROR, __FILE__, __LINE__);
}
break;
default:
$this->_syntax_error("unknown 'is' expression - '$expr_type'", E_USER_ERROR, __FILE__, __LINE__);
break;
}
if ($negate_expr) {
$expr = "!($expr)";
}
array_splice($tokens, 0, $expr_end, $expr);
return $tokens;
}
/**
* Parse attribute string
*
* @param string $tag_args
* @return array
*/
function _parse_attrs($tag_args)
{
/* Tokenize tag attributes. */
preg_match_all('~(?:' . $this->_obj_call_regexp . '|' . $this->_qstr_regexp . ' | (?>[^"\'=\s]+)
)+ |
[=]
~x', $tag_args, $match);
$tokens = $match[0];
$attrs = array();
/* Parse state:
0 - expecting attribute name
1 - expecting '='
2 - expecting attribute value (not '=') */
$state = 0;
foreach ($tokens as $token) {
switch ($state) {
case 0:
/* If the token is a valid identifier, we set attribute name
and go to state 1. */
if (preg_match('~^\w+$~', $token)) {
$attr_name = $token;
$state = 1;
} else
$this->_syntax_error("invalid attribute name: '$token'", E_USER_ERROR, __FILE__, __LINE__);
break;
case 1:
/* If the token is '=', then we go to state 2. */
if ($token == '=') {
$state = 2;
} else
$this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__);
break;
case 2:
/* If token is not '=', we set the attribute value and go to
state 0. */
if ($token != '=') {
/* We booleanize the token if it's a non-quoted possible
boolean value. */
if (preg_match('~^(on|yes|true)$~', $token)) {
$token = 'true';
} else if (preg_match('~^(off|no|false)$~', $token)) {
$token = 'false';
} else if ($token == 'null') {
$token = 'null';
} else if (preg_match('~^' . $this->_num_const_regexp . '|0[xX][0-9a-fA-F]+$~', $token)) {
/* treat integer literally */
} else if (!preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . ')*$~', $token)) {
/* treat as a string, double-quote it escaping quotes */
$token = '"'.addslashes($token).'"';
}
$attrs[$attr_name] = $token;
$state = 0;
} else
$this->_syntax_error("'=' cannot be an attribute value", E_USER_ERROR, __FILE__, __LINE__);
break;
}
$last_token = $token;
}
if($state != 0) {
if($state == 1) {
$this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__);
} else {
$this->_syntax_error("missing attribute value", E_USER_ERROR, __FILE__, __LINE__);
}
}
$this->_parse_vars_props($attrs);
return $attrs;
}
/**
* compile multiple variables and section properties tokens into
* PHP code
*
* @param array $tokens
*/
function _parse_vars_props(&$tokens)
{
foreach($tokens as $key => $val) {
$tokens[$key] = $this->_parse_var_props($val);
}
}
/**
* compile single variable and section properties token into
* PHP code
*
* @param string $val
* @param string $tag_attrs
* @return string
*/
function _parse_var_props($val)
{
$val = trim($val);
if(preg_match('~^(' . $this->_obj_call_regexp . '|' . $this->_dvar_regexp . ')(' . $this->_mod_regexp . '*)$~', $val, $match)) {
// $ variable or object
$return = $this->_parse_var($match[1]);
$modifiers = $match[2];
if (!empty($this->default_modifiers) && !preg_match('~(^|\|)smarty:nodefaults($|\|)~',$modifiers)) {
$_default_mod_string = implode('|',(array)$this->default_modifiers);
$modifiers = empty($modifiers) ? $_default_mod_string : $_default_mod_string . '|' . $modifiers;
}
$this->_parse_modifiers($return, $modifiers);
return $return;
} elseif (preg_match('~^' . $this->_db_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
// double quoted text
preg_match('~^(' . $this->_db_qstr_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);
$return = $this->_expand_quoted_text($match[1]);
if($match[2] != '') {
$this->_parse_modifiers($return, $match[2]);
}
return $return;
}
elseif(preg_match('~^' . $this->_num_const_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
// numerical constant
preg_match('~^(' . $this->_num_const_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);
if($match[2] != '') {
$this->_parse_modifiers($match[1], $match[2]);
return $match[1];
}
}
elseif(preg_match('~^' . $this->_si_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
// single quoted text
preg_match('~^(' . $this->_si_qstr_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);
if($match[2] != '') {
$this->_parse_modifiers($match[1], $match[2]);
return $match[1];
}
}
elseif(preg_match('~^' . $this->_cvar_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
// config var
return $this->_parse_conf_var($val);
}
elseif(preg_match('~^' . $this->_svar_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
// section var
return $this->_parse_section_prop($val);
}
elseif(!in_array($val, $this->_permitted_tokens) && !is_numeric($val)) {
// literal string
return $this->_expand_quoted_text('"' . strtr($val, array('\\' => '\\\\', '"' => '\\"')) .'"');
}
return $val;
}
/**
* expand quoted text with embedded variables
*
* @param string $var_expr
* @return string
*/
function _expand_quoted_text($var_expr)
{
// if contains unescaped $, expand it
if(preg_match_all('~(?:\`(?<!\\\\)\$' . $this->_dvar_guts_regexp . '(?:' . $this->_obj_ext_regexp . ')*\`)|(?:(?<!\\\\)\$\w+(\[[a-zA-Z0-9]+\])*)~', $var_expr, $_match)) {
$_match = $_match[0];
$_replace = array();
foreach($_match as $_var) {
$_replace[$_var] = '".(' . $this->_parse_var(str_replace('`','',$_var)) . ')."';
}
$var_expr = strtr($var_expr, $_replace);
$_return = preg_replace('~\.""|(?<!\\\\)""\.~', '', $var_expr);
} else {
$_return = $var_expr;
}
// replace double quoted literal string with single quotes
$_return = preg_replace('~^"([\s\w]+)"$~',"'\\1'",$_return);
return $_return;
}
/**
* parse variable expression into PHP code
*
* @param string $var_expr
* @param string $output
* @return string
*/
function _parse_var($var_expr)
{
$_has_math = false;
$_math_vars = preg_split('~('.$this->_dvar_math_regexp.'|'.$this->_qstr_regexp.')~', $var_expr, -1, PREG_SPLIT_DELIM_CAPTURE);
if(count($_math_vars) > 1) {
$_first_var = "";
$_complete_var = "";
$_output = "";
// simple check if there is any math, to stop recursion (due to modifiers with "xx % yy" as parameter)
foreach($_math_vars as $_k => $_math_var) {
$_math_var = $_math_vars[$_k];
if(!empty($_math_var) || is_numeric($_math_var)) {
// hit a math operator, so process the stuff which came before it
if(preg_match('~^' . $this->_dvar_math_regexp . '$~', $_math_var)) {
$_has_math = true;
if(!empty($_complete_var) || is_numeric($_complete_var)) {
$_output .= $this->_parse_var($_complete_var);
}
// just output the math operator to php
$_output .= $_math_var;
if(empty($_first_var))
$_first_var = $_complete_var;
$_complete_var = "";
} else {
$_complete_var .= $_math_var;
}
}
}
if($_has_math) {
if(!empty($_complete_var) || is_numeric($_complete_var))
$_output .= $this->_parse_var($_complete_var);
// get the modifiers working (only the last var from math + modifier is left)
$var_expr = $_complete_var;
}
}
// prevent cutting of first digit in the number (we _definitly_ got a number if the first char is a digit)
if(is_numeric(substr($var_expr, 0, 1)))
$_var_ref = $var_expr;
else
$_var_ref = substr($var_expr, 1);
if(!$_has_math) {
// get [foo] and .foo and ->foo and (...) pieces
preg_match_all('~(?:^\w+)|' . $this->_obj_params_regexp . '|(?:' . $this->_var_bracket_regexp . ')|->\$?\w+|\.\$?\w+|\S+~', $_var_ref, $match);
$_indexes = $match[0];
$_var_name = array_shift($_indexes);
/* Handle $smarty.* variable references as a special case. */
if ($_var_name == 'smarty') {
/*
* If the reference could be compiled, use the compiled output;
* otherwise, fall back on the $smarty variable generated at
* run-time.
*/
if (($smarty_ref = $this->_compile_smarty_ref($_indexes)) !== null) {
$_output = $smarty_ref;
} else {
$_var_name = substr(array_shift($_indexes), 1);
$_output = "\$this->_smarty_vars['$_var_name']";
}
} elseif(is_numeric($_var_name) && is_numeric(substr($var_expr, 0, 1))) {
// because . is the operator for accessing arrays thru inidizes we need to put it together again for floating point numbers
if(count($_indexes) > 0)
{
$_var_name .= implode("", $_indexes);
$_indexes = array();
}
$_output = $_var_name;
} else {
$_output = "\$this->_tpl_vars['$_var_name']";
}
foreach ($_indexes as $_index) {
if (substr($_index, 0, 1) == '[') {
$_index = substr($_index, 1, -1);
if (is_numeric($_index)) {
$_output .= "[$_index]";
} elseif (substr($_index, 0, 1) == '$') {
if (strpos($_index, '.') !== false) {
$_output .= '[' . $this->_parse_var($_index) . ']';
} else {
$_output .= "[\$this->_tpl_vars['" . substr($_index, 1) . "']]";
}
} else {
$_var_parts = explode('.', $_index);
$_var_section = $_var_parts[0];
$_var_section_prop = isset($_var_parts[1]) ? $_var_parts[1] : 'index';
$_output .= "[\$this->_sections['$_var_section']['$_var_section_prop']]";
}
} else if (substr($_index, 0, 1) == '.') {
if (substr($_index, 1, 1) == '$')
$_output .= "[\$this->_tpl_vars['" . substr($_index, 2) . "']]";
else
$_output .= "['" . substr($_index, 1) . "']";
} else if (substr($_index,0,2) == '->') {
if(substr($_index,2,2) == '__') {
$this->_syntax_error('call to internal object members is not allowed', E_USER_ERROR, __FILE__, __LINE__);
} elseif($this->security && substr($_index, 2, 1) == '_') {
$this->_syntax_error('(secure) call to private object member is not allowed', E_USER_ERROR, __FILE__, __LINE__);
} elseif (substr($_index, 2, 1) == '$') {
if ($this->security) {
$this->_syntax_error('(secure) call to dynamic object member is not allowed', E_USER_ERROR, __FILE__, __LINE__);
} else {
$_output .= '->{(($_var=$this->_tpl_vars[\''.substr($_index,3).'\']) && substr($_var,0,2)!=\'__\') ? $_var : $this->trigger_error("cannot access property \\"$_var\\"")}';
}
} else {
$_output .= $_index;
}
} elseif (substr($_index, 0, 1) == '(') {
$_index = $this->_parse_parenth_args($_index);
$_output .= $_index;
} else {
$_output .= $_index;
}
}
}
return $_output;
}
/**
* parse arguments in function call parenthesis
*
* @param string $parenth_args
* @return string
*/
function _parse_parenth_args($parenth_args)
{
preg_match_all('~' . $this->_param_regexp . '~',$parenth_args, $match);
$orig_vals = $match = $match[0];
$this->_parse_vars_props($match);
$replace = array();
for ($i = 0, $count = count($match); $i < $count; $i++) {
$replace[$orig_vals[$i]] = $match[$i];
}
return strtr($parenth_args, $replace);
}
/**
* parse configuration variable expression into PHP code
*
* @param string $conf_var_expr
*/
function _parse_conf_var($conf_var_expr)
{
$parts = explode('|', $conf_var_expr, 2);
$var_ref = $parts[0];
$modifiers = isset($parts[1]) ? $parts[1] : '';
$var_name = substr($var_ref, 1, -1);
$output = "\$this->_config[0]['vars']['$var_name']";
$this->_parse_modifiers($output, $modifiers);
return $output;
}
/**
* parse section property expression into PHP code
*
* @param string $section_prop_expr
* @return string
*/
function _parse_section_prop($section_prop_expr)
{
$parts = explode('|', $section_prop_expr, 2);
$var_ref = $parts[0];
$modifiers = isset($parts[1]) ? $parts[1] : '';
preg_match('!%(\w+)\.(\w+)%!', $var_ref, $match);
$section_name = $match[1];
$prop_name = $match[2];
$output = "\$this->_sections['$section_name']['$prop_name']";
$this->_parse_modifiers($output, $modifiers);
return $output;
}
/**
* parse modifier chain into PHP code
*
* sets $output to parsed modified chain
* @param string $output
* @param string $modifier_string
*/
function _parse_modifiers(&$output, $modifier_string)
{
preg_match_all('~\|(@?\w+)((?>:(?:'. $this->_qstr_regexp . '|[^|]+))*)~', '|' . $modifier_string, $_match);
list(, $_modifiers, $modifier_arg_strings) = $_match;
for ($_i = 0, $_for_max = count($_modifiers); $_i < $_for_max; $_i++) {
$_modifier_name = $_modifiers[$_i];
if($_modifier_name == 'smarty') {
// skip smarty modifier
continue;
}
preg_match_all('~:(' . $this->_qstr_regexp . '|[^:]+)~', $modifier_arg_strings[$_i], $_match);
$_modifier_args = $_match[1];
if (substr($_modifier_name, 0, 1) == '@') {
$_map_array = false;
$_modifier_name = substr($_modifier_name, 1);
} else {
$_map_array = true;
}
if (empty($this->_plugins['modifier'][$_modifier_name])
&& !$this->_get_plugin_filepath('modifier', $_modifier_name)
&& function_exists($_modifier_name)) {
if ($this->security && !in_array($_modifier_name, $this->security_settings['MODIFIER_FUNCS'])) {
$this->_trigger_fatal_error("[plugin] (secure mode) modifier '$_modifier_name' is not allowed" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
} else {
$this->_plugins['modifier'][$_modifier_name] = array($_modifier_name, null, null, false);
}
}
$this->_add_plugin('modifier', $_modifier_name);
$this->_parse_vars_props($_modifier_args);
if($_modifier_name == 'default') {
// supress notifications of default modifier vars and args
if(substr($output, 0, 1) == '$') {
$output = '@' . $output;
}
if(isset($_modifier_args[0]) && substr($_modifier_args[0], 0, 1) == '$') {
$_modifier_args[0] = '@' . $_modifier_args[0];
}
}
if (count($_modifier_args) > 0)
$_modifier_args = ', '.implode(', ', $_modifier_args);
else
$_modifier_args = '';
if ($_map_array) {
$output = "((is_array(\$_tmp=$output)) ? \$this->_run_mod_handler('$_modifier_name', true, \$_tmp$_modifier_args) : " . $this->_compile_plugin_call('modifier', $_modifier_name) . "(\$_tmp$_modifier_args))";
} else {
$output = $this->_compile_plugin_call('modifier', $_modifier_name)."($output$_modifier_args)";
}
}
}
/**
* add plugin
*
* @param string $type
* @param string $name
* @param boolean? $delayed_loading
*/
function _add_plugin($type, $name, $delayed_loading = null)
{
if (!isset($this->_plugin_info[$type])) {
$this->_plugin_info[$type] = array();
}
if (!isset($this->_plugin_info[$type][$name])) {
$this->_plugin_info[$type][$name] = array($this->_current_file,
$this->_current_line_no,
$delayed_loading);
}
}
/**
* Compiles references of type $smarty.foo
*
* @param string $indexes
* @return string
*/
function _compile_smarty_ref(&$indexes)
{
/* Extract the reference name. */
$_ref = substr($indexes[0], 1);
foreach($indexes as $_index_no=>$_index) {
if (substr($_index, 0, 1) != '.' && $_index_no<2 || !preg_match('~^(\.|\[|->)~', $_index)) {
$this->_syntax_error('$smarty' . implode('', array_slice($indexes, 0, 2)) . ' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__);
}
}
switch ($_ref) {
case 'now':
$compiled_ref = 'time()';
$_max_index = 1;
break;
case 'foreach':
array_shift($indexes);
$_var = $this->_parse_var_props(substr($indexes[0], 1));
$_propname = substr($indexes[1], 1);
$_max_index = 1;
switch ($_propname) {
case 'index':
array_shift($indexes);
$compiled_ref = "(\$this->_foreach[$_var]['iteration']-1)";
break;
case 'first':
array_shift($indexes);
$compiled_ref = "(\$this->_foreach[$_var]['iteration'] <= 1)";
break;
case 'last':
array_shift($indexes);
$compiled_ref = "(\$this->_foreach[$_var]['iteration'] == \$this->_foreach[$_var]['total'])";
break;
case 'show':
array_shift($indexes);
$compiled_ref = "(\$this->_foreach[$_var]['total'] > 0)";
break;
default:
unset($_max_index);
$compiled_ref = "\$this->_foreach[$_var]";
}
break;
case 'section':
array_shift($indexes);
$_var = $this->_parse_var_props(substr($indexes[0], 1));
$compiled_ref = "\$this->_sections[$_var]";
break;
case 'get':
if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {
$this->_syntax_error("(secure mode) super global access not permitted",
E_USER_WARNING, __FILE__, __LINE__);
return;
}
$compiled_ref = "\$_GET";
break;
case 'post':
if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {
$this->_syntax_error("(secure mode) super global access not permitted",
E_USER_WARNING, __FILE__, __LINE__);
return;
}
$compiled_ref = "\$_POST";
break;
case 'cookies':
if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {
$this->_syntax_error("(secure mode) super global access not permitted",
E_USER_WARNING, __FILE__, __LINE__);
return;
}
$compiled_ref = "\$_COOKIE";
break;
case 'env':
if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {
$this->_syntax_error("(secure mode) super global access not permitted",
E_USER_WARNING, __FILE__, __LINE__);
return;
}
$compiled_ref = "\$_ENV";
break;
case 'server':
if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {
$this->_syntax_error("(secure mode) super global access not permitted",
E_USER_WARNING, __FILE__, __LINE__);
return;
}
$compiled_ref = "\$_SERVER";
break;
case 'session':
if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {
$this->_syntax_error("(secure mode) super global access not permitted",
E_USER_WARNING, __FILE__, __LINE__);
return;
}
$compiled_ref = "\$_SESSION";
break;
/*
* These cases are handled either at run-time or elsewhere in the
* compiler.
*/
case 'request':
if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {
$this->_syntax_error("(secure mode) super global access not permitted",
E_USER_WARNING, __FILE__, __LINE__);
return;
}
if ($this->request_use_auto_globals) {
$compiled_ref = "\$_REQUEST";
break;
} else {
$this->_init_smarty_vars = true;
}
return null;
case 'capture':
return null;
case 'template':
$compiled_ref = "'" . addslashes($this->_current_file) . "'";
$_max_index = 1;
break;
case 'version':
$compiled_ref = "'$this->_version'";
$_max_index = 1;
break;
case 'const':
if ($this->security && !$this->security_settings['ALLOW_CONSTANTS']) {
$this->_syntax_error("(secure mode) constants not permitted",
E_USER_WARNING, __FILE__, __LINE__);
return;
}
array_shift($indexes);
if (preg_match('!^\.\w+$!', $indexes[0])) {
$compiled_ref = '@' . substr($indexes[0], 1);
} else {
$_val = $this->_parse_var_props(substr($indexes[0], 1));
$compiled_ref = '@constant(' . $_val . ')';
}
$_max_index = 1;
break;
case 'config':
$compiled_ref = "\$this->_config[0]['vars']";
$_max_index = 3;
break;
case 'ldelim':
$compiled_ref = "'$this->left_delimiter'";
break;
case 'rdelim':
$compiled_ref = "'$this->right_delimiter'";
break;
default:
$this->_syntax_error('$smarty.' . $_ref . ' is an unknown reference', E_USER_ERROR, __FILE__, __LINE__);
break;
}
if (isset($_max_index) && count($indexes) > $_max_index) {
$this->_syntax_error('$smarty' . implode('', $indexes) .' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__);
}
array_shift($indexes);
return $compiled_ref;
}
/**
* compiles call to plugin of type $type with name $name
* returns a string containing the function-name or method call
* without
gitextract_vqbfnmbo/ ├── .gitignore ├── README.md ├── TODO ├── add.php ├── auth.php ├── docs/ │ ├── services.md │ └── services_ref.md ├── edit.php ├── hook.php ├── index.php ├── lib/ │ ├── auth.php │ ├── config.php.example │ ├── config_env.php │ ├── data.php │ ├── data_files.php │ ├── data_redis.php │ ├── http.php │ ├── init.php │ ├── service.php │ └── smarty/ │ ├── Config_File.class.php │ ├── Smarty.class.php │ ├── Smarty_Compiler.class.php │ ├── debug.tpl │ ├── internals/ │ │ ├── core.assemble_plugin_filepath.php │ │ ├── core.assign_smarty_interface.php │ │ ├── core.create_dir_structure.php │ │ ├── core.display_debug_console.php │ │ ├── core.get_include_path.php │ │ ├── core.get_microtime.php │ │ ├── core.get_php_resource.php │ │ ├── core.is_secure.php │ │ ├── core.is_trusted.php │ │ ├── core.load_plugins.php │ │ ├── core.load_resource_plugin.php │ │ ├── core.process_cached_inserts.php │ │ ├── core.process_compiled_include.php │ │ ├── core.read_cache_file.php │ │ ├── core.rm_auto.php │ │ ├── core.rmdir.php │ │ ├── core.run_insert_handler.php │ │ ├── core.smarty_include_php.php │ │ ├── core.write_cache_file.php │ │ ├── core.write_compiled_include.php │ │ ├── core.write_compiled_resource.php │ │ └── core.write_file.php │ └── plugins/ │ ├── block.textformat.php │ ├── compiler.assign.php │ ├── function.assign_debug_info.php │ ├── function.config_load.php │ ├── function.counter.php │ ├── function.cycle.php │ ├── function.debug.php │ ├── function.eval.php │ ├── function.fetch.php │ ├── function.html_checkboxes.php │ ├── function.html_image.php │ ├── function.html_options.php │ ├── function.html_radios.php │ ├── function.html_select_date.php │ ├── function.html_select_time.php │ ├── function.html_table.php │ ├── function.mailto.php │ ├── function.math.php │ ├── function.popup.php │ ├── function.popup_init.php │ ├── modifier.capitalize.php │ ├── modifier.cat.php │ ├── modifier.count_characters.php │ ├── modifier.count_paragraphs.php │ ├── modifier.count_sentences.php │ ├── modifier.count_words.php │ ├── modifier.date_format.php │ ├── modifier.debug_print_var.php │ ├── modifier.default.php │ ├── modifier.escape.php │ ├── modifier.indent.php │ ├── modifier.lower.php │ ├── modifier.nl2br.php │ ├── modifier.regex_replace.php │ ├── modifier.replace.php │ ├── modifier.spacify.php │ ├── modifier.string_format.php │ ├── modifier.strip.php │ ├── modifier.strip_tags.php │ ├── modifier.truncate.php │ ├── modifier.upper.php │ ├── modifier.wordwrap.php │ ├── outputfilter.trimwhitespace.php │ ├── shared.escape_special_chars.php │ └── shared.make_timestamp.php ├── logout.php ├── new.php ├── oauth.php ├── plugins/ │ ├── atlassian_stash_commits/ │ │ ├── plugin.php │ │ └── templates/ │ │ ├── edit.tpl │ │ └── view.tpl │ ├── coveralls/ │ │ ├── plugin.php │ │ └── templates/ │ │ ├── edit.html │ │ └── view.html │ ├── dployio/ │ │ ├── plugin.php │ │ └── templates/ │ │ ├── edit.tpl │ │ └── view.tpl │ ├── fogbugz/ │ │ ├── plugin.php │ │ └── templates/ │ │ ├── edit.html │ │ └── view.html │ ├── github_commits/ │ │ ├── plugin.php │ │ └── templates/ │ │ ├── edit.txt │ │ └── view.txt │ ├── gitlab_commits/ │ │ ├── plugin.php │ │ └── templates/ │ │ ├── edit.tpl │ │ └── view.tpl │ ├── kiln/ │ │ ├── plugin.php │ │ └── templates/ │ │ ├── edit.html │ │ └── view.html │ ├── papertrail/ │ │ ├── plugin.php │ │ └── templates/ │ │ ├── edit.txt │ │ └── view.txt │ ├── plugins_default/ │ │ ├── plugin_name.php │ │ ├── templates/ │ │ │ ├── description.txt │ │ │ ├── edit.txt │ │ │ ├── new.txt │ │ │ └── summary.txt │ │ └── tests/ │ │ └── plugin_tests.php │ ├── semaphore/ │ │ ├── plugin.php │ │ └── templates/ │ │ ├── edit.html │ │ └── view.html │ ├── sentry/ │ │ ├── plugin.php │ │ └── templates/ │ │ ├── edit.html │ │ └── view.html │ └── testflight/ │ ├── plugin.php │ └── templates/ │ ├── edit.html │ └── view.html ├── style.css ├── templates/ │ ├── inc_foot.txt │ ├── inc_head.txt │ ├── inc_left.txt │ ├── page_add.txt │ ├── page_auth.txt │ ├── page_edit.txt │ ├── page_index.txt │ ├── page_login.txt │ ├── page_new.txt │ └── page_view.txt └── view.php
SYMBOL INDEX (327 symbols across 92 files)
FILE: hook.php
function local_replace_header (line 21) | function local_replace_header($m){
FILE: index.php
function local_sort (line 44) | function local_sort($a, $b){
FILE: lib/auth.php
class SlackAuthPlugin (line 3) | class SlackAuthPlugin {
method saveConfig (line 5) | function saveConfig(){
method isUserAuthed (line 9) | function isUserAuthed(){
method getConfigUrl (line 14) | function getConfigUrl(){
FILE: lib/data.php
class SlackData (line 5) | class SlackData {
method get (line 7) | function get($table, $key){
method get_all (line 11) | function get_all($table){
method set (line 15) | function set($table, $key, $value){
method del (line 19) | function del($table, $key){
method clear (line 23) | function clear($table){
FILE: lib/data_files.php
class SlackDataFiles (line 2) | class SlackDataFiles extends SlackData {
method get (line 6) | function get($table, $key){
method get_all (line 15) | function get_all($table){
method set (line 24) | function set($table, $key, $value){
method del (line 32) | function del($table, $key){
method clear (line 40) | function clear($table){
method load (line 48) | private function load($table){
method save (line 71) | private function save($table, $data){
FILE: lib/data_redis.php
class SlackDataRedis (line 2) | class SlackDataRedis extends SlackData {
method SlackDataRedis (line 4) | function SlackDataRedis(){
method get (line 15) | function get($table, $key){
method get_all (line 21) | function get_all($table){
method set (line 35) | function set($table, $key, $value){
method del (line 41) | function del($table, $key){
method clear (line 47) | function clear($table){
FILE: lib/http.php
class SlackHTTP (line 2) | class SlackHTTP {
method get (line 4) | public static function get($url, $headers=array()){
method post (line 24) | public static function post($url, $params=array(), $headers=array()){
method parse_response (line 46) | private static function parse_response($raw, $info){
method parse_headers (line 92) | private static function parse_headers($raw, $first){
method prepare_outgoing_headers (line 128) | private static function prepare_outgoing_headers($headers=array()){
FILE: lib/init.php
function load_plugins (line 34) | function load_plugins(){
function createPluginInstance (line 63) | function createPluginInstance($class_name){
function getPluginInstance (line 76) | function getPluginInstance($iid){
function getAuthPlugin (line 91) | function getAuthPlugin($id){
function dumper (line 104) | function dumper($foo){
function api_call (line 115) | function api_call($method, $args = array()){
function api_channels_list (line 135) | function api_channels_list(){
function verify_auth (line 147) | function verify_auth(){
function split_sets (line 184) | function split_sets($in, $size){
FILE: lib/service.php
class SlackServicePlugin (line 2) | class SlackServicePlugin {
method SlackServicePlugin (line 15) | function SlackServicePlugin(){
method createInstanceId (line 22) | function createInstanceId(){
method setInstanceConfig (line 26) | function setInstanceConfig($iid, $icfg){
method checkRequirements (line 31) | function checkRequirements(){
method getHookUrl (line 41) | function getHookUrl(){
method getEditUrl (line 50) | function getEditUrl(){
method getViewUrl (line 55) | function getViewUrl(){
method dump (line 60) | function dump(){
method saveConfig (line 67) | function saveConfig(){
method deleteMe (line 73) | function deleteMe(){
method postToChannel (line 79) | function postToChannel($text, $extra){
method getLog (line 118) | function getLog(){
method escapeText (line 122) | function escapeText($str){
method escapeLink (line 126) | function escapeLink($url, $label=null){
method onParentInit (line 142) | function onParentInit(){
method regenToken (line 149) | function regenToken(){
method getChannelsList (line 154) | function getChannelsList(){
method onLiveHook (line 159) | function onLiveHook($req){
method onView (line 178) | function onView(){
method onEdit (line 183) | function onEdit(){
method getLabel (line 188) | function getLabel(){
method onInit (line 193) | function onInit(){
method onHook (line 197) | function onHook($request){
method iconUrl (line 205) | function iconUrl($size=32, $abs=false){
FILE: lib/smarty/Config_File.class.php
class Config_File (line 38) | class Config_File {
method Config_File (line 76) | function Config_File($config_path = NULL)
method set_path (line 88) | function set_path($config_path)
method get (line 112) | function get($file_name, $section_name = NULL, $var_name = NULL)
method get_key (line 152) | function &get_key($config_key)
method get_file_names (line 164) | function get_file_names()
method get_section_names (line 176) | function get_section_names($file_name)
method get_var_names (line 195) | function get_var_names($file_name, $section = NULL)
method clear (line 217) | function clear($file_name = NULL)
method load_file (line 233) | function load_file($file_name, $prepend_path = true)
method set_file_contents (line 260) | function set_file_contents($config_file, $contents)
method parse_contents (line 271) | function parse_contents($contents)
method _set_config_var (line 352) | function _set_config_var(&$container, $var_name, $var_value, $booleanize)
method _trigger_error_msg (line 386) | function _trigger_error_msg($error_msg, $error_type = E_USER_WARNING)
FILE: lib/smarty/Smarty.class.php
class Smarty (line 64) | class Smarty
method Smarty (line 569) | function Smarty()
method assign (line 581) | function assign($tpl_var, $value = null)
method assign_by_ref (line 601) | function assign_by_ref($tpl_var, &$value)
method append (line 613) | function append($tpl_var, $value=null, $merge=false)
method append_by_ref (line 653) | function append_by_ref($tpl_var, &$value, $merge=false)
method clear_assign (line 675) | function clear_assign($tpl_var)
method register_function (line 691) | function register_function($function, $function_impl, $cacheable=true,...
method unregister_function (line 703) | function unregister_function($function)
method register_object (line 717) | function register_object($object, &$object_impl, $allowed = array(), $...
method unregister_object (line 730) | function unregister_object($object)
method register_block (line 742) | function register_block($block, $block_impl, $cacheable=true, $cache_a...
method unregister_block (line 753) | function unregister_block($block)
method register_compiler_function (line 764) | function register_compiler_function($function, $function_impl, $cachea...
method unregister_compiler_function (line 775) | function unregister_compiler_function($function)
method register_modifier (line 786) | function register_modifier($modifier, $modifier_impl)
method unregister_modifier (line 797) | function unregister_modifier($modifier)
method register_resource (line 808) | function register_resource($type, $functions)
method unregister_resource (line 833) | function unregister_resource($type)
method register_prefilter (line 844) | function register_prefilter($function)
method unregister_prefilter (line 855) | function unregister_prefilter($function)
method register_postfilter (line 866) | function register_postfilter($function)
method unregister_postfilter (line 877) | function unregister_postfilter($function)
method register_outputfilter (line 888) | function register_outputfilter($function)
method unregister_outputfilter (line 899) | function unregister_outputfilter($function)
method load_filter (line 910) | function load_filter($type, $name)
method clear_cache (line 936) | function clear_cache($tpl_file = null, $cache_id = null, $compile_id =...
method clear_all_cache (line 968) | function clear_all_cache($exp_time = null)
method is_cached (line 982) | function is_cached($tpl_file, $cache_id = null, $compile_id = null)
method clear_all_assign (line 1004) | function clear_all_assign()
method clear_compiled_tpl (line 1019) | function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp...
method template_exists (line 1039) | function template_exists($tpl_file)
method get_template_vars (line 1052) | function &get_template_vars($name=null)
method get_config_vars (line 1072) | function &get_config_vars($name=null)
method trigger_error (line 1091) | function trigger_error($error_msg, $error_type = E_USER_WARNING)
method display (line 1105) | function display($resource_name, $cache_id = null, $compile_id = null)
method fetch (line 1118) | function fetch($resource_name, $cache_id = null, $compile_id = null, $...
method config_load (line 1320) | function config_load($file, $section = null, $scope = 'global')
method get_registered_object (line 1332) | function &get_registered_object($name) {
method clear_config (line 1347) | function clear_config($var = null)
method _get_plugin_filepath (line 1365) | function _get_plugin_filepath($type, $name)
method _is_compiled (line 1379) | function _is_compiled($resource_name, $compile_path)
method _compile_resource (line 1412) | function _compile_resource($resource_name, $compile_path)
method _compile_source (line 1449) | function _compile_source($resource_name, &$source_content, &$compiled_...
method _get_compile_path (line 1512) | function _get_compile_path($resource_name)
method _fetch_resource_info (line 1532) | function _fetch_resource_info(&$params)
method _parse_resource_name (line 1616) | function _parse_resource_name(&$params)
method _run_mod_handler (line 1677) | function _run_mod_handler()
method _dequote (line 1698) | function _dequote($string)
method _read_file (line 1714) | function _read_file($filename)
method _get_auto_filename (line 1738) | function _get_auto_filename($auto_base, $auto_source = null, $auto_id ...
method _unlink (line 1770) | function _unlink($resource, $exp_time = null)
method _get_auto_id (line 1788) | function _get_auto_id($cache_id=null, $compile_id=null) {
method _trigger_fatal_error (line 1807) | function _trigger_fatal_error($error_msg, $tpl_file = null, $tpl_line ...
method _process_compiled_include_callback (line 1827) | function _process_compiled_include_callback($match) {
method _smarty_include (line 1846) | function _smarty_include($params)
method _smarty_cache_attrs (line 1896) | function &_smarty_cache_attrs($cache_serial, $count) {
method _include (line 1919) | function _include($filename, $once=false, $params=null)
method _eval (line 1933) | function _eval($code, $params=null)
method _get_filter_name (line 1944) | function _get_filter_name($function)
FILE: lib/smarty/Smarty_Compiler.class.php
class Smarty_Compiler (line 35) | class Smarty_Compiler extends Smarty {
method Smarty_Compiler (line 81) | function Smarty_Compiler()
method _compile_file (line 225) | function _compile_file($resource_name, $source_content, &$compiled_con...
method _compile_tag (line 435) | function _compile_tag($template_tag)
method _compile_compiler_tag (line 606) | function _compile_compiler_tag($tag_command, $tag_args, &$output)
method _compile_block_tag (line 675) | function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$...
method _compile_custom_tag (line 766) | function _compile_custom_tag($tag_command, $tag_args, $tag_modifier, &...
method _compile_registered_object_tag (line 839) | function _compile_registered_object_tag($tag_command, $attrs, $tag_mod...
method _compile_insert_tag (line 931) | function _compile_insert_tag($tag_args)
method _compile_include_tag (line 969) | function _compile_include_tag($tag_args)
method _compile_include_php_tag (line 1022) | function _compile_include_php_tag($tag_args)
method _compile_section_start (line 1054) | function _compile_section_start($tag_args)
method _compile_foreach_start (line 1159) | function _compile_foreach_start($tag_args)
method _compile_capture_tag (line 1220) | function _compile_capture_tag($start, $tag_args = '')
method _compile_if_tag (line 1253) | function _compile_if_tag($tag_args, $elseif = false)
method _compile_arg_list (line 1423) | function _compile_arg_list($type, $name, $attrs, &$cache_code) {
method _parse_is_expr (line 1463) | function _parse_is_expr($is_arg, $tokens)
method _parse_attrs (line 1524) | function _parse_attrs($tag_args)
method _parse_vars_props (line 1608) | function _parse_vars_props(&$tokens)
method _parse_var_props (line 1623) | function _parse_var_props($val)
method _expand_quoted_text (line 1683) | function _expand_quoted_text($var_expr)
method _parse_var (line 1709) | function _parse_var($var_expr)
method _parse_parenth_args (line 1844) | function _parse_parenth_args($parenth_args)
method _parse_conf_var (line 1861) | function _parse_conf_var($conf_var_expr)
method _parse_section_prop (line 1882) | function _parse_section_prop($section_prop_expr)
method _parse_modifiers (line 1907) | function _parse_modifiers(&$output, $modifier_string)
method _add_plugin (line 1976) | function _add_plugin($type, $name, $delayed_loading = null)
method _compile_smarty_ref (line 1995) | function _compile_smarty_ref(&$indexes)
method _compile_plugin_call (line 2186) | function _compile_plugin_call($type, $name) {
method _load_filters (line 2210) | function _load_filters()
method _quote_replace (line 2241) | function _quote_replace($string)
method _syntax_error (line 2254) | function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=n...
method _push_cacheable_state (line 2266) | function _push_cacheable_state($type, $name) {
method _pop_cacheable_state (line 2284) | function _pop_cacheable_state($type, $name) {
method _push_tag (line 2298) | function _push_tag($open_tag)
method _pop_tag (line 2309) | function _pop_tag($close_tag)
function _smarty_sort_length (line 2351) | function _smarty_sort_length($a, $b)
FILE: lib/smarty/internals/core.assemble_plugin_filepath.php
function smarty_core_assemble_plugin_filepath (line 15) | function smarty_core_assemble_plugin_filepath($params, &$smarty)
FILE: lib/smarty/internals/core.assign_smarty_interface.php
function smarty_core_assign_smarty_interface (line 17) | function smarty_core_assign_smarty_interface($params, &$smarty)
FILE: lib/smarty/internals/core.create_dir_structure.php
function smarty_core_create_dir_structure (line 16) | function smarty_core_create_dir_structure($params, &$smarty)
FILE: lib/smarty/internals/core.display_debug_console.php
function smarty_core_display_debug_console (line 17) | function smarty_core_display_debug_console($params, &$smarty)
FILE: lib/smarty/internals/core.get_include_path.php
function smarty_core_get_include_path (line 19) | function smarty_core_get_include_path(&$params, &$smarty)
FILE: lib/smarty/internals/core.get_microtime.php
function smarty_core_get_microtime (line 12) | function smarty_core_get_microtime($params, &$smarty)
FILE: lib/smarty/internals/core.get_php_resource.php
function smarty_core_get_php_resource (line 18) | function smarty_core_get_php_resource(&$params, &$smarty)
FILE: lib/smarty/internals/core.is_secure.php
function smarty_core_is_secure (line 18) | function smarty_core_is_secure($params, &$smarty)
FILE: lib/smarty/internals/core.is_trusted.php
function smarty_core_is_trusted (line 18) | function smarty_core_is_trusted($params, &$smarty)
FILE: lib/smarty/internals/core.load_plugins.php
function smarty_core_load_plugins (line 16) | function smarty_core_load_plugins($params, &$smarty)
FILE: lib/smarty/internals/core.load_resource_plugin.php
function smarty_core_load_resource_plugin (line 16) | function smarty_core_load_resource_plugin($params, &$smarty)
FILE: lib/smarty/internals/core.process_cached_inserts.php
function smarty_core_process_cached_inserts (line 14) | function smarty_core_process_cached_inserts($params, &$smarty)
FILE: lib/smarty/internals/core.process_compiled_include.php
function smarty_core_process_compiled_include (line 17) | function smarty_core_process_compiled_include($params, &$smarty)
FILE: lib/smarty/internals/core.read_cache_file.php
function smarty_core_read_cache_file (line 21) | function smarty_core_read_cache_file(&$params, &$smarty)
FILE: lib/smarty/internals/core.rm_auto.php
function smarty_core_rm_auto (line 20) | function smarty_core_rm_auto($params, &$smarty)
FILE: lib/smarty/internals/core.rmdir.php
function smarty_core_rmdir (line 20) | function smarty_core_rmdir($params, &$smarty)
FILE: lib/smarty/internals/core.run_insert_handler.php
function smarty_core_run_insert_handler (line 14) | function smarty_core_run_insert_handler($params, &$smarty)
FILE: lib/smarty/internals/core.smarty_include_php.php
function smarty_core_smarty_include_php (line 21) | function smarty_core_smarty_include_php($params, &$smarty)
FILE: lib/smarty/internals/core.write_cache_file.php
function smarty_core_write_cache_file (line 21) | function smarty_core_write_cache_file($params, &$smarty)
FILE: lib/smarty/internals/core.write_compiled_include.php
function smarty_core_write_compiled_include (line 16) | function smarty_core_write_compiled_include($params, &$smarty)
FILE: lib/smarty/internals/core.write_compiled_resource.php
function smarty_core_write_compiled_resource (line 15) | function smarty_core_write_compiled_resource($params, &$smarty)
FILE: lib/smarty/internals/core.write_file.php
function smarty_core_write_file (line 16) | function smarty_core_write_file($params, &$smarty)
FILE: lib/smarty/plugins/block.textformat.php
function smarty_block_textformat (line 31) | function smarty_block_textformat($params, $content, &$smarty)
FILE: lib/smarty/plugins/compiler.assign.php
function smarty_compiler_assign (line 21) | function smarty_compiler_assign($tag_attrs, &$compiler)
FILE: lib/smarty/plugins/function.assign_debug_info.php
function smarty_function_assign_debug_info (line 19) | function smarty_function_assign_debug_info($params, &$smarty)
FILE: lib/smarty/plugins/function.config_load.php
function smarty_function_config_load (line 27) | function smarty_function_config_load($params, &$smarty)
FILE: lib/smarty/plugins/function.counter.php
function smarty_function_counter (line 22) | function smarty_function_counter($params, &$smarty)
FILE: lib/smarty/plugins/function.cycle.php
function smarty_function_cycle (line 44) | function smarty_function_cycle($params, &$smarty)
FILE: lib/smarty/plugins/function.debug.php
function smarty_function_debug (line 24) | function smarty_function_debug($params, &$smarty)
FILE: lib/smarty/plugins/function.eval.php
function smarty_function_eval (line 21) | function smarty_function_eval($params, &$smarty)
FILE: lib/smarty/plugins/function.fetch.php
function smarty_function_fetch (line 23) | function smarty_function_fetch($params, &$smarty)
FILE: lib/smarty/plugins/function.html_checkboxes.php
function smarty_function_html_checkboxes (line 41) | function smarty_function_html_checkboxes($params, &$smarty)
function smarty_function_html_checkboxes_output (line 126) | function smarty_function_html_checkboxes_output($name, $value, $output, ...
FILE: lib/smarty/plugins/function.html_image.php
function smarty_function_html_image (line 37) | function smarty_function_html_image($params, &$smarty)
FILE: lib/smarty/plugins/function.html_options.php
function smarty_function_html_options (line 30) | function smarty_function_html_options($params, &$smarty)
function smarty_function_html_options_optoutput (line 98) | function smarty_function_html_options_optoutput($key, $value, $selected) {
function smarty_function_html_options_optgroup (line 111) | function smarty_function_html_options_optgroup($key, $values, $selected) {
FILE: lib/smarty/plugins/function.html_radios.php
function smarty_function_html_radios (line 41) | function smarty_function_html_radios($params, &$smarty)
function smarty_function_html_radios_output (line 130) | function smarty_function_html_radios_output($name, $value, $output, $sel...
FILE: lib/smarty/plugins/function.html_select_date.php
function smarty_function_html_select_date (line 38) | function smarty_function_html_select_date($params, &$smarty)
FILE: lib/smarty/plugins/function.html_select_time.php
function smarty_function_html_select_time (line 24) | function smarty_function_html_select_time($params, &$smarty)
FILE: lib/smarty/plugins/function.html_table.php
function smarty_function_html_table (line 49) | function smarty_function_html_table($params, &$smarty)
function smarty_function_html_table_cycle (line 164) | function smarty_function_html_table_cycle($name, $var, $no) {
FILE: lib/smarty/plugins/function.mailto.php
function smarty_function_mailto (line 50) | function smarty_function_mailto($params, &$smarty)
FILE: lib/smarty/plugins/function.math.php
function smarty_function_math (line 22) | function smarty_function_math($params, &$smarty)
FILE: lib/smarty/plugins/function.popup.php
function smarty_function_popup (line 22) | function smarty_function_popup($params, &$smarty)
FILE: lib/smarty/plugins/function.popup_init.php
function smarty_function_popup_init (line 22) | function smarty_function_popup_init($params, &$smarty)
FILE: lib/smarty/plugins/modifier.capitalize.php
function smarty_modifier_capitalize (line 21) | function smarty_modifier_capitalize($string, $uc_digits = false)
function smarty_modifier_capitalize_ucfirst (line 27) | function smarty_modifier_capitalize_ucfirst($string, $uc_digits = null)
FILE: lib/smarty/plugins/modifier.cat.php
function smarty_modifier_cat (line 26) | function smarty_modifier_cat($string, $cat)
FILE: lib/smarty/plugins/modifier.count_characters.php
function smarty_modifier_count_characters (line 22) | function smarty_modifier_count_characters($string, $include_spaces = false)
FILE: lib/smarty/plugins/modifier.count_paragraphs.php
function smarty_modifier_count_paragraphs (line 21) | function smarty_modifier_count_paragraphs($string)
FILE: lib/smarty/plugins/modifier.count_sentences.php
function smarty_modifier_count_sentences (line 21) | function smarty_modifier_count_sentences($string)
FILE: lib/smarty/plugins/modifier.count_words.php
function smarty_modifier_count_words (line 21) | function smarty_modifier_count_words($string)
FILE: lib/smarty/plugins/modifier.date_format.php
function smarty_modifier_date_format (line 31) | function smarty_modifier_date_format($string, $format = '%b %e, %Y', $de...
FILE: lib/smarty/plugins/modifier.debug_print_var.php
function smarty_modifier_debug_print_var (line 23) | function smarty_modifier_debug_print_var($var, $depth = 0, $length = 40)
FILE: lib/smarty/plugins/modifier.default.php
function smarty_modifier_default (line 22) | function smarty_modifier_default($string, $default = '')
FILE: lib/smarty/plugins/modifier.escape.php
function smarty_modifier_escape (line 22) | function smarty_modifier_escape($string, $esc_type = 'html', $char_set =...
FILE: lib/smarty/plugins/modifier.indent.php
function smarty_modifier_indent (line 23) | function smarty_modifier_indent($string,$chars=4,$char=" ")
FILE: lib/smarty/plugins/modifier.lower.php
function smarty_modifier_lower (line 21) | function smarty_modifier_lower($string)
FILE: lib/smarty/plugins/modifier.nl2br.php
function smarty_modifier_nl2br (line 28) | function smarty_modifier_nl2br($string)
FILE: lib/smarty/plugins/modifier.regex_replace.php
function smarty_modifier_regex_replace (line 23) | function smarty_modifier_regex_replace($string, $search, $replace)
function _smarty_regex_replace_check (line 35) | function _smarty_regex_replace_check($search)
FILE: lib/smarty/plugins/modifier.replace.php
function smarty_modifier_replace (line 23) | function smarty_modifier_replace($string, $search, $replace)
FILE: lib/smarty/plugins/modifier.spacify.php
function smarty_modifier_spacify (line 22) | function smarty_modifier_spacify($string, $spacify_char = ' ')
FILE: lib/smarty/plugins/modifier.string_format.php
function smarty_modifier_string_format (line 22) | function smarty_modifier_string_format($string, $format)
FILE: lib/smarty/plugins/modifier.strip.php
function smarty_modifier_strip (line 26) | function smarty_modifier_strip($text, $replace = ' ')
FILE: lib/smarty/plugins/modifier.strip_tags.php
function smarty_modifier_strip_tags (line 22) | function smarty_modifier_strip_tags($string, $replace_with_space = true)
FILE: lib/smarty/plugins/modifier.truncate.php
function smarty_modifier_truncate (line 27) | function smarty_modifier_truncate($string, $length = 80, $etc = '...',
FILE: lib/smarty/plugins/modifier.upper.php
function smarty_modifier_upper (line 21) | function smarty_modifier_upper($string)
FILE: lib/smarty/plugins/modifier.wordwrap.php
function smarty_modifier_wordwrap (line 24) | function smarty_modifier_wordwrap($string,$length=80,$break="\n",$cut=fa...
FILE: lib/smarty/plugins/outputfilter.trimwhitespace.php
function smarty_outputfilter_trimwhitespace (line 28) | function smarty_outputfilter_trimwhitespace($source, &$smarty)
function smarty_outputfilter_trimwhitespace_replace (line 64) | function smarty_outputfilter_trimwhitespace_replace($search_str, $replac...
FILE: lib/smarty/plugins/shared.escape_special_chars.php
function smarty_function_escape_special_chars (line 19) | function smarty_function_escape_special_chars($string)
FILE: lib/smarty/plugins/shared.make_timestamp.php
function smarty_make_timestamp (line 17) | function smarty_make_timestamp($string)
FILE: new.php
function local_sort (line 24) | function local_sort($a, $b){
FILE: plugins/atlassian_stash_commits/plugin.php
class atlassian_stash_commits (line 3) | class atlassian_stash_commits extends SlackServicePlugin {
method onInit (line 12) | function onInit() {
method onView (line 25) | function onView() {
method onEdit (line 29) | function onEdit() {
method onHook (line 48) | function onHook($req) {
method getLabel (line 111) | function getLabel() {
FILE: plugins/coveralls/plugin.php
class coveralls (line 3) | class coveralls extends SlackServicePlugin {
method onView (line 8) | function onView(){
method onEdit (line 12) | function onEdit(){
method onHook (line 32) | function onHook($req){
method sendMessage (line 48) | private function sendMessage($text){
FILE: plugins/dployio/plugin.php
class dployio (line 3) | class dployio extends SlackServicePlugin {
method onInit (line 12) | function onInit() {
method onView (line 25) | function onView() {
method onEdit (line 29) | function onEdit() {
method onHook (line 47) | function onHook($req) {
method getLabel (line 86) | function getLabel() {
FILE: plugins/fogbugz/plugin.php
class fogbugz (line 12) | class fogbugz extends SlackServicePlugin
method onInit (line 21) | public function onInit() {
method onView (line 34) | public function onView() {
method getLabel (line 38) | public function getLabel() {
method onEdit (line 42) | public function onEdit() {
method onHook (line 62) | public function onHook($req) {
method sendMessage (line 77) | private function sendMessage($text) {
FILE: plugins/github_commits/plugin.php
class github_commits (line 3) | class github_commits extends SlackServicePlugin {
method onInit (line 12) | function onInit(){
method onView (line 26) | function onView(){
method onEdit (line 31) | function onEdit(){
method onHook (line 52) | function onHook($req){
method getLabel (line 151) | function getLabel(){
method sendMessage (line 155) | private function sendMessage($text){
FILE: plugins/gitlab_commits/plugin.php
class gitlab_commits (line 3) | class gitlab_commits extends SlackServicePlugin {
method onInit (line 12) | function onInit() {
method onView (line 25) | function onView() {
method onEdit (line 29) | function onEdit() {
method onHook (line 47) | function onHook($req) {
method getLabel (line 103) | function getLabel() {
FILE: plugins/kiln/plugin.php
class kiln (line 17) | class kiln extends SlackServicePlugin
method onInit (line 26) | public function onInit() {
method onView (line 39) | public function onView() {
method getLabel (line 43) | public function getLabel() {
method onEdit (line 47) | public function onEdit() {
method onHook (line 67) | public function onHook($req) {
method sendMessage (line 106) | private function sendMessage($text) {
FILE: plugins/papertrail/plugin.php
class papertrail (line 6) | class papertrail extends SlackServicePlugin {
method onInit (line 15) | function onInit() {
method onView (line 30) | function onView() {
method onEdit (line 34) | function onEdit() {
method onHook (line 54) | function onHook($req) {
method searchLink (line 122) | private function searchLink($search) {
method renderEvent (line 130) | private function renderEvent($e) {
method getLabel (line 138) | function getLabel() {
method sendMessage (line 142) | private function sendMessage($text) {
FILE: plugins/plugins_default/plugin_name.php
class MyServicePlugin (line 3) | class MyServicePlugin extends SlackServicePlugin {
FILE: plugins/semaphore/plugin.php
class semaphore (line 12) | class semaphore extends SlackServicePlugin
method onInit (line 21) | public function onInit() {
method onView (line 33) | public function onView() {
method getLabel (line 37) | public function getLabel() {
method onEdit (line 41) | public function onEdit() {
method onHook (line 60) | public function onHook($req) {
method sendMessage (line 84) | private function sendMessage($text) {
FILE: plugins/sentry/plugin.php
class sentry (line 3) | class sentry extends SlackServicePlugin {
method onView (line 8) | function onView(){
method onEdit (line 12) | function onEdit(){
method onHook (line 32) | function onHook($req){
method sendMessage (line 45) | private function sendMessage($text){
FILE: plugins/testflight/plugin.php
class testflight (line 4) | class testflight extends SlackServicePlugin
method onInit (line 13) | public function onInit() {
method onView (line 25) | public function onView() {
method getLabel (line 29) | public function getLabel() {
method onEdit (line 33) | public function onEdit() {
method onHook (line 52) | public function onHook($req) {
method sendMessage (line 77) | private function sendMessage($text) {
Condensed preview — 144 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (455K chars).
[
{
"path": ".gitignore",
"chars": 22,
"preview": "lib/config.php\ndata/*\n"
},
{
"path": "README.md",
"chars": 2983,
"preview": "# DEPRECATED\nPlease note that this project is no longer maintained.\n\n# Hammock\n=========\n\nHammock is a standalone webapp"
},
{
"path": "TODO",
"chars": 335,
"preview": "* Style config pages to match current slack.com (somewhat done)\n* Log all incoming webhooks and what we sent as a result"
},
{
"path": "add.php",
"chars": 727,
"preview": "<?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']"
},
{
"path": "auth.php",
"chars": 327,
"preview": "<?php\n\t$dir = dirname(__FILE__);\n\tinclude(\"$dir/lib/init.php\");\n\n\tload_plugins();\n\n\t$instance = getAuthPlugin($_GET['id'"
},
{
"path": "docs/services.md",
"chars": 3644,
"preview": "# Creating your own integration service\n\nThis document describes how to create new Slack integrations. If you're just \nl"
},
{
"path": "docs/services_ref.md",
"chars": 4047,
"preview": "# Service Plugin Reference\n\nThis documentation lists all of the currently available properties and methods\nfor custom `S"
},
{
"path": "edit.php",
"chars": 362,
"preview": "<?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 = getPlu"
},
{
"path": "hook.php",
"chars": 1514,
"preview": "<?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\tf"
},
{
"path": "index.php",
"chars": 1098,
"preview": "<?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 "
},
{
"path": "lib/auth.php",
"chars": 273,
"preview": "<?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"
},
{
"path": "lib/config.php.example",
"chars": 906,
"preview": "<?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'] "
},
{
"path": "lib/config_env.php",
"chars": 937,
"preview": "<?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 ("
},
{
"path": "lib/data.php",
"chars": 385,
"preview": "<?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"
},
{
"path": "lib/data_files.php",
"chars": 2105,
"preview": "<?php\n\tclass SlackDataFiles extends SlackData {\n\n\t\tprivate $cache = array();\n\n\t\tfunction get($table, $key){\n\n\t\t\tif (!iss"
},
{
"path": "lib/data_redis.php",
"chars": 1053,
"preview": "<?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 ="
},
{
"path": "lib/http.php",
"chars": 3316,
"preview": "<?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_ar"
},
{
"path": "lib/init.php",
"chars": 4468,
"preview": "<?php\n\terror_reporting((E_ALL | E_STRICT) ^ E_NOTICE);\n\n\tdefine('HAMMOCK_ROOT', realpath(dirname(__FILE__).\"/..\"));\n\n\tif"
},
{
"path": "lib/service.php",
"chars": 4107,
"preview": "<?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\tp"
},
{
"path": "lib/smarty/Config_File.class.php",
"chars": 12918,
"preview": "<?php\n\n/**\n * Config_File class.\n *\n * This library is free software; you can redistribute it and/or\n * modify it under "
},
{
"path": "lib/smarty/Smarty.class.php",
"chars": 63629,
"preview": "<?php\n\n/**\n * Project: Smarty: the PHP compiling template engine\n * File: Smarty.class.php\n *\n * This library"
},
{
"path": "lib/smarty/Smarty_Compiler.class.php",
"chars": 94452,
"preview": "<?php\n\n/**\n * Project: Smarty: the PHP compiling template engine\n * File: Smarty_Compiler.class.php\n *\n * Thi"
},
{
"path": "lib/smarty/debug.tpl",
"chars": 3562,
"preview": "{* Smarty *}\n{* debug.tpl, last updated version 2.1.0 *}\n{assign_debug_info}\n{capture assign=debug_output}\n<!DOCTYPE htm"
},
{
"path": "lib/smarty/internals/core.assemble_plugin_filepath.php",
"chars": 1949,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * assemble filepath of requested plugin\n "
},
{
"path": "lib/smarty/internals/core.assign_smarty_interface.php",
"chars": 1258,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty assign_smarty_interface core plu"
},
{
"path": "lib/smarty/internals/core.create_dir_structure.php",
"chars": 2507,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * create full directory structure\n *\n * @"
},
{
"path": "lib/smarty/internals/core.display_debug_console.php",
"chars": 1583,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty debug_console function plugin\n *"
},
{
"path": "lib/smarty/internals/core.get_include_path.php",
"chars": 1002,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Get path to file from include_path\n *\n "
},
{
"path": "lib/smarty/internals/core.get_microtime.php",
"chars": 360,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Get seconds and microseconds\n * @return"
},
{
"path": "lib/smarty/internals/core.get_php_resource.php",
"chars": 2467,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Retrieves PHP script resource\n *\n * set"
},
{
"path": "lib/smarty/internals/core.is_secure.php",
"chars": 1694,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * determines if a resource is secure or n"
},
{
"path": "lib/smarty/internals/core.is_trusted.php",
"chars": 1284,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * determines if a resource is trusted or "
},
{
"path": "lib/smarty/internals/core.load_plugins.php",
"chars": 4429,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Load requested plugins\n *\n * @param arr"
},
{
"path": "lib/smarty/internals/core.load_resource_plugin.php",
"chars": 2147,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * load a resource plugin\n *\n * @param str"
},
{
"path": "lib/smarty/internals/core.process_cached_inserts.php",
"chars": 2464,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Replace cached inserts with the actual "
},
{
"path": "lib/smarty/internals/core.process_compiled_include.php",
"chars": 1025,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Replace nocache-tags by results of the "
},
{
"path": "lib/smarty/internals/core.read_cache_file.php",
"chars": 3604,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * read a cache file, determine if it need"
},
{
"path": "lib/smarty/internals/core.rm_auto.php",
"chars": 2286,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * delete an automagically created file by"
},
{
"path": "lib/smarty/internals/core.rmdir.php",
"chars": 1444,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * delete a dir recursively (level=0 -> ke"
},
{
"path": "lib/smarty/internals/core.run_insert_handler.php",
"chars": 2656,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Handle insert tags\n *\n * @param array $"
},
{
"path": "lib/smarty/internals/core.smarty_include_php.php",
"chars": 1602,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * called for included php files within te"
},
{
"path": "lib/smarty/internals/core.write_cache_file.php",
"chars": 3647,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Prepend the cache information to the ca"
},
{
"path": "lib/smarty/internals/core.write_compiled_include.php",
"chars": 3130,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Extract non-cacheable parts out of comp"
},
{
"path": "lib/smarty/internals/core.write_compiled_resource.php",
"chars": 1081,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * write the compiled resource\n *\n * @para"
},
{
"path": "lib/smarty/internals/core.write_file.php",
"chars": 1524,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * write out a file to disk\n *\n * @param s"
},
{
"path": "lib/smarty/plugins/block.textformat.php",
"chars": 2843,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty {textformat}{/textformat} block "
},
{
"path": "lib/smarty/plugins/compiler.assign.php",
"chars": 1123,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty {assign} compiler function plugi"
},
{
"path": "lib/smarty/plugins/function.assign_debug_info.php",
"chars": 1162,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty {assign_debug_info} function plu"
},
{
"path": "lib/smarty/plugins/function.config_load.php",
"chars": 6158,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty {config_load} function plugin\n *"
},
{
"path": "lib/smarty/plugins/function.counter.php",
"chars": 1772,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {counter} function plugin\n *\n *"
},
{
"path": "lib/smarty/plugins/function.cycle.php",
"chars": 3314,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty {cycle} function plugin\n *\n * Ty"
},
{
"path": "lib/smarty/plugins/function.debug.php",
"chars": 835,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {debug} function plugin\n *\n * T"
},
{
"path": "lib/smarty/plugins/function.eval.php",
"chars": 1014,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {eval} function plugin\n *\n * Ty"
},
{
"path": "lib/smarty/plugins/function.fetch.php",
"chars": 8757,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {fetch} plugin\n *\n * Type: "
},
{
"path": "lib/smarty/plugins/function.html_checkboxes.php",
"chars": 4381,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {html_checkboxes} function plug"
},
{
"path": "lib/smarty/plugins/function.html_image.php",
"chars": 4783,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {html_image} function plugin\n *"
},
{
"path": "lib/smarty/plugins/function.html_options.php",
"chars": 3797,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {html_options} function plugin\n"
},
{
"path": "lib/smarty/plugins/function.html_radios.php",
"chars": 4841,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {html_radios} function plugin\n "
},
{
"path": "lib/smarty/plugins/function.html_select_date.php",
"chars": 11955,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty {html_select_date} plugin\n *\n * "
},
{
"path": "lib/smarty/plugins/function.html_select_time.php",
"chars": 7262,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {html_select_time} function plu"
},
{
"path": "lib/smarty/plugins/function.html_table.php",
"chars": 5343,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {html_table} function plugin\n *"
},
{
"path": "lib/smarty/plugins/function.mailto.php",
"chars": 5236,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {mailto} function plugin\n *\n * "
},
{
"path": "lib/smarty/plugins/function.math.php",
"chars": 2649,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {math} function plugin\n *\n * Ty"
},
{
"path": "lib/smarty/plugins/function.popup.php",
"chars": 3280,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {popup} function plugin\n *\n * T"
},
{
"path": "lib/smarty/plugins/function.popup_init.php",
"chars": 979,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty {popup_init} function plugin\n *"
},
{
"path": "lib/smarty/plugins/modifier.capitalize.php",
"chars": 1037,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty capitalize modifier plugin\n *\n "
},
{
"path": "lib/smarty/plugins/modifier.cat.php",
"chars": 623,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty cat modifier plugin\n *\n * Type:"
},
{
"path": "lib/smarty/plugins/modifier.count_characters.php",
"chars": 743,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty count_characters modifier plugi"
},
{
"path": "lib/smarty/plugins/modifier.count_paragraphs.php",
"chars": 630,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty count_paragraphs modifier plugi"
},
{
"path": "lib/smarty/plugins/modifier.count_sentences.php",
"chars": 653,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty count_sentences modifier plugin"
},
{
"path": "lib/smarty/plugins/modifier.count_words.php",
"chars": 751,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty count_words modifier plugin\n *\n"
},
{
"path": "lib/smarty/plugins/modifier.date_format.php",
"chars": 1782,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Include the {@link shared.make_timestam"
},
{
"path": "lib/smarty/plugins/modifier.debug_print_var.php",
"chars": 2884,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty debug_print_var modifier plugin"
},
{
"path": "lib/smarty/plugins/modifier.default.php",
"chars": 635,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty default modifier plugin\n *\n * T"
},
{
"path": "lib/smarty/plugins/modifier.escape.php",
"chars": 2751,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty escape modifier plugin\n *\n * Ty"
},
{
"path": "lib/smarty/plugins/modifier.indent.php",
"chars": 567,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty indent modifier plugin\n *\n * Ty"
},
{
"path": "lib/smarty/plugins/modifier.lower.php",
"chars": 481,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty lower modifier plugin\n *\n * Typ"
},
{
"path": "lib/smarty/plugins/modifier.nl2br.php",
"chars": 717,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty plugin\n *\n * Type: modifier"
},
{
"path": "lib/smarty/plugins/modifier.regex_replace.php",
"chars": 1255,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty regex_replace modifier plugin\n "
},
{
"path": "lib/smarty/plugins/modifier.replace.php",
"chars": 585,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty replace modifier plugin\n *\n * T"
},
{
"path": "lib/smarty/plugins/modifier.spacify.php",
"chars": 644,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty spacify modifier plugin\n *\n * T"
},
{
"path": "lib/smarty/plugins/modifier.string_format.php",
"chars": 579,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty string_format modifier plugin\n "
},
{
"path": "lib/smarty/plugins/modifier.strip.php",
"chars": 742,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty strip modifier plugin\n *\n * Typ"
},
{
"path": "lib/smarty/plugins/modifier.strip_tags.php",
"chars": 676,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty strip_tags modifier plugin\n *\n "
},
{
"path": "lib/smarty/plugins/modifier.truncate.php",
"chars": 1324,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty truncate modifier plugin\n *\n * "
},
{
"path": "lib/smarty/plugins/modifier.upper.php",
"chars": 481,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty upper modifier plugin\n *\n * Typ"
},
{
"path": "lib/smarty/plugins/modifier.wordwrap.php",
"chars": 613,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Smarty wordwrap modifier plugin\n *\n * "
},
{
"path": "lib/smarty/plugins/outputfilter.trimwhitespace.php",
"chars": 2669,
"preview": "<?php\n/**\n * Smarty plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n/**\n * Smarty trimwhitespace outputfilter plug"
},
{
"path": "lib/smarty/plugins/shared.escape_special_chars.php",
"chars": 774,
"preview": "<?php\n/**\n * Smarty shared plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * escape_special_chars common fun"
},
{
"path": "lib/smarty/plugins/shared.make_timestamp.php",
"chars": 1167,
"preview": "<?php\n/**\n * Smarty shared plugin\n * @package Smarty\n * @subpackage plugins\n */\n\n\n/**\n * Function: smarty_make_timestamp"
},
{
"path": "logout.php",
"chars": 209,
"preview": "<?php\n\t$dir = dirname(__FILE__);\n\tinclude(\"$dir/lib/init.php\");\n\n\n\t$expire = time();\n\n\tsetcookie($cfg['cookie_name'], ''"
},
{
"path": "new.php",
"chars": 735,
"preview": "<?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"
},
{
"path": "oauth.php",
"chars": 1747,
"preview": "<?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 = arr"
},
{
"path": "plugins/atlassian_stash_commits/plugin.php",
"chars": 3481,
"preview": "<?php\n\nclass atlassian_stash_commits extends SlackServicePlugin {\n\n public $name = \"Atlassian Stash Commits\";\n pub"
},
{
"path": "plugins/atlassian_stash_commits/templates/edit.tpl",
"chars": 605,
"preview": "<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n\n <p>Channel to post to: <select name=\"channel\">\n {"
},
{
"path": "plugins/atlassian_stash_commits/templates/view.tpl",
"chars": 461,
"preview": "{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 "
},
{
"path": "plugins/coveralls/plugin.php",
"chars": 1668,
"preview": "<?php\n\nclass coveralls extends SlackServicePlugin {\n\n public $name = \"Coveralls\";\n public $desc = \"Code coverage h"
},
{
"path": "plugins/coveralls/templates/edit.html",
"chars": 467,
"preview": "\n\n<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n\n<p>Channel to post to: <select name=\"channel\">\n{foreach fr"
},
{
"path": "plugins/coveralls/templates/view.html",
"chars": 360,
"preview": "<p>In your Coveralls repo, choose \"Notifications\" -> \"Webhook\" and add the following URL:</p>\n\n<p><code>{$this->getHo"
},
{
"path": "plugins/dployio/plugin.php",
"chars": 2451,
"preview": "<?php\n\nclass dployio extends SlackServicePlugin {\n\n public $name = \"Dploy.io deployments\";\n public $desc = \"Automa"
},
{
"path": "plugins/dployio/templates/edit.tpl",
"chars": 508,
"preview": "<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n\n <p>Channel to post to: <select name=\"channel\">\n {"
},
{
"path": "plugins/dployio/templates/view.tpl",
"chars": 407,
"preview": "{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 "
},
{
"path": "plugins/fogbugz/plugin.php",
"chars": 2946,
"preview": "<?php\n//\n// FogBugz Case Events Web Hook\n// ============================================================================"
},
{
"path": "plugins/fogbugz/templates/edit.html",
"chars": 748,
"preview": "<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n <p>\n Channel to post to:\n <select name=\"cha"
},
{
"path": "plugins/fogbugz/templates/view.html",
"chars": 1089,
"preview": "\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>Yo"
},
{
"path": "plugins/github_commits/plugin.php",
"chars": 4212,
"preview": "<?php\n\n\tclass github_commits extends SlackServicePlugin {\n\n\t\tpublic $name = \"Github Commits\";\n\t\tpublic $desc = \"Source c"
},
{
"path": "plugins/github_commits/templates/edit.txt",
"chars": 557,
"preview": "\n\n<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n\n<p>Channel to post to: <select name=\"channel\">\n{foreach fr"
},
{
"path": "plugins/github_commits/templates/view.txt",
"chars": 519,
"preview": "\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>G"
},
{
"path": "plugins/gitlab_commits/plugin.php",
"chars": 3032,
"preview": "<?php\n\nclass gitlab_commits extends SlackServicePlugin {\n\n public $name = \"GitLab Commits\";\n public $desc = \"Sourc"
},
{
"path": "plugins/gitlab_commits/templates/edit.tpl",
"chars": 508,
"preview": "<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n\n <p>Channel to post to: <select name=\"channel\">\n {"
},
{
"path": "plugins/gitlab_commits/templates/view.tpl",
"chars": 407,
"preview": "{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 "
},
{
"path": "plugins/kiln/plugin.php",
"chars": 4103,
"preview": "<?php\n//\n// Kiln Commit Integration Web Hook\n// ========================================================================"
},
{
"path": "plugins/kiln/templates/edit.html",
"chars": 764,
"preview": "<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n <p>\n Channel to post to:\n <select name=\"cha"
},
{
"path": "plugins/kiln/templates/view.html",
"chars": 1133,
"preview": "\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>Yo"
},
{
"path": "plugins/papertrail/plugin.php",
"chars": 3661,
"preview": "<?php\n\n// author: Luka Kladaric luka@tripcommon.com\n// based on github_commits plugin\n\n\tclass papertrail extends SlackSe"
},
{
"path": "plugins/papertrail/templates/edit.txt",
"chars": 572,
"preview": "\n\n<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n\n<p>Channel to post to: <select name=\"channel\">\n{foreach fr"
},
{
"path": "plugins/papertrail/templates/view.txt",
"chars": 502,
"preview": "{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 "
},
{
"path": "plugins/plugins_default/plugin_name.php",
"chars": 306,
"preview": "<?php\n\n class MyServicePlugin extends SlackServicePlugin {\n\n const NAME = \"My Awesome Service\";\n "
},
{
"path": "plugins/plugins_default/templates/description.txt",
"chars": 107,
"preview": "<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",
"chars": 2221,
"preview": "{if $error}\n <div class=\"alert alert-error\"><i class=\"fa fa-exclamation-circle small_right_margin\"></i> Oops! Tha"
},
{
"path": "plugins/plugins_default/templates/new.txt",
"chars": 793,
"preview": "{if $error}\n <div class=\"alert alert-error\"><i class=\"fa fa-exclamation-circle small_right_margin\"></i> Oops! Tha"
},
{
"path": "plugins/plugins_default/templates/summary.txt",
"chars": 164,
"preview": "Post alerts to <strong>{$this->getChannelName($this->icfg.channel)|escape|default:'<i>unconfigured</i>'}</strong> as <st"
},
{
"path": "plugins/plugins_default/tests/plugin_tests.php",
"chars": 0,
"preview": ""
},
{
"path": "plugins/semaphore/plugin.php",
"chars": 3004,
"preview": "<?php\n//\n// Semaphore Build Statuses Web Hook\n// ======================================================================="
},
{
"path": "plugins/semaphore/templates/edit.html",
"chars": 641,
"preview": "<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n <p>\n Channel to post to:\n <select name=\"cha"
},
{
"path": "plugins/semaphore/templates/view.html",
"chars": 952,
"preview": "{if $smarty.get.newtoken}\n<p class=\"alert\">Your token has been updated - the webhook URL has changed!</p>\n{/if}\n\n<h3>You"
},
{
"path": "plugins/sentry/plugin.php",
"chars": 1546,
"preview": "<?php\n\nclass sentry extends SlackServicePlugin {\n\n public $name = \"Sentry\";\n public $desc = \"Track code exceptions"
},
{
"path": "plugins/sentry/templates/edit.html",
"chars": 467,
"preview": "\n\n<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n\n<p>Channel to post to: <select name=\"channel\">\n{foreach fr"
},
{
"path": "plugins/sentry/templates/view.html",
"chars": 354,
"preview": "<p>In your Sentry project, view Integrations and find WebHooks. Add the following URL:</p>\n\n<p><code>{$this->getHookUrl("
},
{
"path": "plugins/testflight/plugin.php",
"chars": 2634,
"preview": "<?php\n// TestFlight Integration Hook\n//\nclass testflight extends SlackServicePlugin\n{\n public $name = 'TestFlight';\n p"
},
{
"path": "plugins/testflight/templates/edit.html",
"chars": 641,
"preview": "<form action=\"{$this->getEditUrl()}&save=1\" method=\"post\">\n <p>\n Channel to post to:\n <select name=\"cha"
},
{
"path": "plugins/testflight/templates/view.html",
"chars": 897,
"preview": "\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>Yo"
},
{
"path": "style.css",
"chars": 7052,
"preview": "body {\r\n\tcolor: #555459;\r\n\tfont-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\r\n\tfont-size: 16px;\r\n\tline-height"
},
{
"path": "templates/inc_foot.txt",
"chars": 25,
"preview": "</div>\n\n</body>\n</html>\n\n"
},
{
"path": "templates/inc_head.txt",
"chars": 881,
"preview": "{'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 i"
},
{
"path": "templates/inc_left.txt",
"chars": 452,
"preview": "<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 "
},
{
"path": "templates/page_add.txt",
"chars": 417,
"preview": "{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"
},
{
"path": "templates/page_auth.txt",
"chars": 112,
"preview": "{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",
"chars": 260,
"preview": "{include file='inc_head.txt'}\n\n<h2>Edit Service</h2>\n\n{*<div class=\"alert\">\n\t<strong>This integration has been disabled."
},
{
"path": "templates/page_index.txt",
"chars": 1120,
"preview": "{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 In"
},
{
"path": "templates/page_login.txt",
"chars": 937,
"preview": "{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>$cf"
},
{
"path": "templates/page_new.txt",
"chars": 853,
"preview": "{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 I"
},
{
"path": "templates/page_view.txt",
"chars": 1003,
"preview": "{include file='inc_head.txt'}\n\n<h2>Service Instance</h2>\n\n{*<div class=\"alert\">\n\t<strong>This integration has been disab"
},
{
"path": "view.php",
"chars": 625,
"preview": "<?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 = getPlu"
}
]
About this extraction
This page contains the full source code of the tinyspeck/hammock GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 144 files (415.9 KB), approximately 109.7k tokens, and a symbol index with 327 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.