Index: src/wp-admin/includes/class-wp-ms-sites-list-table.php
===================================================================
--- src/wp-admin/includes/class-wp-ms-sites-list-table.php	(revision 28706)
+++ src/wp-admin/includes/class-wp-ms-sites-list-table.php	(working copy)
@@ -38,8 +38,6 @@
 			$s = trim($s, '*');
 		}
 
-		$like_s = esc_sql( like_escape( $s ) );
-
 		// If the network is large and a search is not being performed, show only the latest blogs with no paging in order
 		// to avoid expensive count queries.
 		if ( !$s && wp_is_large_network() ) {
@@ -58,7 +56,8 @@
 					preg_match( '/^[0-9]{1,3}\.[0-9]{1,3}\.?$/', $s ) ||
 					preg_match( '/^[0-9]{1,3}\.$/', $s ) ) {
 			// IPv4 address
-			$reg_blog_ids = $wpdb->get_col( "SELECT blog_id FROM {$wpdb->registration_log} WHERE {$wpdb->registration_log}.IP LIKE ( '{$like_s}$wild' )" );
+			$sql = $wpdb->prepare( "SELECT blog_id FROM {$wpdb->registration_log} WHERE {$wpdb->registration_log}.IP LIKE %s", $wpdb->esc_like( $s ) . $wild );
+			$reg_blog_ids = $wpdb->get_col( $sql );
 
 			if ( !$reg_blog_ids )
 				$reg_blog_ids = array( 0 );
@@ -69,17 +68,18 @@
 				AND {$wpdb->blogs}.blog_id IN (" . implode( ', ', $reg_blog_ids ) . ")";
 		} else {
 			if ( is_numeric($s) && empty( $wild ) ) {
-				$query .= " AND ( {$wpdb->blogs}.blog_id = '{$like_s}' )";
+				$query .= $wpdb->prepare( " AND ( {$wpdb->blogs}.blog_id = %s )", $s );
 			} elseif ( is_subdomain_install() ) {
-				$blog_s = str_replace( '.' . $current_site->domain, '', $like_s );
-				$blog_s .= $wild . '.' . $current_site->domain;
-				$query .= " AND ( {$wpdb->blogs}.domain LIKE '$blog_s' ) ";
+				$blog_s = str_replace( '.' . $current_site->domain, '', $s );
+				$blog_s = $wpdb->esc_like( $blog_s ) . $wild . $wpdb->esc_like( '.' . $current_site->domain );
+				$query .= $wpdb->prepare( " AND ( {$wpdb->blogs}.domain LIKE %s ) ", $blog_s );
 			} else {
-				if ( $like_s != trim('/', $current_site->path) )
-					$blog_s = $current_site->path . $like_s . $wild . '/';
-				else
-					$blog_s = $like_s;
-				$query .= " AND  ( {$wpdb->blogs}.path LIKE '$blog_s' )";
+				if ( $s != trim('/', $current_site->path) ) {
+					$blog_s = $wpdb->esc_like( $current_site->path . $s ) . $wild . $wpdb->esc_like( '/' );
+				} else {
+					$blog_s = $wpdb->esc_like( $s );
+				}
+				$query .= $wpdb->prepare( " AND  ( {$wpdb->blogs}.path LIKE %s )", $blog_s );
 			}
 		}
 
Index: src/wp-admin/includes/schema.php
===================================================================
--- src/wp-admin/includes/schema.php	(revision 28706)
+++ src/wp-admin/includes/schema.php	(working copy)
@@ -553,19 +553,21 @@
 	// The multi-table delete syntax is used to delete the transient record from table a,
 	// and the corresponding transient_timeout record from table b.
 	$time = time();
