/wp-content/plugins/backwpup/sdk/Aws/Guzzle/Plugin/Oauth/OauthPlugin.php

https://bitbucket.org/cesarmedrano/cesarmedrano · PHP · 226 lines · 119 code · 26 blank · 81 comment · 5 complexity · 5f94a5a37112cd404592ff37027ca05c MD5 · raw file

  1. <?php
  2. namespace Guzzle\Plugin\Oauth;
  3. use Guzzle\Common\Event;
  4. use Guzzle\Common\Collection;
  5. use Guzzle\Http\Message\RequestInterface;
  6. use Guzzle\Http\Message\EntityEnclosingRequestInterface;
  7. use Guzzle\Http\Url;
  8. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  9. /**
  10. * OAuth signing plugin
  11. * @link http://oauth.net/core/1.0/#rfc.section.9.1.1
  12. */
  13. class OauthPlugin implements EventSubscriberInterface
  14. {
  15. /**
  16. * @var Collection Configuration settings
  17. */
  18. protected $config;
  19. /**
  20. * Create a new OAuth 1.0 plugin
  21. *
  22. * @param array $config Configuration array containing these parameters:
  23. * - string 'consumer_key' Consumer key
  24. * - string 'consumer_secret' Consumer secret
  25. * - string 'token' Token
  26. * - string 'token_secret' Token secret
  27. * - string 'version' OAuth version. Defaults to 1.0
  28. * - string 'signature_method' Custom signature method
  29. * - bool 'disable_post_params' Set to true to prevent POST parameters from being signed
  30. * - array|Closure 'signature_callback' Custom signature callback that accepts a string to sign and a signing key
  31. */
  32. public function __construct($config)
  33. {
  34. $this->config = Collection::fromConfig($config, array(
  35. 'version' => '1.0',
  36. 'consumer_key' => 'anonymous',
  37. 'consumer_secret' => 'anonymous',
  38. 'signature_method' => 'HMAC-SHA1',
  39. 'signature_callback' => function($stringToSign, $key) {
  40. return hash_hmac('sha1', $stringToSign, $key, true);
  41. }
  42. ), array(
  43. 'signature_method', 'signature_callback', 'version',
  44. 'consumer_key', 'consumer_secret'
  45. ));
  46. }
  47. /**
  48. * {@inheritdoc}
  49. */
  50. public static function getSubscribedEvents()
  51. {
  52. return array(
  53. 'request.before_send' => array('onRequestBeforeSend', -1000)
  54. );
  55. }
  56. /**
  57. * Request before-send event handler
  58. *
  59. * @param Event $event Event received
  60. * @return array
  61. */
  62. public function onRequestBeforeSend(Event $event)
  63. {
  64. $timestamp = $this->getTimestamp($event);
  65. $request = $event['request'];
  66. $nonce = $this->generateNonce($request);
  67. $authorizationParams = array(
  68. 'oauth_consumer_key' => $this->config['consumer_key'],
  69. 'oauth_nonce' => $nonce,
  70. 'oauth_signature' => $this->getSignature($request, $timestamp, $nonce),
  71. 'oauth_signature_method' => $this->config['signature_method'],
  72. 'oauth_timestamp' => $timestamp,
  73. 'oauth_token' => $this->config['token'],
  74. 'oauth_version' => $this->config['version'],
  75. );
  76. $request->setHeader(
  77. 'Authorization',
  78. $this->buildAuthorizationHeader($authorizationParams)
  79. );
  80. return $authorizationParams;
  81. }
  82. /**
  83. * Builds the Authorization header for a request
  84. *
  85. * @param array $authorizationParams Associative array of authorization parameters
  86. *
  87. * @return string
  88. */
  89. private function buildAuthorizationHeader($authorizationParams)
  90. {
  91. $authorizationString = 'OAuth ';
  92. foreach ($authorizationParams as $key => $val) {
  93. if ($val) {
  94. $authorizationString .= $key . '="' . urlencode($val) . '", ';
  95. }
  96. }
  97. return substr($authorizationString, 0, -2);
  98. }
  99. /**
  100. * Calculate signature for request
  101. *
  102. * @param RequestInterface $request Request to generate a signature for
  103. * @param integer $timestamp Timestamp to use for nonce
  104. * @param string $nonce
  105. *
  106. * @return string
  107. */
  108. public function getSignature(RequestInterface $request, $timestamp, $nonce)
  109. {
  110. $string = $this->getStringToSign($request, $timestamp, $nonce);
  111. $key = urlencode($this->config['consumer_secret']) . '&' . urlencode($this->config['token_secret']);
  112. return base64_encode(call_user_func($this->config['signature_callback'], $string, $key));
  113. }
  114. /**
  115. * Calculate string to sign
  116. *
  117. * @param RequestInterface $request Request to generate a signature for
  118. * @param int $timestamp Timestamp to use for nonce
  119. * @param string $nonce
  120. * @return string
  121. */
  122. public function getStringToSign(RequestInterface $request, $timestamp, $nonce)
  123. {
  124. $params = $this->getParamsToSign($request, $timestamp, $nonce);
  125. // Build signing string from combined params
  126. $parameterString = array();
  127. foreach ($params as $key => $values) {
  128. $key = rawurlencode($key);
  129. $values = (array) $values;
  130. sort($values);
  131. foreach ($values as $value) {
  132. if (is_bool($value)) {
  133. $value = $value ? 'true' : 'false';
  134. }
  135. $parameterString[] = $key . '=' . rawurlencode($value);
  136. }
  137. }
  138. $url = Url::factory($request->getUrl())->setQuery('')->setFragment(null);
  139. return strtoupper($request->getMethod()) . '&'
  140. . rawurlencode($url) . '&'
  141. . rawurlencode(implode('&', $parameterString));
  142. }
  143. /**
  144. * Parameters sorted and filtered in order to properly sign a request
  145. *
  146. * @param RequestInterface $request Request to generate a signature for
  147. * @param integer $timestamp Timestamp to use for nonce
  148. * @param string $nonce
  149. *
  150. * @return array
  151. */
  152. public function getParamsToSign(RequestInterface $request, $timestamp, $nonce)
  153. {
  154. $params = new Collection(array(
  155. 'oauth_consumer_key' => $this->config['consumer_key'],
  156. 'oauth_nonce' => $nonce,
  157. 'oauth_signature_method' => $this->config['signature_method'],
  158. 'oauth_timestamp' => $timestamp,
  159. 'oauth_version' => $this->config['version']
  160. ));
  161. // Filter out oauth_token during temp token step, as in request_token.
  162. if ($this->config['token'] !== false) {
  163. $params->add('oauth_token', $this->config['token']);
  164. }
  165. // Add query string parameters
  166. $params->merge($request->getQuery());
  167. // Add POST fields to signing string
  168. if (!$this->config->get('disable_post_params') &&
  169. $request instanceof EntityEnclosingRequestInterface &&
  170. (string) $request->getHeader('Content-Type') == 'application/x-www-form-urlencoded') {
  171. $params->merge($request->getPostFields());
  172. }
  173. // Sort params
  174. $params = $params->getAll();
  175. ksort($params);
  176. return $params;
  177. }
  178. /**
  179. * Returns a Nonce Based on the unique id and URL. This will allow for multiple requests in parallel with the same
  180. * exact timestamp to use separate nonce's.
  181. *
  182. * @param RequestInterface $request Request to generate a nonce for
  183. *
  184. * @return string
  185. */
  186. public function generateNonce(RequestInterface $request)
  187. {
  188. return sha1(uniqid('', true) . $request->getUrl());
  189. }
  190. /**
  191. * Gets timestamp from event or create new timestamp
  192. *
  193. * @param Event $event
  194. * @return integer
  195. */
  196. public function getTimestamp(Event $event)
  197. {
  198. return $event['timestamp'] ? : time();
  199. }
  200. }