<?php

require_once('library/Atmail/Update/Versions.php');

class Atmail_Update_Db extends Atmail_Update_Abstract
{
	public $updateAttemptFrom;


    function _7_1_1_13425()
    {
        $this->changeConfig('password', 'min_length', '7', 'Integer', '', false);
        $this->changeConfig('password', 'max_length', '64', 'Integer', '', false);
        $this->changeConfig('password', 'min_lowercase_chars', '0', 'Integer', '', false);
        $this->changeConfig('password', 'max_lowercase_chars', '64', 'Integer', '', false);
        $this->changeConfig('password', 'min_uppercase_chars', '0', 'Integer', '', false);
        $this->changeConfig('password', 'max_uppercase_chars', '64', 'Integer', '', false);
        $this->changeConfig('password', 'disallow_numeric_chars', 'False', 'Boolean', '', false);
        $this->changeConfig('password', 'disallow_numeric_first', 'False', 'Boolean', '', false);
        $this->changeConfig('password', 'disallow_numeric_last', 'False', 'Boolean', '', false);
        $this->changeConfig('password', 'min_numeric_chars', '0', 'Integer', '', false);
        $this->changeConfig('password', 'max_numeric_chars', '64', 'Integer', '', false);
        $this->changeConfig('password', 'disallow_nonalphanumeric_chars', 'False', 'Boolean', '', false);
        $this->changeConfig('password', 'disallow_nonalphanumeric_first', 'False', 'Boolean', '', false);
        $this->changeConfig('password', 'disallow_nonalphanumeric_last', 'False', 'Boolean', '', false);
        $this->changeConfig('password', 'min_nonalphanumeric_chars', '0', 'Integer', '', false);
        $this->changeConfig('password', 'max_nonalphanumeric_chars', '64', 'Integer', '', false);
        $this->changeConfig('password', 'three_type_chars', 'False', 'Boolean', '', false);
        $this->changeConfig('password', 'use_password_policy', 'False', 'Boolean', '', false);
    }

    function _7_1_1()
    {
        $this->exceptionQuery("CREATE TABLE `Log_Device` (
  `LogDate` datetime default NULL,
  `LogIP` datetime default NULL,
  `DeviceID` varchar(128) default NULL,
  `DeviceType` varchar(128) default NULL,
  `Account` varchar(128) default NULL,
  `id` bigint(12) unsigned NOT NULL auto_increment,
  PRIMARY KEY  (`id`),
  KEY `iAccount` (`Account`),
  KEY `iDeviceID` (`DeviceID`),
  KEY `iDeviceType` (`DeviceType`),
  KEY `LogDate` (`LogDate`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;");
        // issue with timezone cache, clear it.
        @unlink("library/Atmail/zoneinfo/tz.cache");

		$this->insertConfig('global', 'resolveLogIPsToGeoLocationViaAtmailGeoLocationServer', '1', 'Boolean');
		$this->ignorableQuery("ALTER TABLE `AdminUsers` ADD `cssColorTheme` VARCHAR(32) character set utf8 NOT NULL default 'blue'");
        $this->ignorableQuery("update Users inner join Domains on Account like CONCAT('%@', Domains.Hostname) set UserStatus = 1 where Domains.Enable = 0");
        $this->ignorableQuery("update Users inner join Domains on Account like CONCAT('%@', Domains.Hostname) set UserStatus = 0 where Domains.Enable != 0");

		$this->exceptionQuery("CREATE TABLE `ImageBranding` (
	`Account` varchar(128) NOT NULL DEFAULT '',
  `Type` varchar(8) DEFAULT NULL,
  `ImageData` longtext,
  `ImageHeight` smallint(6) unsigned NOT NULL,
  `ImageWidth` smallint(6) unsigned NOT NULL,
  `ImageType` varchar(4) DEFAULT NULL,
  `DateAdded` datetime DEFAULT NULL,
  `DateModified` datetime DEFAULT NULL,
  `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`),
  KEY `Account` (`Account`)
);");


    }

    function _7_1_0()
    {
        $this->insertConfig('password', 'min_length', '7', 'Integer');
        $this->insertConfig('password', 'max_length', '64', 'Integer');
        $this->insertConfig('password', 'min_lowercase_chars', '0', 'Integer');
        $this->insertConfig('password', 'max_lowercase_chars', '64', 'Integer');
        $this->insertConfig('password', 'min_uppercase_chars', '0', 'Integer');
        $this->insertConfig('password', 'max_uppercase_chars', '64', 'Integer');
        $this->insertConfig('password', 'disallow_numeric_chars', 'False', 'Boolean');
        $this->insertConfig('password', 'disallow_numeric_first', 'False', 'Boolean');
        $this->insertConfig('password', 'disallow_numeric_last', 'False', 'Boolean');
        $this->insertConfig('password', 'min_numeric_chars', '0', 'Integer');
        $this->insertConfig('password', 'max_numeric_chars', '64', 'Integer');
        $this->insertConfig('password', 'disallow_nonalphanumeric_chars', 'False', 'Boolean');
        $this->insertConfig('password', 'disallow_nonalphanumeric_first', 'False', 'Boolean');
        $this->insertConfig('password', 'disallow_nonalphanumeric_last', 'False', 'Boolean');
        $this->insertConfig('password', 'min_nonalphanumeric_chars', '0', 'Integer');
        $this->insertConfig('password', 'max_nonalphanumeric_chars', '64', 'Integer');
        $this->insertConfig('password', 'three_type_chars', 'False', 'Boolean');
        $this->insertConfig('password', 'use_password_policy', 'False', 'Boolean');
    }

	function _7_0_3()
	{
		$this->ignorableQuery("ALTER TABLE `Abook` ADD `SIP` VARCHAR(128) NULL DEFAULT NULL");
		$this->ignorableQuery("CREATE TABLE `ServiceAccounts` (
			  `Account` varchar(128) DEFAULT NULL,
			  `Type` varchar(64) NOT NULL,
			  `Provider` varchar(64) NOT NULL,
			  `PhoneNumber` varchar(32) NOT NULL,
			  `DateAdded` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
			  `SIP` tinyint(4) NOT NULL DEFAULT '0',
			  `SMS` tinyint(1) NOT NULL DEFAULT '0',
			  `Voicemail` tinyint(1) NOT NULL DEFAULT '0',
			  `id` mediumint(12) NOT NULL AUTO_INCREMENT,
			  `UserId` varchar(128) DEFAULT NULL,
			  `Domain` varchar(255) DEFAULT NULL,
			  `AuthorizationName` varchar(128) NOT NULL,
			  `Password` varchar(128) NOT NULL,
			  `DisplayName` varchar(128) DEFAULT NULL,
			  `Data` text NOT NULL COMMENT 'serialized account data specific to service',
			  `SIPServer` varchar(255) DEFAULT NULL,
			  PRIMARY KEY (`id`),
			  KEY `iAccount` (`Account`)
			) ENGINE=InnoDB ENGINE=InnoDB;"
		);
	}
	
	function _7_0_2()
	{
		$this->insertConfig('global', 'enableSpamReporting', '0', 'Integer');
		$this->insertConfig('global', 'reportSpamAddress', '', 'String');
		$this->insertConfig('global', 'reportNotSpamAddress', '', 'String');
		$this->insertConfig('global', 'reportSpamSmtpServer', '', 'String');
		
		$this->insertConfig('defaultUserSettings', 'enableExtraAddressFields', '0', 'Integer');
		$this->ignorableQuery("ALTER TABLE `UserSettings` ADD `enableExtraAddressFields` smallint(1)  default '0'");
		
		$this->insertConfig('global', 'spamassassinVersion', '', 'String');
		$this->insertConfig('global', 'spamassassinDbVersion', '', 'String');
		$this->insertConfig('global', 'spamassassinDbDate', '', 'String');
	}
	
    function _7_0_1()
    {
        $this->updateConfig('global', 'iosProfiles', '1', 'Integer');
    }

	function _7_0_0()
	{
		$this->ignorableQuery("UPDATE Config set keyValue = 'Original' where keyName = 'mobileCssStyle'");
		$this->ignorableQuery("UPDATE Config set keyValue = 'original' where keyName = 'cssStyle'");
		$this->ignorableQuery("ALTER TABLE `Groups` ADD `licenseType` TINYINT(1) NOT NULL DEFAULT 0");
		$this->ignorableQuery("ALTER TABLE `Users` ADD `LicenseID` int NOT NULL default 0");
		$this->ignorableQuery("ALTER TABLE `calendarObjects` CHANGE COLUMN `uri` `uri` VARCHAR(255) NULL DEFAULT NULL");
		$this->ignorableQuery("ALTER TABLE `UserSettings` ADD `cssColorTheme` VARCHAR(32) NOT NULL DEFAULT 'blue'");		
		$this->ignorableQuery("UPDATE Config SET keyValue = 'fresh' WHERE keyName = 'cssStyleTheme'");
		$this->ignorableQuery("UPDATE UserSettings SET cssStyleTheme = 'fresh'");
		$this->ignorableQuery("UPDATE Config SET keyValue = '0' WHERE keyName = 'iosProfiles'");
		$this->ignorableQuery("UPDATE Config SET keyValue = '' WHERE keyName = 'serialKey'");
		$this->insertConfig('global', 'licenseType', '0', 'String');
	}