-	$wpdb->query("DELETE a, b FROM $wpdb->options a, $wpdb->options b WHERE
-	        a.option_name LIKE '\_transient\_%' AND
-	        a.option_name NOT LIKE '\_transient\_timeout\_%' AND
-	        b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )
-	        AND b.option_value < $time");
+	$sql = "DELETE a, b FROM $wpdb->options a, $wpdb->options b
+		WHERE a.option_name LIKE %s
+		AND a.option_name NOT LIKE %s
+		AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )
+		AND b.option_value < %d";
+	$wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( '_transient_' ) . '%', $wpdb->esc_like( '_transient_timeout_' ) . '%', $time ) );
 
 	if ( is_main_site() && is_main_network() ) {
-		$wpdb->query("DELETE a, b FROM $wpdb->options a, $wpdb->options b WHERE
-			a.option_name LIKE '\_site\_transient\_%' AND
-			a.option_name NOT LIKE '\_site\_transient\_timeout\_%' AND
-			b.option_name = CONCAT( '_site_transient_timeout_', SUBSTRING( a.option_name, 17 ) )
-			AND b.option_value < $time");
-    }
+		$sql = "DELETE a, b FROM $wpdb->options a, $wpdb->options b
+			WHERE a.option_name LIKE %s
+			AND a.option_name NOT LIKE %s
+			AND b.option_name = CONCAT( '_site_transient_timeout_', SUBSTRING( a.option_name, 17 ) )
+			AND b.option_value < %d";
+		$wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( '_site_transient_' ) . '%', $wpdb->esc_like( '_site_transient_timeout_' ) . '%', $time ) );
+	}
 }
 
 /**
Index: src/wp-admin/includes/template.php
===================================================================
--- src/wp-admin/includes/template.php	(revision 28706)
+++ src/wp-admin/includes/template.php	(working copy)
@@ -632,14 +632,14 @@
 	 *
 	 * @param int $limit Number of custom fields to retrieve. Default 30.
 	 */
-	$limit = (int) apply_filters( 'postmeta_form_limit', 30 );
-	$keys = $wpdb->get_col( "
-		SELECT meta_key
+	$limit = apply_filters( 'postmeta_form_limit', 30 );
+	$sql = "SELECT meta_key
 		FROM $wpdb->postmeta
 		GROUP BY meta_key
-		HAVING meta_key NOT LIKE '\_%'
+		HAVING meta_key NOT LIKE %s
 		ORDER BY meta_key
-		LIMIT $limit" );
+		LIMIT %d";
+	$keys = $wpdb->get_col( $wpdb->prepare( $sql, $wpdb->esc_like( '_' ) . '%', $limit ) );
 	if ( $keys ) {
 		natcasesort( $keys );
 		$meta_key_input_id = 'metakeyselect';
Index: src/wp-admin/includes/upgrade.php
===================================================================
--- src/wp-admin/includes/upgrade.php	(revision 28706)
+++ src/wp-admin/includes/upgrade.php	(working copy)
@@ -465,9 +465,11 @@
 		}
 	}
 
-	$wpdb->query("UPDATE $wpdb->options SET option_value = REPLACE(option_value, 'wp-links/links-images/', 'wp-images/links/')
-	WHERE option_name LIKE 'links_rating_image%'
-	AND option_value LIKE 'wp-links/links-images/%'");
+	$sql = "UPDATE $wpdb->options
+		SET option_value = REPLACE(option_value, 'wp-links/links-images/', 'wp-images/links/')
+		WHERE option_name LIKE %s
+		AND option_value LIKE %s";
+	$wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( 'links_rating_image' ) . '%', $wpdb->esc_like( 'wp-links/links-images/' ) . '%' ) );
 
 	$done_ids = $wpdb->get_results("SELECT DISTINCT post_id FROM $wpdb->post2cat");
 	if ($done_ids) :
@@ -1100,9 +1102,28 @@
 
 	// 3.0 screen options key name changes.
 	if ( is_main_site() && !defined('DO_NOT_UPGRADE_GLOBAL_TABLES') ) {
-		$prefix = like_escape($wpdb->base_prefix);
-		$wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key LIKE '{$prefix}%meta-box-hidden%' OR meta_key LIKE '{$prefix}%closedpostboxes%' OR meta_key LIKE '{$prefix}%manage-%-columns-hidden%' OR meta_key LIKE '{$prefix}%meta-box-order%' OR meta_key LIKE '{$prefix}%metaboxorder%' OR meta_key LIKE '{$prefix}%screen_layout%'
-					 OR meta_key = 'manageedittagscolumnshidden' OR meta_key='managecategoriescolumnshidden' OR meta_key = 'manageedit-tagscolumnshidden' OR meta_key = 'manageeditcolumnshidden' OR meta_key = 'categories_per_page' OR meta_key = 'edit_tags_per_page'" );
+		$sql = "DELETE FROM $wpdb->usermeta
+			WHERE meta_key LIKE %s
+			OR meta_key LIKE %s
+			OR meta_key LIKE %s
+			OR meta_key LIKE %s
+			OR meta_key LIKE %s
+			OR meta_key LIKE %s
+			OR meta_key = 'manageedittagscolumnshidden'
+			OR meta_key = 'managecategoriescolumnshidden'
+			OR meta_key = 'manageedit-tagscolumnshidden'
+			OR meta_key = 'manageeditcolumnshidden'
+			OR meta_key = 'categories_per_page'
+			OR meta_key = 'edit_tags_per_page'";
+		$prefix = $wpdb->esc_like( $wpdb->base_prefix );
+		$wpdb->query( $wpdb->prepare( $sql,
+			$prefix . '%' . $wpdb->esc_like( 'meta-box-hidden' ) . '%',
+			$prefix . '%' . $wpdb->esc_like( 'closedpostboxes' ) . '%',
+			$prefix . '%' . $wpdb->esc_like( 'manage-'	   ) . '%' . $wpdb->esc_like( '-columns-hidden' ) . '%',
+			$prefix . '%' . $wpdb->esc_like( 'meta-box-order'  ) . '%',
+			$prefix . '%' . $wpdb->esc_like( 'metaboxorder'    ) . '%',
+			$prefix . '%' . $wpdb->esc_like( 'screen_layout'   ) . '%'
+		) );
 	}
 
 }
