Index: branches/5.2.x/core/units/configuration/configuration_event_handler.php
===================================================================
--- branches/5.2.x/core/units/configuration/configuration_event_handler.php	(revision 15524)
+++ branches/5.2.x/core/units/configuration/configuration_event_handler.php	(revision 15525)
@@ -1,562 +1,567 @@
 <?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 ConfigurationEventHandler extends kDBEventHandler  {
 
 		/**
 		 * Allows to override standard permission mapping
 		 *
 		 * @return void
 		 * @access protected
 		 * @see kEventHandler::$permMapping
 		 */
 		protected function mapPermissions()
 		{
 			parent::mapPermissions();
 
 			$permissions = Array (
 				'OnGenerateMaintenancePage' => Array ('self' => 'add|edit'),
 			);
 
 			$this->permMapping = array_merge($this->permMapping, $permissions);
 		}
 
 		/**
 		 * Changes permission section to one from REQUEST, not from config
 		 *
 		 * @param kEvent $event
 		 * @return bool
 		 * @access public
 		 */
 		public function CheckPermission(kEvent $event)
 		{
 			$event->setEventParam('PermSection', $this->Application->GetVar('section'));
 			return parent::CheckPermission($event);
 		}
 
 		/**
 		 * Apply any custom changes to list's sql query
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 * @see kDBEventHandler::OnListBuild()
 		 */
 		protected function SetCustomQuery(kEvent $event)
 		{
 			parent::SetCustomQuery($event);
 
 			$object = $event->getObject();
 			/* @var $object kDBList */
 
 			$module = $this->Application->GetVar('module');
 			$section = $this->Application->GetVar('section');
 
 			$object->addFilter('module_filter', '%1$s.ModuleOwner = ' . $this->Conn->qstr($module));
 			$object->addFilter('section_filter', '%1$s.Section = ' . $this->Conn->qstr($section));
 
 			$can_change = $this->Application->ConfigValue('AllowAdminConsoleInterfaceChange');
 
 			if ( !$can_change && !$this->Application->isDebugMode() ) {
 				$object->addFilter('interface_change_filter', '%1$s.VariableName NOT IN ("AdminConsoleInterface", "AllowAdminConsoleInterfaceChange")');
 			}
 
 			if ( defined('IS_INSTALL') && IS_INSTALL ) {
 				$object->addFilter('install_filter', '%1$s.Install = 1');
 			}
 
 			$object->addFilter('visible_filter', '%1$s.Heading <> ""');
 		}
 
 		/**
 		 * Presets new system setting fields
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnPreCreate(kEvent $event)
 		{
 			parent::OnPreCreate($event);
 
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			$object->SetDBField('Section', $this->Application->GetVar('section'));
 			$object->SetDBField('ModuleOwner', $this->Application->GetVar('module'));
 		}
 
 		/**
 		 * Sets custom validation
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnAfterItemLoad(kEvent $event)
 		{
 			static $default_field_options = null;
 
 			parent::OnAfterItemLoad($event);
 
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			// ability to validate each configuration variable separately
 			if ( !isset($default_field_options) ) {
 				$default_field_options = $object->GetFieldOptions('VariableValue');
 			}
 
 			$new_field_options = $default_field_options;
 			$validation = $object->GetDBField('Validation');
 
 			if ( $validation ) {
 				$new_field_options = array_merge($new_field_options, unserialize($validation));
 			}
 
 			$object->SetFieldOptions('VariableValue', $new_field_options);
 		}
 
 		/**
 		 * Performs custom validation
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnBeforeItemValidate(kEvent $event)
 		{
 			parent::OnBeforeItemValidate($event);
 
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			// if password field is empty, then don't update
 			if ( $object->GetDBField('ElementType') == 'password' ) {
 				if ( trim($object->GetDBField('VariableValue')) != '' ) {
 					$password_formatter = $this->Application->recallObject('kPasswordFormatter');
 					/* @var $password_formatter kPasswordFormatter */
 
 					$object->SetDBField('VariableValue', $password_formatter->EncryptPassword($object->GetDBField('VariableValue'), 'b38'));
 				}
 			}
 
 			$this->_processCountryState($event);
 
 			$variable_name = $object->GetDBField('VariableName');
 			$new_value = $object->GetDBField('VariableValue');
 
 			if ( $variable_name == 'AdminConsoleInterface' ) {
 				$can_change = $this->Application->ConfigValue('AllowAdminConsoleInterfaceChange');
 
 				if ( ($new_value != $object->GetOriginalField('VariableValue')) && !$can_change ) {
 					$object->SetError('VariableValue', 'not_allowed', 'la_error_OperationNotAllowed');
 				}
 			}
 			elseif ( $variable_name == 'HardMaintenanceTemplate' ) {
 				$compile = $event->MasterEvent->getEventParam('compile_maintenance_template');
 				$compile = $compile || $new_value != $object->GetOriginalField('VariableValue');
 
 				if ( $compile && !$this->_generateMaintenancePage($new_value) ) {
 					$object->SetError('VariableValue', 'template_file_missing', 'la_error_TemplateFileMissing');
 				}
 			}
 			elseif ( $variable_name == 'DefaultEmailRecipients' ) {
 				$email_event_data = $this->Application->GetVar('emailevents_' . $event->Prefix);
 				$object->SetDBField('VariableValue', $email_event_data[0]['Recipients']);
 			}
 
 			$sections_helper = $this->Application->recallObject('SectionsHelper');
 			/* @var $sections_helper kSectionsHelper */
 
 			$section = $object->GetDBField('Section');
 
 			if ( $section && !$sections_helper->getSectionData($section) ) {
 				$object->SetError('Section', 'unknown_section');
 			}
 		}
 
 		/**
 		 * Checks, that state belongs to selected country
 		 *
 		 * @param kEvent $event
 		 * @access protected
 		 */
 		protected function _processCountryState(kEvent $event)
 		{
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			$country_iso = $this->_getCountryByState($event);
 			$state_name = $object->GetDBField('VariableValue');
 
 			if ( !$country_iso || !$state_name ) {
 				return;
 			}
 
 			$cs_helper = $this->Application->recallObject('CountryStatesHelper');
 			/* @var $cs_helper kCountryStatesHelper */
 
 			$state_iso = $cs_helper->getStateIso($state_name, $country_iso);
 
 			if ( $state_iso !== false ) {
 				$object->SetDBField('VariableValue', $state_iso);
 			}
 			else {
 				// selected state doesn't belong to selected country
 				$object->SetError('VariableValue', 'invalid_state', 'la_InvalidState');
 			}
 		}
 
 		/**
 		 * Returns country iso code, that matches current state variable name
 		 *
 		 * @param kEvent $event
 		 * @return bool
 		 * @access protected
 		 */
 		protected function _getCountryByState(kEvent $event)
 		{
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			$variable_name = $object->GetDBField('VariableName');
 
 			$state_country_hash = Array (
 				'Comm_State' => 'Comm_Country',
 				'Comm_Shipping_State' => 'Comm_Shipping_Country'
 			);
 
 			if ( !array_key_exists($variable_name, $state_country_hash) ) {
 				return false;
 			}
 
 			$field_values = $this->Application->GetVar($event->getPrefixSpecial(true));
 
 			$sql = 'SELECT VariableId
 					FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
 					WHERE VariableName = ' . $this->Conn->qstr($state_country_hash[$variable_name]);
 			$country_variable_id = $this->Conn->GetOne($sql);
 
 			return $field_values[$country_variable_id]['VariableValue'];
 		}
 
 		/**
 		 * Does custom password setting processong
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnBeforeItemUpdate(kEvent $event)
 		{
 			parent::OnBeforeItemUpdate($event);
 
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			// if password field is empty, then don't update
 			if ( $object->GetDBField('ElementType') == 'password' && trim($object->GetDBField('VariableValue')) == '' ) {
 				$object->SetFieldOption('VariableValue', 'skip_empty', 1);
 			}
 		}
 
 		/**
 		 * Occurs after updating item
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnAfterItemUpdate(kEvent $event)
 		{
 			static $skin_deleted = false;
 
 			parent::OnAfterItemUpdate($event);
 
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			if ( $object->GetDBField('ElementType') == 'password' && trim($object->GetDBField('VariableValue')) == '' ) {
 				$object->SetFieldOption('VariableValue', 'skip_empty', 0);
 			}
 
 			// allows to check if variable's value was changed now
 			$variable_name = $object->GetDBField('VariableName');
 			$changed = $this->Application->GetVar($event->getPrefixSpecial() . '_changed', Array ());
 
 			if ( $object->GetDBField('VariableValue') != $object->GetOriginalField('VariableValue') ) {
 				$changed[] = $variable_name;
 				$this->Application->SetVar($event->getPrefixSpecial() . '_changed', $changed);
 
 				// update value in cache, so other code (during this script run) would use new value
 				$this->Application->SetConfigValue($variable_name, $object->GetDBField('VariableValue'), true);
 			}
 
 			if ( $variable_name == 'Require_AdminSSL' || $variable_name == 'AdminSSL_URL' ) {
 				// when administrative console is moved to SSL mode, then delete skin
 				if ( in_array($variable_name, $changed) && !$skin_deleted ) {
 					$skin_helper = $this->Application->recallObject('SkinHelper');
 					/* @var $skin_helper SkinHelper */
 
 					$skin_file = $skin_helper->getSkinPath();
 					if ( file_exists($skin_file) ) {
 						unlink($skin_file);
 					}
 
 					$skin_deleted = true;
 				}
 			}
