Index: wp-includes/post.php
===================================================================
--- wp-includes/post.php	(revision 4381)
+++ wp-includes/post.php	(working copy)
@@ -229,14 +229,13 @@
 		}
 	}
 
-	$original = $value;
-	if ( is_array($value) || is_object($value) )
-		$value = $wpdb->escape(serialize($value));
+	$post_meta_cache[$post_id][$key][] = $value;
 
+	$value = prepare_data($value);
+	$value = $wpdb->escape($value);
+
 	$wpdb->query("INSERT INTO $wpdb->postmeta (post_id,meta_key,meta_value) VALUES ('$post_id','$key','$value')");
 
-	$post_meta_cache[$post_id][$key][] = $original;
-
 	return true;
 }
 
@@ -311,12 +310,12 @@
 	$post_id = (int) $post_id;
 
 	$original_value = $value;
-	if ( is_array($value) || is_object($value) )
-		$value = $wpdb->escape(serialize($value));
+	$value = prepare_data($value);
+	$value = $wpdb->escape($value);
 
 	$original_prev = $prev_value;
-	if ( is_array($prev_value) || is_object($prev_value) )
-		$prev_value = $wpdb->escape(serialize($prev_value));
+	$prev_value = prepare_data($prev_value);
+	$prev_value = $wpdb->escape($prev_value);
 
 	if (! $wpdb->get_var("SELECT meta_key FROM $wpdb->postmeta WHERE meta_key = '$key' AND post_id = '$post_id'") ) {
 		return false;
Index: wp-includes/pluggable.php
===================================================================
--- wp-includes/pluggable.php	(revision 4381)
+++ wp-includes/pluggable.php	(working copy)
@@ -78,9 +78,7 @@
 
 	if ($metavalues) {
 		foreach ( $metavalues as $meta ) {
-			@ $value = unserialize($meta->meta_value);
-			if ($value === FALSE)
-				$value = $meta->meta_value;
+			$value = maybe_unserialize($meta->meta_value);
 			$user->{$meta->meta_key} = $value;
 
 			// We need to set user_level from meta, not row
@@ -131,9 +129,7 @@
 
 	if ($metavalues) {
 		foreach ( $metavalues as $meta ) {
-			@ $value = unserialize($meta->meta_value);
-			if ($value === FALSE)
-				$value = $meta->meta_value;
+			$value = maybe_unserialize($meta->meta_value);
 			$user->{$meta->meta_key} = $value;
 
 			// We need to set user_level from meta, not row
Index: wp-includes/functions.php
===================================================================
--- wp-includes/functions.php	(revision 4381)
+++ wp-includes/functions.php	(working copy)
@@ -156,12 +156,30 @@
 }
 
 function maybe_unserialize($original) {
-	if ( false !== $gm = @ unserialize($original) )
-		return $gm;
-	else
-		return $original;
+	if ( is_serialized($original) ) // don't attempt to unserialize data that wasn't serialized going in
+		if ( false !== $gm = @ unserialize($original) )
+			return $gm;
+	return $original;
 }
 
+function is_serialized($data) {
+	if ( !is_string($data) ) // if it isn't a string, it isn't serialized
+		return false;
+	$data = trim($data);
+	if ( preg_match("/^[adobis]:[0-9]+:.*[;}]/si",$data) ) // this should fetch all legitimately serialized data
+		return true;
+	return false;
+}
+
+function is_serialized_string($data) {
+	if ( !is_string($data) ) // if it isn't a string, it isn't a serialized string
+		return false;
+	$data = trim($data);
+	if ( preg_match("/^s:[0-9]+:.*[;}]/si",$data) ) // this should fetch all serialized strings
+		return true;
+	return false;
+}
+
 /* Options functions */
 
 function get_option($setting) {
@@ -239,8 +257,7 @@
 	}
 
 	$_newvalue = $newvalue;
-	if ( is_array($newvalue) || is_object($newvalue) )
-		$newvalue = serialize($newvalue);
+	$newvalue = prepare_data($newvalue);
 
 	wp_cache_set($option_name, $newvalue, 'options');
 
@@ -262,8 +279,7 @@
 	if ( false !== get_option($name) )
 		return;
 
-	if ( is_array($value) || is_object($value) )
-		$value = serialize($value);
+	$value = prepare_data($value);
 
 	wp_cache_set($name, $value, 'options');
 
@@ -285,6 +301,16 @@
 	return true;
 }
 
+function prepare_data($data) {
+	if ( is_string($data) )
+		$data = trim($data);
+	elseif ( is_array($data) || is_object($data) )
+		return serialize($data);
+	if ( is_serialized($data) )
+		return serialize($data);
+	return $data;
+}
+
 function gzip_compression() {
 	if ( !get_option('gzipcompression') ) return false;
 
Index: wp-includes/user.php
===================================================================
--- wp-includes/user.php	(revision 4381)
+++ wp-includes/user.php	(working copy)
@@ -114,9 +114,10 @@
 		return false;
 	$meta_key = preg_replace('|[^a-z0-9_]|i', '', $meta_key);
 
-	if ( is_array($meta_value) || is_object($meta_value) )
-		$meta_value = serialize($meta_value);
-	$meta_value = trim( $meta_value );
+	// FIXME: usermeta data is assumed to be already escaped
+	$meta_value = stripslashes($meta_value);
+	$meta_value = prepare_data($meta_value);
+	$meta_value = $wpdb->escape($meta_value);
 
 	if (empty($meta_value)) {
 		return delete_usermeta($user_id, $meta_key);
Index: wp-admin/wp-admin.css
===================================================================
--- wp-admin/wp-admin.css	(revision 4381)
+++ wp-admin/wp-admin.css	(working copy)
@@ -445,6 +445,10 @@
 	width: 250px;
 }
 
+input.disabled, textarea.disabled {
+	background: #ccc;
+}
+
 #adminmenu {
 	background: #83B4D8;
 	border-top: 3px solid #448abd;
Index: wp-admin/admin-functions.php
===================================================================
--- wp-admin/admin-functions.php	(revision 4381)
+++ wp-admin/admin-functions.php	(working copy)
@@ -981,6 +981,18 @@
 			$style = '';
 		if ('_' == $entry['meta_key'] { 0 })
 			$style .= ' hidden';
+
+		if ( is_serialized($entry['meta_value']) ) {
+			if ( 's' == $entry['meta_value']{0} ) {
+				// this is a serialized string, so we should display it
+				$entry['meta_value'] = maybe_unserialize($entry['meta_value']);
+			} else {
+				// this is a serialized array/object so we should NOT display it
+				--$count;
+				continue;
+			}
+		}
+
 		$key_js = js_escape($entry['meta_key']);
 		$entry['meta_key'] = wp_specialchars( $entry['meta_key'], true );
 		$entry['meta_value'] = wp_specialchars( $entry['meta_value'], true );
@@ -1056,7 +1068,8 @@
 
 	$metakeyselect = $wpdb->escape(stripslashes(trim($_POST['metakeyselect'])));
 	$metakeyinput = $wpdb->escape(stripslashes(trim($_POST['metakeyinput'])));
-	$metavalue = $wpdb->escape(stripslashes(trim($_POST['metavalue'])));
+	$metavalue = prepare_data(stripslashes((trim($_POST['metavalue']))));
+	$metavalue = $wpdb->escape($metavalue);
 
 	if ( ('0' === $metavalue || !empty ($metavalue)) && ((('#NONE#' != $metakeyselect) && !empty ($metakeyselect)) || !empty ($metakeyinput)) ) {
 		// We have a key/value pair. If both the select and the 
@@ -1087,8 +1100,9 @@
 
 function update_meta($mid, $mkey, $mvalue) {
 	global $wpdb;
+	if ( is_serialized(stripslashes($mvalue)) ) // $mvalue looks to be already serialized, so we should serialize it again to prevent the data from coming out in a different form than it came in
+		$mvalue = serialize($mvalue);
 	$mid = (int) $mid;
-
 	return $wpdb->query("UPDATE $wpdb->postmeta SET meta_key = '$mkey', meta_value = '$mvalue' WHERE meta_id = '$mid'");
 }
 
Index: wp-admin/options.php
===================================================================
--- wp-admin/options.php	(revision 4381)
+++ wp-admin/options.php	(working copy)
@@ -124,23 +124,32 @@
   <table width="98%">
 <?php
 $options = $wpdb->get_results("SELECT * FROM $wpdb->options ORDER BY option_name");
-foreach ( (array) $options as $option )
-	$options_to_update[] = $option->option_name;
-$options_to_update = implode(',', $options_to_update);
-?>
 
-<input type="hidden" name="page_options" value="<?php echo $options_to_update; ?>" /> 
-
-<?php
 foreach ( (array) $options as $option) :
-	$value = wp_specialchars($option->option_value, 'single');
+	$disabled = '';
+	if ( is_serialized($option->option_value) ) {
+		if ( 's' == $option->option_value{0} ) {
+			// this is a serialized string, so we should display it
+			$value = wp_specialchars(maybe_unserialize($option->option_value), 'single');
+			$options_to_update[] = $option->option_name;
+			$class = 'all-options';
+		} else {
+			$value = 'SERIALIZED DATA';
+			$disabled = ' disabled="disabled"';
+			$class = 'all-options disabled';
+		}
+	} else {
+		$value = wp_specialchars($option->option_value, 'single');
+		$options_to_update[] = $option->option_name;
+		$class = 'all-options';
+	}
 	echo "
 <tr>
 	<th scope='row'><label for='$option->option_name'>$option->option_name</label></th>
 <td>";
 
-	if (stristr($value, "\n")) echo "<textarea class='all-options' name='$option->option_name' id='$option->option_name' cols='30' rows='5'>$value</textarea>";
-	else echo "<input class='all-options' type='text' name='$option->option_name' id='$option->option_name' size='30' value='" . $value . "' />";
+	if (stristr($value, "\n")) echo "<textarea class='$class' name='$option->option_name' id='$option->option_name' cols='30' rows='5'>$value</textarea>";
+	else echo "<input class='$class' type='text' name='$option->option_name' id='$option->option_name' size='30' value='" . $value . "'$disabled />";
 	
 	echo "</td>
 	<td>$option->option_description</td>
@@ -148,7 +157,8 @@
 endforeach;
 ?>
   </table>
-<p class="submit"><input type="submit" name="Update" value="<?php _e('Update Options &raquo;') ?>" /></p>
+<?php $options_to_update = implode(',', $options_to_update); ?>
+<p class="submit"><input type="hidden" name="page_options" value="<?php echo wp_specialchars($options_to_update, true); ?>" /><input type="submit" name="Update" value="<?php _e('Update Options &raquo;') ?>" /></p>
   </form>
 </div>
 

