HttpClient.php
11.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Gdata
* @subpackage Gdata
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id: HttpClient.php 23775 2011-03-01 17:25:24Z ralph $
*/
/**
* Zend_Http_Client
*/
require_once 'Zend/Http/Client.php';
/**
* Gdata Http Client object.
*
* Class to extend the generic Zend Http Client with the ability to perform
* secure AuthSub requests
*
* @category Zend
* @package Zend_Gdata
* @subpackage Gdata
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Gdata_HttpClient extends Zend_Http_Client
{
/**
* OpenSSL private key resource id
* This key is used for AuthSub authentication. If this value is set,
* it is assuemd that secure AuthSub is desired.
*
* @var resource
*/
private $_authSubPrivateKeyId = null;
/**
* Token for AuthSub authentication.
* If this token is set, AuthSub authentication is used.
*
* @var string
*/
private $_authSubToken = null;
/**
* Token for ClientLogin authentication.
* If only this token is set, ClientLogin authentication is used.
*
* @var string
*/
private $_clientLoginToken = null;
/**
* Token for ClientLogin authentication.
* If this token is set, and the AuthSub key is not set,
* ClientLogin authentication is used
*
* @var string
*/
private $_clientLoginKey = null;
/**
* True if this request is being made with data supplied by
* a stream object instead of a raw encoded string.
*
* @var bool
*/
protected $_streamingRequest = null;
/**
* Sets the PEM formatted private key, as read from a file.
*
* This method reads the file and then calls setAuthSubPrivateKey()
* with the file contents.
*
* @param string $file The location of the file containing the PEM key
* @param string $passphrase The optional private key passphrase
* @param bool $useIncludePath Whether to search the include_path
* for the file
* @return void
*/
public function setAuthSubPrivateKeyFile($file, $passphrase = null,
$useIncludePath = false) {
$fp = @fopen($file, "r", $useIncludePath);
if (!$fp) {
require_once 'Zend/Gdata/App/InvalidArgumentException.php';
throw new Zend_Gdata_App_InvalidArgumentException('Failed to open private key file for AuthSub.');
}
$key = '';
while (!feof($fp)) {
$key .= fread($fp, 8192);
}
$this->setAuthSubPrivateKey($key, $passphrase);
fclose($fp);
}
/**
* Sets the PEM formatted private key to be used for secure AuthSub auth.
*
* In order to call this method, openssl must be enabled in your PHP
* installation. Otherwise, a Zend_Gdata_App_InvalidArgumentException
* will be thrown.
*
* @param string $key The private key
* @param string $passphrase The optional private key passphrase
* @throws Zend_Gdata_App_InvalidArgumentException
* @return Zend_Gdata_HttpClient Provides a fluent interface
*/
public function setAuthSubPrivateKey($key, $passphrase = null) {
if ($key != null && !function_exists('openssl_pkey_get_private')) {
require_once 'Zend/Gdata/App/InvalidArgumentException.php';
throw new Zend_Gdata_App_InvalidArgumentException(
'You cannot enable secure AuthSub if the openssl module ' .
'is not enabled in your PHP installation.');
}
$this->_authSubPrivateKeyId = openssl_pkey_get_private(
$key, $passphrase);
return $this;
}
/**
* Gets the openssl private key id
*
* @return string The private key
*/
public function getAuthSubPrivateKeyId() {
return $this->_authSubPrivateKeyId;
}
/**
* Gets the AuthSub token used for authentication
*
* @return string The token
*/
public function getAuthSubToken() {
return $this->_authSubToken;
}
/**
* Sets the AuthSub token used for authentication
*
* @param string $token The token
* @return Zend_Gdata_HttpClient Provides a fluent interface
*/
public function setAuthSubToken($token) {
$this->_authSubToken = $token;
return $this;
}
/**
* Gets the ClientLogin token used for authentication
*
* @return string The token
*/
public function getClientLoginToken() {
return $this->_clientLoginToken;
}
/**
* Sets the ClientLogin token used for authentication
*
* @param string $token The token
* @return Zend_Gdata_HttpClient Provides a fluent interface
*/
public function setClientLoginToken($token) {
$this->_clientLoginToken = $token;
return $this;
}
/**
* Filters the HTTP requests being sent to add the Authorization header.
*
* If both AuthSub and ClientLogin tokens are set,
* AuthSub takes precedence. If an AuthSub key is set, then
* secure AuthSub authentication is used, and the request is signed.
* Requests must be signed only with the private key corresponding to the
* public key registered with Google. If an AuthSub key is set, but
* openssl support is not enabled in the PHP installation, an exception is
* thrown.
*
* @param string $method The HTTP method
* @param string $url The URL
* @param array $headers An associate array of headers to be
* sent with the request or null
* @param string $body The body of the request or null
* @param string $contentType The MIME content type of the body or null
* @throws Zend_Gdata_App_Exception if there was a signing failure
* @return array The processed values in an associative array,
* using the same names as the params
*/
public function filterHttpRequest($method, $url, $headers = array(), $body = null, $contentType = null) {
if ($this->getAuthSubToken() != null) {
// AuthSub authentication
if ($this->getAuthSubPrivateKeyId() != null) {
// secure AuthSub
$time = time();
$nonce = mt_rand(0, 999999999);
$dataToSign = $method . ' ' . $url . ' ' . $time . ' ' . $nonce;
// compute signature
$pKeyId = $this->getAuthSubPrivateKeyId();
$signSuccess = openssl_sign($dataToSign, $signature, $pKeyId,
OPENSSL_ALGO_SHA1);
if (!$signSuccess) {
require_once 'Zend/Gdata/App/Exception.php';
throw new Zend_Gdata_App_Exception(
'openssl_signing failure - returned false');
}
// encode signature
$encodedSignature = base64_encode($signature);
// final header
$headers['authorization'] = 'AuthSub token="' . $this->getAuthSubToken() . '" ' .
'data="' . $dataToSign . '" ' .
'sig="' . $encodedSignature . '" ' .
'sigalg="rsa-sha1"';
} else {
// AuthSub without secure tokens
$headers['authorization'] = 'AuthSub token="' . $this->getAuthSubToken() . '"';
}
} elseif ($this->getClientLoginToken() != null) {
$headers['authorization'] = 'GoogleLogin auth=' . $this->getClientLoginToken();
}
return array('method' => $method, 'url' => $url, 'body' => $body, 'headers' => $headers, 'contentType' => $contentType);
}
/**
* Method for filtering the HTTP response, though no filtering is
* currently done.
*
* @param Zend_Http_Response $response The response object to filter
* @return Zend_Http_Response The filterd response object
*/
public function filterHttpResponse($response) {
return $response;
}
/**
* Return the current connection adapter
*
* @return Zend_Http_Client_Adapter_Interface|string $adapter
*/
public function getAdapter()
{
return $this->adapter;
}
/**
* Load the connection adapter
*
* @param Zend_Http_Client_Adapter_Interface $adapter
* @return void
*/
public function setAdapter($adapter)
{
if ($adapter == null) {
$this->adapter = $adapter;
} else {
parent::setAdapter($adapter);
}
}
/**
* Set the streamingRequest variable which controls whether we are
* sending the raw (already encoded) POST data from a stream source.
*
* @param boolean $value The value to set.
* @return void
*/
public function setStreamingRequest($value)
{
$this->_streamingRequest = $value;
}
/**
* Check whether the client is set to perform streaming requests.
*
* @return boolean True if yes, false otherwise.
*/
public function getStreamingRequest()
{
if ($this->_streamingRequest()) {
return true;
} else {
return false;
}
}
/**
* Prepare the request body (for POST and PUT requests)
*
* @return string
* @throws Zend_Http_Client_Exception
*/
protected function _prepareBody()
{
if($this->_streamingRequest) {
$this->setHeaders(self::CONTENT_LENGTH,
$this->raw_post_data->getTotalSize());
return $this->raw_post_data;
}
else {
return parent::_prepareBody();
}
}
/**
* Clear all custom parameters we set.
*
* @return Zend_Http_Client
*/
public function resetParameters($clearAll = false)
{
$this->_streamingRequest = false;
return parent::resetParameters($clearAll);
}
/**
* Set the raw (already encoded) POST data from a stream source.
*
* This is used to support POSTing from open file handles without
* caching the entire body into memory. It is a wrapper around
* Zend_Http_Client::setRawData().
*
* @param string $data The request data
* @param string $enctype The encoding type
* @return Zend_Http_Client
*/
public function setRawDataStream($data, $enctype = null)
{
$this->_streamingRequest = true;
return $this->setRawData($data, $enctype);
}
}