1
0

OAuthSignature.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. <?php
  2. namespace YahnisElsts\PluginUpdateChecker\v5p1;
  3. if ( !class_exists(OAuthSignature::class, false) ):
  4. /**
  5. * A basic signature generator for zero-legged OAuth 1.0.
  6. */
  7. class OAuthSignature {
  8. private $consumerKey = '';
  9. private $consumerSecret = '';
  10. public function __construct($consumerKey, $consumerSecret) {
  11. $this->consumerKey = $consumerKey;
  12. $this->consumerSecret = $consumerSecret;
  13. }
  14. /**
  15. * Sign a URL using OAuth 1.0.
  16. *
  17. * @param string $url The URL to be signed. It may contain query parameters.
  18. * @param string $method HTTP method such as "GET", "POST" and so on.
  19. * @return string The signed URL.
  20. */
  21. public function sign($url, $method = 'GET') {
  22. $parameters = array();
  23. //Parse query parameters.
  24. $query = wp_parse_url($url, PHP_URL_QUERY);
  25. if ( !empty($query) ) {
  26. parse_str($query, $parsedParams);
  27. if ( is_array($parsedParams) ) {
  28. $parameters = $parsedParams;
  29. }
  30. //Remove the query string from the URL. We'll replace it later.
  31. $url = substr($url, 0, strpos($url, '?'));
  32. }
  33. $parameters = array_merge(
  34. $parameters,
  35. array(
  36. 'oauth_consumer_key' => $this->consumerKey,
  37. 'oauth_nonce' => $this->nonce(),
  38. 'oauth_signature_method' => 'HMAC-SHA1',
  39. 'oauth_timestamp' => time(),
  40. 'oauth_version' => '1.0',
  41. )
  42. );
  43. unset($parameters['oauth_signature']);
  44. //Parameters must be sorted alphabetically before signing.
  45. ksort($parameters);
  46. //The most complicated part of the request - generating the signature.
  47. //The string to sign contains the HTTP method, the URL path, and all of
  48. //our query parameters. Everything is URL encoded. Then we concatenate
  49. //them with ampersands into a single string to hash.
  50. $encodedVerb = urlencode($method);
  51. $encodedUrl = urlencode($url);
  52. $encodedParams = urlencode(http_build_query($parameters, '', '&'));
  53. $stringToSign = $encodedVerb . '&' . $encodedUrl . '&' . $encodedParams;
  54. //Since we only have one OAuth token (the consumer secret) we only have
  55. //to use it as our HMAC key. However, we still have to append an & to it
  56. //as if we were using it with additional tokens.
  57. $secret = urlencode($this->consumerSecret) . '&';
  58. //The signature is a hash of the consumer key and the base string. Note
  59. //that we have to get the raw output from hash_hmac and base64 encode
  60. //the binary data result.
  61. $parameters['oauth_signature'] = base64_encode(hash_hmac('sha1', $stringToSign, $secret, true));
  62. return ($url . '?' . http_build_query($parameters));
  63. }
  64. /**
  65. * Generate a random nonce.
  66. *
  67. * @return string
  68. */
  69. private function nonce() {
  70. $mt = microtime();
  71. $rand = null;
  72. if ( is_callable('random_bytes') ) {
  73. try {
  74. $rand = random_bytes(16);
  75. } catch (\Exception $ex) {
  76. //Fall back to mt_rand (below).
  77. }
  78. }
  79. if ( $rand === null ) {
  80. //phpcs:ignore WordPress.WP.AlternativeFunctions.rand_mt_rand
  81. $rand = function_exists('wp_rand') ? wp_rand() : mt_rand();
  82. }
  83. return md5($mt . '_' . $rand);
  84. }
  85. }
  86. endif;