Index: wp-includes/class-http.php
===================================================================
--- wp-includes/class-http.php (revision 17444)
+++ wp-includes/class-http.php (working copy)
@@ -227,7 +227,9 @@
'body' => null,
'compress' => false,
'decompress' => true,
- 'sslverify' => true
+ 'sslverify' => true,
+ 'stream' => false,
+ 'filename' => null
);
$r = wp_parse_args( $args, $defaults );
@@ -255,6 +257,15 @@
$r['local'] = $homeURL['host'] == $arrURL['host'] || 'localhost' == $arrURL['host'];
unset( $homeURL );
+ if ( $r['stream'] && ! $r['filename'] )
+ $r['filename'] = get_temp_dir() . basename( $url );
+
+ if ( $r['stream'] ) {
+ $r['blocking'] = true;
+ if ( ! is_dir( dirname( $r['filename'] ) ) || ! is_writable( dirname( $r['filename'] ) ) )
+ return new WP_Error( 'http_request_failed', __( 'Destination directory for file streaming does not exist or is not writable.' ) );
+ }
+
if ( is_null( $r['headers'] ) )
$r['headers'] = array();
@@ -748,16 +759,44 @@
}
$strResponse = '';
- while ( ! feof($handle) )
- $strResponse .= fread($handle, 4096);
+ $bodyStarted = false;
- fclose($handle);
+ if ( $r['stream'] )
+ $stream_handle = fopen( $r['filename'], 'w+' );
+ while ( ! feof($handle) ) {
+ if ( $r['stream'] ) {
+ $block = fread( $handle, 4096 );
+ if ( $bodyStarted ) {
+ fwrite( $stream_handle, $block );
+ } else {
+ $strResponse .= $block;
+ if ( strpos( $strResponse, "\r\n\r\n" ) ) {
+ $process = WP_Http::processResponse( $strResponse );
+ $bodyStarted = true;
+ fwrite( $stream_handle, $process['body'] );
+ unset( $strResponse );
+ $process['body'] = '';
+ }
+ }
+ } else {
+ $strResponse .= fread( $handle, 4096 );
+ }
+ }
+
+ fclose( $handle );
+
if ( true === $secure_transport )
error_reporting($error_reporting);
- $process = WP_Http::processResponse($strResponse);
- $arrHeaders = WP_Http::processHeaders($process['headers']);
+ if ( $r['stream'] ) {
+ fclose( $stream_handle );
+ $arrHeaders = WP_Http::processHeaders( $process['headers'] );
+ } else {
+ $process = WP_Http::processResponse( $strResponse );
+ $arrHeaders = WP_Http::processHeaders( $process['headers'] );
+ unset( $strResponse );
+ }
// Is the response code within the 400 range?
if ( (int) $arrHeaders['response']['code'] >= 400 && (int) $arrHeaders['response']['code'] < 500 )
@@ -779,7 +818,7 @@
if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($arrHeaders['headers']) )
$process['body'] = WP_Http_Encoding::decompress( $process['body'] );
- return array('headers' => $arrHeaders['headers'], 'body' => $process['body'], 'response' => $arrHeaders['response'], 'cookies' => $arrHeaders['cookies']);
+ return array('headers' => $arrHeaders['headers'], 'body' => $process['body'], 'response' => $arrHeaders['response'], 'cookies' => $arrHeaders['cookies'], 'filename' => $r['filename']);
}
/**
@@ -1075,10 +1114,17 @@
return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() );
}
- $strResponse = stream_get_contents($handle);
- $meta = stream_get_meta_data($handle);
+ if ( $r['stream'] ) {
+ $stream_handle = fopen( $r['filename'], 'w+' );
+ stream_copy_to_stream( $handle, $stream_handle );
+ fclose( $stream_handle );
+ $strResponse = '';
+ } else {
+ $strResponse = stream_get_contents( $handle );
+ }
+ $meta = stream_get_meta_data( $handle );
- fclose($handle);
+ fclose( $handle );
$processedHeaders = array();
if ( isset( $meta['wrapper_data']['headers'] ) )
@@ -1092,7 +1138,7 @@
if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($processedHeaders['headers']) )
$strResponse = WP_Http_Encoding::decompress( $strResponse );
- return array('headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response'], 'cookies' => $processedHeaders['cookies']);
+ return array('headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response'], 'cookies' => $processedHeaders['cookies'], 'filename' => $r['filename']);
}
/**
@@ -1291,6 +1337,8 @@
*/
class WP_Http_Curl {
+ private $headers;
+
/**
* Send a HTTP request to a URI using cURL extension.
*
@@ -1387,6 +1435,12 @@
else
curl_setopt( $handle, CURLOPT_HEADER, false );
+ if ( $r['stream'] ) {
+ $stream_handle = fopen( $r['filename'], 'w+' );
+ curl_setopt( $handle, CURLOPT_FILE, $stream_handle );
+ curl_setopt( $handle, CURLOPT_HEADERFUNCTION, array( &$this, 'stream_headers' ) );
+ }
+
// The option doesn't work with safe mode or when open_basedir is set.
// Disable HEAD when making HEAD requests.
if ( !ini_get('safe_mode') && !ini_get('open_basedir') && 'HEAD' != $r['method'] )
@@ -1420,15 +1474,20 @@
$theResponse = curl_exec( $handle );
if ( !empty($theResponse) ) {
- $headerLength = curl_getinfo($handle, CURLINFO_HEADER_SIZE);
- $theHeaders = trim( substr($theResponse, 0, $headerLength) );
- if ( strlen($theResponse) > $headerLength )
- $theBody = substr( $theResponse, $headerLength );
- else
+ if ( ! empty( $this->headers ) ) {
+ $theHeaders = $this->headers;
$theBody = '';
- if ( false !== strpos($theHeaders, "\r\n\r\n") ) {
- $headerParts = explode("\r\n\r\n", $theHeaders);
- $theHeaders = $headerParts[ count($headerParts) -1 ];
+ } else {
+ $headerLength = curl_getinfo($handle, CURLINFO_HEADER_SIZE);
+ $theHeaders = trim( substr($theResponse, 0, $headerLength) );
+ if ( strlen($theResponse) > $headerLength )
+ $theBody = substr( $theResponse, $headerLength );
+ else
+ $theBody = '';
+ if ( false !== strpos($theHeaders, "\r\n\r\n") ) {
+ $headerParts = explode("\r\n\r\n", $theHeaders);
+ $theHeaders = $headerParts[ count($headerParts) - 1 ];
+ }
}
$theHeaders = WP_Http::processHeaders($theHeaders);
} else {
@@ -1447,6 +1506,9 @@
curl_close( $handle );
+ if ( $r['stream'] )
+ fclose( $stream_handle );
+
// See #11305 - When running under safe mode, redirection is disabled above. Handle it manually.
if ( !empty($theHeaders['headers']['location']) && (ini_get('safe_mode') || ini_get('open_basedir')) ) {
if ( $r['redirection']-- > 0 ) {
@@ -1459,9 +1521,14 @@
if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($theHeaders['headers']) )
$theBody = WP_Http_Encoding::decompress( $theBody );
- return array('headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $response, 'cookies' => $theHeaders['cookies']);
+ return array('headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $response, 'cookies' => $theHeaders['cookies'], 'filename' => $r['filename']);
}
+ function stream_headers( $handle, $headers ) {
+ $this->headers .= $headers;
+ return strlen($headers);
+ }
+
/**
* Whether this class can be used for retrieving an URL.
*
Index: wp-includes/functions.php
===================================================================
--- wp-includes/functions.php (revision 17444)
+++ wp-includes/functions.php (working copy)
@@ -2111,6 +2111,42 @@
}
/**
+ * Determines a writable directory for temporary files.
+ * Function's preference is to WP_CONTENT_DIR followed by the return value of sys_get_temp_dir()
, before finally defaulting to /tmp/
+ *
+ * In the event that this function does not find a writable location, It may be overridden by the WP_TEMP_DIR
constant in your wp-config.php
file.
+ *
+ * @since 2.5.0
+ *
+ * @return string Writable temporary directory
+ */
+function get_temp_dir() {
+ static $temp;
+ if ( defined('WP_TEMP_DIR') )
+ return trailingslashit(WP_TEMP_DIR);
+
+ if ( $temp )
+ return trailingslashit($temp);
+
+ $temp = WP_CONTENT_DIR . '/';
+ if ( is_dir($temp) && @is_writable($temp) )
+ return $temp;
+
+ if ( function_exists('sys_get_temp_dir') ) {
+ $temp = sys_get_temp_dir();
+ if ( @is_writable($temp) )
+ return trailingslashit($temp);
+ }
+
+ $temp = ini_get('upload_tmp_dir');
+ if ( is_dir($temp) && @is_writable($temp) )
+ return trailingslashit($temp);
+
+ $temp = '/tmp/';
+ return $temp;
+}
+
+/**
* Get an array containing the current upload directory's path and url.
*
* Checks the 'upload_path' option, which should be from the web root folder,
Index: wp-admin/includes/file.php
===================================================================
--- wp-admin/includes/file.php (revision 17444)
+++ wp-admin/includes/file.php (working copy)
@@ -153,42 +153,6 @@
}
/**
- * Determines a writable directory for temporary files.
- * Function's preference is to WP_CONTENT_DIR followed by the return value of sys_get_temp_dir()
, before finally defaulting to /tmp/
- *
- * In the event that this function does not find a writable location, It may be overridden by the WP_TEMP_DIR
constant in your wp-config.php
file.
- *
- * @since 2.5.0
- *
- * @return string Writable temporary directory
- */
-function get_temp_dir() {
- static $temp;
- if ( defined('WP_TEMP_DIR') )
- return trailingslashit(WP_TEMP_DIR);
-
- if ( $temp )
- return trailingslashit($temp);
-
- $temp = WP_CONTENT_DIR . '/';
- if ( is_dir($temp) && @is_writable($temp) )
- return $temp;
-
- if ( function_exists('sys_get_temp_dir') ) {
- $temp = sys_get_temp_dir();
- if ( @is_writable($temp) )
- return trailingslashit($temp);
- }
-
- $temp = ini_get('upload_tmp_dir');
- if ( is_dir($temp) && @is_writable($temp) )
- return trailingslashit($temp);
-
- $temp = '/tmp/';
- return $temp;
-}
-
-/**
* Returns a filename of a Temporary unique file.
* Please note that the calling function must unlink() this itself.
*