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