-
-			$this->Application->StoreVar('config_was_updated', 1);
 		}
 
 		/**
 		 * Updates kDBItem
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnUpdate(kEvent $event)
 		{
 			if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
 				$event->status = kEvent::erFAIL;
 				return;
 			}
 
 			$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
 
 			// 1. save user selected module root category
 			$new_category_id = getArrayValue($items_info, 'ModuleRootCategory', 'VariableValue');
 			if ( $new_category_id !== false ) {
 				unset($items_info['ModuleRootCategory']);
 			}
 
 			$object = $event->getObject( Array('skip_autoload' => true) );
 			/* @var $object kDBItem */
 
 			if ( $items_info ) {
 				$has_error = false;
 
 				foreach ($items_info as $id => $field_values) {
 					$object->Clear(); // clear validation errors from previous variable
 					$object->Load($id);
 					$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
 
 					if ( !$object->Update($id) ) {
 						// don't stop when error found !
 						$has_error = true;
 					}
 				}
 
 				$event->status = $has_error ? kEvent::erFAIL : kEvent::erSUCCESS;
 			}
 
 			if ( $event->status == kEvent::erSUCCESS ) {
+				$event->SetRedirectParam('action_completed', 1);
+
 				if ( $new_category_id !== false ) {
 					// root category was submitted
 					$module = $this->Application->GetVar('module');
 					$root_category_id = $this->Application->findModule('Name', $module, 'RootCat');
 
 					if ( $root_category_id != $new_category_id ) {
 						// root category differs from one in db
 						$fields_hash = Array ('RootCat' => $new_category_id);
 						$this->Conn->doUpdate($fields_hash, TABLE_PREFIX . 'Modules', 'Name = ' . $this->Conn->qstr($module));
 					}
 				}
 
 				// reset cache
 				$changed = $this->Application->GetVar($event->getPrefixSpecial() . '_changed', Array ());
 				$require_refresh = Array ('AdvancedUserManagement', 'Site_Name', 'AdminConsoleInterface', 'UsePopups');
 
 				$refresh_sections = array_intersect($require_refresh, $changed);
 				$require_full_refresh = Array ('Site_Name', 'AdminConsoleInterface');
 
 				if ( array_intersect($require_full_refresh, $changed) ) {
 					$event->SetRedirectParam('refresh_all', 1);
 				}
 				elseif ( $refresh_sections ) {
 					$event->SetRedirectParam('refresh_tree', 1);
 				}
 
 				if ( $refresh_sections ) {
 					// reset sections too, because of AdvancedUserManagement
 					$this->Application->DeleteSectionCache();
 				}
 
 				$this->Application->DeleteUnitCache($changed);
 			}
