Index: src/wp-includes/class-http.php
===================================================================
--- src/wp-includes/class-http.php	(revision 25303)
+++ src/wp-includes/class-http.php	(working copy)
@@ -166,6 +166,9 @@
 		// Construct Cookie: header if any cookies are set
 		WP_Http::buildCookieHeader( $r );
 
+		// Avoid issues where mbstring.func_overload is enabled
+		mbstring_binary_safe_encoding();
+
 		if ( ! isset( $r['headers']['Accept-Encoding'] ) ) {
 			if ( $encoding = WP_Http_Encoding::accept_encoding( $url, $r ) )
 				$r['headers']['Accept-Encoding'] = $encoding;
@@ -187,6 +190,9 @@
 		}
 
 		$response = $this->_dispatch_request( $url, $r );
+
+		reset_mbstring_encoding();
+
 		if ( is_wp_error( $response ) )
 			return $response;
 
@@ -1311,11 +1317,6 @@
 	 * @return int
 	 */
 	private function stream_body( $handle, $data ) {
-		if ( function_exists( 'ini_get' ) && ( ini_get( 'mbstring.func_overload' ) & 2 ) && function_exists( 'mb_internal_encoding' ) ) {
-			$mb_encoding = mb_internal_encoding();
-			mb_internal_encoding( 'ISO-8859-1' );
-		}
-
 		$data_length = strlen( $data );
 
 		if ( $this->max_body_length && ( strlen( $this->body ) + $data_length ) > $this->max_body_length )
@@ -1328,9 +1329,6 @@
 			$bytes_written = $data_length;
 		}
 
-		if ( isset( $mb_encoding ) )
-			mb_internal_encoding( $mb_encoding );
-
 		// Upon event of this function returning less than strlen( $data ) curl will error with CURLE_WRITE_ERROR
 		return $bytes_written;
 	}
Index: src/wp-includes/functions.php
===================================================================
--- src/wp-includes/functions.php	(revision 25302)
+++ src/wp-includes/functions.php	(working copy)
@@ -4092,3 +4092,54 @@
 
 	return $charset;
 }
+
+/**
+ * Sets the mbstring internal encoding to a binary safe encoding whne func_overload is enabled.
+ *
+ * When mbstring.func_overload is in use for multi-byte encodings, the results from strlen() and
+ * similar functions respect the utf8 characters, causing binary data to return incorrect lengths.
+ *
+ * This function overrides the mbstring encoding to a binary-safe encoding, and resets it to the
+ * users expected encoding afterwards through the `reset_mbstring_encoding` function.
+ *
+ * It is safe to recursively call this function, however each `mbstring_binary_safe_encoding` call
+ * must be followed up with an equal number of `reset_mbstring_encoding` calls.
+ *
+ * @see reset_mbstring_encoding()
+ *
+ * @since 3.7.0
+ *
+ * @param bool $reset Whether to reset the encoding back to a previously-set encoding.
+ */
+function mbstring_binary_safe_encoding( $reset = false ) {
+	static $encodings = array();
+	static $overloaded = null;
+
+	if ( is_null( $overloaded ) )
+		$overloaded = function_exists( 'ini_get' ) && ( ini_get( 'mbstring.func_overload' ) & 2 ) && function_exists( 'mb_internal_encoding' );
+
+	if ( false === $overloaded )
+		return;
+
+	if ( ! $reset ) {
+		$encoding = mb_internal_encoding();
+		array_push( $encodings, $encoding );
+		mb_internal_encoding( 'ISO-8859-1' );
+	}
+
+	if ( $reset && $encodings ) {
+		$encoding = array_pop( $encodings );
+		mb_internal_encoding( $encoding );
+	}
+}
+
+/**
+ * Resets the mbstring internal encoding to a users previously set encoding.
+ *
+ * @see mbstring_binary_safe_encoding()
+ *
+ * @since 3.7.0
+ */
+function reset_mbstring_encoding() {
+	mbstring_binary_safe_encoding( true );
+}
\ No newline at end of file
Index: src/wp-admin/includes/file.php
===================================================================
--- src/wp-admin/includes/file.php	(revision 25302)
+++ src/wp-admin/includes/file.php	(working copy)
@@ -642,11 +642,7 @@
 function _unzip_file_pclzip($file, $to, $needed_dirs = array()) {
 	global $wp_filesystem;
 
-	// See #15789 - PclZip uses string functions on binary data, If it's overloaded with Multibyte safe functions the results are incorrect.
-	if ( ( ini_get('mbstring.func_overload') & 2 ) && function_exists('mb_internal_encoding') ) {
-		$previous_encoding = mb_internal_encoding();
-		mb_internal_encoding('ISO-8859-1');
-	}
+	mbstring_binary_safe_encoding();
 
 	require_once(ABSPATH . 'wp-admin/includes/class-pclzip.php');
 
@@ -654,8 +650,7 @@
 
 	$archive_files = $archive->extract(PCLZIP_OPT_EXTRACT_AS_STRING);
 
-	if ( isset($previous_encoding) )
-		mb_internal_encoding($previous_encoding);
+	reset_mbstring_encoding();
 
 	// Is the archive valid?
 	if ( !is_array($archive_files) )
