modified file w3-total-cache
This commit is contained in:
@ -0,0 +1,327 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstract IO base class
|
||||
*/
|
||||
|
||||
abstract class W3TCG_Google_IO_Abstract
|
||||
{
|
||||
const UNKNOWN_CODE = 0;
|
||||
const FORM_URLENCODED = 'application/x-www-form-urlencoded';
|
||||
private static $CONNECTION_ESTABLISHED_HEADERS = array(
|
||||
"HTTP/1.0 200 Connection established\r\n\r\n",
|
||||
"HTTP/1.1 200 Connection established\r\n\r\n",
|
||||
);
|
||||
private static $ENTITY_HTTP_METHODS = array("POST" => null, "PUT" => null);
|
||||
|
||||
/** @var W3TCG_Google_Client */
|
||||
protected $client;
|
||||
|
||||
public function __construct(W3TCG_Google_Client $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
$timeout = $client->getClassConfig('W3TCG_Google_IO_Abstract', 'request_timeout_seconds');
|
||||
if ($timeout > 0) {
|
||||
$this->setTimeout($timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a W3TCG_Google_Http_Request and returns the resulting populated W3TCG_Google_Http_Request
|
||||
* @param W3TCG_Google_Http_Request $request
|
||||
* @return W3TCG_Google_Http_Request $request
|
||||
*/
|
||||
abstract public function executeRequest(W3TCG_Google_Http_Request $request);
|
||||
|
||||
/**
|
||||
* Set options that update the transport implementation's behavior.
|
||||
* @param $options
|
||||
*/
|
||||
abstract public function setOptions($options);
|
||||
|
||||
/**
|
||||
* Set the maximum request time in seconds.
|
||||
* @param $timeout in seconds
|
||||
*/
|
||||
abstract public function setTimeout($timeout);
|
||||
|
||||
/**
|
||||
* Get the maximum request time in seconds.
|
||||
* @return timeout in seconds
|
||||
*/
|
||||
abstract public function getTimeout();
|
||||
|
||||
/**
|
||||
* Test for the presence of a cURL header processing bug
|
||||
*
|
||||
* The cURL bug was present in versions prior to 7.30.0 and caused the header
|
||||
* length to be miscalculated when a "Connection established" header added by
|
||||
* some proxies was present.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
abstract protected function needsQuirk();
|
||||
|
||||
/**
|
||||
* @visible for testing.
|
||||
* Cache the response to an HTTP request if it is cacheable.
|
||||
* @param W3TCG_Google_Http_Request $request
|
||||
* @return bool Returns true if the insertion was successful.
|
||||
* Otherwise, return false.
|
||||
*/
|
||||
public function setCachedRequest(W3TCG_Google_Http_Request $request)
|
||||
{
|
||||
// Determine if the request is cacheable.
|
||||
if (W3TCG_Google_Http_CacheParser::isResponseCacheable($request)) {
|
||||
$this->client->getCache()->set($request->getCacheKey(), $request);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an HTTP Request
|
||||
*
|
||||
* @param W3TCG_Google_HttpRequest $request the http request to be executed
|
||||
* @return W3TCG_Google_HttpRequest http request with the response http code,
|
||||
* response headers and response body filled in
|
||||
* @throws W3TCG_Google_IO_Exception on curl or IO error
|
||||
*/
|
||||
public function makeRequest(W3TCG_Google_Http_Request $request)
|
||||
{
|
||||
// First, check to see if we have a valid cached version.
|
||||
$cached = $this->getCachedRequest($request);
|
||||
if ($cached !== false && $cached instanceof W3TCG_Google_Http_Request) {
|
||||
if (!$this->checkMustRevalidateCachedRequest($cached, $request)) {
|
||||
return $cached;
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists($request->getRequestMethod(), self::$ENTITY_HTTP_METHODS)) {
|
||||
$request = $this->processEntityRequest($request);
|
||||
}
|
||||
|
||||
list($responseData, $responseHeaders, $respHttpCode) = $this->executeRequest($request);
|
||||
|
||||
if ($respHttpCode == 304 && $cached) {
|
||||
// If the server responded NOT_MODIFIED, return the cached request.
|
||||
$this->updateCachedRequest($cached, $responseHeaders);
|
||||
return $cached;
|
||||
}
|
||||
|
||||
if (!isset($responseHeaders['Date']) && !isset($responseHeaders['date'])) {
|
||||
$responseHeaders['Date'] = date("r");
|
||||
}
|
||||
|
||||
$request->setResponseHttpCode($respHttpCode);
|
||||
$request->setResponseHeaders($responseHeaders);
|
||||
$request->setResponseBody($responseData);
|
||||
// Store the request in cache (the function checks to see if the request
|
||||
// can actually be cached)
|
||||
$this->setCachedRequest($request);
|
||||
return $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* @visible for testing.
|
||||
* @param W3TCG_Google_Http_Request $request
|
||||
* @return W3TCG_Google_Http_Request|bool Returns the cached object or
|
||||
* false if the operation was unsuccessful.
|
||||
*/
|
||||
public function getCachedRequest(W3TCG_Google_Http_Request $request)
|
||||
{
|
||||
if (false === W3TCG_Google_Http_CacheParser::isRequestCacheable($request)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->client->getCache()->get($request->getCacheKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* @visible for testing
|
||||
* Process an http request that contains an enclosed entity.
|
||||
* @param W3TCG_Google_Http_Request $request
|
||||
* @return W3TCG_Google_Http_Request Processed request with the enclosed entity.
|
||||
*/
|
||||
public function processEntityRequest(W3TCG_Google_Http_Request $request)
|
||||
{
|
||||
$postBody = $request->getPostBody();
|
||||
$contentType = $request->getRequestHeader("content-type");
|
||||
|
||||
// Set the default content-type as application/x-www-form-urlencoded.
|
||||
if (false == $contentType) {
|
||||
$contentType = self::FORM_URLENCODED;
|
||||
$request->setRequestHeaders(array('content-type' => $contentType));
|
||||
}
|
||||
|
||||
// Force the payload to match the content-type asserted in the header.
|
||||
if ($contentType == self::FORM_URLENCODED && is_array($postBody)) {
|
||||
$postBody = http_build_query($postBody, '', '&');
|
||||
$request->setPostBody($postBody);
|
||||
}
|
||||
|
||||
// Make sure the content-length header is set.
|
||||
if (!$postBody || is_string($postBody)) {
|
||||
$postsLength = strlen($postBody);
|
||||
$request->setRequestHeaders(array('content-length' => $postsLength));
|
||||
}
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an already cached request must be revalidated, and if so update
|
||||
* the request with the correct ETag headers.
|
||||
* @param W3TCG_Google_Http_Request $cached A previously cached response.
|
||||
* @param W3TCG_Google_Http_Request $request The outbound request.
|
||||
* return bool If the cached object needs to be revalidated, false if it is
|
||||
* still current and can be re-used.
|
||||
*/
|
||||
protected function checkMustRevalidateCachedRequest($cached, $request)
|
||||
{
|
||||
if (W3TCG_Google_Http_CacheParser::mustRevalidate($cached)) {
|
||||
$addHeaders = array();
|
||||
if ($cached->getResponseHeader('etag')) {
|
||||
// [13.3.4] If an entity tag has been provided by the origin server,
|
||||
// we must use that entity tag in any cache-conditional request.
|
||||
$addHeaders['If-None-Match'] = $cached->getResponseHeader('etag');
|
||||
} elseif ($cached->getResponseHeader('date')) {
|
||||
$addHeaders['If-Modified-Since'] = $cached->getResponseHeader('date');
|
||||
}
|
||||
|
||||
$request->setRequestHeaders($addHeaders);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a cached request, using the headers from the last response.
|
||||
* @param W3TCG_Google_HttpRequest $cached A previously cached response.
|
||||
* @param mixed Associative array of response headers from the last request.
|
||||
*/
|
||||
protected function updateCachedRequest($cached, $responseHeaders)
|
||||
{
|
||||
if (isset($responseHeaders['connection'])) {
|
||||
$hopByHop = array_merge(
|
||||
self::$HOP_BY_HOP,
|
||||
explode(
|
||||
',',
|
||||
$responseHeaders['connection']
|
||||
)
|
||||
);
|
||||
|
||||
$endToEnd = array();
|
||||
foreach ($hopByHop as $key) {
|
||||
if (isset($responseHeaders[$key])) {
|
||||
$endToEnd[$key] = $responseHeaders[$key];
|
||||
}
|
||||
}
|
||||
$cached->setResponseHeaders($endToEnd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by the IO lib and also the batch processing.
|
||||
*
|
||||
* @param $respData
|
||||
* @param $headerSize
|
||||
* @return array
|
||||
*/
|
||||
public function parseHttpResponse($respData, $headerSize)
|
||||
{
|
||||
// check proxy header
|
||||
foreach (self::$CONNECTION_ESTABLISHED_HEADERS as $established_header) {
|
||||
if (stripos($respData, $established_header) !== false) {
|
||||
// existed, remove it
|
||||
$respData = str_ireplace($established_header, '', $respData);
|
||||
// Subtract the proxy header size unless the cURL bug prior to 7.30.0
|
||||
// is present which prevented the proxy header size from being taken into
|
||||
// account.
|
||||
if (!$this->needsQuirk()) {
|
||||
$headerSize -= strlen($established_header);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($headerSize) {
|
||||
$responseBody = substr($respData, $headerSize);
|
||||
$responseHeaders = substr($respData, 0, $headerSize);
|
||||
} else {
|
||||
$responseSegments = explode("\r\n\r\n", $respData, 2);
|
||||
$responseHeaders = $responseSegments[0];
|
||||
$responseBody = isset($responseSegments[1]) ? $responseSegments[1] :
|
||||
null;
|
||||
}
|
||||
|
||||
$responseHeaders = $this->getHttpResponseHeaders($responseHeaders);
|
||||
return array($responseHeaders, $responseBody);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse out headers from raw headers
|
||||
* @param rawHeaders array or string
|
||||
* @return array
|
||||
*/
|
||||
public function getHttpResponseHeaders($rawHeaders)
|
||||
{
|
||||
if (is_array($rawHeaders)) {
|
||||
return $this->parseArrayHeaders($rawHeaders);
|
||||
} else {
|
||||
return $this->parseStringHeaders($rawHeaders);
|
||||
}
|
||||
}
|
||||
|
||||
private function parseStringHeaders($rawHeaders)
|
||||
{
|
||||
$headers = array();
|
||||
$responseHeaderLines = explode("\r\n", $rawHeaders);
|
||||
foreach ($responseHeaderLines as $headerLine) {
|
||||
if ($headerLine && strpos($headerLine, ':') !== false) {
|
||||
list($header, $value) = explode(': ', $headerLine, 2);
|
||||
$header = strtolower($header);
|
||||
if (isset($headers[$header])) {
|
||||
$headers[$header] .= "\n" . $value;
|
||||
} else {
|
||||
$headers[$header] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $headers;
|
||||
}
|
||||
|
||||
private function parseArrayHeaders($rawHeaders)
|
||||
{
|
||||
$header_count = count($rawHeaders);
|
||||
$headers = array();
|
||||
|
||||
for ($i = 0; $i < $header_count; $i++) {
|
||||
$header = $rawHeaders[$i];
|
||||
// Times will have colons in - so we just want the first match.
|
||||
$header_parts = explode(': ', $header, 2);
|
||||
if (count($header_parts) == 2) {
|
||||
$headers[$header_parts[0]] = $header_parts[1];
|
||||
}
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Curl based implementation of W3TCG_Google_IO.
|
||||
*
|
||||
* @author Stuart Langley <slangley@google.com>
|
||||
*/
|
||||
|
||||
class W3TCG_Google_IO_Curl extends W3TCG_Google_IO_Abstract
|
||||
{
|
||||
// cURL hex representation of version 7.30.0
|
||||
const NO_QUIRK_VERSION = 0x071E00;
|
||||
|
||||
private $options = array();
|
||||
/**
|
||||
* Execute an HTTP Request
|
||||
*
|
||||
* @param W3TCG_Google_HttpRequest $request the http request to be executed
|
||||
* @return W3TCG_Google_HttpRequest http request with the response http code,
|
||||
* response headers and response body filled in
|
||||
* @throws W3TCG_Google_IO_Exception on curl or IO error
|
||||
*/
|
||||
public function executeRequest(W3TCG_Google_Http_Request $request)
|
||||
{
|
||||
$curl = curl_init();
|
||||
|
||||
if ($request->getPostBody()) {
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getPostBody());
|
||||
}
|
||||
|
||||
$requestHeaders = $request->getRequestHeaders();
|
||||
if ($requestHeaders && is_array($requestHeaders)) {
|
||||
$curlHeaders = array();
|
||||
foreach ($requestHeaders as $k => $v) {
|
||||
$curlHeaders[] = "$k: $v";
|
||||
}
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $curlHeaders);
|
||||
}
|
||||
|
||||
curl_setopt($curl, CURLOPT_URL, $request->getUrl());
|
||||
|
||||
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $request->getRequestMethod());
|
||||
curl_setopt($curl, CURLOPT_USERAGENT, $request->getUserAgent());
|
||||
|
||||
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
|
||||
curl_setopt($curl, CURLOPT_SSLVERSION, 1);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_HEADER, true);
|
||||
|
||||
if ($request->canGzip()) {
|
||||
curl_setopt($curl, CURLOPT_ENCODING, 'gzip,deflate');
|
||||
}
|
||||
|
||||
foreach ($this->options as $key => $var) {
|
||||
curl_setopt($curl, $key, $var);
|
||||
}
|
||||
|
||||
if (!isset($this->options[CURLOPT_CAINFO])) {
|
||||
curl_setopt($curl, CURLOPT_CAINFO, dirname(__FILE__) . '/cacerts.pem');
|
||||
}
|
||||
|
||||
$response = curl_exec($curl);
|
||||
if ($response === false) {
|
||||
throw new W3TCG_Google_IO_Exception(curl_error($curl));
|
||||
}
|
||||
$headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
|
||||
|
||||
list($responseHeaders, $responseBody) = $this->parseHttpResponse($response, $headerSize);
|
||||
|
||||
$responseCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||
|
||||
return array($responseBody, $responseHeaders, $responseCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set options that update the transport implementation's behavior.
|
||||
* @param $options
|
||||
*/
|
||||
public function setOptions($options)
|
||||
{
|
||||
$this->options = $options + $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum request time in seconds.
|
||||
* @param $timeout in seconds
|
||||
*/
|
||||
public function setTimeout($timeout)
|
||||
{
|
||||
// Since this timeout is really for putting a bound on the time
|
||||
// we'll set them both to the same. If you need to specify a longer
|
||||
// CURLOPT_TIMEOUT, or a tigher CONNECTTIMEOUT, the best thing to
|
||||
// do is use the setOptions method for the values individually.
|
||||
$this->options[CURLOPT_CONNECTTIMEOUT] = $timeout;
|
||||
$this->options[CURLOPT_TIMEOUT] = $timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum request time in seconds.
|
||||
* @return timeout in seconds
|
||||
*/
|
||||
public function getTimeout()
|
||||
{
|
||||
return $this->options[CURLOPT_TIMEOUT];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for the presence of a cURL header processing bug
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function needsQuirk()
|
||||
{
|
||||
$ver = curl_version();
|
||||
$versionNum = $ver['version_number'];
|
||||
return $versionNum < W3TCG_Google_IO_Curl::NO_QUIRK_VERSION;
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class W3TCG_Google_IO_Exception extends W3TCG_Google_Exception
|
||||
{
|
||||
}
|
@ -0,0 +1,209 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Http Streams based implementation of W3TCG_Google_IO.
|
||||
*
|
||||
* @author Stuart Langley <slangley@google.com>
|
||||
*/
|
||||
|
||||
class W3TCG_Google_IO_Stream extends W3TCG_Google_IO_Abstract
|
||||
{
|
||||
const TIMEOUT = "timeout";
|
||||
const ZLIB = "compress.zlib://";
|
||||
private $options = array();
|
||||
private $trappedErrorNumber;
|
||||
private $trappedErrorString;
|
||||
|
||||
private static $DEFAULT_HTTP_CONTEXT = array(
|
||||
"follow_location" => 0,
|
||||
"ignore_errors" => 1,
|
||||
);
|
||||
|
||||
private static $DEFAULT_SSL_CONTEXT = array(
|
||||
"verify_peer" => true,
|
||||
);
|
||||
|
||||
/**
|
||||
* Execute an HTTP Request
|
||||
*
|
||||
* @param W3TCG_Google_HttpRequest $request the http request to be executed
|
||||
* @return W3TCG_Google_HttpRequest http request with the response http code,
|
||||
* response headers and response body filled in
|
||||
* @throws W3TCG_Google_IO_Exception on curl or IO error
|
||||
*/
|
||||
public function executeRequest(W3TCG_Google_Http_Request $request)
|
||||
{
|
||||
$default_options = stream_context_get_options(stream_context_get_default());
|
||||
|
||||
$requestHttpContext = array_key_exists('http', $default_options) ?
|
||||
$default_options['http'] : array();
|
||||
|
||||
if ($request->getPostBody()) {
|
||||
$requestHttpContext["content"] = $request->getPostBody();
|
||||
}
|
||||
|
||||
$requestHeaders = $request->getRequestHeaders();
|
||||
if ($requestHeaders && is_array($requestHeaders)) {
|
||||
$headers = "";
|
||||
foreach ($requestHeaders as $k => $v) {
|
||||
$headers .= "$k: $v\r\n";
|
||||
}
|
||||
$requestHttpContext["header"] = $headers;
|
||||
}
|
||||
|
||||
$requestHttpContext["method"] = $request->getRequestMethod();
|
||||
$requestHttpContext["user_agent"] = $request->getUserAgent();
|
||||
|
||||
$requestSslContext = array_key_exists('ssl', $default_options) ?
|
||||
$default_options['ssl'] : array();
|
||||
|
||||
if (!array_key_exists("cafile", $requestSslContext)) {
|
||||
$requestSslContext["cafile"] = dirname(__FILE__) . '/cacerts.pem';
|
||||
}
|
||||
|
||||
$options = array(
|
||||
"http" => array_merge(
|
||||
self::$DEFAULT_HTTP_CONTEXT,
|
||||
$requestHttpContext
|
||||
),
|
||||
"ssl" => array_merge(
|
||||
self::$DEFAULT_SSL_CONTEXT,
|
||||
$requestSslContext
|
||||
)
|
||||
);
|
||||
|
||||
$context = stream_context_create($options);
|
||||
|
||||
$url = $request->getUrl();
|
||||
|
||||
if ($request->canGzip()) {
|
||||
$url = self::ZLIB . $url;
|
||||
}
|
||||
|
||||
// We are trapping any thrown errors in this method only and
|
||||
// throwing an exception.
|
||||
$this->trappedErrorNumber = null;
|
||||
$this->trappedErrorString = null;
|
||||
|
||||
// START - error trap.
|
||||
set_error_handler(array($this, 'trapError'));
|
||||
$fh = fopen($url, 'r', false, $context);
|
||||
restore_error_handler();
|
||||
// END - error trap.
|
||||
|
||||
if ($this->trappedErrorNumber) {
|
||||
throw new W3TCG_Google_IO_Exception(
|
||||
sprintf(
|
||||
"HTTP Error: Unable to connect: '%s'",
|
||||
$this->trappedErrorString
|
||||
),
|
||||
$this->trappedErrorNumber
|
||||
);
|
||||
}
|
||||
|
||||
$response_data = false;
|
||||
$respHttpCode = self::UNKNOWN_CODE;
|
||||
if ($fh) {
|
||||
if (isset($this->options[self::TIMEOUT])) {
|
||||
stream_set_timeout($fh, $this->options[self::TIMEOUT]);
|
||||
}
|
||||
|
||||
$response_data = stream_get_contents($fh);
|
||||
fclose($fh);
|
||||
|
||||
$respHttpCode = $this->getHttpResponseCode($http_response_header);
|
||||
}
|
||||
|
||||
if (false === $response_data) {
|
||||
throw new W3TCG_Google_IO_Exception(
|
||||
sprintf(
|
||||
"HTTP Error: Unable to connect: '%s'",
|
||||
$respHttpCode
|
||||
),
|
||||
$respHttpCode
|
||||
);
|
||||
}
|
||||
|
||||
$responseHeaders = $this->getHttpResponseHeaders($http_response_header);
|
||||
|
||||
return array($response_data, $responseHeaders, $respHttpCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set options that update the transport implementation's behavior.
|
||||
* @param $options
|
||||
*/
|
||||
public function setOptions($options)
|
||||
{
|
||||
$this->options = $options + $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to handle errors, used for error handling around
|
||||
* stream connection methods.
|
||||
*/
|
||||
public function trapError($errno, $errstr)
|
||||
{
|
||||
$this->trappedErrorNumber = $errno;
|
||||
$this->trappedErrorString = $errstr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum request time in seconds.
|
||||
* @param $timeout in seconds
|
||||
*/
|
||||
public function setTimeout($timeout)
|
||||
{
|
||||
$this->options[self::TIMEOUT] = $timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum request time in seconds.
|
||||
* @return timeout in seconds
|
||||
*/
|
||||
public function getTimeout()
|
||||
{
|
||||
return $this->options[self::TIMEOUT];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for the presence of a cURL header processing bug
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function needsQuirk()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getHttpResponseCode($response_headers)
|
||||
{
|
||||
$header_count = count($response_headers);
|
||||
|
||||
for ($i = 0; $i < $header_count; $i++) {
|
||||
$header = $response_headers[$i];
|
||||
if (strncasecmp("HTTP", $header, strlen("HTTP")) == 0) {
|
||||
$response = explode(' ', $header);
|
||||
return $response[1];
|
||||
}
|
||||
}
|
||||
return self::UNKNOWN_CODE;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user