Index: wp-includes/version.php
===================================================================
--- wp-includes/version.php	(revision 11028)
+++ wp-includes/version.php	(working copy)
@@ -15,6 +15,6 @@
  *
  * @global int $wp_db_version
  */
-$wp_db_version = 10850;
+$wp_db_version = 11029;
 
-?>
+?>
\ No newline at end of file
Index: wp-includes/user.php
===================================================================
--- wp-includes/user.php	(revision 11028)
+++ wp-includes/user.php	(working copy)
@@ -282,11 +282,188 @@
 	return $users;
 }
 
+
 //
 // User meta functions
 //
 
 /**
+ * Add meta data field to a user.
+ *
+ *
+ * @since 2.8
+ * @uses $wpdb
+ * @link http://codex.wordpress.org/Function_Reference/add_user_meta
+ *
+ * @param int $user_id User ID.
+ * @param string $key Metadata name.
+ * @param mixed $value Metadata value.
+ * @param bool $single Optional, default is false. Whether the same key should not be added.
+ * @return bool False for failure. True for success.
+ */
+function add_user_meta($user_id, $meta_key, $meta_value, $single = false) {
+	global $wpdb;
+
+	$user_id = (int) $user_id;
+	
+	// expected_slashed ($meta_key)
+	$meta_key = stripslashes($meta_key);
+
+	$user = new WP_User($user_id);
+	
+	if ( $single ) {
+		if ( isset($user->{$meta_key}) )
+			return false;
+	}
+
+	$meta_value = maybe_serialize( stripslashes_deep($meta_value) );
+	$single = (int) $single;
+
+	$wpdb->insert( $wpdb->usermeta, compact( 'user_id', 'meta_key', 'meta_value', 'single' ) );
+
+	if ( !$single && isset($user->meta_key) ) {
+		// make sure an initially single-row meta gets treated as a multi-row meta from this point onward
+		$wpdb->update( $wpdb->usermeta, compact('single'), compact('user_id', 'meta_key'));
+	}
+
+	wp_cache_delete($user_id, 'users');
+
+	return true;
+}
+
+/**
+ * Remove matching metadata from a user.
+ *
+ * You can match based on the key, or key and value. Removing based on key and
+ * value, will keep from removing duplicate metadata with the same key. It also
+ * allows removing all metadata matching key, if needed.
+ *
+ * @since 2.8
+ * @uses $wpdb
+ * @link http://codex.wordpress.org/Function_Reference/delete_user_meta
+ *
+ * @param int $user_id User ID
+ * @param string $meta_key Metadata name.
+ * @param mixed $meta_value Optional. Metadata value.
+ * @return bool False for failure. True for success.
+ */
+function delete_user_meta($user_id, $meta_key, $meta_value = '') {
+	global $wpdb;
+
+	$user_id = (int) $user_id;
+	// expected_slashed ($meta_key, $meta_value)
+	$meta_key = stripslashes( $meta_key );
+	$meta_value = maybe_serialize( stripslashes_deep($meta_value) );
+
+	if ( empty( $meta_value ) ) {
+		$user = new WP_User($user_id);
+		if ( !isset($user->{$meta_key}) )
+			return false;
+	} else {
+		$meta_id = $wpdb->get_var( $wpdb->prepare( "SELECT umeta_id FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s AND meta_value = %s", $user_id, $meta_key, $meta_value ) );
+		if ( !$meta_id )
+			return false;
+	}
+
+	if ( empty( $meta_value ) )
+		$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $user_id, $meta_key ) );
+	else
+		$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s AND meta_value = %s", $user_id, $meta_key, $meta_value ) );
+
+	wp_cache_delete($user_id, 'users');
+
+	return true;
+}
+
+/**
+ * Retrieve user meta field for a user.
+ *
+ * @since 2.8
+ * @uses $wpdb
+ * @link http://codex.wordpress.org/Function_Reference/get_user_meta
+ *
+ * @param int $user_id User ID.
+ * @param string $key The meta key to retrieve.
+ * @return mixed Will be an array if $single is false. Will be value of meta data field if $single is true.
+ */
+function get_user_meta($user_id, $key) {
+	$user_id = (int) $user_id;
+
+	$user = new WP_User($user_id);
+	
+	return isset($user->{$key}) ? $user->{$key} : '';
+}
+
+/**
+ * Update user meta field based on User ID.
+ *
+ * Use the $prev_value parameter to differentiate between meta fields with the
+ * same key and User ID.
+ *
+ * If the meta field for the user does not exist, it will be added.
+ *
+ * @since 2.8
+ * @uses $wpdb
+ * @link http://codex.wordpress.org/Function_Reference/update_user_meta
+ *
+ * @param int $user_id User ID.
+ * @param string $key Metadata key.
+ * @param mixed $value Metadata value.
+ * @param mixed $prev_value Optional. Previous value to check before removing.
+ * @return bool False on failure, true if success.
+ */
+function update_user_meta($user_id, $meta_key, $meta_value, $prev_value = '') {
+	global $wpdb;
+
+	// expected_slashed ($meta_key)
+	$meta_key = stripslashes($meta_key);
+
+	if ( ! $wpdb->get_var( $wpdb->prepare( "SELECT meta_key FROM $wpdb->usermeta WHERE meta_key = %s AND user_id = %d", $meta_key, $user_id ) ) ) {
+		return add_user_meta($user_id, $meta_key, $meta_value, empty($prev_value));
+	}
+
+	$meta_value = maybe_serialize( stripslashes_deep($meta_value) );
+	$single = empty($prev_value);
+
+	$data  = compact( 'meta_value', 'single' );
+	$where = compact( 'meta_key', 'user_id' );
+
+	if ( !empty( $prev_value ) ) {
+		$prev_value = maybe_serialize($prev_value);
+		$where['meta_value'] = $prev_value;
+	}
+
+	$wpdb->update( $wpdb->usermeta, $data, $where );
+	wp_cache_delete($user_id, 'users');
+	return true;
+}
+
+/**
+ * Delete everything from user meta matching meta key.
+ *
+ * @since 2.8
+ * @uses $wpdb
+ *
+ * @param string $user_meta_key Key to search for when deleting.
+* @return bool Whether the user meta key was deleted from the database
+ */
+function delete_user_meta_by_key($user_meta_key) {
+	global $wpdb;
+
+	$user_ids = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT user_id FROM $wpdb->usermeta WHERE meta_key = %s", $user_meta_key));
+
+	if ( $user_ids ) {
+		$wpdb->query($wpdb->prepare("DELETE FROM $wpdb->usermeta WHERE meta_key = %s", $user_meta_key));
+		foreach ( $user_ids as $user_id )
+			wp_cache_delete($user_id, 'users');
+
+		return true;
+	}
+	
+	return false;
+}
+
+/**
  * Remove user meta data.
  *
  * @since 2.0.0
@@ -572,13 +749,18 @@
 	global $wpdb;
 
 	$show = $wpdb->hide_errors();
-	$metavalues = $wpdb->get_results($wpdb->prepare("SELECT meta_key, meta_value FROM $wpdb->usermeta WHERE user_id = %d", $user->ID));
+	$metavalues = $wpdb->get_results($wpdb->prepare("SELECT meta_key, meta_value, single FROM $wpdb->usermeta WHERE user_id = %d", $user->ID));
 	$wpdb->show_errors($show);
 
 	if ( $metavalues ) {
 		foreach ( (array) $metavalues as $meta ) {
 			$value = maybe_unserialize($meta->meta_value);
-			$user->{$meta->meta_key} = $value;
+			if ( $meta->single ) {
+				$user->{$meta->meta_key} = $value;
+			} else {
+				$user->{$meta->meta_key}[] = $value;
+			}
+			
 		}
 	}
 
@@ -600,4 +782,4 @@
 	wp_cache_add($user->user_nicename, $user->ID, 'userslugs');
 }
 
-?>
+?>
\ No newline at end of file
Index: wp-admin/includes/schema.php
===================================================================
--- wp-admin/includes/schema.php	(revision 11028)
+++ wp-admin/includes/schema.php	(working copy)
@@ -158,6 +158,7 @@
 CREATE TABLE $wpdb->usermeta (
   umeta_id bigint(20) unsigned NOT NULL auto_increment,
   user_id bigint(20) unsigned NOT NULL default '0',
+  single tinyint(1) unsigned NOT NULL default '1',
   meta_key varchar(255) default NULL,
   meta_value longtext,
   PRIMARY KEY  (umeta_id),
@@ -576,4 +577,4 @@
 	}
 }
 
-?>
+?>
\ No newline at end of file
