Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.710
diff -u -F^f -r1.710 common.inc
--- includes/common.inc	4 Nov 2007 21:24:09 -0000	1.710
+++ includes/common.inc	9 Nov 2007 15:38:00 -0000
@@ -3165,10 +3165,22 @@ function drupal_write_record($table, &$o
       if (empty($info['serialize'])) {
         $values[] = $object->$field;
       }
-      else {
+      elseif (!empty($object->$field)) {
         $values[] = serialize($object->$field);
       }
+      else {
+        $values[] = '';
+      }
+    }
+  }
+
+  if (empty($fields)) {
+    // No changes requested. 
+    // If we began with an array, convert back so we don't surprise the caller.
+    if ($array) {
+      $object = (array)$object;
     }
+    return;
   }
 
   // Build the SQL.
Index: modules/profile/profile.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/profile/profile.module,v
retrieving revision 1.222
diff -u -F^f -r1.222 profile.module
--- modules/profile/profile.module	24 Oct 2007 13:27:12 -0000	1.222
+++ modules/profile/profile.module	9 Nov 2007 15:38:00 -0000
@@ -344,7 +344,8 @@ function profile_field_form_validate($fo
     form_set_error('name', t('The specified form name contains one or more illegal characters. Spaces or any other special characters except dash (-) and underscore (_) are not allowed.'));
   }
 
