diff --git a/core/includes/common.inc b/core/includes/common.inc
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 55b0b40..e827bc0 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -631,9 +631,9 @@ function block_form_user_profile_form_alter(&$form, &$form_state) {
 /**
  * Implements hook_user_presave().
  */
-function block_user_presave(&$edit, $account) {
-  if (isset($edit['block'])) {
-    $edit['data']['block'] = $edit['block'];
+function block_user_presave($edit) {
+  if (isset($edit->block)) {
+    $edit->data['block'] = $edit->block;
   }
 }
 
diff --git a/core/modules/entity/entity.controller.inc b/core/modules/entity/entity.controller.inc
diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module
diff --git a/core/modules/overlay/overlay.module b/core/modules/overlay/overlay.module
index 5433d3e..293426d 100644
--- a/core/modules/overlay/overlay.module
+++ b/core/modules/overlay/overlay.module
@@ -102,9 +102,9 @@ function overlay_form_user_profile_form_alter(&$form, &$form_state) {
 /**
  * Implements hook_user_presave().
  */
-function overlay_user_presave(&$edit, $account) {
-  if (isset($edit['overlay'])) {
-    $edit['data']['overlay'] = $edit['overlay'];
+function overlay_user_presave($edit) {
+  if (isset($edit->overlay)) {
+    $edit->data['overlay'] = $edit->overlay;
   }
 }
 
diff --git a/core/modules/simpletest/drupal_web_test_case.php b/core/modules/simpletest/drupal_web_test_case.php
index 5c711fb..d23aaaf 100644
--- a/core/modules/simpletest/drupal_web_test_case.php
+++ b/core/modules/simpletest/drupal_web_test_case.php
@@ -1116,7 +1116,9 @@ class DrupalWebTestCase extends DrupalTestCase {
     $edit['pass']   = user_password();
     $edit['status'] = 1;
 
-    $account = user_save(drupal_anonymous_user(), $edit);
+    $account = entity_create('user', $edit);
+
+    $account->save();
 
     $this->assertTrue(!empty($account->uid), t('User created with name %name and pass %pass', array('%name' => $edit['name'], '%pass' => $edit['pass'])), t('User login'));
     if (empty($account->uid)) {
@@ -1220,7 +1222,7 @@ class DrupalWebTestCase extends DrupalTestCase {
    *
    * @see drupalCreateUser()
    */
-  protected function drupalLogin(stdClass $user) {
+  protected function drupalLogin(User $user) {
     if ($this->loggedInUser) {
       $this->drupalLogout();
     }
diff --git a/core/modules/user/user.entity.inc b/core/modules/user/user.entity.inc
index 5549c77..a970e4e 100644
--- a/core/modules/user/user.entity.inc
+++ b/core/modules/user/user.entity.inc
@@ -5,12 +5,131 @@
  */
 
 /**
+ * Defines the user entity class.
+ */
+class User extends Entity {
+
+  /**
+   * The user ID.
+   *
+   * @var integer
+   */
+  public $uid;
+
+  /**
+   * The unique user name.
+   *
+   * @var string
+   */
+  public $name = '';
+
+  /**
+   * The user's password (hashed).
+   *
+   * @var string
+   */
+  public $pass;
+
+  /**
+   * The user's email address.
+   *
+   * @var string
+   */
+  public $mail = '';
+
+  /**
+   * The user's default theme.
+   *
+   * @var string
+   */
+  public $theme;
+
+  /**
+   * The user's signature.
+   *
+   * @var string
+   */
+  public $signature;
+
+  /**
+   * The user's signature format.
+   *
+   * @var string
+   */
+  public $signature_format = NULL;
+
+  /**
+   * The timestamp when the user was created.
+   *
+   * @var integer
+   */
+  public $created = 0;
+
+  /**
+   * The timestamp when the user last accessed the site.
+   *
+   * @var integer
+   */
+  public $access = 0;
+
+  /**
+   * The timestamp when the user lasted logged in.
+   *
+   * @var integer
+   */
+  public $login = 0;
+
+  /**
+   * Whether the user is active(1) or blocked(0).
+   *
+   * @var integer
+   */
+  public $status = 0;
+
+  /**
+   * The user's timezone.
+   *
+   * @var string
+   */
+  public $timezone = NULL;
+
+  /**
+   * The user's default language.
+   *
+   * @var string
+   */
+  public $language = '';
+
+  /**
+   * The fid of the user's picture.
+   *
+   * @var integer
+   */
+  public $picture = 0;
+
+  /**
+   * The email address used for initial account creation.
+   *
+   * @var string
+   */
+  public $init = '';
+
+  /**
+   * The user's roles.
+   *
+   * @var array
+   */
+  public $roles = array();
+
+}
+
+/**
  * Controller class for users.
  *
  * This extends the DrupalDefaultEntityController class, adding required
  * special handling for user objects.
  */
-class UserController extends DrupalDefaultEntityController {
+class UserController extends EntityDatabaseStorageController {
 
   function attachLoad(&$queried_users, $revision_id = FALSE) {
     // Build an array of user picture IDs so that these can be fetched later.
@@ -49,4 +168,139 @@ class UserController extends DrupalDefaultEntityController {
     // hook_user_load().
     parent::attachLoad($queried_users, $revision_id);
   }
+
+  function save(EntityInterface $entity) {
+    $entity->is_new = $entity->isNew();
+    if (empty($entity->uid)) {
+      $entity->uid = db_next_id(db_query('SELECT MAX(uid) FROM {users}')->fetchField());
+    }
+    parent::save($entity);
+  }
+
+  function preSave(EntityInterface $entity) {
+    // Update the user password if it has changed.
+    if ($entity->is_new || $entity->pass != $entity->original->pass) {
+      // Allow alternate password hashing schemes.
+      require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'core/includes/password.inc');
+      $entity->pass = user_hash_password(trim($entity->pass));
+      // Abort if the hashing failed and returned FALSE.
+      if (!$entity->pass) {
+        return FALSE;
+      }
+    }
+
+    if (!$entity->is_new) {
+      // Process picture uploads.
+      if (!empty($entity->picture->fid) && (!isset($entity->original->picture->fid) || $entity->picture->fid != $entity->original->picture->fid)) {
+        $picture = $entity->picture;
+        // If the picture is a temporary file move it to its final location and
+        // make it permanent.
+        if (!$picture->status) {
+          $info = image_get_info($picture->uri);
+          $picture_directory =  file_default_scheme() . '://' . variable_get('user_picture_path', 'pictures');
+
+          // Prepare the pictures directory.
+          file_prepare_directory($picture_directory, FILE_CREATE_DIRECTORY);
+          $destination = file_stream_wrapper_uri_normalize($picture_directory . '/picture-' . $account->uid . '-' . REQUEST_TIME . '.' . $info['extension']);
+
+          // Move the temporary file into the final location.
+          if ($picture = file_move($picture, $destination, FILE_EXISTS_RENAME)) {
+            $picture->status = FILE_STATUS_PERMANENT;
+            $account->picture = file_save($picture);
+            file_usage_add($picture, 'user', 'user', $account->uid);
+          }
+        }
+        // Delete the previous picture if it was deleted or replaced.
+        if (!empty($entity->original->picture->fid)) {
+          file_usage_delete($entity->original->picture, 'user', 'user', $account->uid);
+          file_delete($entity->original->picture);
+        }
+      }
+      $entity->picture = empty($entity->picture->fid) ? 0 : $entity->picture->fid;
+
+      // Do not allow 'uid' to be changed.
+      $entity->uid = $entity->original->uid;
+
+      // If the password changed, delete all open sessions and recreate
+      // the current one.
+      if ($entity->pass != $entity->original->pass) {
+        drupal_session_destroy_uid($entity->uid);
+        if ($entity->uid == $GLOBALS['user']->uid) {
+          drupal_session_regenerate();
+        }
+      }
+
+      // Reload user roles if provided.
+      if ($entity->roles != $entity->original->roles) {
+        db_delete('users_roles')
+          ->condition('uid', $entity->uid)
+          ->execute();
+
+        $query = db_insert('users_roles')->fields(array('uid', 'rid'));
+        foreach (array_keys($entity->roles) as $rid) {
+          if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
+            $query->values(array(
+              'uid' => $entity->uid,
+              'rid' => $rid,
+            ));
+          }
+        }
+        $query->execute();
+      }
+
+      // Delete a blocked user's sessions to kick them if they are online.
+      if ($entity->original->status != $entity->status && $entity->status == 0) {
+        drupal_session_destroy_uid($entity->uid);
+      }
+
+      // Send emails after we have the new user object.
+      if ($entity->status != $entity->original->status) {
+        // The user's status is changing; conditionally send notification email.
+        $op = $entity->status == 1 ? 'status_activated' : 'status_blocked';
+        _user_mail_notify($op, $entity);
+      }
+    }
+    else {
+      // Allow 'created' to be set by the caller.
+      if (!isset($entity->created)) {
+        $entity->created = REQUEST_TIME;
+      }
+
+      // Make sure $account is properly initialized.
+      $entity->roles[DRUPAL_AUTHENTICATED_RID] = 'authenticated user';
+
+      // Save user roles.
+      if (count($entity->roles) > 1) {
+        $query = db_insert('users_roles')->fields(array('uid', 'rid'));
+        foreach (array_keys($entity->roles) as $rid) {
+          if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
+            $query->values(array(
+              'uid' => $entity->uid,
+              'rid' => $rid,
+            ));
+          }
+        }
+        $query->execute();
+      }
+    }
+
+    if (!empty($entity->picture_upload)) {
+      $entity->picture = $entity->picture_upload;
+    }
+    // Delete picture if requested, and if no replacement picture was given.
+    elseif (!empty($entity->picture_delete)) {
+      $entity->picture = NULL;
+    }
+    // Prepare user roles.
+    if (isset($entity->roles)) {
+      $entity->roles = array_filter($entity->roles);
+    }
+
+    // Move account cancellation information into $user->data.
+    foreach (array('user_cancel_method', 'user_cancel_notify') as $key) {
+      if (isset($entity->{$key})) {
+        $entity->data[$key] = $entity->{$key};
+      }
+    }
+  }
 }
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 2dded35..9bba3a3 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -143,7 +143,7 @@ function user_theme() {
  * Implements hook_entity_info().
  */
 function user_entity_info() {
-  $return = array(
+  return array(
     'user' => array(
       'label' => t('User'),
       'controller class' => 'UserController',
@@ -151,6 +151,7 @@ function user_entity_info() {
       'uri callback' => 'user_uri',
       'label callback' => 'user_label',
       'fieldable' => TRUE,
+      'entity class' => 'User',
       'entity keys' => array(
         'id' => 'uid',
       ),
@@ -171,7 +172,6 @@ function user_entity_info() {
       ),
     ),
   );
-  return $return;
 }
 
 /**
@@ -1181,30 +1181,6 @@ function user_account_form_validate($form, &$form_state) {
   }
 }
 
-/**
- * Implements hook_user_presave().
- */
-function user_user_presave(&$edit, $account) {
-  if (!empty($edit['picture_upload'])) {
-    $edit['picture'] = $edit['picture_upload'];
-  }
-  // Delete picture if requested, and if no replacement picture was given.
-  elseif (!empty($edit['picture_delete'])) {
-    $edit['picture'] = NULL;
-  }
-  // Prepare user roles.
-  if (isset($edit['roles'])) {
-    $edit['roles'] = array_filter($edit['roles']);
-  }
-
-  // Move account cancellation information into $user->data.
-  foreach (array('user_cancel_method', 'user_cancel_notify') as $key) {
-    if (isset($edit[$key])) {
-      $edit['data'][$key] = $edit[$key];
-    }
-  }
-}
-
 function user_login_block($form) {
   $form['#action'] = url($_GET['q'], array('query' => drupal_get_destination()));
   $form['#id'] = 'user-login-form';
