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 ================================================ 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 ================================================ 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: this is my service
"; } 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:This is my service!
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 ================================================ checkRequirements(); $smarty->assign('instance', $instance); $smarty->assign('html', $instance->onEdit()); $smarty->display('page_edit.txt'); ================================================ FILE: hook.php ================================================ $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 ================================================ 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 ================================================ 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 ================================================ 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 ================================================ 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 ================================================ $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 ================================================ 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 "";
if (is_resource($foo)){
var_dump($foo);
}else{
echo HtmlSpecialChars(var_export($foo, 1));
}
echo "\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
================================================
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 "No information for this plugin.
"; } function onEdit(){ return "No config for this plugin.
"; } 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 ================================================ * @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 ================================================ * @author Andrei Zmievskiarray('escape:"htmlall"');
*
* @var array
*/
var $default_modifiers = array();
/**
* This is the resource type to be used when not specified
* at the beginning of the resource path. examples:
* $smarty->display('file:index.tpl');
* $smarty->display('db:index.tpl');
* $smarty->display('index.tpl'); // will use default resource type
* {include file="file:index.tpl"}
* {include file="db:index.tpl"}
* {include file="index.tpl"} {* will use default resource type *}
*
* @var array
*/
var $default_resource_type = 'file';
/**
* The function used for cache file handling. If not set, built-in caching is used.
*
* @var null|string function name
*/
var $cache_handler_func = null;
/**
* This indicates which filters are automatically loaded into Smarty.
*
* @var array array of filter names
*/
var $autoload_filters = array();
/**#@+
* @var boolean
*/
/**
* This tells if config file vars of the same name overwrite each other or not.
* if disabled, same name variables are accumulated in an array.
*/
var $config_overwrite = true;
/**
* This tells whether or not to automatically booleanize config file variables.
* If enabled, then the strings "on", "true", and "yes" are treated as boolean
* true, and "off", "false" and "no" are treated as boolean false.
*/
var $config_booleanize = true;
/**
* This tells whether hidden sections [.foobar] are readable from the
* tempalates or not. Normally you would never allow this since that is
* the point behind hidden sections: the application can access them, but
* the templates cannot.
*/
var $config_read_hidden = false;
/**
* This tells whether or not automatically fix newlines in config files.
* It basically converts \r (mac) or \r\n (dos) to \n
*/
var $config_fix_newlines = true;
/**#@-*/
/**
* If a template cannot be found, this PHP function will be executed.
* Useful for creating templates on-the-fly or other special action.
*
* @var string function name
*/
var $default_template_handler_func = '';
/**
* The file that contains the compiler class. This can a full
* pathname, or relative to the php_include path.
*
* @var string
*/
var $compiler_file = 'Smarty_Compiler.class.php';
/**
* The class used for compiling templates.
*
* @var string
*/
var $compiler_class = 'Smarty_Compiler';
/**
* The class used to load config vars.
*
* @var string
*/
var $config_class = 'Config_File';
/**#@+
* END Smarty Configuration Section
* There should be no need to touch anything below this line.
* @access private
*/
/**
* where assigned template vars are kept
*
* @var array
*/
var $_tpl_vars = array();
/**
* stores run-time $smarty.* vars
*
* @var null|array
*/
var $_smarty_vars = null;
/**
* keeps track of sections
*
* @var array
*/
var $_sections = array();
/**
* keeps track of foreach blocks
*
* @var array
*/
var $_foreach = array();
/**
* keeps track of tag hierarchy
*
* @var array
*/
var $_tag_stack = array();
/**
* configuration object
*
* @var Config_file
*/
var $_conf_obj = null;
/**
* loaded configuration settings
*
* @var array
*/
var $_config = array(array('vars' => array(), 'files' => array()));
/**
* md5 checksum of the string 'Smarty'
*
* @var string
*/
var $_smarty_md5 = 'f8d698aea36fcbead2b9d5359ffca76f';
/**
* Smarty version number
*
* @var string
*/
var $_version = '2.6.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
================================================
* @author Andrei Zmievski no templates included
{/section}| {ldelim}${$_debug_keys[vars]|escape:'html'}{rdelim} | {$_debug_vals[vars]|@debug_print_var} |
|---|---|
no template variables assigned |
| {ldelim}#{$_debug_config_keys[config_vars]|escape:'html'}#{rdelim} | {$_debug_config_vals[config_vars]|@debug_print_var} |
|---|---|
no config vars assigned |
* Params: style: string (email)
* indent: integer (0)
* wrap: integer (80)
* wrap_char string ("\n")
* indent_char: string (" ")
* wrap_boundary: boolean (true)
*
* @author Monte Ohrt
* array('file' => required config file name,
* 'section' => optional config file section to load
* 'scope' => local/parent/global
* 'global' => overrides scope, setting to parent if true)
*
* @param Smarty
*/
function smarty_function_config_load($params, &$smarty)
{
if ($smarty->debugging) {
$_params = array();
require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
$_debug_start_time = smarty_core_get_microtime($_params, $smarty);
}
$_file = isset($params['file']) ? $smarty->_dequote($params['file']) : null;
$_section = isset($params['section']) ? $smarty->_dequote($params['section']) : null;
$_scope = isset($params['scope']) ? $smarty->_dequote($params['scope']) : 'global';
$_global = isset($params['global']) ? $smarty->_dequote($params['global']) : false;
if (!isset($_file) || strlen($_file) == 0) {
$smarty->trigger_error("missing 'file' attribute in config_load tag", E_USER_ERROR, __FILE__, __LINE__);
}
if (isset($_scope)) {
if ($_scope != 'local' &&
$_scope != 'parent' &&
$_scope != 'global') {
$smarty->trigger_error("invalid 'scope' attribute value", E_USER_ERROR, __FILE__, __LINE__);
}
} else {
if ($_global) {
$_scope = 'parent';
} else {
$_scope = 'local';
}
}
$_params = array('resource_name' => $_file,
'resource_base_path' => $smarty->config_dir,
'get_source' => false);
$smarty->_parse_resource_name($_params);
$_file_path = $_params['resource_type'] . ':' . $_params['resource_name'];
if (isset($_section))
$_compile_file = $smarty->_get_compile_path($_file_path.'|'.$_section);
else
$_compile_file = $smarty->_get_compile_path($_file_path);
if($smarty->force_compile || !file_exists($_compile_file)) {
$_compile = true;
} elseif ($smarty->compile_check) {
$_params = array('resource_name' => $_file,
'resource_base_path' => $smarty->config_dir,
'get_source' => false);
$_compile = $smarty->_fetch_resource_info($_params) &&
$_params['resource_timestamp'] > filemtime($_compile_file);
} else {
$_compile = false;
}
if($_compile) {
// compile config file
if(!is_object($smarty->_conf_obj)) {
require_once SMARTY_DIR . $smarty->config_class . '.class.php';
$smarty->_conf_obj = new $smarty->config_class();
$smarty->_conf_obj->overwrite = $smarty->config_overwrite;
$smarty->_conf_obj->booleanize = $smarty->config_booleanize;
$smarty->_conf_obj->read_hidden = $smarty->config_read_hidden;
$smarty->_conf_obj->fix_newlines = $smarty->config_fix_newlines;
}
$_params = array('resource_name' => $_file,
'resource_base_path' => $smarty->config_dir,
$_params['get_source'] = true);
if (!$smarty->_fetch_resource_info($_params)) {
return;
}
$smarty->_conf_obj->set_file_contents($_file, $_params['source_content']);
$_config_vars = array_merge($smarty->_conf_obj->get($_file),
$smarty->_conf_obj->get($_file, $_section));
if(function_exists('var_export')) {
$_output = '';
} else {
$_output = ''\\\'', '\\'=>'\\\\')) . '\'); ?>';
}
$_params = (array('compile_path' => $_compile_file, 'compiled_content' => $_output, 'resource_timestamp' => $_params['resource_timestamp']));
require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php');
smarty_core_write_compiled_resource($_params, $smarty);
} else {
include($_compile_file);
}
if ($smarty->caching) {
$smarty->_cache_info['config'][$_file] = true;
}
$smarty->_config[0]['vars'] = @array_merge($smarty->_config[0]['vars'], $_config_vars);
$smarty->_config[0]['files'][$_file] = true;
if ($_scope == 'parent') {
$smarty->_config[1]['vars'] = @array_merge($smarty->_config[1]['vars'], $_config_vars);
$smarty->_config[1]['files'][$_file] = true;
} else if ($_scope == 'global') {
for ($i = 1, $for_max = count($smarty->_config); $i < $for_max; $i++) {
$smarty->_config[$i]['vars'] = @array_merge($smarty->_config[$i]['vars'], $_config_vars);
$smarty->_config[$i]['files'][$_file] = true;
}
}
if ($smarty->debugging) {
$_params = array();
require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
$smarty->_smarty_debug_info[] = array('type' => 'config',
'filename' => $_file.' ['.$_section.'] '.$_scope,
'depth' => $smarty->_inclusion_depth,
'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time);
}
}
/* vim: set expandtab: */
?>
================================================
FILE: lib/smarty/plugins/function.counter.php
================================================
* Name: counter
* {cycle values="#eeeeee,#d0d0d0d"}
* {cycle name=row values="one,two,three" reset=true}
* {cycle name=row}
*
* @link http://smarty.php.net/manual/en/language.function.cycle.php {cycle}
* (Smarty online manual)
* @author Monte Ohrt
* {html_checkboxes values=$ids output=$names}
* {html_checkboxes values=$ids name='box' separator='
' output=$names}
* {html_checkboxes values=$ids checked=$checked separator='
' output=$names}
*
* @link http://smarty.php.net/manual/en/language.function.html.checkboxes.php {html_checkboxes}
* (Smarty online manual)
* @author Christopher Kvarme