File indexing completed on 2024-12-22 05:36:53

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_Oauth
0017  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0018  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0019  * @version    $Id$
0020  */
0021 
0022 /** Zend_Oauth_Http_Utility */
0023 // require_once 'Zend/Oauth/Http/Utility.php';
0024 
0025 /** Zend_Uri_Http */
0026 // require_once 'Zend/Uri/Http.php';
0027 
0028 /**
0029  * @category   Zend
0030  * @package    Zend_Oauth
0031  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0032  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0033  */
0034 class Zend_Oauth_Http
0035 {
0036     /**
0037      * Array of all custom service parameters to be sent in the HTTP request
0038      * in addition to the usual OAuth parameters.
0039      *
0040      * @var array
0041      */
0042     protected $_parameters = array();
0043 
0044     /**
0045      * Reference to the Zend_Oauth_Consumer instance in use.
0046      *
0047      * @var string
0048      */
0049     protected $_consumer = null;
0050 
0051     /**
0052      * OAuth specifies three request methods, this holds the current preferred
0053      * one which by default uses the Authorization Header approach for passing
0054      * OAuth parameters, and a POST body for non-OAuth custom parameters.
0055      *
0056      * @var string
0057      */
0058     protected $_preferredRequestScheme = null;
0059 
0060     /**
0061      * Request Method for the HTTP Request.
0062      *
0063      * @var string
0064      */
0065     protected $_preferredRequestMethod = Zend_Oauth::POST;
0066 
0067     /**
0068      * Instance of the general Zend_Oauth_Http_Utility class.
0069      *
0070      * @var Zend_Oauth_Http_Utility
0071      */
0072     protected $_httpUtility = null;
0073 
0074     /**
0075      * Constructor
0076      *
0077      * @param  Zend_Oauth_Consumer $consumer
0078      * @param  null|array $parameters
0079      * @param  null|Zend_Oauth_Http_Utility $utility
0080      * @return void
0081      */
0082     public function __construct(
0083         Zend_Oauth_Consumer $consumer,
0084         array $parameters = null,
0085         Zend_Oauth_Http_Utility $utility = null
0086     ) {
0087         $this->_consumer = $consumer;
0088         $this->_preferredRequestScheme = $this->_consumer->getRequestScheme();
0089         if ($parameters !== null) {
0090             $this->setParameters($parameters);
0091         }
0092         if ($utility !== null) {
0093             $this->_httpUtility = $utility;
0094         } else {
0095             $this->_httpUtility = new Zend_Oauth_Http_Utility;
0096         }
0097     }
0098 
0099     /**
0100      * Set a preferred HTTP request method.
0101      *
0102      * @param  string $method
0103      * @return Zend_Oauth_Http
0104      */
0105     public function setMethod($method)
0106     {
0107         if (!in_array($method, array(Zend_Oauth::POST, Zend_Oauth::GET))) {
0108             // require_once 'Zend/Oauth/Exception.php';
0109             throw new Zend_Oauth_Exception('invalid HTTP method: ' . $method);
0110         }
0111         $this->_preferredRequestMethod = $method;
0112         return $this;
0113     }
0114 
0115     /**
0116      * Preferred HTTP request method accessor.
0117      *
0118      * @return string
0119      */
0120     public function getMethod()
0121     {
0122         return $this->_preferredRequestMethod;
0123     }
0124 
0125     /**
0126      * Mutator to set an array of custom parameters for the HTTP request.
0127      *
0128      * @param  array $customServiceParameters
0129      * @return Zend_Oauth_Http
0130      */
0131     public function setParameters(array $customServiceParameters)
0132     {
0133         $this->_parameters = $customServiceParameters;
0134         return $this;
0135     }
0136 
0137     /**
0138      * Accessor for an array of custom parameters.
0139      *
0140      * @return array
0141      */
0142     public function getParameters()
0143     {
0144         return $this->_parameters;
0145     }
0146 
0147     /**
0148      * Return the Consumer instance in use.
0149      *
0150      * @return Zend_Oauth_Consumer
0151      */
0152     public function getConsumer()
0153     {
0154         return $this->_consumer;
0155     }
0156 
0157     /**
0158      * Commence a request cycle where the current HTTP method and OAuth
0159      * request scheme set an upper preferred HTTP request style and where
0160      * failures generate a new HTTP request style further down the OAuth
0161      * preference list for OAuth Request Schemes.
0162      * On success, return the Request object that results for processing.
0163      *
0164      * @param  array $params
0165      * @return Zend_Http_Response
0166      * @throws Zend_Oauth_Exception on HTTP request errors
0167      * @todo   Remove cycling?; Replace with upfront do-or-die configuration
0168      */
0169     public function startRequestCycle(array $params)
0170     {
0171         $response = null;
0172         $body     = null;
0173         $status   = null;
0174         try {
0175             $response = $this->_attemptRequest($params);
0176         } catch (Zend_Http_Client_Exception $e) {
0177             // require_once 'Zend/Oauth/Exception.php';
0178             throw new Zend_Oauth_Exception('Error in HTTP request', null, $e);
0179         }
0180         if ($response !== null) {
0181             $body   = $response->getBody();
0182             $status = $response->getStatus();
0183         }
0184         if ($response === null // Request failure/exception
0185             || $status == 500  // Internal Server Error
0186             || $status == 400  // Bad Request
0187             || $status == 401  // Unauthorized
0188             || empty($body)    // Missing token
0189         ) {
0190             $this->_assessRequestAttempt($response);
0191             $response = $this->startRequestCycle($params);
0192         }
0193         return $response;
0194     }
0195 
0196     /**
0197      * Return an instance of Zend_Http_Client configured to use the Query
0198      * String scheme for an OAuth driven HTTP request.
0199      *
0200      * @param array $params
0201      * @param string $url
0202      * @return Zend_Http_Client
0203      */
0204     public function getRequestSchemeQueryStringClient(array $params, $url)
0205     {
0206         $client = Zend_Oauth::getHttpClient();
0207         $client->setUri($url);
0208         $client->getUri()->setQuery(
0209             $this->_httpUtility->toEncodedQueryString($params)
0210         );
0211         $client->setMethod($this->_preferredRequestMethod);
0212         return $client;
0213     }
0214 
0215     /**
0216      * Manages the switch from OAuth request scheme to another lower preference
0217      * scheme during a request cycle.
0218      *
0219      * @param  Zend_Http_Response
0220      * @return void
0221      * @throws Zend_Oauth_Exception if unable to retrieve valid token response
0222      */
0223     protected function _assessRequestAttempt(Zend_Http_Response $response = null)
0224     {
0225         switch ($this->_preferredRequestScheme) {
0226             case Zend_Oauth::REQUEST_SCHEME_HEADER:
0227                 $this->_preferredRequestScheme = Zend_Oauth::REQUEST_SCHEME_POSTBODY;
0228                 break;
0229             case Zend_Oauth::REQUEST_SCHEME_POSTBODY:
0230                 $this->_preferredRequestScheme = Zend_Oauth::REQUEST_SCHEME_QUERYSTRING;
0231                 break;
0232             default:
0233                 // require_once 'Zend/Oauth/Exception.php';
0234                 throw new Zend_Oauth_Exception(
0235                     'Could not retrieve a valid Token response from Token URL:'
0236                     . ($response !== null
0237                         ? PHP_EOL . $response->getBody()
0238                         : ' No body - check for headers')
0239                 );
0240         }
0241     }
0242 
0243     /**
0244      * Generates a valid OAuth Authorization header based on the provided
0245      * parameters and realm.
0246      *
0247      * @param  array $params
0248      * @param  string $realm
0249      * @return string
0250      */
0251     protected function _toAuthorizationHeader(array $params, $realm = null)
0252     {
0253         $headerValue = array();
0254         $headerValue[] = 'OAuth realm="' . $realm . '"';
0255         foreach ($params as $key => $value) {
0256             if (!preg_match("/^oauth_/", $key)) {
0257                 continue;
0258             }
0259             $headerValue[] = Zend_Oauth_Http_Utility::urlEncode($key)
0260                            . '="'
0261                            . Zend_Oauth_Http_Utility::urlEncode($value)
0262                            . '"';
0263         }
0264         return implode(",", $headerValue);
0265     }
0266 }