File indexing completed on 2024-12-22 05:36:46
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Gdata 0017 * @subpackage Gdata 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 /** 0024 * Zend_Http_Client 0025 */ 0026 // require_once 'Zend/Http/Client.php'; 0027 0028 /** @see Zend_Crypt_Math */ 0029 // require_once 'Zend/Crypt/Math.php'; 0030 0031 /** 0032 * Gdata Http Client object. 0033 * 0034 * Class to extend the generic Zend Http Client with the ability to perform 0035 * secure AuthSub requests 0036 * 0037 * @category Zend 0038 * @package Zend_Gdata 0039 * @subpackage Gdata 0040 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0041 * @license http://framework.zend.com/license/new-bsd New BSD License 0042 */ 0043 class Zend_Gdata_HttpClient extends Zend_Http_Client 0044 { 0045 0046 /** 0047 * OpenSSL private key resource id 0048 * This key is used for AuthSub authentication. If this value is set, 0049 * it is assuemd that secure AuthSub is desired. 0050 * 0051 * @var resource 0052 */ 0053 private $_authSubPrivateKeyId = null; 0054 0055 /** 0056 * Token for AuthSub authentication. 0057 * If this token is set, AuthSub authentication is used. 0058 * 0059 * @var string 0060 */ 0061 private $_authSubToken = null; 0062 0063 /** 0064 * Token for ClientLogin authentication. 0065 * If only this token is set, ClientLogin authentication is used. 0066 * 0067 * @var string 0068 */ 0069 private $_clientLoginToken = null; 0070 0071 /** 0072 * Token for ClientLogin authentication. 0073 * If this token is set, and the AuthSub key is not set, 0074 * ClientLogin authentication is used 0075 * 0076 * @var string 0077 */ 0078 private $_clientLoginKey = null; 0079 0080 /** 0081 * True if this request is being made with data supplied by 0082 * a stream object instead of a raw encoded string. 0083 * 0084 * @var bool 0085 */ 0086 protected $_streamingRequest = null; 0087 0088 /** 0089 * Sets the PEM formatted private key, as read from a file. 0090 * 0091 * This method reads the file and then calls setAuthSubPrivateKey() 0092 * with the file contents. 0093 * 0094 * @param string $file The location of the file containing the PEM key 0095 * @param string $passphrase The optional private key passphrase 0096 * @param bool $useIncludePath Whether to search the include_path 0097 * for the file 0098 * @return void 0099 */ 0100 public function setAuthSubPrivateKeyFile($file, $passphrase = null, 0101 $useIncludePath = false) { 0102 $fp = @fopen($file, "r", $useIncludePath); 0103 if (!$fp) { 0104 // require_once 'Zend/Gdata/App/InvalidArgumentException.php'; 0105 throw new Zend_Gdata_App_InvalidArgumentException('Failed to open private key file for AuthSub.'); 0106 } 0107 0108 $key = ''; 0109 while (!feof($fp)) { 0110 $key .= fread($fp, 8192); 0111 } 0112 $this->setAuthSubPrivateKey($key, $passphrase); 0113 fclose($fp); 0114 } 0115 0116 /** 0117 * Sets the PEM formatted private key to be used for secure AuthSub auth. 0118 * 0119 * In order to call this method, openssl must be enabled in your PHP 0120 * installation. Otherwise, a Zend_Gdata_App_InvalidArgumentException 0121 * will be thrown. 0122 * 0123 * @param string $key The private key 0124 * @param string $passphrase The optional private key passphrase 0125 * @throws Zend_Gdata_App_InvalidArgumentException 0126 * @return Zend_Gdata_HttpClient Provides a fluent interface 0127 */ 0128 public function setAuthSubPrivateKey($key, $passphrase = null) { 0129 if ($key != null && !function_exists('openssl_pkey_get_private')) { 0130 // require_once 'Zend/Gdata/App/InvalidArgumentException.php'; 0131 throw new Zend_Gdata_App_InvalidArgumentException( 0132 'You cannot enable secure AuthSub if the openssl module ' . 0133 'is not enabled in your PHP installation.'); 0134 } 0135 $this->_authSubPrivateKeyId = openssl_pkey_get_private( 0136 $key, $passphrase); 0137 return $this; 0138 } 0139 0140 /** 0141 * Gets the openssl private key id 0142 * 0143 * @return string The private key 0144 */ 0145 public function getAuthSubPrivateKeyId() { 0146 return $this->_authSubPrivateKeyId; 0147 } 0148 0149 /** 0150 * Gets the AuthSub token used for authentication 0151 * 0152 * @return string The token 0153 */ 0154 public function getAuthSubToken() { 0155 return $this->_authSubToken; 0156 } 0157 0158 /** 0159 * Sets the AuthSub token used for authentication 0160 * 0161 * @param string $token The token 0162 * @return Zend_Gdata_HttpClient Provides a fluent interface 0163 */ 0164 public function setAuthSubToken($token) { 0165 $this->_authSubToken = $token; 0166 return $this; 0167 } 0168 0169 /** 0170 * Gets the ClientLogin token used for authentication 0171 * 0172 * @return string The token 0173 */ 0174 public function getClientLoginToken() { 0175 return $this->_clientLoginToken; 0176 } 0177 0178 /** 0179 * Sets the ClientLogin token used for authentication 0180 * 0181 * @param string $token The token 0182 * @return Zend_Gdata_HttpClient Provides a fluent interface 0183 */ 0184 public function setClientLoginToken($token) { 0185 $this->_clientLoginToken = $token; 0186 return $this; 0187 } 0188 0189 /** 0190 * Filters the HTTP requests being sent to add the Authorization header. 0191 * 0192 * If both AuthSub and ClientLogin tokens are set, 0193 * AuthSub takes precedence. If an AuthSub key is set, then 0194 * secure AuthSub authentication is used, and the request is signed. 0195 * Requests must be signed only with the private key corresponding to the 0196 * public key registered with Google. If an AuthSub key is set, but 0197 * openssl support is not enabled in the PHP installation, an exception is 0198 * thrown. 0199 * 0200 * @param string $method The HTTP method 0201 * @param string $url The URL 0202 * @param array $headers An associate array of headers to be 0203 * sent with the request or null 0204 * @param string $body The body of the request or null 0205 * @param string $contentType The MIME content type of the body or null 0206 * @throws Zend_Gdata_App_Exception if there was a signing failure 0207 * @return array The processed values in an associative array, 0208 * using the same names as the params 0209 */ 0210 public function filterHttpRequest($method, $url, $headers = array(), $body = null, $contentType = null) { 0211 if ($this->getAuthSubToken() != null) { 0212 // AuthSub authentication 0213 if ($this->getAuthSubPrivateKeyId() != null) { 0214 // secure AuthSub 0215 $time = time(); 0216 $nonce = Zend_Crypt_Math::randInteger(0, 999999999); 0217 $dataToSign = $method . ' ' . $url . ' ' . $time . ' ' . $nonce; 0218 0219 // compute signature 0220 $pKeyId = $this->getAuthSubPrivateKeyId(); 0221 $signSuccess = openssl_sign($dataToSign, $signature, $pKeyId, 0222 OPENSSL_ALGO_SHA1); 0223 if (!$signSuccess) { 0224 // require_once 'Zend/Gdata/App/Exception.php'; 0225 throw new Zend_Gdata_App_Exception( 0226 'openssl_signing failure - returned false'); 0227 } 0228 // encode signature 0229 $encodedSignature = base64_encode($signature); 0230 0231 // final header 0232 $headers['authorization'] = 'AuthSub token="' . $this->getAuthSubToken() . '" ' . 0233 'data="' . $dataToSign . '" ' . 0234 'sig="' . $encodedSignature . '" ' . 0235 'sigalg="rsa-sha1"'; 0236 } else { 0237 // AuthSub without secure tokens 0238 $headers['authorization'] = 'AuthSub token="' . $this->getAuthSubToken() . '"'; 0239 } 0240 } elseif ($this->getClientLoginToken() != null) { 0241 $headers['authorization'] = 'GoogleLogin auth=' . $this->getClientLoginToken(); 0242 } 0243 return array('method' => $method, 'url' => $url, 'body' => $body, 'headers' => $headers, 'contentType' => $contentType); 0244 } 0245 0246 /** 0247 * Method for filtering the HTTP response, though no filtering is 0248 * currently done. 0249 * 0250 * @param Zend_Http_Response $response The response object to filter 0251 * @return Zend_Http_Response The filterd response object 0252 */ 0253 public function filterHttpResponse($response) { 0254 return $response; 0255 } 0256 0257 /** 0258 * Return the current connection adapter 0259 * 0260 * @return Zend_Http_Client_Adapter_Interface|string $adapter 0261 */ 0262 public function getAdapter() 0263 { 0264 return $this->adapter; 0265 } 0266 0267 /** 0268 * Load the connection adapter 0269 * 0270 * @param Zend_Http_Client_Adapter_Interface $adapter 0271 * @return void 0272 */ 0273 public function setAdapter($adapter) 0274 { 0275 if ($adapter == null) { 0276 $this->adapter = $adapter; 0277 } else { 0278 parent::setAdapter($adapter); 0279 } 0280 } 0281 0282 /** 0283 * Set the streamingRequest variable which controls whether we are 0284 * sending the raw (already encoded) POST data from a stream source. 0285 * 0286 * @param boolean $value The value to set. 0287 * @return void 0288 */ 0289 public function setStreamingRequest($value) 0290 { 0291 $this->_streamingRequest = $value; 0292 } 0293 0294 /** 0295 * Check whether the client is set to perform streaming requests. 0296 * 0297 * @return boolean True if yes, false otherwise. 0298 */ 0299 public function getStreamingRequest() 0300 { 0301 if ($this->_streamingRequest()) { 0302 return true; 0303 } else { 0304 return false; 0305 } 0306 } 0307 0308 /** 0309 * Prepare the request body (for POST and PUT requests) 0310 * 0311 * @return string 0312 * @throws Zend_Http_Client_Exception 0313 */ 0314 protected function _prepareBody() 0315 { 0316 if($this->_streamingRequest) { 0317 $this->setHeaders(self::CONTENT_LENGTH, 0318 $this->raw_post_data->getTotalSize()); 0319 return $this->raw_post_data; 0320 } 0321 else { 0322 return parent::_prepareBody(); 0323 } 0324 } 0325 0326 /** 0327 * Clear all custom parameters we set. 0328 * 0329 * @return Zend_Http_Client 0330 */ 0331 public function resetParameters($clearAll = false) 0332 { 0333 $this->_streamingRequest = false; 0334 0335 return parent::resetParameters($clearAll); 0336 } 0337 0338 /** 0339 * Set the raw (already encoded) POST data from a stream source. 0340 * 0341 * This is used to support POSTing from open file handles without 0342 * caching the entire body into memory. It is a wrapper around 0343 * Zend_Http_Client::setRawData(). 0344 * 0345 * @param string $data The request data 0346 * @param string $enctype The encoding type 0347 * @return Zend_Http_Client 0348 */ 0349 public function setRawDataStream($data, $enctype = null) 0350 { 0351 $this->_streamingRequest = true; 0352 return $this->setRawData($data, $enctype); 0353 } 0354 0355 }