/source/Oj/OAuth/Detail.php

https://github.com/fetus-hina/OhkaJournal · PHP · 204 lines · 176 code · 13 blank · 15 comment · 25 complexity · 6f4057d417db0c6f39ef6191f215021c MD5 · raw file

  1. <?php
  2. class Oj_OAuth_Detail {
  3. // 3.6.
  4. // rawurlencode() でも良いが、rawurlencode() は upper-case を保証していない気がする
  5. // OAuth では SHA-1 に通す関係で upper-case 必須
  6. static public function percentEncoding($text) {
  7. return
  8. preg_replace_callback(
  9. '/[^[:alnum:]\-._~]/',
  10. function (array $match) { return sprintf('%%%02X', ord($match[0])); },
  11. (string)$text);
  12. }
  13. // 3.4.1.1
  14. static private function signatureBaseString(
  15. $http_method,
  16. $base_string_uri,
  17. $normalized_parameters)
  18. {
  19. $result =
  20. implode(
  21. '&',
  22. array(
  23. self::percentEncoding(strtoupper($http_method)),
  24. self::percentEncoding($base_string_uri),
  25. self::percentEncoding($normalized_parameters)));
  26. return $result;
  27. }
  28. // 3.4.2.1
  29. static private function formatBaseStringUri(Zend_Uri_Http $uri) {
  30. $scheme = strtolower(trim($uri->getScheme()));
  31. $host = strtolower(trim($uri->getHost()));
  32. $port = (int)$uri->getPort();
  33. $path = trim($uri->getPath());
  34. $result = $scheme . '://' . $host;
  35. if($port > 0) {
  36. if(($scheme === 'http' && $port !== 80) ||
  37. ($scheme === 'https' && $port !== 443))
  38. {
  39. $result .= ':' . (string)$port;
  40. }
  41. }
  42. $result .= ($path === '') ? '/' : $path;
  43. return $result;
  44. }
  45. // 3.4.1.3.1. Parameter Sources
  46. static private function parameterSources(Zend_Uri_Http $uri, array $oauth_params, $http_content) {
  47. $parameters = array();
  48. // URL クエリのコピー
  49. if(($query = $uri->getQuery()) != '') {
  50. foreach(explode('&', $query) as $pair_) {
  51. if($pair = explode('=', $pair_)) {
  52. $key = urldecode($pair[0]);
  53. $val = isset($pair[1]) ? urldecode($pair[1]) : null;
  54. if(!isset($parameters[$key])) {
  55. $parameters[$key] = array();
  56. }
  57. $parameters[$key][] = $val;
  58. }
  59. }
  60. }
  61. // OAuth パラメータのコピー
  62. foreach($oauth_params as $key => $value) {
  63. if($key !== 'realm' && $key !== 'oauth_signature') {
  64. if(!isset($parameters[$key])) {
  65. $parameters[$key] = array();
  66. }
  67. $parameters[$key][] = $value;
  68. }
  69. }
  70. // リクエストボディのコピー
  71. if($http_content != '') {
  72. if(is_array($http_content)) {
  73. foreach($http_content as $key => $val) {
  74. if(!isset($parameters[$key])) {
  75. $parameters[$key] = array();
  76. }
  77. $parameters[$key][] = $val;
  78. }
  79. } else {
  80. foreach(explode('&', $http_content) as $pair_) {
  81. if($pair = explode('=', $pair_)) {
  82. $key = urldecode($pair[0]);
  83. $val = isset($pair[1]) ? urldecode($pair[1]) : null;
  84. if(!isset($parameters[$key])) {
  85. $parameters[$key] = array();
  86. }
  87. $parameters[$key][] = $val;
  88. }
  89. }
  90. }
  91. }
  92. return $parameters;
  93. }
  94. // 3.4.1.3.2. パラメータのノーマライゼーション
  95. // $parameters =
  96. // array(
  97. // 'key1' => 'val1-1',
  98. // 'key2' => array('val2-1', 'val2-2'));
  99. static private function parameterNormalization(array $parameters) {
  100. $result = array();
  101. uksort($parameters, function($a,$b){return strcmp(Oj_OAuth_Detail::percentEncoding($a), Oj_OAuth_Detail::percentEncoding($b));});
  102. foreach($parameters as $key => $value) {
  103. if(is_array($value)) {
  104. usort($value, function($a, $b){return strcmp(Oj_OAuth_Detail::percentEncoding($a), Oj_OAuth_Detail::percentEncoding($b));});
  105. foreach($value as $v) {
  106. $result[] = sprintf('%s=%s', self::percentEncoding($key), self::percentEncoding($v));
  107. }
  108. } else {
  109. $result[] = sprintf('%s=%s', self::percentEncoding($key), self::percentEncoding($value));
  110. }
  111. }
  112. return implode('&', $result);
  113. }
  114. // 3.4.2 HMAC-SHA1
  115. static private function hmacSha1($text, $client_shared_key, $token_shared_key) {
  116. $key = self::percentEncoding($client_shared_key) . '&' . self::percentEncoding($token_shared_key);
  117. return Zend_Crypt_Hmac::compute($key, 'sha1', $text, Zend_Crypt_Hmac::BINARY);
  118. }
  119. static private function buildSignature(
  120. $http_method, // "GET", "POST"
  121. Zend_Uri_Http $uri, // URI
  122. $http_post_content, // string
  123. array $oauth_params,
  124. $client_shared_key,
  125. $token_shared_key)
  126. {
  127. $parameter_normalized =
  128. self::parameterNormalization(
  129. self::parameterSources(
  130. $uri,
  131. $oauth_params,
  132. $http_post_content));
  133. return
  134. base64_encode(
  135. self::hmacSha1(
  136. self::signatureBaseString(
  137. $http_method,
  138. self::formatBaseStringUri($uri),
  139. $parameter_normalized),
  140. $client_shared_key,
  141. $token_shared_key));
  142. }
  143. static private function createNonce() {
  144. $table = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  145. $result = '';
  146. for($i = 0, $table_size = strlen($table); $i < 64; ++$i) {
  147. $result .= $table[mt_rand(0, $table_size - 1)];
  148. }
  149. return $result;
  150. }
  151. static public function buildAuthorization(
  152. $http_method,
  153. Zend_Uri_Http $uri, // URI
  154. $http_post_content, // string
  155. $realm,
  156. $oauth_consumer_key,
  157. $oauth_consumer_secret,
  158. $oauth_token,
  159. $oauth_token_secret)
  160. {
  161. $oauth = array();
  162. if($oauth_consumer_key != '') {
  163. $oauth['oauth_consumer_key'] = $oauth_consumer_key;
  164. }
  165. if($oauth_token != '') {
  166. $oauth['oauth_token'] = $oauth_token;
  167. }
  168. $oauth['oauth_signature_method'] = 'HMAC-SHA1';
  169. $oauth['oauth_timestamp'] = (string)time();
  170. $oauth['oauth_nonce'] = self::createNonce();
  171. $oauth['oauth_version'] = '1.0';
  172. $signature =
  173. self::buildSignature(
  174. $http_method,
  175. $uri,
  176. $http_post_content,
  177. $oauth,
  178. $oauth_consumer_secret,
  179. $oauth_token_secret);
  180. $tmp =
  181. array_merge(
  182. array('realm' => $realm),
  183. $oauth,
  184. array('oauth_signature' => $signature));
  185. $result = array();
  186. foreach($tmp as $k => $v) {
  187. $result[] = sprintf('%s="%s"', self::percentEncoding($k), self::percentEncoding($v));
  188. }
  189. return 'OAuth ' . implode(',', $result);
  190. }
  191. }