PluginProbe
ManageWP Worker / 3.9.24
ManageWP Worker v3.9.24
4.9.38 4.9.37 4.9.36 4.9.35 4.9.34 3.8.7 3.8.8 3.9.0 3.9.1 3.9.10 3.9.11 3.9.12 3.9.13 3.9.14 3.9.15 3.9.16 3.9.17 3.9.18 3.9.19 3.9.2 3.9.20 3.9.21 3.9.22 3.9.23 3.9.24 All 73 releases
worker / lib / google-api-client / io / Google_CurlIO.php

Google_CurlIO.php in ManageWP Worker 3.9.24, at lib/google-api-client/io/Google_CurlIO.php

278 lines 9.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 * Copyright 2010 Google Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 /**
19 * Curl based implementation of apiIO.
20 *
21 * @author Chris Chabot <[email protected]>
22 * @author Chirag Shah <[email protected]>
23 */
24
25 require_once 'Google_CacheParser.php';
26
27 class Google_CurlIO implements Google_IO {
28 const CONNECTION_ESTABLISHED = "HTTP/1.0 200 Connection established\r\n\r\n";
29 const FORM_URLENCODED = 'application/x-www-form-urlencoded';
30
31 private static $ENTITY_HTTP_METHODS = array("POST" => null, "PUT" => null);
32 private static $HOP_BY_HOP = array(
33 'connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization',
34 'te', 'trailers', 'transfer-encoding', 'upgrade');
35
36 private $curlParams = array (
37 CURLOPT_RETURNTRANSFER => true,
38 CURLOPT_FOLLOWLOCATION => 0,
39 CURLOPT_FAILONERROR => false,
40 CURLOPT_SSL_VERIFYPEER => true,
41 CURLOPT_HEADER => true,
42 CURLOPT_VERBOSE => false,
43 );
44
45 /**
46 * Perform an authenticated / signed apiHttpRequest.
47 * This function takes the apiHttpRequest, calls apiAuth->sign on it
48 * (which can modify the request in what ever way fits the auth mechanism)
49 * and then calls apiCurlIO::makeRequest on the signed request
50 *
51 * @param Google_HttpRequest $request
52 * @return Google_HttpRequest The resulting HTTP response including the
53 * responseHttpCode, responseHeaders and responseBody.
54 */
55 public function authenticatedRequest(Google_HttpRequest $request) {
56 $request = Google_Client::$auth->sign($request);
57 return $this->makeRequest($request);
58 }
59
60 /**
61 * Execute a apiHttpRequest
62 *
63 * @param Google_HttpRequest $request the http request to be executed
64 * @return Google_HttpRequest http request with the response http code, response
65 * headers and response body filled in
66 * @throws Google_IOException on curl or IO error
67 */
68 public function makeRequest(Google_HttpRequest $request) {
69 // First, check to see if we have a valid cached version.
70 $cached = $this->getCachedRequest($request);
71 if ($cached !== false) {
72 if (Google_CacheParser::mustRevalidate($cached)) {
73 $addHeaders = array();
74 if ($cached->getResponseHeader('etag')) {
75 // [13.3.4] If an entity tag has been provided by the origin server,
76 // we must use that entity tag in any cache-conditional request.
77 $addHeaders['If-None-Match'] = $cached->getResponseHeader('etag');
78 } elseif ($cached->getResponseHeader('date')) {
79 $addHeaders['If-Modified-Since'] = $cached->getResponseHeader('date');
80 }
81
82 $request->setRequestHeaders($addHeaders);
83 } else {
84 // No need to revalidate the request, return it directly
85 return $cached;
86 }
87 }
88
89 if (array_key_exists($request->getRequestMethod(),
90 self::$ENTITY_HTTP_METHODS)) {
91 $request = $this->processEntityRequest($request);
92 }
93
94 $ch = curl_init();
95 curl_setopt_array($ch, $this->curlParams);
96 curl_setopt($ch, CURLOPT_URL, $request->getUrl());
97 if ($request->getPostBody()) {
98 curl_setopt($ch, CURLOPT_POSTFIELDS, $request->getPostBody());
99 }
100
101 $requestHeaders = $request->getRequestHeaders();
102 if ($requestHeaders && is_array($requestHeaders)) {
103 $parsed = array();
104 foreach ($requestHeaders as $k => $v) {
105 $parsed[] = "$k: $v";
106 }
107 curl_setopt($ch, CURLOPT_HTTPHEADER, $parsed);
108 }
109
110 curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request->getRequestMethod());
111 curl_setopt($ch, CURLOPT_USERAGENT, $request->getUserAgent());
112 $respData = curl_exec($ch);
113
114 // Retry if certificates are missing.
115 if (curl_errno($ch) == CURLE_SSL_CACERT) {
116 error_log('SSL certificate problem, verify that the CA cert is OK.'
117 . ' Retrying with the CA cert bundle from google-api-php-client.');
118 curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacerts.pem');
119 $respData = curl_exec($ch);
120 }
121
122 $respHeaderSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
123 $respHttpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
124 $curlErrorNum = curl_errno($ch);
125 $curlError = curl_error($ch);
126 curl_close($ch);
127 if ($curlErrorNum != CURLE_OK) {
128 throw new Google_IOException("HTTP Error: ($respHttpCode) $curlError");
129 }
130
131 // Parse out the raw response into usable bits
132 list($responseHeaders, $responseBody) =
133 self::parseHttpResponse($respData, $respHeaderSize);
134
135 if ($respHttpCode == 304 && $cached) {
136 // If the server responded NOT_MODIFIED, return the cached request.
137 if (isset($responseHeaders['connection'])) {
138 $hopByHop = array_merge(
139 self::$HOP_BY_HOP,
140 explode(',', $responseHeaders['connection'])
141 );
142
143 $endToEnd = array();
144 foreach($hopByHop as $key) {
145 if (isset($responseHeaders[$key])) {
146 $endToEnd[$key] = $responseHeaders[$key];
147 }
148 }
149 $cached->setResponseHeaders($endToEnd);
150 }
151 return $cached;
152 }
153
154 // Fill in the apiHttpRequest with the response values
155 $request->setResponseHttpCode($respHttpCode);
156 $request->setResponseHeaders($responseHeaders);
157 $request->setResponseBody($responseBody);
158 // Store the request in cache (the function checks to see if the request
159 // can actually be cached)
160 $this->setCachedRequest($request);
161 // And finally return it
162 return $request;
163 }
164
165 /**
166 * @visible for testing.
167 * Cache the response to an HTTP request if it is cacheable.
168 * @param Google_HttpRequest $request
169 * @return bool Returns true if the insertion was successful.
170 * Otherwise, return false.
171 */
172 public function setCachedRequest(Google_HttpRequest $request) {
173 // Determine if the request is cacheable.
174 if (Google_CacheParser::isResponseCacheable($request)) {
175 Google_Client::$cache->set($request->getCacheKey(), $request);
176 return true;
177 }
178
179 return false;
180 }
181
182 /**
183 * @visible for testing.
184 * @param Google_HttpRequest $request
185 * @return Google_HttpRequest|bool Returns the cached object or
186 * false if the operation was unsuccessful.
187 */
188 public function getCachedRequest(Google_HttpRequest $request) {
189 if (false == Google_CacheParser::isRequestCacheable($request)) {
190 false;
191 }
192
193 return Google_Client::$cache->get($request->getCacheKey());
194 }
195
196 /**
197 * @param $respData
198 * @param $headerSize
199 * @return array
200 */
201 public static function parseHttpResponse($respData, $headerSize) {
202 if (stripos($respData, self::CONNECTION_ESTABLISHED) !== false) {
203 $respData = str_ireplace(self::CONNECTION_ESTABLISHED, '', $respData);
204 }
205
206 if ($headerSize) {
207 $responseBody = substr($respData, $headerSize);
208 $responseHeaders = substr($respData, 0, $headerSize);
209 } else {
210 list($responseHeaders, $responseBody) = explode("\r\n\r\n", $respData, 2);
211 }
212
213 $responseHeaders = self::parseResponseHeaders($responseHeaders);
214 return array($responseHeaders, $responseBody);
215 }
216
217 public static function parseResponseHeaders($rawHeaders) {
218 $responseHeaders = array();
219
220 $responseHeaderLines = explode("\r\n", $rawHeaders);
221 foreach ($responseHeaderLines as $headerLine) {
222 if ($headerLine && strpos($headerLine, ':') !== false) {
223 list($header, $value) = explode(': ', $headerLine, 2);
224 $header = strtolower($header);
225 if (isset($responseHeaders[$header])) {
226 $responseHeaders[$header] .= "\n" . $value;
227 } else {
228 $responseHeaders[$header] = $value;
229 }
230 }
231 }
232 return $responseHeaders;
233 }
234
235 /**
236 * @visible for testing
237 * Process an http request that contains an enclosed entity.
238 * @param Google_HttpRequest $request
239 * @return Google_HttpRequest Processed request with the enclosed entity.
240 */
241 public function processEntityRequest(Google_HttpRequest $request) {
242 $postBody = $request->getPostBody();
243 $contentType = $request->getRequestHeader("content-type");
244
245 // Set the default content-type as application/x-www-form-urlencoded.
246 if (false == $contentType) {
247 $contentType = self::FORM_URLENCODED;
248 $request->setRequestHeaders(array('content-type' => $contentType));
249 }
250
251 // Force the payload to match the content-type asserted in the header.
252 if ($contentType == self::FORM_URLENCODED && is_array($postBody)) {
253 $postBody = http_build_query($postBody, '', '&');
254 $request->setPostBody($postBody);
255 }
256
257 // Make sure the content-length header is set.
258 if (!$postBody || is_string($postBody)) {
259 $postsLength = strlen($postBody);
260 $request->setRequestHeaders(array('content-length' => $postsLength));
261 }
262
263 return $request;
264 }
265
266 /**
267 * Set options that update cURL's default behavior.
268 * The list of accepted options are:
269 * {@link http://php.net/manual/en/function.curl-setopt.php]
270 *
271 * @param array $optCurlParams Multiple options used by a cURL session.
272 */
273 public function setOptions($optCurlParams) {
274 foreach ($optCurlParams as $key => $val) {
275 $this->curlParams[$key] = $val;
276 }
277 }
278 }