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 }