Index: branches/5.3.x/units/links/link_tag_processor.php
===================================================================
--- branches/5.3.x/units/links/link_tag_processor.php	(revision 16106)
+++ branches/5.3.x/units/links/link_tag_processor.php	(revision 16107)
@@ -1,464 +1,464 @@
 <?php
 /**
 * @version	$Id$
 * @package	In-Link
 * @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 LinkTagProcessor extends kCatDBTagProcessor {
 
 
 	/**
 	 * Returns object used in tag processor
 	 *
 	 * @access public
 	 * @return kDBBase
 	 */
 	/*function &getObject($params = Array())
 	{
 		$object =& parent::getObject($params);
 
 		// Forces item loading (compatibility with old theme)
 		if (is_subclass_of($object, 'kDBItem')) {
 			// force reload when using from old code
 			$id = $this->Application->GetVar($this->Prefix.'_id');
 			if ($object->isLoaded() && $id && ($object->GetID() != $id)) {
 				$object->Load($id);
 			}
 		}
 
 		return $object;
 	}*/
 
 	function getListingInfo($resource_id, $field = null)
 	{
 		$sql = 'SELECT *
 				FROM ' . $this->Application->getUnitConfig('ls')->getTableName() . '
 				WHERE ItemResourceId = ' . $resource_id;
 		$listing_info = $this->Conn->GetRow($sql);
 
 		return isset($field) ? $listing_info[$field] : $listing_info;
 	}
 
 	/**
 	 * Detects listing enhancement status (enhanced or not)
 	 *
 	 * @param Array $params
 	 * @return int
 	 */
 	function LinkIsEnhanced($params)
 	{
 		$object = $this->getObject($params);
 		/* @var $object kDBItem */
 
 		if ($object->GetDBField('Status') == STATUS_PENDING || $object->GetDBField('Status') == STATUS_PENDING_EDITING) {
 			return false;
 		}
 
 		$listing_type_id = $this->getListingInfo($object->GetDBField('ResourceId'), 'ListingTypeId');
 
 		$this->Application->SetVar('lst_id', $listing_type_id); // compatibility with old-theme
 		return $listing_type_id ? 1 : 0;
 	}
 
 	/**
 	 * Detects if enhancement is pending approval
 	 *
 	 * @param Array $params
 	 * @return int
 	 */
 	function EnhancementIsPending($params)
 	{
 		$object = $this->getObject($params);
 		/* @var $object kDBItem */
 
 		$status = $this->getListingInfo($object->GetDBField('ResourceId'), 'Status');
 
 		return $status == STATUS_PENDING ? 1 : 0;
 	}
 
 	function ListingTypeField($params)
 	{
 		$object = $this->getObject($params);
 		/* @var $object kDBItem */
 
 		$lst_id = $this->getListingInfo($object->GetDBField('ResourceId'), 'ListingTypeId');
 
 		$lst_object = $this->Application->recallObject('lst', null, Array('skip_autoload' => true));
 		$lst_object->Load($lst_id);
 
 		return $lst_object->GetField( $this->SelectParam($params, 'name,field') );
 	}
 
 	function EnhancementField($params)
 	{
 		$object = $this->getObject($params);
 		/* @var $object kDBItem */
 
 		$listing_id = $this->getListingInfo($object->GetDBField('ResourceId'), 'ListingId');
 
 		$listing_object = $this->Application->recallObject('ls', null, Array('skip_autoload' => true));
 		$listing_object->Load($listing_id);
 
 		return $listing_object->GetField( $this->SelectParam($params, 'name,field') );
 	}
 
 	function IsRenewalPeriod($params)
 	{
 		$object = $this->getObject($params);
 		/* @var $object kDBItem */
 
 		$listing_info = $this->getListingInfo($object->GetDBField('ResourceId'));
 
 		$sql = 'SELECT RenewalReminder
 				FROM ' . $this->Application->getUnitConfig('lst')->getTableName() . '
 				WHERE ListingTypeId = ' . $listing_info['ListingTypeId'];
 		$renewal_interval = $this->Conn->GetOne($sql) * 3600 * 24;
 
 		return ($listing_info['ExpiresOn'] - time() < $renewal_interval) ? 1 : 0;
 	}
 
 	function FirstListingType($params)
 	{
 		static $first = true;
 		if ($first) {
 			$first = false;
 			return true;
 		}
 		else {
 			return false;
 		}
 	}
 
 	function IsReocurringEnhancement($params)
 	{
 		$params['name'] = 'Recurring';
 		return $this->ListingTypeField($params);
 	}
 
 	function EnhanceUsingInCommerce($params)
 	{
 		if ( !$this->Application->prefixRegistred('ord') ) {
 			return 0;
 		}
 
 		$object = $this->getObject($params);
 		/* @var $object kDBItem */
 
 		$listtype_id = $this->getListingInfo($object->GetDBField('ResourceId'), 'ListingTypeId');
 
 		$lst_object = $this->Application->recallObject('lst', null, Array('skip_autoload' => true));
 		$lst_object->Load($listtype_id);
 
 		return $lst_object->GetDBField('EnableBuying');
 	}
 
 	function ClickLink($params)
 	{
 		$object = $this->getObject($params);
 
 		return $this->Application->HREF($params['t'], '', Array('l_id' => $object->GetID(), 'pass'=>'all,l' ));
 	}
 
 	function ListRelatedLinks($params)
 	{
 		return $this->PrintList2($params);
 	}
 
 	function LinkLink($params)
 	{
 		return $this->ItemLink($params, 'link');
 	}
 
 	function ListingDescription($params)
 	{
 		$listing_type = $this->Application->recallObject('lst');
 		/* @var $listing_type kDBItem */
 
 		return $listing_type->GetDBField('Description');
 	}
 
 	function ListingTypeDetailsLink($params)
 	{
 		$listing_type = $this->Application->recallObject('lst', null, Array ('raise_warnings' => 0));
 		/* @var $listing_type kDBList */
 
 		$params['lst_id'] = $listing_type->isLoaded() ? $listing_type->GetID() : $this->Application->Parser->GetParam('key');
 
 		return $this->Application->ProcessParsedTag('m', 'Link', $params);
 	}
 
 	/**
 	 * Register hit & go to link url
 	 *
 	 * @param Array $params
 	 */
 	function FollowLocation($params)
 	{
 		$object = $this->getObject($params);
 		/* @var $object kCatDBItem */
 
 		if (!$object->isLoaded()) {
 			throw new Exception('No Link ID for redirect');
 		}
 
 		$object->RegisterHit();
 
 		// save user and time
 		if (!$this->Application->isAdmin && $this->Application->LoggedIn()) {
 			$resource_id = $object->GetDBField('ResourceId');
 			$user_id = $this->Application->RecallVar('user_id');
 
 			$link_visit = $this->Application->recallObject('l-visit', null, Array ('skip_autoload' => true));
 			/* @var $link_visit kDBItem */
 
 			$link_visit->Load( Array ('ResourceId' => $resource_id, 'PortalUserId' => $user_id) );
 			if ($link_visit->isLoaded()) {
 				// for existing visits update date
 				$link_visit->SetDBField('VisitTimestamp_date', time());
 				$link_visit->SetDBField('VisitTimestamp_time', time());
 			}
 			else {
 				// for new visits set user & link, visit will be set as default value
 				$link_visit->SetDBField('ResourceId', $resource_id);
 				$link_visit->SetDBField('PortalUserId', $user_id);
 			}
 
 			$status = $link_visit->isLoaded() ? $link_visit->Update() : $link_visit->Create();
 		}
 
 		$url_field = $this->Application->GetVar('url_field');
 		$url = $object->GetDBField($url_field);
 		if (!preg_match('/^(http|ftp|mailto:)(.*)/U', $url)) {
 			$url = 'http://'.$url;
 		}
 
 		$this->Application->Redirect('external:'.$url);
 	}
 
 	/**
 	 * Returns formatted address (from custom fields) for using with google
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function GetGoogleAddress($params)
 	{
 		$object = $this->getObject($params);
 
 		if (isset($params['display_info']) && $params['display_info']) {
 			$ret = $object->GetField('cust_LinkAddress') ? $object->GetField('cust_LinkAddress').'<BR/>' : '';
 			$ret .= $object->GetField('cust_LinkCity') ? $object->GetField('cust_LinkCity').',' : '';
 			$ret .= $object->GetField('cust_LinkState') ? $object->GetField('cust_LinkState') : '';
 			$ret .= $object->GetField('cust_LinkZipCode') ? $object->GetField('cust_LinkZipCode').'<BR/>' : '';
 			$ret .= $object->GetField('cust_LinkCountry') ? $object->GetField('cust_LinkCountry').'<BR/>' : '';
 			$ret .= $object->GetField('cust_LinkPhone') ? '<b>'.$this->Application->Phrase('lu_fld_LinkPhone').':</b> '.$object->GetField('cust_LinkPhone') : '';
 
 			return $ret;
 		}
 
 		$ret = $object->GetField('cust_LinkAddress') ? $object->GetField('cust_LinkAddress').',' : '';
 		$ret .= $object->GetField('cust_LinkCity') ? $object->GetField('cust_LinkCity').',' : '';
 		$ret .= $object->GetField('cust_LinkState') ? $object->GetField('cust_LinkState').',' : '';
 		$ret .= $object->GetField('cust_LinkZipCode') ? $object->GetField('cust_LinkZipCode').',' : '';
 		$ret .= $object->GetField('cust_LinkCountry') ? $object->GetField('cust_LinkCountry') : '';
 
 		return $ret;
 	}
 
 	/**
 	 * Returns timestamp of last link visit for logged in users only.
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function LastVisited($params)
 	{
 		if ( !$this->Application->LoggedIn() ) {
 			// we don't gather link visit statistics for Guests
 			return '';
 		}
 
 		static $link_visited = Array ();
 
 		$object = $this->getObject($params);
 		/* @var $object kDBList */
 
 		if ( !isset($link_visited[$this->Special]) ) {
 			$resource_ids = $object->GetCol('ResourceId');
 			$user_id = $this->Application->RecallVar('user_id');
 
 			$table_name = $this->Application->getUnitConfig('l-visit')->getTableName();
 			$sql = 'SELECT VisitTimestamp, ResourceId
 					FROM ' . $table_name . '
 					WHERE (PortalUserId = ' . $user_id . ') AND (ResourceId IN (' . implode(',', $resource_ids) . '))';
 			$link_visited[$this->Special] = $this->Conn->GetCol($sql, 'ResourceId');
 		}
 
 		if ( !isset($link_visited[$this->Special][$object->GetDBField('ResourceId')]) ) {
 			// link has no visit information for current user
 			return '';
 		}
 
 		$link_visit = $link_visited[$this->Special][$object->GetDBField('ResourceId')];
 
 		if ( isset($params['formatted']) && $params['formatted'] ) {
 			// format the date
 			$lang = $this->Application->recallObject('lang.current');
 			/* @var $lang LanguagesItem */
 
 			if ( isset($params['display_time']) && $params['display_time'] ) {
 				$display_format = $lang->GetDBField('DateFormat') . ' @ ' . $lang->GetDBField('TimeFormat');
 			}
 			else {
 				$display_format = $lang->GetDBField('DateFormat');
 			}
 
 			return date($display_format, $link_visit);
 		}
 
 		return $link_visit;
 	}
 
 	/**
 	 * Checks if specified Custom Fields and condition are true
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function HasValue($params)
 	{
 		$condition = isset($params['condition']) ? strtolower($params['condition']) : false;
 		$fields = isset($params['fields']) ? $params['fields'] : false;
 		if (!$fields || !in_array($condition, Array('or', 'and'))) {
 			// required parameters not passed
 			return false;
 		}
 
 		$fields = explode(',', $fields);
 
 		$object = $this->getObject($params);
 		/* @var $object kDBList */
 
 		switch ($condition) {
 			case 'or':
 				foreach ($fields as $field) {
 					if (strlen($object->GetDBField($field))) {
 						return true;
 					}
 				}
 				break;
 
 			case 'and':
 				foreach ($fields as $field) {
 					if (!strlen($object->GetDBField($field))) {
 						return false;
 					}
 				}
 				break;
 		}
 
 		return $condition == 'and' ? true : false;
 	}
 
 	/**
 	 * Gets and parses custom details template or default one
 	 *
 	 * @param Array $params
 	 * @return string
 	 */
 	function DisplayDetailTemplate($params)
 	{
 		$object = $this->getObject($params);
 		/* @var $object kDBItem */
 
 		$template_name = $object->GetDBField('CustomTemplate');
 		if (!$template_name || !$this->Application->TemplatesCache->TemplateExists($template_name)) {
 			$template_name = $params['default_template'];
 		}
 
 		$block_params['name'] = $template_name;
 
 		// parse template
-		return $this->Application->ParseBlock($block_params);
+		return $this->Application->IncludeTemplate($block_params);
 	}
 
 	/**
 	 * Changes title preset of "Duplicate checker" section to show current grouping
 	 *
 	 * @param Array $params
 	 */
 	function ModifyUnitConfig($params)
 	{
 		$grid = array_key_exists('grid', $params) ? $params['grid'] : false;
 		if ($grid != 'Duplicates') {
 			// only for "Duplicate Checker" section
 			return ;
 		}
 
 		$link_helper = $this->Application->recallObject('LinkHelper');
 		/* @var $link_helper LinkHelper */
 
 		// 1. get current grouping
 		$grouping = $link_helper->getGrouping( $this->getPrefixSpecial() );
 
 		$config = $this->getUnitConfig();
 
 		// 2. replace field names in grouping with their corresponding column titles
 		$grids = $config->getGrids();
 
 		foreach ($grouping as $index => $group_field) {
 			$group_field = preg_replace('/^l[\d]+_/', '', $group_field); // remove ml prefix
 			$grouping[$index] = $this->Application->Phrase($grids[$grid]['Fields'][$group_field]['title']);
 		}
 
 		// 3. patch resulting title preset
 		$concat_with = "' " . $this->Application->Phrase('la_and') . " '";
 		$title_preset = $config->getTitlePresetByName('duplicate_links');
 		$title_preset = str_replace('%s', "'" . implode($concat_with, $grouping) . "'", $title_preset);
 		$config->addTitlePresets($title_preset, 'duplicate_links');
 	}
 
 	/**
 	 * Allows to modify block params & current list record before PrintList parses record
 	 *
 	 * @param kDBList $object
 	 * @param Array $block_params
 	 */
 	function PrepareListElementParams(&$object, &$block_params)
 	{
 		$grid = array_key_exists('grid', $block_params) ? $block_params['grid'] : false;
 		if ($grid != 'Duplicates') {
 			// only for "Duplicate Checker" section
 			return ;
 		}
 
 		static $grouping = null;
 
 		if (!isset($grouping)) {
 			$link_helper = $this->Application->recallObject('LinkHelper');
 			/* @var $link_helper LinkHelper */
 
 			// 1. get current grouping
 			$grouping = $link_helper->getGrouping( $this->getPrefixSpecial() );
 		}
 
 		$fields_hash =& $object->getCurrentRecord();
 
 		$key_fields = Array ();
 		foreach ($grouping as $group_field) {
 			$key_fields[$group_field] = $fields_hash[$group_field];
 		}
 
 		$fields_hash['LinkId'] = base64_encode( serialize($key_fields) );
 	}
