summaryrefslogtreecommitdiff
path: root/Postman/Postman-Mail/google-api-php-client-1.1.2/src/Google/IO/Abstract.php
diff options
context:
space:
mode:
Diffstat (limited to 'Postman/Postman-Mail/google-api-php-client-1.1.2/src/Google/IO/Abstract.php')
-rw-r--r--Postman/Postman-Mail/google-api-php-client-1.1.2/src/Google/IO/Abstract.php329
1 files changed, 329 insertions, 0 deletions
diff --git a/Postman/Postman-Mail/google-api-php-client-1.1.2/src/Google/IO/Abstract.php b/Postman/Postman-Mail/google-api-php-client-1.1.2/src/Google/IO/Abstract.php
new file mode 100644
index 0000000..a480941
--- /dev/null
+++ b/Postman/Postman-Mail/google-api-php-client-1.1.2/src/Google/IO/Abstract.php
@@ -0,0 +1,329 @@
+<?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
+ */
+
+require_once realpath(dirname(__FILE__) . '/../../../autoload.php');
+
+abstract class Postman_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 Postman_Google_Client */
+ protected $client;
+
+ public function __construct(Postman_Google_Client $client)
+ {
+ $this->client = $client;
+ $timeout = $client->getClassConfig('Postman_Google_IO_Abstract', 'request_timeout_seconds');
+ if ($timeout > 0) {
+ $this->setTimeout($timeout);
+ }
+ }
+
+ /**
+ * Executes a Postman_Google_Http_Request and returns the resulting populated Postman_Google_Http_Request
+ * @param Postman_Google_Http_Request $request
+ * @return Postman_Google_Http_Request $request
+ */
+ abstract public function executeRequest(Postman_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 Postman_Google_Http_Request $request
+ * @return bool Returns true if the insertion was successful.
+ * Otherwise, return false.
+ */
+ public function setCachedRequest(Postman_Google_Http_Request $request)
+ {
+ // Determine if the request is cacheable.
+ if (Postman_Google_Http_CacheParser::isResponseCacheable($request)) {
+ $this->client->getCache()->set($request->getCacheKey(), $request);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Execute an HTTP Request
+ *
+ * @param Postman_Google_HttpRequest $request the http request to be executed
+ * @return Postman_Google_HttpRequest http request with the response http code,
+ * response headers and response body filled in
+ * @throws Postman_Google_IO_Exception on curl or IO error
+ */
+ public function makeRequest(Postman_Google_Http_Request $request)
+ {
+ // First, check to see if we have a valid cached version.
+ $cached = $this->getCachedRequest($request);
+ if ($cached !== false && $cached instanceof Postman_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 Postman_Google_Http_Request $request
+ * @return Postman_Google_Http_Request|bool Returns the cached object or
+ * false if the operation was unsuccessful.
+ */
+ public function getCachedRequest(Postman_Google_Http_Request $request)
+ {
+ if (false === Postman_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 Postman_Google_Http_Request $request
+ * @return Postman_Google_Http_Request Processed request with the enclosed entity.
+ */
+ public function processEntityRequest(Postman_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 Postman_Google_Http_Request $cached A previously cached response.
+ * @param Postman_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 (Postman_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 Postman_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;
+ }
+}