1 |
efrain |
1 |
<?php
|
|
|
2 |
|
|
|
3 |
namespace IMSGlobal\LTI\OAuth;
|
|
|
4 |
|
|
|
5 |
/**
|
|
|
6 |
* Class to provide %OAuth utility methods
|
|
|
7 |
*
|
|
|
8 |
* @copyright Andy Smith
|
|
|
9 |
* @version 2008-08-04
|
|
|
10 |
* @license https://opensource.org/licenses/MIT The MIT License
|
|
|
11 |
*/
|
|
|
12 |
#[\AllowDynamicProperties]
|
|
|
13 |
class OAuthUtil {
|
|
|
14 |
|
|
|
15 |
public static function urlencode_rfc3986($input) {
|
|
|
16 |
|
|
|
17 |
if (is_array($input)) {
|
|
|
18 |
return array_map(array('IMSGlobal\LTI\OAuth\OAuthUtil', 'urlencode_rfc3986'), $input);
|
|
|
19 |
} else if (is_scalar($input)) {
|
|
|
20 |
return str_replace('+', ' ', str_replace('%7E', '~', rawurlencode($input)));
|
|
|
21 |
} else {
|
|
|
22 |
return '';
|
|
|
23 |
}
|
|
|
24 |
}
|
|
|
25 |
|
|
|
26 |
// This decode function isn't taking into consideration the above
|
|
|
27 |
// modifications to the encoding process. However, this method doesn't
|
|
|
28 |
// seem to be used anywhere so leaving it as is.
|
|
|
29 |
public static function urldecode_rfc3986($string) {
|
|
|
30 |
return urldecode($string);
|
|
|
31 |
}
|
|
|
32 |
|
|
|
33 |
// Utility function for turning the Authorization: header into
|
|
|
34 |
// parameters, has to do some unescaping
|
|
|
35 |
// Can filter out any non-oauth parameters if needed (default behaviour)
|
|
|
36 |
// May 28th, 2010 - method updated to tjerk.meesters for a speed improvement.
|
|
|
37 |
// see http://code.google.com/p/oauth/issues/detail?id=163
|
|
|
38 |
public static function split_header($header, $only_allow_oauth_parameters = true) {
|
|
|
39 |
|
|
|
40 |
$params = array();
|
|
|
41 |
if (preg_match_all('/('.($only_allow_oauth_parameters ? 'oauth_' : '').'[a-z_-]*)=(:?"([^"]*)"|([^,]*))/', $header, $matches)) {
|
|
|
42 |
foreach ($matches[1] as $i => $h) {
|
|
|
43 |
$params[$h] = OAuthUtil::urldecode_rfc3986(empty($matches[3][$i]) ? $matches[4][$i] : $matches[3][$i]);
|
|
|
44 |
}
|
|
|
45 |
if (isset($params['realm'])) {
|
|
|
46 |
unset($params['realm']);
|
|
|
47 |
}
|
|
|
48 |
}
|
|
|
49 |
|
|
|
50 |
return $params;
|
|
|
51 |
|
|
|
52 |
}
|
|
|
53 |
|
|
|
54 |
// helper to try to sort out headers for people who aren't running apache
|
|
|
55 |
public static function get_headers() {
|
|
|
56 |
|
|
|
57 |
if (function_exists('apache_request_headers')) {
|
|
|
58 |
// we need this to get the actual Authorization: header
|
|
|
59 |
// because apache tends to tell us it doesn't exist
|
|
|
60 |
$headers = apache_request_headers();
|
|
|
61 |
|
|
|
62 |
// sanitize the output of apache_request_headers because
|
|
|
63 |
// we always want the keys to be Cased-Like-This and arh()
|
|
|
64 |
// returns the headers in the same case as they are in the
|
|
|
65 |
// request
|
|
|
66 |
$out = array();
|
|
|
67 |
foreach ($headers AS $key => $value) {
|
|
|
68 |
$key = str_replace(" ", "-", ucwords(strtolower(str_replace("-", " ", $key))));
|
|
|
69 |
$out[$key] = $value;
|
|
|
70 |
}
|
|
|
71 |
} else {
|
|
|
72 |
// otherwise we don't have apache and are just going to have to hope
|
|
|
73 |
// that $_SERVER actually contains what we need
|
|
|
74 |
$out = array();
|
|
|
75 |
if( isset($_SERVER['CONTENT_TYPE']) )
|
|
|
76 |
$out['Content-Type'] = $_SERVER['CONTENT_TYPE'];
|
|
|
77 |
if( isset($_ENV['CONTENT_TYPE']) )
|
|
|
78 |
$out['Content-Type'] = $_ENV['CONTENT_TYPE'];
|
|
|
79 |
|
|
|
80 |
foreach ($_SERVER as $key => $value) {
|
|
|
81 |
if (substr($key, 0, 5) == 'HTTP_') {
|
|
|
82 |
// this is chaos, basically it is just there to capitalize the first
|
|
|
83 |
// letter of every word that is not an initial HTTP and strip HTTP
|
|
|
84 |
// code from przemek
|
|
|
85 |
$key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($key, 5)))));
|
|
|
86 |
$out[$key] = $value;
|
|
|
87 |
}
|
|
|
88 |
}
|
|
|
89 |
}
|
|
|
90 |
return $out;
|
|
|
91 |
}
|
|
|
92 |
|
|
|
93 |
// This function takes a input like a=b&a=c&d=e and returns the parsed
|
|
|
94 |
// parameters like this
|
|
|
95 |
// array('a' => array('b','c'), 'd' => 'e')
|
|
|
96 |
public static function parse_parameters( $input ) {
|
|
|
97 |
|
|
|
98 |
if (!isset($input) || !$input) return array();
|
|
|
99 |
|
|
|
100 |
$pairs = explode('&', $input);
|
|
|
101 |
|
|
|
102 |
$parsed_parameters = array();
|
|
|
103 |
foreach ($pairs as $pair) {
|
|
|
104 |
$split = explode('=', $pair, 2);
|
|
|
105 |
$parameter = self::urldecode_rfc3986($split[0]);
|
|
|
106 |
$value = isset($split[1]) ? self::urldecode_rfc3986($split[1]) : '';
|
|
|
107 |
|
|
|
108 |
if (isset($parsed_parameters[$parameter])) {
|
|
|
109 |
// We have already recieved parameter(s) with this name, so add to the list
|
|
|
110 |
// of parameters with this name
|
|
|
111 |
|
|
|
112 |
if (is_scalar($parsed_parameters[$parameter])) {
|
|
|
113 |
// This is the first duplicate, so transform scalar (string) into an array
|
|
|
114 |
// so we can add the duplicates
|
|
|
115 |
$parsed_parameters[$parameter] = array($parsed_parameters[$parameter]);
|
|
|
116 |
}
|
|
|
117 |
|
|
|
118 |
$parsed_parameters[$parameter][] = $value;
|
|
|
119 |
} else {
|
|
|
120 |
$parsed_parameters[$parameter] = $value;
|
|
|
121 |
}
|
|
|
122 |
}
|
|
|
123 |
|
|
|
124 |
return $parsed_parameters;
|
|
|
125 |
|
|
|
126 |
}
|
|
|
127 |
|
|
|
128 |
public static function build_http_query($params) {
|
|
|
129 |
|
|
|
130 |
if (!$params) return '';
|
|
|
131 |
|
|
|
132 |
// Urlencode both keys and values
|
|
|
133 |
$keys = OAuthUtil::urlencode_rfc3986(array_keys($params));
|
|
|
134 |
$values = OAuthUtil::urlencode_rfc3986(array_values($params));
|
|
|
135 |
$params = array_combine($keys, $values);
|
|
|
136 |
|
|
|
137 |
// Parameters are sorted by name, using lexicographical byte value ordering.
|
|
|
138 |
// Ref: Spec: 9.1.1 (1)
|
|
|
139 |
uksort($params, 'strcmp');
|
|
|
140 |
|
|
|
141 |
$pairs = array();
|
|
|
142 |
foreach ($params as $parameter => $value) {
|
|
|
143 |
if (is_array($value)) {
|
|
|
144 |
// If two or more parameters share the same name, they are sorted by their value
|
|
|
145 |
// Ref: Spec: 9.1.1 (1)
|
|
|
146 |
// June 12th, 2010 - changed to sort because of issue 164 by hidetaka
|
|
|
147 |
sort($value, SORT_STRING);
|
|
|
148 |
foreach ($value as $duplicate_value) {
|
|
|
149 |
$pairs[] = $parameter . '=' . $duplicate_value;
|
|
|
150 |
}
|
|
|
151 |
} else {
|
|
|
152 |
$pairs[] = $parameter . '=' . $value;
|
|
|
153 |
}
|
|
|
154 |
}
|
|
|
155 |
|
|
|
156 |
// For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61)
|
|
|
157 |
// Each name-value pair is separated by an '&' character (ASCII code 38)
|
|
|
158 |
return implode('&', $pairs);
|
|
|
159 |
|
|
|
160 |
}
|
|
|
161 |
|
|
|
162 |
}
|