PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/apps/files_external/3rdparty/Dropbox/OAuth/Curl.php

https://gitlab.com/wuhang2003/core
PHP | 310 lines | 190 code | 32 blank | 88 comment | 34 complexity | 45a35c2400f55f6875cf5db39daf0a74 MD5 | raw file
  1. <?php
  2. /**
  3. * Dropbox OAuth
  4. *
  5. * @package Dropbox
  6. * @copyright Copyright (C) 2011 Daniel Huesken
  7. * @author Daniel Huesken (http://www.danielhuesken.de/)
  8. * @license MIT
  9. */
  10. /**
  11. * This class is used to sign all requests to dropbox.
  12. *
  13. * This specific class uses WordPress WP_Http to authenticate.
  14. */
  15. class Dropbox_OAuth_Curl extends Dropbox_OAuth {
  16. /**
  17. *
  18. * @var string ConsumerKey
  19. */
  20. protected $consumerKey = null;
  21. /**
  22. *
  23. * @var string ConsumerSecret
  24. */
  25. protected $consumerSecret = null;
  26. /**
  27. *
  28. * @var string ProzessCallBack
  29. */
  30. public $ProgressFunction = false;
  31. /**
  32. * Constructor
  33. *
  34. * @param string $consumerKey
  35. * @param string $consumerSecret
  36. */
  37. public function __construct($consumerKey, $consumerSecret) {
  38. if (!function_exists('curl_exec'))
  39. throw new Dropbox_Exception('The PHP curl functions not available!');
  40. $this->consumerKey = $consumerKey;
  41. $this->consumerSecret = $consumerSecret;
  42. $this->putSupported = true;
  43. }
  44. /**
  45. * Fetches a secured oauth url and returns the response body.
  46. *
  47. * @param string $uri
  48. * @param mixed $arguments
  49. * @param string $method
  50. * @param array $httpHeaders
  51. * @return string
  52. */
  53. public function fetch($uri, $arguments = array(), $method = 'GET', $httpHeaders = array()) {
  54. $uri=str_replace('http://', 'https://', $uri); // all https, upload makes problems if not
  55. if (is_string($arguments) and strtoupper($method) == 'POST') {
  56. preg_match("/\?file=(.*)$/i", $uri, $matches);
  57. if (isset($matches[1])) {
  58. $uri = str_replace($matches[0], "", $uri);
  59. $filename = rawurldecode(str_replace('%7E', '~', $matches[1]));
  60. $httpHeaders=array_merge($httpHeaders,$this->getOAuthHeader($uri, array("file" => $filename), $method));
  61. }
  62. } else {
  63. $httpHeaders=array_merge($httpHeaders,$this->getOAuthHeader($uri, $arguments, $method));
  64. }
  65. $ch = curl_init();
  66. if (strtoupper($method) == 'POST') {
  67. curl_setopt($ch, CURLOPT_URL, $uri);
  68. curl_setopt($ch, CURLOPT_POST, true);
  69. if (is_array($arguments)) {
  70. $arguments=http_build_query($arguments);
  71. }
  72. curl_setopt($ch, CURLOPT_POSTFIELDS, $arguments);
  73. $httpHeaders['Content-Length']=strlen($arguments);
  74. } else if (strtoupper($method) == 'PUT' && $this->inFile) {
  75. curl_setopt($ch, CURLOPT_URL, $uri.'?'.http_build_query($arguments));
  76. curl_setopt($ch, CURLOPT_PUT, true);
  77. curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
  78. curl_setopt($ch, CURLOPT_INFILE, $this->inFile);
  79. curl_setopt($ch, CURLOPT_INFILESIZE, $this->inFileSize);
  80. fseek($this->inFile, 0);
  81. $this->inFileSize = $this->inFile = null;
  82. } else {
  83. curl_setopt($ch, CURLOPT_URL, $uri.'?'.http_build_query($arguments));
  84. curl_setopt($ch, CURLOPT_POST, false);
  85. }
  86. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  87. curl_setopt($ch, CURLOPT_TIMEOUT, 600);
  88. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
  89. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
  90. curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
  91. curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . DIRECTORY_SEPARATOR . 'ca-bundle.pem');
  92. //Build header
  93. $headers = array();
  94. foreach ($httpHeaders as $name => $value) {
  95. $headers[] = "{$name}: $value";
  96. }
  97. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  98. if (!ini_get('safe_mode') && !ini_get('open_basedir'))
  99. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true );
  100. if (function_exists($this->ProgressFunction) and defined('CURLOPT_PROGRESSFUNCTION')) {
  101. curl_setopt($ch, CURLOPT_NOPROGRESS, false);
  102. curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, $this->ProgressFunction);
  103. curl_setopt($ch, CURLOPT_BUFFERSIZE, 512);
  104. }
  105. $response=curl_exec($ch);
  106. $errorno=curl_errno($ch);
  107. $error=curl_error($ch);
  108. $status=curl_getinfo($ch,CURLINFO_HTTP_CODE);
  109. curl_close($ch);
  110. $this->lastResponse = array(
  111. 'httpStatus' => $status,
  112. 'body' => $response
  113. );
  114. if (!empty($errorno))
  115. throw new Dropbox_Exception_NotFound('Curl error: ('.$errorno.') '.$error."\n");
  116. if ($status>=300) {
  117. $body = array();
  118. $body = json_decode($response, true);
  119. if (!is_array($body)) {
  120. $body = array();
  121. }
  122. $jsonErr = isset($body['error'])? $body['error'] : '';
  123. switch ($status) {
  124. // Not modified
  125. case 304 :
  126. return array(
  127. 'httpStatus' => 304,
  128. 'body' => null,
  129. );
  130. break;
  131. case 400 :
  132. throw new Dropbox_Exception_Forbidden('Forbidden. Bad input parameter. Error message should indicate which one and why.');
  133. case 401 :
  134. throw new Dropbox_Exception_Forbidden('Forbidden. Bad or expired token. This can happen if the user or Dropbox revoked or expired an access token. To fix, you should re-authenticate the user.');
  135. case 403 :
  136. throw new Dropbox_Exception_Forbidden('Forbidden. This could mean a bad OAuth request, or a file or folder already existing at the target location.');
  137. case 404 :
  138. throw new Dropbox_Exception_NotFound('Resource at uri: ' . $uri . ' could not be found');
  139. case 405 :
  140. throw new Dropbox_Exception_Forbidden('Forbidden. Request method not expected (generally should be GET or POST).');
  141. case 500 :
  142. throw new Dropbox_Exception_Forbidden('Server error. ' . $jsonErr);
  143. case 503 :
  144. throw new Dropbox_Exception_Forbidden('Forbidden. Your app is making too many requests and is being rate limited. 503s can trigger on a per-app or per-user basis.');
  145. case 507 :
  146. throw new Dropbox_Exception_OverQuota('This dropbox is full');
  147. default:
  148. throw new Dropbox_Exception_RequestToken('Error: ('.$status.') ' . $jsonErr);
  149. }
  150. if (!empty($body["error"]))
  151. throw new Dropbox_Exception_RequestToken('Error: ('.$status.') ' . $jsonErr);
  152. }
  153. return array(
  154. 'body' => $response,
  155. 'httpStatus' => $status
  156. );
  157. }
  158. /**
  159. * Returns named array with oauth parameters for further use
  160. * @return array Array with oauth_ parameters
  161. */
  162. private function getOAuthBaseParams() {
  163. $params['oauth_version'] = '1.0';
  164. $params['oauth_signature_method'] = 'HMAC-SHA1';
  165. $params['oauth_consumer_key'] = $this->consumerKey;
  166. $tokens = $this->getToken();
  167. if (isset($tokens['token']) && $tokens['token']) {
  168. $params['oauth_token'] = $tokens['token'];
  169. }
  170. $params['oauth_timestamp'] = time();
  171. $params['oauth_nonce'] = md5(microtime() . mt_rand());
  172. return $params;
  173. }
  174. /**
  175. * Creates valid Authorization header for OAuth, based on URI and Params
  176. *
  177. * @param string $uri
  178. * @param array $params
  179. * @param string $method GET or POST, standard is GET
  180. * @param array $oAuthParams optional, pass your own oauth_params here
  181. * @return array Array for request's headers section like
  182. * array('Authorization' => 'OAuth ...');
  183. */
  184. public function getOAuthHeader($uri, $params, $method = 'GET', $oAuthParams = null) {
  185. $oAuthParams = $oAuthParams ? $oAuthParams : $this->getOAuthBaseParams();
  186. // create baseString to encode for the sent parameters
  187. $baseString = $method . '&';
  188. $baseString .= $this->oauth_urlencode($uri) . "&";
  189. // OAuth header does not include GET-Parameters
  190. $signatureParams = array_merge($params, $oAuthParams);
  191. // sorting the parameters
  192. ksort($signatureParams);
  193. $encodedParams = array();
  194. foreach ($signatureParams as $key => $value) {
  195. if (!is_null($value)) $encodedParams[] = rawurlencode($key) . '=' . rawurlencode($value);
  196. }
  197. $baseString .= $this->oauth_urlencode(implode('&', $encodedParams));
  198. // encode the signature
  199. $tokens = $this->getToken();
  200. $hash = $this->hash_hmac_sha1($this->consumerSecret.'&'.$tokens['token_secret'], $baseString);
  201. $signature = base64_encode($hash);
  202. // add signature to oAuthParams
  203. $oAuthParams['oauth_signature'] = $signature;
  204. $oAuthEncoded = array();
  205. foreach ($oAuthParams as $key => $value) {
  206. $oAuthEncoded[] = $key . '="' . $this->oauth_urlencode($value) . '"';
  207. }
  208. return array('Authorization' => 'OAuth ' . implode(', ', $oAuthEncoded));
  209. }
  210. /**
  211. * Requests the OAuth request token.
  212. *
  213. * @return void
  214. */
  215. public function getRequestToken() {
  216. $result = $this->fetch(self::URI_REQUEST_TOKEN, array(), 'POST');
  217. if ($result['httpStatus'] == "200") {
  218. $tokens = array();
  219. parse_str($result['body'], $tokens);
  220. $this->setToken($tokens['oauth_token'], $tokens['oauth_token_secret']);
  221. return $this->getToken();
  222. } else {
  223. throw new Dropbox_Exception_RequestToken('We were unable to fetch request tokens. This likely means that your consumer key and/or secret are incorrect.');
  224. }
  225. }
  226. /**
  227. * Requests the OAuth access tokens.
  228. *
  229. * This method requires the 'unauthorized' request tokens
  230. * and, if successful will set the authorized request tokens.
  231. *
  232. * @return void
  233. */
  234. public function getAccessToken() {
  235. $result = $this->fetch(self::URI_ACCESS_TOKEN, array(), 'POST');
  236. if ($result['httpStatus'] == "200") {
  237. $tokens = array();
  238. parse_str($result['body'], $tokens);
  239. $this->setToken($tokens['oauth_token'], $tokens['oauth_token_secret']);
  240. return $this->getToken();
  241. } else {
  242. throw new Dropbox_Exception_RequestToken('We were unable to fetch request tokens. This likely means that your consumer key and/or secret are incorrect.');
  243. }
  244. }
  245. /**
  246. * Helper function to properly urlencode parameters.
  247. * See http://php.net/manual/en/function.oauth-urlencode.php
  248. *
  249. * @param string $string
  250. * @return string
  251. */
  252. private function oauth_urlencode($string) {
  253. return str_replace('%E7', '~', rawurlencode($string));
  254. }
  255. /**
  256. * Hash function for hmac_sha1; uses native function if available.
  257. *
  258. * @param string $key
  259. * @param string $data
  260. * @return string
  261. */
  262. private function hash_hmac_sha1($key, $data) {
  263. if (function_exists('hash_hmac') && in_array('sha1', hash_algos())) {
  264. return hash_hmac('sha1', $data, $key, true);
  265. } else {
  266. $blocksize = 64;
  267. $hashfunc = 'sha1';
  268. if (strlen($key) > $blocksize) {
  269. $key = pack('H*', $hashfunc($key));
  270. }
  271. $key = str_pad($key, $blocksize, chr(0x00));
  272. $ipad = str_repeat(chr(0x36), $blocksize);
  273. $opad = str_repeat(chr(0x5c), $blocksize);
  274. $hash = pack('H*', $hashfunc(( $key ^ $opad ) . pack('H*', $hashfunc(($key ^ $ipad) . $data))));
  275. return $hash;
  276. }
  277. }
  278. }