web/lib/Zend/Gdata/HttpClient.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     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  * @version    $Id: HttpClient.php 20096 2010-01-06 02:05:09Z bkarwin $
       
    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 }