	function _6_6_2()
	{
		
		$this->ignorableQuery("ALTER TABLE `calendarObjects` CHANGE COLUMN `uri` `uri` VARCHAR(255) NULL DEFAULT NULL");
		
	}

	function _6_6_1()
	{
		
		$this->insertConfig('global', 'exclusive_sessions', '1', 'Boolean');
		$this->insertConfig('global', 'adminlink', '1', 'Boolean');
		
	}

	function _6_6_0()
	{
	}

	/*	 * *********************************************  6.5.1 ****************************************************** */
	function _6_5_1()
	{
		$this->exceptionQuery("ALTER TABLE `calendarObjects` ADD `start` INT UNSIGNED NOT NULL DEFAULT 4294967295");
		$this->exceptionQuery("ALTER TABLE `calendarObjects` ADD `end` INT UNSIGNED NOT NULL DEFAULT 0");
		$this->exceptionQuery("ALTER TABLE `calendarObjects` ADD `rrule` SMALLINT");

		$this->insertConfig('exim', 'filter_awl_purge_threshold', '5000', 'Integer');
		$this->ignorableQuery("delete from Config where keyName in ('filter_awl_purge_low','filter_awl_purge_medium','filter_awl_purge_high')");

	}
	/*	 * ********************************************* PLACE HOLDER 6.5.0 ****************************************************** */

	/*	 * ********************************************* 6.4.3.10521 ****************************************************** */
	function _6_4_3_10521()
	{
		// mobile ui
		$this->insertConfig('global', 'mobileui', '1', 'Integer');
		$this->insertConfig('global', 'mobileCssTheme', 'Original', 'String');
	}

	/*	 * ********************************************* 6.4.3.10428 ****************************************************** */
	function _6_4_3_10443()
	{
		
		$this->ignorableQuery("CREATE TABLE FileComments ( Account varchar(128) default NULL, FileID varchar(64) NOT NULL, Comment varchar(255) character set utf8 NOT NULL, DateAdded timestamp NOT NULL default CURRENT_TIMESTAMP, id mediumint(12) NOT NULL auto_increment, PRIMARY KEY  (id), KEY iAccount (Account) ) ENGINE=InnoDB;");
		$this->ignorableQuery("CREATE TABLE SharedFiles ( Account varchar(128) default NULL, FileName varchar(128) default NULL, FilePath varchar(255) default NULL, FileMD5 varchar(255) default NULL, Creation datetime default NULL, Expiry datetime default NULL, id mediumint(12) NOT NULL auto_increment, PRIMARY KEY  (id), KEY iAccount (Account),  KEY FileMD5 (FileMD5) ) ENGINE=InnoDB;");
		$this->ignorableQuery("ALTER TABLE `Groups` ADD `WebDavEnabled` TINYINT(1) NOT NULL DEFAULT '1'");
		$this->ignorableQuery("ALTER TABLE `Groups` ADD `StorageTabEnabled` TINYINT(1) NOT NULL DEFAULT '1'");
		$this->ignorableQuery("ALTER TABLE `Groups` ADD `FileSharingEnabled` TINYINT(1) NOT NULL DEFAULT '1'");
		
	}

	function _6_4_3_10428()
	{
		$this->insertConfig('global', 'defaultImapSort', '', 'String');
	}
	
	/*	 * ********************************************* 6.4.3 ****************************************************** */

	function _6_4_3()
	{
		$result = $this->dbAdapter->fetchOne("select count(keyValue) from Config where keyName = 'remoteServers' and keyType = 'String'");
		if($result > 1)
		{
			// more then one remoteServer
			// remove the errornous entries
			$result = $this->dbAdapter->fetchOne("select configId from Config where keyName = 'remoteServers' and keyType = 'String' limit 1");
			$this->exceptionQuery("delete from Config where configId > " . $result . " and keyName = 'remoteServers' and keyType='String'");
		}
		
		$result = $this->dbAdapter->fetchOne("select count(keyValue) from Config where keyName = 'remoteDomains' and keyType = 'String'");
		if($result > 1)
		{
			// more then one remoteServer
			// remove the errornous entries
			$result = $this->dbAdapter->fetchOne("select configId from Config where keyName = 'remoteDomains' and keyType = 'String' limit 1");
			$this->exceptionQuery("delete from Config where configId > " . $result . " and keyName = 'remoteDomains' and keyType='String'");
		}

		if(!$this->testConfig('global', 'cacheType', null))
		{
			$this->insertConfig('global', 'cacheType', 'fs', 'String');
		}
	}
	
	
	/*	 * ********************************************* PLACE HOLDER 6.4.2 ****************************************************** */
	
	/*	 * ********************************************* PLACE HOLDER 6.4.1 ****************************************************** */
	
	/*	 * ********************************************* 6.4 ****************************************************** */

	function _6_4_0()
	{
		$this->insertConfig('global', 'enableSpellCheck', '0', 'Integer');
	    
		$this->ignorableQuery("ALTER TABLE `awl` modify `email` varchar(255) NOT NULL default ''");
		$this->ignorableQuery("ALTER TABLE `awl` modify `ip` varchar(40) NOT NULL default ''");
		$this->ignorableQuery("ALTER TABLE `awl` add `signedby` varchar(255) NOT NULL default ''");
		$this->ignorableQuery("ALTER TABLE `awl` modify `count` int(11) NOT NULL default '0'");
		$this->ignorableQuery("ALTER TABLE `awl` modify `totscore` float NOT NULL default '0'");
		$this->ignorableQuery("ALTER TABLE `awl` drop `IndexDate`");
		$this->ignorableQuery("ALTER TABLE `awl` drop PRIMARY KEY");
		$this->ignorableQuery("ALTER TABLE `awl` add PRIMARY KEY (`username`,`email`,`signedby`,`ip`)");
		$this->ignorableQuery("CREATE TABLE bayes_expire ( id int(11) NOT NULL default '0', runtime int(11) NOT NULL default '0', KEY bayes_expire_idx1 (id) ) ENGINE=InnoDB");
		$this->ignorableQuery("CREATE TABLE bayes_global_vars ( variable varchar(30) NOT NULL default '', value varchar(200) NOT NULL default '', PRIMARY KEY  (variable) ) ENGINE=InnoDB");
		$this->ignorableQuery("INSERT INTO bayes_global_vars VALUES ('VERSION','3')");
		$this->ignorableQuery("CREATE TABLE bayes_seen ( id int(11) NOT NULL default '0', msgid varchar(200) binary NOT NULL default '', flag char(1) NOT NULL default '', PRIMARY KEY  (id,msgid) ) ENGINE=InnoDB");
		$this->ignorableQuery("CREATE TABLE bayes_token ( id int(11) NOT NULL default '0', token char(5) NOT NULL default '', spam_count int(11) NOT NULL default '0', ham_count int(11) NOT NULL default '0', atime int(11) NOT NULL default '0', PRIMARY KEY  (id, token), INDEX bayes_token_idx1 (id, atime) ) ENGINE=InnoDB");
		$this->ignorableQuery("CREATE TABLE bayes_vars ( id int(11) NOT NULL AUTO_INCREMENT, username varchar(200) NOT NULL default '', spam_count int(11) NOT NULL default '0', ham_count int(11) NOT NULL default '0', token_count int(11) NOT NULL default '0', last_expire int(11) NOT NULL default '0', last_atime_delta int(11) NOT NULL default '0', last_expire_reduce int(11) NOT NULL default '0', oldest_token_age int(11) NOT NULL default '2147483647', newest_token_age int(11) NOT NULL default '0', PRIMARY KEY  (id), UNIQUE bayes_vars_idx1 (username) ) ENGINE=InnoDB"); 
		
		// Change the default Spamassassin score from 4 ( Atmail < 6.3 ) to 5, since new rulesets and bayes scores higher
		$this->ignorableQuery("update Config set keyValue='5' where keyName='filter_required_hits' and keyValue='4'");
		
		// DKIM off in Exim, moved logic to Spamassassin for better scoring and less false positives
		$this->ignorableQuery("update Config set keyValue='0' where keyName='dkim_enable'");
		
		$this->insertConfig('defaultUserSettings', 'enableMessagePreview', '1', 'Integer');
	    $this->ignorableQuery("ALTER TABLE `UserSettings` ADD `enableMessagePreview` smallint(1)  default '1'");
        
		$this->insertConfig('defaultUserSettings', 'confirmOnSend', '0', 'Integer');
       	$this->ignorableQuery("ALTER TABLE `UserSettings` ADD `confirmOnSend` smallint(1)  default '0'");
		$this->insertConfig('global', 'enableConfirmOnSend', '0', 'Integer');
		
		$this->insertConfig('defaultUserSettings', 'copyThreadReplyToCurrentFolder', '0', 'Integer');
		$this->ignorableQuery("ALTER TABLE `UserSettings` ADD `copyThreadReplyToCurrentFolder` smallint(1)  default '0'");
		$this->exceptionQuery("update `Config` set keyType = 'Integer' where keyName = 'cacheEnabled' and section = 'global'");
		$this->exceptionQuery("update `Config` set keyValue = 65535 where keyName = 'cacheEnabled' and section = 'global' and keyValue = 1");
		$this->ignorableQuery("delete from calendarDelegates where calendarid not in (select id from calendars)");

		if(!$this->testConfig('global', 'cacheType', null))
		{
			$this->insertConfig('global', 'cacheType', 'fs', 'String');
		}
	}

