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!

Edit settings

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 Zmievski * @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. * * @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. * * @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. * * * @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 "" tags in templates. * possible values: * * * @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: array('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 * @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.'%%%', ''."\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', ''."\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] = ""\'", "\\"=>"\\\\")) . "'; ?>"; 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('\n", $compiled_content); $compiled_content = preg_replace("~(?\n", $compiled_content); // recover legit tags $compiled_content = str_replace($tag_guard, '_cache_serial)) { $compiled_content = "_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 = "_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 = "\n"; $template_header .= $plugins_code; $this->_plugin_info = array(); $this->_plugins_code = $plugins_code; } if ($this->_init_smarty_vars) { $template_header .= "\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 "" . $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 ''; 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 ''; 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 ""; break; case '/section': $_open_tag = $this->_pop_tag('section'); if ($_open_tag == 'sectionelse') return ""; else return ""; case 'foreach': $this->_push_tag('foreach'); return $this->_compile_foreach_start($tag_args); break; case 'foreachelse': $this->_push_tag('foreachelse'); return ""; case '/foreach': $_open_tag = $this->_pop_tag('foreach'); if ($_open_tag == 'foreachelse') return ""; else return ""; 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 ""\'", "\\"=>"\\\\")) . "'; ?>" . $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 ''; } 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 = '_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 = '_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 = '_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 = '_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 '" . $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 "" . $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 = '_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 "" . $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 = '_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 = '_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 = ""; $this->_capture_stack[] = array($buffer, $assign, $append); } else { list($buffer, $assign, $append) = array_pop($this->_capture_stack); $output = "_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 ''; else return ''; } 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('~(?:\`(?_dvar_guts_regexp . '(?:' . $this->_obj_ext_regexp . ')*\`)|(?:(?_parse_var(str_replace('`','',$_var)) . ')."'; } $var_expr = strtr($var_expr, $_replace); $_return = preg_replace('~\.""|(?_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 the paramter-list that would have follow to make the * call valid php-syntax * * @param string $type * @param string $name * @return string */ function _compile_plugin_call($type, $name) { if (isset($this->_plugins[$type][$name])) { /* plugin loaded */ if (is_array($this->_plugins[$type][$name][0])) { return ((is_object($this->_plugins[$type][$name][0][0])) ? "\$this->_plugins['$type']['$name'][0][0]->" /* method callback */ : (string)($this->_plugins[$type][$name][0][0]).'::' /* class callback */ ). $this->_plugins[$type][$name][0][1]; } else { /* function callback */ return $this->_plugins[$type][$name][0]; } } else { /* plugin not loaded -> auto-loadable-plugin */ return 'smarty_'.$type.'_'.$name; } } /** * load pre- and post-filters */ function _load_filters() { if (count($this->_plugins['prefilter']) > 0) { foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) { if ($prefilter === false) { unset($this->_plugins['prefilter'][$filter_name]); $_params = array('plugins' => array(array('prefilter', $filter_name, null, null, false))); require_once(SMARTY_CORE_DIR . 'core.load_plugins.php'); smarty_core_load_plugins($_params, $this); } } } if (count($this->_plugins['postfilter']) > 0) { foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) { if ($postfilter === false) { unset($this->_plugins['postfilter'][$filter_name]); $_params = array('plugins' => array(array('postfilter', $filter_name, null, null, false))); require_once(SMARTY_CORE_DIR . 'core.load_plugins.php'); smarty_core_load_plugins($_params, $this); } } } } /** * Quote subpattern references * * @param string $string * @return string */ function _quote_replace($string) { return strtr($string, array('\\' => '\\\\', '$' => '\\$')); } /** * display Smarty syntax error * * @param string $error_msg * @param integer $error_type * @param string $file * @param integer $line */ function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=null, $line=null) { $this->_trigger_fatal_error("syntax error: $error_msg", $this->_current_file, $this->_current_line_no, $file, $line, $error_type); } /** * check if the compilation changes from cacheable to * non-cacheable state with the beginning of the current * plugin. return php-code to reflect the transition. * @return string */ function _push_cacheable_state($type, $name) { $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4]; if ($_cacheable || 0<$this->_cacheable_state++) return ''; if (!isset($this->_cache_serial)) $this->_cache_serial = md5(uniqid('Smarty')); $_ret = 'if ($this->caching && !$this->_cache_including): echo \'{nocache:' . $this->_cache_serial . '#' . $this->_nocache_count . '}\'; endif;'; return $_ret; } /** * check if the compilation changes from non-cacheable to * cacheable state with the end of the current plugin return * php-code to reflect the transition. * @return string */ function _pop_cacheable_state($type, $name) { $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4]; if ($_cacheable || --$this->_cacheable_state>0) return ''; return 'if ($this->caching && !$this->_cache_including): echo \'{/nocache:' . $this->_cache_serial . '#' . ($this->_nocache_count++) . '}\'; endif;'; } /** * push opening tag-name, file-name and line-number on the tag-stack * @param string the opening tag's name */ function _push_tag($open_tag) { array_push($this->_tag_stack, array($open_tag, $this->_current_line_no)); } /** * pop closing tag-name * raise an error if this stack-top doesn't match with the closing tag * @param string the closing tag's name * @return string the opening tag's name */ function _pop_tag($close_tag) { $message = ''; if (count($this->_tag_stack)>0) { list($_open_tag, $_line_no) = array_pop($this->_tag_stack); if ($close_tag == $_open_tag) { return $_open_tag; } if ($close_tag == 'if' && ($_open_tag == 'else' || $_open_tag == 'elseif' )) { return $this->_pop_tag($close_tag); } if ($close_tag == 'section' && $_open_tag == 'sectionelse') { $this->_pop_tag($close_tag); return $_open_tag; } if ($close_tag == 'foreach' && $_open_tag == 'foreachelse') { $this->_pop_tag($close_tag); return $_open_tag; } if ($_open_tag == 'else' || $_open_tag == 'elseif') { $_open_tag = 'if'; } elseif ($_open_tag == 'sectionelse') { $_open_tag = 'section'; } elseif ($_open_tag == 'foreachelse') { $_open_tag = 'foreach'; } $message = " expected {/$_open_tag} (opened line $_line_no)."; } $this->_syntax_error("mismatched tag {/$close_tag}.$message", E_USER_ERROR, __FILE__, __LINE__); } } /** * compare to values by their string length * * @access private * @param string $a * @param string $b * @return 0|-1|1 */ function _smarty_sort_length($a, $b) { if($a == $b) return 0; if(strlen($a) == strlen($b)) return ($a > $b) ? -1 : 1; return (strlen($a) > strlen($b)) ? -1 : 1; } /* vim: set et: */ ?> ================================================ FILE: lib/smarty/debug.tpl ================================================ {* Smarty *} {* debug.tpl, last updated version 2.1.0 *} {assign_debug_info} {capture assign=debug_output} Smarty Debug Console {literal} {/literal}

