Index: wp-includes/query.php
===================================================================
--- wp-includes/query.php	(revision 17692)
+++ wp-includes/query.php	(working copy)
@@ -2290,33 +2290,49 @@
 
 		$where .= $search . $whichauthor . $whichmimetype;
 
-		if ( empty($q['order']) || ((strtoupper($q['order']) != 'ASC') && (strtoupper($q['order']) != 'DESC')) )
+		if ( empty($q['order']) || !in_array( strtoupper($q['order']), array('ASC', 'DESC') ) )
 			$q['order'] = 'DESC';
 
 		// Order by
-		if ( empty($q['orderby']) ) {
-			$orderby = "$wpdb->posts.post_date " . $q['order'];
-		} elseif ( 'none' == $q['orderby'] ) {
+		if ( empty($q['orderby']) )
+			$q_orderby = array();
+		elseif ( is_array( $q['orderby'] ) )
+			$q_orderby = $q['orderby'];
+		else
+			$q_orderby = explode(' ', $q['orderby']);
+
+		// Used to filter values
+		$allowed_keys = array('author', 'date', 'title', 'modified', 'menu_order', 'parent', 'ID', 'rand', 'comment_count');
+		$orderby_array = array();
+
+		foreach ( $q_orderby as $_order ) {
+			if ( empty($_order) )
+				continue;
 			$orderby = '';
-		} else {
-			// Used to filter values
-			$allowed_keys = array('author', 'date', 'title', 'modified', 'menu_order', 'parent', 'ID', 'rand', 'comment_count');
-			if ( !empty($q['meta_key']) ) {
-				$allowed_keys[] = $q['meta_key'];
-				$allowed_keys[] = 'meta_value';
-				$allowed_keys[] = 'meta_value_num';
-			}
-			$q['orderby'] = urldecode($q['orderby']);
-			$q['orderby'] = addslashes_gpc($q['orderby']);
+			$order = '';
+			$field = '';
+			$meta_key = '';
+			$value = null;
 
-			$orderby_array = array();
-			foreach ( explode( ' ', $q['orderby'] ) as $i => $orderby ) {
-				// Only allow certain values for safety
-				if ( ! in_array($orderby, $allowed_keys) )
+			if ( ! is_array( $_order ) )
+				$field = urldecode($_order);
+			else
+				extract($_order, EXTR_OVERWRITE);
+
+			// Skip over empty data sets.
+			if ( empty( $field ) ) {
+				if ( '' === $meta_key )
 					continue;
+				$field = 'meta_value';
+			}
 
-				switch ( $orderby ) {
+			if ( empty( $order ) || !in_array( strtoupper($order), array('ASC', 'DESC') ) )
+				$order = $q['order'];
+
+			if ( in_array($field, $allowed_keys) ) {
+				switch ( $field ) {
 					case 'menu_order':
+						$orderby = "$wpdb->posts.menu_order";
 						break;
 					case 'ID':
 						$orderby = "$wpdb->posts.ID";
@@ -2324,29 +2340,43 @@
 					case 'rand':
 						$orderby = 'RAND()';
 						break;
-					case $q['meta_key']:
-					case 'meta_value':
-						$orderby = "$wpdb->postmeta.meta_value";
-						break;
-					case 'meta_value_num':
-						$orderby = "$wpdb->postmeta.meta_value+0";
-						break;
 					case 'comment_count':
 						$orderby = "$wpdb->posts.comment_count";
 						break;
-					default:
-						$orderby = "$wpdb->posts.post_" . $orderby;
+					default: // author, date, title, modified, parent
+						$orderby = "$wpdb->posts.post_" . $wpdb->escape( $field );
 				}
+			} elseif ( ! empty( $q['meta_query'] ) ) {
+				$i = 0;
+				foreach ( (array) $q['meta_query'] as $mq ) {
+					if ( empty($mq['key']) )
+						continue;
 
+					// Fieldnames *may* be a queried meta_key
+					if ( '' === $meta_key && $field == $mq['key'] )
+						$meta_key = $field;
+
+					if ( $meta_key == $mq['key'] ) {
+						$alias = $i ? 'mt' . $i : $wpdb->postmeta; // See wp-includes/meta.php _get_meta_sql() for alias names
+						if ( 'meta_value' == $field )
+							$orderby = "$alias.meta_value";
+						elseif ( 'meta_value_num' == $field )
+							$orderby = "$alias.meta_value+0";
+						break; // out of the foreach
+					}
+					$i++;
+				}
+			}
+			if ( !empty($orderby) ) {
+				if ( null !== $value )
+					$orderby = $wpdb->prepare("($orderby = %s)", $value);
+				$orderby .= ' ' . $order;
 				$orderby_array[] = $orderby;
 			}
-			$orderby = implode( ',', $orderby_array );
-
-			if ( empty( $orderby ) )
-				$orderby = "$wpdb->posts.post_date ".$q['order'];
-			else
-				$orderby .= " {$q['order']}";
 		}
+		$orderby = implode( ', ', $orderby_array );
+		if ( empty( $orderby ) )
+			$orderby = "$wpdb->posts.post_date " . $q['order'];
 
 		if ( is_array( $post_type ) ) {
 			$post_type_cap = 'multiple_post_type';
