PluginProbe
Gianism / 1.1
Gianism v1.1
4.3.0 4.3.1 4.3.2 4.3.3 4.3.4 4.4.0 5.0.0 5.0.1 5.0.2 5.1.0 5.2.1 5.2.2 5.3.0 6.0.0 6.0.1 trunk 1.0 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 All 65 releases
gianism / sdks / google / external / OAuth.php

OAuth.php in Gianism 1.1, at sdks/google/external/OAuth.php

487 lines 14.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /* Generic exception class
4 */
5 class apiClientOAuthException extends Exception {
6 // pass
7 }
8
9 class apiClientOAuthConsumer {
10 public $key;
11 public $secret;
12
13 public function __construct($key, $secret, $callback_url=NULL) {
14 $this->key = $key;
15 $this->secret = $secret;
16 $this->callback_url = $callback_url;
17 }
18 }
19
20 class apiClientOAuthToken {
21 // access tokens and request tokens
22 public $key;
23 public $secret;
24
25 /**
26 * key = the token
27 * secret = the token secret
28 */
29 function __construct($key, $secret) {
30 $this->key = $key;
31 $this->secret = $secret;
32 }
33
34 /**
35 * generates the basic string serialization of a token that a server
36 * would respond to request_token and access_token calls with
37 */
38 function to_string() {
39 return "oauth_token=" . apiClientOAuthUtil::urlencodeRFC3986($this->key) .
40 "&oauth_token_secret=" . apiClientOAuthUtil::urlencodeRFC3986($this->secret);
41 }
42
43 function __toString() {
44 return $this->to_string();
45 }
46 }
47
48 class apiClientOAuthSignatureMethod {
49 public function check_signature(&$request, $consumer, $token, $signature) {
50 $built = $this->build_signature($request, $consumer, $token);
51 return $built == $signature;
52 }
53 }
54
55 class apiClientOAuthSignatureMethod_HMAC_SHA1 extends apiClientOAuthSignatureMethod {
56 function get_name() {
57 return "HMAC-SHA1";
58 }
59
60 public function build_signature($request, $consumer, $token, $privKey=NULL) {
61 $base_string = $request->get_signature_base_string();
62 $request->base_string = $base_string;
63
64 $key_parts = array(
65 $consumer->secret,
66 ($token) ? $token->secret : ""
67 );
68
69 $key_parts = array_map(array('apiClientOAuthUtil','urlencodeRFC3986'), $key_parts);
70 $key = implode('&', $key_parts);
71
72 return base64_encode( hash_hmac('sha1', $base_string, $key, true));
73 }
74 }
75
76 class apiClientOAuthSignatureMethod_RSA_SHA1 extends apiClientOAuthSignatureMethod {
77 public function get_name() {
78 return "RSA-SHA1";
79 }
80
81 protected function fetch_public_cert(&$request) {
82 // not implemented yet, ideas are:
83 // (1) do a lookup in a table of trusted certs keyed off of consumer
84 // (2) fetch via http using a url provided by the requester
85 // (3) some sort of specific discovery code based on request
86 //
87 // either way should return a string representation of the certificate
88 throw Exception("fetch_public_cert not implemented");
89 }
90
91 protected function fetch_private_cert($privKey) {//&$request) {
92 // not implemented yet, ideas are:
93 // (1) do a lookup in a table of trusted certs keyed off of consumer
94 //
95 // either way should return a string representation of the certificate
96 throw Exception("fetch_private_cert not implemented");
97 }
98
99 public function build_signature(&$request, $consumer, $token, $privKey) {
100 $base_string = $request->get_signature_base_string();
101
102 // Fetch the private key cert based on the request
103 //$cert = $this->fetch_private_cert($consumer->privKey);
104
105 //Pull the private key ID from the certificate
106 //$privatekeyid = openssl_get_privatekey($cert);
107
108 // hacked in
109 if ($privKey == '') {
110 $fp = fopen($GLOBALS['PRIV_KEY_FILE'], "r");
111 $privKey = fread($fp, 8192);
112 fclose($fp);
113 }
114 $privatekeyid = openssl_get_privatekey($privKey);
115
116 //Check the computer signature against the one passed in the query
117 $ok = openssl_sign($base_string, $signature, $privatekeyid);
118
119 //Release the key resource
120 openssl_free_key($privatekeyid);
121
122 return base64_encode($signature);
123 }
124
125 public function check_signature(&$request, $consumer, $token, $signature) {
126 $decoded_sig = base64_decode($signature);
127
128 $base_string = $request->get_signature_base_string();
129
130 // Fetch the public key cert based on the request
131 $cert = $this->fetch_public_cert($request);
132
133 //Pull the public key ID from the certificate
134 $publickeyid = openssl_get_publickey($cert);
135
136 //Check the computer signature against the one passed in the query
137 $ok = openssl_verify($base_string, $decoded_sig, $publickeyid);
138
139 //Release the key resource
140 openssl_free_key($publickeyid);
141
142 return $ok == 1;
143 }
144 }
145
146 class apiClientOAuthRequest {
147 private $parameters;
148 private $http_method;
149 private $http_url;
150 // for debug purposes
151 public $base_string;
152 public static $version = '1.0';
153
154 function __construct($http_method, $http_url, $parameters=NULL) {
155 @$parameters or $parameters = array();
156 $this->parameters = $parameters;
157 $this->http_method = $http_method;
158 $this->http_url = $http_url;
159 }
160
161
162 /**
163 * attempt to build up a request from what was passed to the server
164 */
165 public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) {
166 $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") ? 'http' : 'https';
167 @$http_url or $http_url = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
168 @$http_method or $http_method = $_SERVER['REQUEST_METHOD'];
169
170 $request_headers = apiClientOAuthRequest::get_headers();
171
172 // let the library user override things however they'd like, if they know
173 // which parameters to use then go for it, for example XMLRPC might want to
174 // do this
175 if ($parameters) {
176 $req = new apiClientOAuthRequest($http_method, $http_url, $parameters);
177 }
178 // next check for the auth header, we need to do some extra stuff
179 // if that is the case, namely suck in the parameters from GET or POST
180 // so that we can include them in the signature
181 else if (@substr($request_headers['Authorization'], 0, 5) == "OAuth") {
182 $header_parameters = apiClientOAuthRequest::split_header($request_headers['Authorization']);
183 if ($http_method == "GET") {
184 $req_parameters = $_GET;
185 }
186 else if ($http_method = "POST") {
187 $req_parameters = $_POST;
188 }
189 $parameters = array_merge($header_parameters, $req_parameters);
190 $req = new apiClientOAuthRequest($http_method, $http_url, $parameters);
191 }
192 else if ($http_method == "GET") {
193 $req = new apiClientOAuthRequest($http_method, $http_url, $_GET);
194 }
195 else if ($http_method == "POST") {
196 $req = new apiClientOAuthRequest($http_method, $http_url, $_POST);
197 }
198 return $req;
199 }
200
201 /**
202 * pretty much a helper function to set up the request
203 */
204 public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) {
205 @$parameters or $parameters = array();
206 $defaults = array("oauth_version" => apiClientOAuthRequest::$version,
207 "oauth_nonce" => apiClientOAuthRequest::generate_nonce(),
208 "oauth_timestamp" => apiClientOAuthRequest::generate_timestamp(),
209 "oauth_consumer_key" => $consumer->key);
210 $parameters = array_merge($defaults, $parameters);
211
212 if ($token) {
213 $parameters['oauth_token'] = $token->key;
214 }
215
216 // oauth v1.0a
217 /*if (isset($_REQUEST['oauth_verifier'])) {
218 $parameters['oauth_verifier'] = $_REQUEST['oauth_verifier'];
219 }*/
220
221
222 return new apiClientOAuthRequest($http_method, $http_url, $parameters);
223 }
224
225 public function set_parameter($name, $value) {
226 $this->parameters[$name] = $value;
227 }
228
229 public function get_parameter($name) {
230 return $this->parameters[$name];
231 }
232
233 public function get_parameters() {
234 return $this->parameters;
235 }
236
237 /**
238 * Returns the normalized parameters of the request
239 *
240 * This will be all (except oauth_signature) parameters,
241 * sorted first by key, and if duplicate keys, then by
242 * value.
243 *
244 * The returned string will be all the key=value pairs
245 * concated by &.
246 *
247 * @return string
248 */
249 public function get_signable_parameters() {
250 // Grab all parameters
251 $params = $this->parameters;
252
253 // Remove oauth_signature if present
254 if (isset($params['oauth_signature'])) {
255 unset($params['oauth_signature']);
256 }
257
258 // Urlencode both keys and values
259 $keys = array_map(array('apiClientOAuthUtil', 'urlencodeRFC3986'), array_keys($params));
260 $values = array_map(array('apiClientOAuthUtil', 'urlencodeRFC3986'), array_values($params));
261 $params = array_combine($keys, $values);
262
263 // Sort by keys (natsort)
264 uksort($params, 'strnatcmp');
265
266 if(isset($params['title']) && isset($params['title-exact'])) {
267 $temp = $params['title-exact'];
268 $title = $params['title'];
269
270 unset($params['title']);
271 unset($params['title-exact']);
272
273 $params['title-exact'] = $temp;
274 $params['title'] = $title;
275 }
276
277 // Generate key=value pairs
278 $pairs = array();
279 foreach ($params as $key=>$value ) {
280 if (is_array($value)) {
281 // If the value is an array, it's because there are multiple
282 // with the same key, sort them, then add all the pairs
283 natsort($value);
284 foreach ($value as $v2) {
285 $pairs[] = $key . '=' . $v2;
286 }
287 } else {
288 $pairs[] = $key . '=' . $value;
289 }
290 }
291
292 // Return the pairs, concated with &
293 return implode('&', $pairs);
294 }
295
296 /**
297 * Returns the base string of this request
298 *
299 * The base string defined as the method, the url
300 * and the parameters (normalized), each urlencoded
301 * and the concated with &.
302 */
303 public function get_signature_base_string() {
304 $parts = array(
305 $this->get_normalized_http_method(),
306 $this->get_normalized_http_url(),
307 $this->get_signable_parameters()
308 );
309
310 $parts = array_map(array('apiClientOAuthUtil', 'urlencodeRFC3986'), $parts);
311
312 return implode('&', $parts);
313 }
314
315 /**
316 * just uppercases the http method
317 */
318 public function get_normalized_http_method() {
319 return strtoupper($this->http_method);
320 }
321
322 /**
323 * parses the url and rebuilds it to be
324 * scheme://host/path
325 */
326 public function get_normalized_http_url() {
327 $parts = parse_url($this->http_url);
328
329 // FIXME: port should handle according to http://groups.google.com/group/oauth/browse_thread/thread/1b203a51d9590226
330 $port = (isset($parts['port']) && $parts['port'] != '80') ? ':' . $parts['port'] : '';
331 $path = (isset($parts['path'])) ? $parts['path'] : '';
332
333 return $parts['scheme'] . '://' . $parts['host'] . $port . $path;
334 }
335
336 /**
337 * builds a url usable for a GET request
338 */
339 public function to_url() {
340 $out = $this->get_normalized_http_url() . "?";
341 $out .= $this->to_postdata();
342 return $out;
343 }
344
345 /**
346 * builds the data one would send in a POST request
347 */
348 public function to_postdata() {
349 $total = array();
350 foreach ($this->parameters as $k => $v) {
351 $total[] = apiClientOAuthUtil::urlencodeRFC3986($k) . "=" . apiClientOAuthUtil::urlencodeRFC3986($v);
352 }
353 $out = implode("&", $total);
354 return $out;
355 }
356
357 /**
358 * builds the Authorization: header
359 */
360 public function to_header() {
361 $out ='Authorization: OAuth ';
362 $total = array();
363 foreach ($this->parameters as $k => $v) {
364 if (substr($k, 0, 5) != "oauth") continue;
365 $out .= apiClientOAuthUtil::urlencodeRFC3986($k) . '="' . apiClientOAuthUtil::urlencodeRFC3986($v) . '", ';
366 }
367 $out = substr_replace($out, '', strlen($out) - 2);
368 return $out;
369 }
370
371 public function __toString() {
372 return $this->to_url();
373 }
374
375
376 public function sign_request($signature_method, $consumer, $token, $privKey=NULL) {
377 $this->set_parameter("oauth_signature_method", $signature_method->get_name());
378 $signature = $this->build_signature($signature_method, $consumer, $token, $privKey);
379 $this->set_parameter("oauth_signature", $signature);
380 }
381
382 public function build_signature($signature_method, $consumer, $token, $privKey=NULL) {
383 $signature = $signature_method->build_signature($this, $consumer, $token, $privKey);
384 return $signature;
385 }
386
387 /**
388 * util function: current timestamp
389 */
390 private static function generate_timestamp() {
391 return time();
392 }
393
394 /**
395 * util function: current nonce
396 */
397 private static function generate_nonce() {
398 $mt = microtime();
399 $rand = mt_rand();
400
401 return md5($mt . $rand); // md5s look nicer than numbers
402 }
403
404 /**
405 * util function for turning the Authorization: header into
406 * parameters, has to do some unescaping
407 */
408 private static function split_header($header) {
409 // this should be a regex
410 // error cases: commas in parameter values
411 $parts = explode(",", $header);
412 $out = array();
413 foreach ($parts as $param) {
414 $param = ltrim($param);
415 // skip the "realm" param, nobody ever uses it anyway
416 if (substr($param, 0, 5) != "oauth") continue;
417
418 $param_parts = explode("=", $param);
419
420 // rawurldecode() used because urldecode() will turn a "+" in the
421 // value into a space
422 $out[$param_parts[0]] = rawurldecode(substr($param_parts[1], 1, -1));
423 }
424 return $out;
425 }
426
427 /**
428 * helper to try to sort out headers for people who aren't running apache
429 */
430 private static function get_headers() {
431 if (function_exists('apache_request_headers')) {
432 // we need this to get the actual Authorization: header
433 // because apache tends to tell us it doesn't exist
434 return apache_request_headers();
435 }
436 // otherwise we don't have apache and are just going to have to hope
437 // that $_SERVER actually contains what we need
438 $out = array();
439 foreach ($_SERVER as $key => $value) {
440 if (substr($key, 0, 5) == "HTTP_") {
441 // this is chaos, basically it is just there to capitalize the first
442 // letter of every word that is not an initial HTTP and strip HTTP
443 // code from przemek
444 $key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))));
445 $out[$key] = $value;
446 }
447 }
448 return $out;
449 }
450 }
451
452 class apiClientOAuthDataStore {
453 function lookup_consumer($consumer_key) {
454 // implement me
455 }
456
457 function lookup_token($consumer, $token_type, $token) {
458 // implement me
459 }
460
461 function lookup_nonce($consumer, $token, $nonce, $timestamp) {
462 // implement me
463 }
464
465 function fetch_request_token($consumer) {
466 // return a new token attached to this consumer
467 }
468
469 function fetch_access_token($token, $consumer) {
470 // return a new access token attached to this consumer
471 // for the user associated with this token if the request token
472 // is authorized
473 // should also invalidate the request token
474 }
475
476 }
477
478 class apiClientOAuthUtil {
479 public static function urlencodeRFC3986($string) {
480 return str_replace('%7E', '~', rawurlencode($string));
481 }
482
483 public static function urldecodeRFC3986($string) {
484 return rawurldecode($string);
485 }
486 }
487