	function _6_3_6_9421()
	{
		$this->insertConfig('global', 'ActiveSyncTimeout', '30', 'Integer');
		$this->insertConfig('global', 'ActiveSyncTarpit', '0', 'Integer');
		$this->insertConfig('global', 'ActiveSyncTarpitMultiplier', '1', 'Integer');
	}
	
	function _6_3_6_9267()
	{
		$this->ignorableQuery('ALTER TABLE AbookGroup ADD INDEX iGroupID (GroupID)');
	}
	
	function _6_3_6_9241()
	{
		$this->exceptionQuery("insert into Config (section, keyName, keyValue, keyType) values ( 'global', 'remoteServers', '', 'String')");
		$result = $this->dbAdapter->fetchOne("select group_concat(keyValue separator '\n') from Config where keyName = 'remoteServers' and keyType = 'Array'");
		$this->exceptionQuery("update Config set keyValue = '" . $result . "' where keyName = 'remoteServers' and keyType='String'");
		$this->exceptionQuery("delete from Config where keyName = 'remoteServers' and keyType = 'Array'");

		$this->exceptionQuery("insert into Config (section, keyName, keyValue, keyType) values ( 'global', 'remoteDomains', '', 'String')");
		$result = $this->dbAdapter->fetchOne("select group_concat(keyValue separator '\n') from Config where keyName = 'remoteDomains' and keyType = 'Array'");
		$this->exceptionQuery("update Config set keyValue = '" . $result . "' where keyName = 'remoteDomains' and keyType='String'");
		$this->exceptionQuery("delete from Config where keyName = 'remoteDomains' and keyType = 'Array'");
	}
	
	/*	 * ********************************************* 6.3.6 ****************************************************** */
	function _6_3_6()
	{
		$this->ignorableQuery("ALTER TABLE `UserSettings` ADD `DeleteTrashOnLogout` smallint(1)  default '0'");
		$this->exceptionQuery("alter table `Abook` modify `UserEmail` varchar(255) collate utf8_general_ci");
		$this->exceptionQuery("alter table `Abook` modify `UserEmail2` varchar(255) collate utf8_general_ci");
		$this->exceptionQuery("alter table `Abook` modify `UserEmail3` varchar(255) collate utf8_general_ci");
		$this->exceptionQuery("alter table `Abook` modify `UserEmail4` varchar(255) collate utf8_general_ci");
		$this->exceptionQuery("alter table `Abook` modify `UserEmail5` varchar(255) collate utf8_general_ci");
		$this->exceptionQuery("alter table `Abook` modify `UserURL` varchar(128) collate utf8_general_ci");
		$this->insertConfig('defaultUserSettings', 'DeleteTrashOnLogout', '0', 'Integer');
		$this->insertConfig('global', 'externalUserPasswordEncryptionType', 'PLAIN', 'String');
		$this->ignorableQuery('ALTER TABLE AbookGroup ADD INDEX iAbookID (AbookID)');
	}
	
	/*	 * ********************************************* PLACE HOLDER 6.3.5 ****************************************************** */

	
	/*	 * ********************************************* 6.3.4 ****************************************************** */
	function _6_3_4()
	{
		$this->ignorableQuery('alter table UserSession drop column PasswordMD5');
		$this->ignorableQuery('drop table Accounts');
	}

	/*	 * ********************************************* 6.3.3 ****************************************************** */
	function _6_3_3()
	{
		
		// Step 1: Convert to InnoDB
		$this->exceptionQuery('alter table calendarDelegates engine=InnoDB');
		$this->exceptionQuery('alter table calendarExtendedData engine=InnoDB');
		$this->exceptionQuery('alter table calendarObjects engine=InnoDB');
		$this->exceptionQuery('alter table calendars engine=InnoDB');
		$this->exceptionQuery('alter table principals engine=InnoDB');

		// Step 2: Add indexes to calendar tables
		$this->exceptionQuery('alter table calendarObjects add key(calendarid)');
		$this->exceptionQuery('alter table calendars add key(principaluri)');
		$this->exceptionQuery('alter table calendarDelegates add key(principalid)');
		
	}

	/*	 * ********************************************* 6.3.2.8327 ****************************************************** */
	function _6_3_2_8327()
	{
		if(!$this->testConfig('exim', 'dkim_domain', null))
		{
			// no dkim domains defined, disable outbound dkim
			$this->updateConfig('exim', 'dkim_enable_outbound', '0', 'Boolean');
		}	
	}
	
	/*	 * ********************************************* PLACE HOLDER 6.3.2 ****************************************************** */

	/*	 * ********************************************* 6.3.1 ****************************************************** */
	function _6_3_1()
	{
		// Remove incorrect CalDAV logins, without an IP. (Direct API access)
		$this->ignorableQuery('delete from Log_Login where LogType="6" and LogIP is null');
	}
	