-  if (in_array($form_state['values']['name'], user_fields())) {
+  $user_fields = drupal_get_schema('users');
+  if (in_array($form_state['values']['name'], array_keys($user_fields['fields']))) {
     form_set_error('name', t('The specified form name is reserved for use by Drupal.'));
   }
   // Validate the category:
Index: modules/user/user.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.install,v
retrieving revision 1.3
diff -u -F^f -r1.3 user.install
--- modules/user/user.install	4 Nov 2007 14:33:07 -0000	1.3
+++ modules/user/user.install	9 Nov 2007 15:38:00 -0000
@@ -247,6 +247,7 @@ function user_schema() {
         'type' => 'text',
         'not null' => FALSE,
         'size' => 'big',
+        'serialize' => TRUE,
         'description' => t('A serialized array of name value pairs that are related to the user. Any form values posted during user edit are stored and are loaded into the $user object during user_load(). Use of this field is discouraged and it will likely disappear in a future version of Drupal.'),
       ),
     ),
Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.862
diff -u -F^f -r1.862 user.module
--- modules/user/user.module	6 Nov 2007 12:20:14 -0000	1.862
+++ modules/user/user.module	9 Nov 2007 15:38:01 -0000
@@ -197,43 +197,43 @@ function user_load($array = array()) {
  *   (optional) The category for storing profile information in.
  */
 function user_save($account, $array = array(), $category = 'account') {
-  // Dynamically compose a SQL query:
-  $user_fields = user_fields();
+  $fields = drupal_get_schema('users');
+  $user_fields = array_keys($fields['fields']);
+  
+  if (!empty($array['pass'])) {
+    $array['pass'] = md5($array['pass']);
+  }
+  else {
+    // Avoid overwriting an existing password with a blank password.
+    unset($array['pass']);
+  }
+  
   if (is_object($account) && $account->uid) {
     user_module_invoke('update', $array, $account, $category);
-    $query = '';
     $data = unserialize(db_result(db_query('SELECT data FROM {users} WHERE uid = %d', $account->uid)));
     // Consider users edited by an administrator as logged in, if they haven't
     // already, so anonymous users can view the profile (if allowed).
     if (empty($array['access']) && empty($account->access) && user_access('administer users')) {
       $array['access'] = time();
     }
+    
     foreach ($array as $key => $value) {
-      if ($key == 'pass' && !empty($value)) {
-        $query .= "$key = '%s', ";
-        $v[] = md5($value);
-      }
-      else if ((substr($key, 0, 4) !== 'auth') && ($key != 'pass')) {
-        if (in_array($key, $user_fields)) {
-          // Save standard fields
-          $query .= "$key = '%s', ";
-          $v[] = $value;
+      // Fields that don't pertain to the users, users_roles, or authmap tables are automatically serialized
+      // into the users.data column. Authmap fields always begin with 'auth'.
+      if ($key != 'roles' && substr($key, 0, 4) !== 'auth' && !in_array($key, $user_fields)) {
+        if ($value === NULL) {
+          unset($data[$key]);
         }
-        else if ($key != 'roles') {
-          // Roles is a special case: it used below.
-          if ($value === NULL) {
-            unset($data[$key]);
-          }
-          else {
-            $data[$key] = $value;
-          }
+        else {
+          $data[$key] = $value;
         }
-      }
+      }      
     }
-    $query .= "data = '%s' ";
-    $v[] = serialize($data);
-
-    db_query("UPDATE {users} SET $query WHERE uid = %d", array_merge($v, array($account->uid)));
+      
+    $array['data'] = $data;
+    $array['uid'] = $account->uid;
+    // Save changes to the users table.
+    drupal_write_record('users', $array, 'uid');
 
     // Reload user roles if provided
     if (isset($array['roles']) && is_array($array['roles'])) {
@@ -280,48 +280,25 @@ function user_save($account, $array = ar
       $array['access'] = time();
     }
 
-    // Note, we wait with saving the data column to prevent module-handled
-    // fields from being saved there. We cannot invoke hook_user('insert') here
-    // because we don't have a fully initialized user object yet.
-    foreach ($array as $key => $value) {
-      switch ($key) {
-        case 'pass':
-          $fields[] = $key;
-          $values[] = md5($value);
-          $s[] = "'%s'";
-          break;
-        case 'mode':       case 'sort':     case 'timezone':
-        case 'threshold':  case 'created':  case 'access':
-        case 'login':      case 'status':
-          $fields[] = $key;
-          $values[] = $value;
-          $s[] = "%d";
-          break;
-        default:
-          if (substr($key, 0, 4) !== 'auth' && in_array($key, $user_fields)) {
-            $fields[] = $key;
-            $values[] = $value;
-            $s[] = "'%s'";
-          }
-          break;
-      }
-    }
-    db_query('INSERT INTO {users} ('. implode(', ', $fields) .') VALUES ('. implode(', ', $s) .')', $values);
-    $array['uid'] = db_last_insert_id('users', 'uid');
+    drupal_write_record('users', $array);
 
     // Build the initial user object.
     $user = user_load(array('uid' => $array['uid']));
 
     user_module_invoke('insert', $array, $user, $category);
 
-    // Build and save the serialized data field now
+    // Note, we wait with saving the data column to prevent module-handled
+    // fields from being saved there.
     $data = array();
     foreach ($array as $key => $value) {
       if ((substr($key, 0, 4) !== 'auth') && ($key != 'roles') && (!in_array($key, $user_fields)) && ($value !== NULL)) {
         $data[$key] = $value;
       }
     }
-    db_query("UPDATE {users} SET data = '%s' WHERE uid = %d", serialize($data), $user->uid);
+    if (!empty($data)) {
+      $data_array = array('uid' => $user->uid, 'data' => $data);
+      drupal_write_record('users', $data_array, 'uid');
+    }
 
     // Save user roles (delete just to be safe).
     if (isset($array['roles']) && is_array($array['roles'])) {
@@ -494,23 +471,6 @@ function user_is_blocked($name) {
   return $deny;
 }
 
-function user_fields() {
-  static $fields;
-
-  if (!$fields) {
-    $result = db_query('SELECT * FROM {users} WHERE uid = 1');
-    if ($field = db_fetch_array($result)) {
-      $fields = array_keys($field);
-    }
-    else {
-      // Make sure we return the default fields at least
-      $fields = array('uid', 'name', 'pass', 'mail', 'picture', 'mode', 'sort', 'threshold', 'theme', 'signature', 'created', 'access', 'login', 'status', 'timezone', 'language', 'init', 'data');
-    }
-  }
-
-  return $fields;
-}
-
 /**
  * Implementation of hook_perm().
  */
@@ -2112,7 +2072,7 @@ function user_register_submit($form, &$f
     return;
   }
   //the unset below is needed to prevent these form values from being saved as user data
-  unset($form_state['values']['form_token'], $form_state['values']['submit'], $form_state['values']['op'], $form_state['values']['notify'], $form_state['values']['form_id'], $form_state['values']['affiliates'], $form_state['values']['destination']);
+  unset($form_state['values']['form_token'], $form_state['values']['submit'], $form_state['values']['op'], $form_state['values']['notify'], $form_state['values']['form_id'], $form_state['values']['affiliates'], $form_state['values']['destination'], $form_state['values']['form_build_id']);
 
   $merge_data = array('pass' => $pass, 'init' => $mail, 'roles' => $roles);
   if (!$admin) {
Index: modules/user/user.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.pages.inc,v
retrieving revision 1.3
diff -u -F^f -r1.3 user.pages.inc
--- modules/user/user.pages.inc	27 Oct 2007 14:01:12 -0000	1.3
+++ modules/user/user.pages.inc	9 Nov 2007 15:38:01 -0000
@@ -274,7 +274,7 @@ function user_profile_form_validate($for
 function user_profile_form_submit($form, &$form_state) {
   $account = $form_state['values']['_account'];
   $category = $form_state['values']['_category'];
-  unset($form_state['values']['_account'], $form_state['values']['op'], $form_state['values']['submit'], $form_state['values']['delete'], $form_state['values']['form_token'], $form_state['values']['form_id'], $form_state['values']['_category']);
+  unset($form_state['values']['_account'], $form_state['values']['op'], $form_state['values']['submit'], $form_state['values']['delete'], $form_state['values']['form_token'], $form_state['values']['form_id'], $form_state['values']['_category'], $form_state['values']['form_build_id']);
   user_module_invoke('submit', $form_state['values'], $account, $category);
   user_save($account, $form_state['values'], $category);
 
@@ -340,7 +340,7 @@ function user_edit_validate($form, &$for
 function user_edit_submit($form, &$form_state) {
   $account = $form_state['values']['_account'];
   $category = $form_state['values']['_category'];
-  unset($form_state['values']['_account'], $form_state['values']['op'], $form_state['values']['submit'], $form_state['values']['delete'], $form_state['values']['form_token'], $form_state['values']['form_id'], $form_state['values']['_category']);
+  unset($form_state['values']['_account'], $form_state['values']['op'], $form_state['values']['submit'], $form_state['values']['delete'], $form_state['values']['form_token'], $form_state['values']['form_id'], $form_state['values']['_category'], $form_state['values']['form_build_id']);
   user_module_invoke('submit', $form_state['values'], $account, $category);
   user_save($account, $form_state['values'], $category);
 
