|
1 <?php |
|
2 /** |
|
3 * Zend Framework |
|
4 * |
|
5 * LICENSE |
|
6 * |
|
7 * This source file is subject to the new BSD license that is bundled |
|
8 * with this package in the file LICENSE.txt. |
|
9 * It is also available through the world-wide-web at this URL: |
|
10 * http://framework.zend.com/license/new-bsd |
|
11 * If you did not receive a copy of the license and are unable to |
|
12 * obtain it through the world-wide-web, please send an email |
|
13 * to license@zend.com so we can send you a copy immediately. |
|
14 * |
|
15 * @category Zend |
|
16 * @package Zend_Oauth |
|
17 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
18 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
19 * @version $Id: Client.php 23076 2010-10-10 21:37:20Z padraic $ |
|
20 */ |
|
21 |
|
22 /** Zend_Oauth */ |
|
23 require_once 'Zend/Oauth.php'; |
|
24 |
|
25 /** Zend_Http_Client */ |
|
26 require_once 'Zend/Http/Client.php'; |
|
27 |
|
28 /** Zend_Oauth_Http_Utility */ |
|
29 require_once 'Zend/Oauth/Http/Utility.php'; |
|
30 |
|
31 /** Zend_Oauth_Config */ |
|
32 require_once 'Zend/Oauth/Config.php'; |
|
33 |
|
34 /** |
|
35 * @category Zend |
|
36 * @package Zend_Oauth |
|
37 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
38 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
39 */ |
|
40 class Zend_Oauth_Client extends Zend_Http_Client |
|
41 { |
|
42 /** |
|
43 * Flag to indicate that the client has detected the server as supporting |
|
44 * OAuth 1.0a |
|
45 */ |
|
46 public static $supportsRevisionA = false; |
|
47 |
|
48 /** |
|
49 * Holds the current OAuth Configuration set encapsulated in an instance |
|
50 * of Zend_Oauth_Config; it's not a Zend_Config instance since that level |
|
51 * of abstraction is unnecessary and doesn't let me escape the accessors |
|
52 * and mutators anyway! |
|
53 * |
|
54 * @var Zend_Oauth_Config |
|
55 */ |
|
56 protected $_config = null; |
|
57 |
|
58 /** |
|
59 * True if this request is being made with data supplied by |
|
60 * a stream object instead of a raw encoded string. |
|
61 * |
|
62 * @var bool |
|
63 */ |
|
64 protected $_streamingRequest = null; |
|
65 |
|
66 /** |
|
67 * Constructor; creates a new HTTP Client instance which itself is |
|
68 * just a typical Zend_Http_Client subclass with some OAuth icing to |
|
69 * assist in automating OAuth parameter generation, addition and |
|
70 * cryptographioc signing of requests. |
|
71 * |
|
72 * @param array $oauthOptions |
|
73 * @param string $uri |
|
74 * @param array|Zend_Config $config |
|
75 * @return void |
|
76 */ |
|
77 public function __construct($oauthOptions, $uri = null, $config = null) |
|
78 { |
|
79 if (!isset($config['rfc3986_strict'])) { |
|
80 $config['rfc3986_strict'] = true; |
|
81 } |
|
82 parent::__construct($uri, $config); |
|
83 $this->_config = new Zend_Oauth_Config; |
|
84 if ($oauthOptions !== null) { |
|
85 if ($oauthOptions instanceof Zend_Config) { |
|
86 $oauthOptions = $oauthOptions->toArray(); |
|
87 } |
|
88 $this->_config->setOptions($oauthOptions); |
|
89 } |
|
90 } |
|
91 |
|
92 /** |
|
93 * Return the current connection adapter |
|
94 * |
|
95 * @return Zend_Http_Client_Adapter_Interface|string $adapter |
|
96 */ |
|
97 public function getAdapter() |
|
98 { |
|
99 return $this->adapter; |
|
100 } |
|
101 |
|
102 /** |
|
103 * Load the connection adapter |
|
104 * |
|
105 * @param Zend_Http_Client_Adapter_Interface $adapter |
|
106 * @return void |
|
107 */ |
|
108 public function setAdapter($adapter) |
|
109 { |
|
110 if ($adapter == null) { |
|
111 $this->adapter = $adapter; |
|
112 } else { |
|
113 parent::setAdapter($adapter); |
|
114 } |
|
115 } |
|
116 |
|
117 /** |
|
118 * Set the streamingRequest variable which controls whether we are |
|
119 * sending the raw (already encoded) POST data from a stream source. |
|
120 * |
|
121 * @param boolean $value The value to set. |
|
122 * @return void |
|
123 */ |
|
124 public function setStreamingRequest($value) |
|
125 { |
|
126 $this->_streamingRequest = $value; |
|
127 } |
|
128 |
|
129 /** |
|
130 * Check whether the client is set to perform streaming requests. |
|
131 * |
|
132 * @return boolean True if yes, false otherwise. |
|
133 */ |
|
134 public function getStreamingRequest() |
|
135 { |
|
136 if ($this->_streamingRequest) { |
|
137 return true; |
|
138 } else { |
|
139 return false; |
|
140 } |
|
141 } |
|
142 |
|
143 /** |
|
144 * Prepare the request body (for POST and PUT requests) |
|
145 * |
|
146 * @return string |
|
147 * @throws Zend_Http_Client_Exception |
|
148 */ |
|
149 protected function _prepareBody() |
|
150 { |
|
151 if($this->_streamingRequest) { |
|
152 $this->setHeaders(self::CONTENT_LENGTH, |
|
153 $this->raw_post_data->getTotalSize()); |
|
154 return $this->raw_post_data; |
|
155 } |
|
156 else { |
|
157 return parent::_prepareBody(); |
|
158 } |
|
159 } |
|
160 |
|
161 /** |
|
162 * Clear all custom parameters we set. |
|
163 * |
|
164 * @return Zend_Http_Client |
|
165 */ |
|
166 public function resetParameters($clearAll = false) |
|
167 { |
|
168 $this->_streamingRequest = false; |
|
169 return parent::resetParameters($clearAll); |
|
170 } |
|
171 |
|
172 /** |
|
173 * Set the raw (already encoded) POST data from a stream source. |
|
174 * |
|
175 * This is used to support POSTing from open file handles without |
|
176 * caching the entire body into memory. It is a wrapper around |
|
177 * Zend_Http_Client::setRawData(). |
|
178 * |
|
179 * @param string $data The request data |
|
180 * @param string $enctype The encoding type |
|
181 * @return Zend_Http_Client |
|
182 */ |
|
183 public function setRawDataStream($data, $enctype = null) |
|
184 { |
|
185 $this->_streamingRequest = true; |
|
186 return $this->setRawData($data, $enctype); |
|
187 } |
|
188 |
|
189 /** |
|
190 * Same as Zend_Http_Client::setMethod() except it also creates an |
|
191 * Oauth specific reference to the method type. |
|
192 * Might be defunct and removed in a later iteration. |
|
193 * |
|
194 * @param string $method |
|
195 * @return Zend_Http_Client |
|
196 */ |
|
197 public function setMethod($method = self::GET) |
|
198 { |
|
199 if ($method == self::GET) { |
|
200 $this->setRequestMethod(self::GET); |
|
201 } elseif($method == self::POST) { |
|
202 $this->setRequestMethod(self::POST); |
|
203 } elseif($method == self::PUT) { |
|
204 $this->setRequestMethod(self::PUT); |
|
205 } elseif($method == self::DELETE) { |
|
206 $this->setRequestMethod(self::DELETE); |
|
207 } elseif($method == self::HEAD) { |
|
208 $this->setRequestMethod(self::HEAD); |
|
209 } |
|
210 return parent::setMethod($method); |
|
211 } |
|
212 |
|
213 /** |
|
214 * Same as Zend_Http_Client::request() except just before the request is |
|
215 * executed, we automatically append any necessary OAuth parameters and |
|
216 * sign the request using the relevant signature method. |
|
217 * |
|
218 * @param string $method |
|
219 * @return Zend_Http_Response |
|
220 */ |
|
221 public function request($method = null) |
|
222 { |
|
223 if ($method !== null) { |
|
224 $this->setMethod($method); |
|
225 } |
|
226 $this->prepareOauth(); |
|
227 return parent::request(); |
|
228 } |
|
229 |
|
230 /** |
|
231 * Performs OAuth preparation on the request before sending. |
|
232 * |
|
233 * This primarily means taking a request, correctly encoding and signing |
|
234 * all parameters, and applying the correct OAuth scheme to the method |
|
235 * being used. |
|
236 * |
|
237 * @return void |
|
238 * @throws Zend_Oauth_Exception If POSTBODY scheme requested, but GET request method used; or if invalid request scheme provided |
|
239 */ |
|
240 public function prepareOauth() |
|
241 { |
|
242 $requestScheme = $this->getRequestScheme(); |
|
243 $requestMethod = $this->getRequestMethod(); |
|
244 $query = null; |
|
245 if ($requestScheme == Zend_Oauth::REQUEST_SCHEME_HEADER) { |
|
246 $oauthHeaderValue = $this->getToken()->toHeader( |
|
247 $this->getUri(true), |
|
248 $this->_config, |
|
249 $this->_getSignableParametersAsQueryString() |
|
250 ); |
|
251 $this->setHeaders('Authorization', $oauthHeaderValue); |
|
252 } elseif ($requestScheme == Zend_Oauth::REQUEST_SCHEME_POSTBODY) { |
|
253 if ($requestMethod == self::GET) { |
|
254 require_once 'Zend/Oauth/Exception.php'; |
|
255 throw new Zend_Oauth_Exception( |
|
256 'The client is configured to' |
|
257 . ' pass OAuth parameters through a POST body but request method' |
|
258 . ' is set to GET' |
|
259 ); |
|
260 } |
|
261 $raw = $this->getToken()->toQueryString( |
|
262 $this->getUri(true), |
|
263 $this->_config, |
|
264 $this->_getSignableParametersAsQueryString() |
|
265 ); |
|
266 $this->setRawData($raw, 'application/x-www-form-urlencoded'); |
|
267 $this->paramsPost = array(); |
|
268 } elseif ($requestScheme == Zend_Oauth::REQUEST_SCHEME_QUERYSTRING) { |
|
269 $params = array(); |
|
270 $query = $this->getUri()->getQuery(); |
|
271 if ($query) { |
|
272 $queryParts = explode('&', $this->getUri()->getQuery()); |
|
273 foreach ($queryParts as $queryPart) { |
|
274 $kvTuple = explode('=', $queryPart); |
|
275 $params[urldecode($kvTuple[0])] = |
|
276 (array_key_exists(1, $kvTuple) ? urldecode($kvTuple[1]) : NULL); |
|
277 } |
|
278 } |
|
279 if (!empty($this->paramsPost)) { |
|
280 $params = array_merge($params, $this->paramsPost); |
|
281 $query = $this->getToken()->toQueryString( |
|
282 $this->getUri(true), $this->_config, $params |
|
283 ); |
|
284 } |
|
285 $query = $this->getToken()->toQueryString( |
|
286 $this->getUri(true), $this->_config, $params |
|
287 ); |
|
288 $this->getUri()->setQuery($query); |
|
289 $this->paramsGet = array(); |
|
290 } else { |
|
291 require_once 'Zend/Oauth/Exception.php'; |
|
292 throw new Zend_Oauth_Exception('Invalid request scheme: ' . $requestScheme); |
|
293 } |
|
294 } |
|
295 |
|
296 /** |
|
297 * Collect all signable parameters into a single array across query string |
|
298 * and POST body. These are returned as a properly formatted single |
|
299 * query string. |
|
300 * |
|
301 * @return string |
|
302 */ |
|
303 protected function _getSignableParametersAsQueryString() |
|
304 { |
|
305 $params = array(); |
|
306 if (!empty($this->paramsGet)) { |
|
307 $params = array_merge($params, $this->paramsGet); |
|
308 $query = $this->getToken()->toQueryString( |
|
309 $this->getUri(true), $this->_config, $params |
|
310 ); |
|
311 } |
|
312 if (!empty($this->paramsPost)) { |
|
313 $params = array_merge($params, $this->paramsPost); |
|
314 $query = $this->getToken()->toQueryString( |
|
315 $this->getUri(true), $this->_config, $params |
|
316 ); |
|
317 } |
|
318 return $params; |
|
319 } |
|
320 |
|
321 /** |
|
322 * Simple Proxy to the current Zend_Oauth_Config method. It's that instance |
|
323 * which holds all configuration methods and values this object also presents |
|
324 * as it's API. |
|
325 * |
|
326 * @param string $method |
|
327 * @param array $args |
|
328 * @return mixed |
|
329 * @throws Zend_Oauth_Exception if method does not exist in config object |
|
330 */ |
|
331 public function __call($method, array $args) |
|
332 { |
|
333 if (!method_exists($this->_config, $method)) { |
|
334 require_once 'Zend/Oauth/Exception.php'; |
|
335 throw new Zend_Oauth_Exception('Method does not exist: ' . $method); |
|
336 } |
|
337 return call_user_func_array(array($this->_config,$method), $args); |
|
338 } |
|
339 } |