-}
\ No newline at end of file
+}
Index: branches/5.3.x/units/link_validation/link_validation_eh.php
===================================================================
--- branches/5.3.x/units/link_validation/link_validation_eh.php	(revision 16106)
+++ branches/5.3.x/units/link_validation/link_validation_eh.php	(revision 16107)
@@ -1,585 +1,585 @@
 <?php
 /**
 * @version	$Id$
 * @package	In-Link
 * @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 LinkValidationEventHandler extends kDBEventHandler {
 
 		/**
 		 * Allows to override standard permission mapping
 		 *
 		 * @return void
 		 * @access protected
 		 * @see kEventHandler::$permMapping
 		 */
 		protected function mapPermissions()
 		{
 			parent::mapPermissions();
 
 			$permissions = Array (
 				'OnResetValidationStatus' => Array ('self' => 'advanced:reset',),
 				'OnRestartValidation' => Array ('self' => 'advanced:restart',),
 				'OnContinueValidation' => Array ('self' => 'advanced:continue',),
 				'OnValidateSelected' => Array ('self' => 'advanced:validate',),
 				'OnValidateProgress' => Array ('self' => 'advanced:validate|advanced:continue|advanced:restart|advanced:reset',),
 				'OnCancelValidation' => Array ('self' => 'advanced:validate|advanced:continue|advanced:restart|advanced:reset',),
 				'OnCronValidation' => Array ('self' => 'advanced:validate|advanced:continue|advanced:restart|advanced:reset',),
 			);
 
 			$this->permMapping = array_merge($this->permMapping, $permissions);
 		}
 
 		/**
 		 * Define alternative event processing method names
 		 *
 		 * @return void
 		 * @see kEventHandler::$eventMethods
 		 * @access protected
 		 */
 		protected function mapEvents()
 		{
 			parent::mapEvents();
 
 			$events_map = Array (
 				'OnApproveLinks' => 'iterateItems',
 				'OnDeclineLinks' => 'iterateItems',
 			);
 
 			$this->eventMethods = array_merge($this->eventMethods, $events_map);
 		}
 
 		/**
 		 * Checks user permission to execute given $event
 		 *
 		 * @param kEvent $event
 		 * @return bool
 		 * @access public
 		 */
 		public function CheckPermission(kEvent $event)
 		{
 			$check_events = Array ('OnApproveLinks', 'OnDeclineLinks', 'OnDeleteLinks');
 
 			if ( in_array($event->Name, $check_events) ) {
 				$ids = $this->_getSelectedIds($event);
 
 				$perm_value = true;
 				if ( $ids ) {
 					$perm_helper = $this->Application->recallObject('PermissionsHelper');
 					/* @var $perm_helper kPermissionsHelper */
 
 					$items = $perm_helper->GetCategoryItemData('l', $ids);
 					$check_method = $event->Name == 'OnDeleteLinks' ? 'DeleteCheckPermission' : 'ModifyCheckPermission';
 					foreach ($items as $item_id => $item_data) {
 						if ( $perm_helper->$check_method($item_data['CreatedById'], $item_data['CategoryId'], 'l') == 0 ) {
 							// one of items selected has no permission
 							$perm_value = false;
 							break;
 						}
 					}
 
 					if ( !$perm_value ) {
 						$event->status = kEvent::erPERM_FAIL;
 					}
 				}
 
 				return $perm_value;
 			}
 
 			return parent::CheckPermission($event);
 		}
 
 		/**
 		 * Adds calculates fields for category name
 		 *
 		 * @param kDBItem|kDBList $object
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function prepareObject(&$object, kEvent $event)
 		{
 			parent::prepareObject($object, $event);
 
 			$object->addCalculatedField('CachedNavbar', 'c.l' . $this->Application->GetVar('m_lang') . '_CachedNavbar');
 		}
 
 		/**
 		 * Allows to show only invalid links
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 * @see kDBEventHandler::OnListBuild()
 		 */
 		protected function SetCustomQuery(kEvent $event)
 		{
 			parent::SetCustomQuery($event);
 
 			$object = $event->getObject();
 			/* @var $object kDBList */
 
 			$object->addFilter('primary_category_filter', 'ci.PrimaryCat = 1');
 
 			if ( $event->Special == 'invalid' ) {
 				$object->addFilter('status_filter', '%1$s.ValidationStatus = ' . LINK_VALIDATION_INVALID);
 			}
 		}
 
 		/**
 		 * Restarts link validation process
 		 *
 		 * @param kEvent $event
 		 */
 		function OnRestartValidation($event)
 		{
 			$this->_resetValidation($event);
 
 			$this->OnContinueValidation($event);
 		}
 
 		/**
 		 * Restarts link validation process
 		 *
 		 * @param kEvent $event
 		 */
 		function _resetValidation($event)
 		{
 			$config = $event->getUnitConfig();
 
 			// 1. delete previous validation results
 			$sql = 'SELECT ' . $config->getIDField() . '
 					FROM ' . $config->getTableName();
 			$ids = $this->Conn->GetCol($sql);
 
 			if ( $ids ) {
 				$temp_handler = $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
 				/* @var $temp_handler kTempTablesHandler */
 
 				$temp_handler->DeleteItems($event->Prefix, $event->Special, $ids);
 			}
 		}
 
 		/**
 		 * Validates only selected links
 		 *
 		 * @param kEvent $event
 		 */
 		function OnValidateSelected($event)
 		{
 			$link_ids = $this->_getSelectedIds($event);
 			if (!$link_ids) {
 				return ;
 			}
 
 			$validation_data = Array (
 				'processed' => 0,
 				'total' => count($link_ids),
 				'items' => $link_ids,
 			);
 			$this->Application->StoreVar($event->Prefix . '_status', serialize($validation_data));
 
 			$event->redirect = $this->Application->GetVar('progress_template');
 		}
 
 		/**
 		 * Validates only links, that were not previously validated
 		 *
 		 * @param kEvent $event
 		 */
 		function OnContinueValidation($event)
 		{
 			$have_data = $this->_prepareValidation($event);
 			if ($have_data) {
 				$event->redirect = $this->Application->GetVar('progress_template');
 			}
 		}
 
 		/**
 		 * Performs validation
 		 *
 		 * @param kEvent $event
 		 * @param bool $from_ajax
 		 */
 		function _validate($event, $from_ajax = true)
 		{
 			$validation_data = unserialize( $this->Application->RecallVar($event->Prefix . '_status') );
 
 			$i = 0;
 			$link_ids = $validation_data['items'];
 			$per_page = count($link_ids) >= LINK_VALIDATION_PER_PAGE ? LINK_VALIDATION_PER_PAGE : count($link_ids);
 
 			while ($i < $per_page) {
 				$this->_validateLink($link_ids[$i]);
 				$i++;
 			}
 
 			// remove processed links from array
 			array_splice($link_ids, 0, LINK_VALIDATION_PER_PAGE);
 
 			// store validation progress
 			$validation_data['processed'] += $i;
 			$validation_data['items'] = $link_ids;
 
 			if ($validation_data['processed'] >= $validation_data['total']) {
 				// finished
 				$this->Application->emailAdmin('LINK.VALIDATION.RESULTS');
 
 				$this->Application->RemoveVar($event->Prefix . '_status');
 				return true;
 			}
 
 			// show progress, proceed to next step
 			$this->Application->StoreVar($event->Prefix . '_status', serialize($validation_data));
 
 			if ($from_ajax) {
 				echo $validation_data['processed'] / $validation_data['total'] * 100;
 				$event->status = kEvent::erSTOP;
 			}
 
 			return false;
 		}
 
 		/**
 		 * Performs validation of links (called from AjaxProgressBar)
 		 *
 		 * @param kEvent $event
 		 */
 		function OnValidateProgress($event)
 		{
 			$done = $this->_validate($event, true);
 
 			if ($done) {
 				$this->Application->Redirect( $this->Application->GetVar('finish_template') );
 			}
 		}
 
 		/**
 		 * Returns categories, that are located inside recycle bin category
 		 *
 		 * @return Array
 		 */
 		function _getRecycleBinCategories()
 		{
 			$recycle_bin = $this->Application->ConfigValue('RecycleBinFolder');
 
 			if ( !is_numeric($recycle_bin) ) {
 				return Array ();
 			}
 
 			$recycle_categories = $this->Application->RecallVar('recycle_categories');
 
 			if ( $recycle_categories === false ) {
 				$categories_config = $this->Application->getUnitConfig('c');
 				$tree_indexes = $this->Application->getTreeIndex($recycle_bin);
 
 				$sql = 'SELECT ' . $categories_config->getIDField() . '
 						FROM ' . $categories_config->getTableName() . '
 						WHERE TreeLeft BETWEEN ' . $tree_indexes['TreeLeft'] . ' AND ' . $tree_indexes['TreeRight'];
 				$recycle_categories = serialize($this->Conn->GetCol($sql));
 
 				// store recycle bin categories in session to prevent query below happening on each link validation step
 				$this->Application->StoreVar('recycle_categories', $recycle_categories);
 			}
 
 			return unserialize($recycle_categories);
 
 		}
 
 		/**
 		 * Checks, that link is located in one of RecycleBin subcategories
 		 *
 		 * @param unknown_type $resource_id
 		 * @return unknown
 		 */
 		function _inRecycleBin($resource_id)
 		{
 			static $recycle_bin = null;
 
 			if ( !isset($recycle_bin) ) {
 				$recycle_bin = $this->_getRecycleBinCategories();
 			}
 
 			if ( !$recycle_bin ) {
 				// Recycle Bin not used in system -> link is 100% not there
 				return false;
 			}
 
 			$sql = 'SELECT CategoryId
 					FROM ' . $this->Application->getUnitConfig('l-ci')->getTableName() . '
 					WHERE ItemResourceId = ' . $resource_id . ' AND PrimaryCat = 1';
 
 			return in_array($this->Conn->GetOne($sql), $recycle_bin);
 		}
 
 		function _validateLink($link_id)
 		{
 			$curl_helper = $this->Application->recallObject('CurlHelper');
 			/* @var $curl_helper kCurlHelper */
 
 			$link_config = $this->Application->getUnitConfig('l');
 
 			$sql = 'SELECT Url, ResourceId
 					FROM ' . $link_config->getTableName() . '
 					WHERE ' . $link_config->getIDField() . ' = ' . $link_id;
 			$link_data = $this->Conn->GetRow($sql);
 
 			if ( !preg_match('/^(http|https):\/\/(.*)/U', $link_data['Url']) || $this->_inRecycleBin($link_data['ResourceId']) ) {
 				return;
 			}
 
 			$curl_helper->timeout = LINK_VALIDATION_TIMEOUT;
 
 			$result = $curl_helper->Send($link_data['Url']);
 			if ( $result === false || $curl_helper->lastErrorMsg != '' ) {
-				$curl_helper->lastErrorCode = 500;
+				$curl_helper->lastHTTPCode = 500;
 			}
 
 			$link_validation = $this->Application->recallObject($this->Prefix . '.-item', null, Array ('skip_autoload' => true));
 			/* @var $link_validation kDBItem */
 
 			$link_validation->Load($link_id, 'LinkId');
 
 			$now = time();
 
 			$fields_hash = Array (
 				'LinkId' => $link_id,
 				'ValidationTime_date' => $now,
 				'ValidationTime_time' => $now,
 				'ValidationCode' => $curl_helper->lastHTTPCode,
 				'ValidationStatus' => $curl_helper->lastHTTPCode < 400 ? LINK_VALIDATION_VALID : LINK_VALIDATION_INVALID,
 			);
 
 			$link_validation->SetDBFieldsFromHash($fields_hash);
 
 			return $link_validation->isLoaded() ? $link_validation->Update() : $link_validation->Create();
 		}
 
 		/**
 		 * Cancels validation (from validation progress bar)
 		 *
 		 * @param kEvent $event
 		 */
 		function OnCancelValidation($event)
 		{
 			$this->Application->RemoveVar($event->Prefix . '_status');
 		}
 
 		/**
 		 * Resets validation status for selected
 		 *
 		 * @param kEvent $event
 		 */
 		function OnResetValidationStatus($event)
 		{
 			$ids = $this->_getSelectedIds($event, true);
 			if (!$ids) {
 				return ;
 			}
 
 			$temp_handler = $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler', Array ('parent_event' => $event));
 			/* @var $temp_handler kTempTablesHandler */
 
 			$temp_handler->DeleteItems($event->Prefix, $event->Special, $ids);
 		}
 
 		/**
 		 * Returns ids, that user has checked in grid
 		 *
 		 * @param kEvent $event
 		 * @param bool $transform convert link ids to link validation ids
 		 * @return Array
 		 */
 		function _getSelectedIds($event, $transform = false)
 		{
 			$ids = Array ();
 
 			$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
 
 			if ( $items_info ) {
 				foreach ($items_info as $id => $field_values) {
 					if ( getArrayValue($field_values, 'ForeignLinkId') ) {
 						// we are not gathering ids by unit idfield here!
 						array_push($ids, $id);
 					}
 				}
 			}
 
 			if ( $transform && $ids ) {
 				$config = $event->getUnitConfig();
 
 				$sql = 'SELECT ' . $config->getIDField() . '
 						FROM ' . $config->getTableName() . '
 						WHERE LinkId IN (' . implode(',', $ids) . ')';
 				$ids = $this->Conn->GetCol($sql);
 			}
 
 			return $ids;
 		}
 
 		/**
 		 * Approves/declines selected links
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function iterateItems(kEvent $event)
 		{
 			if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
 				$event->status = kEvent::erFAIL;
 				return;
 			}
 
 			$ids = $this->_getSelectedIds($event);
 			if ( !$ids ) {
 				return;
 			}
 
 			$object = $this->Application->recallObject('l.-item', null, Array ('skip_autoload' => true));
 			/* @var $object kCatDBItem */
 
 			foreach ($ids as $id) {
 				$ret = true;
 				$object->Load($id);
 
 				switch ( $event->Name ) {
 					case 'OnApproveLinks':
 						$ret = $object->ApproveChanges();
 						break;
 
 					case 'OnDeclineLinks':
 						$ret = $object->DeclineChanges();
 						break;
 				}
 
 				if ( !$ret ) {
 					$event->status = kEvent::erFAIL;
 					$event->redirect = false;
 					break;
 				}
 			}
 		}
 
 		/**
 		 * Deletes selected links
 		 *
 		 * @param kEvent $event
 		 */
 		function OnDeleteLinks($event)
 		{
 			if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
 				$event->status = kEvent::erFAIL;
 				return;
 			}
 
 			$ids = $this->_getSelectedIds($event);
 			if (!$ids) {
 				return ;
 			}
 
 			$temp_handler = $this->Application->recallObject('l_TempHandler', 'kTempTablesHandler', Array ('parent_event' => $event));
 			/* @var $temp_handler kTempTablesHandler */
 
 			$temp_handler->DeleteItems('l', '', $ids);
 		}
 
 		/**
 		 * [HOOK] Allows to edit links, used in selected link validation records
 		 *
 		 * @param kEvent $event
 		 */
 		function OnPrepareLinkEditing($event)
 		{
 			// hook to OnAfterConfigRead instead of OnEdit, because fake ids should be available in CheckPermission
 			if ( $this->Application->GetVar('l_event') != 'OnEdit' ) {
 				return;
 			}
 
 			$items_info = Array ();
 			$ids = $this->_getSelectedIds($event);
 			$id_field = $this->Application->getUnitConfig('l')->getIDField();
 
 			foreach ($ids as $id) {
 				$items_info[$id][$id_field] = 'on';
 			}
 
 			$this->Application->SetVar('l', $items_info);
 		}
 
 		/**
 		 * Gets all links, that are not yet validated and prepare data
 		 *
 		 * @param kEvent $event
 		 *
 		 * @return bool
 		 */
 		function _prepareValidation($event)
 		{
 			// 2. get ids of all links and put them into validation queue
 			$links_config = $this->Application->getUnitConfig('l');
 
 			$sql = 'SELECT ' . $links_config->getIDField() . '
 					FROM ' . $links_config->getTableName() . '
 					WHERE LinkId NOT IN (SELECT LinkId FROM ' . $event->getUnitConfig()->getTableName() . ')';
 			$link_ids = $this->Conn->GetCol($sql);
 
 			if ( $link_ids ) {
 				$validation_data = Array (
 					'processed' => 0,
 					'total' => count($link_ids),
 					'items' => $link_ids,
 				);
 
 				$this->Application->StoreVar($event->Prefix . '_status', serialize($validation_data)); // 4K links will be 78KB serialized
 
 				return true;
 			}
 
 			return false;
 		}
 
 		/**
 		 * [SCHEDULED TASK] Performs link validation through cron
 		 *
 		 * @param kEvent $event
 		 */
 		function OnCronValidation($event)
 		{
 			$this->_resetValidation($event); // remove this for continuing to non validated before links
 
 			$have_data = $this->_prepareValidation($event);
 			if ($have_data) {
 				do {
 					$done = $this->_validate($event, false);
 				} while (!$done);
 			}
 		}
 
 		/**
 		 * Makes calculated fields to go to multilingual link fields
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnAfterConfigRead(kEvent $event)
 		{
 			parent::OnAfterConfigRead($event);
 
 			$event->getUnitConfig()->addCalculatedFieldsBySpecial('', Array (
 				'LinkName' => 'l.l' . $this->Application->GetVar('m_lang') . '_Name',
 			));
 		}
 
 	}
\ No newline at end of file
Index: branches/5.3.x/admin_templates/user_item_tab.tpl
===================================================================
--- branches/5.3.x/admin_templates/user_item_tab.tpl	(revision 16106)
+++ branches/5.3.x/admin_templates/user_item_tab.tpl	(revision 16107)
@@ -1,34 +1,34 @@
 <inp2:m_RequireLogin permissions="in-portal:user_list.view" system="1"/>
 <inp2:m_DefineElement name="catalog_tab">
 	<inp2:m_if check="m_ParamEquals" name="tab_init" value="" inverse="inverse">
 		<inp2:m_if check="m_ParamEquals" name="tab_init" value="1">
 			<div id="links_div" prefix="<inp2:m_param name="prefix"/>" view_template="in-link/user_item_tab" edit_template="in-link/links/links_edit" dep_buttons="new_link" category_id="-1" class="catalog-tab"><!-- IE minimal height problem fix --></div>
 			<script type="text/javascript">$Catalog.registerTab('links');</script>
 		</inp2:m_if>
 		<inp2:m_if check="m_ParamEquals" name="tab_init" value="2">
 			<inp2:adm_CatalogTab render_as="item_tab" prefix="$prefix" title_property="$title_property"/>
 		</inp2:m_if>
 	<inp2:m_else/>
 		<inp2:m_include t="incs/blocks"/>
 		<inp2:m_include t="incs/in-portal"/>
 		<inp2:m_include t="categories/ci_blocks"/>
 		<inp2:$prefix_InitList grid="$grid_name"/>
 
 		$Catalog.setItemCount('<inp2:m_param name="prefix"/>', '<inp2:{$prefix}_CatalogItemCount/>');
-		$Catalog.setCurrentCategory('<inp2:m_param name="prefix"/>', <inp2:m_get name="m_cat_id"/>);
+		$Catalog.setCurrentCategory('<inp2:m_param name="prefix"/>', <inp2:m_get name="m_cat_id" no_html_escape="1" js_escape="1"/>);
 		$Catalog.saveSearch('<inp2:m_Param name="prefix"/>', '<inp2:$prefix_SearchKeyword js_escape="1"/>', '<inp2:m_Param name="grid_name"/>');
 
 		<inp2:m_RenderElement name="grid_js" PrefixSpecial="$prefix" IdField="LinkId" grid="$grid_name" menu_filters="yes"/>
 
 		Grids['<inp2:m_param name="prefix"/>'].SetDependantToolbarButtons( new Array('edit','delete'));
 		$Catalog.setViewMenu('<inp2:m_param name="prefix"/>');
 		#separator#
 		<!-- links tab: begin -->
 		<inp2:m_RenderElement name="kernel_form" form_name="links_form"/>
 			<inp2:m_RenderElement name="grid" ajax="1" PrefixSpecial="$prefix" IdField="LinkId" grid="$grid_name" menu_filters="yes"/>
 		<inp2:m_RenderElement name="kernel_form_end"/>
 		<!-- links tab: end -->
 	</inp2:m_if>
 </inp2:m_DefineElement>
 
-<inp2:l_InitCatalogTab render_as="catalog_tab" default_grid="Default" radio_grid="Radio"/>
\ No newline at end of file
+<inp2:l_InitCatalogTab render_as="catalog_tab" default_grid="Default" radio_grid="Radio"/>
Index: branches/5.3.x/admin_templates/duplicate_checker.tpl
===================================================================
--- branches/5.3.x/admin_templates/duplicate_checker.tpl	(revision 16106)
+++ branches/5.3.x/admin_templates/duplicate_checker.tpl	(revision 16107)
@@ -1,73 +1,73 @@
 <inp2:m_include t="incs/header"/>
 
 <inp2:m_RenderElement name="combined_header" prefix="l.duplicates" section="in-link:duplicate_checker" grid="Duplicates" title_preset="duplicate_links" pagination="1"/>
 
 <!-- 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();
 
 				function edit()
 				{
 					open_popup('l.duplicates', 'OnStoreSelected', 'in-link/duplicate_checker/duplicate_link_view');
 				}
 
 				a_toolbar.AddButton( new ToolBarButton('edit', '<inp2:m_phrase label="la_ToolTip_Edit" escape="1"/>::<inp2:m_phrase label="la_ToolTip_Edit" escape="1"/>', edit) );
 
 				a_toolbar.AddButton( new ToolBarSeparator('sep1') );
 
 			  	a_toolbar.AddButton( new ToolBarButton('view', '<inp2:m_phrase label="la_ToolTip_View" escape="1"/>', function() {
 							show_viewmenu(a_toolbar,'view');
 						}
 				) );
 
 				a_toolbar.Render();
 
 				function set_grouping($prefix_special, $dupe_fields)
 				{
 					set_hidden_field($prefix_special + '_dupe_fields', $dupe_fields);
 					submit_event($prefix_special, 'OnSetGrouping');
 
 				}
 
 				Application.setHook(
 					'l.duplicates:OnCreateViewMenu',
 					function() {
 						// create grouping menu
 						$Menus['l.duplicates_grouping_menu'] = menuMgr.createMenu(rs('l.duplicates.grouping.menu'));
 						$Menus['l.duplicates_grouping_menu'].applyBorder(false, false, false, false);
 						$Menus['l.duplicates_grouping_menu'].dropShadow("none");
 						$Menus['l.duplicates_grouping_menu'].showIcon = true;
-						<inp2:m_Get name="m_lang" result_to_var="language"/>
+						<inp2:m_Get name="m_lang" no_html_escape="1" result_to_var="language"/>
 						$Menus['l.duplicates_grouping_menu'].addItem(rs('l.duplicates.group.name'), 'Name', 'javascript:set_grouping("l.duplicates", "|l<inp2:m_Param name="language"/>_Name|");' <inp2:m_if check="m_RecallEquals" name="l.duplicates_dupe_fields" value="|l{$language}_Name|">,['img/check_on.gif']</inp2:m_if>);
 						$Menus['l.duplicates_grouping_menu'].addItem(rs('l.duplicates.group.url'), 'Url',  'javascript:set_grouping("l.duplicates", "|Url|");' <inp2:m_if check="m_RecallEquals" name="l.duplicates_dupe_fields" value="|Url|">,['img/check_on.gif']</inp2:m_if>);
 						$Menus['l.duplicates_grouping_menu'].addItem(rs('l.duplicates.group.name.url'), 'Name <inp2:m_phrase name="la_and"/> Url', 'javascript:set_grouping("l.duplicates", "|l<inp2:m_Param name="language"/>_Name|Url|");' <inp2:m_if check="m_RecallEquals" name="l.duplicates_dupe_fields" value="|l{$language}_Name|Url|">,['img/check_on.gif']</inp2:m_if>);
 
 						// add grouping menu to view menu
 						$Menus['l.duplicates_view_menu'].addItem(
 							rs('l.duplicates.grouping.menu.item'),
 							'<inp2:m_phrase name="la_menu_Grouping"/>',
 							'javascript:void()',
 							null, true, null,
 							rs('l.duplicates.grouping.menu'),
 							'<inp2:m_phrase name="la_menu_Grouping"/>'
 						);
 					}
 				);
 			</script>
 		</td>
 
 		<inp2:m_RenderElement name="search_main_toolbar" prefix="l.duplicates" grid="Duplicates"/>
 	</tr>
 </tbody>
 </table>
 
 <inp2:m_RenderElement name="grid" PrefixSpecial="l.duplicates" IdField="LinkId" grid="Duplicates"/>
 <script type="text/javascript">
 	Grids['l.duplicates'].SetDependantToolbarButtons( new Array('edit') );
 </script>
 
-<inp2:m_include t="incs/footer"/>
\ No newline at end of file
+<inp2:m_include t="incs/footer"/>
Index: branches/5.3.x/admin_templates/catalog_tab.tpl
===================================================================
--- branches/5.3.x/admin_templates/catalog_tab.tpl	(revision 16106)
+++ branches/5.3.x/admin_templates/catalog_tab.tpl	(revision 16107)
@@ -1,55 +1,55 @@
 <inp2:m_RequireLogin permissions="in-portal:browse.view" system="1"/>
 <inp2:m_DefineElement name="catalog_tab">
 	<inp2:m_if check="m_ParamEquals" name="tab_init" value="" inverse="inverse">
 		<inp2:m_if check="m_ParamEquals" name="tab_init" value="1">
 			a_toolbar.AddButton(
 				new ToolBarButton(
 					'in-link:new_link',
 					'<inp2:m_phrase label="lu_btn_NewLink" escape="1"/>',
 					add_item,
 					true
 		 		)
 		 	);
 		</inp2:m_if>
 
 		<inp2:m_if check="m_ParamEquals" name="tab_init" value="2">
 			<div id="links_div" prefix="<inp2:m_param name='prefix'/>" view_template="in-link/catalog_tab" edit_template="in-link/links/links_edit" category_id="-1" dep_buttons="new_link" class="catalog-tab"><!-- IE minimal height problem fix --></div>
 			<script type="text/javascript">$Catalog.registerTab('links');</script>
 		</inp2:m_if>
 
 		<inp2:m_if check="m_ParamEquals" name="tab_init" value="3">
 			$Catalog.setItemCount('<inp2:m_Param name="prefix"/>', '<inp2:{$prefix}_CatalogItemCount grid="$grid_name"/>');
 		</inp2:m_if>
 	<inp2:m_else/>
 		<inp2:lang.current_SetContentType content_type="text/plain"/>
 		<inp2:m_include t="incs/blocks"/>
 		<inp2:m_include t="incs/in-portal"/>
 		<inp2:m_include t="categories/ci_blocks"/>
 		<inp2:$prefix_InitList grid="$grid_name"/>
 
 		$Catalog.setItemCount('<inp2:m_param name="prefix"/>', '<inp2:{$prefix}_CatalogItemCount/>');
-		$Catalog.setCurrentCategory('<inp2:m_param name="prefix"/>', <inp2:m_get name="m_cat_id"/>);
+		$Catalog.setCurrentCategory('<inp2:m_param name="prefix"/>', <inp2:m_get name="m_cat_id" no_html_escape="1" js_escape="1"/>);
 		$Catalog.saveSearch('<inp2:m_Param name="prefix"/>', '<inp2:$prefix_SearchKeyword js_escape="1"/>', '<inp2:m_Param name="grid_name"/>');
 
 		<inp2:m_RenderElement name="grid_js" PrefixSpecial="$prefix" IdField="LinkId" grid="$grid_name" menu_filters="yes"/>
 		<inp2:m_RenderElement name="grid_search_buttons" PrefixSpecial="$prefix" grid="$grid_name" ajax="1"/>
 		<inp2:m_if check="m_ParamEquals" name="tab_dependant" value="yes">
 			Grids['<inp2:m_param name="prefix"/>'].AddAlternativeGrid('<inp2:m_param name="cat_prefix"/>', true);
 		</inp2:m_if>
 		Grids['<inp2:m_param name="prefix"/>'].SetDependantToolbarButtons( new Array('edit','delete','approve','decline','sep3','cut','copy','move_up','move_down','sep6'));
 		<inp2:m_RenderElement name="reflect_catalog_buttons"/>
 
 		$Catalog.setViewMenu('<inp2:m_param name="prefix"/>');
 		<inp2:m_if check="m_ParamEquals" name="tab_mode" value="single">
 			Grids['<inp2:m_param name="prefix"/>'].DblClick = function() {return false};
 		</inp2:m_if>
 		#separator#
 		<!-- links tab: begin -->
 		<inp2:m_RenderElement name="kernel_form" form_name="links_form"/>
 			<inp2:m_RenderElement name="grid" ajax="1" PrefixSpecial="$prefix" IdField="LinkId" grid="$grid_name" menu_filters="yes"/>
 		<inp2:m_RenderElement name="kernel_form_end"/>
 		<!-- links tab: end -->
 	</inp2:m_if>
 </inp2:m_DefineElement>
 
-<inp2:l_InitCatalogTab render_as="catalog_tab" default_grid="Default" radio_grid="Radio"/>
\ No newline at end of file
+<inp2:l_InitCatalogTab render_as="catalog_tab" default_grid="Default" radio_grid="Radio"/>
Index: branches/5.3.x/install/upgrades.php
===================================================================
--- branches/5.3.x/install/upgrades.php	(revision 16106)
+++ branches/5.3.x/install/upgrades.php	(revision 16107)
@@ -1,184 +1,185 @@
 <?php
 /**
 * @version	$Id$
 * @package	In-Link
 * @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!');
 
 	$upgrade_class = 'InLinkUpgrades';
 
 	/**
 	 * Class, that holds all upgrade scripts for "In-Link" module
 	 *
 	 */
 	class InLinkUpgrades extends kUpgradeHelper {
 
 		public function __construct()
 		{
 			parent::__construct();
 
 			$this->dependencies = Array (
 				'4.3.9' => Array ('Core' => '4.3.9'),
 				'5.0.0' => Array ('Core' => '5.0.0'),
 				'5.0.1' => Array ('Core' => '5.0.1'),
 				'5.0.2-B1' => Array ('Core' => '5.0.2-B1'),
 				'5.0.2-B2' => Array ('Core' => '5.0.2-B2'),
 				'5.0.2-RC1' => Array ('Core' => '5.0.2-RC1'),
 				'5.0.2' => Array ('Core' => '5.0.2'),
 				'5.0.3-B1' => Array ('Core' => '5.0.3-B1'),
 				'5.0.3-B2' => Array ('Core' => '5.0.3-B2'),
 				'5.0.3-RC1' => Array ('Core' => '5.0.3-RC1'),
 				'5.0.3' => Array ('Core' => '5.0.3'),
 				'5.0.4-B1' => Array ('Core' => '5.0.4-B1'),
 				'5.0.4-B2' => Array ('Core' => '5.0.4-B2'),
 				'5.0.4' => Array ('Core' => '5.0.4'),
 				'5.1.0-B1' => Array ('Core' => '5.1.0-B1'),
 				'5.1.0-RC1' => Array ('Core' => '5.1.0-RC1'),
 				'5.1.0' => Array ('Core' => '5.1.0'),
 				'5.1.1-B1' => Array ('Core' => '5.1.1-B1'),
 				'5.1.1-B2' => Array ('Core' => '5.1.1-B2'),
 				'5.1.1-RC1' => Array ('Core' => '5.1.1-RC1'),
 				'5.1.1' => Array ('Core' => '5.1.1'),
 				'5.1.2-B1' => Array ('Core' => '5.1.2-B1'),
 				'5.1.2-RC1' => Array ('Core' => '5.1.2-RC1'),
 				'5.1.2' => Array ('Core' => '5.1.2'),
 				'5.1.3-B1' => Array ('Core' => '5.1.3-B2'),
 				'5.1.3-RC1' => Array ('Core' => '5.1.3-RC1'),
 				'5.1.3-RC2' => Array ('Core' => '5.1.3-RC2'),
 				'5.1.3' => Array ('Core' => '5.1.3'),
 				'5.2.0-B1' => Array ('Core' => '5.2.0-B1'),
 				'5.2.0-B2' => Array ('Core' => '5.2.0-B2'),
 				'5.2.0-B3' => Array ('Core' => '5.2.0-B3'),
 				'5.2.0-RC1' => Array ('Core' => '5.2.0-RC1'),
 				'5.2.0' => Array ('Core' => '5.2.0'),
 				'5.2.1-B1' => Array ('Core' => '5.2.1-B1'),
 				'5.2.1-B2' => Array ('Core' => '5.2.1-B2'),
 				'5.2.1-RC1' => Array ('Core' => '5.2.1-RC1'),
+				'5.2.1' => Array ('Core' => '5.2.1'),
 				'5.3.0-B1' => Array ('Core' => '5.3.0-B1'),
 			);
 		}
 
 		/**
 		 * Changes table structure, where multilingual fields of TEXT type are present
 		 *
 		 * @param string $mode when called mode {before, after)
 		 */
 		function Upgrade_5_0_0($mode)
 		{
 			if ($mode == 'after') {
 				$categories_config = $this->Application->getUnitConfig('c');
 				$root_category = $this->Application->findModule('Name', 'In-Link', 'RootCat');
 
 				$sql = 'UPDATE ' . $categories_config->getTableName() . '
 						SET UseMenuIconUrl = 1, MenuIconUrl = "in-link/img/menu_links.gif"
 						WHERE ' . $categories_config->getIDField() . ' = ' . $root_category;
 				$this->Conn->Query($sql);
 
 				$this->_updateDetailTemplate('l', 'inlink/detail', 'in-link/designs/detail');
 
 				// copy link name and description to their multilingual equivalents
 				$this->_copyToMultilingual();
 			}
 		}
 
 		/**
 		 * Copy link values from normal fields to multilingual
 		 *
 		 */
 		function _copyToMultilingual()
 		{
 			$fields = Array ('Name', 'Description');
 			$primary_language = $this->Application->GetDefaultLanguageId();
 
 			$set_clause = Array ();
 			foreach ($fields as $field) {
 				$set_clause[] = 'l' . $primary_language . '_' . $field . ' = ' . $field;
 			}
 
 			$sql = 'UPDATE ' . TABLE_PREFIX . 'Link
 					SET ' . implode(', ', $set_clause);
 			$this->Conn->Query($sql);
 		}
 
 		/**
 		 * Update to 5.0.1
 		 *
 		 * @param string $mode when called mode {before, after)
 		 */
 		function Upgrade_5_0_1($mode)
 		{
 			if ($mode == 'after') {
 				$this->_updateDetailTemplate('l', 'in-link/designs/detail', 'in-link/links/link_detail');
 
 				// delete old events
 				$events_to_delete = Array ( 'LINK.OWNER.MODIFY.PENDING', 'LINK.OWNER.MODIFY' );
 
 				$sql = 'SELECT EventId FROM ' . TABLE_PREFIX . 'Events
 							WHERE Event IN ("' . implode('","', $events_to_delete) . '")';
 				$event_ids = $this->Conn->GetCol($sql);
 
 				if ($event_ids) {
 					$sql = 'DELETE FROM ' . TABLE_PREFIX . 'EmailMessage
 								WHERE EventId IN (' . implode(',', $event_ids) . ')';
 					$this->Conn->Query($sql);
 
 					$sql = 'DELETE FROM ' . TABLE_PREFIX . 'Events
 								WHERE EventId IN (' . implode(',', $event_ids) . ')';
 					$this->Conn->Query($sql);
 
 					$sql = 'DELETE FROM ' . TABLE_PREFIX . 'Phrase
 								WHERE Phrase IN ("la_event_link.owner.modify", "la_event_link.owner.modify.pending")';
 					$this->Conn->Query($sql);
 				}
 			}
 		}
 
 		/**
 		 * Update to 5.0.4-B1
 		 *
 		 * @param string $mode when called mode {before, after)
 		 */
 		function Upgrade_5_0_4_B1($mode)
 		{
 			if ($mode == 'after') {
 				// check in-link custom fields if need to add to search config
 				$custom_fields = Array (
 					'LinkAddress' => "('CustomField', 'LinkAddress', 1, 1, 'la_fld_LinkAddress', 'lu_fld_LinkAddress', 'In-Link', 'la_section_BusinessLocation', 1, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, {CUSTOM_FIELD_ID})",
 					'LinkCity' => "('CustomField', 'LinkCity', 1, 1, 'la_fld_LinkCity', 'lu_fld_LinkCity', 'In-Link', 'la_section_BusinessLocation', 2, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, {CUSTOM_FIELD_ID})",
 					'LinkState' => "('CustomField', 'LinkState', 1, 1, 'la_fld_LinkState', 'lu_fld_LinkState', 'In-Link', 'la_section_BusinessLocation', 3, DEFAULT, 0, 'select', NULL, NULL, NULL, NULL, NULL, NULL, {CUSTOM_FIELD_ID})",
 					'LinkZipCode' => "('CustomField', 'LinkZipCode', 1, 1, 'la_fld_LinkZipCode', 'lu_fld_LinkZipCode', 'In-Link', 'la_section_BusinessLocation', 4, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, {CUSTOM_FIELD_ID})",
 					'LinkCountry' => "('CustomField', 'LinkCountry', 1, 1, 'la_fld_LinkCountry', 'lu_fld_LinkCountry', 'In-Link', 'la_section_BusinessLocation', 5, DEFAULT, 0, 'select', NULL, NULL, NULL, NULL, NULL, NULL, {CUSTOM_FIELD_ID})",
 					'LinkPhone' => "('CustomField', 'LinkPhone', 1, 1, 'la_fld_LinkPhone', 'lu_fld_LinkPhone', 'In-Link', 'la_section_BusinessLocation', 6, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, {CUSTOM_FIELD_ID})",
 				);
 
 				// get all in-link custom fields ides at once
 				$sql = 'SELECT CustomFieldId, FieldName
 						FROM ' . TABLE_PREFIX . 'CustomField
 						WHERE Type = 4 AND IsSystem = 0';
 				$custom_field_ids = $this->Conn->GetCol($sql, 'FieldName');
 
 				foreach ($custom_fields as $field_name => $custom_field_sql) {
 					$sql = 'SELECT FieldName
 							FROM ' . TABLE_PREFIX . 'SearchConfig
 							WHERE (FieldName = ' . $this->Conn->qstr($field_name) . ') AND (LOWER(ModuleName) = "in-link")';
 					$found = $this->Conn->GetOne($sql);
 
 					if (!$found) {
 						// replace sql and insert new search config record
 						$sql = str_replace('{CUSTOM_FIELD_ID}', $custom_field_ids[$field_name], $custom_field_sql);
 						$sql = 'INSERT INTO ' . TABLE_PREFIX . 'SearchConfig VALUES ' . $sql;
 						$this->Conn->Query($sql);
 					}
 				}
 			}
 		}
 	}
