Index: branches/5.1.x/core/units/categories/categories_tag_processor.php
===================================================================
--- branches/5.1.x/core/units/categories/categories_tag_processor.php	(revision 13203)
+++ branches/5.1.x/core/units/categories/categories_tag_processor.php	(revision 13204)
@@ -1,1919 +1,1922 @@
 <?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.
 */
 
 class CategoriesTagProcessor extends kDBTagProcessor {
 
 	function SubCatCount($params)
 	{
 		$object =& $this->getObject($params);
 
 		if (isset($params['today']) && $params['today']) {
 			$sql = 'SELECT COUNT(*)
 					FROM '.$object->TableName.'
 					WHERE (ParentPath LIKE "'.$object->GetDBField('ParentPath').'%") AND (CreatedOn > '.(adodb_mktime() - 86400).')';
 			return $this->Conn->GetOne($sql) - 1;
 		}
 
 		return $object->GetDBField('CachedDescendantCatsQty');
 	}
 
 	/**
 	 * Returns category count in system
 	 *
 	 * @param Array $params
 	 * @return int
 	 */
 	function CategoryCount($params)
 	{
 		$count_helper =& $this->Application->recallObject('CountHelper');
 		/* @var $count_helper kCountHelper */
 
 		$today_only = isset($params['today']) && $params['today'];
 		return $count_helper->CategoryCount($today_only);
 	}
 
 	function IsNew($params)
 	{
 		$object =& $this->getObject($params);
 		return $object->GetDBField('IsNew') ? 1 : 0;
 	}
 
 	function IsPick($params)
 	{
 		return $this->IsEditorsPick($params);
 	}
 
 	/**
 	 * Returns item's editors pick status (using not formatted value)
 	 *
 	 * @param Array $params
 	 * @return bool
 	 */
 	function IsEditorsPick($params)
 	{
 		$object =& $this->getObject($params);
 
 		return $object->GetDBField('EditorsPick') == 1;
 	}
 
 	function ItemIcon($params)
 	{
 		$grids = $this->Application->getUnitOption($this->Prefix, 'Grids');
 		$grid = $grids[ $params['grid'] ];
 
 		if (!array_key_exists('Icons', $grid)) {
 			return '';
 		}
 
 		$icons = $grid['Icons'];
 
 		if (array_key_exists('name', $params)) {
 			$icon_name = $params['name'];
 			return array_key_exists($icon_name, $icons) ? $icons[$icon_name] : '';
 		}
 
 		$object =& $this->getObject($params);
 		/* @var $object kDBList */
 
 		if ($object->GetDBField('CreatedBySystem')) {
 			if (!$object->GetDBField('IsMenu')) {
 				return 'icon16_section_menuhidden_system.png';
 			}
 			return 'icon16_section_system.png';
 		}
 
 		$status = $object->GetDBField('Status');
 
 		if ($status == STATUS_DISABLED) {
 			return 'icon16_section_disabled.png';
 		}
 
 		if (!$object->GetDBField('IsMenu')) {
 			return 'icon16_section_menuhidden.png';
 		}
 
 		if ($status == STATUS_PENDING) {
 			return 'icon16_section_pending.png';
 		}
 
 		if ($object->GetDBField('IsNew')) {
 			return 'icon16_section_new.png';
 		}
 
 		return 'icon16_section.png';
 	}
 
 	function ItemCount($params)
 	{
 		$object =& $this->getObject($params);
 		$ci_table = $this->Application->getUnitOption('l-ci', 'TableName');
 
 		$sql = 'SELECT COUNT(*)
 				FROM ' . $object->TableName . ' c
 				LEFT JOIN ' . $ci_table . ' ci ON c.CategoryId = ci.CategoryId
 				WHERE (c.TreeLeft BETWEEN ' . $object->GetDBField('TreeLeft') . ' AND ' . $object->GetDBField('TreeRight') . ') AND NOT (ci.CategoryId IS NULL)';
 		return $this->Conn->GetOne($sql);
 	}
 
 	function ListCategories($params)
 	{
 		return $this->PrintList2($params);
 	}
 
 	function RootCategoryName($params)
 	{
 		return $this->Application->ProcessParsedTag('m', 'RootCategoryName', $params);
 	}
 
 	function CheckModuleRoot($params)
 	{
 		$module_name = getArrayValue($params, 'module') ? $params['module'] : 'In-Commerce';
 		$module_root_cat = $this->Application->findModule('Name', $module_name, 'RootCat');
 
 		$additional_cats = $this->SelectParam($params, 'add_cats');
 		if ($additional_cats) {
 			$additional_cats = explode(',', $additional_cats);
 		}
 		else {
 			$additional_cats = array();
 		}
 
 		if ($this->Application->GetVar('m_cat_id') == $module_root_cat || in_array($this->Application->GetVar('m_cat_id'), $additional_cats)) {
 			$home_template = getArrayValue($params, 'home_template');
 			if (!$home_template) return;
 			$this->Application->Redirect($home_template, Array('pass'=>'all'));
 		};
 	}
 
 	function CategoryPath($params)
 	{
 		$category_helper =& $this->Application->recallObject('CategoryHelper');
 		/* @var $category_helper CategoryHelper */
 
 		return $category_helper->NavigationBar($params);
 	}
 
 	/**
 	 * Shows category path to specified category
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function FieldCategoryPath($params)
 	{
 		$object =& $this->getObject();
 		/* @var $object kDBItem */
 
 		$field = $this->SelectParam($params, 'name,field');
 		$category_id = $object->GetDBField($field);
 
 		if ($category_id) {
 			$params['cat_id'] = $category_id;
 			return $this->CategoryPath($params);
 		}
 
 		return '';
 	}
 
 	function CurrentCategoryName($params)
 	{
 		$cat_object =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix.'_List');
 		$sql = 'SELECT '.$this->getTitleField().'
 				FROM '.$cat_object->TableName.'
 				WHERE CategoryId = '.(int)$this->Application->GetVar('m_cat_id');
 		return $this->Conn->GetOne($sql);
 	}
 
 	/**
 	 * Returns current category name
 	 *
 	 * @param Array $params
 	 * @return string
 	 * @todo Find where it's used
 	 */
 	function CurrentCategory($params)
 	{
 		return $this->CurrentCategoryName($params);
 	}
 
 	function getTitleField()
 	{
 		$ml_formatter =& $this->Application->recallObject('kMultiLanguage');
 		return $ml_formatter->LangFieldName('Name');
 	}
 
 	/**
 	 * Returns symlinked category for given category
 	 *
 	 * @param $category_id
 	 */
 	function getCategorySymLink($category_id)
 	{
 		if (!$category_id) {
 			// don't bother to get symlink for "Home" category
 			return $category_id;
 		}
 
 		$cache_key = 'category_symlinks[%CSerial%]';
 		$cache = $this->Application->getCache($cache_key);
 
 		if ($cache === false) {
 			$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
 			$table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
 
 			// get symlinked categories, that are not yet deleted
 			$this->Conn->nextQueryCachable = true;
 			$sql = 'SELECT c1.SymLinkCategoryId, c1.' . $id_field . '
 					FROM ' . $table_name . ' c1
 					JOIN ' . $table_name . ' c2 ON c1.SymLinkCategoryId = c2.' . $id_field;
 			$cache = $this->Conn->GetCol($sql, $id_field);
 
 			$this->Application->setCache($cache_key, $cache);
 		}
 
 		return array_key_exists($category_id, $cache) ? $cache[$category_id] : $category_id;
 	}
 
 	function CategoryLink($params)
 	{
 		$category_id = getArrayValue($params, 'cat_id');
 
 		if ($category_id === false) {
 			$category_id = $this->Application->GetVar($this->getPrefixSpecial() . '_id');
 		}
 
 		if ("$category_id" == 'Root') {
 			$category_id = $this->Application->findModule('Name', $params['module'], 'RootCat');
 		}
 		elseif ("$category_id" == 'current') {
 			$category_id = $this->Application->GetVar('m_cat_id');
 		}
 
 		$category_id = $this->getCategorySymLink( (int)$category_id );
 
 		unset($params['cat_id'], $params['module']);
 
 		$new_params = Array ('pass' => 'm', 'm_cat_id' => $category_id, 'pass_category' => 1);
 		$params = array_merge_recursive2($params, $new_params);
 
 		return $this->Application->ProcessParsedTag('m', 't', $params);
 	}
 
 	function CategoryList($params)
 	{
 		//$object =& $this->Application->recallObject( $this->getPrefixSpecial() , $this->Prefix.'_List', $params );
 		$object =& $this->GetList($params);
 
 
 		if ($object->RecordsCount == 0)
 		{
 			if (isset($params['block_no_cats'])) {
 				$params['name'] = $params['block_no_cats'];
 				return $this->Application->ParseBlock($params);
 			}
 			else {
 				return '';
 			}
 		}
 
 		if (isset($params['block'])) {
 			return $this->PrintList($params);
 		}
 		else {
 			$params['block'] = $params['block_main'];
 			if (isset($params['block_row_start'])) {
 				$params['row_start_block'] = $params['block_row_start'];
 			}
 
 			if (isset($params['block_row_end'])) {
 				$params['row_end_block'] = $params['block_row_end'];
 			}
 			return $this->PrintList2($params);
 		}
 	}
 
 	function Meta($params)
 	{
 		$object =& $this->Application->recallObject($this->Prefix); // .'.-item'
 		/* @var $object CategoriesItem */
 
 		$meta_type = $params['name'];
 		if ($object->isLoaded()) {
 			// 1. get module prefix by current category
 			$category_helper =& $this->Application->recallObject('CategoryHelper');
 			/* @var $category_helper CategoryHelper */
 
 			$category_path = explode('|', substr($object->GetDBField('ParentPath'), 1, -1));
 			$module_info = $category_helper->getCategoryModule($params,  $category_path);
 
 			// In-Edit & Proj-CMS module prefixes doesn't have custom field with item template
 			if ($module_info && $module_info['Var'] != 'adm' && $module_info['Var'] != 'st') {
 
 				// 2. get item template by current category & module prefix
 				$mod_rewrite_helper = $this->Application->recallObject('ModRewriteHelper');
 				/* @var $mod_rewrite_helper kModRewriteHelper */
 
 				$category_params = Array (
 				'CategoryId' => $object->GetID(),
 				'ParentPath' => $object->GetDBField('ParentPath'),
 				);
 
 				$item_template = $mod_rewrite_helper->GetItemTemplate($category_params, $module_info['Var']);
 
 				if ($this->Application->GetVar('t') == $item_template) {
 					// we are located on item's details page
 					$item =& $this->Application->recallObject($module_info['Var']);
 					/* @var $item kCatDBItem */
 
 					// 3. get item's meta data
 					$value = $item->GetField('Meta'.$meta_type);
 					if ($value) {
 						return $value;
 					}
 				}
 
 				// 4. get category meta data
 				$value = $object->GetField('Meta'.$meta_type);
 				if ($value) {
 					return $value;
 				}
 			}
 		}
 
 		// 5. get default meta data
 		switch ($meta_type) {
 			case 'Description':
 				$config_name = 'Category_MetaDesc';
 				break;
 			case 'Keywords':
 				$config_name = 'Category_MetaKey';
 				break;
 		}
 
 		return $this->Application->ConfigValue($config_name);
 	}
 
 	function BuildListSpecial($params)
 	{
 		if (($this->Special != '') && !is_numeric($this->Special)) {
 			// When recursive category list is printed (like in sitemap), then special
 			// should be generated even if it's already present. Without it list on this
 			// level will erase list on previous level, because it will be stored in same object.
 			return $this->Special;
 		}
 
 		if ( isset($params['parent_cat_id']) ) {
 			$parent_cat_id = $params['parent_cat_id'];
 		}
 		else {
 			$parent_cat_id = $this->Application->GetVar($this->Prefix.'_id');
 			if (!$parent_cat_id) {
 				$parent_cat_id = $this->Application->GetVar('m_cat_id');
 			}
 			if (!$parent_cat_id) {
 				$parent_cat_id = 0;
 			}
 		}
 
 		$list_unique_key = $this->getUniqueListKey($params);
 		// check for "admin" variable, because we are parsing front-end template from admin when using template editor feature
 		if ($this->Application->GetVar('admin') || !$this->Application->isAdmin) {
 			// add parent category to special, when on Front-End,
 			// because there can be many category lists on same page
 			$list_unique_key .= $parent_cat_id;
 		}
 
 		if ($list_unique_key == '') {
 			return parent::BuildListSpecial($params);
 		}
 
 		return crc32($list_unique_key);
 	}
 
 	function IsCurrent($params)
 	{
 		$object =& $this->getObject($params);
 		if ($object->GetID() == $this->Application->GetVar('m_cat_id')) {
 			return true;
 		}
 		else {
 			return false;
 		}
 	}
 
 	/**
 	 * Substitutes category in last template base on current category
 	 * This is required becasue when you navigate catalog using AJAX, last_template is not updated
 	 * but when you open item edit from catalog last_template is used to build opener_stack
 	 * So, if we don't substitute m_cat_id in last_template, after saving item we'll get redirected
 	 * to the first category we've opened, not the one we navigated to using AJAX
 	 *
 	 * @param Array $params
 	 */
 	function UpdateLastTemplate($params)
 	{
 		$category_id = $this->Application->GetVar('m_cat_id');
 
 		$wid = $this->Application->GetVar('m_wid');
 		list($index_file, $env) = explode('|', $this->Application->RecallVar(rtrim('last_template_'.$wid, '_')), 2);
 
 		$vars_backup = Array ();
 		$vars = $this->Application->HttpQuery->processQueryString( str_replace('%5C', '\\', $env) );
 
 		foreach ($vars as $var_name => $var_value) {
 			$vars_backup[$var_name] = $this->Application->GetVar($var_name);
 			$this->Application->SetVar($var_name, $var_value);
 		}
 
 		// update required fields
 		$this->Application->SetVar('m_cat_id', $category_id);
 		$this->Application->Session->SaveLastTemplate($params['template']);
 
 		foreach ($vars_backup as $var_name => $var_value) {
 			$this->Application->SetVar($var_name, $var_value);
 		}
 	}
 
 	function GetParentCategory($params)
 	{
 		$parent_id = 0;
 		$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
 		$table = $this->Application->getUnitOption($this->Prefix,'TableName');
 		$cat_id = $this->Application->GetVar('m_cat_id');
 		if ($cat_id > 0) {
 			$sql = 'SELECT ParentId
 					FROM '.$table.'
 					WHERE '.$id_field.' = '.$cat_id;
 			$parent_id = $this->Conn->GetOne($sql);
 		}
 		return $parent_id;
 	}
 
 	function InitCacheUpdater($params)
 	{
 		safeDefine('CACHE_PERM_CHUNK_SIZE', 30);
 
 		$continue = $this->Application->GetVar('continue');
 		$total_cats = (int) $this->Conn->GetOne('SELECT COUNT(*) FROM '.TABLE_PREFIX.'Category');
 
 		if ($continue === false && $total_cats > CACHE_PERM_CHUNK_SIZE) {
 			// first step, if category count > CACHE_PERM_CHUNK_SIZE, then ask for cache update
 			return true;
 		}
 
 		if ($continue === false) {
 			// if we don't have to ask, then assume user selected "Yes" in permcache update dialog
 			$continue = 1;
 		}
 
 		$updater =& $this->Application->recallObject('kPermCacheUpdater', null, Array('continue' => $continue));
 		/* @var $updater kPermCacheUpdater */
 		if ($continue === '0') { // No in dialog
 			$updater->clearData();
 			$this->Application->Redirect($params['destination_template']);
 		}
 
 		$ret = false; // don't ask for update
 		if ($continue == 1) {  // Initial run
 			$updater->setData();
 		}
 		if ($continue == 2) { // Continuing
 			// called from AJAX request => returns percent
 			$needs_more = true;
 			while ($needs_more && $updater->iteration <= CACHE_PERM_CHUNK_SIZE) {
 				// until proceeeded in this step category count exceeds category per step limit
 				$needs_more = $updater->DoTheJob();
 			}
 
 			if ($needs_more) {
 				// still some categories are left for next step
 				$updater->setData();
 			}
 			else {
 				// all done -> redirect
 				$updater->SaveData();
 				$this->Application->RemoveVar('PermCache_UpdateRequired');
 				$this->Application->Redirect($params['destination_template']);
 			}
 
 			$ret = $updater->getDonePercent();
 		}
 		return $ret;
 	}
 
 	/**
 	 * Parses warning block, but with style="display: none;". Used during permissions saving from AJAX
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function SaveWarning($params)
 	{
 		if ($this->Prefix == 'st') {
 			// don't use this method for other prefixes then Category, that use this tag processor
 			return parent::SaveWarning($params);
 		}
 
 		$main_prefix = getArrayValue($params, 'main_prefix');
 		if ($main_prefix && $main_prefix != '$main_prefix') {
 			$top_prefix = $main_prefix;
 		}
 		else {
 			$top_prefix = $this->Application->GetTopmostPrefix($this->Prefix);
 		}
 
 		$temp_tables = substr($this->Application->GetVar($top_prefix.'_mode'), 0, 1) == 't';
 		$modified = $this->Application->RecallVar($top_prefix.'_modified');
 
 		if (!$temp_tables) {
 			$this->Application->RemoveVar($top_prefix.'_modified');
 			return '';
 		}
 
 		$block_name = $this->SelectParam($params, 'render_as,name');
 		if ($block_name) {
 			$block_params = $this->prepareTagParams($params);
 			$block_params['name'] = $block_name;
 			$block_params['edit_mode'] = $temp_tables ? 1 : 0;
 			$block_params['display'] = $temp_tables && $modified ? 1 : 0;
 			return $this->Application->ParseBlock($block_params);
 		}
 		else {
 			return $temp_tables && $modified ? 1 : 0;
 		}
 		return ;
 	}
 
 	/**
 	 * Allows to detect if this prefix has something in clipboard
 	 *
 	 * @param Array $params
 	 * @return bool
 	 */
 	function HasClipboard($params)
 	{
 		$clipboard = $this->Application->RecallVar('clipboard');
 		if ($clipboard) {
 			$clipboard = unserialize($clipboard);
 			foreach ($clipboard as $prefix => $clipboard_data) {
 				foreach ($clipboard_data as $mode => $ids) {
 					if (count($ids)) return 1;
 				}
 			}
 		}
 		return 0;
 	}
 
 	/**
 	 * Allows to detect if root category being edited
 	 *
 	 * @param Array $params
 	 */
 	function IsRootCategory($params)
 	{
 		$object =& $this->getObject($params);
 		return $object->IsRoot();
 	}
 
 	/**
 	 * Returns home category id
 	 *
 	 * @param Array $params
 	 * @return int
 	 */
 	function HomeCategory($params)
 	{
 		static $root_category = null;
 
 		if (!isset($root_category)) {
 			$root_category = $this->Application->findModule('Name', 'Core', 'RootCat');
 		}
 
 		return $root_category;
 	}
 
 	/**
 	 * Used for disabling "Home" and "Up" buttons in category list
 	 *
 	 * @param Array $params
 	 * @return bool
 	 */
 	function ModuleRootCategory($params)
 	{
 		return $this->Application->GetVar('m_cat_id') == $this->HomeCategory($params);
 	}
 
 	function CatalogItemCount($params)
 	{
 		$params['skip_quering'] = true;
 		$object =& $this->GetList($params);
 
 		if (!$object->Counted) {
 			$object->CountRecs();
 		}
 
 		return $object->NoFilterCount != $object->RecordsCount ? $object->RecordsCount.' / '.$object->NoFilterCount : $object->RecordsCount;
 	}
 
 	function InitCatalog($params)
 	{
 		$tab_prefixes = $this->Application->GetVar('tp'); // {all, <prefixes_list>, none}
 		if ($tab_prefixes === false) $tab_prefixes = 'all';
 		$skip_prefixes = isset($params['skip_prefixes']) && $params['skip_prefixes'] ? explode(',', $params['skip_prefixes']) : Array();
 		$replace_main = isset($params['replace_m']) && $params['replace_m'];
 
 		// get all prefixes available
 		$prefixes = Array();
 		foreach ($this->Application->ModuleInfo as $module_name => $module_data) {
 			$prefix = $module_data['Var'];
 
 			if ($prefix == 'adm'/* || $prefix == 'm'*/) continue;
 
 			if ($prefix == 'm' && $replace_main) {
 				$prefix = 'c';
 			}
 
 			$prefixes[] = $prefix;
 		}
 
 		if ($tab_prefixes == 'none') {
 			$skip_prefixes = array_unique(array_merge($skip_prefixes, $prefixes));
 			unset($skip_prefixes[ array_search($replace_main ? 'c' : 'm', $skip_prefixes) ]);
 		}
 		elseif ($tab_prefixes != 'all') {
 			// prefix list here
 			$tab_prefixes = explode(',', $tab_prefixes); // list of prefixes that should stay
 			$skip_prefixes = array_unique(array_merge($skip_prefixes, array_diff($prefixes, $tab_prefixes)));
 		}
 
 		$params['name'] = $params['render_as'];
 		$params['skip_prefixes'] = implode(',', $skip_prefixes);
 		return $this->Application->ParseBlock($params, 1);
 	}
 
 	/**
 	 * Determines, that printed category/menu item is currently active (will also match parent category)
 	 *
 	 * @param Array $params
 	 * @return bool
 	 */
 	function IsActive($params)
 	{
 		static $current_path = null;
 
 		if (!isset($current_path)) {
 			$sql = 'SELECT ParentPath
 					FROM ' . TABLE_PREFIX . 'Category
 					WHERE CategoryId = ' . (int)$this->Application->GetVar('m_cat_id');
 			$current_path = $this->Conn->GetOne($sql);
 		}
 
 		if (array_key_exists('parent_path', $params)) {
 			$test_path = $params['parent_path'];
 		}
 		else {
 			$template = $params['template'];
 			if ($template) {
 				// when using from "c:CachedMenu" tag
 				$sql = 'SELECT ParentPath
 						FROM ' . TABLE_PREFIX . 'Category
 						WHERE NamedParentPath = ' . $this->Conn->qstr('Content/' . $template);
 				$test_path = $this->Conn->GetOne($sql);
 			}
 			else {
 				// when using from "c:PrintList" tag
 				$cat_id = array_key_exists('cat_id', $params) && $params['cat_id'] ? $params['cat_id'] : false;
 				if ($cat_id === false) {
 					// category not supplied -> get current from PrintList
 					$category =& $this->getObject($params);
 				}
 				else {
 					if ("$cat_id" == 'Root') {
 						$cat_id = $this->Application->findModule('Name', $params['module'], 'RootCat');
 					}
 
 					$category =& $this->Application->recallObject($this->Prefix . '.-c' . $cat_id, $this->Prefix, Array ('skip_autoload' => true));
 					$category->Load($cat_id);
 				}
 
 				$test_path = $category->GetDBField('ParentPath');
 			}
 		}
 
 		return strpos($current_path, $test_path) !== false;
 	}
 
 	/**
 	 * Checks if user have one of required permissions
 	 *
 	 * @param Array $params
 	 * @return bool
 	 */
 	function HasPermission($params)
 	{
 		$perm_helper =& $this->Application->recallObject('PermissionsHelper');
 		/* @var $perm_helper kPermissionsHelper */
 
 		$params['raise_warnings'] = 0;
 		$object =& $this->getObject($params);
 		/* @var $object kDBItem */
 
 		$params['cat_id'] = $object->isLoaded() ? $object->GetDBField('ParentPath') : $this->Application->GetVar('m_cat_id');
 		return $perm_helper->TagPermissionCheck($params);
 	}
 
 	/**
 	 * Prepares name for field with event in it (used only on front-end)
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function SubmitName($params)
 	{
 		return 'events[' . $this->Prefix . '][' . $params['event'] . ']';
 	}
 
 	/**
 	 * Returns last modification date of items in category / system
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function LastUpdated($params)
 	{
 		$category_id = (int)$this->Application->GetVar('m_cat_id');
 		$local = array_key_exists('local', $params) && ($category_id > 0) ? $params['local'] : false;
 
 		$serial_name = $this->Application->incrementCacheSerial('c', $local ? $category_id : null, false);
 		$cache_key = 'category_last_updated[%' . $serial_name . '%]';
 
 		$row_data = $this->Application->getCache($cache_key);
 
 		if ($row_data === false) {
 			if ($local && ($category_id > 0)) {
 				// scan only current category & it's children
 				list ($tree_left, $tree_right) = $this->Application->getTreeIndex($category_id);
 
 				$sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate
 		        		FROM ' . TABLE_PREFIX . 'Category
 		        		WHERE TreeLeft BETWEEN ' . $tree_left . ' AND ' . $tree_right;
 			}
 			else {
 				// scan all categories in system
 				$sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate
 		       			FROM ' . TABLE_PREFIX . 'Category';
 			}
 
 			$this->Conn->nextQueryCachable = true;
 			$row_data = $this->Conn->GetRow($sql);
 			$this->Application->setCache($cache_key, $row_data);
 		}
 
 		if (!$row_data) {
 			return '';
 		}
 
 		$date = $row_data[ $row_data['NewDate'] > $row_data['ModDate'] ? 'NewDate' : 'ModDate' ];
 
 		// format date
 		$format = isset($params['format']) ? $params['format'] : '_regional_DateTimeFormat';
 		if (preg_match("/_regional_(.*)/", $format, $regs)) {
 			$lang =& $this->Application->recallObject('lang.current');
 			if ($regs[1] == 'DateTimeFormat') {
 				// combined format
 				$format = $lang->GetDBField('DateFormat') . ' ' . $lang->GetDBField('TimeFormat');
 			}
 			else {
 				// simple format
 				$format = $lang->GetDBField($regs[1]);
 			}
 		}
 
 		return adodb_date($format, $date);
 	}
 
 	function CategoryItemCount($params)
 	{
 		$object =& $this->getObject($params);
 		/* @var $object kDBList */
 
 		$params['cat_id'] = $object->GetID();
 
 		$count_helper =& $this->Application->recallObject('CountHelper');
 		/* @var $count_helper kCountHelper */
 
 		return $count_helper->CategoryItemCount($params['prefix'], $params);
 	}
 
 	/**
 	 * Returns prefix + any word (used for shared between categories per page settings)
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function VarName($params)
 	{
 		return $this->Prefix.'_'.$params['type'];
 	}
 
 	/**
 	 * Checks if current category is valid symbolic link to another category
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function IsCategorySymLink($params)
 	{
 		$object =& $this->getObject($params);
 		/* @var $object kDBList */
 
 		$sym_category_id = $object->GetDBField('SymLinkCategoryId');
 
 		if (is_null($sym_category_id))
 		{
 			return false;
 		}
 
 		$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
 		$table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
 
 		$sql = 'SELECT '.$id_field.'
 				FROM '.$table_name.'
 				WHERE '.$id_field.' = '.$sym_category_id;
 
 		return $this->Conn->GetOne($sql)? true : false;
 	}
 
 	/**
 	 * Returns module prefix based on root category for given
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function GetModulePrefix($params)
 	{
 		$object =& $this->getObject($params);
 		/* @var $object kDBItem */
 
 		$parent_path = explode('|', substr($object->GetDBField('ParentPath'), 1, -1));
 
 		$category_helper =& $this->Application->recallObject('CategoryHelper');
 		/* @var $category_helper CategoryHelper */
 
 		$module_info = $category_helper->getCategoryModule($params, $parent_path);
 		return $module_info['Var'];
 	}
 
 	function ImageSrc($params)
 	{
 		list ($ret, $tag_processed) = $this->processAggregatedTag('ImageSrc', $params, $this->getPrefixSpecial());
 		return $tag_processed ? $ret : false;
 	}
 
 	function PageLink($params)
 	{
 		$params['m_cat_page'] = $this->Application->GetVar($this->getPrefixSpecial() . '_Page');
 
 		return parent::PageLink($params);
 	}
 
 	/**
 	 * Returns spelling suggestions against search keyword
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function SpellingSuggestions($params)
 	{
 		$keywords = unhtmlentities( trim($this->Application->GetVar('keywords')) );
 		if (!$keywords) {
 			return ;
 		}
 
 		// 1. try to get already cached suggestion
 		$cache_key = 'search.suggestion[%SpellingDictionary%]:' . $keywords;
 		$suggestion = $this->Application->getCache($cache_key);
 
 		if ($suggestion !== false) {
 			return $suggestion;
 		}
 
 		$table_name = $this->Application->getUnitOption('spelling-dictionary', 'TableName');
 
 		// 2. search suggestion in database
 		$this->Conn->nextQueryCachable = true;
 		$sql = 'SELECT SuggestedCorrection
 				FROM ' . $table_name . '
 				WHERE MisspelledWord = ' . $this->Conn->qstr($keywords);
 		$suggestion = $this->Conn->GetOne($sql);
 
 		if ($suggestion !== false) {
 			$this->Application->setCache($cache_key, $suggestion);
 			return $suggestion;
 		}
 
 		// 3. suggestion not found in database, ask webservice
 		$app_id = $this->Application->ConfigValue('YahooApplicationId');
 		$url = 'http://search.yahooapis.com/WebSearchService/V1/spellingSuggestion?appid=' . $app_id . '&query=';
 
 		$curl_helper =& $this->Application->recallObject('CurlHelper');
 		/* @var $curl_helper kCurlHelper */
 
 		$xml_data = $curl_helper->Send($url . urlencode($keywords));
 
 		$xml_helper =& $this->Application->recallObject('kXMLHelper');
 		/* @var $xml_helper kXMLHelper */
 
 		$root_node =& $xml_helper->Parse($xml_data);
 
 		$result = $root_node->FindChild('RESULT');
 		/* @var $result kXMLNode */
 
 		if (is_object($result)) {
 			// webservice responded -> save in local database
 			$fields_hash = Array (
 			'MisspelledWord' => $keywords,
 			'SuggestedCorrection' => $result->Data,
 			);
 
 			$this->Conn->doInsert($fields_hash, $table_name);
 			$this->Application->setCache($cache_key, $result->Data);
 
 			return $result->Data;
 		}
 
 		return '';
 	}
 
 	/**
 	 * Shows link for searching by suggested word
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function SuggestionLink($params)
 	{
 		$params['keywords'] = $this->SpellingSuggestions($params);
 
 		return $this->Application->ProcessParsedTag('m', 'Link', $params);
 	}
 
 	function InitCatalogTab($params)
 	{
 		$tab_params['mode'] = $this->Application->GetVar('tm'); // single/multi selection possible
 		$tab_params['special'] = $this->Application->GetVar('ts'); // use special for this tab
 		$tab_params['dependant'] = $this->Application->GetVar('td'); // is grid dependant on categories grid
 
 		// set default params (same as in catalog)
 		if ($tab_params['mode'] === false) $tab_params['mode'] = 'multi';
 		if ($tab_params['special'] === false) $tab_params['special'] = '';
 		if ($tab_params['dependant'] === false) $tab_params['dependant'] = 'yes';
 
 		// pass params to block with tab content
 		$params['name'] = $params['render_as'];
 		$special = $tab_params['special'] ? $tab_params['special'] : $this->Special;
 		$params['prefix'] = trim($this->Prefix.'.'.$special, '.');
 
 		$prefix_append = $this->Application->GetVar('prefix_append');
 		if ($prefix_append) {
 			$params['prefix'] .= $prefix_append;
 		}
 
 		$default_grid = array_key_exists('default_grid', $params) ? $params['default_grid'] : 'Default';
 		$radio_grid = array_key_exists('radio_grid', $params) ? $params['radio_grid'] : 'Radio';
 
 		$params['cat_prefix'] = trim('c.'.($tab_params['special'] ? $tab_params['special'] : $this->Special), '.');
 		$params['tab_mode'] = $tab_params['mode'];
 		$params['grid_name'] = ($tab_params['mode'] == 'multi') ? $default_grid : $radio_grid;
 		$params['tab_dependant'] = $tab_params['dependant'];
 		$params['show_category'] = $tab_params['special'] == 'showall' ? 1 : 0; // this is advanced view -> show category name
 
 		if ($special == 'showall' || $special == 'user') {
 			$params['grid_name'] .= 'ShowAll';
 		}
 
 		return $this->Application->ParseBlock($params, 1);
 	}
 
 	/**
 	 * Show CachedNavbar of current item primary category
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function CategoryName($params)
 	{
 		// show category cachednavbar of
 		$object =& $this->getObject($params);
 		$category_id = isset($params['cat_id']) ? $params['cat_id'] : $object->GetDBField('CategoryId');
 
 		$cache_key = 'category_paths[%CIDSerial:' . $category_id . '%]';
 
 		if ($category_id == 0) {
 			// home category name is phrase AND phrase name is defined in configuration
 			$cache_key .= '[%PhrasesSerial%][%ConfSerial%]';
 		}
 
 		$category_path = $this->Application->getCache($cache_key);
 
 		if ($category_path === false) {
 			// not chached
 			if ($category_id > 0) {
 				$cached_navbar = $object->GetField('CachedNavbar');
 
 				if ($category_id == $object->GetDBField('ParentId')) {
 					// parent category cached navbar is one element smaller, then current ones
 					$cached_navbar = explode('&|&', $cached_navbar);
 					array_pop($cached_navbar);
 					$cached_navbar = implode('&|&', $cached_navbar);
 				}
 				else {
 					// no relation with current category object -> query from db
 					$language_id = (int)$this->Application->GetVar('m_lang');
 					if (!$language_id) {
 						$language_id = 1;
 					}
 
 					$sql = 'SELECT l' . $language_id . '_CachedNavbar
 							FROM ' . $object->TableName . '
 							WHERE ' . $object->IDField . ' = ' . $category_id;
 					$cached_navbar = $this->Conn->GetOne($sql);
 				}
 
 				$cached_navbar = preg_replace('/^(Content&\|&|Content)/i', '', $cached_navbar);
 
 				$category_path = trim($this->CategoryName( Array('cat_id' => 0) ).' > '.str_replace('&|&', ' > ', $cached_navbar), ' > ');
 			}
 			else {
 				$category_path = $this->Application->Phrase( $this->Application->ConfigValue('Root_Name') );
 			}
 
 			$this->Application->setCache($cache_key, $category_path);
 		}
 
 		return $category_path;
 	}
 
 	// structure related
 
 	/**
 	 * Returns page object based on requested params
 	 *
 	 * @param Array $params
 	 * @return PagesItem
 	 */
 	function &_getPage($params)
 	{
 		$page =& $this->Application->recallObject($this->Prefix . '.-virtual', null, $params);
 		/* @var $page kDBItem */
 
 		// 1. load by given id
 		$page_id = array_key_exists('page_id', $params) ? $params['page_id'] : false;
 		if ($page_id) {
 			if ($page_id != $page->GetID()) {
 				// load if different
 				$page->Load($page_id);
 			}
 
 			return $page;
 		}
 
 		// 2. load by template
 		$template = array_key_exists('page', $params) ? $params['page'] : '';
 		if (!$template) {
 			$template = $this->Application->GetVar('t');
 		}
 
 		// different path in structure AND design template differes from requested template
 		$structure_path_match = strtolower( $page->GetDBField('NamedParentPath') ) == strtolower('Content/' . $template);
 		$design_match = $page->GetDBField('CachedTemplate') == $template;
 
 		if (!$structure_path_match && !$design_match) {
 			// Same sql like in "c:getPassedID". Load, when current page object doesn't match requested page object
 			$themes_helper =& $this->Application->recallObject('ThemesHelper');
 			/* @var $themes_helper kThemesHelper */
 
 			$page_id = $themes_helper->getPageByTemplate($template);
 
 			$page->Load($page_id);
 		}
 
 		return $page;
 	}
 
 	/**
 	 * Returns requested content block content of current or specified page
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function ContentBlock($params)
 	{
 		$num = getArrayValue($params, 'num');
 		if (!$num) {
 			return 'NO CONTENT NUM SPECIFIED';
 		}
 
 		$page =& $this->_getPage($params);
 		/* @var $page kDBItem */
 
 		if (!$page->isLoaded()) {
 			// page is not created yet => all blocks are empty
 			return '';
 		}
 
 		$page_id = $page->GetID();
 
 		$content =& $this->Application->recallObject('content.-block', null, Array ('skip_autoload' => true));
 		/* @var $content kDBItem */
 
 		$data = Array ('PageId' => $page_id, 'ContentNum' => $num);
 		$content->Load($data);
 
 		if (!$content->isLoaded()) {
 			// bug: missing content blocks are created even if user have no SMS-management rights
 			$content->SetFieldsFromHash($data);
 			$content->Create();
 		}
 
 		$edit_code_before = $edit_code_after = '';
 
 		if (EDITING_MODE == EDITING_MODE_CONTENT) {
 			$bg_color = isset($params['bgcolor']) ? $params['bgcolor'] : '#ffffff';
 			$url_params = Array (
 				'pass'			=>	'm,c,content',
 				'm_opener'		=>	'd',
 				'c_id'			=>	$page->GetID(),
 				'content_id'	=>	$content->GetID(),
 				'front'			=>	1,
 				'admin'			=>	1,
 				'__URLENCODE__'	=>	1,
 				'__NO_REWRITE__'=>	1,
 				'escape'		=>	1,
 				'index_file' => 'index.php',
 //				'bgcolor' => $bg_color,
 //				'__FORCE_SID__' => 1
 			);
 
 			// link from Front-End to admin, don't remove "index.php"
 			$edit_url = $this->Application->HREF('categories/edit_content', ADMIN_DIRECTORY, $url_params, 'index.php');
 			$edit_code_before = '
 				<div class="cms-edit-btn-container">
 					<div class="cms-edit-btn" onclick="$form_name=\'kf_cont_'.$content->GetID().'\'; std_edit_item(\'content\', \'categories/edit_content\');">
 						<div class="cms-btn-image">
 							<img src="' . $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/content_mode.png" width="15" height="16" alt=""/>
 						</div>
 						<div class="cms-btn-text">' . $this->Application->Phrase('la_btn_EditContent', false, true) . ' '.(defined('DEBUG_MODE') && DEBUG_MODE ? " - #{$num}" : '').'</div>
 					</div>
 					<div class="cms-btn-content">';
 
 			$edit_form = '<form method="POST" style="display: inline; margin: 0px" name="kf_cont_'.$content->GetID().'" id="kf_cont_'.$content->GetID().'" action="'.$edit_url.'">';
 			$edit_form .= '<input type="hidden" name="c_id" value="'.$page->GetID().'"/>';
 			$edit_form .= '<input type="hidden" name="content_id" value="'.$content->GetID().'"/>';
 			$edit_form .= '<input type="hidden" name="front" value="1"/>';
 			$edit_form .= '<input type="hidden" name="bgcolor" value="'.$bg_color.'"/>';
 			$edit_form .= '<input type="hidden" name="m_lang" value="'.$this->Application->GetVar('m_lang').'"/>';
 			$edit_form .= '</form>';
 
 			$edit_code_after = '</div></div>';
 
 			if (array_key_exists('forms_later', $params) && $params['forms_later']) {
 				$all_forms = $this->Application->GetVar('all_forms');
 				$this->Application->SetVar('all_forms', $all_forms . $edit_form);
 			}
 			else {
 				$edit_code_after .= $edit_form;
 			}
 		}
 
 		if ($this->Application->GetVar('_editor_preview_') == 1) {
 			$data = $this->Application->RecallVar('_editor_preview_content_');
 		} else {
 			$data = $content->GetField('Content');
 		}
 
 		$data = $edit_code_before . $this->_transformContentBlockData($data, $params) . $edit_code_after;
 
 		if ($data != '') {
 			$this->Application->Parser->DataExists = true;
 		}
 
 		return $data;
 	}
 
 	/**
 	 * Apply all kinds of content block data transformations without rewriting ContentBlock tag
 	 *
 	 * @param string $data
 	 * @return string
 	 */
 	function _transformContentBlockData(&$data, $params)
 	{
 		return $data;
 	}
 
 	/**
 	 * Returns current page name or page based on page/page_id parameters
 	 *
 	 * @param Array $params
 	 * @return string
 	 * @todo Used?
 	 */
 	function PageName($params)
 	{
 		$page =& $this->_getPage($params);
 
 		return $page->GetDBField('Name');
 	}
 
 	/**
 	 * Returns current/given page information
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function PageInfo($params)
 	{
 		$page =& $this->_getPage($params);
 
 		if ($params['type'] == 'index_tools') {
 			$page_info = $page->GetDBField('IndexTools');
 			if ($page_info) {
 				return $page_info;
 			}
 			else {
 				if (PROTOCOL == 'https://') {
 					return $this->Application->ConfigValue('cms_DefaultIndextoolsCode_SSL');
 				}
 				else {
 					return $this->Application->ConfigValue('cms_DefaultIndextoolsCode');
 				}
 			}
 		}
 
 		switch ($params['type']) {
 			case 'title':
 				$db_field = 'Title';
 				break;
 
 			case 'htmlhead_title':
 				$db_field = 'Name';
 				break;
 
 			case 'meta_title':
 				$db_field = 'MetaTitle';
 				break;
 
 			case 'meta_keywords':
 				$db_field = 'MetaKeywords';
 				$cat_field = 'Keywords';
 				break;
 
 			case 'meta_description':
 				$db_field = 'MetaDescription';
 				$cat_field = 'Description';
 				break;
 
 			default:
 				return '';
 		}
 
 		$default = isset($params['default']) ? $params['default'] : '';
 		$val = $page->GetField($db_field);
 		if (!$default) {
 			if ($this->Application->isModuleEnabled('In-Portal')) {
 				if (!$val && ($params['type'] == 'meta_keywords' || $params['type'] == 'meta_description')) {
 					// take category meta if it's not set for the page
 					return $this->Application->ProcessParsedTag('c', 'Meta', Array('name' => $cat_field));
 				}
 			}
 		}
 
 		if (isset($params['force_default']) && $params['force_default']) {
 			return $default;
 		}
 
 		if (preg_match('/^_Auto:/', $val)) {
 			$val = $default;
 
 			/*if ($db_field == 'Title') {
 				$page->SetDBField($db_field, $default);
 				$page->Update();
 			}*/
 		}
 		elseif ($page->GetID() == false) {
 			return $default;
 		}
 
 		return $val;
 	}
 
 	/**
 	 * Includes admin css and js, that are required for cms usage on Front-Edn
 	 *
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function EditingScripts($params)
 	{
 		if ($this->Application->GetVar('admin_scripts_included') || !EDITING_MODE) {
 			return ;
 		}
 
 		$this->Application->SetVar('admin_scripts_included', 1);
 
 		$js_url = $this->Application->BaseURL() . 'core/admin_templates/js';
 
 		$ret = '<link rel="stylesheet" href="' . $js_url . '/jquery/thickbox/thickbox.css" type="text/css" media="screen"/>' . "\n";
 		$ret .= '<link rel="stylesheet" href="' . $js_url . '/../incs/cms.css" type="text/css" media="screen"/>' . "\n";
 
 		if (EDITING_MODE == EDITING_MODE_DESIGN) {
 			$ret .= '	<style type="text/css" media="all">
 							div.movable-element .movable-header { cursor: move; }
 						</style>';
 		}
 
 		$ret .= '<script type="text/javascript" src="' . $js_url . '/jquery/jquery.pack.js"></script>' . "\n";
 		$ret .= '<script type="text/javascript" src="' . $js_url . '/jquery/jquery-ui.custom.min.js"></script>' . "\n";
 		$ret .= '<script type="text/javascript" src="' . $js_url . '/is.js"></script>' . "\n";
 		$ret .= '<script type="text/javascript" src="' . $js_url . '/application.js"></script>' . "\n";
 		$ret .= '<script type="text/javascript" src="' . $js_url . '/script.js"></script>' . "\n";
 		$ret .= '<script type="text/javascript" src="' . $js_url . '/jquery/thickbox/thickbox.js"></script>' . "\n";
 		$ret .= '<script type="text/javascript" src="' . $js_url . '/template_manager.js"></script>' . "\n";
 		$ret .= '<script language="javascript">' . "\n";
 		$ret .= "TB.pathToImage = '" . $js_url . "/jquery/thickbox/loadingAnimation.gif';" . "\n";
 
 		$template = $this->Application->GetVar('t');
 		$theme_id = $this->Application->GetVar('m_theme');
 
 		$url_params = Array ('block' => '#BLOCK#', 'theme-file_event' => '#EVENT#', 'theme_id' => $theme_id, 'source' => $template, 'pass' => 'all,theme-file', 'front' => 1, 'm_opener' => 'd', '__NO_REWRITE__' => 1, 'no_amp' => 1);
 		$edit_template_url = $this->Application->HREF('themes/template_edit', ADMIN_DIRECTORY, $url_params, 'index.php');
 
 		$url_params = Array ('theme-file_event' => 'OnSaveLayout', 'source' => $template, 'pass' => 'all,theme-file', '__NO_REWRITE__' => 1, 'no_amp' => 1);
 		$save_layout_url = $this->Application->HREF('index', '', $url_params);
 
 		$this_url = $this->Application->HREF('', '', Array ('editing_mode' => '#EDITING_MODE#', '__NO_REWRITE__' => 1, 'no_amp' => 1));
 		$ret .= "var aTemplateManager = new TemplateManager('" . $edit_template_url . "', '" . $this_url . "', '" . $save_layout_url . "', " . (int)EDITING_MODE . ");\n";
 		$ret .= "var main_title = '" . addslashes( $this->Application->ConfigValue('Site_Name') ) . "';" . "\n";
 
 		$use_popups = (int)$this->Application->ConfigValue('UsePopups');
 		$ret .= "var \$use_popups = " . ($use_popups > 0 ? 'true' : 'false') . ";\n";
 		$ret .= "var \$modal_windows = " . ($use_popups == 2 ? 'true' : 'false') . ";\n";
 
 		if (EDITING_MODE != EDITING_MODE_BROWSE) {
 			$ret .= "var base_url = '" . $this->Application->BaseURL() . "';" . "\n";
 			$ret .= 'TB.closeHtml = \'<img src="' . $js_url . '/../img/close_window15.gif" width="15" height="15" style="border-width: 0px;" alt="close"/><br/>\';' . "\n";
 
 			$url_params = Array('m_theme' => '', 'pass' => 'm', 'm_opener' => 'r', '__NO_REWRITE__' => 1, 'no_amp' => 1);
 			$browse_url = $this->Application->HREF('catalog/catalog', ADMIN_DIRECTORY, $url_params, 'index.php');
 			$browse_url = preg_replace('/&(admin|editing_mode)=[\d]/', '', $browse_url);
 
 			$ret .= '
 				var topmost = window.top;
 
 				topmost.document.title = document.title + \' - ' . addslashes($this->Application->Phrase('la_AdministrativeConsole', false)) . '\';
 				t = \''.$this->Application->GetVar('t').'\';
 
 				if (window.parent.frames["menu"] != undefined) {
 					if ( $.isFunction(window.parent.frames["menu"].SyncActive) ) {
 						window.parent.frames["menu"].SyncActive("' . $browse_url . '");
 					}
 				}
 			';
 		}
 
 		$ret .= '</script>' . "\n";
 
 		if (EDITING_MODE != EDITING_MODE_BROWSE) {
 			// add form, so admin scripts could work
 			$ret .= '<form id="kernel_form" name="kernel_form" enctype="multipart/form-data" method="post" action="' . $browse_url . '">
 						<input type="hidden" name="MAX_FILE_SIZE" id="MAX_FILE_SIZE" value="' . MAX_UPLOAD_SIZE . '" />
 						<input type="hidden" name="sid" id="sid" value="' . $this->Application->GetSID() . '" />
 					</form>';
 		}
 
 		return $ret;
 	}
 
 	/**
 	 * Prints "Edit Page" button on cms page
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function EditPage($params)
 	{
 		if (!EDITING_MODE) {
 			return '';
 		}
 
 		$display_mode = array_key_exists('mode', $params) ? $params['mode'] : false;
 		$edit_code = '';
 
 		$page =& $this->_getPage($params);
 
 		if (!$page->isLoaded() || (($display_mode != 'end') && (EDITING_MODE == EDITING_MODE_BROWSE))) {
 			// when "EditingScripts" tag is not used, make sure, that scripts are also included
 			return $this->EditingScripts($params);
 		}
 
 		// show "EditPage" button only for pages, that exists in structure
 		if ($display_mode != 'end') {
 			$edit_btn = '';
 
 			if (EDITING_MODE == EDITING_MODE_CONTENT) {
 				$url_params = Array(
 					'pass'			=>	'm,c',
 					'm_opener'		=>	'd',
 					'c_id'			=>	$page->GetID(),
 					'c_mode'		=>	't',
 					'c_event'		=>	'OnEdit',
 					'front'			=>	1,
 					'__URLENCODE__'	=>	1,
 					'__NO_REWRITE__'=>	1,
 					'escape'		=>	1,
 					'index_file' => 'index.php',
 				);
 
 				$edit_url = $this->Application->HREF('categories/categories_edit', ADMIN_DIRECTORY, $url_params);
 
 				$edit_btn .= '
 					<div class="cms-section-properties-btn"' . ($display_mode === false ? ' style="margin: 0px;"' : '') . ' onmouseover="window.status=\''.$edit_url.'\'; return true" onclick="$form_name=\'kf_'.$page->GetID().'\'; std_edit_item(\'c\', \'categories/categories_edit\');">
 						<div class="cms-btn-image">
 							<img src="' . $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/section_properties.png" width="15" height="16" alt=""/>
 						</div>
 						<div class="cms-btn-text">' . $this->Application->Phrase('la_btn_SectionProperties', false, true) . '</div>
 					</div>' . "\n";
 			} elseif (EDITING_MODE == EDITING_MODE_DESIGN) {
 				$url_params = Array(
 					'pass'			=>	'm,theme',
 					'm_opener'		=>	'd',
 					'theme_id'		=>	$this->Application->GetVar('m_theme'),
 					'theme_mode'	=>	't',
 					'theme_event'	=>	'OnEdit',
 					'theme-file_id' =>	$this->_getThemeFileId(),
 					'front'			=>	1,
 					'__URLENCODE__'	=>	1,
 					'__NO_REWRITE__'=>	1,
 					'escape'		=>	1,
 					'index_file' => 'index.php',
 				);
 
 				$edit_url = $this->Application->HREF('themes/file_edit', ADMIN_DIRECTORY, $url_params);
 
 				$edit_btn .= '
 					<div class="cms-layout-btn-container"' . ($display_mode === false ? ' style="margin: 0px;"' : '') . '>
 						<div class="cms-save-layout-btn" onclick="aTemplateManager.saveLayout(); return false;">
 							<div class="cms-btn-image">
 								<img src="' . $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/save_button.gif" width="16" height="16" alt=""/>
 							</div>
 							<div class="cms-btn-text">' . $this->Application->Phrase('la_btn_SaveChanges', false, true) . '</div>
 						</div>
 						<div class="cms-cancel-layout-btn" onclick="aTemplateManager.cancelLayout(); return false;">
 							<div class="cms-btn-image">
 								<img src="' . $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/cancel_button.gif" width="16" height="16" alt=""/>
 							</div>
 							<div class="cms-btn-text">' . $this->Application->Phrase('la_btn_Cancel', false, true) . '</div>
 						</div>
 					</div>
 
 					<div class="cms-section-properties-btn"' . ($display_mode === false ? ' style="margin: 0px;"' : '') . ' onmouseover="window.status=\''.$edit_url.'\'; return true" onclick="$form_name=\'kf_'.$page->GetID().'\'; std_edit_item(\'theme\', \'themes/file_edit\');">
 						<div class="cms-btn-image">
 							<img src="' . $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/section_properties.png" width="15" height="16" alt=""/>
 						</div>
 						<div class="cms-btn-text">' . $this->Application->Phrase('la_btn_SectionTemplate', false, true) . '</div>
 					</div>' . "\n";
 			}
 
 			if ($display_mode == 'start') {
 				// button with border around the page
 				$edit_code .= '<div class="cms-section-properties-btn-container">' . $edit_btn . '<div class="cms-btn-content">';
 
 			}
 			else {
 				// button without border around the page
 				$edit_code .= $edit_btn;
 			}
 		}
 
 		if ($display_mode == 'end') {
 			// draw border around the page
 			$edit_code .= '</div></div>';
 		}
 
 		if ($display_mode != 'end') {
 			$edit_code .= '<form method="POST" style="display: inline; margin: 0px" name="kf_'.$page->GetID().'" id="kf_'.$page->GetID().'" action="'.$edit_url.'"></form>';
 
 			// when "EditingScripts" tag is not used, make sure, that scripts are also included
 			$edit_code .= $this->EditingScripts($params);
 		}
 
 		return $edit_code;
 	}
 
 	function _getThemeFileId()
 	{
 		$template = $this->Application->GetVar('t');
 
 		if (!$this->Application->TemplatesCache->TemplateExists($template) && !$this->Application->isAdmin) {
 			$cms_handler =& $this->Application->recallObject($this->Prefix . '_EventHandler');
 			/* @var $cms_handler CategoriesEventHandler */
 
 			$template = ltrim($cms_handler->GetDesignTemplate(), '/');
 		}
 
 		$file_path = dirname($template) == '.' ? '' : '/' . dirname($template);
 		$file_name = basename($template);
 
 		$sql = 'SELECT FileId
 				FROM ' . TABLE_PREFIX . 'ThemeFiles
 				WHERE (ThemeId = ' . (int)$this->Application->GetVar('m_theme') . ') AND (FilePath = ' . $this->Conn->qstr($file_path) . ') AND (FileName = ' . $this->Conn->qstr($file_name . '.tpl') . ')';
 		return $this->Conn->GetOne($sql);
 	}
 
 	/**
 	 * Builds site menu
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function CachedMenu($params)
 	{
 		$menu_helper =& $this->Application->recallObject('MenuHelper');
 		/* @var $menu_helper MenuHelper */
 
 		return $menu_helper->menuTag($this->getPrefixSpecial(), $params);
 	}
 
 	/**
 	 * Trick to allow some kind of output formatting when using CachedMenu tag
 	 *
 	 * @param Array $params
 	 * @return bool
 	 */
 	function SplitColumn($params)
 	{
 		return $this->Application->GetVar($params['i']) > ceil($params['total'] / $params['columns']);
 	}
 
 	/**
 	 * Returns direct children count of given category
 	 *
 	 * @param Array $params
 	 * @return int
 	 */
 	function HasSubCats($params)
 	{
 		$sql = 'SELECT COUNT(*)
 				FROM ' . TABLE_PREFIX . 'Category
 				WHERE ParentId = ' . $params['cat_id'];
 
 		return $this->Conn->GetOne($sql);
 	}
 
 	/**
 	 * Prints sub-pages of given/current page.
 	 *
 	 * @param Array $params
 	 * @return string
 	 * @todo This could be reached by using "parent_cat_id" parameter. Only difference here is new block parameter "path". Need to rewrite.
 	 */
 	function PrintSubPages($params)
 	{
 		$list =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix.'_List', $params);
 		/* @var $list kDBList */
 
 		$category_id = array_key_exists('category_id', $params) ? $params['category_id'] : $this->Application->GetVar('m_cat_id');
 
 		$list->addFilter('current_pages', TABLE_PREFIX . 'CategoryItems.CategoryId = ' . $category_id);
 		$list->Query();
 		$list->GoFirst();
 
 		$o = '';
 		$block_params = $this->prepareTagParams($params);
 		$block_params['name'] = $params['render_as'];
 
 		while (!$list->EOL()) {
 			$block_params['path'] = $list->GetDBField('Path');
 			$o .= $this->Application->ParseBlock($block_params, 1);
 
 			$list->GoNext();
 		}
 
 		return $o;
 	}
 
 	/**
 	 * Builds link for browsing current page on Front-End
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function PageBrowseLink($params)
 	{
 		$object =& $this->getObject($params);
 
 		$themes_helper =& $this->Application->recallObject('ThemesHelper');
 		/* @var $themes_helper kThemesHelper */
 
 		$site_config_helper =& $this->Application->recallObject('SiteConfigHelper');
 		/* @var $site_config_helper SiteConfigHelper */
 
 		$settings = $site_config_helper->getSettings();
 
 		$url_params = Array (
 			'm_cat_id' => $object->GetID(),
 			'm_theme' => $themes_helper->getCurrentThemeId(),
 			'editing_mode' => $settings['default_editing_mode'],
 			'pass' => 'm',
 			'admin' => 1,
 			'index_file' => 'index.php'
 		);
 
 		if ($this->Application->ConfigValue('UseModRewrite')) {
 			$url_params['__MOD_REWRITE__'] = 1;
 		}
 
 		return $this->Application->HREF($object->GetDBField('NamedParentPath'), '_FRONT_END_', $url_params);
 	}
 
 	/**
 	 * Builds link to cms page (used?)
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function ContentPageLink($params)
 	{
 		$object =& $this->getObject($params);
 		$params['t'] = $object->GetDBField('NamedParentPath');
 		$params['m_cat_id'] = 0;
 
 		return $this->Application->ProcessParsedTag('m', 'Link', $params);
 	}
 
 	/**
 	 * Prepares cms page description for search result page
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function SearchDescription($params)
 	{
 		$object =& $this->getObject($params);
 		$desc =  $object->GetField('MetaDescription');
 		if (!$desc) {
 			$sql = 'SELECT *
 					FROM ' . TABLE_PREFIX . 'PageContent
 					WHERE PageId = ' . $object->GetID() . ' AND ContentNum = 1';
 			$content = $this->Conn->GetRow($sql);
 
 			if ($content['l'.$this->Application->GetVar('m_lang').'_Content']) {
 				$desc = $content['l'.$this->Application->GetVar('m_lang').'_Content'];
 			}
 			else {
 				$desc = $content['l'.$this->Application->GetDefaultLanguageId().'_Content'];
 			}
 		}
 
 		return mb_substr($desc, 0, 300).(mb_strlen($desc) > 300 ? '...' : '');
 	}
 
 	/**
 	 * Simplified version of "c:CategoryLink" for "c:PrintList"
 	 *
 	 * @param Array $params
 	 * @return string
 	 * @todo Used? Needs refactoring.
 	 */
 	function EnterCatLink($params)
 	{
 		$object =& $this->getObject($params);
 
 		$url_params = Array ('pass' => 'm', 'm_cat_id' => $object->GetID());
 		return $this->Application->HREF($params['template'], '', $url_params);
 	}
 
 	/**
 	 * Simplified version of "c:CategoryPath", that do not use blocks for rendering
 	 *
 	 * @param Array $params
 	 * @return string
 	 * @todo Used? Maybe needs to be removed.
 	 */
 	function PagePath($params)
 	{
 		$object =& $this->getObject($params);
 		$path = $object->GetField('CachedNavbar');
 		if ($path) {
 			$items = explode('&|&', $path);
 			array_shift($items);
 			return implode(' -&gt; ', $items);
 		}
 
 		return '';
 	}
 
 	/**
 	 * Returns configuration variable value
 	 *
 	 * @param Array $params
 	 * @return string
 	 * @todo Needs to be replaced with "m:GetConfig" tag; Not used now (were used on structure_edit.tpl).
 	 */
 	function AllowManualFilenames($params)
 	{
 		return $this->Application->ConfigValue('ProjCMSAllowManualFilenames');
 	}
 
 	/**
 	 * Draws path to current page (each page can be link to it)
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function CurrentPath($params)
 	{
 		$block_params = $this->prepareTagParams($params);
 		$block_params['name'] = $block_params['render_as'];
 
 		$object =& $this->Application->recallObject($this->Prefix);
 		/* @var $object kDBItem */
 
 		$category_ids = explode('|', substr($object->GetDBField('ParentPath'), 1, -1));
 
 		$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
 		$table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
 
 		$language = (int)$this->Application->GetVar('m_lang');
 
 		if (!$language) {
 			$language = 1;
 		}
 
 		$sql = 'SELECT l'.$language.'_Name AS Name, NamedParentPath
 				FROM '.$table_name.'
 				WHERE '.$id_field.' IN ('.implode(',', $category_ids).')';
 		$categories_data = $this->Conn->Query($sql);
 
 		$ret = '';
 		foreach ($categories_data as $index => $category_data) {
 			if ($category_data['Name'] == 'Content') {
 				continue;
 			}
 			$block_params['title'] = $category_data['Name'];
 			$block_params['template'] = preg_replace('/^Content\//i', '', $category_data['NamedParentPath']);
 			$block_params['is_first'] = $index == 1; // because Content is 1st element
 			$block_params['is_last'] = $index == count($categories_data) - 1;
 
 			$ret .= $this->Application->ParseBlock($block_params);
 		}
 
 		return $ret;
 	}
 
 	/**
 	 * Synonim to PrintList2 for "onlinestore" theme
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function ListPages($params)
 	{
 		return $this->PrintList2($params);
 	}
 
 	/**
 	 * Returns information about parser element locations in template
 	 *
 	 * @param Array $params
 	 * @return mixed
 	 */
 	function BlockInfo($params)
 	{
 		if (!EDITING_MODE) {
 			return '';
 		}
 
 		$template_helper =& $this->Application->recallObject('TemplateHelper');
 		/* @var $template_helper TemplateHelper */
 
 		return $template_helper->blockInfo( $params['name'] );
 	}
 
 	/**
 	 * Hide all editing tabs except permission tab, when editing "Home" (ID = 0) category
 	 *
 	 * @param Array $params
 	 */
 	function ModifyUnitConfig($params)
 	{
 		$root_category = $this->Application->RecallVar('IsRootCategory_' . $this->Application->GetVar('m_wid'));
 		if (!$root_category) {
 			return ;
 		}
 
 		$edit_tab_presets = $this->Application->getUnitOption($this->Prefix, 'EditTabPresets');
 		$edit_tab_presets['Default'] = Array (
 			'permissions' => $edit_tab_presets['Default']['permissions'],
 		);
 		$this->Application->setUnitOption($this->Prefix, 'EditTabPresets', $edit_tab_presets);
 	}
 
 	/**
 	 * Prints catalog export templates
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function PrintCatalogExportTemplates($params)
 	{
 		$prefixes = explode(',', $params['prefixes']);
 
 		$ret = Array ();
 		foreach ($prefixes as $prefix) {
 			if ($this->Application->prefixRegistred($prefix)) {
-				$ret[$prefix] = $this->Application->getUnitOption($prefix, 'ModuleFolder') . '/export';
+				$module_path = $this->Application->getUnitOption($prefix, 'ModuleFolder') . '/';
+				$module_name = $this->Application->findModule('Path', $module_path, 'Name');
+
+				$ret[$prefix] = mb_strtolower($module_name) . '/export';
 			}
 		}
 
 		$json_helper =& $this->Application->recallObject('JSONHelper');
 		/* @var $json_helper JSONHelper */
 
 		return $json_helper->encode($ret);
 	}
 
 	/**
 	 * Checks, that "view in browse mode" functionality available
 	 *
 	 * @param Array $params
 	 * @return bool
 	 */
 	function BrowseModeAvailable($params)
 	{
 		$valid_special = $params['Special'] != 'user';
 		$not_selector = $this->Application->GetVar('type') != 'item_selector';
 
 		return $valid_special && $not_selector;
 	}
 
 	/**
 	 * Returns a link for editing product
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function ItemEditLink($params)
 	{
 		$object =& $this->getObject();
 		/* @var $object kDBList */
 
 		$edit_template = $this->Application->getUnitOption($this->Prefix, 'AdminTemplatePath') . '/' . $this->Application->getUnitOption($this->Prefix, 'AdminTemplatePrefix') . 'edit';
 
 		$url_params = Array (
 			'm_opener'				=>	'd',
 			$this->Prefix.'_mode'	=>	't',
 			$this->Prefix.'_event'	=>	'OnEdit',
 			$this->Prefix.'_id'		=>	$object->GetID(),
 			'm_cat_id'				=>	$object->GetDBField('ParentId'),
 			'pass'					=>	'all,'.$this->Prefix,
 			'no_pass_through'		=>	1,
 		);
 
 		return $this->Application->HREF($edit_template,'', $url_params);
 	}
 
 	function RelevanceIndicator($params)
 	{
 		$object =& $this->getObject($params);
 
 		$search_results_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
 		$sql = 'SELECT Relevance
 				FROM '.$search_results_table.'
 				WHERE ResourceId = '.$object->GetDBField('ResourceId');
 
     	$percents_off = (int)(100 - (100 * $this->Conn->GetOne($sql)));
     	$percents_off = ($percents_off < 0) ? 0 : $percents_off;
     	if ($percents_off) {
         	$params['percent_off'] = $percents_off;
     		$params['percent_on'] = 100 - $percents_off;
         	$params['name'] = $this->SelectParam($params, 'relevance_normal_render_as,block_relevance_normal');
     	}
     	else {
     		$params['name'] = $this->SelectParam($params, 'relevance_full_render_as,block_relevance_full');
     	}
     	return $this->Application->ParseBlock($params);
 	}
 }
