<?php
/**
* @version	$Id: admin_tag_processor.php 15618 2012-11-07 16:27:32Z alex $
* @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 AdminTagProcessor extends kDBTagProcessor {

		/**
		 * Allows to execute js script after the page is fully loaded
		 *
		 * @param Array $params
		 * @return string
		 */
		function AfterScript($params)
		{
			$after_script = $this->Application->GetVar('after_script');
			if ($after_script) {
				return '<script type="text/javascript">'.$after_script.'</script>';
			}
			return '';
		}

		/**
		 * Returns section title with #section# keyword replaced with current section
		 *
		 * @param Array $params
		 * @return string
		 */
		function GetSectionTitle($params)
		{
			if (array_key_exists('default', $params)) {
				return $params['default'];
			}

			return $this->Application->Phrase( kUtil::replaceModuleSection($params['phrase']) );
		}

		/**
		 * Returns section icon with #section# keyword replaced with current section
		 *
		 * @param Array $params
		 * @return string
		 */
		function GetSectionIcon($params)
		{
			return kUtil::replaceModuleSection($params['icon']);
		}

		/**
		 * Returns version of module by name
		 *
		 * @param Array $params
		 * @return string
		 */
		function ModuleVersion($params)
		{
			return $this->Application->findModule('Name', $params['module'], 'Version');
		}

		/**
		 * Used in table form section drawing
		 *
		 * @param Array $params
		 * @return string
		 */
		function DrawTree($params)
		{
			static $deep_level = 0;

			// when processings, then sort children by priority (key of children array)
			$ret = '';
			$section_name = $params['section_name'];
			$params['name'] = $this->SelectParam($params, 'name,render_as,block');
			$sections_helper = $this->Application->recallObject('SectionsHelper');
			/* @var $sections_helper kSectionsHelper */

			$section_data =& $sections_helper->getSectionData($section_name);

			$params['children_count'] = isset($section_data['children']) ? count($section_data['children']) : 0;
			$params['deep_level'] = $deep_level++;
			$template = $section_data['url']['t'];
			unset($section_data['url']['t']);
			$section_data['section_url'] = $this->Application->HREF($template, '', $section_data['url']);
			$ret .= $this->Application->ParseBlock( array_merge($params, $section_data) );
			if (!isset($section_data['children'])) {
				return $ret;
			}

			ksort($section_data['children'], SORT_NUMERIC);
			foreach ($section_data['children'] as $section_name) {
				if (!$sections_helper->sectionVisible($section_name)) {
					continue;
				}

				$params['section_name'] = $section_name;
				$ret .= $this->DrawTree($params);
				$deep_level--;
			}


			return $ret;
		}


		function SectionInfo($params)
		{
			$section = $params['section'];
			if ($section == '#session#') {
				$section = $this->Application->RecallVar('section');
			}

			$sections_helper = $this->Application->recallObject('SectionsHelper');
			/* @var $sections_helper kSectionsHelper */

			$section_data =& $sections_helper->getSectionData($section);
			if (!$section_data) {
				throw new Exception('Use of undefined section "<strong>' . $section . '</strong>" in "<strong>' . __METHOD__ . '</strong>"');
				return '';
			}

			if (array_key_exists('parent', $params) && $params['parent']) {
				do {
					$section = $section_data['parent'];
					$section_data =& $sections_helper->getSectionData($section);
				} while (array_key_exists('use_parent_header', $section_data) && $section_data['use_parent_header']);
			}

			$info = $params['info'];
			switch ($info) {
				case 'module_path':
					if (isset($params['module']) && $params['module']) {
						$module = $params['module'];
					}
					elseif (isset($section_data['icon_module'])) {
						$module = $section_data['icon_module'];
					}
					else {
						$module = '#session#';
					}
					$res = $this->ModulePath(array('module' => $module));
					break;

				case 'perm_section':
					$res = $sections_helper->getPermSection($section);
					break;

				case 'label':
					$res = '';

					if ( $section ) {
						if ( $section == 'in-portal:root' ) {
							// don't translate label for top section, because it's already translated
							$res = $section_data['label'];
						}
						else {
							$no_editing = array_key_exists('no_editing', $params) ? $params['no_editing'] : false;

							$res = $this->Application->Phrase($section_data['label'], !$no_editing);
						}
					}
					break;

				default:
					$res = $section_data[$info];
					break;
			}

			if (array_key_exists('as_label', $params) && $params['as_label']) {
				$res = $this->Application->Phrase($res);
			}

			return $res;
		}


		function PrintSection($params)
		{
			$section_name = $params['section_name'];
			if ($section_name == '#session#') {
				$section_name = $this->Application->RecallVar('section');
			}

			$sections_helper = $this->Application->recallObject('SectionsHelper');
			/* @var $sections_helper kSectionsHelper */

			if (isset($params['use_first_child']) && $params['use_first_child']) {
				$section_name = $sections_helper->getFirstChild($section_name, true);
			}

			$section_data =& $sections_helper->getSectionData($section_name);

			$params['name'] = $this->SelectParam($params, 'name,render_as,block');
			$params['section_name'] = $section_name;

			$url_params = $section_data['url'];
			unset($url_params['t']);

			$section_data['section_url'] = $this->Application->HREF($section_data['url']['t'], '', $url_params);
			$ret = $this->Application->ParseBlock( array_merge($params, $section_data) );

			return $ret;
		}

		/**
		 * Used in XML drawing for tree
		 *
		 * @param Array $params
		 * @return string
		 */
		function PrintSections($params)
		{
			// when processings, then sort children by priority (key of children array)
			$ret = '';
			$section_name = $params['section_name'];
			if ($section_name == '#session#') {
				$section_name = $this->Application->RecallVar('section');
			}

			$sections_helper = $this->Application->recallObject('SectionsHelper');
			/* @var $sections_helper kSectionsHelper */

			$section_data =& $sections_helper->getSectionData($section_name);

			$params['name'] = $this->SelectParam($params, 'name,render_as,block');
			if (!isset($section_data['children'])) {
				return '';
			}

			ksort($section_data['children'], SORT_NUMERIC);
			foreach ($section_data['children'] as $section_name) {
				$params['section_name'] = $section_name;
				$section_data =& $sections_helper->getSectionData($section_name);

				if (!$sections_helper->sectionVisible($section_name)) {
					continue;
				}
				else {
					$show_mode = isset($section_data['show_mode']) ? $section_data['show_mode'] : smNORMAL;
					$section_data['debug_only'] = ($show_mode == smDEBUG) || ($show_mode == smSUPER_ADMIN) ? 1 : 0;
				}

				if (isset($section_data['tabs_only']) && $section_data['tabs_only']) {
					$perm_status = false;
					$folder_label = $section_data['label'];
					ksort($section_data['children'], SORT_NUMERIC);
					foreach ($section_data['children'] as $priority => $section_name) {
						// if only tabs in this section & none of them have permission, then skip section too

						$section_name = $sections_helper->getPermSection($section_name);
						$perm_status = $this->Application->CheckPermission($section_name.'.view', 1);
						if ($perm_status) {
							break;
						}
					}
					if (!$perm_status) {
						// no permission for all tabs -> don't display tree node either
						continue;
					}

					$params['section_name'] = $section_name;
					$section_data =& $sections_helper->getSectionData($section_name);
					$section_data['label'] = $folder_label; // use folder label in tree
					$section_data['is_tab'] = 1;
				}
				else  {
					$section_name = $sections_helper->getPermSection($section_name);
					if (!$this->Application->CheckPermission($section_name.'.view', 1)) continue;
				}

				$params['children_count'] = isset($section_data['children']) ? count($section_data['children']) : 0;

				// remove template, so it doesn't appear as additional parameter in url
				$template = $section_data['url']['t'];
				unset($section_data['url']['t']);

				$section_data['section_url'] = $this->Application->HREF($template, '', $section_data['url']);

				$late_load = getArrayValue($section_data, 'late_load');
				if ($late_load) {
					$t = $late_load['t'];
					unset($late_load['t']);
					$section_data['late_load'] = $this->Application->HREF($t, '', $late_load);
					$params['children_count'] = 99;
				}
				else {
					$section_data['late_load'] = '';
				}

				// restore template
				$section_data['url']['t'] = $template;

				$ret .= $this->Application->ParseBlock( array_merge($params, $section_data) );
				$params['section_name'] = $section_name;
			}

			return preg_replace("/\r\n|\n/", '', $ret);
		}

		function ListSectionPermissions($params)
		{
			$section_name = isset($params['section_name']) ? $params['section_name'] : $this->Application->GetVar('section_name');

			$sections_helper = $this->Application->recallObject('SectionsHelper');
			/* @var $sections_helper kSectionsHelper */

			$section_data =& $sections_helper->getSectionData($section_name);

			$block_params = array_merge($section_data, Array('name' => $params['render_as'], 'section_name' => $section_name));

			$ret = '';
			foreach ($section_data['permissions'] as $perm_name) {
				if (preg_match('/^advanced:(.*)/', $perm_name) != $params['type']) continue;
				$block_params['perm_name'] = $perm_name;
				$ret .= $this->Application->ParseBlock($block_params);
			}
			return $ret;
		}

		function ModuleInclude($params)
		{
			foreach ($params as $param_name => $param_value) {
				$params[$param_name] = kUtil::replaceModuleSection($param_value);
			}

			return $this->Application->ProcessParsedTag('m', 'ModuleInclude', $params);
		}

		function TodayDate($params)
		{
			return date($params['format']);
		}

		function TreeEditWarrning($params)
		{
			$ret = $this->Application->Phrase($params['label']);
			$ret = str_replace(Array('&lt;', '&gt;', 'br/', 'br /', "\n", "\r"), Array('<', '>', 'br', 'br', '', ''), $ret);
			if (getArrayValue($params, 'escape')) {
				$ret = addslashes($ret);
			}
			$ret = str_replace('<br>', '\n', $ret);
			return $ret;
		}

		/**
		 * Draws section tabs using block name passed
		 *
		 * @param Array $params
		 */
		function ListTabs($params)
		{
			$sections_helper = $this->Application->recallObject('SectionsHelper');
			/* @var $sections_helper kSectionsHelper */

			$section_data =& $sections_helper->getSectionData($params['section_name']);

			$ret = '';
			$block_params = Array('name' => $params['render_as']);
			ksort($section_data['children'], SORT_NUMERIC);
			foreach ($section_data['children'] as $priority => $section_name) {
				$perm_section = $sections_helper->getPermSection($section_name);

				if ( !$this->Application->CheckPermission($perm_section.'.view') ) {
					continue;
				}

				$tab_data =& $sections_helper->getSectionData($section_name);
				$block_params['t'] = $tab_data['url']['t'];
				$block_params['pass'] = $tab_data['url']['pass'];
				$block_params['title'] = $tab_data['label'];
				$block_params['main_prefix'] = $section_data['SectionPrefix'];
				$ret .= $this->Application->ParseBlock($block_params);
			}


			return $ret;
		}

		/**
		 * Returns list of module item tabs that have view permission in current category
		 *
		 * @param Array $params
		 */
		function ListCatalogTabs($params)
		{
			$ret = '';
			$special = isset($params['special']) ? $params['special'] : '';
			$replace_main = isset($params['replace_m']) && $params['replace_m'];
			$skip_prefixes = isset($params['skip_prefixes']) ? explode(',', $params['skip_prefixes']) : Array();

			$block_params = $this->prepareTagParams($params);
			$block_params['name'] = $params['render_as'];

			foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
				$prefix = $module_info['Var'];

				if ($prefix == 'm' && $replace_main) {
					$prefix = 'c';
				}

				if (in_array($prefix, $skip_prefixes) || !$this->Application->prefixRegistred($prefix) || !$this->Application->getUnitOption($prefix, 'CatalogItem')) {
					continue;
				}

				$icon = $this->Application->getUnitOption($prefix, 'CatalogTabIcon');
				if (strpos($icon, ':') !== false) {
					list ($icon_module, $icon) = explode(':', $icon, 2);
				}
				else {
					$icon_module = 'core';
				}

				$label = $this->Application->getUnitOption($prefix, $params['title_property']);
				$block_params['title'] = $label;
				$block_params['prefix'] = $prefix;
				$block_params['icon_module'] = $icon_module;
				$block_params['icon'] = $icon;
				$ret .= $this->Application->ParseBlock($block_params);
			}
			return $ret;
		}

		/**
		 * Renders inividual catalog tab based on prefix and title_property given
		 *
		 * @param Array $params
		 * @return string
		 */
		function CatalogTab($params)
		{
			$icon = $this->Application->getUnitOption($params['prefix'], 'CatalogTabIcon');
			if (strpos($icon, ':') !== false) {
				list ($icon_module, $icon) = explode(':', $icon, 2);
			}
			else {
				$icon_module = 'core';
			}

			$block_params = $this->prepareTagParams($params);
			$block_params['name'] = $params['render_as'];
			$block_params['icon_module'] = $icon_module;
			$block_params['icon'] = $icon;
			$block_params['title'] = $this->Application->getUnitOption($params['prefix'], $params['title_property']);

			return $this->Application->ParseBlock($block_params);
		}

		/**
		 * Allows to construct link for opening any type of catalog item selector
		 *
		 * @param Array $params
		 * @return string
		 */
		function SelectorLink($params)
		{
			$mode = 'catalog';
			if (isset($params['mode'])) { // {catalog, advanced_view}
				$mode = $params['mode'];
				unset($params['mode']);
			}

			$params['t'] = 'catalog/item_selector/item_selector_'.$mode;
			$params['m_cat_id'] = $this->Application->getBaseCategory();

			$default_params = Array('no_amp' => 1, 'pass' => 'all,'.$params['prefix']);
			unset($params['prefix']);

			$pass_through = Array();
			if (isset($params['tabs_dependant'])) { // {yes, no}
				$pass_through['td'] = $params['tabs_dependant'];
				unset($params['tabs_dependant']);
			}

			if (isset($params['selection_mode'])) { // {single, multi}
				$pass_through['tm'] = $params['selection_mode'];
				unset($params['selection_mode']);
			}

			if (isset($params['tab_prefixes'])) { // {all, none, <comma separated prefix list>}
				$pass_through['tp'] = $params['tab_prefixes'];
				unset($params['tab_prefixes']);
			}

			if ($pass_through) {
				// add pass_through to selector url if any
				$params['pass_through'] = implode(',', array_keys($pass_through));
				$params = array_merge($params, $pass_through);
			}

			// user can override default parameters (except pass_through of course)
			$params = array_merge($default_params, $params);

	    	return $this->Application->ProcessParsedTag('m', 'T', $params);
		}

		function TimeFrame($params)
		{
			$w = adodb_date('w');
			$m = adodb_date('m');
			$y = adodb_date('Y');

			//FirstDayOfWeek is 0 for Sunday and 1 for Monday
			$fdow = $this->Application->ConfigValue('FirstDayOfWeek');

			if ( $fdow && $w == 0 ) {
				$w = 7;
			}
			$today_start = adodb_mktime(0, 0, 0, adodb_date('m'), adodb_date('d'), $y);
			$first_day_of_this_week = $today_start - ($w - $fdow) * 86400;
			$first_day_of_this_month = adodb_mktime(0, 0, 0, $m, 1, $y);
			$this_quater = ceil($m / 3);
			$this_quater_start = adodb_mktime(0, 0, 0, $this_quater * 3 - 2, 1, $y);

			switch ( $params['type'] ) {
				case 'last_week_start':
					$timestamp = $first_day_of_this_week - 86400 * 7;
					break;

				case 'last_week_end':
					$timestamp = $first_day_of_this_week - 1;
					break;

				case 'last_month_start':
					$timestamp = $m == 1 ? adodb_mktime(0, 0, 0, 12, 1, $y - 1) : adodb_mktime(0, 0, 0, $m - 1, 1, $y);
					break;

				case 'last_month_end':
					$timestamp = $first_day_of_this_month = adodb_mktime(0, 0, 0, $m, 1, $y) - 1;
					break;

				case 'last_quater_start':
					$timestamp = $this_quater == 1 ? adodb_mktime(0, 0, 0, 10, 1, $y - 1) : adodb_mktime(0, 0, 0, ($this_quater - 1) * 3 - 2, 1, $y);
					break;

				case 'last_quater_end':
					$timestamp = $this_quater_start - 1;
					break;

				case 'last_6_months_start':
					$timestamp = $m <= 6 ? adodb_mktime(0, 0, 0, $m + 6, 1, $y - 1) : adodb_mktime(0, 0, 0, $m - 6, 1, $y);
					break;

				case 'last_year_start':
					$timestamp = adodb_mktime(0, 0, 0, 1, 1, $y - 1);
					break;

				case 'last_year_end':
					$timestamp = adodb_mktime(23, 59, 59, 12, 31, $y - 1);
					break;

				default:
					$timestamp = 0;
					break;
			}

			if ( isset($params['format']) ) {
				$format = $params['format'];

				if ( preg_match("/_regional_(.*)/", $format, $regs) ) {
					$lang = $this->Application->recallObject('lang.current');
					/* @var $lang LanguagesItem */

					$format = $lang->GetDBField($regs[1]);
				}

				return adodb_date($format, $timestamp);
			}

			return $timestamp;
		}

		/**
		 * Redirect to cache rebuild template, when required by installator
		 *
		 * @param Array $params
		 */
		function CheckPermCache($params)
		{
			// we have separate session between install wizard and admin console, so store in cache
			$global_mark = $this->Application->getDBCache('ForcePermCacheUpdate');
			$local_mark = $this->Application->RecallVar('PermCache_UpdateRequired');

			if ( $global_mark || $local_mark ) {
				$this->Application->RemoveVar('PermCache_UpdateRequired');
				$rebuild_mode = $this->Application->ConfigValue('CategoryPermissionRebuildMode');

				if ( $rebuild_mode == CategoryPermissionRebuild::SILENT ) {
					$updater = $this->Application->makeClass('kPermCacheUpdater');
					/* @var $updater kPermCacheUpdater */

					$updater->OneStepRun();

					$this->Application->HandleEvent(new kEvent('c:OnResetCMSMenuCache'));
				}
				elseif ( $rebuild_mode == CategoryPermissionRebuild::AUTOMATIC ) {
					// update with progress bar
					return true;
				}
			}

			return false;
		}

		/**
		 * Checks if current protocol is SSL
		 *
		 * @param Array $params
		 * @return int
		 */
		function IsSSL($params)
		{
			return (PROTOCOL == 'https://')? 1 : 0;
		}

		function PrintColumns($params)
		{
			$picker_helper = $this->Application->recallObject('ColumnPickerHelper');
			$picker_helper->SetGridName($this->Application->GetLinkedVar('grid_name'));
			/* @var $picker_helper kColumnPickerHelper */

			$main_prefix = $this->Application->RecallVar('main_prefix');
			$cols = $picker_helper->LoadColumns($main_prefix);

			$this->Application->Phrases->AddCachedPhrase('__FREEZER__', '-------------');

			$o = '';
			if (isset($params['hidden']) && $params['hidden']) {
				foreach ($cols['hidden_fields'] as $col) {
					$title = $this->Application->Phrase($cols['titles'][$col]);
					$o .= "<option value='$col'>".$title;
				}
			}
			else {
				foreach ($cols['order'] as $col) {
					if (in_array($col, $cols['hidden_fields'])) continue;
					$title = $this->Application->Phrase($cols['titles'][$col]);
					$o .= "<option value='$col'>".$title;
				}
			}
			return $o;
		}

		/**
		 * Allows to set popup size (key - current template name)
		 *
		 * @param Array $params
		 * @return string
		 * @access protected
		 */
		protected function SetPopupSize($params)
		{
			$width = $params['width'];
			$height = $params['height'];

			if ( $this->Application->GetVar('ajax') == 'yes' ) {
				// during AJAX request just output size
				die($width . 'x' . $height);
			}

			if ( !$this->UsePopups($params) ) {
				return;
			}

			$t = $this->Application->GetVar('t');

			$sql = 'SELECT *
					FROM ' . TABLE_PREFIX . 'PopupSizes
					WHERE TemplateName = ' . $this->Conn->qstr($t);
			$popup_info = $this->Conn->GetRow($sql);

			if ( !$popup_info ) {
				// create new popup size record
				$fields_hash = Array (
					'TemplateName' => $t,
					'PopupWidth' => $width,
					'PopupHeight' => $height,
				);

				$this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'PopupSizes');
			}
			elseif ( $popup_info['PopupWidth'] != $width || $popup_info['PopupHeight'] != $height ) {
				// popup found and size in tag differs from one in db -> update in db
				$fields_hash = Array (
					'PopupWidth' => $width,
					'PopupHeight' => $height,
				);

				$this->Conn->doUpdate($fields_hash, TABLE_PREFIX . 'PopupSizes', 'PopupId = ' . $popup_info['PopupId']);
			}
		}

		/**
		 * Allows to check if popups are generally enabled OR to check for "popup" or "modal" mode is enabled
		 *
		 * @param Array $params
		 * @return bool
		 */
		function UsePopups($params)
		{
			if ($this->Application->GetVar('_force_popup')) {
				return true;
			}

			$use_popups = (int)$this->Application->ConfigValue('UsePopups');

			if (array_key_exists('mode', $params)) {
				$mode_mapping = Array ('popup' => 1, 'modal' => 2);
				return $use_popups == $mode_mapping[ $params['mode'] ];
			}

			return $use_popups;
		}

		function UseToolbarLabels($params)
		{
			return (int)$this->Application->ConfigValue('UseToolbarLabels');
		}

		/**
		 * Checks if debug mode enabled (optionally) and specified constant is on
		 *
		 * @param Array $params
		 * @return bool
		 * @todo Could be a duplicate of kMainTagProcessor::ConstOn
		 */
		function ConstOn($params)
		{
			$constant_name = $this->SelectParam($params, 'name,const');
			$debug_mode = isset($params['debug_mode']) && $params['debug_mode'] ? $this->Application->isDebugMode() : true;

			return $debug_mode && kUtil::constOn($constant_name);
		}

		/**
		 * Builds link to last template in main frame of admin
		 *
		 * @param Array $params
		 * @return string
		 */
		function MainFrameLink($params)
		{
			$persistent = isset($params['persistent']) && $params['persistent'];
			if ($persistent && $this->Application->ConfigValue('RememberLastAdminTemplate')) {
				// check last_template in persistent session
				$last_template = $this->Application->RecallPersistentVar('last_template_popup');
			}
			else {
				// check last_template in session
				$last_template = $this->Application->RecallVar('last_template_popup'); // because of m_opener=s there
			}

			if (!$last_template) {
				$params['persistent'] = 1;
				return $persistent ? false : $this->MainFrameLink($params);
			}

			list($index_file, $env) = explode('|', $last_template);
			$vars = $this->Application->processQueryString($env, 'pass');
			$recursion_templates = Array ('login', 'index', 'no_permission');

			if (isset($vars['admin']) && $vars['admin'] == 1) {
				// index template doesn't begin recursion on front-end (in admin frame)
				$vars['m_theme'] = '';

				if (isset($params['m_opener']) && $params['m_opener'] == 'r') {
					// front-end link for highlighting purposes
					$vars['t'] = 'index';
					$vars['m_cat_id'] = $this->Application->getBaseCategory();
				}

				unset($recursion_templates[ array_search('index', $recursion_templates)]);
			}

			if (in_array($vars['t'], $recursion_templates)) {
				// prevents redirect recursion OR old in-portal pages
				$params['persistent'] = 1;
				return $persistent ? false : $this->MainFrameLink($params);
			}

			$vars = array_merge($vars, $params);
			$t = $vars['t'];
			unset($vars['t'], $vars['persistent']);

			// substitute language in link to current (link will work, even when language will be changed)
			$vars['m_lang'] = $this->Application->GetVar('m_lang');

			return $this->Application->HREF($t, '', $vars, $index_file);
		}

		/**
		 * Returns menu frame width or 200 in case, when invalid width specified in config
		 *
		 * @param Array $params
		 * @return string
		 */
		function MenuFrameWidth($params)
		{
			$width = (int)$this->Application->ConfigValue('MenuFrameWidth');

			return $width > 0 ? $width : 200;
		}

		function AdminSkin($params)
		{
			$skin_helper = $this->Application->recallObject('SkinHelper');
			/* @var $skin_helper SkinHelper */

			return $skin_helper->AdminSkinTag($params);
		}

		/**
		 * Prints errors, discovered during mass template compilation
		 *
		 * @param $params
		 * @return string
		 * @access protected
		 */
		protected function PrintCompileErrors($params)
		{
			$block_params = $this->prepareTagParams($params);
			$block_params['name'] = $params['render_as'];

			$errors = $this->Application->RecallVar('compile_errors');
			if ( !$errors ) {
				return '';
			}

			$ret = '';
			$errors = unserialize($errors);
			$path_regexp = '/^' . preg_quote(FULL_PATH, '/') . '/';

			foreach ($errors as $an_error) {
				$block_params = array_merge($block_params, $an_error);
				$block_params['file'] = preg_replace($path_regexp, '', $an_error['file'], 1);

				$ret .= $this->Application->ParseBlock($block_params);
			}

			$this->Application->RemoveVar('compile_errors');

			return $ret;
		}

		function CompileErrorCount($params)
		{
			$errors = $this->Application->RecallVar('compile_errors');
			if (!$errors) {
				return 0;
			}

			return count( unserialize($errors) );
		}

		/**
		 * Detects if given exception isn't one caused by tag error
		 *
		 * @param Array $params
		 * @return string
		 * @access protected
		 */
		protected function IsParserException($params)
		{
			return mb_strtolower($params['class']) == 'parserexception';
		}

		function ExportData($params)
		{
			$export_helper = $this->Application->recallObject('CSVHelper');
			/* @var $export_helper kCSVHelper */
			$result = $export_helper->ExportData( $this->SelectParam($params, 'var,name,field') );
			return ($result === false) ? '' : $result;
		}

		function ImportData($params)
		{
			$import_helper = $this->Application->recallObject('CSVHelper');
			/* @var $import_helper kCSVHelper */
			$result = $import_helper->ImportData( $this->SelectParam($params, 'var,name,field') );
			return ($result === false) ? '' : $result;
		}

		function PrintCSVNotImportedLines($params)
		{
			$import_helper = $this->Application->recallObject('CSVHelper');
			/* @var $import_helper kCSVHelper */
			return  $import_helper->GetNotImportedLines();
		}

		/**
		 * Returns input field name to
		 * be placed on form (for correct
		 * event processing)
		 *
		 * @param Array $params
		 * @return string
		 * @access public
		 */
		function InputName($params)
		{
			list($id, $field) = $this->prepareInputName($params);

			$ret = $this->getPrefixSpecial().'[0]['.$field.']'; // 0 always, as has no idfield
			if( getArrayValue($params, 'as_preg') ) $ret = preg_quote($ret, '/');
			return $ret;
		}

		/**
		 * Returns list of all backup file dates formatted
		 * in passed block
		 *
		 * @param Array $params
		 * @return string
		 * @access public
		 */
		function PrintBackupDates($params)
		{
	 		$backup_helper = $this->Application->recallObject('BackupHelper');
			/* @var $backup_helper BackupHelper */

			$ret = '';
			$dates = $backup_helper->getBackupFiles();

			foreach ($dates as $date) {
				$params['backuptimestamp'] = $date['filedate'];
				$params['backuptime'] = date('F j, Y, g:i a', $date['filedate']);
				$params['backupsize'] = round($date['filesize'] / 1024 / 1024, 2); // MBytes

				$ret .= $this->Application->ParseBlock($params);
			}

	        return $ret;
		}

		/**
		 * Returns phpinfo() output
		 *
		 * @param Array $params
		 * @return string
		 */
		function PrintPHPinfo($params)
		{
			ob_start();
			phpinfo();

			return ob_get_clean();
		}

		function PrintSqlCols($params)
		{
			$ret = '';
			$block = $params['render_as'];
			$a_data = unserialize($this->Application->GetVar('sql_rows'));

			$a_row = current($a_data);

			foreach ($a_row AS $col => $value) {
				$ret .= $this->Application->ParseBlock(Array ('name' => $block, 'value' => $col));
			}

			return $ret;
		}

		function PrintSqlRows($params)
		{
			$ret = '';
			$block = $params['render_as'];
			$a_data = unserialize($this->Application->GetVar('sql_rows'));

			foreach ($a_data as $a_row) {
				$cells = '';
				$a_row = array_map('htmlspecialchars', $a_row);

				foreach ($a_row as $value) {
					$cells .= '<td>' . $value . '</td>';
				}

				$ret .= $this->Application->ParseBlock(Array ('name' => $block, 'cells' => $cells));
			}

			return $ret;
		}

		/**
		 * Prints available and enabled import sources using given block
		 *
		 * @param Array $params
		 * @return string
		 */
		function PrintImportSources($params)
 		{
 			$sql = 'SELECT *
 					FROM ' . TABLE_PREFIX . 'ImportScripts
 					WHERE (Status = ' . STATUS_ACTIVE . ') AND (Type = "CSV")';
 			$import_sources = $this->Conn->Query($sql);

 			$block_params = $this->prepareTagParams($params);
 			$block_params['name'] = $params['render_as'];

 			$ret = '';
 			foreach ($import_sources as $import_source) {
 				$block_params['script_id'] = $import_source['ImportId'];
 				$block_params['script_module'] = mb_strtolower($import_source['Module']);
 				$block_params['script_name'] = $import_source['Name'];
 				$block_params['script_prefix'] = $import_source['Prefix'];
 				$block_params['module_path'] = $this->Application->findModule('Name', $import_source['Module'], 'Path');

 				$ret .= $this->Application->ParseBlock($block_params);
 			}

 			return $ret;
 		}

 		/**
 		 * Checks, that new window should be opened in "incs/close_popup" template instead of refreshing parent window
 		 *
 		 * @param Array $params
 		 * @return bool
 		 */
 		function OpenNewWindow($params)
 		{
			if (!$this->UsePopups($params)) {
				return false;
			}

 			$diff = array_key_exists('diff', $params) ? $params['diff'] : 0;
 			$wid = $this->Application->GetVar('m_wid');

			$stack_name = rtrim('opener_stack_' . $wid, '_');
			$opener_stack = $this->Application->RecallVar($stack_name);
			$opener_stack = $opener_stack ? unserialize($opener_stack) : Array ();

			return count($opener_stack) >= 2 - $diff;
 		}

		/**
		 * Allows to dynamically change current language in template
		 *
		 * @param Array $params
		 */
		function SetLanguage($params)
		{
			$this->Application->SetVar('m_lang', $params['language_id']);
			$this->Application->Phrases->Init('phrases', '', $params['language_id']);
		}

		/**
		 * Performs HTTP Authentification for administrative console
		 *
		 * @param Array $params
		 * @return bool
		 */
		function HTTPAuth($params)
		{
			if ( !$this->Application->ConfigValue('UseHTTPAuth') ) {
				// http authentification not required
				return true;
			}

			$super_admin_ips = defined('SA_IP') ? SA_IP : false;
			$auth_bypass_ips = $this->Application->ConfigValue('HTTPAuthBypassIPs');

			if ( ($auth_bypass_ips && kUtil::ipMatch($auth_bypass_ips)) || ($super_admin_ips && kUtil::ipMatch($super_admin_ips)) ) {
				// user ip is in ip bypass list
				return true;
			}

			if ( !array_key_exists('PHP_AUTH_USER', $_SERVER) ) {
				// ask user to authentificate, when not authentificated before
				return $this->_httpAuthentificate();
			}
			else {
				// validate user credentials (browsers remembers user/password
				// and sends them each time page is visited, so no need to save
				// authentification result in session)
				if ( $this->Application->ConfigValue('HTTPAuthUsername') != $_SERVER['PHP_AUTH_USER'] ) {
					// incorrect username
					return $this->_httpAuthentificate();
				}

				$password_formatter = $this->Application->recallObject('kPasswordFormatter');
				/* @var $password_formatter kPasswordFormatter */

				if ( !$password_formatter->checkPasswordFromSetting('HTTPAuthPassword', $_SERVER['PHP_AUTH_PW']) ) {
					// incorrect password
					return $this->_httpAuthentificate();
				}
			}

			return true;
		}

		/**
		 * Ask user to authentificate
		 *
		 * @return bool
		 */
		function _httpAuthentificate()
		{
			$realm = strip_tags( $this->Application->ConfigValue('Site_Name') );
			header('WWW-Authenticate: Basic realm="' . $realm . '"');
			header('HTTP/1.0 401 Unauthorized');

			return false;
		}

		/**
		 * Checks, that we are using memory cache
		 *
		 * @param Array $params
		 * @return bool
		 */
		function MemoryCacheEnabled($params)
		{
			return $this->Application->isCachingType(CACHING_TYPE_MEMORY);
		}
	}