/lib/EpiOAuth.php

https://github.com/Knight-Mozilla/spurious · PHP · 233 lines · 191 code · 37 blank · 5 comment · 18 complexity · 70bf670b7c7a2940c514756b5bbe3a2a MD5 · raw file

  1. <?php
  2. session_start();
  3. class EpiOAuth
  4. {
  5. public $version = '1.0';
  6. protected $requestTokenUrl;
  7. protected $accessTokenUrl;
  8. protected $authorizeUrl;
  9. protected $consumerKey;
  10. protected $consumerSecret;
  11. protected $token;
  12. protected $tokenSecret;
  13. protected $signatureMethod;
  14. public function getAccessToken()
  15. {
  16. $resp = $this->httpRequest('GET', $this->accessTokenUrl);
  17. return new EpiOAuthResponse($resp);
  18. }
  19. public function getAuthorizationUrl()
  20. {
  21. $retval = "{$this->authorizeUrl}?";
  22. $token = $this->getRequestToken();
  23. return $this->authorizeUrl . '?oauth_token=' . $token->oauth_token;
  24. }
  25. public function getRequestToken()
  26. {
  27. $resp = $this->httpRequest('GET', $this->requestTokenUrl);
  28. return new EpiOAuthResponse($resp);
  29. }
  30. public function httpRequest($method = null, $url = null, $params = null)
  31. {
  32. if(empty($method) || empty($url))
  33. return false;
  34. if(empty($params['oauth_signature']))
  35. $params = $this->prepareParameters($method, $url, $params);
  36. switch($method)
  37. {
  38. case 'GET':
  39. return $this->httpGet($url, $params);
  40. break;
  41. case 'POST':
  42. return $this->httpPost($url, $params);
  43. break;
  44. }
  45. }
  46. public function setToken($token = null, $secret = null)
  47. {
  48. $params = func_get_args();
  49. $this->token = $token;
  50. $this->tokenSecret = $secret;
  51. }
  52. public function encode($string)
  53. {
  54. return rawurlencode(utf8_encode($string));
  55. }
  56. protected function addOAuthHeaders(&$ch, $url, $oauthHeaders)
  57. {
  58. $_h = array('Expect:');
  59. $urlParts = parse_url($url);
  60. $oauth = 'Authorization: OAuth realm="' . $urlParts['path'] . '",';
  61. foreach($oauthHeaders as $name => $value)
  62. {
  63. $oauth .= "{$name}=\"{$value}\",";
  64. }
  65. $_h[] = substr($oauth, 0, -1);
  66. curl_setopt($ch, CURLOPT_HTTPHEADER, $_h);
  67. }
  68. protected function generateNonce()
  69. {
  70. if(isset($this->nonce)) // for unit testing
  71. return $this->nonce;
  72. return md5(uniqid(rand(), true));
  73. }
  74. protected function generateSignature($method = null, $url = null, $params = null)
  75. {
  76. if(empty($method) || empty($url))
  77. return false;
  78. // concatenating
  79. $concatenatedParams = '';
  80. foreach($params as $k => $v)
  81. {
  82. $v = $this->encode($v);
  83. $concatenatedParams .= "{$k}={$v}&";
  84. }
  85. $concatenatedParams = $this->encode(substr($concatenatedParams, 0, -1));
  86. // normalize url
  87. $normalizedUrl = $this->encode($this->normalizeUrl($url));
  88. $method = $this->encode($method); // don't need this but why not?
  89. $signatureBaseString = "{$method}&{$normalizedUrl}&{$concatenatedParams}";
  90. return $this->signString($signatureBaseString);
  91. }
  92. protected function httpGet($url, $params = null)
  93. {
  94. if(count($params['request']) > 0)
  95. {
  96. $url .= '?';
  97. foreach($params['request'] as $k => $v)
  98. {
  99. $url .= "{$k}={$v}&";
  100. }
  101. $url = substr($url, 0, -1);
  102. }
  103. $ch = curl_init($url);
  104. $this->addOAuthHeaders($ch, $url, $params['oauth']);
  105. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  106. $resp = $this->curl->addCurl($ch);
  107. return $resp;
  108. }
  109. protected function httpPost($url, $params = null)
  110. {
  111. $ch = curl_init($url);
  112. $this->addOAuthHeaders($ch, $url, $params['oauth']);
  113. curl_setopt($ch, CURLOPT_POST, 1);
  114. curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params['request']));
  115. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  116. $resp = $this->curl->addCurl($ch);
  117. return $resp;
  118. }
  119. protected function normalizeUrl($url = null)
  120. {
  121. $urlParts = parse_url($url);
  122. $scheme = strtolower($urlParts['scheme']);
  123. $host = strtolower($urlParts['host']);
  124. $port = intval($urlParts['port']);
  125. $retval = "{$scheme}://{$host}";
  126. if($port > 0 && ($scheme === 'http' && $port !== 80) || ($scheme === 'https' && $port !== 443))
  127. {
  128. $retval .= ":{$port}";
  129. }
  130. $retval .= $urlParts['path'];
  131. if(!empty($urlParts['query']))
  132. {
  133. $retval .= "?{$urlParts['query']}";
  134. }
  135. return $retval;
  136. }
  137. protected function prepareParameters($method = null, $url = null, $params = null)
  138. {
  139. if(empty($method) || empty($url))
  140. return false;
  141. $oauth['oauth_consumer_key'] = $this->consumerKey;
  142. $oauth['oauth_token'] = $this->token;
  143. $oauth['oauth_nonce'] = $this->generateNonce();
  144. $oauth['oauth_timestamp'] = !isset($this->timestamp) ? time() : $this->timestamp; // for unit test
  145. $oauth['oauth_signature_method'] = $this->signatureMethod;
  146. $oauth['oauth_version'] = $this->version;
  147. // encoding
  148. array_walk($oauth, array($this, 'encode'));
  149. if(is_array($params))
  150. array_walk($params, array($this, 'encode'));
  151. $encodedParams = array_merge($oauth, (array)$params);
  152. // sorting
  153. ksort($encodedParams);
  154. // signing
  155. $oauth['oauth_signature'] = $this->encode($this->generateSignature($method, $url, $encodedParams));
  156. return array('request' => $params, 'oauth' => $oauth);
  157. }
  158. protected function signString($string = null)
  159. {
  160. $retval = false;
  161. switch($this->signatureMethod)
  162. {
  163. case 'HMAC-SHA1':
  164. $key = $this->encode($this->consumerSecret) . '&' . $this->encode($this->tokenSecret);
  165. $retval = base64_encode(hash_hmac('sha1', $string, $key, true));
  166. break;
  167. }
  168. return $retval;
  169. }
  170. public function __construct($consumerKey, $consumerSecret, $signatureMethod='HMAC-SHA1')
  171. {
  172. $this->consumerKey = $consumerKey;
  173. $this->consumerSecret = $consumerSecret;
  174. $this->signatureMethod = $signatureMethod;
  175. $this->curl = EpiCurl::getInstance();
  176. }
  177. }
  178. class EpiOAuthResponse
  179. {
  180. private $__resp;
  181. public function __construct($resp)
  182. {
  183. $this->__resp = $resp;
  184. }
  185. public function __get($name)
  186. {
  187. if($this->__resp->code < 200 || $this->__resp->code > 299)
  188. return false;
  189. parse_str($this->__resp->data, $result);
  190. foreach($result as $k => $v)
  191. {
  192. $this->$k = $v;
  193. }
  194. return $result[$name];
  195. }
  196. }