\ No newline at end of file
Index: branches/5.1.x/core/units/admin/admin_tag_processor.php
===================================================================
--- branches/5.1.x/core/units/admin/admin_tag_processor.php	(revision 13203)
+++ branches/5.1.x/core/units/admin/admin_tag_processor.php	(revision 13204)
@@ -1,1149 +1,1149 @@
 <?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 AdminTagProcessor extends kDBTagProcessor {
 
 		function SetConst($params)
 		{
 			$name = $this->SelectParam($params, 'name,const');
 			safeDefine($name, $params['value']);
 		}
 
 		/**
 		 * 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( replaceModuleSection($params['phrase']) );
 		}
 
 		/**
 		 * Returns section icon with #section# keyword replaced with current section
 		 *
 		 * @param Array $params
 		 * @return string
 		 */
 		function GetSectionIcon($params)
 		{
 			return 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');
 			$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_recursive2($params, $section_data) );
 			if (!isset($section_data['children'])) {
 				return $ret;
 			}
 
 			$debug_mode = $this->Application->isDebugMode();
 			$super_admin_mode = $this->Application->RecallVar('super_admin');
 
 			ksort($section_data['children'], SORT_NUMERIC);
 			foreach ($section_data['children'] as $section_name) {
 				$section_data =& $sections_helper->getSectionData($section_name);
 
 				if (isset($section_data['show_mode']) && is_numeric($section_data['show_mode'])) {
 					$show_mode = $section_data['show_mode'];
 					// if super admin section -> show in super admin mode & debug mode
 					$show_section = $show_mode == smNORMAL || ((($show_mode & smSUPER_ADMIN) == smSUPER_ADMIN) && ($super_admin_mode || $debug_mode));
 					if (!$show_section) {
 						// if section is in debug mode only && debug mode -> show
 						$show_section = (($show_mode & smDEBUG) == smDEBUG) && $debug_mode;
 					}
 					if (!$show_section) {
 						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) {
 				trigger_error('Use of undefined section "<strong>' . $section . '</strong>" in "<strong>' . __METHOD__ . '</strong>"', E_USER_ERROR);
 				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 = $section_data['label'];
 					if ($section != 'in-portal:root') {
 						// don't translate label for top section, because it's already translated
 						$no_editing = array_key_exists('no_editing', $params) ? $params['no_editing'] : false;
 
 						$res = $this->Application->Phrase($res, !$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;
 
 			$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_recursive2($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 '';
 			}
 
 			$debug_mode = $this->Application->isDebugMode();
 			$super_admin_mode = $this->Application->RecallVar('super_admin');
 
 			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 (isset($section_data['show_mode']) && is_numeric($section_data['show_mode'])) {
 					$show_mode = $section_data['show_mode'];
 					// if super admin section -> show in super admin mode & debug mode
 					$show_section = $show_mode == smNORMAL || ((($show_mode & smSUPER_ADMIN) == smSUPER_ADMIN) && ($super_admin_mode || $debug_mode));
 					if (!$show_section) {
 						// if section is in debug mode only && debug mode -> show
 						$show_section = (($show_mode & smDEBUG) == smDEBUG) && $debug_mode;
 					}
 					if (!$show_section) {
 						continue;
 					}
 				}
 
 				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_recursive2($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');
 			$section_data =& $sections_helper->getSectionData($section_name);
 
 			$block_params = array_merge_recursive2($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] = replaceModuleSection($param_value);
 			}
 
 			$m =& $this->Application->recallObject('m_TagProcessor');
 			return $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');
 			$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) {
 				if (!$this->Application->CheckPermission($section_name.'.view', 1)) continue;
 
 				$tab_data =& $sections_helper->getSectionData($section_name);
 				$block_params['t'] = $tab_data['url']['t'];
 				$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->findModule('Name', 'Core', 'RootCat');
 
 			$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_recursive2($params, $pass_through);
 			}
 
 			// user can override default parameters (except pass_through of course)
 			$params = array_merge_recursive2($default_params, $params);
 
 			$main_processor =& $this->Application->recallObject('m_TagProcessor');
 	    	return $main_processor->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;
 			}
 
 
 			if (isset($params['format'])) {
 				$format = $params['format'];
 				if(preg_match("/_regional_(.*)/", $format, $regs))
 				{
 					$lang =& $this->Application->recallObject('lang.current');
 					$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');
 
 				if ($this->Application->ConfigValue('QuickCategoryPermissionRebuild')) {
 					$updater =& $this->Application->recallObject('kPermCacheUpdater');
 					/* @var $updater kPermCacheUpdater */
 
 					$updater->OneStepRun();
 				}
 				else {
 					// 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
 		 */
 		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']);
 			}
 		}
 
 		/**
 		 * Returns popup size (by template), if not cached, then parse template to get value
 		 *
 		 * @param Array $params
 		 * @return string
 		 */
 		function GetPopupSize($params)
 		{
 			$t = $this->Application->GetVar('template_name');
 			$sql = 'SELECT *
 					FROM '.TABLE_PREFIX.'PopupSizes
 					WHERE TemplateName = '.$this->Conn->qstr($t);
 			$popup_info = $this->Conn->GetRow($sql);
 			if (!$popup_info) {
 				$this->Application->InitParser();
 				$this->Application->ParseBlock(array('name' => $t)); // dies when SetPopupSize tag found & in ajax requrest
 				return '750x400'; // tag SetPopupSize not found in template -> use default size
 			}
 			return $popup_info['PopupWidth'].'x'.$popup_info['PopupHeight'];
 		}
 
 		/**
 		 * 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
 		 */
 		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 && 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->HttpQuery->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->findModule('Name', 'Core', 'RootCat');
 				}
 
 				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_recursive2($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);
 		}
 
 		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);
 
 			foreach ($errors as $an_error) {
 				$block_params['file'] = str_replace(FULL_PATH, '', $an_error['file']);
 				$block_params['line'] = $an_error['line'];
 				$block_params['message'] = $an_error['msg'];
 
 				$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) );
 		}
 
 		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)
 		{
 	 		$datearray = $this->getDirList($this->Application->ConfigValue('Backup_Path'));
 	 		$ret = '';
 	        foreach($datearray as $key => $value)
 	        {
 	        	$params['backuptimestamp'] = $value['filedate'];
 	        	$params['backuptime'] = date('F j, Y, g:i a', $value['filedate']);
 	        	$params['backupsize'] = round($value['filesize']/1024/1024, 2); // MBytes
 	        	$ret .= $this->Application->ParseBlock($params);
 	        }
 	        return $ret;
 		}
 
 		function getDirList ($dirName)
 		{
 		    $fileinfo = array();
 		    $d = dir($dirName);
 
 		    while($entry = $d->read())
 		    {
 		        if ($entry != "." && $entry != "..")
 		        {
 		            if (!is_dir($dirName."/".$entry) && strpos($entry, 'dump') !== false)
 		            {
 		                $fileinfo[]= Array('filedate' => $this->chopchop($entry),
 		                					'filesize' => filesize($dirName. '/'. $entry)
 		                					);
 		            }
 		        }
 		    }
 		    $d->close();
 		    rsort($fileinfo);
 
 		    return $fileinfo;
 
 		}
 
 		function chopchop ($filename)
 		{
 			 $p = pathinfo($filename);
 			 $ext = '.'.$p['extension'];
 		     $filename;
 		     $filename = str_replace('dump', '',$filename);
 		     $filename = str_replace($ext, '', $filename);
 
 		     return $filename;
 		}
 
 		/**
 		 * Returns phpinfo() output
 		 *
 		 * @param Array $params
 		 * @return string
 		 */
 		function PrintPHPinfo($params)
 		{
 			ob_start();
 			phpinfo();
 
 			return ob_get_clean();
 		}
 
 		function PrintSqlCols($params)
 		{
 			$a_data = unserialize($this->Application->GetVar('sql_rows'));
 			$ret = '';
 			$block = $params['render_as'];
 			foreach ($a_data AS $a_row)
 			{
 				foreach ($a_row AS $col => $value)
 				{
 					$ret .= $this->Application->ParseBlock(Array('name'=>$block, 'value'=>$col));
 				}
 				break;
 			}
 			return $ret;
 		}
 
 		function PrintSqlRows($params)
 		{
 			$a_data = unserialize($this->Application->GetVar('sql_rows'));
 			$ret = '';
 			$block = $params['render_as'];
 			foreach ($a_data AS $a_row)
 			{
 				$cells = '';
 				foreach ($a_row AS $col => $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'] = $import_source['Module'];
+ 				$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('');
 
 			$this->Application->Phrases->LanguageId = $params['language_id'];
 			$this->Application->Phrases->LoadPhrases( $this->Application->Caches['PhraseList'] );
 		}
 
 		/**
 		 * Performs HTTP Authentification for administrative console
 		 *
 		 * @param Array $params
 		 */
 		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 && ipMatch($auth_bypass_ips)) || ($super_admin_ips && 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 */
 
 				$password = $password_formatter->EncryptPassword($_SERVER['PHP_AUTH_PW'], 'b38');
 
 				if ($this->Application->ConfigValue('HTTPAuthPassword') != $password) {
 					// incorrect password
 					return $this->_httpAuthentificate();
 				}
 			}
 
 			return true;
 		}
 
 		/**
 		 * Ask user to authentificate
 		 *
 		 * @return false
 		 */
 		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);
 		}
 	}
