PluginProbe
InfiniteWP Client / trunk
InfiniteWP Client vtrunk
1.13.10 1.13.7 trunk 0.1.4 0.1.5 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.1.0 1.1.1 1.1.10 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 1.11.0 1.11.1 1.12.1 1.12.3 All 92 releases
iwp-client / lib / Google / IO / Stream.php

Stream.php in InfiniteWP Client trunk, at lib/Google/IO/Stream.php

183 lines 5.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 * Copyright 2013 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 * Http Streams based implementation of IWP_google_IO.
20 *
21 * @author Stuart Langley <slangley@google.com>
22 */
23
24 require_once $GLOBALS['iwp_mmb_plugin_dir'].'/lib/Google/IO/Abstract.php';
25
26 class IWP_google_IO_Stream extends IWP_google_IO_Abstract
27 {
28 const TIMEOUT = "timeout";
29 const ZLIB = "compress.zlib://";
30 private $options = array();
31
32 private static $DEFAULT_HTTP_CONTEXT = array(
33 "follow_location" => 0,
34 "ignore_errors" => 1,
35 );
36
37 private static $DEFAULT_SSL_CONTEXT = array(
38 "verify_peer" => true,
39 );
40
41 /**
42 * Execute an HTTP Request
43 *
44 * @param IWP_google_HttpRequest $request the http request to be executed
45 * @return IWP_google_HttpRequest http request with the response http code,
46 * response headers and response body filled in
47 * @throws IWP_google_IO_Exception on curl or IO error
48 */
49 public function executeRequest(IWP_google_Http_Request $request)
50 {
51 $default_options = stream_context_get_options(stream_context_get_default());
52
53 $requestHttpContext = array_key_exists('http', $default_options) ?
54 $default_options['http'] : array();
55
56 if ($request->getPostBody()) {
57 $requestHttpContext["content"] = $request->getPostBody();
58 }
59
60 $requestHeaders = $request->getRequestHeaders();
61 if ($requestHeaders && is_array($requestHeaders)) {
62 $headers = "";
63 foreach ($requestHeaders as $k => $v) {
64 $headers .= "$k: $v\r\n";
65 }
66 $requestHttpContext["header"] = $headers;
67 }
68
69 $requestHttpContext["method"] = $request->getRequestMethod();
70 $requestHttpContext["user_agent"] = $request->getUserAgent();
71
72 $requestSslContext = array_key_exists('ssl', $default_options) ?
73 $default_options['ssl'] : array();
74
75 if (!array_key_exists("cafile", $requestSslContext)) {
76 $requestSslContext["cafile"] = dirname(__FILE__) . '/cacerts.pem';
77 }
78
79 $options = array(
80 "http" => array_merge(
81 self::$DEFAULT_HTTP_CONTEXT,
82 $requestHttpContext
83 ),
84 "ssl" => array_merge(
85 self::$DEFAULT_SSL_CONTEXT,
86 $requestSslContext
87 )
88 );
89
90 $context = stream_context_create($options);
91
92 $url = $request->getUrl();
93
94 if ($request->canGzip()) {
95 $url = self::ZLIB . $url;
96 }
97
98 // Not entirely happy about this, but supressing the warning from the
99 // fopen seems like the best situation here - we can't do anything
100 // useful with it, and failure to connect is a legitimate run
101 // time situation.
102 @$fh = fopen($url, 'r', false, $context);
103
104 $response_data = false;
105 $respHttpCode = self::UNKNOWN_CODE;
106 if ($fh) {
107 if (isset($this->options[self::TIMEOUT])) {
108 stream_set_timeout($fh, $this->options[self::TIMEOUT]);
109 }
110
111 $response_data = stream_get_contents($fh);
112 fclose($fh);
113
114 $respHttpCode = $this->getHttpResponseCode($http_response_header);
115 }
116
117 if (false === $response_data) {
118 throw new IWP_google_IO_Exception(
119 sprintf(
120 "HTTP Error: Unable to connect: '%s'",
121 $respHttpCode
122 ),
123 $respHttpCode
124 );
125 }
126
127 $responseHeaders = $this->getHttpResponseHeaders($http_response_header);
128
129 return array($response_data, $responseHeaders, $respHttpCode);
130 }
131
132 /**
133 * Set options that update the transport implementation's behavior.
134 * @param $options
135 */
136 public function setOptions($options)
137 {
138 $this->options = $options + $this->options;
139 }
140
141 /**
142 * Set the maximum request time in seconds.
143 * @param $timeout in seconds
144 */
145 public function setTimeout($timeout)
146 {
147 $this->options[self::TIMEOUT] = $timeout;
148 }
149
150 /**
151 * Get the maximum request time in seconds.
152 * @return timeout in seconds
153 */
154 public function getTimeout()
155 {
156 return $this->options[self::TIMEOUT];
157 }
158
159 /**
160 * Determine whether "Connection Established" quirk is needed
161 * @return boolean
162 */
163 protected function needsQuirk()
164 {
165 // Stream needs the special quirk
166 return true;
167 }
168
169 protected function getHttpResponseCode($response_headers)
170 {
171 $header_count = count($response_headers);
172
173 for ($i = 0; $i < $header_count; $i++) {
174 $header = $response_headers[$i];
175 if (strncasecmp("HTTP", $header, strlen("HTTP")) == 0) {
176 $response = explode(' ', $header);
177 return $response[1];
178 }
179 }
180 return self::UNKNOWN_CODE;
181 }
182 }
183