Client.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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_Oauth
  17. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id$
  20. */
  21. /** Zend_Oauth */
  22. require_once 'Zend/Oauth.php';
  23. /** Zend_Http_Client */
  24. require_once 'Zend/Http/Client.php';
  25. /** Zend_Oauth_Http_Utility */
  26. require_once 'Zend/Oauth/Http/Utility.php';
  27. /** Zend_Oauth_Config */
  28. require_once 'Zend/Oauth/Config.php';
  29. /**
  30. * @category Zend
  31. * @package Zend_Oauth
  32. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  33. * @license http://framework.zend.com/license/new-bsd New BSD License
  34. */
  35. class Zend_Oauth_Client extends Zend_Http_Client
  36. {
  37. /**
  38. * Flag to indicate that the client has detected the server as supporting
  39. * OAuth 1.0a
  40. */
  41. public static $supportsRevisionA = false;
  42. /**
  43. * Holds the current OAuth Configuration set encapsulated in an instance
  44. * of Zend_Oauth_Config; it's not a Zend_Config instance since that level
  45. * of abstraction is unnecessary and doesn't let me escape the accessors
  46. * and mutators anyway!
  47. *
  48. * @var Zend_Oauth_Config
  49. */
  50. protected $_config = null;
  51. /**
  52. * True if this request is being made with data supplied by
  53. * a stream object instead of a raw encoded string.
  54. *
  55. * @var bool
  56. */
  57. protected $_streamingRequest = null;
  58. /**
  59. * Constructor; creates a new HTTP Client instance which itself is
  60. * just a typical Zend_Http_Client subclass with some OAuth icing to
  61. * assist in automating OAuth parameter generation, addition and
  62. * cryptographioc signing of requests.
  63. *
  64. * @param array $oauthOptions
  65. * @param string $uri
  66. * @param array|Zend_Config $config
  67. * @return void
  68. */
  69. public function __construct(array $oauthOptions, $uri = null, $config = null)
  70. {
  71. parent::__construct($uri, $config);
  72. $this->_config = new Zend_Oauth_Config;
  73. if (!is_null($oauthOptions)) {
  74. if ($oauthOptions instanceof Zend_Config) {
  75. $oauthOptions = $oauthOptions->toArray();
  76. }
  77. $this->_config->setOptions($oauthOptions);
  78. }
  79. }
  80. /**
  81. * Return the current connection adapter
  82. *
  83. * @return Zend_Http_Client_Adapter_Interface|string $adapter
  84. */
  85. public function getAdapter()
  86. {
  87. return $this->adapter;
  88. }
  89. /**
  90. * Load the connection adapter
  91. *
  92. * @param Zend_Http_Client_Adapter_Interface $adapter
  93. * @return void
  94. */
  95. public function setAdapter($adapter)
  96. {
  97. if ($adapter == null) {
  98. $this->adapter = $adapter;
  99. } else {
  100. parent::setAdapter($adapter);
  101. }
  102. }
  103. /**
  104. * Set the streamingRequest variable which controls whether we are
  105. * sending the raw (already encoded) POST data from a stream source.
  106. *
  107. * @param boolean $value The value to set.
  108. * @return void
  109. */
  110. public function setStreamingRequest($value)
  111. {
  112. $this->_streamingRequest = $value;
  113. }
  114. /**
  115. * Check whether the client is set to perform streaming requests.
  116. *
  117. * @return boolean True if yes, false otherwise.
  118. */
  119. public function getStreamingRequest()
  120. {
  121. if ($this->_streamingRequest) {
  122. return true;
  123. } else {
  124. return false;
  125. }
  126. }
  127. /**
  128. * Prepare the request body (for POST and PUT requests)
  129. *
  130. * @return string
  131. * @throws Zend_Http_Client_Exception
  132. */
  133. protected function _prepareBody()
  134. {
  135. if($this->_streamingRequest) {
  136. $this->setHeaders(self::CONTENT_LENGTH,
  137. $this->raw_post_data->getTotalSize());
  138. return $this->raw_post_data;
  139. }
  140. else {
  141. return parent::_prepareBody();
  142. }
  143. }
  144. /**
  145. * Clear all custom parameters we set.
  146. *
  147. * @return Zend_Http_Client
  148. */
  149. public function resetParameters($clearAll = false)
  150. {
  151. $this->_streamingRequest = false;
  152. return parent::resetParameters($clearAll);
  153. }
  154. /**
  155. * Set the raw (already encoded) POST data from a stream source.
  156. *
  157. * This is used to support POSTing from open file handles without
  158. * caching the entire body into memory. It is a wrapper around
  159. * Zend_Http_Client::setRawData().
  160. *
  161. * @param string $data The request data
  162. * @param string $enctype The encoding type
  163. * @return Zend_Http_Client
  164. */
  165. public function setRawDataStream($data, $enctype = null)
  166. {
  167. $this->_streamingRequest = true;
  168. return $this->setRawData($data, $enctype);
  169. }
  170. /**
  171. * Same as Zend_Http_Client::setMethod() except it also creates an
  172. * Oauth specific reference to the method type.
  173. * Might be defunct and removed in a later iteration.
  174. *
  175. * @param string $method
  176. * @return Zend_Http_Client
  177. */
  178. public function setMethod($method = self::GET)
  179. {
  180. if ($method == self::GET) {
  181. $this->setRequestMethod(self::GET);
  182. } elseif($method == self::POST) {
  183. $this->setRequestMethod(self::POST);
  184. } elseif($method == self::PUT) {
  185. $this->setRequestMethod(self::PUT);
  186. } elseif($method == self::DELETE) {
  187. $this->setRequestMethod(self::DELETE);
  188. } elseif($method == self::HEAD) {
  189. $this->setRequestMethod(self::HEAD);
  190. }
  191. return parent::setMethod($method);
  192. }
  193. /**
  194. * Same as Zend_Http_Client::request() except just before the request is
  195. * executed, we automatically append any necessary OAuth parameters and
  196. * sign the request using the relevant signature method.
  197. *
  198. * @param string $method
  199. * @return Zend_Http_Response
  200. */
  201. public function request($method = null)
  202. {
  203. if (!is_null($method)) {
  204. $this->setMethod($method);
  205. }
  206. $this->prepareOauth();
  207. return parent::request();
  208. }
  209. /**
  210. * Performs OAuth preparation on the request before sending.
  211. *
  212. * This primarily means taking a request, correctly encoding and signing
  213. * all parameters, and applying the correct OAuth scheme to the method
  214. * being used.
  215. *
  216. * @return void
  217. * @throws Zend_Oauth_Exception If POSTBODY scheme requested, but GET request method used; or if invalid request scheme provided
  218. */
  219. public function prepareOauth()
  220. {
  221. $requestScheme = $this->getRequestScheme();
  222. $requestMethod = $this->getRequestMethod();
  223. $query = null;
  224. if ($requestScheme == Zend_Oauth::REQUEST_SCHEME_HEADER) {
  225. $oauthHeaderValue = $this->getToken()->toHeader(
  226. $this->getUri(true),
  227. $this->_config,
  228. $this->_getSignableParametersAsQueryString()
  229. );
  230. $this->setHeaders('Authorization', $oauthHeaderValue);
  231. } elseif ($requestScheme == Zend_Oauth::REQUEST_SCHEME_POSTBODY) {
  232. if ($requestMethod == self::GET) {
  233. require_once 'Zend/Oauth/Exception.php';
  234. throw new Zend_Oauth_Exception(
  235. 'The client is configured to'
  236. . ' pass OAuth parameters through a POST body but request method'
  237. . ' is set to GET'
  238. );
  239. }
  240. $raw = $this->getToken()->toQueryString(
  241. $this->getUri(true),
  242. $this->_config,
  243. $this->_getSignableParametersAsQueryString()
  244. );
  245. $this->setRawData($raw);
  246. $this->paramsPost = array();
  247. } elseif ($requestScheme == Zend_Oauth::REQUEST_SCHEME_QUERYSTRING) {
  248. $params = array();
  249. $query = $this->getUri()->getQuery();
  250. if ($query) {
  251. $queryParts = explode('&', $this->getUri()->getQuery());
  252. foreach ($queryParts as $queryPart) {
  253. $kvTuple = explode('=', $queryPart);
  254. $params[$kvTuple[0]] =
  255. (array_key_exists(1, $kvTuple) ? $kvTuple[1] : NULL);
  256. }
  257. }
  258. if (!empty($this->paramsPost)) {
  259. $params = array_merge($params, $this->paramsPost);
  260. $query = $this->getToken()->toQueryString(
  261. $this->getUri(true), $this->_config, $params
  262. );
  263. }
  264. $query = $this->getToken()->toQueryString(
  265. $this->getUri(true), $this->_config, $params
  266. );
  267. $this->getUri()->setQuery($query);
  268. $this->paramsGet = array();
  269. } else {
  270. require_once 'Zend/Oauth/Exception.php';
  271. throw new Zend_Oauth_Exception('Invalid request scheme: ' . $requestScheme);
  272. }
  273. }
  274. /**
  275. * Collect all signable parameters into a single array across query string
  276. * and POST body. These are returned as a properly formatted single
  277. * query string.
  278. *
  279. * @return string
  280. */
  281. protected function _getSignableParametersAsQueryString()
  282. {
  283. $params = array();
  284. if (!empty($this->paramsGet)) {
  285. $params = array_merge($params, $this->paramsGet);
  286. $query = $this->getToken()->toQueryString(
  287. $this->getUri(true), $this->_config, $params
  288. );
  289. }
  290. if (!empty($this->paramsPost)) {
  291. $params = array_merge($params, $this->paramsPost);
  292. $query = $this->getToken()->toQueryString(
  293. $this->getUri(true), $this->_config, $params
  294. );
  295. }
  296. return $params;
  297. }
  298. /**
  299. * Simple Proxy to the current Zend_Oauth_Config method. It's that instance
  300. * which holds all configuration methods and values this object also presents
  301. * as it's API.
  302. *
  303. * @param string $method
  304. * @param array $args
  305. * @return mixed
  306. * @throws Zend_Oauth_Exception if method does not exist in config object
  307. */
  308. public function __call($method, array $args)
  309. {
  310. if (!method_exists($this->_config, $method)) {
  311. require_once 'Zend/Oauth/Exception.php';
  312. throw new Zend_Oauth_Exception('Method does not exist: ' . $method);
  313. }
  314. return call_user_func_array(array($this->_config,$method), $args);
  315. }
  316. }