	/*	 * ********************************************* 6.3 ****************************************************** */
	function _6_3_0()
	{
		// Turn off (client) Carddav, its talking to Atmail directly now
		$this->exceptionQuery('update Groups set Carddav=0');

		// drop old calendar server tables
		$this->ignorableQuery('drop table CalAddresses');
		$this->ignorableQuery('drop table CalDav');
		$this->ignorableQuery('drop table CalDavService');
		$this->ignorableQuery('drop table CalGroups');

		$this->updateConfig('global', 'session_timeout', '120', 'String');
		$this->exceptionQuery('
            CREATE TABLE IF NOT EXISTS `principals` (
              `id` int(10) unsigned NOT NULL auto_increment,
              `uri` varchar(100) NOT NULL,
              `email` varchar(80) default NULL,
              `displayname` varchar(80) default NULL,
              PRIMARY KEY  (`id`),
              UNIQUE KEY `uri` (`uri`)
            ) ENGINE=MyISAM DEFAULT CHARSET=latin1;');

		$this->exceptionQuery('
            CREATE TABLE IF NOT EXISTS `calendars` (
              `id` int(10) unsigned NOT NULL auto_increment,
              `principaluri` varchar(100) default NULL,
              `displayname` varchar(100) default NULL,
              `uri` varchar(100) default NULL,
              `ctag` int(10) unsigned NOT NULL default \'0\',
              `description` text,
              `calendarorder` int(10) unsigned default \'0\',
              `calendarcolor` varchar(10) default NULL,
              `timezone` text,
              `components` varchar(20) default NULL,
              PRIMARY KEY  (`id`)
            ) ENGINE=MyISAM DEFAULT CHARSET=utf8;');

		$this->exceptionQuery('
            CREATE TABLE IF NOT EXISTS `calendarObjects` (
              `id` int(10) unsigned NOT NULL auto_increment,
              `calendardata` text,
              `uri` varchar(100) default NULL,
              `calendarid` int(10) unsigned NOT NULL,
              `lastmodified` int(11) default NULL,
              PRIMARY KEY  (`id`)
            ) ENGINE=MyISAM DEFAULT CHARSET=utf8;');

		$this->exceptionQuery('
			CREATE TABLE IF NOT EXISTS calendarDelegates (
				id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
				calendarid INT(11) UNSIGNED NOT NULL,
				principalid INT(11) UNSIGNED NOT NULL,
				mode TINYINT(2) UNSIGNED);');

		$this->exceptionQuery('
			CREATE TABLE IF NOT EXISTS groupMembers (
				id INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
				principalid INT(10) UNSIGNED NOT NULL,
				memberid INT(10) UNSIGNED NOT NULL,
				mode TINYINT(2) UNSIGNED
			);');

		$this->exceptionQuery('
            ALTER TABLE Abook
                ADD `VCardData` mediumblob,
                ADD `CardDAVUrl` varchar(100) default NULL;');

		$this->exceptionQuery("
            ALTER TABLE Groups
              ADD CalDAVServer TINYINT(1) NOT NULL DEFAULT '1',
              ADD CardDAVServer TINYINT(1) NOT NULL DEFAULT '1',
              ADD WebDAVRootUrl VARCHAR(100) NULL;");
              
		$this->insertConfig("global", "iosProfiles", 1, "Integer");
	}
	
	/************************************************* PLACE HOLDER 6.2.13 *******************************************************/
	/*	 * ********************************************* PLACE HOLDER 6.2.12 ****************************************************** */
	/*	 * ********************************************* 6.2.11 ****************************************************** */
	function _6_2_11()
	{
		// Add the JSON and JSONP values - JSONP off by default for security
		$this->insertConfig("global", "jsonpAPI", 0, "Integer");
	}

	/*	 * ********************************************* 6.2.10 ****************************************************** */
	function _6_2_10()
	{
		$this->ignorableQuery("ALTER TABLE `UserSettings` ADD `DisplayEmailImages` smallint(1)  default '1'");
		$this->ignorableQuery("ALTER TABLE `UserSettings` ADD `SaveDrafts` smallint(1) NOT NULL default '1'");
		$this->ignorableQuery("ALTER TABLE `UserSettings` ADD `AutoReload` smallint(1) NOT NULL default '1'");
		$this->ignorableQuery("alter table MailRelay change IPaddress `IPaddress` varchar(24) NOT NULL default ''");

		// Apply the new user defaults
		// Add DisplayEmailImages, default on
		$this->insertConfig("defaultUserSettings", "DisplayEmailImages", '1', "String");

		// Add save drafts, default on
		$this->insertConfig("defaultUserSettings", "SaveDrafts", '1', "String");

		// Add autoreload, default on, no sounds
		$this->insertConfig("defaultUserSettings", "AutoReload", '1', "String");

		// Update the whitelist/blacklist from @domain.com to domain.com
		$rows = $this->dbAdapter->fetchAll("select * from SpamSettings where value like '@%' and (preference='whitelist_from' or preference='blacklist_from')");

		foreach ($rows as $row)
		{
			$value = str_replace('@', '', $row['value']);
			$this->dbAdapter->update("SpamSettings", array('value' => $value), $this->dbAdapter->quoteInto('prefid = ?', $row['prefid']));
		}

		// Add staff.atmail.com to whitelist senders
		$whitelist = $this->dbAdapter->fetchOne('select value from SpamSettings where username="GLOBAL" and preference="whitelist_from" and value="staff.atmail.com"');

		if (empty($whitelist))
		{
			$this->dbAdapter->insert('SpamSettings', array('username' => 'GLOBAL', 'preference' => 'whitelist_from', 'value' => 'staff.atmail.com'));
		}
	}

	/*	 * ********************************************* 6.2.8 ****************************************************** */
	function _6_2_8()
	{
		$this->exceptionQuery("UPDATE AdminUsers set SessionID = NULL");
		$this->exceptionQuery("ALTER TABLE AdminUsers modify SessionID varchar(32) unique");
	}

	/*	 * ********************************************* 6.2.7 ****************************************************** */
	function _6_2_7()
	{
		$this->exceptionQuery('update UserSettings set CalDavView = "Day" where CalDavView = ""');
		$this->ignorableQuery("UPDATE UserSettings SET TimeZone = 'GMT' WHERE TimeZone = '' OR TimeZone IS NULL");
		$this->ignorableQuery("UPDATE Config SET keyValue = 'GMT' WHERE keyValue = '' and keyName = 'TimeZone' and section = 'defaultUserSettings'");

		$this->insertConfig("defaultUserSettings", "DateDisplay", 1, "Integer");
		$this->exceptionQuery("ALTER TABLE UserSettings add `DateDisplay` smallint(1) NOT NULL default '1'");
		$this->ignorableQuery("update UserSettings set RealName = replace(RealName, '&amp', '&')");
	}

	/*	 * ********************************************* 6.2.6 ****************************************************** */
	function _6_2_6()
	{
		$this->insertConfig("defaultUserSettings", "CalDavView", "Day", "String");
		$this->exceptionQuery('ALTER TABLE UserSettings add CalDavView varchar(5)');
		$this->exceptionQuery('update UserSettings set CalDavView = "Day"');

		//reset language if null (should not be null)
		$this->exceptionQuery("UPDATE Config SET keyValue = 'en' WHERE section = 'defaultUserSettings' AND keyName = 'Language' AND keyValue = ''");
		$this->exceptionQuery("UPDATE UserSettings SET Language = 'en' WHERE Language = '' OR Language IS NULL");
		$this->ignorableQuery("UPDATE UserSettings SET TimeZone = 'GMT' WHERE TimeZone = '' OR TimeZone IS NULL");
	}

	// ********************************* 6.2.5 UPDATE ***************************************** //
	function _6_2_5()
	{
		// Make MailRelay multi-server safe
		$this->ignorableQuery("alter table MailRelay drop primary key");
		$this->ignorableQuery("alter table MailRelay change IPaddress `IPaddress` varchar(24) NOT NULL default ''");
		$this->ignorableQuery("alter table MailRelay add `id` bigint(20) unsigned NOT NULL auto_increment PRIMARY KEY");
	}

	// ********************************* 6.2.4 UPDATE ***************************************** //
	function _6_2_4()
	{
		$this->insertConfig("global", "autocompleteFetchThreshold", 50, "Integer");
		$this->insertConfig("global", "autocompleteCacheSize", 100, "Integer");
		$this->insertConfig("global", "autocompleteFetchSize", 25, "Integer");
		$this->insertConfig("global", "autocompleteMinFetchLength", 2, "Integer");

		$this->insertConfig("global", "log_purge_days", 180, "Integer");
		$this->insertConfig("exim", "filter_awl_purge_low", 7, "Integer");
		$this->insertConfig("exim", "filter_awl_purge_medium", 14, "Integer");
		$this->insertConfig("exim", "filter_awl_purge_high", 30, "Integer");

		$this->insertConfig("global", "ActiveSyncCacheLifespan", 14, "Integer");

		$this->ignorableQuery('alter table Abook modify Global tinyint(1) not null default 0');
		$this->ignorableQuery('alter table Abook modify Shared tinyint(1) not null default 0');

		$this->ignorableQuery('alter table Abook add column Favourite tinyint(1) default NULL');
		$this->ignorableQuery('alter table Abook add column UsageCount int default 0 not null');
		$this->ignorableQuery('alter table AbookGroup modify GroupID mediumint(12) default NULL');
		$this->ignorableQuery('update UserSettings set CalDavUrl = "http://localhost:8008/calendars/users/" where CalDavUrl is NULL or CalDavUrl = ""');

		$this->ignorableQuery('delete from Config where keyName = "calendarenable" and section = "global"');
		$this->ignorableQuery("update UserSession LEFT JOIN Users on Users.Account = (IF ( position('@' in SUBSTRING_INDEX(UserSession.Account, '-', 1)) = 0 , CONCAT( SUBSTRING_INDEX( UserSession.Account, '-', 1), '@', SUBSTRING_INDEX(UserSession.Account, '@', -1) ), UserSession.Account)) LEFT JOIN Groups ON Users.Ugroup = GroupName  LEFT JOIN Domains ON HostName = SUBSTRING_INDEX(Users.Account, '@', -1) set CalendarUserStatus = !((select Calendar from Groups where GroupName = 'default') && IFNULL(Calendar, 0) && IFNULL(Enable,1) && !IFNULL(UserStatus, 0))");
	}

	// ********************************* 6.2.3 UPDATE ***************************************** //
	function _6_2_3()
	{
		$this->ignorableQuery("update SpamSettings set value='20' where preference='required_score' and value='Disabled'");

		$this->updateConfig('global', 'remoteServersOverwrite', '1', 'Boolean', 'select distinct true from Config where (select true from Config where keyName = "remoteServersOverwrite" and keyValue = 0) and (select true from Config where keyName = "remoteServers" and keyValue = "")');
		$this->ignorableQuery('update Config set keyType = "Array" where keyName = "remoteServers" and keyType = "String"');

		// expand the IPaddress column to 16 chars beacause as is (varchar(15)) it wont fit an address like 123.123.123.0/22
		$this->ignorableQuery("alter table MailRelay modify IPaddress varchar(24) not null");
	}

	// ********************************* 6.2.2 UPDATE ***************************************** //
	function _6_2_2()
	{
		$this->ignorableQuery("ALTER TABLE `" . $this->dbTables->AdminUsers . "` ADD EmailAddress varchar(128) NULL default NULL AFTER Fullname");
		$this->ignorableQuery('update ignore UserSession set Account = replace(Account, "@", "") where account like "%-%@"');
		$this->ignorableQuery("ALTER TABLE `UserSettings` ADD ThreadLimit tinyint default 6");

		$this->insertConfig("defaultUserSettings", "ThreadLimit", 6, "Integer");

		// make sure everyone is on the same page :)
		$this->ignorableQuery("alter table AbookGroup modify GroupName varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserFirstName varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserMiddleName varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserLastName varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserTitle varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserHomeAddress varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserHomeCity varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserHomeState varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserHomeZip varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserHomeCountry varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserWorkCompany varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserWorkTitle varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserWorkDept varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserWorkOffice varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserWorkAddress varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserWorkCity varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserWorkState varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserWorkZip varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserWorkCountry varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table Abook modify UserInfo varchar(128) character set utf8 default NULL");

		$this->ignorableQuery("alter table AbookGroupNames modify GroupName varchar(128) character set utf8 default NULL");

		$this->ignorableQuery("alter table AdminGroup modify Ugroup varchar(64) character set utf8 default NULL");

		$this->ignorableQuery("alter table AdminUsers modify Username varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table AdminUsers modify Password varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table AdminUsers modify Company varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table AdminUsers modify Fullname varchar(128) character set utf8 default NULL");

		$this->ignorableQuery("alter table Config modify keyValue varchar(256) character set utf8 default NULL");
		$this->ignorableQuery("alter table Config modify keyType varchar(8) default NULL");

		$this->ignorableQuery("alter table Groups modify GroupName varchar(255) character set utf8 NOT NULL default ''");
		$this->ignorableQuery("alter table Groups modify GroupDescription varchar(255) character set utf8 default NULL");

		$this->ignorableQuery("alter table UserSession modify Password varchar(64) character set utf8 default NULL");
		$this->ignorableQuery("alter table UserSession modify SessionData mediumtext character set utf8");

		$this->ignorableQuery("alter table UserSettings modify RealName varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table UserSettings modify ReplyTo varchar(128) character set utf8 default NULL");
		$this->ignorableQuery("alter table UserSettings modify Signature text character set utf8");
		$this->ignorableQuery("alter table UserSettings add column cssStyleTheme varchar(64) character set utf8 NOT NULL default 'Blue-Steel'");

		$this->ignorableQuery("alter table Users modify PasswordQuestion varchar(256) character set utf8 default NULL");
		$this->ignorableQuery("alter table Users modify Ugroup varchar(255) character set utf8 default 'default'");
		$this->ignorableQuery("alter table Users modify AutoReply text character set utf8");
		$this->ignorableQuery("alter table Users modify Forward varchar(128) character set utf8 default NULL");

		$this->ignorableQuery("update Users set Ugroup = 'default' where (select count(*) from Groups where Ugroup = GroupName) = 0");
		$this->ignorableQuery("update Users set Ugroup = 'default' where Ugroup = 'Default'");
		$this->ignorableQuery("update Config set keyValue = 'Blue-Steel' where keyName = 'cssStyleTheme' and keyValue = 'blue-steel'");
		$this->ignorableQuery("update UserSettings set cssStyleTheme = 'Blue-Steel' where cssStyleTheme = 'blue-steel'");

		// Fix the broken spam-score value
		$this->ignorableQuery("update SpamSettings set value='20' where preference='required_score' and value='Disabled'");
		$this->ignorableQuery("update SpamSettings set value='2' where preference='required_score' and value='Minimal'");
		$this->ignorableQuery("update SpamSettings set value='3' where preference='required_score' and value='Low'");
		$this->ignorableQuery("update SpamSettings set value='4' where preference='required_score' and value='Normal'");
		$this->ignorableQuery("update SpamSettings set value='6' where preference='required_score' and value='High'");
		$this->ignorableQuery("update SpamSettings set value='15' where preference='required_score' and value='Max'");
	}

	// ********************************* PLACE HOLDER 6.2.1 UPDATE ***************************************** //
	// ********************************* 6.2 UPDATE ***************************************** //
	function _6_2()
	{
		// Update the new SerialConf
		$this->exceptionQuery('ALTER TABLE `SerialConf` change `Value` `Value` longtext;');

		// Convert SerialConf to InnoDB for performance
		$this->exceptionQuery('ALTER TABLE `SerialConf` TYPE=INNODB');

		// Update all Subadmins with logs, unless specifically turned off ( NULL , if 0 turned off by admin previously )
		$this->exceptionQuery('update AdminUsers set ULogs="1" where ULogs is null');

		// Delete duplicate entries in Plugins ( can cause issues from running update multiple times )
		$this->exceptionQuery('DELETE t1 FROM Plugins t1, Plugins t2 WHERE t1.name=t2.name AND t1.id < t2.id');
	}

	// ********************************* PLACE HOLDER 6.1.9 UPDATE ***************************************** //
	// ********************************* 6.1.8 UPDATE ***************************************** //
	function _6_1_8()
	{
		//Optional: Clear UserSession.SessionData to force users to log in again (for cached js changes etc.)
		$this->dbAdapter->update($this->dbTables->UserSession, array('SessionData' => ''));
		$this->insertConfig("global", "userPasswordEncryptionType", 'PLAIN', "String");

		// check that cssStyle and cssStyleTheme in Config
		$this->insertConfig("global", "cssStyle", 'original', "String");
		$this->insertConfig("global", "cssStyleTheme", 'Blue-Steel', "String");

		//check for or insert with default UserSettings.cssStyle
		if (!$this->fieldExists($this->dbTables->UserSettings, 'cssStyleTheme'))
		{
			$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->UserSettings . "` ADD cssStyleTheme varchar(64) CHARACTER SET utf8 NOT NULL default 'Blue-Steel'");
			$this->dbAdapter->update($this->dbTables->UserSettings, array('cssStyleTheme' => 'Blue-Steel'));
		}

		$this->insertConfig("global", "themeEnabled", "1", "Boolean");

		// insert default carddav value
		$this->insertConfig("defaultUserSettings", "CardDavUrl", "http://localhost:8800", "String");
		$this->insertConfig("defaultUserSettings", "ViewCardDav", "0", "String");

		//clean up old, redundant sql fields (how can you access these args if you dont have them)
		$this->exceptionQuery('delete from Config where keyName = "sql_host";');
		$this->exceptionQuery('delete from Config where keyName = "sql_user";');
		$this->exceptionQuery('delete from Config where keyName = "sql_pass";');
		$this->exceptionQuery('delete from Config where keyName = "sql_table";');

		system("chmod 0660 " . APP_ROOT . "config/dbconfig.ini");

		$this->dbAdapter->query("DROP TABLE IF EXISTS `AbookServers`");
		$this->dbAdapter->query("CREATE TABLE `AbookServers` (
			  `Account` varchar(128) NOT NULL default '',
			  `username` varchar(128) character set utf8 default NULL,
			  `password` varchar(128) character set utf8 default NULL,
			  `server` varchar(256) character set utf8 default NULL,
			  `port` int(6) NOT NULL default '8800',
			  `url` text character set utf8 default NULL,
			  `protocol` varchar(7) NOT NULL default 'carddav',
			  `id` mediumint(8) unsigned NOT NULL auto_increment,
			  PRIMARY KEY  (`id`),
			  KEY `iAccount` (`Account`)
			) ENGINE=MyISAM DEFAULT CHARSET=latin1;");
		if (!$this->fieldExists('Groups', 'Carddav'))
		{
			$this->exceptionQuery('ALTER TABLE Groups add Carddav int(1) default 1');
		}
	}

	// ********************************* 6.1.7 UPDATE ***************************************** //
	function _6_1_7()
	{
		//Optional: Clear UserSession.SessionData to force users to log in again (for cached js changes etc.)
		$this->dbAdapter->update($this->dbTables->UserSession, array('SessionData' => ''));
	}

	// ********************************* 6.1.6 UPDATE ***************************************** //
	function _6_1_6()
	{
		// Delete duplicate smtp_auth setting
		$this->ignorableQuery("delete from Config where keyName = 'smtp_auth' and section = 'global'");
		$this->ignorableQuery("DROP TABLE IF EXISTS `Plugins`");
		$this->ignorableQuery("CREATE TABLE `Plugins` (
			  `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
			  `module` varchar(8) NOT NULL,
			  `settings` text,
			  `status` tinyint(1) NOT NULL DEFAULT '1',
			  `name` varchar(64) NOT NULL,
			  `company` varchar(64) NOT NULL,
			  PRIMARY KEY (`id`),
			  KEY `module` (`module`),
			  KEY `status` (`status`)
			) ENGINE=MyISAM DEFAULT CHARSET=latin1;");

		$res = $this->dbAdapter->fetchOne('select name from Plugins where name="FilePreview"');
		if (empty($res))
		{
			$this->dbAdapter->insert('Plugins', array('module' => 'mail', 'status' => 1, 'name' => 'FilePreview', 'company' => 'Atmail'));
		}
		$res = $this->dbAdapter->fetchOne('select name from Plugins where name="Test"');
		if (empty($res))
		{
			$this->dbAdapter->insert('Plugins', array('module' => 'mail', 'status' => 1, 'name' => 'Test', 'company' => 'Atmail'));
		}

		$this->ignorableQuery("delete from Config where section = 'plugins'");
		$this->ignorableQuery("alter table UserSession modify SessionData MEDIUMTEXT");

		// add calendar extended data table
		$this->ignorableQuery('drop table if exists `calendarExtendedData`');
		$this->ignorableQuery('create table `calendarExtendedData` ( `Account` varchar(128) character set latin1 default NULL, `EntryID` varchar(64) default NULL, `ObjectId` varchar(64) default NULL, `id` mediumint(12) NOT NULL auto_increment, PRIMARY KEY (`id`))');
		$this->ignorableQuery('alter table SharedLookup modify column LookupID varchar(128)');

		if (!$this->fieldExists('Groups', 'WebSyncShared'))
		{
			$this->exceptionQuery("ALTER TABLE Groups ADD `WebSyncShared` int(1) NOT NULL DEFAULT 1");
		}

		if (!$this->fieldExists('Groups', 'WebSyncGlobal'))
		{
			$this->exceptionQuery("ALTER TABLE Groups ADD `WebSyncGlobal` int(1) NOT NULL DEFAULT 1");
		}

		$this->ignorableQuery('delete from Config where keyName="websyncEnabledShared"');
		$this->ignorableQuery('delete from Config where keyName="websyncEnabledGlobal"');
		$this->ignorableQuery('delete from Config where keyName="websyncEnabled"');
	}

	// ********************************* 6.1.5 UPDATE ***************************************** //
	function _6_1_5()
	{
		$this->ignorableQuery("UPDATE `" . $this->dbTables->Users . "` SET `Ugroup` = 'default' WHERE (`Ugroup` IS NULL or `Ugroup` = '' or `Ugroup` = 'Default')");
		$this->ignorableQuery("UPDATE Groups SET GroupName='default' where GroupName='Default'");
		$this->ignorableQuery("delete from Groups where GroupName=''");
		$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->Users . "` CHANGE `Ugroup` `Ugroup` varchar(255) NOT NULL DEFAULT 'default'");
		$this->ignorableQuery("ALTER TABLE `" . $this->dbTables->Users . "` ADD INDEX ( `Ugroup` )");
	}

	// ********************************* 6.1.4 UPDATE ***************************************** //
	function _6_1_4()
	{
		$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->AbookGroup . "` CHANGE `GroupName` `GroupName` VARCHAR( 128 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL");
		$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->AbookGroupNames . "` CHANGE `GroupName` `GroupName` VARCHAR( 128 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL");
		$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->Users . "`  CHANGE `Ugroup` `Ugroup` VARCHAR( 255 ) NULL DEFAULT NULL");
		$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->UserSettings . "` CHANGE `Language` `Language` VARCHAR( 5 ) NULL DEFAULT NULL");
		$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->Groups . "` CHANGE `GroupName` `GroupName` VARCHAR( 255 ) NOT NULL");
		$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->Groups . "` CHANGE `GroupDescription` `GroupDescription` VARCHAR( 255 ) NULL DEFAULT NULL");

		//add new AdminUsers fields
		$describeAdminUsers = $this->dbAdapter->query('DESCRIBE `' . $this->dbTables->AdminUsers . '`')->fetchAll();
		$adminUsersFields = array();
		foreach ($describeAdminUsers as $adminUsersField)
		{
			$adminUsersFields[] = $adminUsersField['Field'];
		}
		if (!in_array('Language', $adminUsersFields))
		{
			$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->AdminUsers . "` ADD `Language` VARCHAR( 5 ) NULL ; ");
		}

		//add new Groups fields
		$describeGroups = $this->dbAdapter->query('DESCRIBE `' . $this->dbTables->Groups . '`')->fetchAll();

		$groupsFields = array();
		foreach ($describeGroups as $groupField)
		{
			$groupsFields[] = $groupField['Field'];
		}

		if (!in_array('GroupwareZone', $groupsFields))
		{
			$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->Groups . "` ADD `GroupwareZone` VARCHAR( 6 ) NOT NULL DEFAULT 'Domain'");
		}
		if (!in_array('Webmail', $groupsFields))
		{
			$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->Groups . "` ADD `Webmail` INT( 1 ) NOT NULL DEFAULT '1'");
		}
		if (!in_array('Calendar', $groupsFields))
		{
			$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->Groups . "` ADD `Calendar` INT( 1 ) NOT NULL DEFAULT '1'");
		}
		if (!in_array('SharedAbook', $groupsFields))
		{
			$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->Groups . "` ADD `SharedAbook` INT( 1 ) NOT NULL DEFAULT '1'");
		}
		if (in_array('GlobalAbook', $groupsFields))
		{
			$this->dbAdapter->update($this->dbTables->Groups, array('GroupwareZone' => 'Off'), "GlobalAbook = 0");
			$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->Groups . "` DROP `GlobalAbook`");
		}

		//only add INDEX if not already and INDEX
		foreach ($describeGroups as $groupField)
		{
			if ($groupField['Field'] == 'POP3Support' && $groupField['Key'] != 'MUL')
			{
				$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->Groups . "` ADD INDEX ( `POP3Support` )");
			}
			elseif ($groupField['Field'] == 'Webmail' && $groupField['Key'] != 'MUL')
			{
				$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->Groups . "` ADD INDEX ( `Webmail` )");
			}
			elseif ($groupField['Field'] == 'IMAPSupport' && $groupField['Key'] != 'MUL')
			{
				$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->Groups . "` ADD INDEX ( `IMAPSupport` )");
			}
		}

		//Add default group that domains without 'inherit' set will 'inherit' - by extracting settings from Config
		$configGlobal = $this->config->global;
		//set default settings based on server config.
		$defaultConfig = array(
			'GroupwareZone' => 'System',
			'Webmail' => '1',
			'Calendar' => ($configGlobal['calendarenable'] == 'on' ? '1' : '0'),
			'SharedAbook' => ($configGlobal['sharedAbook'] == '0' ? '0' : '1'),
			'POP3Support' => 1,
			'IMAPSupport' => 1,
			'Sync' => ((!isset($configGlobal['websyncEnabled']) || $configGlobal['websyncEnabled'] == '1') ? '1' : '0'),
		);
		//inset the default group/system group config before removing old config vars out of Config
		$result = $this->exceptionQuery("INSERT IGNORE INTO " . $this->dbTables->Groups . " (`GroupName`, `GroupwareZone`, `Webmail`, `Calendar`, `SharedAbook`, `POP3Support`, `IMAPSupport`, `Sync`) values ('default', '" . $defaultConfig['GroupwareZone'] . "', '" . $defaultConfig['Webmail'] . "', '" . $defaultConfig['Calendar'] . "', '" . $defaultConfig['SharedAbook'] . "', '" . $defaultConfig['POP3Support'] . "', '" . $defaultConfig['IMAPSupport'] . "', '" . $defaultConfig['Sync'] . "')");

		//update all users and set them to belong to default group if not already set
		$result = $this->exceptionQuery("UPDATE `" . $this->dbTables->Users . "` SET `Ugroup` = 'default' WHERE (`Ugroup` IS NULL or `Ugroup` = '' or `Ugroup` = 'Default')");
		$this->exceptionQuery("UPDATE `" . $this->dbTables->Users . "` SET `UserStatus` = 0 WHERE `UserStatus` IS NULL");
		$this->exceptionQuery("ALTER TABLE `" . $this->dbTables->Users . "` CHANGE `UserStatus` `UserStatus` INT( 1 ) NOT NULL DEFAULT '0'");
		$this->exceptionQuery('update Config set keyValue="0" where keyName="allow_Signup"');
		try
		{
			$smtpuser = $this->dbAdapter->fetchOne('select keyValue from Config where keyName="smtpauth_username"');
			$smtppass = $this->dbAdapter->fetchOne('select keyValue from Config where keyName="smtpauth_password"');
			$smtpauth = $this->dbAdapter->fetchOne('select keyValue from Config where keyName="smtp_auth" and section="global"');
			$smtpauthsection = $this->dbAdapter->fetchOne('select section from Config where keyName="smtp_auth" and section="global"');

			// SMTP auth flag is missing
			if (!empty($smtpuser) && !empty($smtppass) && empty($smtpauthsection))
			{
				$this->dbAdapter->query('insert ignore into Config (section, keyName, keyValue, keyType) values ("global", "smtp_auth", "1", "String")');
			}
			else if (empty($smtpuser) && empty($smtppass) && empty($smtpauthsection))
			{
				$this->dbAdapter->query('insert ignore into Config (section, keyName, keyValue, keyType) values ("global", "smtp_auth", "0", "String")');
			}

			// SMTP auth is on, update flag
			elseif (!empty($smtpuser) && !empty($smtppass))
			{
				$this->dbAdapter->query('update Config set keyValue="1" where keyName="smtp_auth" and section="global"');
			}
			else if (empty($smtpuser) && empty($smtppass))
			{
				$this->dbAdapter->query('update Config set keyValue="0" where keyName="smtp_auth" and section="global"');
			}
			// SMTP auth is off, update flag
		}
		catch (Exception $e)
		{

		}

		//TODO: do we drop the old config fields in this release or in next release when we know these changes are stable and no cascading problems with code relying on removed Config rows.
		$row = $this->dbAdapter->fetchOne('select keyValue from Config where section="admin" and keyName="password" and keyValue="md5"');
		if ($row == "")
		{
			//switch all plain text passwords to md5
			$this->dbAdapter->update('AdminUsers', array('Password' => new Zend_Db_Expr('md5(Password)')));
			$this->dbAdapter->update('Config', array('keyValue' => 'md5'), "section = 'admin' AND keyName = 'password'");
		}
		$this->dbAdapter->query("update Config set keyName = concat('mail:', keyName) where section = 'plugins' and keyName not like 'mail:%'");

		@unlink("application/modules/mail/plugins/Atmail/MailOS.php");
		@unlink("application/modules/mail/plugins/Atmail/FilePreview.php");

		// expand the IPaddress column to 16 chars beacause as is (varchar(15)) it wont fit an address like 123.123.123.0/22
		$this->dbAdapter->query("alter table MailRelay modify IPaddress varchar(24) not null");
	}

	// ********************************* 6.1.3 UPDATE ***************************************** //
	function _6_1_3()
	{
		//mail filtering changes
		$this->exceptionQuery("ALTER TABLE `UserSettings` ADD `SieveSupport` SMALLINT NOT NULL DEFAULT '0'");
		$rows = $this->dbAdapter->select()->from('Config')->where("`keyName` = 'enableMailFilters'")->query()->fetchAll();

		if ($rows == null || $rows == false || count($rows) == 0)
		{
			$result = $this->dbAdapter->insert('Config', array('section' => 'exim', 'keyName' => 'enableMailFilters', 'keyValue' => '1', 'keyType' => 'Boolean'));
		}

		$this->dbAdapter->update('Config', array('keyType' => 'String'), "section = 'exim' AND keyName = 'filter_max_bodysize'");

		try
		{
			$row = $this->dbAdapter->fetchOne('select keyValue from Config where keyName="cssStyle"');
			if ($row == "")
			{
				$this->exceptionQuery('insert into Config (section, keyName, keyValue, keyType) values ("global", "cssStyle", "Original", "String")');
			}
		}
		catch (Exception $e)
		{
			//throw exception here if failure of this point not allowed
		}

		// Check URI DNS ability
		try
		{
			$row = $this->dbAdapter->fetchOne('select keyValue from Config where keyName="filter_uridnsbl_servers"');
			if ($row == "")
			{
				$this->exceptionQuery('insert into Config (section, keyName, keyValue, keyType) values ("exim", "filter_uridnsbl_servers", "multi.surbl.org", "String")');
			}
		}
		catch (Exception $e)
		{
			//throw exception here if failure of this point not allowed
		}
	}

	// ********************************* 6.1.2 UPDATE ***************************************** //
	function _6_1_2()
	{
		$this->exceptionQuery("ALTER TABLE `Users` CHANGE `MailDir` `MailDir` VARCHAR( 255 ) NULL");
		$this->exceptionQuery("ALTER TABLE `AdminUsers` ADD `UArchiveVault` TINYINT ( 1 ) NULL DEFAULT '0' AFTER `UAlias`");

		// Update all AdminUsers, to reflect the NumQuota in MB vs the old Atmail 5 KB
		$adminusers = $this->dbAdapter->fetchAll('select id from AdminUsers where NumQuota > 0');
		foreach ($adminusers as $adminuser)
		{
			// Select the existing NumQuota
			$quota = $this->dbAdapter->fetchOne('select NumQuota from AdminUsers where id = ' . $this->dbAdapter->quote($adminuser));
			$quota = round($quota / 1024);
			$this->dbAdapter->update("AdminUsers", array('NumQuota' => $quota), "id=" . $this->dbAdapter->quote($adminuser));
		}

		// Update the UserSession table for CalendarUserStatus support, used as a performance reference for the Calendar-server.
		$this->exceptionQuery("alter table UserSession add CalendarUserStatus int(1) NOT NULL default '0'");
		$disabled_domain_users = $this->dbAdapter->fetchAll('select Account from Users where UserStatus = "1"');
		foreach ($disabled_domain_users as $user)
		{
			$this->dbAdapter->update('UserSession', array('CalendarUserStatus' => '1'), "Account = " . $this->dbAdapter->quote($user['Account']));
			list($username, $domain) = explode('@', $this->dbAdapter->quote($user['Account']), 2);
			$this->dbAdapter->update('UserSession', array('CalendarUserStatus' => '1'), "Account like " . $username . "-%@" . $domain);
		}
		$disabled_users = $this->dbAdapter->fetchAll('select Account from Users where UserStatus = "2"');
		foreach ($disabled_users as $user)
		{
			$this->dbAdapter->update('UserSession', array('CalendarUserStatus' => '2'), "Account = " . $this->dbAdapter->quote($user['Account']));
			list($username, $domain) = explode('@', $this->dbAdapter->quote($user['Account']), 2);
			$this->dbAdapter->update('UserSession', array('CalendarUserStatus' => '2'), "Account like " . $username . "-%@" . $domain);
		}
	}

	// ********************************* 6.1.1 UPDATE ***************************************** //
	function _6_1_1()
	{
		$this->exceptionQuery("alter table Domains modify Enable char(1) NOT NULL default '1'");
		$this->exceptionQuery("alter table Users modify UserStatus char(1) NOT NULL default '0'");
		//making this a db rule prevents the use case of configuring server install to allow logins to remote servers
		//$this->exceptionQuery("alter table Users modify MailDir varchar(255) NOT NULL default ''");
		$this->exceptionQuery("update Domains set Enable = 1 where (Enable is NULL or Enable='')");
	}

	// ********************************* 6.1 UPDATE ***************************************** //
	function _6_1()
	{
		// add calendar extended data table
		$this->ignorableQuery('drop table if exists `calendarExtendedData`');
		$this->exceptionQuery('create table `calendarExtendedData` ( `Account` varchar(128) character set latin1 default NULL, `EntryID` varchar(64) default NULL, `ObjectId` varchar(64) default NULL, `id` mediumint(12) NOT NULL auto_increment, PRIMARY KEY (`id`))');
		$row = $this->dbAdapter->fetchOne('select keyValue from Config where keyName="websyncEnabled"');
		if ($row == "")
		{
			$result = $this->dbAdapter->insert('Config', array('keyName' => 'websyncEnabled', 'keyValue' => '1', 'section' => 'global', 'keyType' => 'String'));
			$result = $this->dbAdapter->insert('Config', array('keyName' => 'websyncEnabledShared', 'keyValue' => '1', 'section' => 'global', 'keyType' => 'String'));
			$result = $this->dbAdapter->insert('Config', array('keyName' => 'websyncEnabledGlobal', 'keyValue' => '1', 'section' => 'global', 'keyType' => 'String'));
		}

		//TODO: update all references to table names to use dbTables class
		$this->exceptionQuery('ALTER TABLE `AdminUsers` ADD `sessionData` TEXT NULL AFTER `Password`');
		$this->exceptionQuery('ALTER TABLE `AdminUsers` ADD `ipAddress` VARCHAR( 15 ) NULL AFTER `LastLogin`'); // standard Practice
		$this->exceptionQuery('ALTER TABLE `AdminUsers` ADD `modified` INT NULL AFTER `LastLogin`'); //used for gc UNIXTIMESTAMP GMT
		//Update User RealName to UTF-8
		$this->exceptionQuery('ALTER TABLE `UserSettings` CHANGE `RealName` `RealName` VARCHAR( 128 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL');
		$this->exceptionQuery('ALTER TABLE `Abook` CHANGE `UserFirstName` `UserFirstName` VARCHAR( 128 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL');
		$this->exceptionQuery('ALTER TABLE `Abook` CHANGE `UserMiddleName` `UserMiddleName` VARCHAR( 128 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL');
		$this->exceptionQuery('ALTER TABLE `Abook` CHANGE `UserLastName` `UserLastName` VARCHAR( 128 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL');

		$this->exceptionQuery('alter table UserSession change modified modified INT(11) unsigned not null default 0');
		$this->exceptionQuery('alter table UserSession change lifetime lifetime INT(11) unsigned not null default 0');

		// Next, insert max values for threads/sort
		try
		{
			$row = $this->dbAdapter->fetchOne('select keyValue from Config where keyName="sortMaxLimit"');
			if ($row == "")
			{
				$result = $this->dbAdapter->insert('Config', array('keyName' => 'sortMaxLimit', 'keyValue' => '30000', 'section' => 'global', 'keyType' => 'String'));
			}

			$row = $this->dbAdapter->fetchOne('select keyValue from Config where keyName="threadingMaxLimit"');
			if ($row == "")
			{
				$result = $this->dbAdapter->insert('Config', array('keyName' => 'threadingMaxLimit', 'keyValue' => '30000', 'section' => 'global', 'keyType' => 'String'));
			}
		}
		catch (Exception $e)
		{

		}

		// Next, add the new thread limit code
		try
		{
			$this->exceptionQuery('ALTER TABLE `UserSettings` ADD `ThreadLimit` tinyint(2) default 6 AFTER `CalDavType`');
		}
		catch (Exception $e)
		{

		}

		try
		{
			// Update the filter_max_bodysize from boolean to string
			$this->exceptionQuery('update Config set keyType="string" where keyName="filter_max_bodysize"');
			$row = $this->dbAdapter->fetchOne('select keyValue from Config where keyName="filter_max_bodysize"');
			if ($row == "1")
			{
				$this->exceptionQuery('update Config set keyValue="50" where keyName="filter_max_bodysize"');
			}
		}
		catch (Exception $e)
		{

		}

		//delete log files as may contain sensitive data, disable logging by default
		@unlink(APP_ROOT . 'log/debug.log');
		@unlink(APP_ROOT . 'log/error.log');
		@unlink(APP_ROOT . 'log/imap.log');

		try
		{
			$this->exceptionQuery('delete from Config where keyName = "debug"');
		}
		catch (Exception $e)
		{

		}
	}

	// ********************************* 6.0.12 UPDATE ***************************************** //
	function _6_0_12()
	{
		// no schema changes
	}

	// ********************************* 6.0.11 UPDATE ***************************************** //
	function _6_0_11()
	{
		try
		{
			// purge duplicate admin users/groups
			$this->exceptionQuery('delete bad_rows.* from AdminGroup as good_rows inner join AdminGroup as bad_rows on bad_rows.Domain = good_rows.Domain and bad_rows.Username = good_rows.Username and bad_rows.id > good_rows.id');
			$this->exceptionQuery('delete bad_rows.* from AdminUsers as good_rows inner join AdminUsers as bad_rows on bad_rows.Username = good_rows.Username and bad_rows.Password = good_rows.Password and bad_rows.BrandDomain = good_rows.BrandDomain and bad_rows.id > good_rows.id');
		}
		catch (Exception $e)
		{

		} //ignore if didnt exist
	}

	// ********************************* PLACE HOLDER 6.0.10 UPDATE ***************************************** //
	// ********************************* 6.0.9 UPDATE ***************************************** //
	function _6_0_9()
	{
		try
		{
			$this->exceptionQuery('ALTER TABLE `MailRelay` change IPaddress IPaddress varchar(24)');
		}
		catch (Exception $e)
		{

		} //ignore if didnt exist

		$row = $this->dbAdapter->fetchOne('select keyValue from Config where keyName="virus_autoupdate"');
		if ($row == "")
		{
			$result = $this->dbAdapter->insert('Config', array('keyName' => 'virus_autoupdate',
				'keyValue' => '1',
				'section' => 'exim',
				'keyType' => 'String'));
		}
		$row = $this->dbAdapter->fetchOne('select keyValue from Config where keyName="spam_autoupdate"');
		if ($row == "")
		{
			$result = $this->dbAdapter->insert('Config', array('keyName' => 'spam_autoupdate',
				'keyValue' => '1',
				'section' => 'exim',
				'keyType' => 'String'));
		}
	}

	// ********************************* 6.0.8 UPDATE ***************************************** //
	function _6_0_8()
	{
		// insert default caldav type
		try
		{
			$row = $this->dbAdapter->fetchOne('select keyValue from Config where keyName="CalDavType"');
			if ($row == "")
			{
				$this->exceptionQuery('insert into Config (section, keyName, keyValue, keyType) values ("defaultUserSettings", "CalDavType", "at", "String")');
			}
		}
		catch (Exception $e)
		{

		}

		try
		{
			$row = $this->dbAdapter->fetchOne('select keyValue from Config where keyName="session_timeout"');
			if ($row == "")
			{
				$this->exceptionQuery('insert into Config (section, keyName, keyValue, keyType) values ("global", "session_timeout", "120", "String")');
			}
		}
		catch (Exception $e)
		{

		}

		// insert user
		try
		{
			try
			{
				$row = $this->dbAdapter->fetchOne('select CalDavType from UserSettings');
			}
			catch (Exception $e)
			{
				$row = "";
			}
			if ($row == "")
			{
				$this->exceptionQuery('ALTER TABLE UserSettings add CalDavType varchar(2)');
			}
		}
		catch (Exception $e)
		{

		}

		$this->exceptionQuery('update UserSettings set CalDavType = "at" where CalDavType is NULL or CalDavType = ""');
		$this->exceptionQuery('update UserSettings set DefaultView = "3p" where DefaultView is NULL or DefaultView = ""');
		$this->exceptionQuery('update UserSettings set CalDavUrl = "http://localhost:8008/calendars/users/" where CalDavUrl is NULL or CalDavUrl = ""');
	}

	// ********************************* 6.0.7 UPDATE ***************************************** //
	function _6_0_7()
	{
		// insert default mail view value for webadmin
		try
		{
			$row = $this->dbAdapter->fetchOne('select keyValue from Config where keyName="DefaultView"');
			if ($row == "")
			{
				$this->exceptionQuery('insert into Config (section, keyName, keyValue, keyType) values ("defaultUserSettings", "DefaultView", "3p", "String")');
			}
		}
		catch (Exception $e)
		{

		}

		// add user default view
		try
		{
			try
			{
				$row = $this->dbAdapter->fetchOne('select DefaultView from UserSettings');
			}
			catch (Exception $e)
			{
				$row = "";
			}
			if ($row == "")
			{
				$this->exceptionQuery('ALTER TABLE UserSettings add DefaultView varchar(2)');
			}
			$this->exceptionQuery('update UserSettings set DefaultView = "3p" where DefaultView is NULL or DefaultView = ""');
		}
		catch (Exception $e)
		{

		}
	}

	// ********************************* PLACE HOLDER 6.0.6 UPDATE ***************************************** //
	// ********************************* 6.0.5 UPDATE ***************************************** //
	function _6_0_5()
	{
		$this->exceptionQuery('ALTER TABLE `Config` DROP INDEX `section`');
		$this->exceptionQuery('RENAME TABLE `GROUPS` TO `CalGroups`');
		$this->exceptionQuery('RENAME TABLE `CALDAV` TO `CalDav`');
		$this->exceptionQuery('RENAME TABLE `SERVICE` TO `CalDavService`');
		$this->exceptionQuery('RENAME TABLE `ADDRESSES` TO `CalAddresses`');
		$this->exceptionQuery('ALTER TABLE CalDavService CHANGE COLUMN REALM Realm text');
		$this->exceptionQuery('ALTER TABLE CalGroups CHANGE COLUMN SHORT_NAME ShortName varchar(255)');
		$this->exceptionQuery('ALTER TABLE CalGroups CHANGE COLUMN MEMBER_RECORD_TYPE MemberRecordType text');
		$this->exceptionQuery('ALTER TABLE CalGroups CHANGE COLUMN MEMBER_SHORT_NAME MemberShortName text');
		$this->exceptionQuery('ALTER TABLE CalAddresses CHANGE COLUMN ADDRESS Address varchar(255)');
		$this->exceptionQuery('ALTER TABLE CalAddresses CHANGE COLUMN SHORT_NAME ShortName varchar(255)');

		//complile list of missing Abook entries and add them (needed for Admin external account list)
		try
		{
			$AccountUserSessions = $this->dbAdapter->select()->from('UserSession', array('Account'))->query()->fetchAll();
			$AccountAbooks = $this->dbAdapter->select()->from('Abook', array('Account'))->where('Global = 1')->query()->fetchAll();
			$missingAbooks = array();
			foreach ($AccountUserSessions as $AccountUserSession)
			{
				$missing = true;
				foreach ($AccountAbooks as $AccountAbook)
				{
					if ($AccountAbook['Account'] == $AccountUserSession['Account'])
					{
						$missing = false;
						break;
					}
				}
				if ($missing)
				{
					$result = $this->dbAdapter->insert('Abook', array('Account' => $AccountUserSession['Account'],
						'UserEmail' => $AccountUserSession['Account'],
						'DateAdded' => new Zend_Db_Expr('NOW()'),
						'Global' => 1));
				}
			}
		}
		catch (Exception $e)
		{

		} //ignore if didnt exist
		// Fix global "duplicate" Exim/DKIM settings
		$this->exceptionQuery('delete from Config where keyName="dkim_enable" and section="global"');
		$this->exceptionQuery('delete from Config where keyName="dkim_enable_outbound" and section="global"');
		$this->exceptionQuery('delete from Config where keyName="tlssmtp" and section="global"');
		$this->exceptionQuery('delete from Config where keyName="tlssmtp_remote" and section="global"');

		$row = $this->dbAdapter->fetchOne('select keyValue from Config where keyName="groupwareenable"');
		if ($row == "")
		{
			$result = $this->dbAdapter->insert('Config', array('keyName' => 'groupwareenable',
				'keyValue' => 'system',
				'section' => 'global',
				'keyType' => 'String'));
		}

		$row = $this->dbAdapter->fetchOne('select keyValue from Config where keyName="sharedAbook"');
		if ($row == "")
		{
			$result = $this->dbAdapter->insert('Config', array('keyName' => 'sharedAbook',
				'keyValue' => '1',
				'section' => 'global',
				'keyType' => 'String'));
		}
	}
	
	
	// overload update/updateAll function to test for previous
	// updates cli status
	//
	// no cli.version or cli.version == null means previous
	// cli update has completed or was not required
	//
	// if a cli.version exists, user has not run cli update
	// for previous completed update, dont allow update
	public function update($version)
	{
		$result = parent::update($version);

		if($result && $this->updateAttemptFrom !== false)
		{
			// update the cli version indicator - AFTER a successfull update.
			$this->updateConfig('global', 'cli.version', $this->updateAttemptFrom, 'String');
			$this->updateAttemptFrom = false;
		}
		return $result;
	}
	
	public function updateAll()
	{
		$global = Zend_Registry::get('config')->global;
		if(isset($global['cli.version']) && $global['cli.version'] != null)
		{
			throw new Exception("A previous update attempt to " . generateVersionString($global['cli.version'], true) . " has not been completed. Please run the CLI update utility from the command line.");
		}
		$this->updateAttemptFrom = generateVersionString($global['version'], true);
		return parent::updateAll();
	}

	// ****** CLASS DEFINED HERE ****** //
	public function __construct(&$dbAdapter)
	{
		parent::__construct($dbAdapter);
		$this->myKeyname = 'version';
		$this->updateAttemptFrom = false;
	}	
}

