Index: config-dist.php =================================================================== RCS file: /cvsroot/moodle/moodle/config-dist.php,v retrieving revision 1.103.2.11 diff -u -r1.103.2.11 config-dist.php --- config-dist.php 17 Nov 2009 16:31:20 -0000 1.103.2.11 +++ config-dist.php 28 Dec 2009 00:54:49 -0000 @@ -176,6 +176,21 @@ // shared out from your site/institution! // $CFG->includeuserpasswordsinbackup = true; // +// Completely disable user creation on restore, bypassing any right granted +// via roles/capabilities. By enabling this setting any restore process +// requiring users to be created will be stopped before any further action. +// $CFG->disableusercreationonrestore = true; +// +// Modify the restore process in order to force the "user checks" to assume +// that the backup was originated in a different site so detection of matching +// users is performed with some different (more "relaxed") rules. *Only* useful +// if the backup file has been generated with Moodle < 1.9.4 and the site has +// been rebuilt from scratch using backup files (not the best way, btw). If you +// are getting user conflicts on restore, try to restore the backup to a different +// site, backup it again and then restore on target server instead of enabling this +// setting permanently! +// $CFG->forcedifferentsitecheckingusersonrestore = true; +// // Prevent stats processing and hide the GUI // $CFG->disablestatsprocessing = true; // Index: version.php =================================================================== RCS file: /cvsroot/moodle/moodle/version.php,v retrieving revision 1.563.2.754 diff -u -r1.563.2.754 version.php --- version.php 28 Dec 2009 00:35:53 -0000 1.563.2.754 +++ version.php 28 Dec 2009 00:54:49 -0000 @@ -6,7 +6,7 @@ // This is compared against the values stored in the database to determine // whether upgrades should be performed (see lib/db/*.php) - $version = 2007101570; // YYYYMMDD = date of the 1.9 branch (don't change) + $version = 2007101570.01; // YYYYMMDD = date of the 1.9 branch (don't change) // X = release number 1.9.[0,1,2,3,4,5...] // Y.YY = micro-increments between releases Index: backup/restorelib.php =================================================================== RCS file: /cvsroot/moodle/moodle/backup/restorelib.php,v retrieving revision 1.283.2.91 diff -u -r1.283.2.91 restorelib.php --- backup/restorelib.php 18 Dec 2009 18:47:14 -0000 1.283.2.91 +++ backup/restorelib.php 28 Dec 2009 00:54:57 -0000 @@ -746,7 +746,7 @@ } // Handle checks from same site backups - if (backup_is_same_site($restore)) { + if (backup_is_same_site($restore) && empty($CFG->forcedifferentsitecheckingusersonrestore)) { // 1A - If match by id and username and mnethost => ok, return target user if ($rec = get_record('user', 'id', $user->id, 'username', addslashes($user->username), 'mnethostid', $user->mnethostid)) { @@ -766,7 +766,7 @@ AND mnethostid = $user->mnethostid AND deleted = 1 AND ( - username LIKE '$user->email.%' + username LIKE '".addslashes($user->email).".%' OR ( ".sql_isnotempty('user', 'email', false, false)." AND email = '".md5($user->username)."' @@ -787,7 +787,7 @@ FROM {$CFG->prefix}user u WHERE id = $user->id AND mnethostid = $user->mnethostid - AND email = '$trimemail'")) { + AND email = '".addslashes($trimemail)."'")) { return $rec; // Matching user, deleted in backup file found, return it } } @@ -806,10 +806,10 @@ // (email or non-zero firstaccess) => ok, return target user if ($rec = get_record_sql("SELECT * FROM {$CFG->prefix}user u - WHERE username = '$user->username' + WHERE username = '".addslashes($user->username)."' AND mnethostid = $user->mnethostid AND ( - email = '$user->email' + email = '".addslashes($user->email)."' OR ( firstaccess != 0 AND firstaccess = $user->firstaccess @@ -832,7 +832,7 @@ AND ".sql_isnotempty('user', 'email', false, false)." AND email = '".md5($user->username)."' AND ( - username LIKE '$user->email.%' + username LIKE '".addslashes($user->email).".%' OR ( firstaccess != 0 AND firstaccess = $user->firstaccess @@ -849,7 +849,7 @@ FROM {$CFG->prefix}user u WHERE mnethostid = $user->mnethostid AND deleted = 1 - AND username LIKE '$user->email.%' + AND username LIKE '".addslashes($user->email).".%' AND firstaccess != 0 AND firstaccess = $user->firstaccess")) { return $rec; // Matching user found, return it @@ -866,7 +866,7 @@ if ($rec = get_record_sql("SELECT * FROM {$CFG->prefix}user u WHERE mnethostid = $user->mnethostid - AND email = '$trimemail' + AND email = '".addslashes($trimemail)."' AND firstaccess != 0 AND firstaccess = $user->firstaccess")) { return $rec; // Matching user, deleted in backup file found, return it @@ -876,10 +876,10 @@ // 2D - If match by username and mnethost and not by (email or non-zero firstaccess) => conflict, return false if ($rec = get_record_sql("SELECT * FROM {$CFG->prefix}user u - WHERE username = '$user->username' + WHERE username = '".addslashes($user->username)."' AND mnethostid = $user->mnethostid AND NOT ( - email = '$user->email' + email = '".addslashes($user->email)."' OR ( firstaccess != 0 AND firstaccess = $user->firstaccess @@ -947,7 +947,7 @@ $user = $rec->info; // Find the correct mnethostid for user before performing any further check - if (empty($user->mnethosturl) || $user->mnethosturl===$CFG->wwwroot) { + if (empty($user->mnethosturl) || $user->mnethosturl === $CFG->wwwroot) { $user->mnethostid = $CFG->mnet_localhost_id; } else { // fast url-to-id lookups @@ -962,13 +962,18 @@ $usercheck = restore_check_user($restore, $user); if (is_object($usercheck)) { // No problem, we have found one user in DB to be mapped to + // Annotate it, for later process by restore_create_users(). Set new_id to mapping user->id + backup_putid($restore->backup_unique_code, 'user', $userid, $usercheck->id, $user); } else if ($usercheck === false) { // Found conflict, report it as problem $problems[] = get_string('restoreuserconflict', '', $user->username); $status = false; } else if ($usercheck === true) { // User needs to be created, check if we are able - if (!$cancreateuser) { // Cannot create, report as problem + if ($cancreateuser) { // Can create user, annotate it, for later process by restore_create_users(). Set new_id to 0 + backup_putid($restore->backup_unique_code, 'user', $userid, 0, $user); + + } else { // Cannot create user, report it as problem $problems[] = get_string('restorecannotcreateuser', '', $user->username); $status = false; @@ -2766,25 +2771,17 @@ $authcache = array(); // Cache to get some bits from authentication plugins $status = true; - //Check it exists - if (!file_exists($xml_file)) { - $status = false; - } - //Get info from xml - if ($status) { - //info will contain the old_id of every user - //in backup_ids->info will be the real info (serialized) - $info = restore_read_xml_users($restore,$xml_file); - } - //Now, get evey user_id from $info and user data from $backup_ids - //and create the necessary db structures + // Users have already been checked by restore_precheck_users() so they are loaded + // in backup_ids table. They don't need to be loaded (parsed) from XML again. Also, note + // the same function has performed the needed modifications in the $user->mnethostid field + // so we don't need to do it again here at all. Just some checks. - if (!empty($info->users)) { + // Get users ids from backup_ids table + $userids = get_fieldset_select('backup_ids', 'old_id', "backup_code = $restore->backup_unique_code AND table_name = 'user'"); - /// Grab mnethosts keyed by wwwroot, to map to id - $mnethosts = get_records('mnet_host', '', '', - 'wwwroot', 'wwwroot, id'); + // Have users to process, proceed with them + if (!empty($userids)) { /// Get languages for quick search later $languages = get_list_of_languages(); @@ -2794,9 +2791,22 @@ /// Init trailing messages $messages = array(); - foreach ($info->users as $userid) { - $rec = backup_getid($restore->backup_unique_code,"user",$userid); - $user = $rec->info; + foreach ($userids as $userid) { + // Defaults + $user_exists = false; // By default user does not exist + $newid = null; // By default, there is not newid + + // Get record from backup_ids + $useridsdbrec = backup_getid($restore->backup_unique_code, 'user', $userid); + + // Based in restore_precheck_users() calculations, if the user exists + // new_id must contain the id of the matching user + if (!empty($useridsdbrec->new_id)) { + $user_exists = true; + $newid = $useridsdbrec->new_id; + } + + $user = $useridsdbrec->info; foreach (array_keys(get_object_vars($user)) as $field) { if (!is_array($user->$field)) { $user->$field = backup_todb($user->$field); @@ -2844,31 +2854,12 @@ //Has role teacher or student or needed $is_course_user = ($is_teacher or $is_student or $is_needed); - // in case we are restoring to same server, look for user by id and username - // it should return record always, but in sites rebuilt from scratch - // and being reconstructed using course backups - $user_data = false; - if (backup_is_same_site($restore)) { - $user_data = get_record('user', 'id', $user->id, 'username', addslashes($user->username)); - } - // Only try to perform mnethost/auth modifications if restoring to another server // or if, while restoring to same server, the user doesn't exists yet (rebuilt site) // // So existing user data in same server *won't be modified by restore anymore*, // under any circumpstance. If somehting is wrong with existing data, it's server fault. - if (!backup_is_same_site($restore) || (backup_is_same_site($restore) && !$user_data)) { - //Calculate mnethostid - if (empty($user->mnethosturl) || $user->mnethosturl===$CFG->wwwroot) { - $user->mnethostid = $CFG->mnet_localhost_id; - } else { - // fast url-to-id lookups - if (isset($mnethosts[$user->mnethosturl])) { - $user->mnethostid = $mnethosts[$user->mnethosturl]->id; - } else { - $user->mnethostid = $CFG->mnet_localhost_id; - } - } + if (!backup_is_same_site($restore) || (backup_is_same_site($restore) && !$user_exists)) { //Arriving here, any user with mnet auth and using $CFG->mnet_localhost_id is wrong //as own server cannot be accesed over mnet. Change auth to manual and inform about the switch if ($user->auth == 'mnet' && $user->mnethostid == $CFG->mnet_localhost_id) { @@ -2887,21 +2878,6 @@ } unset($user->mnethosturl); - //To store user->id along all the iteration - $newid=null; - //check if it exists (by username) and get its id - $user_exists = true; - if (!backup_is_same_site($restore) || !$user_data) { /// Restoring to another server, or rebuilding site (failed id& - /// login search above), look for existing user based on fields - $user_data = get_record('user', 'username', addslashes($user->username), 'mnethostid', $user->mnethostid); - } - - if (!$user_data) { - $user_exists = false; - } else { - $newid = $user_data->id; - } - //Flags to see what parts are we going to restore $create_user = true; $create_roles = true; @@ -3182,7 +3158,7 @@ } backup_flush(300); } - } /// End of loop over all the users loaded from xml + } /// End of loop over all the users loaded from backup_ids table /// Inform about all the messages geerated while restoring users if (!defined('RESTORE_SILENTLY')) { @@ -8264,7 +8240,6 @@ // Precheck the users section, detecting various situations that can lead to problems, so // we stop restore before performing any further action - /* if (!defined('RESTORE_SILENTLY')) { echo '