? .DS_Store
? .buildpath
? .cache
? .git
? .project
? .settings
? 301049-you-missed-a-spot_0.patch
? INSTALL.sqlite.txt
? USER_PICTURES_MANAGED.PATCH
? before.sql
? junk
? logs
? includes/dummy_stream_wrapper.inc
? sites/.DS_Store
? sites/all/modules
? sites/default/.DS_Store
? sites/default/files
? sites/default/settings.php
? sites/default/test
Index: includes/file.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/file.inc,v
retrieving revision 1.152
diff -u -p -r1.152 file.inc
--- includes/file.inc	10 Jan 2009 06:09:54 -0000	1.152
+++ includes/file.inc	11 Jan 2009 21:27:58 -0000
@@ -305,7 +305,7 @@ function file_load_multiple($fids = arra
  * @param $fid
  *  A file ID.
  * @return
- *   A file object.
+ *   A file object or FALSE if the fid does not exist.
  *
  * @see hook_file_load()
  * @see file_load_multiple()
@@ -845,8 +845,8 @@ function file_space_used($uid = NULL, $s
  *   destination directory should overwritten. A false value will generate a
  *   new, unique filename in the destination directory.
  * @return
- *   An object containing the file information, or FALSE in the event of an
- *   error.
+ *   An object containing the file information if the upload succeeded, FALSE
+ *   in the event of an error, or NULL if no file was uploaded.
  */
 function file_save_upload($source, $validators = array(), $destination = FALSE, $replace = FILE_EXISTS_RENAME) {
   global $user;
@@ -859,9 +859,10 @@ function file_save_upload($source, $vali
   }
 
   // Make sure there's an upload to process.
-  if (!isset($_FILES['files']['name'][$source])) {
-    return FALSE;
+  if (empty($_FILES['files']['name'][$source])) {
+    return NULL;
   }
+dvm($_FILES);
 
   // Check for file upload errors and return FALSE if a lower level system
   // error occurred. For a complete list of errors:
Index: modules/user/user.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.install,v
retrieving revision 1.16
diff -u -p -r1.16 user.install
--- modules/user/user.install	8 Jan 2009 08:42:13 -0000	1.16
+++ modules/user/user.install	11 Jan 2009 21:27:58 -0000
@@ -169,12 +169,11 @@ function user_schema() {
         'default' => '',
         'description' => "User's default language.",
       ),
-      'picture' => array(
-        'type' => 'varchar',
-        'length' => 255,
+      'picture_fid' => array(
+        'type' => 'int',
         'not null' => TRUE,
-        'default' => '',
-        'description' => "Path to the user's uploaded picture.",
+        'default' => 0,
+        'description' => "Foriegn key: {files}.fid of user's picture.",
       ),
       'init' => array(
         'type' => 'varchar',
@@ -388,6 +387,81 @@ function user_update_7003() {
 }
 
 /**
+ * Add the user's pictures to the {files} table and make them managed files.
+ */
+function user_update_7004(&$sandbox) {
+  $ret = array();
+
+  if (!isset($sandbox['progress'])) {
+    // Check that the field hasn't been updated in an aborted run of this
+    // update.
+    if (!db_column_exists('users', 'picture_fid')) {
+      // Add a new field for the fid.
+      $picture_fid_field = array(
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => t("Foriegn key: {files}.fid of user's picture."),
+      );
+      db_add_field($ret, 'users', 'picture_fid', $picture_fid_field);
+    }
+
+    // Initialize batch update information.
+    $sandbox['progress'] = 0;
+    $sandbox['last_user_processed'] = -1;
+    $sandbox['max'] = db_query("SELECT COUNT(DISTINCT picture) FROM {users} WHERE picture <> '' AND picture IS NOT NULL")->fetchField();
+  }
+
+  // As a batch operation move the photos into the {files} table and update the
+  // {user} records.
+  $limit = 1; // TODO: starting this at a low number for testing
+  $result = db_query_range("SELECT uid, picture FROM {users} WHERE uid > %d AND picture <> '' AND picture IS NOT NULL ORDER BY uid", $sandbox['last_user_processed'], 0, $limit);
+  foreach ($result as $user) {
+    // Don't bother adding files that don't exist.
+    if (!file_exists($user->picture)) {
+      continue;
+    }
+
+    // Check if the file already exists.
+    $files = file_load_multiple(array(), array('filepath' => $user->picture));
+    if (count($files)) {
+      $file = reset($files);
+    }
+    else {
+      // Create a file object.
+      $file = new stdClass();
+      $file->filepath = $user->picture;
+      $file->filename = basename($file->filepath);
+      $file->filemime = file_get_mimetype($file->filepath);
+      $file->uid      = 1;
+      $file->status   = FILE_STATUS_PERMANENT;
+      $file = file_save($file);
+    }
+
+    db_update('users')
+      ->fields(array('picture_fid' => $file->fid))
+      ->condition('uid', $user->uid)
+      ->execute();
+
+    // Update our progress information for the batch update.
+    $sandbox['progress']++;
+    $sandbox['last_user_processed'] = $user->uid;
+  }
+
+  // Indicate our current progress to the batch update system.
+  if ($sandbox['progress'] < $sandbox['max']) {
+    $ret['#finished'] = $sandbox['progress'] / $sandbox['max'];
+  }
+
+  // If we're finished, remove the old field.
+  if (isset($ret['#finished']) && $ret['#finished'] == 1) {
+    db_drop_field($ret, 'users', 'picture');
+  }
+
+  return $ret;
+}
+
+/**
  * @} End of "defgroup user-updates-6.x-to-7.x"
  * The next series of updates should start at 8000.
  */
Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.953
diff -u -p -r1.953 user.module
--- modules/user/user.module	8 Jan 2009 08:42:13 -0000	1.953
+++ modules/user/user.module	11 Jan 2009 21:27:58 -0000
@@ -186,6 +186,14 @@ function user_load($array = array()) {
     while ($role = db_fetch_object($result)) {
       $user->roles[$role->rid] = $role->name;
     }
+
+    if ($user->picture_fid && ($file = file_load($user->picture_fid))) {
+      $user->picture = $file;
+    }
+    else {
+      $user->picture = NULL;
+    }
+
     user_module_invoke('load', $array, $user);
   }
   else {
@@ -233,6 +241,13 @@ function user_save($account, $edit = arr
     unset($edit['pass']);
   }
 
+
+  // Move the fid into the object's field and remove the picture so it doesn't
+  //end up serialized.
+  $picture = empty($edit['picture']);
+  $edit['picture_fid'] = empty($picture->fid) ? NULL : $picture->fid;
+  unset($edit['picture']);
+
   if (is_object($account) && $account->uid) {
     user_module_invoke('update', $edit, $account, $category);
     $data = unserialize(db_result(db_query('SELECT data FROM {users} WHERE uid = %d', $account->uid)));
@@ -350,6 +365,25 @@ function user_save($account, $edit = arr
     $user = user_load(array('uid' => $edit['uid']));
   }
 
+  // Finish up with the user's picture.
+  if ($edit['picture_fid']) {
+    // If the picture is a temporary file move it to its final location and make it permanent.
+    if ($picture->status & FILE_STATUS_PERMANENT == 0) {
+      $info = image_get_info($picture->filepath);
+      $destination = file_create_path(variable_get('user_picture_path', 'pictures') . '/picture-' . $edit['uid'] . '.' . $info['extension']);
+      if ($picture = file_move($picture, $destination, FILE_EXISTS_REPLACE)) {
+        $picture->status |= FILE_STATUS_PERMANENT;
+        $edit['picture'] = file_save($picture);
+      }
+    }
+  }
+
+  // If the picture changed or unset, remove the old one.
+  if (isset($account->picture->fid) && ($edit['picture_fid'] != $account->picture->fid)) {
+    file_delete($account->picture);
+  }
+
+
   return $user;
 }
 
@@ -405,23 +439,14 @@ function user_validate_picture(&$form, &
     'file_validate_image_resolution' => array(variable_get('user_picture_dimensions', '85x85')),
     'file_validate_size' => array(variable_get('user_picture_file_size', '30') * 1024),
   );
-  if ($file = file_save_upload('picture_upload', $validators)) {
-    // Remove the old picture.
-    if (isset($form_state['values']['_account']->picture) && file_exists($form_state['values']['_account']->picture)) {
-      file_unmanaged_delete($form_state['values']['_account']->picture);
-    }
 
-    // The image was saved using file_save_upload() and was added to the
-    // files table as a temporary file. We'll make a copy and let the garbage
-    // collector delete the original upload.
-    $info = image_get_info($file->filepath);
-    $destination = file_create_path(variable_get('user_picture_path', 'pictures') . '/picture-' . $form['#uid'] . '.' . $info['extension']);
-    if ($filepath = file_unmanaged_copy($file->filepath, $destination, FILE_EXISTS_REPLACE)) {
-      $form_state['values']['picture'] = $filepath;
-    }
-    else {
-      form_set_error('picture_upload', t("Failed to upload the picture image; the %directory directory doesn't exist or is not writable.", array('%directory' => variable_get('user_picture_path', 'pictures'))));
-    }
+  // Save the file as a temporary file.
+  $file = file_save_upload('picture_upload', $validators);
+  if ($file === FALSE) {
+    form_set_error('picture_upload', t("Failed to upload the picture image; the %directory directory doesn't exist or is not writable.", array('%directory' => variable_get('user_picture_path', 'pictures'))));
+  }
+  elseif ($file !== NULL) {
+    $form_state['values']['picture'] = $file;
   }
 }
 
@@ -604,14 +629,37 @@ function user_perm() {
  *
  * Ensure that user pictures (avatars) are always downloadable.
  */
-function user_file_download($file) {
-  if (strpos($file, variable_get('user_picture_path', 'pictures') . '/picture-') === 0) {
-    $info = image_get_info(file_create_path($file));
+function user_file_download($filepath) {
+  if (strpos($filepath, variable_get('user_picture_path', 'pictures') . '/picture-') === 0) {
+    $info = image_get_info(file_create_path($filepath));
     return array('Content-type: ' . $info['mime_type']);
   }
 }
 
 /**
+ * Implementation of hook_file_references().
+ */
+function user_file_references($file) {
+  // If upload.module is still using a file, do not let other modules delete it.
+  $count = db_query('SELECT COUNT(*) FROM {users} WHERE picture_fid = :fid', array(':fid' => $file->fid))->fetchField();
+  if ($count) {
+    // Return the name of the module and how many references it has to the file.
+    return array('user' => $count);
+  }
+}
+
+/**
+ * Implementatin of hook_file_delete().
+ */
+function user_file_delete($file) {
+  // Remove any references to the file.
+  db_update('users')
+      ->fields(array('picture_fid' => NULL))
+      ->condition('picture_fid', $file->fid)
+      ->execute();
+}
+
+/**
  * Implementation of hook_search().
  */
 function user_search($op = 'search', $keys = NULL, $skip_access_check = FALSE) {
@@ -688,20 +736,47 @@ function user_user_form(&$edit, &$accoun
 }
 
 /**
- * Implementation of hook_user_validate.
+ * Implementation of hook_user_validate().
  */
 function user_user_validate(&$edit, &$account, $category = NULL) {
   if ($category == 'account') {
-    return _user_edit_validate($account, $edit);
+    $uid = isset($account->uid) ? $account->uid : FALSE;
+    // Validate the username when: new user account; or user is editing own account and can change username; or an admin user.
+    if (!$uid || ($GLOBALS['user']->uid == $uid && user_access('change own username')) || user_access('administer users')) {
+      if ($error = user_validate_name($edit['name'])) {
+        form_set_error('name', $error);
+      }
+      elseif (db_result(db_query("SELECT COUNT(*) FROM {users} WHERE uid != %d AND LOWER(name) = LOWER('%s')", $uid, $edit['name'])) > 0) {
+        form_set_error('name', t('The name %name is already taken.', array('%name' => $edit['name'])));
+      }
+    }
+
+    // Validate the e-mail address:
+    if ($error = user_validate_mail($edit['mail'])) {
+      form_set_error('mail', $error);
+    }
+    elseif (db_result(db_query("SELECT COUNT(*) FROM {users} WHERE uid != %d AND LOWER(mail) = LOWER('%s')", $uid, $edit['mail'])) > 0) {
+      form_set_error('mail', t('The e-mail address %email is already registered. <a href="@password">Have you forgotten your password?</a>', array('%email' => $edit['mail'], '@password' => url('user/password'))));
+    }
   }
 }
 
 /**
- * Implementation of hook_user_submit.
+ * Implementation of hook_user_submit().
  */
 function user_user_submit(&$edit, &$account, $category = NULL) {
   if ($category == 'account') {
-    return _user_edit_submit($account, $edit);
+    // Delete picture if requested, and if no replacement picture was given.
+dsm('user_user_submit');
+dsm($edit);
+    if (!empty($edit['picture_delete']) && !empty($user->picture)) {
+      $edit['picture'] = NULL;
+    }
+    unset($edit['picture_delete']);
+    if (isset($edit['roles'])) {
+      $edit['roles'] = array_filter($edit['roles']);
+    }
+dsm($edit);
   }
 }
 
@@ -888,16 +963,16 @@ function template_preprocess_user_pictur
   $variables['picture'] = '';
   if (variable_get('user_pictures', 0)) {
     $account = $variables['account'];
-    if (!empty($account->picture) && file_exists($account->picture)) {
-      $picture = file_create_url($account->picture);
+    if (!empty($account->picture->filepath)) {
+      $filepath = file_create_url($account->picture->filepath);
     }
     elseif (variable_get('user_picture_default', '')) {
-      $picture = variable_get('user_picture_default', '');
+      $filepath = variable_get('user_picture_default', '');
     }
 
-    if (isset($picture)) {
+    if (isset($filepath)) {
       $alt = t("@user's picture", array('@user' => $account->name ? $account->name : variable_get('anonymous', t('Anonymous'))));
-      $variables['picture'] = theme('image', $picture, $alt, $alt, '', FALSE);
+      $variables['picture'] = theme('image', $filepath, $alt, $alt, '', FALSE);
       if (!empty($account->uid) && user_access('access user profiles')) {
         $attributes = array('attributes' => array('title' => t('View user profile.')), 'html' => TRUE);
         $variables['picture'] = l($variables['picture'], "user/$account->uid", $attributes);
@@ -1583,13 +1658,12 @@ function user_edit_form(&$form_state, $u
   // Picture/avatar:
   if (variable_get('user_pictures', 0) && !$register) {
     $form['picture'] = array('#type' => 'fieldset', '#title' => t('Picture'), '#weight' => 1);
-    $picture = theme('user_picture', (object)$edit);
     if ($edit['picture']) {
-      $form['picture']['current_picture'] = array('#markup' => $picture);
+      $form['picture']['current_picture'] = array('#markup' => theme('user_picture', (object)$edit));
       $form['picture']['picture_delete'] = array('#type' => 'checkbox', '#title' => t('Delete picture'), '#description' => t('Check this box to delete your current picture.'));
     }
     else {
-      $form['picture']['picture_delete'] = array('#type' => 'hidden');
+      $form['picture']['picture_delete'] = array('#type' => 'value');
     }
     $form['picture']['picture_upload'] = array('#type' => 'file', '#title' => t('Upload picture'), '#size' => 48, '#description' => t('Your virtual face or picture. Maximum dimensions are %dimensions and the maximum size is %size kB.', array('%dimensions' => variable_get('user_picture_dimensions', '85x85'), '%size' => variable_get('user_picture_file_size', '30'))) . ' ' . variable_get('user_picture_guidelines', ''));
     $form['#validate'][] = 'user_validate_picture';
@@ -1599,40 +1673,6 @@ function user_edit_form(&$form_state, $u
   return $form;
 }
 
-function _user_edit_validate($account, &$edit) {
-  $uid = isset($account->uid) ? $account->uid : FALSE;
-  // Validate the username when: new user account; or user is editing own account and can change username; or an admin user.
-  if (!$uid || ($GLOBALS['user']->uid == $uid && user_access('change own username')) || user_access('administer users')) {
-    if ($error = user_validate_name($edit['name'])) {
-      form_set_error('name', $error);
-    }
-    elseif (db_result(db_query("SELECT COUNT(*) FROM {users} WHERE uid != %d AND LOWER(name) = LOWER('%s')", $uid, $edit['name'])) > 0) {
-      form_set_error('name', t('The name %name is already taken.', array('%name' => $edit['name'])));
-    }
-  }
-
-  // Validate the e-mail address:
-  if ($error = user_validate_mail($edit['mail'])) {
-    form_set_error('mail', $error);
-  }
-  elseif (db_result(db_query("SELECT COUNT(*) FROM {users} WHERE uid != %d AND LOWER(mail) = LOWER('%s')", $uid, $edit['mail'])) > 0) {
-    form_set_error('mail', t('The e-mail address %email is already registered. <a href="@password">Have you forgotten your password?</a>', array('%email' => $edit['mail'], '@password' => url('user/password'))));
-  }
-}
-
-function _user_edit_submit($account, &$edit) {
-  // Delete picture if requested, and if no replacement picture was given.
-  if (!empty($edit['picture_delete'])) {
-    if ($account->picture && file_exists($account->picture)) {
-      file_unmanaged_delete($account->picture);
-    }
-    $edit['picture'] = '';
-  }
-  if (isset($edit['roles'])) {
-    $edit['roles'] = array_filter($edit['roles']);
-  }
-}
-
 /**
  * Cancel a user account.
  *
