Index: branches/5.1.x/core/kernel/processors/main_processor.php
===================================================================
--- branches/5.1.x/core/kernel/processors/main_processor.php	(revision 13561)
+++ branches/5.1.x/core/kernel/processors/main_processor.php	(revision 13562)
@@ -1,1059 +1,1072 @@
 <?php
 /**
 * @version	$Id$
 * @package	In-Portal
 * @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
 * @license      GNU/GPL
 * In-Portal is Open Source software.
 * This means that this software may have been modified pursuant
 * the GNU General Public License, and as distributed it includes
 * or is derivative of works licensed under the GNU General Public License
 * or other free or open source software licenses.
 * See http://www.in-portal.org/license for copyright notices and details.
 */
 
 defined('FULL_PATH') or die('restricted access!');
 
 class kMainTagProcessor extends kTagProcessor {
 
 	function Init($prefix, $special, $event_params = null)
 	{
 		parent::Init($prefix, $special, $event_params);
 
 		$actions =& $this->Application->recallObject('kActions');
 		$actions->Set('t', $this->Application->GetVar('t'));
 		$actions->Set('sid', $this->Application->GetSID());
 		$actions->Set('m_opener', $this->Application->GetVar('m_opener') );
 	}
 
 	/**
 	 * Base folder for all template includes
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function TemplatesBase($params)
 	{
 		static $cached = Array ();
 
 		$cache_key = crc32( serialize($params) );
 
 		if (!array_key_exists($cache_key, $cached)) {
 			$module = array_key_exists('module', $params) ? $params['module'] : 'core';
 
 			if ($this->Application->isAdmin) {
 				if ($module == 'in-portal') {
 					$module = 'kernel';
 				}
 
 				// remove leading slash + substitute module
 				$module_path = $this->Application->findModule('Name', $module, 'Path');
 
 				if ($module_path !== false) {
 					$path = $module_path . 'admin_templates';
 				}
 				else {
 					// remove leading slash + substitute module
 					$path = preg_replace('/\/(.*?)\/(.*)/', $module . '/\\2', THEMES_PATH);
 				}
 			}
 			else {
 				$path = mb_substr(THEMES_PATH, 1);
 
 				if (mb_strtolower($module) == 'in-portal') {
 					$module_folder = 'platform';
 				}
 				else {
 					$module_folder = $this->Application->findModule('Name', $module, 'TemplatePath');
 				}
 
 				$path .= rtrim('/' . trim($module_folder, '/'), '/') . '/';
 			}
 
 			$cached[$cache_key] = $this->Application->BaseURL() . $path;
 		}
 
 		return $cached[$cache_key];
 	}
 
 	/**
 	 * Creates <base href ..> HTML tag for all templates
 	 * affects future css, js files and href params of links
 	 *
 	 * @return string
 	 * @access public
 	 */
 	function Base_Ref($params)
 	{
 		return '<base href="'.$this->TemplatesBase($params).'/" />';
 	}
 
 	/**
 	 * Returns base url for web-site
 	 *
 	 * @return string
 	 * @access public
 	 */
 	function BaseURL()
 	{
 		return $this->Application->BaseURL();
 	}
 
 	//for compatability with K3 tags
 	function Base($params)
 	{
 		return $this->TemplatesBase($params).'/';
 	}
 
 	function ProjectBase($params)
 	{
 		return $this->Application->BaseURL();
 	}
 
 	/*function Base($params)
 	{
 		return $this->Application->BaseURL().$params['add'];
 	}*/
 
 	/**
 	 * Used to create link to any template.
 	 * use "pass" paramter if "t" tag to specify
 	 * prefix & special of object to be represented
 	 * in resulting url
 	 *
 	 * @param Array $params
 	 * @return string
 	 * @access public
 	 */
 	function T($params)
 	{
-		//by default link to current template
+		// by default link to current template
 		$template = $this->SelectParam($params, 't,template');
 		$prefix = array_key_exists('prefix', $params) ? $params['prefix'] : '';
 
 		unset($params['t'], $params['template'], $params['prefix']);
 
 		return $this->Application->HREF($template, $prefix, $params);
 	}
 
 	function Link($params)
 	{
 		// pass "m" prefix, instead of "all", that is by default on Front-End
 		if (!array_key_exists('pass', $params)) {
 			$params['pass'] = 'm';
 		}
 
 		return $this->T($params);
 	}
 
+	/**
+	 * Performs redirect to provided template/url
+	 *
+	 * @param Array $params
+	 * @return string
+	 */
+	function Redirect($params)
+	{
+		$this->Application->Redirect('external:' . $this->Link($params));
+
+		return '';
+	}
+
 	function Env($params)
 	{
 		$t = $params['template'];
 		unset($params['template']);
 		return $this->Application->BuildEnv($t, $params, 'm', null, false);
 	}
 
 	function FormAction($params)
 	{
 		if (!array_key_exists('pass', $params)) {
 			$params['pass'] = 'all,m';
 		}
 
 		$params['pass_category'] = 1;
 
 		return $this->Application->HREF('', '', $params);
 	}
 
 	/*// NEEDS TEST
 	function Config($params)
 	{
 		return $this->Application->ConfigOption($params['var']);
 	}
 
 	function Object($params)
 	{
 		$name = $params['name'];
 		$method = $params['method'];
 
 		$tmp =& $this->Application->recallObject($name);
 		if ($tmp != null) {
 			if (method_exists($tmp, $method))
 				return $tmp->$method($params);
 			else
 				echo "Method $method does not exist in object ".get_class($tmp)." named $name<br>";
 		}
 		else
 			echo "Object $name does not exist in the appliaction<br>";
 	}*/
 
 	/**
 	 * Tag, that always returns true.
 	 * For parser testing purposes
 	 *
 	 * @param Array $params
 	 * @return bool
 	 * @access public
 	 */
 	function True($params)
 	{
 		return true;
 	}
 
 	/**
 	 * Tag, that always returns false.
 	 * For parser testing purposes
 	 *
 	 * @param Array $params
 	 * @return bool
 	 * @access public
 	 */
 	function False($params)
 	{
 		return false;
 	}
 
 	/**
 	 * Returns block parameter by name (used only as "check" parameter value for "m_if" tag!)
 	 *
 	 * @param Array $params
 	 * @return stirng
 	 * @access public
 	 */
 	function Param($params)
 	{
 		$name = $params['name'];
 
 		if (array_key_exists($name, $this->Application->Parser->Captures)) {
 			$capture_params = $params;
 			$capture_params['name'] = '__capture_' . $name;
 
 			$this->Application->Parser->SetParam($name, $this->Application->ParseBlock($capture_params));
 		}
 
 		$res = $this->Application->Parser->GetParam($name);
 
 		if ($res === false) {
 			$res = '';
 		}
 
 		if (array_key_exists('plus', $params)) {
 			$res += $params['plus'];
 		}
 
 		return $res;
 	}
 
 	/**
 	 * Compares block parameter with value specified
 	 *
 	 * @param Array $params
 	 * @return bool
 	 * @access public
 	 */
 	function ParamEquals($params)
 	{
 		$name = $this->SelectParam($params, 'name,var,param');
 		$value = $params['value'];
 
 		return ($this->Application->Parser->GetParam($name) == $value);
 	}
 
 	/*function PHP_Self($params)
 	{
 		return $HTTP_SERVER_VARS['PHP_SELF'];
 	}
 	*/
 
 	/**
 	 * Returns session variable value by name
 	 *
 	 * @param Array $params
 	 * @return string
 	 * @access public
 	 */
 	function Recall($params)
 	{
 		$var_name = $this->SelectParam($params,'name,var,param');
 
 		if (isset($params['persistent']) && $params['persistent']) {
 			$ret = $this->Application->RecallPersistentVar($var_name);
 		}
 		else {
 			 $ret = $this->Application->RecallVar($var_name);
 		}
 
 		$ret = ($ret === false && isset($params['no_null'])) ? '' : $ret;
 		if (getArrayValue($params, 'special') || getArrayValue($params, 'htmlchars')) {
 			$ret = htmlspecialchars($ret);
 		}
 
 		if (getArrayValue($params, 'urlencode')) {
 			$ret = urlencode($ret);
 		}
 
 		return $ret;
 	}
 
 	function RemoveVar($params)
 	{
 		$this->Application->RemoveVar( $this->SelectParam($params,'name,var,param') );
 	}
 
 	// bad style to store something from template to session !!! (by Alex)
 	// Used here only to test how session works, nothing more
 	function Store($params)
 	{
 		//echo"Store $params[name]<br>";
 		$name = $params['name'];
 		$value = $params['value'];
 		$this->Application->StoreVar($name,$value);
 	}
 
 	/**
 	 * Sets application variable value(-s)
 	 *
 	 * @param Array $params
 	 * @access public
 	 */
 	function Set($params)
 	{
 		foreach ($params as $param => $value) {
 			$this->Application->SetVar($param, $value);
 		}
 	}
 
 	/**
 	 * Increment application variable
 	 * specified by number specified
 	 *
 	 * @param Array $params
 	 * @access public
 	 */
 	function Inc($params)
 	{
 		$this->Application->SetVar($params['param'], $this->Application->GetVar($params['param']) + $params['by']);
 	}
 
 	/**
 	 * Retrieves application variable
 	 * value by name
 	 *
 	 * @param Array $params
 	 * @return string
 	 * @access public
 	 */
 	function Get($params)
 	{
 		$name = $this->SelectParam($params, 'name,var,param');
 		$ret = $this->Application->GetVar($name, '');
 
 		if (array_key_exists('no_html_escape', $params) && $params['no_html_escape']) {
 			return unhtmlentities($ret);
 		}
 
 		return $ret;
 	}
 
 	/**
 	 * Retrieves application constant
 	 * value by name
 	 *
 	 * @param Array $params
 	 * @return string
 	 * @access public
 	 */
 	function GetConst($params)
 	{
 		$constant_name = $this->SelectParam($params, 'name,const');
 
 		return defined($constant_name) ? constant($constant_name) : '';
 	}
 
 	/**
 	 * Retrieves configuration variable value by name
 	 *
 	 * @param Array $params
 	 * @return string
 	 * @access public
 	 */
 	function GetConfig($params)
 	{
 		$config_name = $this->SelectParam($params, 'name,var');
 
 		return $this->Application->ConfigValue($config_name);
 	}
 
 	function ConfigEquals($params)
 	{
 		$option = $this->SelectParam($params, 'name,option,var');
 		return $this->Application->ConfigValue($option) == getArrayValue($params, 'value');
 	}
 
 	/**
 	 * Creates all hidden fields
 	 * needed for kernel_form
 	 *
 	 * @param Array $params
 	 * @return string
 	 * @access public
 	 */
 	function DumpSystemInfo($params)
 	{
 		$actions =& $this->Application->recallObject('kActions');
 		$actions->Set('t', $this->Application->GetVar('t') );
 
 		$params = $actions->GetParams();
 		$o='';
 		foreach ($params AS $name => $val)
 		{
 			$o .= "<input type='hidden' name='$name' id='$name' value='$val'>\n";
 		}
 		return $o;
 	}
 
 	/**
 	 * Used for search sidebox on front-end only
 	 *
 	 * @param Array $params
 	 * @return string
 	 * @author Alex
 	 */
 	function GetFormHiddens($params)
 	{
 		$t = $this->SelectParam($params, 'template,t');
 		unset($params['template']);
 
 		$form_fields = Array ();
 		if ($this->Application->RewriteURLs()) {
 			$session =& $this->Application->recallObject('Session');
 			if ($session->NeedQueryString()) {
 				$form_fields['sid'] = $this->Application->GetSID();
 			}
 		}
 		else {
 			$form_fields['env'] = $this->Application->BuildEnv($t, $params, 'm', null, false);
 		}
 
 		if ($this->Application->GetVar('admin') == 1) {
 			$form_fields['admin'] = 1;
 		}
 
 		$ret = '';
 		$field_tpl = '<input type="hidden" name="%1$s" id="%1$s" value="%2$s"/>'."\n";
 		foreach ($form_fields as $form_field => $field_value) {
 			$ret .= sprintf($field_tpl, $form_field, $field_value);
 		}
 
 		return $ret;
 	}
 
 	function Odd_Even($params)
 	{
 		$odd = $params['odd'];
 		$even = $params['even'];
 		if (!isset($params['var'])) {
 			$var = 'odd_even';
 		}
 		else {
 			$var = $params['var'];
 		}
 
 		if ($this->Application->GetVar($var) == 'even') {
 			if (!isset($params['readonly']) || !$params['readonly']) {
 				$this->Application->SetVar($var, 'odd');
 			}
 			return $even;
 		}
 		else {
 			if (!isset($params['readonly']) || !$params['readonly']) {
 				$this->Application->SetVar($var, 'even');
 			}
 			return $odd;
 		}
 	}
 
 	/**
 	 * Returns phrase translation by name
 	 *
 	 * @param Array $params
 	 * @return string
 	 * @access public
 	 */
 	function Phrase($params)
 	{
 		$phrase_name = $this->SelectParam($params, 'label,name,title');
 		$no_editing = array_key_exists('no_editing', $params) && $params['no_editing'];
 		$translation = $this->Application->Phrase($phrase_name, !$no_editing);
 
 		if (isset($params['escape']) && $params['escape']) {
 			$translation = htmlspecialchars($translation, ENT_QUOTES);
 			$translation = addslashes($translation);
 		}
 		return $translation;
 	}
 
 	// for tabs
 	function is_active($params)
 	{
 		$test_templ =  $this->SelectParam($params, 'templ,template,t');
 		if ( !getArrayValue($params,'allow_empty') )
 		{
 			$if_true=getArrayValue($params,'true') ? $params['true'] : 1;
 			$if_false=getArrayValue($params,'false') ? $params['false'] : 0;
 		}
 		else
 		{
 			$if_true=$params['true'];
 			$if_false=$params['false'];
 		}
 
 		if ( preg_match("/^".str_replace('/', '\/', $test_templ)."/i", $this->Application->GetVar('t'))) {
 			return $if_true;
 		}
 		else {
 			return $if_false;
 		}
 	}
 
 	function IsNotActive($params)
 	{
 		return !$this->is_active($params);
 	}
 
 	function IsActive($params)
 	{
 		return $this->is_active($params);
 	}
 
 	function is_t_active($params)
 	{
 		return $this->is_active($params);
 	}
 
 	function CurrentTemplate($params)
 	{
 		return $this->is_active($params);
 	}
 
 	/**
 	 * Checks if session variable
 	 * specified by name value match
 	 * value passed as parameter
 	 *
 	 * @param Array $params
 	 * @return string
 	 * @access public
 	 */
 	function RecallEquals($params)
 	{
 		$name = $this->SelectParam($params, 'name,var');
 		$value = $params['value'];
 
 		if (isset($params['persistent']) && $params['persistent']) {
 			return $this->Application->RecallPersistentVar($name) == $value;
 		}
 
 		return ($this->Application->RecallVar($name) == $value);
 	}
 
 	/**
 	 * Checks if application variable
 	 * specified by name value match
 	 * value passed as parameter
 	 *
 	 * @param Array $params
 	 * @return bool
 	 * @access public
 	 */
 	function GetEquals($params)
 	{
 		$name = $this->SelectParam($params, 'var,name,param');
 
 		$value = $params['value'];
 		if ($this->Application->GetVar($name) == $value) {
 			return 1;
 		}
 	}
 
 	function ModuleInclude($params)
 	{
 		$ret = '';
 		$included = Array ();
 		$block_params = array_merge($params, Array('is_silent' => 2)); // don't make fatal errors in case if template is missing
 		$current_template = $this->Application->GetVar('t');
 
 		$replace_main = isset($params['replace_m']) && $params['replace_m'];
 		$skip_prefixes = isset($params['skip_prefixes']) ? explode(',', $params['skip_prefixes']) : Array();
 		$cms_mode = $this->Application->GetVar('admin');
 
 		foreach ($this->Application->ModuleInfo as $module_name => $module_data) {
 			$module_key = mb_strtolower($module_name);
 
 			if ($module_name == 'In-Portal') {
 				if (!$cms_mode && $this->Application->isAdmin) {
 					// don't process In-Portal templates in admin
 					continue;
 				}
 
 				// Front-End still relies on In-Portal module
 				$module_prefix = $module_data['TemplatePath'];
 			}
 			elseif ($this->Application->isAdmin) {
 				$module_prefix = $module_key . '/'; // was $module_data['Path'];
 			}
 			else {
 				$module_prefix = $module_data['TemplatePath']; // always have trailing "/"
 			}
 
 			if (in_array($module_prefix, $included)) {
 				// template by this path was already included by other module (e.g. in-portal used core's template)
 				continue;
 			}
 
 			$block_params['t'] = $module_prefix.$this->SelectParam($params, $module_key.'_template,'.$module_key.'_t,template,t');
 
 			$check_prefix = $module_data['Var'];
 
 			if ($check_prefix == 'adm' && $replace_main) {
 				$check_prefix = 'c';
 			}
 
 			if ($block_params['t'] == $current_template || in_array($check_prefix, $skip_prefixes)) {
 				continue;
 			}
 
 			$no_data = $this->SelectParam($params, $module_key.'_block_no_data,block_no_data');
 			if ($no_data) {
 				$block_params['block_no_data'] = $module_prefix.'/'.$no_data;
 			}
 
 			$ret .= $this->Application->IncludeTemplate($block_params);
 			$included[] = $module_prefix;
 		}
 
 		return $ret;
 	}
 
 	function ModuleEnabled($params)
 	{
 		return $this->Application->isModuleEnabled( $params['module'] );
 	}
 
 	/**
 	 * Checks if debug mode is on
 	 *
 	 * @param Array $params
 	 * @return bool
 	 * @access public
 	 */
 	function IsDebugMode($params)
 	{
 		return defined('DEBUG_MODE') && $this->Application->isDebugMode();
 	}
 
 	/*function MassParse($params)
 	{
 		$qty = $params['qty'];
 		$block = $params['block'];
 		$mode = $params['mode'];
 
 		$o = '';
 		if ($mode == 'func') {
 			$func = create_function('$params', '
 					$o = \'<tr>\';
 					$o.= \'<td>a\'.$params[\'param1\'].\'</td>\';
 					$o.= \'<td>a\'.$params[\'param2\'].\'</td>\';
 					$o.= \'<td>a\'.$params[\'param3\'].\'</td>\';
 					$o.= \'<td>a\'.$params[\'param4\'].\'</td>\';
 					$o.= \'</tr>\';
 					return $o;
 				');
 			for ($i=1; $i<$qty; $i++) {
 				$block_params['param1'] = rand(1, 10000);
 				$block_params['param2'] = rand(1, 10000);
 				$block_params['param3'] = rand(1, 10000);
 				$block_params['param4'] = rand(1, 10000);
 				$o .= $func($block_params);
 			}
 			return $o;
 		}
 
 		$block_params['name'] = $block;
 
 		for ($i=0; $i<$qty; $i++) {
 			$block_params['param1'] = rand(1, 10000);
 			$block_params['param2'] = rand(1, 10000);
 			$block_params['param3'] = rand(1, 10000);
 			$block_params['param4'] = rand(1, 10000);
 			$block_params['passed'] = $params['passed'];
 			$block_params['prefix'] = 'm';
 
 			$o.= $this->Application->ParseBlock($block_params);
 		}
 		return $o;
 	}*/
 
 	function LoggedIn($params)
 	{
 		return $this->Application->LoggedIn();
 	}
 
 	/**
 	 * Allows to check if permission exists directly in template and perform additional actions if required
 	 *
 	 * @param Array $params
 	 * @return bool
 	 */
 	function CheckPermission($params)
 	{
 		$perm_helper =& $this->Application->recallObject('PermissionsHelper');
 		return $perm_helper->TagPermissionCheck($params);
 	}
 
 	/**
 	 * Checks if user is logged in and if not redirects it to template passed
 	 *
 	 * @param Array $params
 	 */
 	function RequireLogin($params)
 	{
 		$t = $this->Application->GetVar('t');
 		if ($next_t = getArrayValue($params, 'next_template')) {
 			$t = $next_t;
 		}
 
 		// check by permissions: begin
 		if ((isset($params['perm_event']) && $params['perm_event']) ||
 			(isset($params['perm_prefix']) && $params['perm_prefix']) ||
 			(isset($params['permissions']) && $params['permissions'])) {
 
 			$perm_helper =& $this->Application->recallObject('PermissionsHelper');
 			/* @var $perm_helper kPermissionsHelper */
 
 			$perm_status = $perm_helper->TagPermissionCheck($params);
 			if (!$perm_status) {
 				list($redirect_template, $redirect_params) = $perm_helper->getPermissionTemplate($params);
 				$this->Application->Redirect($redirect_template, $redirect_params);
 			}
 			else {
 				return ;
 			}
 		}
 		// check by permissions: end
 
 		// check by configuration value: begin
 		$condition = getArrayValue($params, 'condition');
 		if (!$condition) {
 			$condition = true;
 		}
 		else {
 			if (substr($condition, 0, 1) == '!') {
 				$condition = !$this->Application->ConfigValue(substr($condition, 1));
 			}
 			else {
 				$condition = $this->Application->ConfigValue($condition);
 			}
 		}
 		// check by configuration value: end
 
 		// check by belonging to group: begin
 		$group = $this->SelectParam($params, 'group');
 		$group_access = true;
 		if ($group) {
 			$conn =& $this->Application->GetADODBConnection();
 			$group_id = $conn->GetOne('SELECT GroupId FROM '.TABLE_PREFIX.'PortalGroup WHERE Name = '.$conn->qstr($group));
 			if ($group_id) {
 				$groups = explode(',', $this->Application->RecallVar('UserGroups'));
 				$group_access = in_array($group_id, $groups);
 			}
 		}
 		// check by belonging to group: end
 
 		if ((!$this->Application->LoggedIn() || !$group_access) && $condition) {
 			$redirect_params = $this->Application->HttpQuery->getRedirectParams(true);
 
 			if (array_key_exists('pass_category', $params)) {
 				$redirect_params['pass_category'] = $params['pass_category'];
 			}
 
 			if (MOD_REWRITE) {
 				// TODO: $next_t variable is ignored !!! (is anyone using m_RequireLogin tag with "next_template" parameter?)
 				$redirect_params = Array (
 					'm_cat_id' => 0,
 					'next_template' => urlencode('external:' . $_SERVER['REQUEST_URI']),
 				);
 			}
 			else {
 				$redirect_params['next_template'] = $t;
 			}
 
 			if ( $this->Application->LoggedIn() && !$group_access) {
 				$this->Application->Redirect($params['no_group_perm_template'], $redirect_params);
 			}
 
 			$this->Application->Redirect($params['login_template'], $redirect_params);
 		}
 	}
 
 	function IsMember($params)
 	{
 		$group = getArrayValue($params, 'group');
 		$conn =& $this->Application->DB;
 		$group_id = $conn->GetOne('SELECT GroupId FROM '.TABLE_PREFIX.'PortalGroup WHERE Name = '.$conn->qstr($group));
 		if ($group_id) {
 			$groups = explode(',', $this->Application->RecallVar('UserGroups'));
 			$group_access = in_array($group_id, $groups);
 		}
 		return $group_access;
 	}
 
 	/**
 	 * Checks if SSL is on and redirects to SSL URL if needed
 	 * If SSL_URL is not defined in config - the tag does not do anything
 	 * If for_logged_in_only="1" exits if user is not logged in.
 	 * If called without params forces https right away. If called with by_config="1" checks the
 	 * Require SSL setting from General Config and if it is ON forces https
 	 *
 	 * @param unknown_type $params
 	 */
 	function CheckSSL($params)
 	{
 		$ssl = $this->Application->isAdmin ? $this->Application->ConfigValue('AdminSSL_URL') : false;
 
 		if (!$ssl) {
 			// not in admin or admin ssl url is empty
 			$ssl_url = $this->Application->siteDomainField('SSLUrl');
 			$ssl = $ssl_url !== false ? $ssl_url : $this->Application->ConfigValue('SSL_URL');
 		}
 
 		if (!$ssl) {
 			// SSL URL is not set - no way to require SSL
 			return;
 		}
 
 		$require = false;
 
 		if (isset($params['mode']) && $params['mode'] == 'required') {
 			$require = true;
 			if (isset($params['for_logged_in_only']) && $params['for_logged_in_only'] && !$this->Application->LoggedIn()) {
 				$require = false;
 			}
 
 			if (isset($params['condition'])) {
 				if (!$this->Application->ConfigValue($params['condition'])) {
 					$require = false;
 				}
 			}
 		}
 
 		$http_query =& $this->Application->recallObject('HTTPQuery');
 		$pass = $http_query->getRedirectParams();
 		$pass['pass_events'] = 1; // to make sure all events are passed when redirect happens
 
 		if ($require) {
 			if (PROTOCOL == 'https://') {
 				$this->Application->SetVar('__KEEP_SSL__', 1);
 				return;
 			}
 			$this->Application->Redirect('', array_merge_recursive2($pass, Array('__SSL__' => 1)));
 		}
 		else {
 			if (PROTOCOL == 'https://' && $this->Application->ConfigValue('Force_HTTP_When_SSL_Not_Required')) {
 				if ($this->Application->GetVar('__KEEP_SSL__')) return;
 				// $pass_more = Array ('pass' => 'm', 'm_cat_id' => 0, '__SSL__' => 0);
 				$this->Application->Redirect('', array_merge_recursive2($pass, Array('__SSL__' => 0))); // $pass_more
 			}
 		}
 	}
 
 	function ConstOn($params)
 	{
 		$name = $this->SelectParam($params,'name,const');
 		return constOn($name);
 	}
 
 	function SetDefaultCategory($params)
 	{
 		$category_id = $this->Application->findModule('Name', $params['module'], 'RootCat');
 		$this->Application->SetVar('m_cat_id', $category_id);
 	}
 
 	function XMLTemplate($params)
 	{
 		safeDefine('DBG_SKIP_REPORTING', 1);
 
 		if (isset($params['cache']) && $params['cache']) {
 			$nextyear = intval(date('Y') + 1);
 
 			$format = "D, d M Y H:i:s";
 			$expiration = gmdate($format, mktime() + $params['cache']).' GMT';
 			$last_modified = mktime();
 
 			header ('Cache-Control: public, cache, max-age='.$params['cache']);
 			header ("Expires: $expiration");
 			header ('Pragma: public');
 
 			// Getting headers sent by the client.
 			$headers = request_headers();
 
 			// Checking if the client is validating his cache and if it is current.
 			if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) > $last_modified-$params['cache'])) {
 			   // Client's cache IS current, so we just respond '304 Not Modified'.
 			   header('Last-Modified: '.date($format, strtotime($headers['If-Modified-Since'])).' GMT', true, 304);
 			   exit();
 			} else {
 			   // Image not cached or cache outdated, we respond '200 OK' and output the image.
 			   header('Last-Modified: '.gmdate($format, $last_modified).' GMT', true, 200);
 			}
 		}
 
 		// xml documents are usually long
 		set_time_limit(0);
 		ini_set('memory_limit', -1);
 
 		return $this->Application->XMLHeader(getArrayValue($params, 'xml_version'));
 	}
 
 	function Header($params)
 	{
 		header($params['data']);
 	}
 
 	function NoDebug($params)
 	{
 		if (!$this->Application->GetVar('debug')) {
 			define('DBG_SKIP_REPORTING', 1);
 		}
 	}
 
 	function RootCategoryName($params)
 	{
 		$phrase_name = $this->Application->ConfigValue('Root_Name');
 		$no_editing = array_key_exists('no_editing', $params) && $params['no_editing'];
 
 		return $this->Application->Phrase($phrase_name, !$no_editing);
 	}
 
 	/**
 	 * Allows to attach file directly from email event template
 	 *
 	 * @param Array $params
 	 */
 	function AttachFile($params)
 	{
 		$esender =& $application->recallObject('EmailSender'.(isset($params['special']) ? '.'.$params['special'] : ''));
 		/* @var $esender kEmailSendingHelper */
 
 		$path = FULL_PATH.'/'.$params['path'];
 		if (file_exists($path)) {
 			$esender->AddAttachment($path);
 		}
 	}
 
 	function CaptchaImage($params)
 	{
 		$this->NoDebug($params);
 		$this->Application->SetVar('skip_last_template', 1);
 
 		$captcha_helper =& $this->Application->recallObject('CaptchaHelper');
 		/* @var $captcha_helper kCaptchaHelper */
 
 		// generate captcha code
 		$code = $captcha_helper->prepareCode( $this->Application->GetVar('var') );
 
 		$captcha_helper->GenerateCaptchaImage($code, $this->Application->GetVar('w'), $this->Application->GetVar('h'), true);
 	}
 
 	function SID($params)
 	{
 		return $this->Application->GetSID();
 	}
 
 	function ModuleInfo($params)
 	{
 		return $this->Application->findModule($params['key'], $params['value'], $params['return']);
 	}
 
 	function Random($params)
 	{
 		return rand(1, 100000000);
 	}
 
 	/**
 	 * Prints parser params, available at current deep level
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function PrintCurrentParams($params)
 	{
 		$current_params = $this->Application->Parser->Params;
 
 		foreach ($current_params as $param_name => $param_value) {
 			$current_params[$param_name] = $param_name . ' = "' . $param_value . '"';
 		}
 
 		return '<pre>' . implode("\n", $current_params) . '</pre>';
 	}
 
 	/**
 	 * Gets previously defined counter result
 	 *
 	 * @param Array $params
 	 * @return int
 	 */
 	function GetCounter($params)
 	{
 		return $this->Application->getCounter($params['name'], $params);
 	}
 
 	/**
 	 * Increments PageHit counter
 	 *
 	 * @param Array $params
 	 * @return int
 	 */
 	function RegisterPageHit($params)
 	{
 		if ($this->Application->ConfigValue('UsePageHitCounter')) {
 			$db =& $this->Application->GetADODBConnection();
 
 			// get current counte
 			$sql = 'SELECT VariableValue
 					FROM '.TABLE_PREFIX.'ConfigurationValues
 					WHERE VariableName = "PageHitCounter"';
 			$page_counter = (int)$db->GetOne($sql);
 
 			$sql = 'UPDATE LOW_PRIORITY '.TABLE_PREFIX.'ConfigurationValues
 					SET VariableValue = '.($page_counter + 1).'
 					WHERE VariableName = "PageHitCounter"';
 			$db->Query($sql);
 		}
 	}
 
 	function Timestamp($params)
 	{
 		$format = isset($params['format']) ? $params['format'] : 'd.m.Y H:i:s';
 		return adodb_date($format);
 	}
 
 	function GetUrlHiddenFileds($params)
 	{
 		$vars = Array ('page', 'per_page', 'sort_by');
 		$ret = '<input type="hidden" name="main_list" value="1"/>';
 
 		if (array_key_exists('skip', $params)) {
 			$vars = array_diff($vars, $params['skip']);
 		}
 
 		foreach ($vars as $var_name) {
 			$var_value = $this->Application->GetVar($var_name);
 
 			if ($var_value) {
 				$ret .= '<input type="hidden" name="' . $var_name . '" value="' . $var_value . '"/>';
 			}
 		}
 
 		return $ret;
 	}
 }