PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/ltiprovider/src/OAuth/OAuthRequest.php

https://gitlab.com/unofficial-mirrors/moodle
PHP | 290 lines | 165 code | 62 blank | 63 comment | 32 complexity | 8be6087b1b149f97f32e51f1a020ff1d MD5 | raw file
  1. <?php
  2. namespace IMSGlobal\LTI\OAuth;
  3. /**
  4. * Class to represent an %OAuth Request
  5. *
  6. * @copyright Andy Smith
  7. * @version 2008-08-04
  8. * @license https://opensource.org/licenses/MIT The MIT License
  9. */
  10. class OAuthRequest {
  11. protected $parameters;
  12. protected $http_method;
  13. protected $http_url;
  14. // for debug purposes
  15. public $base_string;
  16. public static $version = '1.0';
  17. public static $POST_INPUT = 'php://input';
  18. function __construct($http_method, $http_url, $parameters = null) {
  19. $parameters = ($parameters) ? $parameters : array();
  20. $parameters = array_merge( OAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters);
  21. $this->parameters = $parameters;
  22. $this->http_method = $http_method;
  23. $this->http_url = $http_url;
  24. }
  25. /**
  26. * attempt to build up a request from what was passed to the server
  27. */
  28. public static function from_request($http_method = null, $http_url = null, $parameters = null) {
  29. $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on")
  30. ? 'http'
  31. : 'https';
  32. $http_url = ($http_url) ? $http_url : $scheme .
  33. '://' . $_SERVER['SERVER_NAME'] .
  34. ':' .
  35. $_SERVER['SERVER_PORT'] .
  36. $_SERVER['REQUEST_URI'];
  37. $http_method = ($http_method) ? $http_method : $_SERVER['REQUEST_METHOD'];
  38. // We weren't handed any parameters, so let's find the ones relevant to
  39. // this request.
  40. // If you run XML-RPC or similar you should use this to provide your own
  41. // parsed parameter-list
  42. if (!$parameters) {
  43. // Find request headers
  44. $request_headers = OAuthUtil::get_headers();
  45. // Parse the query-string to find GET parameters
  46. if (isset($_SERVER['QUERY_STRING'])) {
  47. $parameters = OAuthUtil::parse_parameters($_SERVER['QUERY_STRING']);
  48. } else {
  49. $parameters = array();
  50. }
  51. // It's a POST request of the proper content-type, so parse POST
  52. // parameters and add those overriding any duplicates from GET
  53. if ($http_method == "POST"
  54. && isset($request_headers['Content-Type'])
  55. && strstr($request_headers['Content-Type'], 'application/x-www-form-urlencoded')) {
  56. $post_data = OAuthUtil::parse_parameters(file_get_contents(self::$POST_INPUT));
  57. $parameters = array_merge($parameters, $post_data);
  58. }
  59. // We have a Authorization-header with OAuth data. Parse the header
  60. // and add those overriding any duplicates from GET or POST
  61. if (isset($request_headers['Authorization']) && substr($request_headers['Authorization'], 0, 6) == 'OAuth ') {
  62. $header_parameters = OAuthUtil::split_header($request_headers['Authorization']);
  63. $parameters = array_merge($parameters, $header_parameters);
  64. }
  65. }
  66. return new OAuthRequest($http_method, $http_url, $parameters);
  67. }
  68. /**
  69. * pretty much a helper function to set up the request
  70. */
  71. public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters = null) {
  72. $parameters = ($parameters) ? $parameters : array();
  73. $defaults = array('oauth_version' => OAuthRequest::$version,
  74. 'oauth_nonce' => OAuthRequest::generate_nonce(),
  75. 'oauth_timestamp' => OAuthRequest::generate_timestamp(),
  76. 'oauth_consumer_key' => $consumer->key);
  77. if ($token)
  78. $defaults['oauth_token'] = $token->key;
  79. $parameters = array_merge($defaults, $parameters);
  80. return new OAuthRequest($http_method, $http_url, $parameters);
  81. }
  82. public function set_parameter($name, $value, $allow_duplicates = true) {
  83. if ($allow_duplicates && isset($this->parameters[$name])) {
  84. // We have already added parameter(s) with this name, so add to the list
  85. if (is_scalar($this->parameters[$name])) {
  86. // This is the first duplicate, so transform scalar (string)
  87. // into an array so we can add the duplicates
  88. $this->parameters[$name] = array($this->parameters[$name]);
  89. }
  90. $this->parameters[$name][] = $value;
  91. } else {
  92. $this->parameters[$name] = $value;
  93. }
  94. }
  95. public function get_parameter($name) {
  96. return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
  97. }
  98. public function get_parameters() {
  99. return $this->parameters;
  100. }
  101. public function unset_parameter($name) {
  102. unset($this->parameters[$name]);
  103. }
  104. /**
  105. * The request parameters, sorted and concatenated into a normalized string.
  106. * @return string
  107. */
  108. public function get_signable_parameters() {
  109. // Grab all parameters
  110. $params = $this->parameters;
  111. // Remove oauth_signature if present
  112. // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.")
  113. if (isset($params['oauth_signature'])) {
  114. unset($params['oauth_signature']);
  115. }
  116. return OAuthUtil::build_http_query($params);
  117. }
  118. /**
  119. * Returns the base string of this request
  120. *
  121. * The base string defined as the method, the url
  122. * and the parameters (normalized), each urlencoded
  123. * and the concated with &.
  124. */
  125. public function get_signature_base_string() {
  126. $parts = array(
  127. $this->get_normalized_http_method(),
  128. $this->get_normalized_http_url(),
  129. $this->get_signable_parameters()
  130. );
  131. $parts = OAuthUtil::urlencode_rfc3986($parts);
  132. return implode('&', $parts);
  133. }
  134. /**
  135. * just uppercases the http method
  136. */
  137. public function get_normalized_http_method() {
  138. return strtoupper($this->http_method);
  139. }
  140. /**
  141. * parses the url and rebuilds it to be
  142. * scheme://host/path
  143. */
  144. public function get_normalized_http_url() {
  145. $parts = parse_url($this->http_url);
  146. $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http';
  147. $port = (isset($parts['port'])) ? $parts['port'] : (($scheme == 'https') ? '443' : '80');
  148. $host = (isset($parts['host'])) ? strtolower($parts['host']) : '';
  149. $path = (isset($parts['path'])) ? $parts['path'] : '';
  150. if (($scheme == 'https' && $port != '443')
  151. || ($scheme == 'http' && $port != '80')) {
  152. $host = "$host:$port";
  153. }
  154. return "$scheme://$host$path";
  155. }
  156. /**
  157. * builds a url usable for a GET request
  158. */
  159. public function to_url() {
  160. $post_data = $this->to_postdata();
  161. $out = $this->get_normalized_http_url();
  162. if ($post_data) {
  163. $out .= '?'.$post_data;
  164. }
  165. return $out;
  166. }
  167. /**
  168. * builds the data one would send in a POST request
  169. */
  170. public function to_postdata() {
  171. return OAuthUtil::build_http_query($this->parameters);
  172. }
  173. /**
  174. * builds the Authorization: header
  175. */
  176. public function to_header($realm = null) {
  177. $first = true;
  178. if($realm) {
  179. $out = 'Authorization: OAuth realm="' . OAuthUtil::urlencode_rfc3986($realm) . '"';
  180. $first = false;
  181. } else
  182. $out = 'Authorization: OAuth';
  183. $total = array();
  184. foreach ($this->parameters as $k => $v) {
  185. if (substr($k, 0, 5) != "oauth") continue;
  186. if (is_array($v)) {
  187. throw new OAuthException('Arrays not supported in headers');
  188. }
  189. $out .= ($first) ? ' ' : ',';
  190. $out .= OAuthUtil::urlencode_rfc3986($k) .
  191. '="' .
  192. OAuthUtil::urlencode_rfc3986($v) .
  193. '"';
  194. $first = false;
  195. }
  196. return $out;
  197. }
  198. public function __toString() {
  199. return $this->to_url();
  200. }
  201. public function sign_request($signature_method, $consumer, $token) {
  202. $this->set_parameter(
  203. "oauth_signature_method",
  204. $signature_method->get_name(),
  205. false
  206. );
  207. $signature = $this->build_signature($signature_method, $consumer, $token);
  208. $this->set_parameter("oauth_signature", $signature, false);
  209. }
  210. public function build_signature($signature_method, $consumer, $token) {
  211. $signature = $signature_method->build_signature($this, $consumer, $token);
  212. return $signature;
  213. }
  214. /**
  215. * util function: current timestamp
  216. */
  217. private static function generate_timestamp() {
  218. return time();
  219. }
  220. /**
  221. * util function: current nonce
  222. */
  223. private static function generate_nonce() {
  224. $mt = microtime();
  225. $rand = mt_rand();
  226. return md5($mt . $rand); // md5s look nicer than numbers
  227. }
  228. }