\ No newline at end of file
Index: branches/5.3.x/install/upgrades.sql
===================================================================
--- branches/5.3.x/install/upgrades.sql	(revision 16106)
+++ branches/5.3.x/install/upgrades.sql	(revision 16107)
@@ -1,207 +1,209 @@
 # ===== v 4.3.9 =====
 INSERT INTO Events VALUES (DEFAULT, 'LINK.VALIDATION.RESULTS', NULL, 1, 0, 'In-Link', 'la_event_link.validation.results', 1);
 
 INSERT INTO ImportScripts VALUES (DEFAULT, 'Links from CSV file [In-Link]', '', 'l', 'In-Link', '', 'CSV', '1');
 
 UPDATE CustomField
 SET ValueList = '=+||<SQL>SELECT DestAbbr AS OptionValue, DestName AS OptionName FROM <PREFIX>StdDestinations WHERE DestType = 2 AND (DestParentId = 225 OR DestParentId = 38) ORDER BY DestParentId DESC, DestAbbr ASC</SQL>'
 WHERE FieldName = 'LinkState';
 
 UPDATE CustomField
 SET ValueList = '=+||<SQL>SELECT DestAbbr AS OptionValue, DestName AS OptionName FROM <PREFIX>StdDestinations WHERE DestType = 1 ORDER BY DestAbbr ASC</SQL>'
 WHERE FieldName = 'LinkCountry';
 
 # ===== v 5.0.0 =====
 INSERT INTO Counters VALUES (DEFAULT, 'linkhits_count', 'SELECT ROUND(SUM(Hits)) FROM <%PREFIX%>Link', NULL, NULL, '300', '0', '|Link|');
 UPDATE Category SET Template = '/in-link/designs/section' WHERE Template = 'inlink/index';
 UPDATE Category SET CachedTemplate = '/in-link/designs/section' WHERE CachedTemplate = 'inlink/index';
 
 UPDATE ConfigurationValues SET VariableValue = '/in-link/designs/section' WHERE VariableName = 'l_CategoryTemplate';
 UPDATE ConfigurationValues SET VariableValue = 'in-link/designs/detail' WHERE VariableName = 'l_ItemTemplate';
 
 INSERT INTO Permissions VALUES (DEFAULT, 'in-link:links.view', 11, 1, 1, 0);
 INSERT INTO Permissions VALUES (DEFAULT, 'in-link:setting_folder.view', 11, 1, 1, 0);
 DELETE FROM Permissions WHERE Permission LIKE 'in-link:inlink_general.%';
 
 UPDATE Events SET Description = 'la_event_link.owner.modify' WHERE  Description = 'la_event_link.modify.modify';
 UPDATE Events SET Description = 'la_event_link.owner.modify.pending' WHERE  Description = 'la_event_link.modify.modify.pending';
 
 UPDATE Phrase SET Module = 'In-Link' WHERE ((Phrase LIKE '%Links%' OR Phrase LIKE '%Listing%') AND (Module = 'Core') AND Phrase NOT IN ('la_section_QuickLinks'));
 
 UPDATE Phrase SET Module = 'In-Link', PhraseType = 1 WHERE ( (Phrase LIKE '%Validation%' OR Phrase LIKE 'la_title_In-Link') AND (Module = 'Core') AND Phrase NOT IN ('la_ValidationEmail', 'la_prompt_validation'));
 
 # ===== v 5.0.1 =====
 UPDATE ConfigurationValues SET VariableValue = 'in-link/links/link_detail' WHERE VariableName = 'l_ItemTemplate';
 
 UPDATE ConfigurationAdmin SET ValueList = 'ReviewText=la_opt_CommentText,CreatedOn=la_opt_CreatedOn'
 WHERE VariableName IN ('Link_ReviewsSort', 'Link_ReviewsSort2');
 
 UPDATE ConfigurationAdmin SET ValueList = 'ASC=la_common_Ascending,DESC=la_common_Descending'
 WHERE VariableName IN ('Link_ReviewsOrder', 'Link_ReviewsOrder2');
 
 UPDATE ConfigurationAdmin SET ValueList = 'Name=la_Link_Name,Description=la_Link_Description,Url=la_Link_URL,CreatedOn=la_opt_CreatedOn,Hits=la_Link_Hits,CachedRating=la_opt_Rating,<SQL>SELECT Prompt AS OptionName, CONCAT("cust_", FieldName) AS OptionValue FROM <PREFIX>CustomField WHERE (Type = 4) AND (IsSystem = 0)</SQL>'
 WHERE VariableName IN ('Link_SortField', 'Link_SortField2');
 
 UPDATE ConfigurationAdmin
 SET ValueList = '1=la_opt_Sec,60=la_opt_Min,3600=la_opt_Hour,86400=la_opt_Day,604800=la_opt_Week,2419200=la_opt_Month,29030400=la_opt_Year'
 WHERE VariableName IN ('link_ReviewDelay_Interval', 'link_RatingDelay_Interval');
 
 UPDATE CustomField SET FieldLabel = 'la_fld_cust_l_ItemTemplate', Prompt = 'la_fld_cust_l_ItemTemplate' WHERE FieldName = 'l_ItemTemplate';
 
 INSERT INTO Events VALUES(DEFAULT, 'LINK.REVIEW.ADD.PENDING', NULL, 1, 0, NULL, 'In-Link', 'la_event_link.review.add.pending', 1);
 
 UPDATE ConfigurationAdmin SET ValueList = 'style="width: 50px;"' WHERE VariableName IN ('link_ReviewDelay_Value', 'link_RatingDelay_Value');
 
 # ===== v 5.0.2-B1 =====
 ALTER TABLE ListingTypes CHANGE Description Description text NULL;
 ALTER TABLE LinkValidation CHANGE ValidationTime ValidationTime INT NULL DEFAULT NULL;
 ALTER TABLE LinkVisits CHANGE VisitTimestamp VisitTimestamp INT(11) NULL DEFAULT NULL;
 
 # ===== v 5.0.2-B2 =====
 
 # ===== v 5.0.2-RC1 =====
 
 # ===== v 5.0.2 =====
 
 # ===== v 5.0.3-B1 =====
 UPDATE Phrase
 SET Module = 'In-Link'
 WHERE Phrase IN (
 	'lu_PermName_Link.Add.Pending_desc', 'lu_PermName_Link.Add_desc', 'lu_PermName_Link.Delete_desc',
 	'lu_PermName_Link.Modify.Pending_desc', 'lu_PermName_Link.Modify_desc', 'lu_PermName_Link.Owner.Delete_desc',
 	'lu_PermName_Link.Owner.Modify.Pending_desc', 'lu_PermName_Link.Owner.Modify_desc', 'lu_PermName_Link.Rate_desc',
 	'lu_PermName_Link.Review_Pending_desc', 'lu_PermName_Link.View_desc'
 );
 
 # ===== v 5.0.3-B2 =====
 
 # ===== v 5.0.3-RC1 =====
 
 # ===== v 5.0.3 =====
 
 # ===== v 5.0.4-B1 =====
 
 # ===== v 5.0.4-B2 =====
 
 # ===== v 5.0.4 =====
 
 # ===== v 5.1.0-B1 =====
 UPDATE Modules SET Path = 'modules/in-link/' WHERE `Name` = 'In-Link';
 DELETE FROM ConfigurationValues WHERE VariableName IN ('StartValidationTime', 'LastExpirationTime', 'Link_Root');
 
 UPDATE CustomField
 SET ValueList = '=+||<SQL+>SELECT IsoCode AS OptionValue, l%3$s_Name AS OptionName FROM <PREFIX>CountryStates WHERE Type = 2 ORDER BY StateCountryId DESC, IsoCode ASC</SQL>'
 WHERE ValueList = '=+||<SQL>SELECT DestAbbr AS OptionValue, DestName AS OptionName FROM <PREFIX>StdDestinations WHERE DestType = 2 AND (DestParentId = 225 OR DestParentId = 38) ORDER BY DestParentId DESC, DestAbbr ASC</SQL>';
 
 UPDATE CustomField
 SET ValueList = '=+||<SQL+>SELECT IsoCode AS OptionValue, l%3$s_Name AS OptionName FROM <PREFIX>CountryStates WHERE Type = 1 ORDER BY IsoCode ASC</SQL>'
 WHERE ValueList = '=+||<SQL>SELECT DestAbbr AS OptionValue, DestName AS OptionName FROM <PREFIX>StdDestinations WHERE DestType = 1 ORDER BY DestAbbr ASC</SQL>';
 
 DELETE FROM Permissions WHERE Permission LIKE 'in-link:configuration_email%';
 
 # ===== v 5.1.0-RC1 =====
 
 # ===== v 5.1.0 =====
 
 # ===== v 5.1.1-B1 =====
 ALTER TABLE Link
 	CHANGE CreatedById CreatedById INT(11) NULL DEFAULT NULL ,
 	CHANGE ModifiedById ModifiedById INT(11) NULL DEFAULT NULL;
 
 # ===== v 5.1.1-B2 =====
 UPDATE Events
 SET l<%PRIMARY_LANGUAGE%>_Body = REPLACE(l<%PRIMARY_LANGUAGE%>_Body, '<inp2:<inp2:', '<inp2:')
 WHERE Event LIKE 'LINK.ADD.PENDING' AND `Type` = 1;
 
 # ===== v 5.1.1-RC1 =====
 
 # ===== v 5.1.1 =====
 
 # ===== v 5.1.2-B1 =====
 
 # ===== v 5.1.2-RC1 =====
 
 # ===== v 5.1.2 =====
 
 # ===== v 5.1.3-B1 =====
 
 # ===== v 5.1.3-RC1 =====
 UPDATE ConfigurationValues
 SET VariableValue = 'in-link/links/link_detail'
 WHERE VariableName = 'l_ItemTemplate' AND VariableValue = 'in-link/designs/detail';
 
 # ===== v 5.1.3-RC2 =====
 
 # ===== v 5.1.3 =====
 UPDATE Phrase
 SET `Module` = 'Core'
 WHERE PhraseKey IN ('LA_FLD_LISTINGID', 'LA_FLD_LISTINGTYPE');
 
 # ===== v 5.2.0-B1 =====
 UPDATE SearchConfig
 SET ForeignField = 'PortalUser.Username'
 WHERE ForeignField = 'PortalUser.Login' AND ModuleName = 'In-Link';
 
 UPDATE SearchConfig
 SET DisplayName = REPLACE(DisplayName, 'lu_', 'lc_')
 WHERE DisplayName IN ('lu_field_linkid', 'lu_field_url');
 
 UPDATE SystemSettings
 SET Section = 'in-portal:configure_advanced', ModuleOwner = 'In-Portal', Heading = 'la_section_Settings3rdPartyAPI', DisplayOrder = 80.02
 WHERE VariableName = 'l_GoogleMapsAPIKey';
 
 UPDATE SystemSettings
 SET DisplayOrder = DisplayOrder - 0.01
 WHERE VariableName IN ('l_EnableLinkContactForm', 'ReciprocalLinkChecking');
 
 UPDATE LanguageLabels
 SET Module = 'In-Link'
 WHERE PhraseKey IN ('LA_LINK_CREATEDON', 'LA_LINK_DESCRIPTION', 'LA_LINK_HITS', 'LA_LINK_NAME', 'LA_LINK_URL');
 
 DELETE FROM LanguageLabels
 WHERE PhraseKey IN (
 	'LA_LINK_URLSTATUS_PROMPT', 'LA_TEXT_LINK_SEARCH', 'LA_LINK_CATCHEDRATING',
 	'LA_LINK_CATCHEDREVIEWSQTY', 'LA_LINK_CATCHEDVOTESQTY'
 );
 
 DELETE FROM SystemSettings
 WHERE VariableName IN (
 	'Link_Highlight_OpenTag', 'Link_Highlight_CloseTag', 'Link_RatingToPop', 'Link_UrlStatus',
 	'Search_Link_CatchedRating', 'Search_Link_CatchedReviewsQty', 'Search_Link_CatchedVotesQty',
 	'Search_Link_CreatedOn', 'Search_Link_Description', 'Search_Link_EditorsPick', 'Search_Link_Hits',
 	'Search_Link_HotItem', 'Search_Link_LinkId', 'Search_Link_Name', 'Search_Link_NewItem', 'Search_Link_PopItem',
 	'Search_Link_Priority', 'Search_Link_ResourceId', 'Search_Link_ReviewById', 'Search_Link_Status', 'Search_Link_Url'
 );
 
 UPDATE SystemSettings
 SET DisplayOrder = DisplayOrder - 0.01
 WHERE VariableName IN (
 	'link_ReviewDelay_Value', 'link_ReviewDelay_Interval', 'link_RatingDelay_Value', 'link_RatingDelay_Interval',
 	'l_MaxCategories', 'l_EnableGoogleMaps', 'l_EnableLinkContactForm', 'ReciprocalLinkChecking'
 );
 
 UPDATE SearchConfig
 SET ForeignField = 'Users.Username'
 WHERE ForeignField = 'PortalUser.Username' AND ModuleName = 'In-Link';
 
 # ===== v 5.2.0-B2 =====
 UPDATE Link main_table
 SET main_table.CachedReviewsQty = (SELECT COUNT(*) FROM <%TABLE_PREFIX%>CatalogReviews review_table WHERE review_table.ItemId = main_table.ResourceId);
 
 # ===== v 5.2.0-B3 =====
 
 # ===== v 5.2.0-RC1 =====
 
 # ===== v 5.2.0 =====
 INSERT INTO Permissions VALUES(DEFAULT, 'in-link:configuration_output.add', 11, 1, 1, 0);
 
 # ===== v 5.2.1-B1 =====
 
 # ===== v 5.2.1-B2 =====
 UPDATE Modules
 SET ClassNamespace = 'Intechnic\\InPortal\\Modules\\InLink'
 WHERE `Name` = 'In-Link';
 
 # ===== v 5.2.1-RC1 =====
 
+# ===== v 5.2.1 =====
+
 # ===== v 5.3.0-B1 =====
Index: branches/5.3.x
===================================================================
--- branches/5.3.x	(revision 16106)
+++ branches/5.3.x	(revision 16107)

Property changes on: branches/5.3.x
___________________________________________________________________
Modified: svn:mergeinfo
## -0,0 +0,2 ##
   Merged /modules/in-link/releases/5.2.1:r16070
   Merged /modules/in-link/branches/5.2.x:r15900-16069