@@ -1284,11 +1305,12 @@
 		// The multi-table delete syntax is used to delete the transient record from table a,
 		// and the corresponding transient_timeout record from table b.
 		$time = time();
-		$wpdb->query("DELETE a, b FROM $wpdb->sitemeta a, $wpdb->sitemeta b WHERE
-			a.meta_key LIKE '\_site\_transient\_%' AND
-			a.meta_key NOT LIKE '\_site\_transient\_timeout\_%' AND
-			b.meta_key = CONCAT( '_site_transient_timeout_', SUBSTRING( a.meta_key, 17 ) )
-			AND b.meta_value < $time");
+		$sql = "DELETE a, b FROM $wpdb->sitemeta a, $wpdb->sitemeta b
+			WHERE a.meta_key LIKE %s
+			AND a.meta_key NOT LIKE %s
+			AND b.meta_key = CONCAT( '_site_transient_timeout_', SUBSTRING( a.meta_key, 17 ) )
+			AND b.meta_value < %d";
+		$wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( '_site_transient_' ) . '%', $wpdb->esc_like ( '_site_transient_timeout_' ) . '%', $time ) );
 	}
 
 	// 2.8
@@ -1382,13 +1404,18 @@
  */
 function maybe_create_table($table_name, $create_ddl) {
 	global $wpdb;
-	if ( $wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name )
+	
+	$query = $wpdb->prepare( "SHOW TABLES LIKE %s", $wpdb->esc_like( $table_name ) );
+
+	if ( $wpdb->get_var( $query ) == $table_name ) {
 		return true;
+	}
 	//didn't find it try to create it.
 	$wpdb->query($create_ddl);
 	// we cannot directly tell that whether this succeeded!
-	if ( $wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name )
+	if ( $wpdb->get_var( $query ) == $table_name ) {
 		return true;
+	}
 	return false;
 }
 
