WordPress.org

Make WordPress Core

Ticket #16236: 16236.14.diff

File 16236.14.diff, 14.6 KB (added by sivel, 3 years ago)

Remove wp_list_pluck code, and fix body contents for cURL when streaming to a file

  • wp-includes/class-http.php

     
    9797                        'body' => null, 
    9898                        'compress' => false, 
    9999                        'decompress' => true, 
    100                         'sslverify' => true 
     100                        'sslverify' => true, 
     101                        'stream' => false, 
     102                        'filename' => null 
    101103                ); 
    102104 
    103105                 
     
    136138                $r['local'] = $homeURL['host'] == $arrURL['host'] || 'localhost' == $arrURL['host']; 
    137139                unset( $homeURL ); 
    138140 
     141                // If we are streaming to a file but no filename was given drop it in the WP temp dir 
     142                // and pick it's name using the basename of the $url 
     143                if ( $r['stream']  && empty( $r['filename'] ) ) 
     144                        $r['filename'] = get_temp_dir() . basename( $url ); 
     145 
     146                // Force some settings if we are streaming to a file and check for existence and perms of destination directory 
     147                if ( $r['stream'] ) { 
     148                        $r['blocking'] = true; 
     149                        if ( ! is_writable( dirname( $r['filename'] ) ) ) 
     150                                return new WP_Error( 'http_request_failed', __( 'Destination directory for file streaming does not exist or is not writable.' ) ); 
     151                } 
     152 
    139153                if ( is_null( $r['headers'] ) ) 
    140154                        $r['headers'] = array(); 
    141155 
     
    659673                } 
    660674 
    661675                $strResponse = ''; 
    662                 while ( ! feof($handle) ) 
    663                         $strResponse .= fread($handle, 4096); 
     676                $bodyStarted = false; 
    664677 
    665                 fclose($handle); 
     678                // If streaming to a file setup the file handle 
     679                if ( $r['stream'] ) { 
     680                        if ( ! WP_DEBUG ) 
     681                                $stream_handle = @fopen( $r['filename'], 'w+' ); 
     682                        else 
     683                                $stream_handle = fopen( $r['filename'], 'w+' ); 
     684                        if ( ! $stream_handle ) 
     685                                return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) ); 
    666686 
     687                        while ( ! feof($handle) ) { 
     688                                $block = fread( $handle, 4096 ); 
     689                                if ( $bodyStarted ) { 
     690                                        fwrite( $stream_handle, $block ); 
     691                                } else { 
     692                                        $strResponse .= $block; 
     693                                        if ( strpos( $strResponse, "\r\n\r\n" ) ) { 
     694                                                $process = WP_Http::processResponse( $strResponse ); 
     695                                                $bodyStarted = true; 
     696                                                fwrite( $stream_handle, $process['body'] ); 
     697                                                unset( $strResponse ); 
     698                                                $process['body'] = ''; 
     699                                        } 
     700                                } 
     701                        } 
     702 
     703                        fclose( $stream_handle ); 
     704 
     705                } else {  
     706                        while ( ! feof($handle) ) 
     707                                $strResponse .= fread( $handle, 4096 ); 
     708                } 
     709 
     710                fclose( $handle ); 
     711 
    667712                if ( true === $secure_transport ) 
    668713                        error_reporting($error_reporting); 
    669714 
    670                 $process = WP_Http::processResponse($strResponse); 
    671                 $arrHeaders = WP_Http::processHeaders($process['headers']); 
     715                if ( $r['stream'] ) { 
     716                        $arrHeaders = WP_Http::processHeaders( $process['headers'] ); 
     717                } else { 
     718                        $process = WP_Http::processResponse( $strResponse ); 
     719                        $arrHeaders = WP_Http::processHeaders( $process['headers'] ); 
     720                        unset( $strResponse ); 
     721                } 
    672722 
    673723                // Is the response code within the 400 range? 
    674724                if ( (int) $arrHeaders['response']['code'] >= 400 && (int) $arrHeaders['response']['code'] < 500 ) 
     
    690740                if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($arrHeaders['headers']) ) 
    691741                        $process['body'] = WP_Http_Encoding::decompress( $process['body'] ); 
    692742 
    693                 return array('headers' => $arrHeaders['headers'], 'body' => $process['body'], 'response' => $arrHeaders['response'], 'cookies' => $arrHeaders['cookies']); 
     743                return array( 'headers' => $arrHeaders['headers'], 'body' => $process['body'], 'response' => $arrHeaders['response'], 'cookies' => $arrHeaders['cookies'], 'filename' => $r['filename'] ); 
    694744        } 
    695745 
    696746        /** 
     
    834884                        return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() ); 
    835885                } 
    836886 
    837                 $strResponse = stream_get_contents($handle); 
    838                 $meta = stream_get_meta_data($handle); 
     887                if ( $r['stream'] ) { 
     888                        if ( ! WP_DEBUG ) 
     889                                $stream_handle = @fopen( $r['filename'], 'w+' ); 
     890                        else 
     891                                $stream_handle = fopen( $r['filename'], 'w+' ); 
     892                        if ( ! $stream_handle ) 
     893                                return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) ); 
     894                        stream_copy_to_stream( $handle, $stream_handle ); 
     895                        fclose( $stream_handle ); 
     896                        $strResponse = ''; 
     897                } else { 
     898                        $strResponse = stream_get_contents( $handle ); 
     899                } 
    839900 
    840                 fclose($handle); 
     901                $meta = stream_get_meta_data( $handle ); 
    841902 
     903                fclose( $handle ); 
     904 
    842905                $processedHeaders = array(); 
    843906                if ( isset( $meta['wrapper_data']['headers'] ) ) 
    844907                        $processedHeaders = WP_Http::processHeaders($meta['wrapper_data']['headers']); 
     
    856919                if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($processedHeaders['headers']) ) 
    857920                        $strResponse = WP_Http_Encoding::decompress( $strResponse ); 
    858921 
    859                 return array('headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response'], 'cookies' => $processedHeaders['cookies']); 
     922                return array( 'headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response'], 'cookies' => $processedHeaders['cookies'], 'filename' => $r['filename'] ); 
    860923        } 
    861924 
    862925        /** 
     
    10061069                if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($theHeaders['headers']) ) 
    10071070                        $theBody = http_inflate( $theBody ); 
    10081071 
     1072                if ( $r['stream'] ) { 
     1073                        if ( !WP_DEBUG ) 
     1074                                $stream_handle = @fopen( $r['filename'], 'w+' ); 
     1075                        else 
     1076                                $stream_handle = fopen( $r['filename'], 'w+' ); 
     1077 
     1078                        if ( ! $stream_handle ) 
     1079                                return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) ); 
     1080 
     1081                        fwrite( $stream_handle, $theBody ); 
     1082                        fclose( $stream_handle ); 
     1083                        $theBody = ''; 
     1084                } 
     1085 
    10091086                $theResponse = array(); 
    10101087                $theResponse['code'] = $info['response_code']; 
    10111088                $theResponse['message'] = get_status_header_desc($info['response_code']); 
    10121089 
    1013                 return array('headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $theResponse, 'cookies' => $theHeaders['cookies']); 
     1090                return array( 'headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $theResponse, 'cookies' => $theHeaders['cookies'], 'filename' => $r['filename'] ); 
    10141091        } 
    10151092 
    10161093        /** 
     
    10381115class WP_Http_Curl { 
    10391116 
    10401117        /** 
     1118         * Temporary header storage for use with streaming to a file. 
     1119         * 
     1120         * @since 3.2.0 
     1121         * @access private 
     1122         * @var string 
     1123         */ 
     1124        private $headers; 
     1125 
     1126        /** 
    10411127         * Send a HTTP request to a URI using cURL extension. 
    10421128         * 
    10431129         * @access public 
     
    11211207                } 
    11221208 
    11231209                if ( true === $r['blocking'] ) 
    1124                         curl_setopt( $handle, CURLOPT_HEADER, true ); 
    1125                 else 
    1126                         curl_setopt( $handle, CURLOPT_HEADER, false ); 
     1210                        curl_setopt( $handle, CURLOPT_HEADERFUNCTION, array( &$this, 'stream_headers' ) ); 
    11271211 
     1212                curl_setopt( $handle, CURLOPT_HEADER, false ); 
     1213 
     1214                // If streaming to a file open a file handle, and setup our curl streaming handler 
     1215                if ( $r['stream'] ) { 
     1216                        if ( ! WP_DEBUG ) 
     1217                                $stream_handle = @fopen( $r['filename'], 'w+' ); 
     1218                        else 
     1219                                $stream_handle = fopen( $r['filename'], 'w+' ); 
     1220                        if ( ! $stream_handle ) 
     1221                                return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) ); 
     1222                        curl_setopt( $handle, CURLOPT_FILE, $stream_handle ); 
     1223                } 
     1224 
    11281225                // The option doesn't work with safe mode or when open_basedir is set. 
    11291226                if ( !ini_get('safe_mode') && !ini_get('open_basedir') && 0 !== $r['_redirection'] ) 
    11301227                        curl_setopt( $handle, CURLOPT_FOLLOWLOCATION, true ); 
     
    11551252                } 
    11561253 
    11571254                $theResponse = curl_exec( $handle ); 
     1255                $theBody = ''; 
     1256                $theHeaders = WP_Http::processHeaders( $this->headers ); 
    11581257 
    1159                 if ( !empty($theResponse) ) { 
    1160                         $headerLength = curl_getinfo($handle, CURLINFO_HEADER_SIZE); 
    1161                         $theHeaders = trim( substr($theResponse, 0, $headerLength) ); 
    1162                         if ( strlen($theResponse) > $headerLength ) 
    1163                                 $theBody = substr( $theResponse, $headerLength ); 
    1164                         else 
    1165                                 $theBody = ''; 
    1166                         if ( false !== strpos($theHeaders, "\r\n\r\n") ) { 
    1167                                 $headerParts = explode("\r\n\r\n", $theHeaders); 
    1168                                 $theHeaders = $headerParts[ count($headerParts) -1 ]; 
    1169                         } 
    1170                         $theHeaders = WP_Http::processHeaders($theHeaders); 
    1171                 } else { 
     1258                if ( ! empty($theResponse) && ! is_bool( $theResponse ) ) 
     1259                        $theBody = $theResponse; 
     1260 
     1261                // If no response, and It's not a HEAD request with valid headers returned 
     1262                if ( empty($theResponse) && 'HEAD' != $args['method'] && ! empty($this->headers) ) { 
    11721263                        if ( $curl_error = curl_error($handle) ) 
    11731264                                return new WP_Error('http_request_failed', $curl_error); 
    11741265                        if ( in_array( curl_getinfo( $handle, CURLINFO_HTTP_CODE ), array(301, 302) ) ) 
    11751266                                return new WP_Error('http_request_failed', __('Too many redirects.')); 
    1176  
    1177                         $theHeaders = array( 'headers' => array(), 'cookies' => array() ); 
    1178                         $theBody = ''; 
    11791267                } 
    11801268 
     1269                unset( $this->headers ); 
     1270 
    11811271                $response = array(); 
    11821272                $response['code'] = curl_getinfo( $handle, CURLINFO_HTTP_CODE ); 
    11831273                $response['message'] = get_status_header_desc($response['code']); 
    11841274 
    11851275                curl_close( $handle ); 
    11861276 
     1277                if ( $r['stream'] ) 
     1278                        fclose( $stream_handle ); 
     1279 
    11871280                // See #11305 - When running under safe mode, redirection is disabled above. Handle it manually. 
    1188                 if ( !empty($theHeaders['headers']['location']) && (ini_get('safe_mode') || ini_get('open_basedir')) && 0 !== $r['_redirection'] ) { 
     1281                if ( ! empty( $theHeaders['headers']['location'] ) && ( ini_get( 'safe_mode' ) || ini_get( 'open_basedir' ) ) && 0 !== $r['_redirection'] ) { 
    11891282                        if ( $r['redirection']-- > 0 ) { 
    1190                                 return $this->request($theHeaders['headers']['location'], $r); 
     1283                                return $this->request( $theHeaders['headers']['location'], $r ); 
    11911284                        } else { 
    1192                                 return new WP_Error('http_request_failed', __('Too many redirects.')); 
     1285                                return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) ); 
    11931286                        } 
    11941287                } 
    11951288 
    11961289                if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($theHeaders['headers']) ) 
    11971290                        $theBody = WP_Http_Encoding::decompress( $theBody ); 
    11981291 
    1199                 return array('headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $response, 'cookies' => $theHeaders['cookies']); 
     1292                return array( 'headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $response, 'cookies' => $theHeaders['cookies'], 'filename' => $r['filename'] ); 
    12001293        } 
    12011294 
    12021295        /** 
     1296         * Grab the headers of the cURL request 
     1297         * 
     1298         * Each header is sent individually to this callback, so we append to the $header property for temporary storage 
     1299         * 
     1300         * @since 3.2.0 
     1301         * @access private 
     1302         * @return int 
     1303         */ 
     1304        private function stream_headers( $handle, $headers ) { 
     1305                $this->headers .= $headers; 
     1306                return strlen( $headers ); 
     1307        } 
     1308 
     1309        /** 
    12031310         * Whether this class can be used for retrieving an URL. 
    12041311         * 
    12051312         * @static 
  • wp-includes/functions.php

     
    21112111} 
    21122112 
    21132113/** 
     2114 * Determines a writable directory for temporary files. 
     2115 * Function's preference is to WP_CONTENT_DIR followed by the return value of <code>sys_get_temp_dir()</code>, before finally defaulting to /tmp/ 
     2116 * 
     2117 * In the event that this function does not find a writable location, It may be overridden by the <code>WP_TEMP_DIR</code> constant in your <code>wp-config.php</code> file. 
     2118 * 
     2119 * @since 2.5.0 
     2120 * 
     2121 * @return string Writable temporary directory 
     2122 */ 
     2123function get_temp_dir() { 
     2124        static $temp; 
     2125        if ( defined('WP_TEMP_DIR') ) 
     2126                return trailingslashit(WP_TEMP_DIR); 
     2127 
     2128        if ( $temp ) 
     2129                return trailingslashit($temp); 
     2130 
     2131        $temp = WP_CONTENT_DIR . '/'; 
     2132        if ( is_dir($temp) && @is_writable($temp) ) 
     2133                return $temp; 
     2134 
     2135        if  ( function_exists('sys_get_temp_dir') ) { 
     2136                $temp = sys_get_temp_dir(); 
     2137                if ( @is_writable($temp) ) 
     2138                        return trailingslashit($temp); 
     2139        } 
     2140 
     2141        $temp = ini_get('upload_tmp_dir'); 
     2142        if ( is_dir($temp) && @is_writable($temp) ) 
     2143                return trailingslashit($temp); 
     2144 
     2145        $temp = '/tmp/'; 
     2146        return $temp; 
     2147} 
     2148 
     2149/** 
    21142150 * Get an array containing the current upload directory's path and url. 
    21152151 * 
    21162152 * Checks the 'upload_path' option, which should be from the web root folder, 
  • wp-admin/includes/file.php

     
    153153} 
    154154 
    155155/** 
    156  * Determines a writable directory for temporary files. 
    157  * Function's preference is to WP_CONTENT_DIR followed by the return value of <code>sys_get_temp_dir()</code>, before finally defaulting to /tmp/ 
    158  * 
    159  * In the event that this function does not find a writable location, It may be overridden by the <code>WP_TEMP_DIR</code> constant in your <code>wp-config.php</code> file. 
    160  * 
    161  * @since 2.5.0 
    162  * 
    163  * @return string Writable temporary directory 
    164  */ 
    165 function get_temp_dir() { 
    166         static $temp; 
    167         if ( defined('WP_TEMP_DIR') ) 
    168                 return trailingslashit(WP_TEMP_DIR); 
    169  
    170         if ( $temp ) 
    171                 return trailingslashit($temp); 
    172  
    173         $temp = WP_CONTENT_DIR . '/'; 
    174         if ( is_dir($temp) && @is_writable($temp) ) 
    175                 return $temp; 
    176  
    177         if  ( function_exists('sys_get_temp_dir') ) { 
    178                 $temp = sys_get_temp_dir(); 
    179                 if ( @is_writable($temp) ) 
    180                         return trailingslashit($temp); 
    181         } 
    182  
    183         $temp = ini_get('upload_tmp_dir'); 
    184         if ( is_dir($temp) && @is_writable($temp) ) 
    185                 return trailingslashit($temp); 
    186  
    187         $temp = '/tmp/'; 
    188         return $temp; 
    189 } 
    190  
    191 /** 
    192156 * Returns a filename of a Temporary unique file. 
    193157 * Please note that the calling function must unlink() this itself. 
    194158 * 
     
    513477function download_url( $url, $timeout = 300 ) { 
    514478        //WARNING: The file is not automatically deleted, The script must unlink() the file. 
    515479        if ( ! $url ) 
    516                 return new WP_Error('http_no_url', __('Invalid URL Provided.')); 
     480                return new WP_Error( 'http_no_url', __( 'Invalid URL Provided.' ) ); 
    517481 
    518         $tmpfname = wp_tempnam($url); 
     482        $tmpfname = wp_tempnam( $url ); 
    519483        if ( ! $tmpfname ) 
    520                 return new WP_Error('http_no_file', __('Could not create Temporary file.')); 
     484                return new WP_Error( 'http_no_file', __( 'Could not create Temporary file.' ) ); 
    521485 
    522         $handle = @fopen($tmpfname, 'wb'); 
    523         if ( ! $handle ) 
    524                 return new WP_Error('http_no_file', __('Could not create Temporary file.')); 
     486        $response = wp_remote_get( $url, array( 'timeout' => $timeout, 'stream' => true, 'filename' => $tmpfname ) ); 
    525487 
    526         $response = wp_remote_get($url, array('timeout' => $timeout)); 
    527  
    528         if ( is_wp_error($response) ) { 
    529                 fclose($handle); 
    530                 unlink($tmpfname); 
     488        if ( is_wp_error( $response ) ) { 
     489                unlink( $tmpfname ); 
    531490                return $response; 
    532491        } 
    533492 
    534493        if ( $response['response']['code'] != '200' ){ 
    535                 fclose($handle); 
    536                 unlink($tmpfname); 
    537                 return new WP_Error('http_404', trim($response['response']['message'])); 
     494                unlink( $tmpfname ); 
     495                return new WP_Error( 'http_404', trim( $response['response']['message'] ) ); 
    538496        } 
    539497 
    540         fwrite($handle, $response['body']); 
    541         fclose($handle); 
    542  
    543498        return $tmpfname; 
    544499} 
    545500