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.
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
26 require_once 'Zend/Http/Client.php';
29 * Gdata Http Client object.
31 * Class to extend the generic Zend Http Client with the ability to perform
32 * secure AuthSub requests
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
40 class Zend_Gdata_HttpClient extends Zend_Http_Client
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.
50 private $_authSubPrivateKeyId = null;
53 * Token for AuthSub authentication.
54 * If this token is set, AuthSub authentication is used.
58 private $_authSubToken = null;
61 * Token for ClientLogin authentication.
62 * If only this token is set, ClientLogin authentication is used.
66 private $_clientLoginToken = null;
69 * Token for ClientLogin authentication.
70 * If this token is set, and the AuthSub key is not set,
71 * ClientLogin authentication is used
75 private $_clientLoginKey = null;
78 * True if this request is being made with data supplied by
79 * a stream object instead of a raw encoded string.
83 protected $_streamingRequest = null;
86 * Sets the PEM formatted private key, as read from a file.
88 * This method reads the file and then calls setAuthSubPrivateKey()
89 * with the file contents.
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
97 public function setAuthSubPrivateKeyFile($file, $passphrase = null,
98 $useIncludePath = false) {
99 $fp = @fopen($file, "r", $useIncludePath);
101 require_once 'Zend/Gdata/App/InvalidArgumentException.php';
102 throw new Zend_Gdata_App_InvalidArgumentException('Failed to open private key file for AuthSub.');
107 $key .= fread($fp, 8192);
109 $this->setAuthSubPrivateKey($key, $passphrase);
114 * Sets the PEM formatted private key to be used for secure AuthSub auth.
116 * In order to call this method, openssl must be enabled in your PHP
117 * installation. Otherwise, a Zend_Gdata_App_InvalidArgumentException
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
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.');
132 $this->_authSubPrivateKeyId = openssl_pkey_get_private(
138 * Gets the openssl private key id
140 * @return string The private key
142 public function getAuthSubPrivateKeyId() {
143 return $this->_authSubPrivateKeyId;
147 * Gets the AuthSub token used for authentication
149 * @return string The token
151 public function getAuthSubToken() {
152 return $this->_authSubToken;
156 * Sets the AuthSub token used for authentication
158 * @param string $token The token
159 * @return Zend_Gdata_HttpClient Provides a fluent interface
161 public function setAuthSubToken($token) {
162 $this->_authSubToken = $token;
167 * Gets the ClientLogin token used for authentication
169 * @return string The token
171 public function getClientLoginToken() {
172 return $this->_clientLoginToken;
176 * Sets the ClientLogin token used for authentication
178 * @param string $token The token
179 * @return Zend_Gdata_HttpClient Provides a fluent interface
181 public function setClientLoginToken($token) {
182 $this->_clientLoginToken = $token;
187 * Filters the HTTP requests being sent to add the Authorization header.
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
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
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) {
213 $nonce = mt_rand(0, 999999999);
214 $dataToSign = $method . ' ' . $url . ' ' . $time . ' ' . $nonce;
217 $pKeyId = $this->getAuthSubPrivateKeyId();
218 $signSuccess = openssl_sign($dataToSign, $signature, $pKeyId,
221 require_once 'Zend/Gdata/App/Exception.php';
222 throw new Zend_Gdata_App_Exception(
223 'openssl_signing failure - returned false');
226 $encodedSignature = base64_encode($signature);
229 $headers['authorization'] = 'AuthSub token="' . $this->getAuthSubToken() . '" ' .
230 'data="' . $dataToSign . '" ' .
231 'sig="' . $encodedSignature . '" ' .
234 // AuthSub without secure tokens
235 $headers['authorization'] = 'AuthSub token="' . $this->getAuthSubToken() . '"';
237 } elseif ($this->getClientLoginToken() != null) {
238 $headers['authorization'] = 'GoogleLogin auth=' . $this->getClientLoginToken();
240 return array('method' => $method, 'url' => $url, 'body' => $body, 'headers' => $headers, 'contentType' => $contentType);
244 * Method for filtering the HTTP response, though no filtering is
247 * @param Zend_Http_Response $response The response object to filter
248 * @return Zend_Http_Response The filterd response object
250 public function filterHttpResponse($response) {
255 * Return the current connection adapter
257 * @return Zend_Http_Client_Adapter_Interface|string $adapter
259 public function getAdapter()
261 return $this->adapter;
265 * Load the connection adapter
267 * @param Zend_Http_Client_Adapter_Interface $adapter
270 public function setAdapter($adapter)
272 if ($adapter == null) {
273 $this->adapter = $adapter;
275 parent::setAdapter($adapter);
280 * Set the streamingRequest variable which controls whether we are
281 * sending the raw (already encoded) POST data from a stream source.
283 * @param boolean $value The value to set.
286 public function setStreamingRequest($value)
288 $this->_streamingRequest = $value;
292 * Check whether the client is set to perform streaming requests.
294 * @return boolean True if yes, false otherwise.
296 public function getStreamingRequest()
298 if ($this->_streamingRequest()) {
306 * Prepare the request body (for POST and PUT requests)
309 * @throws Zend_Http_Client_Exception
311 protected function _prepareBody()
313 if($this->_streamingRequest) {
314 $this->setHeaders(self::CONTENT_LENGTH,
315 $this->raw_post_data->getTotalSize());
316 return $this->raw_post_data;
319 return parent::_prepareBody();
324 * Clear all custom parameters we set.
326 * @return Zend_Http_Client
328 public function resetParameters($clearAll = false)
330 $this->_streamingRequest = false;
332 return parent::resetParameters($clearAll);
336 * Set the raw (already encoded) POST data from a stream source.
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().
342 * @param string $data The request data
343 * @param string $enctype The encoding type
344 * @return Zend_Http_Client
346 public function setRawDataStream($data, $enctype = null)
348 $this->_streamingRequest = true;
349 return $this->setRawData($data, $enctype);