Index: branches/5.2.x/core/units/helpers/curl_helper.php =================================================================== diff -u -N -r14671 -r15337 --- branches/5.2.x/core/units/helpers/curl_helper.php (.../curl_helper.php) (revision 14671) +++ branches/5.2.x/core/units/helpers/curl_helper.php (.../curl_helper.php) (revision 15337) @@ -1,6 +1,6 @@ followLocation && ((defined('SAFE_MODE') && SAFE_MODE) || ini_get('open_basedir'))) { - // this won't work with such restrictions, so turn it off - $this->followLocation = false; - } - $default_options = Array ( // customizable options - CURLOPT_FOLLOWLOCATION => $this->followLocation ? 1 : 0, CURLOPT_TIMEOUT => $this->timeout, // hardcoded options @@ -376,14 +378,58 @@ $this->responseHeaders = Array (); $this->prepareOptions(); - $this->lastResponse = curl_exec($this->connectionID); + $this->lastResponse = $this->execFollow(); $this->Finalize($close_connection); return $this->lastResponse; } /** + * Fixes curl inability to automatically follow location when safe_mode/open_basedir restriction in effect + * + * @param bool $headers_only + * @return string + * @access protected + */ + protected function execFollow($headers_only = false) + { + curl_setopt($this->connectionID, CURLOPT_HEADER, true); + curl_setopt($this->connectionID, CURLOPT_RETURNTRANSFER, true); + + if ( $this->followLocation && !$this->followLocationLimited() ) { + // no restrictions - let curl do automatic redirects + curl_setopt($this->connectionID, CURLOPT_FOLLOWLOCATION, true); + } + + $data = curl_exec($this->connectionID); + $http_code = $this->getInfo(CURLINFO_HTTP_CODE); + + if ( $http_code == 301 || $http_code == 302 ) { + // safe more or open_basedir restriction - do redirects manually + list ($header) = explode("\r\n\r\n", $data, 2); + preg_match('/(Location:|URI:)(.*?)\n/', $header, $regs); + $url = trim(array_pop($regs)); + $url_parsed = parse_url($url); + + if ( isset($url_parsed) ) { + curl_setopt($this->connectionID, CURLOPT_URL, $url); + $this->lastRedirectCount++; + + return $this->execFollow($headers_only); + } + } + + if ( $headers_only ) { + return $data; + } + + list(, $body) = explode("\r\n\r\n", $data, 2); + + return $body; + } + + /** * Returns various info about request made * * @param int $info_type @@ -394,10 +440,25 @@ */ public function getInfo($info_type) { + if ( $info_type == CURLINFO_REDIRECT_COUNT && $this->followLocationLimited() ) { + return $this->lastRedirectCount; + } + return curl_getinfo($this->connectionID, $info_type); } /** + * Detects, that follow location can't be done automatically by curl due safe_mode/open_basedir restrictions + * + * @return bool + * @access protected + */ + protected function followLocationLimited() + { + return (defined('SAFE_MODE') && SAFE_MODE) || ini_get('open_basedir'); + } + + /** * Finalizes curl request and saves some data from curl before closing connection * * @param bool $close_connection @@ -408,7 +469,7 @@ { $this->lastErrorCode = curl_errno($this->connectionID); $this->lastErrorMsg = curl_error($this->connectionID); - $this->lastHTTPCode = curl_getinfo($this->connectionID, CURLINFO_HTTP_CODE); + $this->lastHTTPCode = $this->getInfo(CURLINFO_HTTP_CODE); if ( $close_connection ) { $this->CloseConnection();