Index: src/wp-admin/install.php
===================================================================
--- src/wp-admin/install.php	(revision 28706)
+++ src/wp-admin/install.php	(working copy)
@@ -74,8 +74,10 @@
  */
 function display_setup_form( $error = null ) {
 	global $wpdb;
-	$user_table = ( $wpdb->get_var("SHOW TABLES LIKE '$wpdb->users'") != null );
 
+	$sql = $wpdb->prepare( "SHOW TABLES LIKE %s", $wpdb->esc_like( $wpdb->users ) );
+	$user_table = ( $wpdb->get_var( $sql ) != null );
+
 	// Ensure that Blogs appear in search engines by default
 	$blog_public = 1;
 	if ( ! empty( $_POST ) )
Index: src/wp-admin/maint/repair.php
===================================================================
--- src/wp-admin/maint/repair.php	(revision 28706)
+++ src/wp-admin/maint/repair.php	(working copy)
@@ -36,8 +36,10 @@
 	$tables = $wpdb->tables();
 
 	// Sitecategories may not exist if global terms are disabled.
-	if ( is_multisite() && ! $wpdb->get_var( "SHOW TABLES LIKE '$wpdb->sitecategories'" ) )
+	$query = $wpdb->prepare( "SHOW TABLES LIKE %s", $wpdb->esc_like( $wpdb->sitecategories ) );
+	if ( is_multisite() && ! $wpdb->get_var( $query ) ) {
 		unset( $tables['sitecategories'] );
+	}
 
 	/**
 	 * Filter additional database tables to repair.
Index: src/wp-admin/network/site-settings.php
===================================================================
--- src/wp-admin/network/site-settings.php	(revision 28706)
+++ src/wp-admin/network/site-settings.php	(working copy)
@@ -113,7 +113,14 @@
 	<table class="form-table">
 		<?php
 		$blog_prefix = $wpdb->get_blog_prefix( $id );
-		$options = $wpdb->get_results( "SELECT * FROM {$blog_prefix}options WHERE option_name NOT LIKE '\_%' AND option_name NOT LIKE '%user_roles'" );
+		$sql = "SELECT * FROM {$blog_prefix}options
+			WHERE option_name NOT LIKE %s
+			AND option_name NOT LIKE %s";
+		$query = $wpdb->prepare( $sql,
+			$wpdb->esc_like( '_' ) . '%',
+			'%' . $wpdb->esc_like( 'user_roles' )
+		);
+		$options = $wpdb->get_results( $query );
 		foreach ( $options as $option ) {
 			if ( $option->option_name == 'default_role' )
 				$editblog_default_role = $option->option_value;
Index: src/wp-admin/network.php
===================================================================
--- src/wp-admin/network.php	(revision 28706)
+++ src/wp-admin/network.php	(working copy)
@@ -39,8 +39,11 @@
  */
 function network_domain_check() {
 	global $wpdb;
-	if ( $wpdb->get_var( "SHOW TABLES LIKE '$wpdb->site'" ) )
+
+	$sql = $wpdb->prepare( "SHOW TABLES LIKE %s", $wpdb->esc_like( $wpdb->site ) );
+	if ( $wpdb->get_var( $sql ) ) {
 		return $wpdb->get_var( "SELECT domain FROM $wpdb->site ORDER BY id ASC LIMIT 1" );
+	}
 	return false;
 }
 
Index: src/wp-includes/bookmark.php
===================================================================
--- src/wp-includes/bookmark.php	(revision 28706)
+++ src/wp-includes/bookmark.php	(working copy)
@@ -208,8 +208,8 @@
 
 	$search = '';
 	if ( ! empty( $r['search'] ) ) {
-		$search = esc_sql( like_escape( $r['search'] ) );
-		$search = " AND ( (link_url LIKE '%$search%') OR (link_name LIKE '%$search%') OR (link_description LIKE '%$search%') ) ";
+		$like = '%' . $wpdb->esc_like( $r['search'] ) . '%';
+		$search = $wpdb->prepare(" AND ( (link_url LIKE %s) OR (link_name LIKE %s) OR (link_description LIKE %s) ) ", $like, $like, $like );
 	}
 
 	$category_query = '';
Index: src/wp-includes/canonical.php
===================================================================
--- src/wp-includes/canonical.php	(revision 28706)
+++ src/wp-includes/canonical.php	(working copy)
@@ -504,7 +504,7 @@
 	global $wpdb, $wp_rewrite;
 
 	if ( get_query_var('name') ) {
-		$where = $wpdb->prepare("post_name LIKE %s", like_escape( get_query_var('name') ) . '%');
+		$where = $wpdb->prepare("post_name LIKE %s", $wpdb->esc_like( get_query_var('name') ) . '%');
 
 		// if any of post_type, year, monthnum, or day are set, use them to refine the query
 		if ( get_query_var('post_type') )
Index: src/wp-includes/class-wp-xmlrpc-server.php
===================================================================
--- src/wp-includes/class-wp-xmlrpc-server.php	(revision 28706)
+++ src/wp-includes/class-wp-xmlrpc-server.php	(working copy)
@@ -5764,7 +5764,7 @@
 			} elseif ( is_string($urltest['fragment']) ) {
 				// ...or a string #title, a little more complicated
 				$title = preg_replace('/[^a-z0-9]/i', '.', $urltest['fragment']);
-				$sql = $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_title RLIKE %s", like_escape( $title ) );
+				$sql = $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_title RLIKE %s", $title );
 				if (! ($post_ID = $wpdb->get_var($sql)) ) {
 					// returning unknown error '0' is better than die()ing
 			  		return $this->pingback_error( 0, '' );
Index: src/wp-includes/comment.php
===================================================================
--- src/wp-includes/comment.php	(revision 28706)
+++ src/wp-includes/comment.php	(working copy)
@@ -481,11 +481,11 @@
 	 * @return string
 	 */
 	protected function get_search_sql( $string, $cols ) {
-		$string = esc_sql( like_escape( $string ) );
+		global $wpdb;
 
 		$searches = array();
 		foreach ( $cols as $col )
-			$searches[] = "$col LIKE '%$string%'";
+			$searches[] = $wpdb->prepare( "$col LIKE %s", $wpdb->esc_like( $string ) );
 
 		return ' AND (' . implode(' OR ', $searches) . ')';
 	}
Index: src/wp-includes/deprecated.php
===================================================================
--- src/wp-includes/deprecated.php	(revision 28706)
+++ src/wp-includes/deprecated.php	(working copy)
@@ -3457,3 +3457,18 @@
 	_deprecated_function( __FUNCTION__, '3.9' );
 	return $content;
 }
+
+/**
+ * Formerly used to escape strings before searching the DB. It was poorly documented and never worked as described.
+ *
+ * @since 2.5.0
+ * @deprecated 4.0.0
+ * @deprecated Use wpdb::esc_like()
+ *
+ * @param string $text The text to be escaped.
+ * @return string text, safe for inclusion in LIKE query.
+ */
+function like_escape($text) {
+	_deprecated_function( __FUNCTION__, '4.0', 'wpdb::esc_like()' );
+	return str_replace(array("%", "_"), array("\\%", "\\_"), $text);
+}
Index: src/wp-includes/formatting.php
===================================================================
--- src/wp-includes/formatting.php	(revision 28706)
+++ src/wp-includes/formatting.php	(working copy)
@@ -3100,18 +3100,6 @@
 }
 
 /**
- * Escapes text for SQL LIKE special characters % and _.
- *
- * @since 2.5.0
- *
- * @param string $text The text to be escaped.
- * @return string text, safe for inclusion in LIKE query.
- */
-function like_escape($text) {
-	return str_replace(array("%", "_"), array("\\%", "\\_"), $text);
-}
-
-/**
  * Convert full URL paths to absolute paths.
  *
  * Removes the http or https protocols and the domain. Keeps the path '/' at the
Index: src/wp-includes/functions.php
===================================================================
--- src/wp-includes/functions.php	(revision 28706)
+++ src/wp-includes/functions.php	(working copy)
@@ -479,7 +479,7 @@
 
 	foreach ( $pung as $link_test ) {
 		if ( ! in_array( $link_test, $post_links_temp ) ) { // link no longer in post
-			$mids = $wpdb->get_col( $wpdb->prepare("SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE (%s)", $post_ID, like_escape( $link_test ) . '%') );
+			$mids = $wpdb->get_col( $wpdb->prepare("SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE %s", $post_ID, $wpdb->esc_like( $link_test ) . '%') );
 			foreach ( $mids as $mid )
 				delete_metadata_by_mid( 'post', $mid );
 		}
@@ -498,7 +498,7 @@
 	}
 
 	foreach ( (array) $post_links as $url ) {
-		if ( $url != '' && !$wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE (%s)", $post_ID, like_escape( $url ) . '%' ) ) ) {
+		if ( $url != '' && !$wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE %s", $post_ID, $wpdb->esc_like( $url ) . '%' ) ) ) {
 
 			if ( $headers = wp_get_http_headers( $url) ) {
 				$len = isset( $headers['content-length'] ) ? (int) $headers['content-length'] : 0;
Index: src/wp-includes/meta.php
===================================================================
--- src/wp-includes/meta.php	(revision 28706)
+++ src/wp-includes/meta.php	(working copy)
@@ -1047,8 +1047,8 @@
 			} elseif ( 'BETWEEN' == substr( $meta_compare, -7) ) {
 				$meta_value = array_slice( $meta_value, 0, 2 );
 				$meta_compare_string = '%s AND %s';
-			} elseif ( 'LIKE' == substr( $meta_compare, -4 ) ) {
-				$meta_value = '%' . like_escape( $meta_value ) . '%';
+			} elseif ( 'LIKE' == $meta_compare || 'NOT LIKE' == $meta_compare ) ) {
+				$meta_value = '%' . $wpdb->esc_like( $meta_value ) . '%';
 				$meta_compare_string = '%s';
 			} else {
 				$meta_compare_string = '%s';
Index: src/wp-includes/ms-load.php
===================================================================
--- src/wp-includes/ms-load.php	(revision 28706)
+++ src/wp-includes/ms-load.php	(working copy)
@@ -397,14 +397,17 @@
 
 	$title = __( 'Error establishing a database connection' );
 	$msg  = '<h1>' . $title . '</h1>';
-	if ( ! is_admin() )
+	if ( ! is_admin() ) {
 		die( $msg );
+	}
 	$msg .= '<p>' . __( 'If your site does not display, please contact the owner of this network.' ) . '';
 	$msg .= ' ' . __( 'If you are the owner of this network please check that MySQL is running properly and all tables are error free.' ) . '</p>';
-	if ( ! $wpdb->get_var( "SHOW TABLES LIKE '$wpdb->site'" ) )
+	$query = $wpdb->prepare( "SHOW TABLES LIKE %s", $wpdb->esc_like( $wpdb->site ) );
+	if ( ! $wpdb->get_var( $query ) ) {
 		$msg .= '<p>' . sprintf( __( '<strong>Database tables are missing.</strong> This means that MySQL is not running, WordPress was not installed properly, or someone deleted <code>%s</code>. You really should look at your database now.' ), $wpdb->site ) . '</p>';
-	else
+	} else {
 		$msg .= '<p>' . sprintf( __( '<strong>Could not find site <code>%1$s</code>.</strong> Searched for table <code>%2$s</code> in database <code>%3$s</code>. Is that right?' ), rtrim( $domain . $path, '/' ), $wpdb->blogs, DB_NAME ) . '</p>';
+	}
 	$msg .= '<p><strong>' . __( 'What do I do now?' ) . '</strong> ';
 	$msg .= __( 'Read the <a target="_blank" href="http://codex.wordpress.org/Debugging_a_WordPress_Network">bug report</a> page. Some of the guidelines there may help you figure out what went wrong.' );
 	$msg .= ' ' . __( 'If you&#8217;re still stuck with this message, then check that your database contains the following tables:' ) . '</p><ul>';
Index: src/wp-includes/post.php
===================================================================
--- src/wp-includes/post.php	(revision 28706)
+++ src/wp-includes/post.php	(working copy)
@@ -4796,7 +4796,7 @@
 
 	if ( ! empty($meta['thumb']) ) {
 		// Don't delete the thumb if another attachment uses it
-		if (! $wpdb->get_row( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE meta_key = '_wp_attachment_metadata' AND meta_value LIKE %s AND post_id <> %d", '%' . $meta['thumb'] . '%', $post_id)) ) {
+		if (! $wpdb->get_row( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE meta_key = '_wp_attachment_metadata' AND meta_value LIKE %s AND post_id <> %d", '%' . $wpdb->esc_like( $meta['thumb'] ) . '%', $post_id)) ) {
 			$thumbfile = str_replace(basename($file), $meta['thumb'], $file);
 			/** This filter is documented in wp-admin/custom-header.php */
 			$thumbfile = apply_filters( 'wp_delete_file', $thumbfile );
Index: src/wp-includes/query.php
===================================================================
--- src/wp-includes/query.php	(revision 28706)
+++ src/wp-includes/query.php	(working copy)
@@ -1983,11 +1983,13 @@
 		$searchand = '';
 		$q['search_orderby_title'] = array();
 		foreach ( $q['search_terms'] as $term ) {
-			$term = like_escape( esc_sql( $term ) );
-			if ( $n )
-				$q['search_orderby_title'][] = "$wpdb->posts.post_title LIKE '%$term%'";
+			if ( $n ) {
+				$like = '%' . $wpdb->esc_like( $term ) . '%';
+				$q['search_orderby_title'][] = $wpdb->prepare( "$wpdb->posts.post_title LIKE %s", $like );
+			}
 
-			$search .= "{$searchand}(($wpdb->posts.post_title LIKE '{$n}{$term}{$n}') OR ($wpdb->posts.post_content LIKE '{$n}{$term}{$n}'))";
+			$like = $n . $wpdb->esc_like( $term ) . $n;
+			$search .= $wpdb->prepare( "{$searchand}(($wpdb->posts.post_title LIKE %s) OR ($wpdb->posts.post_content LIKE %s))", $like, $like );
 			$searchand = ' AND ';
 		}
 
@@ -2086,11 +2088,11 @@
 
 		if ( $q['search_terms_count'] > 1 ) {
 			$num_terms = count( $q['search_orderby_title'] );
-			$search_orderby_s = like_escape( esc_sql( $q['s'] ) );
+			$like = '%' . $wpdb->esc_like( $q['s'] ) . '%';
 
 			$search_orderby = '(CASE ';
 			// sentence match in 'post_title'
-			$search_orderby .= "WHEN $wpdb->posts.post_title LIKE '%{$search_orderby_s}%' THEN 1 ";
+			$search_orderby .= $wpdb->prepare( "WHEN $wpdb->posts.post_title LIKE %s THEN 1 ", $like );
 
 			// sanity limit, sort as sentence when more than 6 terms
 			// (few searches are longer than 6 terms and most titles are not)
@@ -2103,7 +2105,7 @@
 			}
 
 			// sentence match in 'post_content'
-			$search_orderby .= "WHEN $wpdb->posts.post_content LIKE '%{$search_orderby_s}%' THEN 4 ";
+			$search_orderby .= $wpdb->prepare( "WHEN $wpdb->posts.post_content LIKE %s THEN 4 ", $like );
 			$search_orderby .= 'ELSE 5 END)';
 		} else {
 			// single word or sentence search
Index: src/wp-includes/taxonomy.php
===================================================================
--- src/wp-includes/taxonomy.php	(revision 28706)
+++ src/wp-includes/taxonomy.php	(working copy)
@@ -1480,13 +1480,11 @@
 	}
 
 	if ( ! empty( $args['name__like'] ) ) {
-		$name__like = like_escape( $args['name__like'] );
-		$where .= $wpdb->prepare( " AND t.name LIKE %s", '%' . $name__like . '%' );
+		$where .= $wpdb->prepare( " AND t.name LIKE %s", '%' . $wpdb->esc_like( $args['name__like'] ) . '%' );
 	}
 
 	if ( ! empty( $args['description__like'] ) ) {
-		$description__like = like_escape( $args['description__like'] );
-		$where .= $wpdb->prepare( " AND tt.description LIKE %s", '%' . $description__like . '%' );
+		$where .= $wpdb->prepare( " AND tt.description LIKE %s", '%' . $wpdb->esc_like( $args['description__like'] ) . '%' );
 	}
 
 	if ( '' !== $parent ) {
@@ -1517,8 +1515,8 @@
 	}
 
 	if ( ! empty( $args['search'] ) ) {
-		$search = like_escape( $args['search'] );
-		$where .= $wpdb->prepare( ' AND ((t.name LIKE %s) OR (t.slug LIKE %s))', '%' . $search . '%', '%' . $search . '%' );
+		$like = '%' . $wpdb->esc_like( $args['search'] ) . '%';
+		$where .= $wpdb->prepare( ' AND ((t.name LIKE %s) OR (t.slug LIKE %s))', $like, $like );
 	}
 
 	$selects = array();
