You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by ch...@apache.org on 2008/07/16 01:33:51 UTC
svn commit: r677097 -
/incubator/shindig/trunk/php/src/gadgets/oauth/OAuth.php
Author: chabotc
Date: Tue Jul 15 16:33:51 2008
New Revision: 677097
URL: http://svn.apache.org/viewvc?rev=677097&view=rev
Log:
Get signed oauth requests working & remove partuza hack, better patch incomming (we hope)
Modified:
incubator/shindig/trunk/php/src/gadgets/oauth/OAuth.php
Modified: incubator/shindig/trunk/php/src/gadgets/oauth/OAuth.php
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/oauth/OAuth.php?rev=677097&r1=677096&r2=677097&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/oauth/OAuth.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/oauth/OAuth.php Tue Jul 15 16:33:51 2008
@@ -1,650 +1,652 @@
-<?php
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-class OAuth {
- public static $VERSION_1_0 = "1.0";
- public static $ENCODING = "UTF-8";
- public static $FORM_ENCODED = "application/x-www-form-urlencoded";
- public static $OAUTH_CONSUMER_KEY = "oauth_consumer_key";
- public static $OAUTH_TOKEN = "oauth_token";
- public static $OAUTH_TOKEN_SECRET = "oauth_token_secret";
- public static $OAUTH_SIGNATURE_METHOD = "oauth_signature_method";
- public static $OAUTH_SIGNATURE = "oauth_signature";
- public static $OAUTH_TIMESTAMP = "oauth_timestamp";
- public static $OAUTH_NONCE = "oauth_nonce";
- public static $OAUTH_VERSION = "oauth_version";
- public static $HMAC_SHA1 = "HMAC_SHA1";
- public static $RSA_SHA1 = "RSA_SHA1";
- public static $BEGIN_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----";
- public static $END_PRIVATE_KEY = "-----END PRIVATE KEY-----";
- public static $OAUTH_PROBLEM = "oauth_problem";
-}
-
-/* Generic exception class
- */
-class OAuthException extends Exception {}
-
-class OAuthProblemException extends Exception {}
-
-class OAuthProtocolException extends Exception {}
-
-class OAuthConsumer {
- public $key;
- public $secret;
- public $callback_url;
- private $properties = array();
-
- function __construct($key, $secret, $callback_url = NULL)
- {
- $this->key = $key;
- $this->secret = $secret;
- $this->callback_url = $callback_url;
- }
-
- public function getProperty($name)
- {
- return $this->properties[$name];
- }
-
- public function setProperty($name, $value)
- {
- $this->properties[$name] = $value;
- }
-
-}
-
-class OAuthToken {
- // access tokens and request tokens
- public $key;
- public $secret;
-
- /**
- * key = the token
- * secret = the token secret
- */
- function __construct($key, $secret)
- {
- $this->key = $key;
- $this->secret = $secret;
- }
-
- /**
- * generates the basic string serialization of a token that a server
- * would respond to request_token and access_token calls with
- */
- function to_string()
- {
- return "oauth_token=" . OAuthUtil::urlencodeRFC3986($this->key) . "&oauth_token_secret=" . OAuthUtil::urlencodeRFC3986($this->secret);
- }
-
- function __toString()
- {
- return $this->to_string();
- }
-}
-
-class OAuthSignatureMethod {
-
- public function check_signature(&$request, $consumer, $token, $signature)
- {
- $built = $this->build_signature($request, $consumer, $token);
- return $built == $signature;
- }
-}
-
-class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod {
-
- function get_name()
- {
- return "HMAC-SHA1";
- }
-
- public function build_signature($request, $consumer, $token)
- {
- $base_string = $request->get_signature_base_string();
- $request->base_string = $base_string;
- $key_parts = array($consumer->secret, (isset($token)) ? $token : "");
- $key_parts = array_map(array('OAuthUtil', 'urlencodeRFC3986'), $key_parts);
- $key = implode('&', $key_parts);
- return base64_encode(hash_hmac('sha1', $base_string, $key, true));
- }
-
- //TODO: Double check this!
- public function check_signature(&$request, $consumer, $token, $signature)
- {
- $sign = $this->build_signature($request, $consumer, $token);
- return $sign == $signature;
- }
-}
-
-class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod {
-
- public function get_name()
- {
- return "PLAINTEXT";
- }
-
- public function build_signature($request, $consumer, $token)
- {
- $sig = array(OAuthUtil::urlencodeRFC3986($consumer->secret));
- if ($token) {
- array_push($sig, OAuthUtil::urlencodeRFC3986($token->secret));
- } else {
- array_push($sig, '');
- }
- $raw = implode("&", $sig);
- // for debug purposes
- $request->base_string = $raw;
- return OAuthUtil::urlencodeRFC3986($raw);
- }
-
- //TODO: Double check this!
- public function check_signature(&$request, $consumer, $token, $signature)
- {
- $raw = OAuthUtil::urldecodeRFC3986($request->base_string);
- $sig = explode("&", $raw);
- array_pop($sig);
- $secret = array(OAuthUtil::urldecodeRFC3986($consumer->secret));
- return $sig == $secret;
- }
-}
-
-class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod {
- public static $PRIVATE_KEY = "RSA-SHA1.PrivateKey";
-
- public function get_name()
- {
- return "RSA-SHA1";
- }
-
- protected function fetch_public_cert(&$request)
- {
- // not implemented yet, ideas are:
- // (1) do a lookup in a table of trusted certs keyed off of consumer
- // (2) fetch via http using a url provided by the requester
- // (3) some sort of specific discovery code based on request
- //
- // either way should return a string representation of the certificate
- throw Exception("fetch_public_cert not implemented");
- }
-
- protected function fetch_private_cert(&$request)
- {
- // not implemented yet, ideas are:
- // (1) do a lookup in a table of trusted certs keyed off of consumer
- //
- // either way should return a string representation of the certificate
- throw new Exception("fetch_private_cert not implemented");
- }
-
- public function build_signature(&$request, OAuthConsumer $consumer, $token)
- {
- $base_string = $request->get_signature_base_string();
- // Fetch the private key cert based on the request
- $cert = $consumer->getProperty(OAuthSignatureMethod_RSA_SHA1::$PRIVATE_KEY);
- // Pull the private key ID from the certificate
- //FIXME this function seems to be called both for a oauth.json action where
- // there is no phrase required, but for signed requests too, which do require it
- // this is a dirty hack to make it work .. kinda
- if (! $privatekeyid = @openssl_pkey_get_private($cert)) {
- if (! $privatekeyid = @openssl_pkey_get_private($cert, Config::get('private_key_phrase') != '' ? (Config::get('private_key_phrase')) : null)) {
- throw new Exception("Could not load private key");
- }
- }
- // Sign using the key
- $signature = '';
- if (($ok = openssl_sign($base_string, $signature, $privatekeyid)) === false) {
- throw new OAuthException("Could not create signature");
- }
- // Release the key resource
- @openssl_free_key($privatekeyid);
- return base64_encode($signature);
- }
-
- public function check_signature(&$request, $consumer, $token, $signature)
- {
- $decoded_sig = base64_decode($signature);
- $base_string = $request->get_signature_base_string();
- // Fetch the public key cert based on the request
- $cert = $this->fetch_public_cert($request);
- // Pull the public key ID from the certificate
- $publickeyid = openssl_get_publickey($cert);
- // Check the computed signature against the one passed in the query
- $ok = openssl_verify($base_string, $decoded_sig, $publickeyid);
- // Release the key resource
- @openssl_free_key($publickeyid);
- return $ok == 1;
- }
-}
-
-class OAuthRequest {
- private $parameters;
- private $http_method;
- private $http_url;
- public $base_string;
- public static $version = '1.0';
-
- function __construct($http_method, $http_url, $parameters = NULL)
- {
- @$parameters or $parameters = array();
- $this->parameters = $parameters;
- $this->http_method = $http_method;
- $this->http_url = $http_url;
- }
-
- /**
- * attempt to build up a request from what was passed to the server
- */
- public static function from_request($http_method = NULL, $http_url = NULL, $parameters = NULL)
- {
- $scheme = (! isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") ? 'http' : 'https';
- @$http_url or $http_url = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
- @$http_method or $http_method = $_SERVER['REQUEST_METHOD'];
- $request_headers = OAuthRequest::get_headers();
- // let the library user override things however they'd like, if they know
- // which parameters to use then go for it, for example XMLRPC might want to
- // do this
- if ($parameters) {
- $req = new OAuthRequest($http_method, $http_url, $parameters);
- } elseif (@substr($request_headers['Authorization'], 0, 5) == "OAuth") {
- // next check for the auth header, we need to do some extra stuff
- // if that is the case, namely suck in the parameters from GET or POST
- // so that we can include them in the signature
- $header_parameters = OAuthRequest::split_header($request_headers['Authorization']);
- if ($http_method == "GET") {
- $req_parameters = $_GET;
- } else
- if ($http_method = "POST") {
- $req_parameters = $_POST;
- }
- $parameters = array_merge($header_parameters, $req_parameters);
- $req = new OAuthRequest($http_method, $http_url, $parameters);
- } elseif ($http_method == "GET") {
- $req = new OAuthRequest($http_method, $http_url, $_GET);
- } elseif ($http_method == "POST") {
- $req = new OAuthRequest($http_method, $http_url, $_POST);
- }
- return $req;
- }
-
- /**
- * pretty much a helper function to set up the request
- */
- public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters = NULL)
- {
- $parameters = is_array($parameters) ? $parameters : array();
- $defaults = array("oauth_nonce" => OAuthRequest::generate_nonce(),
- "oauth_timestamp" => OAuthRequest::generate_timestamp(),
- "oauth_consumer_key" => $consumer->key, 'synd' => 'partuza',
- 'container' => 'partuza');
- $parameters = array_merge($defaults, $parameters);
- if (isset($token)) {
- $parameters['oauth_token'] = $token;
- }
- return new OAuthRequest($http_method, $http_url, $parameters);
- }
-
- public function set_parameter($name, $value)
- {
- $this->parameters[$name] = $value;
- }
-
- public function get_parameter($name)
- {
- return @$this->parameters[$name];
- }
-
- public function get_parameters()
- {
- return $this->parameters;
- }
-
- public function set_parameters($params)
- {
- return $this->parameters = $params;
- }
-
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+class OAuth {
+ public static $VERSION_1_0 = "1.0";
+ public static $ENCODING = "UTF-8";
+ public static $FORM_ENCODED = "application/x-www-form-urlencoded";
+ public static $OAUTH_CONSUMER_KEY = "oauth_consumer_key";
+ public static $OAUTH_TOKEN = "oauth_token";
+ public static $OAUTH_TOKEN_SECRET = "oauth_token_secret";
+ public static $OAUTH_SIGNATURE_METHOD = "oauth_signature_method";
+ public static $OAUTH_SIGNATURE = "oauth_signature";
+ public static $OAUTH_TIMESTAMP = "oauth_timestamp";
+ public static $OAUTH_NONCE = "oauth_nonce";
+ public static $OAUTH_VERSION = "oauth_version";
+ public static $HMAC_SHA1 = "HMAC_SHA1";
+ public static $RSA_SHA1 = "RSA_SHA1";
+ public static $BEGIN_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----";
+ public static $END_PRIVATE_KEY = "-----END PRIVATE KEY-----";
+ public static $OAUTH_PROBLEM = "oauth_problem";
+}
+
+/* Generic exception class
+ */
+class OAuthException extends Exception {}
+
+class OAuthProblemException extends Exception {}
+
+class OAuthProtocolException extends Exception {}
+
+class OAuthConsumer {
+ public $key;
+ public $secret;
+ public $callback_url;
+ private $properties = array();
+
+ function __construct($key, $secret, $callback_url = NULL)
+ {
+ $this->key = $key;
+ $this->secret = $secret;
+ $this->callback_url = $callback_url;
+ }
+
+ public function getProperty($name)
+ {
+ return $this->properties[$name];
+ }
+
+ public function setProperty($name, $value)
+ {
+ $this->properties[$name] = $value;
+ }
+
+}
+
+class OAuthToken {
+ // access tokens and request tokens
+ public $key;
+ public $secret;
+
+ /**
+ * key = the token
+ * secret = the token secret
+ */
+ function __construct($key, $secret)
+ {
+ $this->key = $key;
+ $this->secret = $secret;
+ }
+
+ /**
+ * generates the basic string serialization of a token that a server
+ * would respond to request_token and access_token calls with
+ */
+ function to_string()
+ {
+ return "oauth_token=" . OAuthUtil::urlencodeRFC3986($this->key) . "&oauth_token_secret=" . OAuthUtil::urlencodeRFC3986($this->secret);
+ }
+
+ function __toString()
+ {
+ return $this->to_string();
+ }
+}
+
+class OAuthSignatureMethod {
+
+ public function check_signature(&$request, $consumer, $token, $signature)
+ {
+ $built = $this->build_signature($request, $consumer, $token);
+ return $built == $signature;
+ }
+}
+
+class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod {
+
+ function get_name()
+ {
+ return "HMAC-SHA1";
+ }
+
+ public function build_signature($request, $consumer, $token)
+ {
+ $base_string = $request->get_signature_base_string();
+ $request->base_string = $base_string;
+ $key_parts = array($consumer->secret, (isset($token)) ? $token : "");
+ $key_parts = array_map(array('OAuthUtil', 'urlencodeRFC3986'), $key_parts);
+ $key = implode('&', $key_parts);
+ return base64_encode(hash_hmac('sha1', $base_string, $key, true));
+ }
+
+ //TODO: Double check this!
+ public function check_signature(&$request, $consumer, $token, $signature)
+ {
+ $sign = $this->build_signature($request, $consumer, $token);
+ return $sign == $signature;
+ }
+}
+
+class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod {
+
+ public function get_name()
+ {
+ return "PLAINTEXT";
+ }
+
+ public function build_signature($request, $consumer, $token)
+ {
+ $sig = array(OAuthUtil::urlencodeRFC3986($consumer->secret));
+ if ($token) {
+ array_push($sig, OAuthUtil::urlencodeRFC3986($token->secret));
+ } else {
+ array_push($sig, '');
+ }
+ $raw = implode("&", $sig);
+ // for debug purposes
+ $request->base_string = $raw;
+ return OAuthUtil::urlencodeRFC3986($raw);
+ }
+
+ //TODO: Double check this!
+ public function check_signature(&$request, $consumer, $token, $signature)
+ {
+ $raw = OAuthUtil::urldecodeRFC3986($request->base_string);
+ $sig = explode("&", $raw);
+ array_pop($sig);
+ $secret = array(OAuthUtil::urldecodeRFC3986($consumer->secret));
+ return $sig == $secret;
+ }
+}
+
+class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod {
+ public static $PRIVATE_KEY = "RSA-SHA1.PrivateKey";
+
+ public function get_name()
+ {
+ return "RSA-SHA1";
+ }
+
+ protected function fetch_public_cert(&$request)
+ {
+ // not implemented yet, ideas are:
+ // (1) do a lookup in a table of trusted certs keyed off of consumer
+ // (2) fetch via http using a url provided by the requester
+ // (3) some sort of specific discovery code based on request
+ //
+ // either way should return a string representation of the certificate
+ throw Exception("fetch_public_cert not implemented");
+ }
+
+ protected function fetch_private_cert(&$request)
+ {
+ // not implemented yet, ideas are:
+ // (1) do a lookup in a table of trusted certs keyed off of consumer
+ //
+ // either way should return a string representation of the certificate
+ throw new Exception("fetch_private_cert not implemented");
+ }
+
+ public function build_signature(&$request, OAuthConsumer $consumer, $token)
+ {
+ $base_string = $request->get_signature_base_string();
+ // Fetch the private key cert based on the request
+ $cert = $consumer->getProperty(OAuthSignatureMethod_RSA_SHA1::$PRIVATE_KEY);
+ // Pull the private key ID from the certificate
+ //FIXME this function seems to be called both for a oauth.json action where
+ // there is no phrase required, but for signed requests too, which do require it
+ // this is a dirty hack to make it work .. kinda
+ if (! $privatekeyid = @openssl_pkey_get_private($cert)) {
+ if (! $privatekeyid = @openssl_pkey_get_private($cert, Config::get('private_key_phrase') != '' ? (Config::get('private_key_phrase')) : null)) {
+ throw new Exception("Could not load private key");
+ }
+ }
+ // Sign using the key
+ $signature = '';
+ if (($ok = openssl_sign($base_string, $signature, $privatekeyid)) === false) {
+ throw new OAuthException("Could not create signature");
+ }
+ // Release the key resource
+ @openssl_free_key($privatekeyid);
+ return base64_encode($signature);
+ }
+
+ public function check_signature(&$request, $consumer, $token, $signature)
+ {
+ $decoded_sig = base64_decode($signature);
+ $base_string = $request->get_signature_base_string();
+ // Fetch the public key cert based on the request
+ $cert = $this->fetch_public_cert($request);
+ // Pull the public key ID from the certificate
+ $publickeyid = openssl_get_publickey($cert);
+ // Check the computed signature against the one passed in the query
+ $ok = openssl_verify($base_string, $decoded_sig, $publickeyid);
+ // Release the key resource
+ @openssl_free_key($publickeyid);
+ return $ok == 1;
+ }
+}
+
+class OAuthRequest {
+ private $parameters;
+ private $http_method;
+ private $http_url;
+ public $base_string;
+ public static $version = '1.0';
+
+ function __construct($http_method, $http_url, $parameters = NULL)
+ {
+ @$parameters or $parameters = array();
+ $this->parameters = $parameters;
+ $this->http_method = $http_method;
+ $this->http_url = $http_url;
+ }
+
+ /**
+ * attempt to build up a request from what was passed to the server
+ */
+ public static function from_request($http_method = NULL, $http_url = NULL, $parameters = NULL)
+ {
+ $scheme = (! isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") ? 'http' : 'https';
+ @$http_url or $http_url = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
+ @$http_method or $http_method = $_SERVER['REQUEST_METHOD'];
+ $request_headers = OAuthRequest::get_headers();
+ // let the library user override things however they'd like, if they know
+ // which parameters to use then go for it, for example XMLRPC might want to
+ // do this
+ if ($parameters) {
+ $req = new OAuthRequest($http_method, $http_url, $parameters);
+ } elseif (@substr($request_headers['Authorization'], 0, 5) == "OAuth") {
+ // next check for the auth header, we need to do some extra stuff
+ // if that is the case, namely suck in the parameters from GET or POST
+ // so that we can include them in the signature
+ $header_parameters = OAuthRequest::split_header($request_headers['Authorization']);
+ if ($http_method == "GET") {
+ $req_parameters = $_GET;
+ } else
+ if ($http_method = "POST") {
+ $req_parameters = $_POST;
+ }
+ $parameters = array_merge($header_parameters, $req_parameters);
+ $req = new OAuthRequest($http_method, $http_url, $parameters);
+ } elseif ($http_method == "GET") {
+ $req = new OAuthRequest($http_method, $http_url, $_GET);
+ } elseif ($http_method == "POST") {
+ $req = new OAuthRequest($http_method, $http_url, $_POST);
+ }
+ return $req;
+ }
+
+ /**
+ * pretty much a helper function to set up the request
+ */
+ public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters = NULL)
+ {
+ $parameters = is_array($parameters) ? $parameters : array();
+ $defaults = array("oauth_nonce" => OAuthRequest::generate_nonce(),
+ "oauth_timestamp" => OAuthRequest::generate_timestamp(),
+ "oauth_consumer_key" => $consumer->key);
+ $parameters = array_merge($defaults, $parameters);
+ if (isset($token)) {
+ $parameters['oauth_token'] = $token;
+ }
+ return new OAuthRequest($http_method, $http_url, $parameters);
+ }
+
+ public function set_parameter($name, $value)
+ {
+ $this->parameters[$name] = $value;
+ }
+
+ public function get_parameter($name)
+ {
+ return @$this->parameters[$name];
+ }
+
+ public function get_parameters()
+ {
+ return $this->parameters;
+ }
+
+ public function set_parameters($params)
+ {
+ return $this->parameters = $params;
+ }
+
//TODO double check if hash can be used
- public function requireParameters($names)
- {
- $present = $this->parameters;
- $absent = array();
- foreach ($names as $required) {
- if (! in_array($required, $present)) {
- $absent[] = $required;
- }
- }
- if (count($absent) == 0) {
- throw new OAuthProblemException("oauth_parameters_absent: " . OAuthUtil::urlencodeRFC3986($absent));
- }
- }
-
- /**
- * Returns the normalized parameters of the request
- *
- * This will be all (except oauth_signature) parameters,
- * sorted first by key, and if duplicate keys, then by
- * value.
- *
- * The returned string will be all the key=value pairs
- * concated by &.
- *
- * @return string
- */
- public function get_signable_parameters()
- {
- // Grab all parameters
- $params = $this->parameters;
- // Remove oauth_signature if present
- if (isset($params['oauth_signature'])) {
- unset($params['oauth_signature']);
- }
- // Urlencode both keys and values
- $keys = array_map(array('OAuthUtil', 'urlencodeRFC3986'), array_keys($params));
- $values = array_map(array('OAuthUtil', 'urlencodeRFC3986'), array_values($params));
- $params = array_combine($keys, $values);
- // Sort by keys (natsort)
- uksort($params, 'strnatcmp');
- // Generate key=value pairs
- $pairs = array();
- foreach ($params as $key => $value) {
- if (is_array($value)) {
- // If the value is an array, it's because there are multiple
- // with the same key, sort them, then add all the pairs
- natsort($value);
- foreach ($value as $v2) {
- $pairs[] = $key . '=' . $v2;
- }
- } else {
- $pairs[] = $key . '=' . $value;
- }
- }
- // Return the pairs, concated with &
- return implode('&', $pairs);
- }
-
- /**
- * Returns the base string of this request
- *
- * The base string defined as the method, the url
- * and the parameters (normalized), each urlencoded
- * and the concated with &.
- */
- public function get_signature_base_string()
- {
- $tmp = $this->parameters;
- $parts = parse_url($this->http_url);
- parse_str(@$parts['query'], $params);
- foreach ($params as $key => $value) {
- $this->parameters[$key] = $value;
- }
- $parts = array($this->get_normalized_http_method(), $this->get_normalized_http_url(),
- $this->get_signable_parameters());
- $parts = array_map(array('OAuthUtil', 'urlencodeRFC3986'), $parts);
- $this->parameters = $tmp;
- return implode('&', $parts);
- }
-
- /**
- * just uppercases the http method
- */
- public function get_normalized_http_method()
- {
- return strtoupper($this->http_method);
- }
-
- /**
- * parses the url and rebuilds it to be
- * scheme://host/path
- */
- public function get_normalized_http_url()
- {
- $parts = parse_url($this->http_url);
- // FIXME: port should handle according to http://groups.google.com/group/oauth/browse_thread/thread/1b203a51d9590226
- $port = (isset($parts['port']) && $parts['port'] != '80') ? ':' . $parts['port'] : '';
- $path = (isset($parts['path'])) ? $parts['path'] : '';
-
- return $parts['scheme'] . '://' . $parts['host'] . $port . $path;
- }
-
- /**
- * builds a url usable for a GET request
- */
- public function to_url()
- {
- $out = $this->get_normalized_http_url() . "?";
- $out .= $this->to_postdata();
- $parts = parse_url($this->http_url);
- $out .= "&" . @$parts['query'];
- return $out;
- }
-
- public function get_url()
- {
- return $this->http_url;
- }
-
- /**
- * builds the data one would send in a POST request
- */
- public function to_postdata()
- {
- $total = array();
- foreach ($this->parameters as $k => $v) {
- $total[] = OAuthUtil::urlencodeRFC3986($k) . "=" . OAuthUtil::urlencodeRFC3986($v);
- }
- $out = implode("&", $total);
- return $out;
- }
-
- /**
- * builds the Authorization: header
- */
- public function to_header()
- {
- $out = '"Authorization: OAuth realm="",';
- foreach ($this->parameters as $k => $v) {
- if (substr($k, 0, 5) != "oauth")
- continue;
- $out .= ',' . OAuthUtil::urlencodeRFC3986($k) . '="' . OAuthUtil::urlencodeRFC3986($v) . '"';
- }
- return $out;
- }
-
- public function __toString()
- {
- return $this->to_url();
- }
-
- public function sign_request($signature_method, $consumer, $token)
- {
- $this->set_parameter("oauth_signature_method", $signature_method->get_name());
- $signature = $this->build_signature($signature_method, $consumer, $token);
- $this->set_parameter("oauth_signature", $signature);
- }
-
- public function build_signature($signature_method, $consumer, $token)
- {
- $signature = $signature_method->build_signature($this, $consumer, $token);
- return $signature;
- }
-
- /**
- * util function: current timestamp
- */
- private static function generate_timestamp()
- {
- return time();
- }
-
- /**
- * util function: current nonce
- */
- public static function generate_nonce()
- {
- $mt = microtime();
- $rand = mt_rand();
- return md5($mt . $rand); // md5s look nicer than numbers
- }
-
- /**
- * util function for turning the Authorization: header into
- * parameters, has to do some unescaping
- */
- private static function split_header($header)
- {
- // this should be a regex
- // error cases: commas in parameter values
- $parts = explode(",", $header);
- $out = array();
- foreach ($parts as $param) {
- $param = ltrim($param);
- // skip the "realm" param, nobody ever uses it anyway
- if (substr($param, 0, 5) != "oauth")
- continue;
- $param_parts = explode("=", $param);
- // rawurldecode() used because urldecode() will turn a "+" in the
- // value into a space
- $out[$param_parts[0]] = rawurldecode(substr($param_parts[1], 1, - 1));
- }
- return $out;
- }
-
- /**
- * helper to try to sort out headers for people who aren't running apache
- */
- private static function get_headers()
- {
- if (function_exists('apache_request_headers')) {
- // we need this to get the actual Authorization: header
- // because apache tends to tell us it doesn't exist
- return apache_request_headers();
- }
- // otherwise we don't have apache and are just going to have to hope
- // that $_SERVER actually contains what we need
- $out = array();
- foreach ($_SERVER as $key => $value) {
- if (substr($key, 0, 5) == "HTTP_") {
- // this is chaos, basically it is just there to capitalize the first
- // letter of every word that is not an initial HTTP and strip HTTP
- // code from przemek
- $key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))));
- $out[$key] = $value;
- }
- }
- return $out;
- }
-}
-
-class OAuthUtil {
-
- public static $AUTH_SCHEME = "OAuth";
- private static $AUTHORIZATION = "\ *[a-zA-Z0-9*]\ +(.*)";
- private static $NVP = "(\\S*)\\s*\\=\\s*\"([^\"]*)\"";
-
- public static function getPostBodyString(Array $params)
- {
- $result = '';
- $first = true;
- foreach ($params as $key => $val) {
- if ($first) {
- $first = false;
- } else {
- $result .= '&';
- }
- $result .= OAuthUtil::urlencodeRFC3986($key) . "=" . OAuthUtil::urlencodeRFC3986($val);
- }
- return $result;
- }
-
- public static function urlencodeRFC3986($string)
- {
- return str_replace('%7E', '~', rawurlencode($string));
- }
-
- public static function urldecodeRFC3986($string)
- {
- return rawurldecode($string);
- }
-
- /** Return true if the given Content-Type header means FORM_ENCODED. */
- public static function isFormEncoded($contentType)
- {
- if (! isset($contentType)) {
- return false;
- }
- $semi = strpos($contentType, ";");
- if ($semi >= 0) {
- $contentType = substr($contentType, 0, $semi);
- }
- return strtolower(OAuth::$FORM_ENCODED) == strtolower(trim($contentType));
- }
-
- public static function addParameters($url, $oauthParams)
- {
- $url .= strchr($url, '?') === false ? '?' : '&';
- foreach ($oauthParams as $key => $value) {
- $url .= "$key=$value&";
- }
- return $url;
- }
-
- public static function decodeForm($form)
- {
- $parameters = array();
- $explodedForm = explode("&", $form);
- foreach ($explodedForm as $params) {
- $value = explode("=", $params);
- if (! empty($value[0]) && ! empty($value[1])) {
- $parameters[OAuthUtil::urldecodeRFC3986($value[0])] = OAuthUtil::urldecodeRFC3986($value[1]);
- }
- }
- return $parameters;
- }
-
- /**
- * Parse the parameters from an OAuth Authorization or WWW-Authenticate
- * header. The realm is included as a parameter. If the given header doesn't
- * start with "OAuth ", return an empty list.
- */
- public static function decodeAuthorization($authorization)
- {
- $into = array();
- if ($authorization != null) {
- $m = ereg(self::$AUTHORIZATION, $authorization);
- if ($m !== false) {
- if (strpos($authorization, OAuthUtil::$AUTH_SCHEME) == 0) {
- $authorization = str_replace("OAuth ", "", $authorization);
- $authParams = explode(", ", $authorization);
- foreach ($authParams as $params) {
- $m = ereg(OAuthUtil::$NVP, $params);
- if ($m == 1) {
- $keyValue = explode("=", $params);
- $name = OAuthUtil::urlencodeRFC3986($keyValue[0]);
- $value = OAuthUtil::urlencodeRFC3986(str_replace("\"", "", $keyValue[1]));
- $into[$name] = $value;
- }
- }
- }
- }
- }
- return $into;
- }
-}
\ No newline at end of file
+ public function requireParameters($names)
+ {
+ $present = $this->parameters;
+ $absent = array();
+ foreach ($names as $required) {
+ if (! in_array($required, $present)) {
+ $absent[] = $required;
+ }
+ }
+ if (count($absent) == 0) {
+ throw new OAuthProblemException("oauth_parameters_absent: " . OAuthUtil::urlencodeRFC3986($absent));
+ }
+ }
+
+ /**
+ * Returns the normalized parameters of the request
+ *
+ * This will be all (except oauth_signature) parameters,
+ * sorted first by key, and if duplicate keys, then by
+ * value.
+ *
+ * The returned string will be all the key=value pairs
+ * concated by &.
+ *
+ * @return string
+ */
+ public function get_signable_parameters()
+ {
+ // Grab all parameters
+ $params = $this->parameters;
+ // Remove oauth_signature if present
+ if (isset($params['oauth_signature'])) {
+ unset($params['oauth_signature']);
+ }
+ // Urlencode both keys and values
+ $keys = array_map(array('OAuthUtil', 'urlencodeRFC3986'), array_keys($params));
+ $values = array_map(array('OAuthUtil', 'urlencodeRFC3986'), array_values($params));
+ $params = array_combine($keys, $values);
+ // Sort by keys (natsort)
+ uksort($params, 'strnatcmp');
+ // Generate key=value pairs
+ $pairs = array();
+ foreach ($params as $key => $value) {
+ if (is_array($value)) {
+ // If the value is an array, it's because there are multiple
+ // with the same key, sort them, then add all the pairs
+ natsort($value);
+ foreach ($value as $v2) {
+ $pairs[] = $key . '=' . $v2;
+ }
+ } else {
+ $pairs[] = $key . '=' . $value;
+ }
+ }
+ // Return the pairs, concated with &
+ return implode('&', $pairs);
+ }
+
+ /**
+ * Returns the base string of this request
+ *
+ * The base string defined as the method, the url
+ * and the parameters (normalized), each urlencoded
+ * and the concated with &.
+ */
+ public function get_signature_base_string()
+ {
+ $tmp = $this->parameters;
+ $parts = parse_url($this->http_url);
+ parse_str(@$parts['query'], $params);
+ foreach ($params as $key => $value) {
+ if ($key == "signOwner" || $key == "signViewer") {
+ continue;
+ }
+ $this->parameters[$key] = $value;
+ }
+ $parts = array($this->get_normalized_http_method(), $this->get_normalized_http_url(),
+ $this->get_signable_parameters());
+ $parts = array_map(array('OAuthUtil', 'urlencodeRFC3986'), $parts);
+ $this->parameters = $tmp;
+ return implode('&', $parts);
+ }
+
+ /**
+ * just uppercases the http method
+ */
+ public function get_normalized_http_method()
+ {
+ return strtoupper($this->http_method);
+ }
+
+ /**
+ * parses the url and rebuilds it to be
+ * scheme://host/path
+ */
+ public function get_normalized_http_url()
+ {
+ $parts = parse_url($this->http_url);
+ // FIXME: port should handle according to http://groups.google.com/group/oauth/browse_thread/thread/1b203a51d9590226
+ $port = (isset($parts['port']) && $parts['port'] != '80') ? ':' . $parts['port'] : '';
+ $path = (isset($parts['path'])) ? $parts['path'] : '';
+
+ return $parts['scheme'] . '://' . $parts['host'] . $port . $path;
+ }
+
+ /**
+ * builds a url usable for a GET request
+ */
+ public function to_url()
+ {
+ $out = $this->get_normalized_http_url() . "?";
+ $out .= $this->to_postdata();
+ $parts = parse_url($this->http_url);
+ $out .= "&" . @$parts['query'];
+ return $out;
+ }
+
+ public function get_url()
+ {
+ return $this->http_url;
+ }
+
+ /**
+ * builds the data one would send in a POST request
+ */
+ public function to_postdata()
+ {
+ $total = array();
+ foreach ($this->parameters as $k => $v) {
+ $total[] = OAuthUtil::urlencodeRFC3986($k) . "=" . OAuthUtil::urlencodeRFC3986($v);
+ }
+ $out = implode("&", $total);
+ return $out;
+ }
+
+ /**
+ * builds the Authorization: header
+ */
+ public function to_header()
+ {
+ $out = '"Authorization: OAuth realm="",';
+ foreach ($this->parameters as $k => $v) {
+ if (substr($k, 0, 5) != "oauth")
+ continue;
+ $out .= ',' . OAuthUtil::urlencodeRFC3986($k) . '="' . OAuthUtil::urlencodeRFC3986($v) . '"';
+ }
+ return $out;
+ }
+
+ public function __toString()
+ {
+ return $this->to_url();
+ }
+
+ public function sign_request($signature_method, $consumer, $token)
+ {
+ $this->set_parameter("oauth_signature_method", $signature_method->get_name());
+ $signature = $this->build_signature($signature_method, $consumer, $token);
+ $this->set_parameter("oauth_signature", $signature);
+ }
+
+ public function build_signature($signature_method, $consumer, $token)
+ {
+ $signature = $signature_method->build_signature($this, $consumer, $token);
+ return $signature;
+ }
+
+ /**
+ * util function: current timestamp
+ */
+ private static function generate_timestamp()
+ {
+ return time();
+ }
+
+ /**
+ * util function: current nonce
+ */
+ public static function generate_nonce()
+ {
+ $mt = microtime();
+ $rand = mt_rand();
+ return md5($mt . $rand); // md5s look nicer than numbers
+ }
+
+ /**
+ * util function for turning the Authorization: header into
+ * parameters, has to do some unescaping
+ */
+ private static function split_header($header)
+ {
+ // this should be a regex
+ // error cases: commas in parameter values
+ $parts = explode(",", $header);
+ $out = array();
+ foreach ($parts as $param) {
+ $param = ltrim($param);
+ // skip the "realm" param, nobody ever uses it anyway
+ if (substr($param, 0, 5) != "oauth")
+ continue;
+ $param_parts = explode("=", $param);
+ // rawurldecode() used because urldecode() will turn a "+" in the
+ // value into a space
+ $out[$param_parts[0]] = rawurldecode(substr($param_parts[1], 1, - 1));
+ }
+ return $out;
+ }
+
+ /**
+ * helper to try to sort out headers for people who aren't running apache
+ */
+ private static function get_headers()
+ {
+ if (function_exists('apache_request_headers')) {
+ // we need this to get the actual Authorization: header
+ // because apache tends to tell us it doesn't exist
+ return apache_request_headers();
+ }
+ // otherwise we don't have apache and are just going to have to hope
+ // that $_SERVER actually contains what we need
+ $out = array();
+ foreach ($_SERVER as $key => $value) {
+ if (substr($key, 0, 5) == "HTTP_") {
+ // this is chaos, basically it is just there to capitalize the first
+ // letter of every word that is not an initial HTTP and strip HTTP
+ // code from przemek
+ $key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))));
+ $out[$key] = $value;
+ }
+ }
+ return $out;
+ }
+}
+
+class OAuthUtil {
+
+ public static $AUTH_SCHEME = "OAuth";
+ private static $AUTHORIZATION = "\ *[a-zA-Z0-9*]\ +(.*)";
+ private static $NVP = "(\\S*)\\s*\\=\\s*\"([^\"]*)\"";
+
+ public static function getPostBodyString(Array $params)
+ {
+ $result = '';
+ $first = true;
+ foreach ($params as $key => $val) {
+ if ($first) {
+ $first = false;
+ } else {
+ $result .= '&';
+ }
+ $result .= OAuthUtil::urlencodeRFC3986($key) . "=" . OAuthUtil::urlencodeRFC3986($val);
+ }
+ return $result;
+ }
+
+ public static function urlencodeRFC3986($string)
+ {
+ return str_replace('%7E', '~', rawurlencode($string));
+ }
+
+ public static function urldecodeRFC3986($string)
+ {
+ return rawurldecode($string);
+ }
+
+ /** Return true if the given Content-Type header means FORM_ENCODED. */
+ public static function isFormEncoded($contentType)
+ {
+ if (! isset($contentType)) {
+ return false;
+ }
+ $semi = strpos($contentType, ";");
+ if ($semi >= 0) {
+ $contentType = substr($contentType, 0, $semi);
+ }
+ return strtolower(OAuth::$FORM_ENCODED) == strtolower(trim($contentType));
+ }
+
+ public static function addParameters($url, $oauthParams)
+ {
+ $url .= strchr($url, '?') === false ? '?' : '&';
+ foreach ($oauthParams as $key => $value) {
+ $url .= "$key=$value&";
+ }
+ return $url;
+ }
+
+ public static function decodeForm($form)
+ {
+ $parameters = array();
+ $explodedForm = explode("&", $form);
+ foreach ($explodedForm as $params) {
+ $value = explode("=", $params);
+ if (! empty($value[0]) && ! empty($value[1])) {
+ $parameters[OAuthUtil::urldecodeRFC3986($value[0])] = OAuthUtil::urldecodeRFC3986($value[1]);
+ }
+ }
+ return $parameters;
+ }
+
+ /**
+ * Parse the parameters from an OAuth Authorization or WWW-Authenticate
+ * header. The realm is included as a parameter. If the given header doesn't
+ * start with "OAuth ", return an empty list.
+ */
+ public static function decodeAuthorization($authorization)
+ {
+ $into = array();
+ if ($authorization != null) {
+ $m = ereg(self::$AUTHORIZATION, $authorization);
+ if ($m !== false) {
+ if (strpos($authorization, OAuthUtil::$AUTH_SCHEME) == 0) {
+ $authorization = str_replace("OAuth ", "", $authorization);
+ $authParams = explode(", ", $authorization);
+ foreach ($authParams as $params) {
+ $m = ereg(OAuthUtil::$NVP, $params);
+ if ($m == 1) {
+ $keyValue = explode("=", $params);
+ $name = OAuthUtil::urlencodeRFC3986($keyValue[0]);
+ $value = OAuthUtil::urlencodeRFC3986(str_replace("\"", "", $keyValue[1]));
+ $into[$name] = $value;
+ }
+ }
+ }
+ }
+ }
+ return $into;
+ }
+}