Index: branches/5.2.x/core/units/configuration/configuration_event_handler.php
===================================================================
--- branches/5.2.x/core/units/configuration/configuration_event_handler.php	(revision 15459)
+++ branches/5.2.x/core/units/configuration/configuration_event_handler.php	(revision 15460)
@@ -1,378 +1,393 @@
 <?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 <> ""');
 		}
 
 		/**
-		 * Performs validation of configuration variable value
+		 * Sets custom validation
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
-		protected function OnBeforeItemUpdate(kEvent $event)
+		protected function OnAfterItemLoad(kEvent $event)
 		{
 			static $default_field_options = null;
 
-			parent::OnBeforeItemUpdate($event);
+			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 validation of configuration variable value
+		 *
+		 * @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' ) {
 				if ( trim($object->GetDBField('VariableValue')) == '' ) {
 					$field_options = $object->GetFieldOptions('VariableValue');
 					$field_options['skip_empty'] = 1;
 					$object->SetFieldOptions('VariableValue', $field_options);
 				}
 				else {
 					$password_formatter = $this->Application->recallObject('kPasswordFormatter');
 					/* @var $password_formatter kPasswordFormatter */
 
 					$object->SetDBField('VariableValue', $password_formatter->EncryptPassword($object->GetDBField('VariableValue'), 'b38'));
 				}
 			}
 
 			$field_name = $object->GetDBField('VariableName');
 			$field_values = $this->Application->GetVar($event->getPrefixSpecial(true));
 			$state_country_hash = Array ('Comm_State' => 'Comm_Country', 'Comm_Shipping_State' => 'Comm_Shipping_Country');
 
 			if ( array_key_exists($field_name, $state_country_hash) ) {
 				// if this is state field
 				$sql = 'SELECT VariableId
 						FROM ' . $this->Application->getUnitOption('conf', 'TableName') . '
 						WHERE VariableName = "' . $state_country_hash[$field_name] . '"';
 				$country_variable_id = $this->Conn->GetOne($sql);
 
 				$check_state = $object->GetDBField('VariableValue');
 				$check_country = $field_values[$country_variable_id]['VariableValue'];
 
 				if ( !$check_country || !$check_state ) {
 					return;
 				}
 
 				$cs_helper = $this->Application->recallObject('CountryStatesHelper');
 				/* @var $cs_helper kCountryStatesHelper */
 
 				$state_iso = $cs_helper->getStateIso($check_state, $check_country);
 
 				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');
 				}
 			}
 
 			$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']);
 			}
 		}
 
 		/**
 		 * 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' ) {
 				if ( trim($object->GetDBField('VariableValue')) == '' ) {
 					$field_options = $object->GetFieldOptions('VariableValue');
 					unset($field_options['skip_empty']);
 					$object->SetFieldOptions('VariableValue', $field_options);
 				}
 			}
 
 			// 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 ) {
 				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());
 			}
 
 			// 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;
 		}
 	}
\ No newline at end of file