Index: src/wp-includes/user.php
===================================================================
--- src/wp-includes/user.php	(revision 28706)
+++ src/wp-includes/user.php	(working copy)
@@ -797,7 +797,7 @@
 	 * @return string
 	 */
 	protected function get_search_sql( $string, $cols, $wild = false ) {
-		$string = esc_sql( $string );
+		global $wpdb;
 
 		$searches = array();
 		$leading_wild = ( 'leading' == $wild || 'both' == $wild ) ? '%' : '';
@@ -804,9 +804,9 @@
 		$trailing_wild = ( 'trailing' == $wild || 'both' == $wild ) ? '%' : '';
 		foreach ( $cols as $col ) {
 			if ( 'ID' == $col )
-				$searches[] = "$col = '$string'";
+				$searches[] = $wpdb->prepare( "$col = %s", $string );
 			else
-				$searches[] = "$col LIKE '$leading_wild" . like_escape($string) . "$trailing_wild'";
+				$searches[] = $wpdb->prepare( "$col LIKE %s", $leading_wild . $wpdb->esc_like( $string ) . $trailing_wild );
 		}
 
 		return ' AND (' . implode(' OR ', $searches) . ')';
@@ -1149,7 +1149,7 @@
 		// Build a CPU-intensive query that will return concise information.
 		$select_count = array();
 		foreach ( $avail_roles as $this_role => $name ) {
-			$select_count[] = "COUNT(NULLIF(`meta_value` LIKE '%\"" . like_escape( $this_role ) . "\"%', false))";
+			$select_count[] = $wpdb->prepare( "COUNT(NULLIF(`meta_value` LIKE %s, false))", '%' . $wpdb->esc_like( '"' . $this_role . '"' ) . '%');
 		}
 		$select_count = implode(', ', $select_count);
 
Index: src/wp-includes/wp-db.php
===================================================================
--- src/wp-includes/wp-db.php	(revision 28706)
+++ src/wp-includes/wp-db.php	(working copy)
@@ -1169,6 +1169,29 @@
 	}
 
 	/**
+	 * First half of escaping for LIKE special characters % and _ before preparing for MySQL.
+	 *
+	 * Use this only before wpdb::prepare() or esc_sql().  Reversing the order is very bad for security.
+	 *
+	 * Example Prepared Statement:
+	 *  $wild = '%';
+	 *  $find = 'only 43% of planets';
+	 *  $like = $wild . $wpdb->esc_like( $find ) . $wild;
+	 *  $sql  = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_content LIKE %s", $like );
+	 *
+	 * Example Escape Chain:
+	 *  $sql  = esc_sql( $wpdb->esc_like( $input ) );
+	 *
+	 * @since 4.0.0
+	 *
+	 * @param string $text The raw text to be escaped. The input typed by the user should have no extra or deleted slashes.
+	 * @return string Text in the form of a LIKE phrase. The output is not SQL safe. Call prepare or real_escape next.
+	 */
+	function esc_like($text) {
+		return addcslashes( $text, '_%\\' );
+	}
+
+	/**
 	 * Print SQL/DB error.
 	 *
 	 * @since 0.71
Index: tests/phpunit/tests/db.php
===================================================================
--- tests/phpunit/tests/db.php	(revision 28706)
+++ tests/phpunit/tests/db.php	(working copy)
@@ -337,4 +337,103 @@
 		$row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->users WHERE ID = %d", $last ) );
 		$this->assertEquals( 'Walter Replace Sobchak', $row->display_name );
 	}
+
+	/**
+	 * @ticket 10041
+	 */
+	function test_esc_like() {
+		global $wpdb;
+
+		$inputs = array(
+			'howdy%', //Single Percent
+			'howdy_', //Single Underscore
+			'howdy\\', //Single slash
+			'howdy\\howdy%howdy_', //The works
+			'howdy\'"[[]*#[^howdy]!+)(*&$#@!~|}{=--`/.,<>?', //Plain text
+		);
+		$expected = array(
+			'howdy\\%',
+			'howdy\\_',
+			'howdy\\\\',
+			'howdy\\\\howdy\\%howdy\\_',
+			'howdy\'"[[]*#[^howdy]!+)(*&$#@!~|}{=--`/.,<>?',
+		);
+
+		foreach ($inputs as $key => $input) {
+			$this->assertEquals($expected[$key], $wpdb->esc_like($input));
+		}
+	}
+
+	/**
+	 * Test LIKE Queries
+	 *
+	 * Make sure $wpdb is fully compatible with esc_like() by testing the identity of various strings.
+	 * When escaped properly, a string literal is always LIKE itself (1)
+	 * and never LIKE any other string literal (0) no matter how crazy the SQL looks.
+	 *
+	 * @ticket 10041
+	 * @dataProvider data_like_query
+	 * @param $data string The haystack, raw.
+	 * @param $like string The like phrase, raw.
+         * @param $result string The expected comparison result; '1' = true, '0' = false
+	 */
+	function test_like_query( $data, $like, $result ) {
+		global $wpdb;
+		return $this->assertEquals( $result, $wpdb->get_var( $wpdb->prepare( "SELECT %s LIKE %s", $data, $wpdb->esc_like( $like ) ) ) );
+	}
+
+	function data_like_query() {
+		return array(
+			array(
+				'aaa',
+				'aaa',
+				'1',
+			),
+			array(
+				'a\\aa', // SELECT 'a\\aa'  # This represents a\aa in both languages.
+				'a\\aa', // LIKE 'a\\\\aa'
+				'1',
+			),
+			array(
+				'a%aa',
+				'a%aa',
+				'1',
+			),
+			array(
+				'aaaa',
+				'a%aa',
+				'0',
+			),
+			array(
+				'a\\%aa', // SELECT 'a\\%aa'
+				'a\\%aa', // LIKE 'a\\\\\\%aa' # The PHP literal would be "LIKE 'a\\\\\\\\\\\\%aa'".  This is why we need reliable escape functions!
+				'1',
+			),
+			array(
+				'a%aa',
+				'a\\%aa',
+				'0',
+			),
+			array(
+				'a\\%aa',
+				'a%aa',
+				'0',
+			),
+			array(
+				'a_aa',
+				'a_aa',
+				'1',
+			),
+			array(
+				'aaaa',
+				'a_aa',
+				'0',
+			),
+			array(
+				'howdy\'"[[]*#[^howdy]!+)(*&$#@!~|}{=--`/.,<>?',
+				'howdy\'"[[]*#[^howdy]!+)(*&$#@!~|}{=--`/.,<>?',
+				'1',
+			),
+		);
+	}
 }
Index: tests/phpunit/tests/formatting/LikeEscape.php
===================================================================
--- tests/phpunit/tests/formatting/LikeEscape.php	(revision 28706)
+++ tests/phpunit/tests/formatting/LikeEscape.php	(working copy)
@@ -1,29 +0,0 @@
-<?php
-
-/**
- * @group formatting
- */
-class Tests_Formatting_LikeEscape extends WP_UnitTestCase {
-	/**
-	 * @ticket 10041
-	 */
-	function test_like_escape() {
-
-		$inputs = array(
-			'howdy%', //Single Percent
-			'howdy_', //Single Underscore
-			'howdy\\', //Single slash
-			'howdy\\howdy%howdy_', //The works
-		);
-		$expected = array(
-			"howdy\\%",
-			'howdy\\_',
-			'howdy\\\\',
-			'howdy\\\\howdy\\%howdy\\_'
-		);
-
-		foreach ($inputs as $key => $input) {
-			$this->assertEquals($expected[$key], like_escape($input));
-		}
-	}
-}