\ No newline at end of file
Index: branches/5.1.x/core/admin_templates/tools/import2.tpl
===================================================================
--- branches/5.1.x/core/admin_templates/tools/import2.tpl	(revision 13203)
+++ branches/5.1.x/core/admin_templates/tools/import2.tpl	(revision 13204)
@@ -1,94 +1,94 @@
 <inp2:adm_SetPopupSize width="780" height="670"/>
 
 <inp2:m_include t="incs/header"/>
 <inp2:m_RenderElement name="combined_header" prefix="adm" section="in-portal:main_import" title_preset="import"/>
 
 <!-- ToolBar -->
 <table class="toolbar" height="30" cellspacing="0" cellpadding="0" width="100%" border="0">
 <tbody>
 	<tr>
   	<td>
   		<script type="text/javascript">
 				a_toolbar = new ToolBar();
 				a_toolbar.AddButton( new ToolBarButton('prev', '<inp2:m_phrase label="la_ToolTip_Prev" escape="1"/>', function() {
 							location.href = '<inp2:m_Link t="tools/import1"/>';
 						}
 					) );
 				a_toolbar.AddButton( new ToolBarButton('next', '<inp2:m_phrase label="la_ToolTip_Next" escape="1"/>', function() {
 							ImportRedirect(ChoiseMade('kernel_form','choose'));
 						}
 				 ) );
 
 				<inp2:m_if check="m_Get" name="m_wid">
 					a_toolbar.AddButton( new ToolBarSeparator('sep1') );
 					a_toolbar.AddButton( new ToolBarButton('cancel', '<inp2:m_phrase label="la_ToolTip_Cancel" escape="1"/>', function() {
 							window_close();
 							}
 					 ) );
 				</inp2:m_if>
 
 				a_toolbar.Render();
 				a_toolbar.DisableButton('next');
 
 
 				function ImportRedirect(import_id)
 				{
 					<inp2:m_DefineElement name="import_js_script">
 						if (import_id == <inp2:m_Param name="script_id"/>) {
-							redirect('<inp2:m_Link template="{$module_path}import" pass="{$script_prefix}.import" {$script_prefix}.import_event="OnResetSettings"/>');
+							redirect('<inp2:m_Link template="{$script_module}/import" pass="{$script_prefix}.import" {$script_prefix}.import_event="OnResetSettings"/>');
 							return ;
 						}
 					</inp2:m_DefineElement>
 
 					<inp2:adm_PrintImportSources render_as="import_js_script"/>
 				}
 
 				function ChoiseMade(form, radio_name)
 				{
 					// checks if user has selected enabled radio button
 					var frm = document.getElementById(form);
 					if(frm)
 					{
 						var i = 0;
 						var element_count = frm.elements.length;
 						for(i = 0; i < element_count; i++)
 							if(frm[i].type == 'radio' && frm[i].name == radio_name)
 								if(frm[i].checked == true)
 									return frm[i].value;
 
 						return false;
 					}
 				}
 
 				$(document).ready(
 					function() {
 						$('#step_number').text(2);
 					}
 				);
 			</script>
 		</td>
 	</tr>
 </tbody>
 </table>
 	<input type="hidden" name="import_id" id="import_id" value="">
 <table width="100%" border="0" cellspacing="0" cellpadding="4" class="bordered" id="config_table">
 	<inp2:m_RenderElement name="subsection" title="la_prompt_Import_Source"/>
 		<tr class="<inp2:m_odd_even odd="table-color1" even="table-color2"/>">
 			<inp2:m_inc param="tab_index" by="1"/>
 			<td>
 				<span class="text">Select the format you are importing the data from:</span>
 			</td>
 		</tr>
 		<tr class="<inp2:m_odd_even odd="table-color1" even="table-color2"/>">
 			<inp2:m_inc param="tab_index" by="1"/>
 			<td>
 			<inp2:m_DefineElement name="import_script">
 				<input name="choose" id="ch<inp2:m_param name="script_id"/>" value="<inp2:m_param name="script_id"/>" onclick="a_toolbar.EnableButton('next')" type="radio"><span class="text"><label for="ch<inp2:m_param name="script_id"/>"><inp2:m_param name="script_name"/></label></span><br>
 			</inp2:m_DefineElement>
 
 			<inp2:adm_PrintImportSources render_as="import_script"/>
 			</td>
 		</tr>
 </table>
 
 <inp2:m_include t="incs/footer"/>
\ No newline at end of file