Smarty Debug Console

included templates & config files (load time in seconds)

{section name=templates loop=$_debug_tpls} {section name=indent loop=$_debug_tpls[templates].depth}   {/section} {$_debug_tpls[templates].filename|escape:html} {if isset($_debug_tpls[templates].exec_time)} ({$_debug_tpls[templates].exec_time|string_format:"%.5f"}) {if %templates.index% eq 0}(total){/if} {/if}
{sectionelse}

no templates included

{/section}

assigned template variables

{section name=vars loop=$_debug_keys} {sectionelse} {/section}
{ldelim}${$_debug_keys[vars]|escape:'html'}{rdelim} {$_debug_vals[vars]|@debug_print_var}

no template variables assigned

assigned config file variables (outer template scope)

{section name=config_vars loop=$_debug_config_keys} {sectionelse} {/section}
{ldelim}#{$_debug_config_keys[config_vars]|escape:'html'}#{rdelim} {$_debug_config_vals[config_vars]|@debug_print_var}

no config vars assigned

{/capture} {if isset($_smarty_debug_output) and $_smarty_debug_output eq "html"} {$debug_output} {else} {/if} ================================================ FILE: lib/smarty/internals/core.assemble_plugin_filepath.php ================================================ plugins_dir as $_plugin_dir) { $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename; // see if path is relative if (!preg_match("/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/", $_plugin_dir)) { $_relative_paths[] = $_plugin_dir; // relative path, see if it is in the SMARTY_DIR if (@is_readable(SMARTY_DIR . $_plugin_filepath)) { $_return = SMARTY_DIR . $_plugin_filepath; break; } } // try relative to cwd (or absolute) if (@is_readable($_plugin_filepath)) { $_return = $_plugin_filepath; break; } } if($_return === false) { // still not found, try PHP include_path if(isset($_relative_paths)) { foreach ((array)$_relative_paths as $_plugin_dir) { $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename; $_params = array('file_path' => $_plugin_filepath); require_once(SMARTY_CORE_DIR . 'core.get_include_path.php'); if(smarty_core_get_include_path($_params, $smarty)) { $_return = $_params['new_file_path']; break; } } } } $_filepaths_cache[$_plugin_filename] = $_return; return $_return; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.assign_smarty_interface.php ================================================ * Name: assign_smarty_interface
* Purpose: assign the $smarty interface variable * @param array Format: null * @param Smarty */ function smarty_core_assign_smarty_interface($params, &$smarty) { if (isset($smarty->_smarty_vars) && isset($smarty->_smarty_vars['request'])) { return; } $_globals_map = array('g' => 'HTTP_GET_VARS', 'p' => 'HTTP_POST_VARS', 'c' => 'HTTP_COOKIE_VARS', 's' => 'HTTP_SERVER_VARS', 'e' => 'HTTP_ENV_VARS'); $_smarty_vars_request = array(); foreach (preg_split('!!', strtolower($smarty->request_vars_order)) as $_c) { if (isset($_globals_map[$_c])) { $_smarty_vars_request = array_merge($_smarty_vars_request, $GLOBALS[$_globals_map[$_c]]); } } $_smarty_vars_request = @array_merge($_smarty_vars_request, $GLOBALS['HTTP_SESSION_VARS']); $smarty->_smarty_vars['request'] = $_smarty_vars_request; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.create_dir_structure.php ================================================ _dir_perms) && !is_dir($_new_dir)) { $smarty->trigger_error("problem creating directory '" . $_new_dir . "'"); return false; } $_new_dir .= '/'; } } } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.display_debug_console.php ================================================ * Name: display_debug_console
* Purpose: display the javascript debug console window * @param array Format: null * @param Smarty */ function smarty_core_display_debug_console($params, &$smarty) { // we must force compile the debug template in case the environment // changed between separate applications. if(empty($smarty->debug_tpl)) { // set path to debug template from SMARTY_DIR $smarty->debug_tpl = SMARTY_DIR . 'debug.tpl'; if($smarty->security && is_file($smarty->debug_tpl)) { $smarty->secure_dir[] = realpath($smarty->debug_tpl); } $smarty->debug_tpl = 'file:' . SMARTY_DIR . 'debug.tpl'; } $_ldelim_orig = $smarty->left_delimiter; $_rdelim_orig = $smarty->right_delimiter; $smarty->left_delimiter = '{'; $smarty->right_delimiter = '}'; $_compile_id_orig = $smarty->_compile_id; $smarty->_compile_id = null; $_compile_path = $smarty->_get_compile_path($smarty->debug_tpl); if ($smarty->_compile_resource($smarty->debug_tpl, $_compile_path)) { ob_start(); $smarty->_include($_compile_path); $_results = ob_get_contents(); ob_end_clean(); } else { $_results = ''; } $smarty->_compile_id = $_compile_id_orig; $smarty->left_delimiter = $_ldelim_orig; $smarty->right_delimiter = $_rdelim_orig; return $_results; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.get_include_path.php ================================================ ================================================ FILE: lib/smarty/internals/core.get_microtime.php ================================================ ================================================ FILE: lib/smarty/internals/core.get_php_resource.php ================================================ trusted_dir; $smarty->_parse_resource_name($params, $smarty); /* * Find out if the resource exists. */ if ($params['resource_type'] == 'file') { $_readable = false; if(file_exists($params['resource_name']) && is_readable($params['resource_name'])) { $_readable = true; } else { // test for file in include_path $_params = array('file_path' => $params['resource_name']); require_once(SMARTY_CORE_DIR . 'core.get_include_path.php'); if(smarty_core_get_include_path($_params, $smarty)) { $_include_path = $_params['new_file_path']; $_readable = true; } } } else if ($params['resource_type'] != 'file') { $_template_source = null; $_readable = is_callable($smarty->_plugins['resource'][$params['resource_type']][0][0]) && call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][0], array($params['resource_name'], &$_template_source, &$smarty)); } /* * Set the error function, depending on which class calls us. */ if (method_exists($smarty, '_syntax_error')) { $_error_funcc = '_syntax_error'; } else { $_error_funcc = 'trigger_error'; } if ($_readable) { if ($smarty->security) { require_once(SMARTY_CORE_DIR . 'core.is_trusted.php'); if (!smarty_core_is_trusted($params, $smarty)) { $smarty->$_error_funcc('(secure mode) ' . $params['resource_type'] . ':' . $params['resource_name'] . ' is not trusted'); return false; } } } else { $smarty->$_error_funcc($params['resource_type'] . ':' . $params['resource_name'] . ' is not readable'); return false; } if ($params['resource_type'] == 'file') { $params['php_resource'] = $params['resource_name']; } else { $params['php_resource'] = $_template_source; } return true; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.is_secure.php ================================================ security || $smarty->security_settings['INCLUDE_ANY']) { return true; } if ($params['resource_type'] == 'file') { $_rp = realpath($params['resource_name']); if (isset($params['resource_base_path'])) { foreach ((array)$params['resource_base_path'] as $curr_dir) { if ( ($_cd = realpath($curr_dir)) !== false && strncmp($_rp, $_cd, strlen($_cd)) == 0 && substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR ) { return true; } } } if (!empty($smarty->secure_dir)) { foreach ((array)$smarty->secure_dir as $curr_dir) { if ( ($_cd = realpath($curr_dir)) !== false) { if($_cd == $_rp) { return true; } elseif (strncmp($_rp, $_cd, strlen($_cd)) == 0 && substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR) { return true; } } } } } else { // resource is not on local file system return call_user_func_array( $smarty->_plugins['resource'][$params['resource_type']][0][2], array($params['resource_name'], &$smarty)); } return false; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.is_trusted.php ================================================ trusted_dir)) { $_rp = realpath($params['resource_name']); foreach ((array)$smarty->trusted_dir as $curr_dir) { if (!empty($curr_dir) && is_readable ($curr_dir)) { $_cd = realpath($curr_dir); if (strncmp($_rp, $_cd, strlen($_cd)) == 0 && substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR ) { $_smarty_trusted = true; break; } } } } } else { // resource is not on local file system $_smarty_trusted = call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][3], array($params['resource_name'], $smarty)); } return $_smarty_trusted; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.load_plugins.php ================================================ _plugins[$_type][$_name]; /* * We do not load plugin more than once for each instance of Smarty. * The following code checks for that. The plugin can also be * registered dynamically at runtime, in which case template file * and line number will be unknown, so we fill them in. * * The final element of the info array is a flag that indicates * whether the dynamically registered plugin function has been * checked for existence yet or not. */ if (isset($_plugin)) { if (empty($_plugin[3])) { if (!is_callable($_plugin[0])) { $smarty->_trigger_fatal_error("[plugin] $_type '$_name' is not implemented", $_tpl_file, $_tpl_line, __FILE__, __LINE__); } else { $_plugin[1] = $_tpl_file; $_plugin[2] = $_tpl_line; $_plugin[3] = true; if (!isset($_plugin[4])) $_plugin[4] = true; /* cacheable */ } } continue; } else if ($_type == 'insert') { /* * For backwards compatibility, we check for insert functions in * the symbol table before trying to load them as a plugin. */ $_plugin_func = 'insert_' . $_name; if (function_exists($_plugin_func)) { $_plugin = array($_plugin_func, $_tpl_file, $_tpl_line, true, false); continue; } } $_plugin_file = $smarty->_get_plugin_filepath($_type, $_name); if (! $_found = ($_plugin_file != false)) { $_message = "could not load plugin file '$_type.$_name.php'\n"; } /* * If plugin file is found, it -must- provide the properly named * plugin function. In case it doesn't, simply output the error and * do not fall back on any other method. */ if ($_found) { include_once $_plugin_file; $_plugin_func = 'smarty_' . $_type . '_' . $_name; if (!function_exists($_plugin_func)) { $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", $_tpl_file, $_tpl_line, __FILE__, __LINE__); continue; } } /* * In case of insert plugins, their code may be loaded later via * 'script' attribute. */ else if ($_type == 'insert' && $_delayed_loading) { $_plugin_func = 'smarty_' . $_type . '_' . $_name; $_found = true; } /* * Plugin specific processing and error checking. */ if (!$_found) { if ($_type == 'modifier') { /* * In case modifier falls back on using PHP functions * directly, we only allow those specified in the security * context. */ if ($smarty->security && !in_array($_name, $smarty->security_settings['MODIFIER_FUNCS'])) { $_message = "(secure mode) modifier '$_name' is not allowed"; } else { if (!function_exists($_name)) { $_message = "modifier '$_name' is not implemented"; } else { $_plugin_func = $_name; $_found = true; } } } else if ($_type == 'function') { /* * This is a catch-all situation. */ $_message = "unknown tag - '$_name'"; } } if ($_found) { $smarty->_plugins[$_type][$_name] = array($_plugin_func, $_tpl_file, $_tpl_line, true, true); } else { // output error $smarty->_trigger_fatal_error('[plugin] ' . $_message, $_tpl_file, $_tpl_line, __FILE__, __LINE__); } } } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.load_resource_plugin.php ================================================ _plugins['resource'][$params['type']]; if (isset($_plugin)) { if (!$_plugin[1] && count($_plugin[0])) { $_plugin[1] = true; foreach ($_plugin[0] as $_plugin_func) { if (!is_callable($_plugin_func)) { $_plugin[1] = false; break; } } } if (!$_plugin[1]) { $smarty->_trigger_fatal_error("[plugin] resource '" . $params['type'] . "' is not implemented", null, null, __FILE__, __LINE__); } return; } $_plugin_file = $smarty->_get_plugin_filepath('resource', $params['type']); $_found = ($_plugin_file != false); if ($_found) { /* * If the plugin file is found, it -must- provide the properly named * plugin functions. */ include_once($_plugin_file); /* * Locate functions that we require the plugin to provide. */ $_resource_ops = array('source', 'timestamp', 'secure', 'trusted'); $_resource_funcs = array(); foreach ($_resource_ops as $_op) { $_plugin_func = 'smarty_resource_' . $params['type'] . '_' . $_op; if (!function_exists($_plugin_func)) { $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", null, null, __FILE__, __LINE__); return; } else { $_resource_funcs[] = $_plugin_func; } } $smarty->_plugins['resource'][$params['type']] = array($_resource_funcs, true); } } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.process_cached_inserts.php ================================================ _smarty_md5.'{insert_cache (.*)}'.$smarty->_smarty_md5.'!Uis', $params['results'], $match); list($cached_inserts, $insert_args) = $match; for ($i = 0, $for_max = count($cached_inserts); $i < $for_max; $i++) { if ($smarty->debugging) { $_params = array(); require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); $debug_start_time = smarty_core_get_microtime($_params, $smarty); } $args = unserialize($insert_args[$i]); $name = $args['name']; if (isset($args['script'])) { $_params = array('resource_name' => $smarty->_dequote($args['script'])); require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php'); if(!smarty_core_get_php_resource($_params, $smarty)) { return false; } $resource_type = $_params['resource_type']; $php_resource = $_params['php_resource']; if ($resource_type == 'file') { $smarty->_include($php_resource, true); } else { $smarty->_eval($php_resource); } } $function_name = $smarty->_plugins['insert'][$name][0]; if (empty($args['assign'])) { $replace = $function_name($args, $smarty); } else { $smarty->assign($args['assign'], $function_name($args, $smarty)); $replace = ''; } $params['results'] = substr_replace($params['results'], $replace, strpos($params['results'], $cached_inserts[$i]), strlen($cached_inserts[$i])); if ($smarty->debugging) { $_params = array(); require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); $smarty->_smarty_debug_info[] = array('type' => 'insert', 'filename' => 'insert_'.$name, 'depth' => $smarty->_inclusion_depth, 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $debug_start_time); } } return $params['results']; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.process_compiled_include.php ================================================ _cache_including; $smarty->_cache_including = true; $_return = $params['results']; foreach ($smarty->_cache_info['cache_serials'] as $_include_file_path=>$_cache_serial) { $smarty->_include($_include_file_path, true); } foreach ($smarty->_cache_info['cache_serials'] as $_include_file_path=>$_cache_serial) { $_return = preg_replace_callback('!(\{nocache\:('.$_cache_serial.')#(\d+)\})!s', array(&$smarty, '_process_compiled_include_callback'), $_return); } $smarty->_cache_including = $_cache_including; return $_return; } ?> ================================================ FILE: lib/smarty/internals/core.read_cache_file.php ================================================ force_compile) { // force compile enabled, always regenerate return false; } if (isset($content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']])) { list($params['results'], $smarty->_cache_info) = $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']]; return true; } if (!empty($smarty->cache_handler_func)) { // use cache_handler function call_user_func_array($smarty->cache_handler_func, array('read', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null)); } else { // use local cache file $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']); $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id); $params['results'] = $smarty->_read_file($_cache_file); } if (empty($params['results'])) { // nothing to parse (error?), regenerate cache return false; } $_contents = $params['results']; $_info_start = strpos($_contents, "\n") + 1; $_info_len = (int)substr($_contents, 0, $_info_start - 1); $_cache_info = unserialize(substr($_contents, $_info_start, $_info_len)); $params['results'] = substr($_contents, $_info_start + $_info_len); if ($smarty->caching == 2 && isset ($_cache_info['expires'])){ // caching by expiration time if ($_cache_info['expires'] > -1 && (time() > $_cache_info['expires'])) { // cache expired, regenerate return false; } } else { // caching by lifetime if ($smarty->cache_lifetime > -1 && (time() - $_cache_info['timestamp'] > $smarty->cache_lifetime)) { // cache expired, regenerate return false; } } if ($smarty->compile_check) { $_params = array('get_source' => false, 'quiet'=>true); foreach (array_keys($_cache_info['template']) as $_template_dep) { $_params['resource_name'] = $_template_dep; if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) { // template file has changed, regenerate cache return false; } } if (isset($_cache_info['config'])) { $_params = array('resource_base_path' => $smarty->config_dir, 'get_source' => false, 'quiet'=>true); foreach (array_keys($_cache_info['config']) as $_config_dep) { $_params['resource_name'] = $_config_dep; if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) { // config file has changed, regenerate cache return false; } } } } $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']] = array($params['results'], $_cache_info); $smarty->_cache_info = $_cache_info; return true; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.rm_auto.php ================================================ $params['auto_base'], 'level' => 0, 'exp_time' => $params['exp_time'] ); require_once(SMARTY_CORE_DIR . 'core.rmdir.php'); $_res = smarty_core_rmdir($_params, $smarty); } else { $_tname = $smarty->_get_auto_filename($params['auto_base'], $params['auto_source'], $params['auto_id']); if(isset($params['auto_source'])) { if (isset($params['extensions'])) { $_res = false; foreach ((array)$params['extensions'] as $_extension) $_res |= $smarty->_unlink($_tname.$_extension, $params['exp_time']); } else { $_res = $smarty->_unlink($_tname, $params['exp_time']); } } elseif ($smarty->use_sub_dirs) { $_params = array( 'dirname' => $_tname, 'level' => 1, 'exp_time' => $params['exp_time'] ); require_once(SMARTY_CORE_DIR . 'core.rmdir.php'); $_res = smarty_core_rmdir($_params, $smarty); } else { // remove matching file names $_handle = opendir($params['auto_base']); $_res = true; while (false !== ($_filename = readdir($_handle))) { if($_filename == '.' || $_filename == '..') { continue; } elseif (substr($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, 0, strlen($_tname)) == $_tname) { $_res &= (bool)$smarty->_unlink($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, $params['exp_time']); } } } } return $_res; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.rmdir.php ================================================ keep root) * WARNING: no tests, it will try to remove what you tell it! * * @param string $dirname * @param integer $level * @param integer $exp_time * @return boolean */ // $dirname, $level = 1, $exp_time = null function smarty_core_rmdir($params, &$smarty) { if(!isset($params['level'])) { $params['level'] = 1; } if(!isset($params['exp_time'])) { $params['exp_time'] = null; } if($_handle = @opendir($params['dirname'])) { while (false !== ($_entry = readdir($_handle))) { if ($_entry != '.' && $_entry != '..') { if (@is_dir($params['dirname'] . DIRECTORY_SEPARATOR . $_entry)) { $_params = array( 'dirname' => $params['dirname'] . DIRECTORY_SEPARATOR . $_entry, 'level' => $params['level'] + 1, 'exp_time' => $params['exp_time'] ); smarty_core_rmdir($_params, $smarty); } else { $smarty->_unlink($params['dirname'] . DIRECTORY_SEPARATOR . $_entry, $params['exp_time']); } } } closedir($_handle); } if ($params['level']) { return @rmdir($params['dirname']); } return (bool)$_handle; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.run_insert_handler.php ================================================ debugging) { $_params = array(); $_debug_start_time = smarty_core_get_microtime($_params, $smarty); } if ($smarty->caching) { $_arg_string = serialize($params['args']); $_name = $params['args']['name']; if (!isset($smarty->_cache_info['insert_tags'][$_name])) { $smarty->_cache_info['insert_tags'][$_name] = array('insert', $_name, $smarty->_plugins['insert'][$_name][1], $smarty->_plugins['insert'][$_name][2], !empty($params['args']['script']) ? true : false); } return $smarty->_smarty_md5."{insert_cache $_arg_string}".$smarty->_smarty_md5; } else { if (isset($params['args']['script'])) { $_params = array('resource_name' => $smarty->_dequote($params['args']['script'])); require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php'); if(!smarty_core_get_php_resource($_params, $smarty)) { return false; } if ($_params['resource_type'] == 'file') { $smarty->_include($_params['php_resource'], true); } else { $smarty->_eval($_params['php_resource']); } unset($params['args']['script']); } $_funcname = $smarty->_plugins['insert'][$params['args']['name']][0]; $_content = $_funcname($params['args'], $smarty); if ($smarty->debugging) { $_params = array(); require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); $smarty->_smarty_debug_info[] = array('type' => 'insert', 'filename' => 'insert_'.$params['args']['name'], 'depth' => $smarty->_inclusion_depth, 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time); } if (!empty($params['args']["assign"])) { $smarty->assign($params['args']["assign"], $_content); } else { return $_content; } } } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.smarty_include_php.php ================================================ $params['smarty_file']); require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php'); smarty_core_get_php_resource($_params, $smarty); $_smarty_resource_type = $_params['resource_type']; $_smarty_php_resource = $_params['php_resource']; if (!empty($params['smarty_assign'])) { ob_start(); if ($_smarty_resource_type == 'file') { $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']); } else { $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']); } $smarty->assign($params['smarty_assign'], ob_get_contents()); ob_end_clean(); } else { if ($_smarty_resource_type == 'file') { $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']); } else { $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']); } } } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.write_cache_file.php ================================================ _cache_info['timestamp'] = time(); if ($smarty->cache_lifetime > -1){ // expiration set $smarty->_cache_info['expires'] = $smarty->_cache_info['timestamp'] + $smarty->cache_lifetime; } else { // cache will never expire $smarty->_cache_info['expires'] = -1; } // collapse nocache.../nocache-tags if (preg_match_all('!\{(/?)nocache\:[0-9a-f]{32}#\d+\}!', $params['results'], $match, PREG_PATTERN_ORDER)) { // remove everything between every pair of outermost noache.../nocache-tags // and replace it by a single nocache-tag // this new nocache-tag will be replaced by dynamic contents in // smarty_core_process_compiled_includes() on a cache-read $match_count = count($match[0]); $results = preg_split('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!', $params['results'], -1, PREG_SPLIT_DELIM_CAPTURE); $level = 0; $j = 0; for ($i=0, $results_count = count($results); $i < $results_count && $j < $match_count; $i++) { if ($results[$i] == $match[0][$j]) { // nocache tag if ($match[1][$j]) { // closing tag $level--; unset($results[$i]); } else { // opening tag if ($level++ > 0) unset($results[$i]); } $j++; } elseif ($level > 0) { unset($results[$i]); } } $params['results'] = implode('', $results); } $smarty->_cache_info['cache_serials'] = $smarty->_cache_serials; // prepend the cache header info into cache file $_cache_info = serialize($smarty->_cache_info); $params['results'] = strlen($_cache_info) . "\n" . $_cache_info . $params['results']; if (!empty($smarty->cache_handler_func)) { // use cache_handler function call_user_func_array($smarty->cache_handler_func, array('write', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], $smarty->_cache_info['expires'])); } else { // use local cache file if(!@is_writable($smarty->cache_dir)) { // cache_dir not writable, see if it exists if(!@is_dir($smarty->cache_dir)) { $smarty->trigger_error('the $cache_dir \'' . $smarty->cache_dir . '\' does not exist, or is not a directory.', E_USER_ERROR); return false; } $smarty->trigger_error('unable to write to $cache_dir \'' . realpath($smarty->cache_dir) . '\'. Be sure $cache_dir is writable by the web server user.', E_USER_ERROR); return false; } $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']); $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id); $_params = array('filename' => $_cache_file, 'contents' => $params['results'], 'create_dirs' => true); require_once(SMARTY_CORE_DIR . 'core.write_file.php'); smarty_core_write_file($_params, $smarty); return true; } } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.write_compiled_include.php ================================================ caching && \!\$this->_cache_including\)\: echo \'\{nocache\:('.$params['cache_serial'].')#(\d+)\}\'; endif;'; $_tag_end = 'if \(\$this->caching && \!\$this->_cache_including\)\: echo \'\{/nocache\:(\\2)#(\\3)\}\'; endif;'; preg_match_all('!('.$_tag_start.'(.*)'.$_tag_end.')!Us', $params['compiled_content'], $_match_source, PREG_SET_ORDER); // no nocache-parts found: done if (count($_match_source)==0) return; // convert the matched php-code to functions $_include_compiled = "_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n"; $_include_compiled .= " compiled from " . strtr(urlencode($params['resource_name']), array('%2F'=>'/', '%3A'=>':')) . " */\n\n"; $_compile_path = $params['include_file_path']; $smarty->_cache_serials[$_compile_path] = $params['cache_serial']; $_include_compiled .= "\$this->_cache_serials['".$_compile_path."'] = '".$params['cache_serial']."';\n\n?>"; $_include_compiled .= $params['plugins_code']; $_include_compiled .= "= 5.0) ? '_smarty' : 'this'; for ($_i = 0, $_for_max = count($_match_source); $_i < $_for_max; $_i++) { $_match =& $_match_source[$_i]; $source = $_match[4]; if ($this_varname == '_smarty') { /* rename $this to $_smarty in the sourcecode */ $tokens = token_get_all('\n"; $_params = array('filename' => $_compile_path, 'contents' => $_include_compiled, 'create_dirs' => true); require_once(SMARTY_CORE_DIR . 'core.write_file.php'); smarty_core_write_file($_params, $smarty); return true; } ?> ================================================ FILE: lib/smarty/internals/core.write_compiled_resource.php ================================================ compile_dir)) { // compile_dir not writable, see if it exists if(!@is_dir($smarty->compile_dir)) { $smarty->trigger_error('the $compile_dir \'' . $smarty->compile_dir . '\' does not exist, or is not a directory.', E_USER_ERROR); return false; } $smarty->trigger_error('unable to write to $compile_dir \'' . realpath($smarty->compile_dir) . '\'. Be sure $compile_dir is writable by the web server user.', E_USER_ERROR); return false; } $_params = array('filename' => $params['compile_path'], 'contents' => $params['compiled_content'], 'create_dirs' => true); require_once(SMARTY_CORE_DIR . 'core.write_file.php'); smarty_core_write_file($_params, $smarty); return true; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/internals/core.write_file.php ================================================ $_dirname); require_once(SMARTY_CORE_DIR . 'core.create_dir_structure.php'); smarty_core_create_dir_structure($_params, $smarty); } // write to tmp file, then rename it to avoid file locking race condition $_tmp_file = tempnam($_dirname, 'wrt'); if (!($fd = @fopen($_tmp_file, 'wb'))) { $_tmp_file = $_dirname . DIRECTORY_SEPARATOR . uniqid('wrt'); if (!($fd = @fopen($_tmp_file, 'wb'))) { $smarty->trigger_error("problem writing temporary file '$_tmp_file'"); return false; } } fwrite($fd, $params['contents']); fclose($fd); if (DIRECTORY_SEPARATOR == '\\' || !@rename($_tmp_file, $params['filename'])) { // On platforms and filesystems that cannot overwrite with rename() // delete the file before renaming it -- because windows always suffers // this, it is short-circuited to avoid the initial rename() attempt @unlink($params['filename']); @rename($_tmp_file, $params['filename']); } @chmod($params['filename'], $smarty->_file_perms); return true; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/plugins/block.textformat.php ================================================ * Name: textformat
* Purpose: format text a certain way with preset styles * or custom wrap/indent settings
* @link http://smarty.php.net/manual/en/language.function.textformat.php {textformat} * (Smarty online manual) * @param array *
 * Params:   style: string (email)
 *           indent: integer (0)
 *           wrap: integer (80)
 *           wrap_char string ("\n")
 *           indent_char: string (" ")
 *           wrap_boundary: boolean (true)
 * 
* @author Monte Ohrt * @param string contents of the block * @param Smarty clever simulation of a method * @return string string $content re-formatted */ function smarty_block_textformat($params, $content, &$smarty) { if (is_null($content)) { return; } $style = null; $indent = 0; $indent_first = 0; $indent_char = ' '; $wrap = 80; $wrap_char = "\n"; $wrap_cut = false; $assign = null; foreach ($params as $_key => $_val) { switch ($_key) { case 'style': case 'indent_char': case 'wrap_char': case 'assign': $$_key = (string)$_val; break; case 'indent': case 'indent_first': case 'wrap': $$_key = (int)$_val; break; case 'wrap_cut': $$_key = (bool)$_val; break; default: $smarty->trigger_error("textformat: unknown attribute '$_key'"); } } if ($style == 'email') { $wrap = 72; } // split into paragraphs $_paragraphs = preg_split('![\r\n][\r\n]!',$content); $_output = ''; for($_x = 0, $_y = count($_paragraphs); $_x < $_y; $_x++) { if ($_paragraphs[$_x] == '') { continue; } // convert mult. spaces & special chars to single space $_paragraphs[$_x] = preg_replace(array('!\s+!','!(^\s+)|(\s+$)!'), array(' ',''), $_paragraphs[$_x]); // indent first line if($indent_first > 0) { $_paragraphs[$_x] = str_repeat($indent_char, $indent_first) . $_paragraphs[$_x]; } // wordwrap sentences $_paragraphs[$_x] = wordwrap($_paragraphs[$_x], $wrap - $indent, $wrap_char, $wrap_cut); // indent lines if($indent > 0) { $_paragraphs[$_x] = preg_replace('!^!m', str_repeat($indent_char, $indent), $_paragraphs[$_x]); } } $_output = implode($wrap_char . $wrap_char, $_paragraphs); return $assign ? $smarty->assign($assign, $_output) : $_output; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/plugins/compiler.assign.php ================================================ * Name: assign
* Purpose: assign a value to a template variable * @link http://smarty.php.net/manual/en/language.custom.functions.php#LANGUAGE.FUNCTION.ASSIGN {assign} * (Smarty online manual) * @author Monte Ohrt (initial author) * @author messju mohr (conversion to compiler function) * @param string containing var-attribute and value-attribute * @param Smarty_Compiler */ function smarty_compiler_assign($tag_attrs, &$compiler) { $_params = $compiler->_parse_attrs($tag_attrs); if (!isset($_params['var'])) { $compiler->_syntax_error("assign: missing 'var' parameter", E_USER_WARNING); return; } if (!isset($_params['value'])) { $compiler->_syntax_error("assign: missing 'value' parameter", E_USER_WARNING); return; } return "\$this->assign({$_params['var']}, {$_params['value']});"; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/plugins/function.assign_debug_info.php ================================================ * Name: assign_debug_info
* Purpose: assign debug info to the template
* @author Monte Ohrt * @param array unused in this plugin, this plugin uses {@link Smarty::$_config}, * {@link Smarty::$_tpl_vars} and {@link Smarty::$_smarty_debug_info} * @param Smarty */ function smarty_function_assign_debug_info($params, &$smarty) { $assigned_vars = $smarty->_tpl_vars; ksort($assigned_vars); if (@is_array($smarty->_config[0])) { $config_vars = $smarty->_config[0]; ksort($config_vars); $smarty->assign("_debug_config_keys", array_keys($config_vars)); $smarty->assign("_debug_config_vals", array_values($config_vars)); } $included_templates = $smarty->_smarty_debug_info; $smarty->assign("_debug_keys", array_keys($assigned_vars)); $smarty->assign("_debug_vals", array_values($assigned_vars)); $smarty->assign("_debug_tpls", $included_templates); } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/plugins/function.config_load.php ================================================ * Name: config_load
* Purpose: load config file vars * @link http://smarty.php.net/manual/en/language.function.config.load.php {config_load} * (Smarty online manual) * @author Monte Ohrt * @author messju mohr (added use of resources) * @param array Format: *
 * 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
* Purpose: print out a counter value * @author Monte Ohrt * @link http://smarty.php.net/manual/en/language.function.counter.php {counter} * (Smarty online manual) * @param array parameters * @param Smarty * @return string|null */ function smarty_function_counter($params, &$smarty) { static $counters = array(); $name = (isset($params['name'])) ? $params['name'] : 'default'; if (!isset($counters[$name])) { $counters[$name] = array( 'start'=>1, 'skip'=>1, 'direction'=>'up', 'count'=>1 ); } $counter =& $counters[$name]; if (isset($params['start'])) { $counter['start'] = $counter['count'] = (int)$params['start']; } if (!empty($params['assign'])) { $counter['assign'] = $params['assign']; } if (isset($counter['assign'])) { $smarty->assign($counter['assign'], $counter['count']); } if (isset($params['print'])) { $print = (bool)$params['print']; } else { $print = empty($counter['assign']); } if ($print) { $retval = $counter['count']; } else { $retval = null; } if (isset($params['skip'])) { $counter['skip'] = $params['skip']; } if (isset($params['direction'])) { $counter['direction'] = $params['direction']; } if ($counter['direction'] == "down") $counter['count'] -= $counter['skip']; else $counter['count'] += $counter['skip']; return $retval; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/plugins/function.cycle.php ================================================ * Name: cycle
* Date: May 3, 2002
* Purpose: cycle through given values
* Input: * - name = name of cycle (optional) * - values = comma separated list of values to cycle, * or an array of values to cycle * (this can be left out for subsequent calls) * - reset = boolean - resets given var to true * - print = boolean - print var or not. default is true * - advance = boolean - whether or not to advance the cycle * - delimiter = the value delimiter, default is "," * - assign = boolean, assigns to template var instead of * printed. * * Examples:
*
 * {cycle values="#eeeeee,#d0d0d0d"}
 * {cycle name=row values="one,two,three" reset=true}
 * {cycle name=row}
 * 
* @link http://smarty.php.net/manual/en/language.function.cycle.php {cycle} * (Smarty online manual) * @author Monte Ohrt * @author credit to Mark Priatel * @author credit to Gerard * @author credit to Jason Sweat * @version 1.3 * @param array * @param Smarty * @return string|null */ function smarty_function_cycle($params, &$smarty) { static $cycle_vars; $name = (empty($params['name'])) ? 'default' : $params['name']; $print = (isset($params['print'])) ? (bool)$params['print'] : true; $advance = (isset($params['advance'])) ? (bool)$params['advance'] : true; $reset = (isset($params['reset'])) ? (bool)$params['reset'] : false; if (!in_array('values', array_keys($params))) { if(!isset($cycle_vars[$name]['values'])) { $smarty->trigger_error("cycle: missing 'values' parameter"); return; } } else { if(isset($cycle_vars[$name]['values']) && $cycle_vars[$name]['values'] != $params['values'] ) { $cycle_vars[$name]['index'] = 0; } $cycle_vars[$name]['values'] = $params['values']; } if (isset($params['delimiter'])) { $cycle_vars[$name]['delimiter'] = $params['delimiter']; } elseif (!isset($cycle_vars[$name]['delimiter'])) { $cycle_vars[$name]['delimiter'] = ','; } if(is_array($cycle_vars[$name]['values'])) { $cycle_array = $cycle_vars[$name]['values']; } else { $cycle_array = explode($cycle_vars[$name]['delimiter'],$cycle_vars[$name]['values']); } if(!isset($cycle_vars[$name]['index']) || $reset ) { $cycle_vars[$name]['index'] = 0; } if (isset($params['assign'])) { $print = false; $smarty->assign($params['assign'], $cycle_array[$cycle_vars[$name]['index']]); } if($print) { $retval = $cycle_array[$cycle_vars[$name]['index']]; } else { $retval = null; } if($advance) { if ( $cycle_vars[$name]['index'] >= count($cycle_array) -1 ) { $cycle_vars[$name]['index'] = 0; } else { $cycle_vars[$name]['index']++; } } return $retval; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/plugins/function.debug.php ================================================ * Name: debug
* Date: July 1, 2002
* Purpose: popup debug window * @link http://smarty.php.net/manual/en/language.function.debug.php {debug} * (Smarty online manual) * @author Monte Ohrt * @version 1.0 * @param array * @param Smarty * @return string output from {@link Smarty::_generate_debug_output()} */ function smarty_function_debug($params, &$smarty) { if (isset($params['output'])) { $smarty->assign('_smarty_debug_output', $params['output']); } require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php'); return smarty_core_display_debug_console(null, $smarty); } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/plugins/function.eval.php ================================================ * Name: eval
* Purpose: evaluate a template variable as a template
* @link http://smarty.php.net/manual/en/language.function.eval.php {eval} * (Smarty online manual) * @author Monte Ohrt * @param array * @param Smarty */ function smarty_function_eval($params, &$smarty) { if (!isset($params['var'])) { $smarty->trigger_error("eval: missing 'var' parameter"); return; } if($params['var'] == '') { return; } $smarty->_compile_source('evaluated template', $params['var'], $_var_compiled); ob_start(); $smarty->_eval('?>' . $_var_compiled); $_contents = ob_get_contents(); ob_end_clean(); if (!empty($params['assign'])) { $smarty->assign($params['assign'], $_contents); } else { return $_contents; } } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/plugins/function.fetch.php ================================================ * Name: fetch
* Purpose: fetch file, web or ftp data and display results * @link http://smarty.php.net/manual/en/language.function.fetch.php {fetch} * (Smarty online manual) * @author Monte Ohrt * @param array * @param Smarty * @return string|null if the assign parameter is passed, Smarty assigns the * result to a template variable */ function smarty_function_fetch($params, &$smarty) { if (empty($params['file'])) { $smarty->_trigger_fatal_error("[plugin] parameter 'file' cannot be empty"); return; } $content = ''; if ($smarty->security && !preg_match('!^(http|ftp)://!i', $params['file'])) { $_params = array('resource_type' => 'file', 'resource_name' => $params['file']); require_once(SMARTY_CORE_DIR . 'core.is_secure.php'); if(!smarty_core_is_secure($_params, $smarty)) { $smarty->_trigger_fatal_error('[plugin] (secure mode) fetch \'' . $params['file'] . '\' is not allowed'); return; } // fetch the file if($fp = @fopen($params['file'],'r')) { while(!feof($fp)) { $content .= fgets ($fp,4096); } fclose($fp); } else { $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] . '\''); return; } } else { // not a local file if(preg_match('!^http://!i',$params['file'])) { // http fetch if($uri_parts = parse_url($params['file'])) { // set defaults $host = $server_name = $uri_parts['host']; $timeout = 30; $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*"; $agent = "Smarty Template Engine ".$smarty->_version; $referer = ""; $uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/'; $uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : ''; $_is_proxy = false; if(empty($uri_parts['port'])) { $port = 80; } else { $port = $uri_parts['port']; } if(!empty($uri_parts['user'])) { $user = $uri_parts['user']; } if(!empty($uri_parts['pass'])) { $pass = $uri_parts['pass']; } // loop through parameters, setup headers foreach($params as $param_key => $param_value) { switch($param_key) { case "file": case "assign": case "assign_headers": break; case "user": if(!empty($param_value)) { $user = $param_value; } break; case "pass": if(!empty($param_value)) { $pass = $param_value; } break; case "accept": if(!empty($param_value)) { $accept = $param_value; } break; case "header": if(!empty($param_value)) { if(!preg_match('![\w\d-]+: .+!',$param_value)) { $smarty->_trigger_fatal_error("[plugin] invalid header format '".$param_value."'"); return; } else { $extra_headers[] = $param_value; } } break; case "proxy_host": if(!empty($param_value)) { $proxy_host = $param_value; } break; case "proxy_port": if(!preg_match('!\D!', $param_value)) { $proxy_port = (int) $param_value; } else { $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'"); return; } break; case "agent": if(!empty($param_value)) { $agent = $param_value; } break; case "referer": if(!empty($param_value)) { $referer = $param_value; } break; case "timeout": if(!preg_match('!\D!', $param_value)) { $timeout = (int) $param_value; } else { $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'"); return; } break; default: $smarty->_trigger_fatal_error("[plugin] unrecognized attribute '".$param_key."'"); return; } } if(!empty($proxy_host) && !empty($proxy_port)) { $_is_proxy = true; $fp = fsockopen($proxy_host,$proxy_port,$errno,$errstr,$timeout); } else { $fp = fsockopen($server_name,$port,$errno,$errstr,$timeout); } if(!$fp) { $smarty->_trigger_fatal_error("[plugin] unable to fetch: $errstr ($errno)"); return; } else { if($_is_proxy) { fputs($fp, 'GET ' . $params['file'] . " HTTP/1.0\r\n"); } else { fputs($fp, "GET $uri HTTP/1.0\r\n"); } if(!empty($host)) { fputs($fp, "Host: $host\r\n"); } if(!empty($accept)) { fputs($fp, "Accept: $accept\r\n"); } if(!empty($agent)) { fputs($fp, "User-Agent: $agent\r\n"); } if(!empty($referer)) { fputs($fp, "Referer: $referer\r\n"); } if(isset($extra_headers) && is_array($extra_headers)) { foreach($extra_headers as $curr_header) { fputs($fp, $curr_header."\r\n"); } } if(!empty($user) && !empty($pass)) { fputs($fp, "Authorization: BASIC ".base64_encode("$user:$pass")."\r\n"); } fputs($fp, "\r\n"); while(!feof($fp)) { $content .= fgets($fp,4096); } fclose($fp); $csplit = preg_split("!\r\n\r\n!",$content,2); $content = $csplit[1]; if(!empty($params['assign_headers'])) { $smarty->assign($params['assign_headers'],preg_split("!\r\n!",$csplit[0])); } } } else { $smarty->_trigger_fatal_error("[plugin] unable to parse URL, check syntax"); return; } } else { // ftp fetch if($fp = @fopen($params['file'],'r')) { while(!feof($fp)) { $content .= fgets ($fp,4096); } fclose($fp); } else { $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] .'\''); return; } } } if (!empty($params['assign'])) { $smarty->assign($params['assign'],$content); } else { return $content; } } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/plugins/function.html_checkboxes.php ================================================ * Type: function
* Name: html_checkboxes
* Date: 24.Feb.2003
* Purpose: Prints out a list of checkbox input types
* Input:
* - name (optional) - string default "checkbox" * - values (required) - array * - options (optional) - associative array * - checked (optional) - array default not set * - separator (optional) - ie
or   * - output (optional) - the output next to each checkbox * - assign (optional) - assign the output as an array to this variable * Examples: *
 * {html_checkboxes values=$ids output=$names}
 * {html_checkboxes values=$ids name='box' separator='
' output=$names} * {html_checkboxes values=$ids checked=$checked separator='
' output=$names} *
* @link http://smarty.php.net/manual/en/language.function.html.checkboxes.php {html_checkboxes} * (Smarty online manual) * @author Christopher Kvarme * @author credits to Monte Ohrt * @version 1.0 * @param array * @param Smarty * @return string * @uses smarty_function_escape_special_chars() */ function smarty_function_html_checkboxes($params, &$smarty) { require_once $smarty->_get_plugin_filepath('shared','escape_special_chars'); $name = 'checkbox'; $values = null; $options = null; $selected = null; $separator = ''; $labels = true; $output = null; $extra = ''; foreach($params as $_key => $_val) { switch($_key) { case 'name': case 'separator': $$_key = $_val; break; case 'labels': $$_key = (bool)$_val; break; case 'options': $$_key = (array)$_val; break; case 'values': case 'output': $$_key = array_values((array)$_val); break; case 'checked': case 'selected': $selected = array_map('strval', array_values((array)$_val)); break; case 'checkboxes': $smarty->trigger_error('html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', E_USER_WARNING); $options = (array)$_val; break; case 'assign': break; default: if(!is_array($_val)) { $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"'; } else { $smarty->trigger_error("html_checkboxes: extra attribute '$_key' cannot be an array", E_USER_NOTICE); } break; } } if (!isset($options) && !isset($values)) return ''; /* raise error here? */ settype($selected, 'array'); $_html_result = array(); if (isset($options)) { foreach ($options as $_key=>$_val) $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels); } else { foreach ($values as $_i=>$_key) { $_val = isset($output[$_i]) ? $output[$_i] : ''; $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels); } } if(!empty($params['assign'])) { $smarty->assign($params['assign'], $_html_result); } else { return implode("\n",$_html_result); } } function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels) { $_output = ''; if ($labels) $_output .= ''; $_output .= $separator; return $_output; } ?> ================================================ FILE: lib/smarty/plugins/function.html_image.php ================================================ * Name: html_image
* Date: Feb 24, 2003
* Purpose: format HTML tags for the image
* Input:
* - file = file (and path) of image (required) * - height = image height (optional, default actual height) * - width = image width (optional, default actual width) * - basedir = base directory for absolute paths, default * is environment variable DOCUMENT_ROOT * - path_prefix = prefix for path output (optional, default empty) * * Examples: {html_image file="/images/masthead.gif"} * Output: * @link http://smarty.php.net/manual/en/language.function.html.image.php {html_image} * (Smarty online manual) * @author Monte Ohrt * @author credits to Duda - wrote first image function * in repository, helped with lots of functionality * @version 1.0 * @param array * @param Smarty * @return string * @uses smarty_function_escape_special_chars() */ function smarty_function_html_image($params, &$smarty) { require_once $smarty->_get_plugin_filepath('shared','escape_special_chars'); $alt = ''; $file = ''; $height = ''; $width = ''; $extra = ''; $prefix = ''; $suffix = ''; $path_prefix = ''; $server_vars = ($smarty->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS']; $basedir = isset($server_vars['DOCUMENT_ROOT']) ? $server_vars['DOCUMENT_ROOT'] : ''; foreach($params as $_key => $_val) { switch($_key) { case 'file': case 'height': case 'width': case 'dpi': case 'path_prefix': case 'basedir': $$_key = $_val; break; case 'alt': if(!is_array($_val)) { $$_key = smarty_function_escape_special_chars($_val); } else { $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE); } break; case 'link': case 'href': $prefix = ''; $suffix = ''; break; default: if(!is_array($_val)) { $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"'; } else { $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE); } break; } } if (empty($file)) { $smarty->trigger_error("html_image: missing 'file' parameter", E_USER_NOTICE); return; } if (substr($file,0,1) == '/') { $_image_path = $basedir . $file; } else { $_image_path = $file; } if(!isset($params['width']) || !isset($params['height'])) { if(!$_image_data = @getimagesize($_image_path)) { if(!file_exists($_image_path)) { $smarty->trigger_error("html_image: unable to find '$_image_path'", E_USER_NOTICE); return; } else if(!is_readable($_image_path)) { $smarty->trigger_error("html_image: unable to read '$_image_path'", E_USER_NOTICE); return; } else { $smarty->trigger_error("html_image: '$_image_path' is not a valid image file", E_USER_NOTICE); return; } } if ($smarty->security && ($_params = array('resource_type' => 'file', 'resource_name' => $_image_path)) && (require_once(SMARTY_CORE_DIR . 'core.is_secure.php')) && (!smarty_core_is_secure($_params, $smarty)) ) { $smarty->trigger_error("html_image: (secure) '$_image_path' not in secure directory", E_USER_NOTICE); } if(!isset($params['width'])) { $width = $_image_data[0]; } if(!isset($params['height'])) { $height = $_image_data[1]; } } if(isset($params['dpi'])) { if(strstr($server_vars['HTTP_USER_AGENT'], 'Mac')) { $dpi_default = 72; } else { $dpi_default = 96; } $_resize = $dpi_default/$params['dpi']; $width = round($width * $_resize); $height = round($height * $_resize); } return $prefix . ''.$alt.'' . $suffix; } /* vim: set expandtab: */ ?> ================================================ FILE: lib/smarty/plugins/function.html_options.php ================================================ * Name: html_options
* Input:
* - name (optional) - string default "select" * - values (required if no options supplied) - array * - options (required if no values supplied) - associative array * - selected (optional) - string default not set * - output (required if not options supplied) - array * Purpose: Prints the list of