Index: ./modules/system/system.install =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.install,v retrieving revision 1.40 diff -u -p -r1.40 system.install --- ./modules/system/system.install 8 Nov 2006 19:24:11 -0000 1.40 +++ ./modules/system/system.install 12 Nov 2006 22:25:52 -0000 @@ -3375,6 +3375,135 @@ function system_update_1014() { return array(); } +function system_update_1015() { + // TODO can the functions CONCAT and MD5 be used on pgsql ? + $ret = array(); + $limit = 50; + + // Multi-part update + if (!isset($_SESSION['system_update_9955'])) { + $_SESSION['system_update_9955'] = 0; + $_SESSION['system_update_9955_max'] = db_result(db_query('SELECT MAX(uid) FROM {users}')); + $_SESSION['system_update_9955_copy_start'] = 0; + $_SESSION['system_update_9955_check_start'] = 0; + $_SESSION['system_update_9955_count_old'] = 0; + $_SESSION['system_update_9955_count_salted'] = 0; + $_SESSION['system_update_9955_ret'] = array(); + + if (db_table_exists('users_new')) { + $ret[] = update_sql('DROP TABLE {users_new}'); + } + switch ($GLOBALS['db_type']) { + case 'mysql': + case 'mysqli': + $ret[] = update_sql("CREATE TABLE {users_new} ( + uid int unsigned NOT NULL default '0', + name varchar(60) NOT NULL default '', + pass varchar(32) NOT NULL default '', + salt varchar(8) NOT NULL default '', + mail varchar(64) default '', + mode tinyint NOT NULL default '0', + sort tinyint default '0', + threshold tinyint default '0', + theme varchar(255) NOT NULL default '', + signature varchar(255) NOT NULL default '', + created int NOT NULL default '0', + access int NOT NULL default '0', + login int NOT NULL default '0', + status tinyint NOT NULL default '0', + timezone varchar(8) default NULL, + language varchar(12) NOT NULL default '', + picture varchar(255) NOT NULL DEFAULT '', + init varchar(64) default '', + data longtext, + PRIMARY KEY (uid), + UNIQUE KEY name (name), + KEY access (access) + ) /*!40100 DEFAULT CHARACTER SET UTF8 */ "); + break; + + case 'pgsql': + $ret[] = update_sql("CREATE TABLE {users_new} ( + uid serial CHECK (uid >= 0), + name varchar(60) NOT NULL default '', + pass varchar(32) NOT NULL default '', + salt varchar(8) NOT NULL default '', + mail varchar(64) default '', + mode smallint NOT NULL default '0', + sort smallint default '0', + threshold smallint default '0', + theme varchar(255) NOT NULL default '', + signature varchar(255) NOT NULL default '', + created int NOT NULL default '0', + access int NOT NULL default '0', + login int NOT NULL default '0', + status smallint NOT NULL default '0', + timezone varchar(8) default NULL, + language varchar(12) NOT NULL default '', + picture varchar(255) NOT NULL DEFAULT '', + init varchar(64) default '', + data text, + PRIMARY KEY (uid), + UNIQUE (name) + )"); + break; + } + // uid 0 is the anonymous user (without any password or salt) + $ret[] = update_sql("INSERT INTO {users_new} (uid,name,mail) VALUES(0,'','')"); + } + else { + $ret = $_SESSION['system_update_9955_ret']; + } + + if ($_SESSION['system_update_9955_copy_start'] <= $_SESSION['system_update_9955_max']) { + $range_end = $_SESSION['system_update_9955_copy_start'] + $limit; + db_query("INSERT INTO {users_new} (uid, name, pass, salt, mail, mode, sort, threshold, theme, signature, created, access, login, status, timezone, language, picture, init, data) SELECT uid, name, MD5(CONCAT(SUBSTRING(MD5(created),1,8), pass)), SUBSTRING(MD5(created),1,8), mail, mode, sort, threshold, theme, signature, created, access, login, status, timezone, language, picture, init, data FROM {users} WHERE uid > %d AND uid <= %d", $_SESSION['system_update_9955_copy_start'], $range_end); + $_SESSION['system_update_9955_copy_start'] = $range_end; + $_SESSION['system_update_9955_ret'] = $ret; + // Report percentage finished (make sure we never get 100% in this stage, we go to max 50% here) + return array('#finished' => ($_SESSION['system_update_9955_copy_start'] / ($_SESSION['system_update_9955_max'] + $limit + 1) / 2)); + } + else { + if ($_SESSION['system_update_9955'] == 0) { + // checking the user_new table fase 1: number of rows the same ? + $_SESSION['system_update_9955_count_old'] = db_result(db_query('SELECT COUNT(uid) FROM {users}')); + $count_new = db_result(db_query('SELECT COUNT(uid) FROM {users_new}')); + if ($_SESSION['system_update_9955_count_old'] == $count_new) { + $_SESSION['system_update_9955'] = 1; + } + else { + $ret[] = array('success' => false, 'query' => t('Adding salt to users table failed : not all rows are copied to temporary table user_new.')); + return $ret; + } + } + if ($_SESSION['system_update_9955_check_start'] <= $_SESSION['system_update_9955_max']) { + // checking the user_new table fase 2: all passwords are correctly salted ? + // We have to do this in fases, because it might take too long on big sites + $range_end = $_SESSION['system_update_9955_check_start'] + $limit; + $_SESSION['system_update_9955_count_salted'] += db_result(db_query('SELECT COUNT(n.uid) FROM {users} u, {users_new} n WHERE n.pass = MD5(CONCAT(n.salt, u.pass)) AND u.uid > %d AND u.uid <= %d', $_SESSION['system_update_9955_check_start'], $range_end)); + $_SESSION['system_update_9955_check_start'] = $range_end; + $_SESSION['system_update_9955_ret'] = $ret; + // Report percentage finished (make sure we never get 100% in this stage) + return array('#finished' => (0.50 + ($_SESSION['system_update_9955_check_start'] / ($_SESSION['system_update_9955_max'] + $limit + 1) / 2))); + } + // uid = 0 is excluded from this test (it has no password) + if ($_SESSION['system_update_9955_count_old'] == ($_SESSION['system_update_9955_count_salted'] + 1)) { + $ret[] = update_sql('DROP TABLE {users}'); + $ret[] = update_sql('RENAME TABLE {users_new} to {users}'); + unset($_SESSION['system_update_9955']); + unset($_SESSION['system_update_9955_copy_start']); + unset($_SESSION['system_update_9955_max']); + unset($_SESSION['system_update_9955_check_start']); + unset($_SESSION['system_update_9955_ret']); + return $ret; + } + else { + $ret[] = array('success' => false, 'query' => t('Adding salt to users table failed : not all passwords are correctly salted in the temporary table user_new.')); + return $ret; + } + } +} + /** * @} End of "defgroup updates-4.7-to-x.x" * The next series of updates should start at 2000.