-			elseif ( $this->Application->GetVar('errors_' . $event->getPrefixSpecial()) ) {
-				// because we have list out there, and this is item
-				$this->Application->removeObject($event->getPrefixSpecial());
+			else{
+				$errors = $this->Application->GetVar('errors_' . $event->getPrefixSpecial());
+
+				if ( $errors ) {
+					// because we have list out there, and this is item
+					$this->Application->SetVar('first_error', key($errors));
+					$this->Application->removeObject($event->getPrefixSpecial());
+				}
 			}
 
 			// keeps module and section in REQUEST to ensure, that last admin template will work
 			$event->SetRedirectParam('module', $this->Application->GetVar('module'));
 			$event->SetRedirectParam('section', $this->Application->GetVar('section'));
 		}
 
 		/**
 		 * Process items from selector (selected_ids var, key - prefix, value - comma separated ids)
 		 *
 		 * @param kEvent $event
 		 */
 		function OnProcessSelected($event)
 		{
 			$selected_ids = $this->Application->GetVar('selected_ids');
 			$this->Application->StoreVar('ModuleRootCategory', $selected_ids['c']);
 
 			$event->SetRedirectParam('opener', 'u');
 		}
 
 		/**
 		 * Generates maintenance page
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnGenerateMaintenancePage(kEvent $event)
 		{
 			$event->setEventParam('compile_maintenance_template', 1);
 
 			$event->CallSubEvent('OnUpdate');
 		}
 
 		/**
 		 * Generates HTML version of hard maintenance template
 		 *
 		 * @param string $template
 		 * @return bool
 		 * @access protected
 		 */
 		protected function _generateMaintenancePage($template = null)
 		{
 			if ( !isset($template) ) {
 				$template = $this->Application->ConfigValue('HardMaintenanceTemplate');
 			}
 
 			$curl_helper = $this->Application->recallObject('CurlHelper');
 			/* @var $curl_helper kCurlHelper */
 
 			$html = $curl_helper->Send($this->Application->BaseURL() . '?t=' . $template);
 
 			if ( $curl_helper->isGoodResponseCode() ) {
 				file_put_contents(WRITEABLE . DIRECTORY_SEPARATOR . 'maintenance.html', $html);
 
 				return true;
 			}
 
 			return false;
 		}
 
 		/**
 		 * Returns auto-complete values for ajax-dropdown
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnSuggestValues(kEvent $event)
 		{
 			if ( !$this->Application->isAdminUser ) {
 				// very careful here, because this event allows to
 				// view every object field -> limit only to logged-in admins
 				return;
 			}
 
 			$event->status = kEvent::erSTOP;
 
 			$field = $this->Application->GetVar('field');
 			$cur_value = $this->Application->GetVar('cur_value');
 
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			if ( !$field || !$cur_value || !$object->isField($field) ) {
 				return;
 			}
 
 			$limit = $this->Application->GetVar('limit');
 			if ( !$limit ) {
 				$limit = 20;
 			}
 
 			$sql = 'SELECT DISTINCT ' . $field . ', ModuleOwner
 					FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
 					WHERE ' . $field . ' LIKE ' . $this->Conn->qstr('%' . $cur_value . '%') . '
 					ORDER BY ' . $field . ' ASC';
 			$raw_suggestions = $this->Conn->Query($sql);
 
 			$suggestions = Array ();
 			$this->Application->XMLHeader();
 
 			foreach ($raw_suggestions as $raw_suggestion) {
 				$suggestion = $raw_suggestion[$field];
 
 				if ( !isset($suggestions[$suggestion]) ) {
 					$suggestions[$suggestion] = Array ();
 				}
 
 				$suggestions[$suggestion][] = $raw_suggestion['ModuleOwner'];
 			}
 
 			array_splice($suggestions, $limit);
 
 			echo '<suggestions>';
 			$of_label = $this->Application->Phrase('la_From', false);
 
 			foreach ($suggestions as $suggestion_value => $suggestion_modules) {
 				$suggestion_module = in_array('In-Portal', $suggestion_modules) ? 'In-Portal' : implode(', ', $suggestion_modules);
 				$suggestion_title = $suggestion_value . ' <em style="color: grey;">' . $of_label . ' ' . $suggestion_module . '</em>';
 
 				echo '<item value="' . htmlspecialchars($suggestion_value) . '">' . htmlspecialchars($suggestion_title) . '</item>';
 			}
 
 			echo '</suggestions>';
 		}
 
 		/**
 		 * Prefills module dropdown
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnAfterConfigRead(kEvent $event)
 		{
 			parent::OnAfterConfigRead($event);
 
 			$options = Array ();
 
 			foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
 				if ( $module_name == 'Core' ) {
 					continue;
 				}
 
 				$options[$module_name] = $module_name;
 
 				if ( $module_name == 'In-Portal' ) {
 					$options['In-Portal:Users'] = 'In-Portal:Users';
 				}
 			}
 
 			$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
 			$fields['ModuleOwner']['options'] = $options;
 			$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
 		}
 	}
\ No newline at end of file
Index: branches/5.2.x/core/admin_templates/incs/config_blocks.tpl
===================================================================
--- branches/5.2.x/core/admin_templates/incs/config_blocks.tpl	(revision 15524)
+++ branches/5.2.x/core/admin_templates/incs/config_blocks.tpl	(revision 15525)
@@ -1,132 +1,131 @@
 <inp2:m_DefineElement name="config_edit_text">
 	<input type="text" tabindex="<inp2:m_get param='tab_index'/>" name="<inp2:InputName field='$field'/>" id="<inp2:InputName field='$field'/>" value="<inp2:Field field='$field' />"<inp2:m_if check="m_Param" name="field_params"> <inp2:m_Param name="field_params"/><inp2:m_else/> style="width:100%"</inp2:m_if>/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_edit_password">
 	<input type="password" autocomplete="off" tabindex="<inp2:m_get param='tab_index'/>" primarytype="password" name="<inp2:InputName field='$field'/>" id="<inp2:InputName field='$field'/>" value="" />
 	<inp2:m_Inc param="tab_index" by="1"/>
 	<input type="password" autocomplete="off" tabindex="<inp2:m_get param='tab_index'/>" name="verify_<inp2:InputName field='$field'/>" id="verify_<inp2:InputName field='$field'/>" value="" />
 	&nbsp;<span class="error" id="error_<inp2:InputName field="$field"/>"></span>
 
 	<script type="text/javascript">
 		$(document).ready(
 			function() {
 				// fixes Firefox 2.0+ bug will password autocomplete
 				document.getElementById('<inp2:InputName field="$field"/>').value = '';
 				document.getElementById('verify_<inp2:InputName field="$field"/>').value = '';
 			}
 		);
 	</script>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_edit_option">
 		<option value="<inp2:m_param name='key'/>"<inp2:m_param name="selected"/>><inp2:m_param name="option"/></option>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_edit_select">
 	<select name="<inp2:InputName field='$field'/>" id="<inp2:InputName field='$field'/>" tabindex="<inp2:m_get param='tab_index'/>">
 		<inp2:PredefinedOptions field="$field" block="config_edit_option" selected="selected"/>
 	</select>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_edit_multiselect">
 	<select id="<inp2:InputName field='$field'/>_select" onchange="update_multiple_options('<inp2:InputName field='$field'/>');" tabindex="<inp2:m_get param='tab_index'/>" multiple>
 		<inp2:PredefinedOptions field="$field" block="config_edit_option" selected="selected"/>
 	</select>
 	<input type="hidden" id="<inp2:InputName field='$field'/>" name="<inp2:InputName field='$field'/>" value="<inp2:Field field='$field'/>"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_edit_checkbox" field_class="">
 	<input type="hidden" id="<inp2:InputName field='$field'/>" name="<inp2:InputName field='$field'/>" value="<inp2:Field field='$field' db='db'/>">
 	<input tabindex="<inp2:m_get param='tab_index'/>" type="checkbox" id="_cb_<inp2:InputName field='$field'/>" name="_cb_<inp2:InputName field='$field'/>" <inp2:Field field="$field" checked="checked" db="db"/> class="<inp2:m_param name="field_class"/>" onclick="update_checkbox(this, document.getElementById('<inp2:InputName field="$field"/>'))">
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_edit_textarea">
 	<textarea tabindex="<inp2:m_get param='tab_index'/>" name="<inp2:InputName field='$field'/>" id="<inp2:InputName field='$field'/>" <inp2:m_param name="field_params" />><inp2:Field field="$field" /></textarea>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_radio_item">
 	<input type="radio" <inp2:m_param name="checked"/> name="<inp2:InputName field="$field"/>" id="<inp2:InputName field="$field"/>_<inp2:m_param name="key"/>" value="<inp2:m_param name="key"/>"><label for="<inp2:InputName field="$field"/>_<inp2:m_param name="key"/>"><inp2:m_param name="option"/></label>&nbsp;
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_edit_radio">
 		<inp2:PredefinedOptions field="$field" block="config_radio_item" selected="checked"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="cf_default_value">
 	<inp2:ConfigFormElement PrefixSpecial="$PrefixSpecial" field="VariableValue" blocks_prefix="config_edit_" element_type_field="ElementType" value_list_field="ValueList"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="cf_default_caption">
 	<td style="width: 500px;">
 		<inp2:Field name="VariableName" result_to_var="error_field"/>
 		<span class="<inp2:m_if check='HasError' field='$error_field' id_field='VariableName'>error-cell</inp2:m_if>">
 		<inp2:Field field="Prompt" as_label="1" /></span><inp2:m_if check="IsRequired" field="VariableValue"><span class="field-required">&nbsp;*</span></inp2:m_if>:<inp2:m_if check="Field" name="HintLabel"><span>&nbsp;<img src="<inp2:m_TemplatesBase/>/img/hint_icon.png" width="12" height="13" title="<inp2:Field name='HintLabel' as_label='1' html_escape='1'/>" alt="<inp2:Field name='HintLabel' as_label='1' html_escape='1'/>"/></inp2:m_if>
 
 		<inp2:m_if check="m_IsDebugMode">
 			<br/><small style="color: gray;">[<inp2:Field field="DisplayOrder"/>] <inp2:Field field="VariableName"/> [<a href="<inp2:ItemEditLink template='config/config_edit'/>" onclick="return direct_edit('<inp2:m_param name="PrefixSpecial"/>', this.href);"><inp2:m_Phrase name="la_btn_Edit"/></a>]</small>
 		</inp2:m_if>
 	</td>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_block">
 	<inp2:m_inc param="tab_index" by="1"/>
 	<inp2:m_if check="m_ParamEquals" name="show_heading" value="1">
 		<tr class="subsectiontitle">
 			<td colspan="2">
 				<inp2:Field name="Heading" as_label="1"/>
 	   		</td>
 	   		<td align="right">
 	   			<a class="config-header" href="javascript:toggle_section('<inp2:Field name="Heading"/>');" id="toggle_mark[<inp2:Field name="Heading"/>]" title="Collapse/Expand Section">[-]</a>
 	   		</td>
 		</tr>
 	</inp2:m_if>
 
 	<tr class="<inp2:m_odd_even odd='table-color1' even='table-color2'/>" id="<inp2:m_param name="PrefixSpecial"/>_<inp2:field field="$IdField"/>" header_label="<inp2:Field name="Heading"/>">
 		<inp2:m_RenderElement name="cf_default_caption" pass_params="1"/>
 
 		<td>
 			<inp2:m_RenderElement name="$value_render_as" pass_params="1"/>
 		</td>
 
-		<td class="error"><inp2:Error id_field="VariableName"/>&nbsp;</td>
+		<td class="field-<inp2:Field name='VariableName'/> error"><inp2:Error id_field="VariableName"/>&nbsp;</td>
 	</tr>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_block1">
 	<inp2:m_inc param="tab_index" by="1"/>
 	<inp2:m_if check="m_ParamEquals" name="show_heading" value="1">
 		<tr class="subsectiontitle">
 			<td colspan="2">
 	    		<inp2:Field name="Heading" as_label="1"/>
 	   		</td>
 	   		<td align="right">
 	   			<a class="config-header" href="javascript:toggle_section('<inp2:Field name="Heading"/>');" id="toggle_mark[<inp2:Field name="Heading"/>]" title="Collapse/Expand Section">[-]</a>
 	   		</td>
 		</tr>
 	</inp2:m_if>
 
 	<tr class="<inp2:m_odd_even odd='table-color1' even='table-color2'/>" id="<inp2:m_param name="PrefixSpecial"/>_<inp2:Field field="$IdField"/>" header_label="<inp2:Field name="Heading"/>">
 		<inp2:m_RenderElement name="cf_default_caption" pass_params="1"/>
 
 		<td>
 			<nobr><inp2:m_RenderElement name="$value_render_as" pass_params="1"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_block2">
 			<inp2:m_RenderElement name="$value_render_as" pass_params="1"/></nobr>
 		</td>
-		<td class="error"><inp2:Error id_field="VariableName"/>&nbsp;</td>
+		<td class="field-<inp2:Field name='VariableName'/> error"><inp2:Error id_field="VariableName"/>&nbsp;</td>
 	</tr>
 </inp2:m_DefineElement>
 
 <inp2:m_ModuleInclude template="config/custom_variables"/>
 
 <inp2:m_DefineElement name="config_updated_notice">
-	<inp2:m_if check="m_Recall" var="config_was_updated">
+	<inp2:m_if check="m_Get" var="action_completed">
 		<inp2:m_RenderElement design="form_message" type="notice">
 			<inp2:m_Phrase name="la_msg_YourChangesWereSuccessfullySaved"/><br/>
 		</inp2:m_RenderElement>
-		<inp2:m_RemoveVar name="config_was_updated" />
 	</inp2:m_if>
 </inp2:m_DefineElement>
Index: branches/5.2.x/core/admin_templates/config/config_general.tpl
===================================================================
--- branches/5.2.x/core/admin_templates/config/config_general.tpl	(revision 15524)
+++ branches/5.2.x/core/admin_templates/config/config_general.tpl	(revision 15525)
@@ -1,170 +1,180 @@
 <inp2:m_include t="incs/header"/>
 
 <inp2:m_Get name="section" result_to_var="section"/>
 <inp2:m_RenderElement name="combined_header" prefix="conf" section="$section" perm_event="conf:OnLoad" title_preset="config_list_general"/>
 
 <!-- ToolBar -->
 <table class="toolbar" height="30" cellspacing="0" cellpadding="0" width="100%" border="0">
 	<tbody>
 		<tr>
   			<td>
   				<script type="text/javascript">
 					function validate_password_fields() {
 						var $validated = true;
 
 						$("input[primarytype='password']", '#' + $form_name).each(
 							function ($e) {
 								if ( !validate_password_field(this.id) ) {
 									$validated = false;
 								}
 							}
 						);
 
 						return $validated;
 					}
 
 					function validate_password_field($field_id) {
 						var password_field = document.getElementById($field_id),
 							password_verify_field = document.getElementById('verify_' + $field_id);
 
 						if ( password_field && password_verify_field && password_field.value == password_verify_field.value ) {
 							return true;
 						}
 						else {
 							var password_error_cell = document.getElementById('error_' + $field_id);
 
 							if ( password_error_cell ) {
 								$(window).scrollTop($(password_field).position().top - 15);
 								password_error_cell.innerHTML = '<inp2:m_Phrase name="la_error_PasswordMatch"/>';
 							}
 
 							return false;
 						}
 					}
 
 					function toggle_section($label) {
 						var $table = document.getElementById('config_table');
 						var $row = null;
 						var $is_visible = false;
 
 						for (var $i = 0; $i < $table.rows.length; $i++) {
 							$row = $table.rows[$i];
 							if ( $row.getAttribute('header_label') != $label ) {
 								continue;
 							}
 
 							if ( !$row.style.display ) {
 								$row.style.display = document.all ? 'block' : 'table-row';
 							}
 
 							$is_visible = !($row.style.display == 'none');
 							$row.style.display = $is_visible ? 'none' : (document.all ? 'block' : 'table-row');
 
 							document.getElementById('toggle_mark[' + $label + ']').innerHTML = '[' + ($is_visible ? '+' : '-') + ']';
 						}
 					}
 
   					var a_toolbar = new ToolBar();
 
 					a_toolbar.AddButton(
 						new ToolBarButton(
 							'select',
 							'<inp2:m_phrase label="la_ToolTip_Save" escape="1"/>',
 							function() {
 								submit_event('conf','<inp2:conf_SaveEvent/>');
 							}
 						)
 					);
 
 					a_toolbar.AddButton(
 						new ToolBarButton(
 							'cancel',
 							'<inp2:m_phrase label="la_ToolTip_Cancel" escape="1"/>',
 							function() {
 								submit_event('conf','OnCancel');
 							}
 					 	)
 					);
 
 					<inp2:m_if check="m_IsDebugMode">
 						a_toolbar.AddButton( new ToolBarSeparator('sep1') );
 
 						a_toolbar.AddButton(
 							new ToolBarButton(
 								'new_item',
 								'<inp2:m_phrase label="la_ToolTip_NewSystemSetting" escape="1"/>::<inp2:m_phrase label="la_ToolTip_Add" escape="1"/>',
 								function() {
 									std_precreate_item('conf', 'config/config_edit');
 								}
 							)
 						);
 					</inp2:m_if>
 
 					<inp2:m_ModuleInclude template = "config/custom_toolbar"/>
 
 					a_toolbar.Render();
 				</script>
 			</td>
 		</tr>
 	</tbody>
 </table>
 
 <inp2:m_include t="incs/config_blocks"/>
 
 <inp2:m_RenderElement name="config_updated_notice"/>
 <inp2:conf_SaveWarning name="grid_save_warning"/>
 
 <table width="100%" border="0" cellspacing="0" cellpadding="4" class="bordered" id="config_table">
 	<!-- module root category selector: begin -->
 	<tr class="subsectiontitle">
 		<td colspan="2">
 	    		<inp2:m_phrase name="la_Text_RootCategory" />
 	   		</td>
    		<td align="right">
    			<a class="config-header" href="javascript:toggle_section('la_Text_RootCategory');" id="toggle_mark[la_Text_RootCategory]" title="Collapse/Expand Section">[-]</a>
    		</td>
 	</tr>
 
 	<tr class="<inp2:m_odd_even odd="table-color1" even="table-color2"/>" header_label="la_Text_RootCategory">
 		<td>
 			<span class="text"><inp2:m_phrase name="la_prompt_RootCategory" /></span>
 		</td>
 		<td>
 			<inp2:m_DefineElement name="category_caption">
 				<inp2:m_ifnot check="m_Param" name="is_first">
 					<inp2:m_param name="separator"/>
 				</inp2:m_ifnot>
 				<inp2:m_param name="cat_name"/>
 			</inp2:m_DefineElement>
 
 			<b><inp2:conf_CategoryPath separator=" &gt; " render_as="category_caption" /></b>
 			<input type="hidden" name="conf[ModuleRootCategory][VariableValue]" value="<inp2:conf_ModuleRootCategory/>"/>
 			<a href="<inp2:adm_SelectorLink prefix='conf' selection_mode='single' tab_prefixes='none'/>" onclick="openSelector('conf', this.href, 'ModuleRootCategory', '950x600'); return false;"><img src="img/icons/icon24_cat.gif" border="0" align="absmiddle" /></a>
 		</td>
 		<td class="error">&nbsp;</td>
 	</tr>
 	<!-- module root category selector: end -->
 
 	<inp2:conf_PrintList block="config_block" per_page="-1" full_block="config_block" half_block1="config_block1" half_block2="config_block2" value_render_as="cf_default_value"/>
 </table>
 
 <script type="text/javascript">
 	<inp2:m_if check="m_Get" name="refresh_tree">
 		getFrame('menu').location.reload();
 	</inp2:m_if>
 
 	<inp2:m_if check="m_Get" name="refresh_all">
 		var $menu_frame = getFrame('menu');
 
 		$menu_frame.parent.location.href = $menu_frame.parent.location.href;
 	</inp2:m_if>
 
 	Application.setHook(
 		'conf:*',
 		function ($event) {
 			$event.status = $event.Name == 'OnCancel' ? true : validate_password_fields();
 		}
 	);
+
+	<inp2:m_if check="m_Get" name="first_error">
+		$(document).ready(function () {
+			var $error_cell = $('.field-<inp2:m_Get name="first_error"/>.error');
+
+			if ( $error_cell.length ) {
+				$(window).scrollTop($error_cell.position().top - 15);
+			}
+		});
+	</inp2:m_if>
 </script>
 
 <inp2:m_include t="incs/footer"/>
\ No newline at end of file
Index: branches/5.2.x/core/admin_templates/config/config_universal.tpl
===================================================================
--- branches/5.2.x/core/admin_templates/config/config_universal.tpl	(revision 15524)
+++ branches/5.2.x/core/admin_templates/config/config_universal.tpl	(revision 15525)
@@ -1,141 +1,151 @@
 <inp2:m_include t="incs/header"/>
 
 <inp2:conf_InitList name="Default" per_page="-1"/>
 <inp2:m_Get name="section" result_to_var="section"/>
 <inp2:m_RenderElement name="combined_header" prefix="conf" section="$section" title_preset="section_label" perm_event="conf:OnLoad"/>
 
 <!-- ToolBar -->
 <table class="toolbar" height="30" cellspacing="0" cellpadding="0" width="100%" border="0">
 	<tbody>
 		<tr>
 			<td>
 				<script type="text/javascript">
 					function validate_password_fields() {
 						var $validated = true;
 
 						$("input[primarytype='password']", '#' + $form_name).each(
 							function ($e) {
 								if ( !validate_password_field(this.id) ) {
 									$validated = false;
 								}
 							}
 						);
 
 						return $validated;
 					}
 
 					function validate_password_field($field_id) {
 						var password_field = document.getElementById($field_id),
 							password_verify_field = document.getElementById('verify_' + $field_id);
 
 						if ( password_field && password_verify_field && password_field.value == password_verify_field.value ) {
 							return true;
 						}
 						else {
 							var password_error_cell = document.getElementById('error_' + $field_id);
 
 							if ( password_error_cell ) {
 								$(window).scrollTop($(password_field).position().top - 15);
 								password_error_cell.innerHTML = '<inp2:m_Phrase name="la_error_PasswordMatch"/>';
 							}
 
 							return false;
 						}
 					}
 
 					function toggle_section($label) {
 						var $row = null,
 							$is_visible = false,
 							$table = document.getElementById('config_table');
 
 						for (var $i = 0; $i < $table.rows.length; $i++) {
 							$row = $table.rows[$i];
 							if ( $row.getAttribute('header_label') != $label ) {
 								continue;
 							}
 
 							if ( !$row.style.display ) {
 								$row.style.display = document.all ? 'block' : 'table-row';
 							}
 
 							$is_visible = !($row.style.display == 'none');
 							$row.style.display = $is_visible ? 'none' : (document.all ? 'block' : 'table-row');
 
 							document.getElementById('toggle_mark[' + $label + ']').innerHTML = '[' + ($is_visible ? '+' : '-') + ']';
 						}
 					}
 
 					var a_toolbar = new ToolBar();
 
 					a_toolbar.AddButton(
 						new ToolBarButton(
 							'select',
 							'<inp2:m_phrase label="la_ToolTip_Save" escape="1"/>',
 							function () {
 								submit_event('conf', '<inp2:conf_SaveEvent/>');
 							}
 						)
 					);
 
 					a_toolbar.AddButton(
 						new ToolBarButton(
 							'cancel',
 							'<inp2:m_phrase label="la_ToolTip_Cancel" escape="1"/>',
 							function () {
 								submit_event('conf', 'OnCancel');
 							}
 						)
 					);
 
 					<inp2:m_if check="m_IsDebugMode">
 						a_toolbar.AddButton( new ToolBarSeparator('sep1') );
 
 						a_toolbar.AddButton(
 							new ToolBarButton(
 								'new_item',
 								'<inp2:m_phrase label="la_ToolTip_NewSystemSetting" escape="1"/>::<inp2:m_phrase label="la_ToolTip_Add" escape="1"/>',
 								function() {
 									std_precreate_item('conf', 'config/config_edit');
 								}
 							)
 						);
 					</inp2:m_if>
 
 					<inp2:m_ModuleInclude template = "config/custom_toolbar"/>
 
 					a_toolbar.Render();
 				</script>
 			</td>
 		</tr>
 	</tbody>
 </table>
 
 <inp2:m_include t="incs/config_blocks"/>
 
 <inp2:m_RenderElement name="config_updated_notice"/>
 <inp2:conf_SaveWarning name="grid_save_warning"/>
 
 <table width="100%" border="0" cellspacing="0" cellpadding="4" class="bordered" id="config_table">
 	<inp2:conf_PrintList list_name="default" block="config_block" full_block="config_block" half_block1="config_block1" half_block2="config_block2" value_render_as="cf_default_value"/>
 </table>
 
 <script type="text/javascript">
 	<inp2:m_if check="m_Get" name="refresh_tree">
 		getFrame('menu').location.reload();
 	</inp2:m_if>
 
 	<inp2:m_if check="m_Get" name="refresh_all">
 		var $menu_frame = getFrame('menu');
 
 		$menu_frame.parent.location.href = $menu_frame.parent.location.href;
 	</inp2:m_if>
 
 	Application.setHook(
 		'conf:*',
 		function ($event) {
 			$event.status = $event.Name == 'OnCancel' ? true : validate_password_fields();
 		}
 	);
+
+	<inp2:m_if check="m_Get" name="first_error">
+		$(document).ready(function () {
+			var $error_cell = $('.field-<inp2:m_Get name="first_error"/>.error');
+
+			if ( $error_cell.length ) {
+				$(window).scrollTop($error_cell.position().top - 15);
+			}
+		});
+	</inp2:m_if>
 </script>
 
 <inp2:m_include t="incs/footer"/>
\ No newline at end of file