aboutsummaryrefslogtreecommitdiff
path: root/mod/oauth_api/vendors/oauth/library/OAuthRequest.php
diff options
context:
space:
mode:
authorbrettp <brettp@36083f99-b078-4883-b0ff-0f9b5a30f544>2011-03-15 03:46:37 +0000
committerbrettp <brettp@36083f99-b078-4883-b0ff-0f9b5a30f544>2011-03-15 03:46:37 +0000
commit6c8c03142db734678d460ee085a73df1d05a88a1 (patch)
tree2ae02d3f7f68fbc7c16aed798dcae16047531767 /mod/oauth_api/vendors/oauth/library/OAuthRequest.php
parent74d029022863a78500ec76bdf000b781b5838544 (diff)
downloadelgg-6c8c03142db734678d460ee085a73df1d05a88a1.tar.gz
elgg-6c8c03142db734678d460ee085a73df1d05a88a1.tar.bz2
Refs #3115. Moved oauth_lib to oauth_api.
git-svn-id: http://code.elgg.org/elgg/trunk@8715 36083f99-b078-4883-b0ff-0f9b5a30f544
Diffstat (limited to 'mod/oauth_api/vendors/oauth/library/OAuthRequest.php')
-rw-r--r--mod/oauth_api/vendors/oauth/library/OAuthRequest.php801
1 files changed, 801 insertions, 0 deletions
diff --git a/mod/oauth_api/vendors/oauth/library/OAuthRequest.php b/mod/oauth_api/vendors/oauth/library/OAuthRequest.php
new file mode 100644
index 000000000..c0d6ddbc7
--- /dev/null
+++ b/mod/oauth_api/vendors/oauth/library/OAuthRequest.php
@@ -0,0 +1,801 @@
+<?php
+
+/**
+ * Request wrapper class. Prepares a request for consumption by the OAuth routines
+ *
+ * @version $Id: OAuthRequest.php 50 2008-10-01 15:11:08Z marcw@pobox.com $
+ * @author Marc Worrell <marcw@pobox.com>
+ * @date Nov 16, 2007 12:20:31 PM
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2007-2008 Mediamatic Lab
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+require_once dirname(__FILE__) . '/OAuthException.php';
+
+/**
+ * Object to parse an incoming OAuth request or prepare an outgoing OAuth request
+ */
+class OAuthRequest
+{
+ /* the realm for this request */
+ protected $realm;
+
+ /* all the parameters, RFC3986 encoded name/value pairs */
+ protected $param = array();
+
+ /* the parsed request uri */
+ protected $uri_parts;
+
+ /* the raw request uri */
+ protected $uri;
+
+ /* the request headers */
+ protected $headers;
+
+ /* the request method */
+ protected $method;
+
+ /* the body of the OAuth request */
+ protected $body;
+
+
+ /**
+ * Construct from the current request. Useful for checking the signature of a request.
+ * When not supplied with any parameters this will use the current request.
+ *
+ * @param string uri might include parameters
+ * @param string method GET, PUT, POST etc.
+ * @param string parameters additional post parameters, urlencoded (RFC1738)
+ * @param array headers headers for request
+ * @param string body optional body of the OAuth request (POST or PUT)
+ */
+ function __construct ( $uri = null, $method = 'GET', $parameters = '', $headers = array(), $body = null )
+ {
+ if (empty($uri))
+ {
+ if (is_object($_SERVER))
+ {
+ // Tainted arrays - the normal stuff in anyMeta
+ $method = $_SERVER->REQUEST_METHOD->getRawUnsafe();
+ $uri = $_SERVER->REQUEST_URI->getRawUnsafe();
+ }
+ else
+ {
+ // non anyMeta systems
+ $method = $_SERVER['REQUEST_METHOD'];
+ $uri = $_SERVER['REQUEST_URI'];
+ }
+ $headers = getallheaders();
+ $parameters = '';
+ $this->method = strtoupper($method);
+
+ // If this is a post then also check the posted variables
+ if (strcasecmp($method, 'POST') == 0)
+ {
+ /*
+ // TODO: what to do with 'multipart/form-data'?
+ if ($this->getRequestContentType() == 'multipart/form-data')
+ {
+ throw new OAuthException('Unsupported POST content type, expected "application/x-www-form-urlencoded" got "'.@$_SERVER['CONTENT_TYPE'].'"');
+ }
+ */
+ if ($this->getRequestContentType() == 'application/x-www-form-urlencoded')
+ {
+ // Get the posted body (when available)
+ if (!isset($headers['X-OAuth-Test']))
+ {
+ $parameters .= $this->getRequestBody();
+ }
+ }
+ else
+ {
+ $body = $this->getRequestBody();
+ }
+ }
+ else if (strcasecmp($method, 'PUT') == 0)
+ {
+ $body = $this->getRequestBody();
+ }
+ }
+
+ $this->method = strtoupper($method);
+ $this->headers = $headers;
+ // Store the values, prepare for oauth
+ $this->uri = $uri;
+ $this->body = $body;
+ $this->parseUri($parameters);
+ $this->parseHeaders();
+ $this->transcodeParams();
+ }
+
+
+ /**
+ * Return the signature base string.
+ * Note that we can't use rawurlencode due to specified use of RFC3986.
+ *
+ * @return string
+ */
+ function signatureBaseString ()
+ {
+ $sig = array();
+ $sig[] = $this->method;
+ $sig[] = $this->getRequestUrl();
+ $sig[] = $this->getNormalizedParams();
+
+ return implode('&', array_map(array($this, 'urlencode'), $sig));
+ }
+
+
+ /**
+ * Calculate the signature of the request, using the method in oauth_signature_method.
+ * The signature is returned encoded in the form as used in the url. So the base64 and
+ * urlencoding has been done.
+ *
+ * @param string consumer_secret
+ * @param string token_secret
+ * @exception when not all parts available
+ * @return string
+ */
+ function calculateSignature ( $consumer_secret, $token_secret, $token_type = 'access' )
+ {
+ $required = array(
+ 'oauth_consumer_key',
+ 'oauth_signature_method',
+ 'oauth_timestamp',
+ 'oauth_nonce'
+ );
+
+ if ($token_type !== false)
+ {
+ $required[] = 'oauth_token';
+ }
+
+ foreach ($required as $req)
+ {
+ if (!isset($this->param[$req]))
+ {
+ throw new OAuthException('Can\'t sign request, missing parameter "'.$req.'"');
+ }
+ }
+
+ $this->checks();
+
+ $base = $this->signatureBaseString();
+ $signature = $this->calculateDataSignature($base, $consumer_secret, $token_secret, $this->param['oauth_signature_method']);
+ return $signature;
+ }
+
+
+ /**
+ * Calculate the signature of a string.
+ * Uses the signature method from the current parameters.
+ *
+ * @param string data
+ * @param string consumer_secret
+ * @param string token_secret
+ * @param string signature_method
+ * @exception OAuthException thrown when the signature method is unknown
+ * @return string signature
+ */
+ function calculateDataSignature ( $data, $consumer_secret, $token_secret, $signature_method )
+ {
+ if (is_null($data))
+ {
+ $data = '';
+ }
+
+ $sig = $this->getSignatureMethod($signature_method);
+ return $sig->signature($this, $data, $consumer_secret, $token_secret);
+ }
+
+
+ /**
+ * Select a signature method from the list of available methods.
+ * We try to check the most secure methods first.
+ *
+ * @todo Let the signature method tell us how secure it is
+ * @param array methods
+ * @exception OAuthException when we don't support any method in the list
+ * @return string
+ */
+ public function selectSignatureMethod ( $methods )
+ {
+ if (in_array('HMAC-SHA1', $methods))
+ {
+ $method = 'HMAC-SHA1';
+ }
+ else if (in_array('MD5', $methods))
+ {
+ $method = 'MD5';
+ }
+ else
+ {
+ $method = false;
+ foreach ($methods as $m)
+ {
+ $m = strtoupper($m);
+ $m = preg_replace('/[^A-Z0-9]/', '_', $m);
+ if (file_exists(dirname(__FILE__).'/signature_method/OAuthSignatureMethod_'.$m.'.php'))
+ {
+ $method = $m;
+ break;
+ }
+ }
+
+ if (empty($method))
+ {
+ throw new OAuthException('None of the signing methods is supported.');
+ }
+ }
+ return $method;
+ }
+
+
+ /**
+ * Fetch the signature object used for calculating and checking the signature base string
+ *
+ * @param string method
+ * @return OAuthSignatureMethod object
+ */
+ function getSignatureMethod ( $method )
+ {
+ $m = strtoupper($method);
+ $m = preg_replace('/[^A-Z0-9]/', '_', $m);
+ $class = 'OAuthSignatureMethod_'.$m;
+
+ if (file_exists(dirname(__FILE__).'/signature_method/'.$class.'.php'))
+ {
+ require_once dirname(__FILE__).'/signature_method/'.$class.'.php';
+ $sig = new $class();
+ }
+ else
+ {
+ throw new OAuthException('Unsupported signature method "'.$m.'".');
+ }
+ return $sig;
+ }
+
+
+ /**
+ * Perform some sanity checks.
+ *
+ * @exception OAuthException thrown when sanity checks failed
+ */
+ function checks ()
+ {
+ if (isset($this->param['oauth_version']))
+ {
+ $version = $this->urldecode($this->param['oauth_version']);
+ if ($version != '1.0')
+ {
+ throw new OAuthException('Expected OAuth version 1.0, got "'.$this->param['oauth_version'].'"');
+ }
+ }
+ }
+
+
+ /**
+ * Return the request method
+ *
+ * @return string
+ */
+ function getMethod ()
+ {
+ return $this->method;
+ }
+
+ /**
+ * Return the complete parameter string for the signature check.
+ * All parameters are correctly urlencoded and sorted on name and value
+ *
+ * @return string
+ */
+ function getNormalizedParams ()
+ {
+ /*
+ // sort by name, then by value
+ // (needed when we start allowing multiple values with the same name)
+ $keys = array_keys($this->param);
+ $values = array_values($this->param);
+ array_multisort($keys, SORT_ASC, $values, SORT_ASC);
+ */
+ $params = $this->param;
+ $normalized = array();
+
+ ksort($params);
+ foreach ($params as $key => $value)
+ {
+ // all names and values are already urlencoded, exclude the oauth signature
+ if ($key != 'oauth_signature')
+ {
+ if (is_array($value))
+ {
+ $value_sort = $value;
+ sort($value_sort);
+ foreach ($value_sort as $v)
+ {
+ $normalized[] = $key.'='.$v;
+ }
+ }
+ else
+ {
+ $normalized[] = $key.'='.$value;
+ }
+ }
+ }
+ return implode('&', $normalized);
+ }
+
+
+ /**
+ * Return the normalised url for signature checks
+ */
+ function getRequestUrl ()
+ {
+ $url = $this->uri_parts['scheme'] . '://'
+ . $this->uri_parts['user'] . (!empty($this->uri_parts['pass']) ? ':' : '')
+ . $this->uri_parts['pass'] . (!empty($this->uri_parts['user']) ? '@' : '')
+ . $this->uri_parts['host'];
+
+ if ( $this->uri_parts['port']
+ && $this->uri_parts['port'] != $this->defaultPortForScheme($this->uri_parts['scheme']))
+ {
+ $url .= ':'.$this->uri_parts['port'];
+ }
+ if (!empty($this->uri_parts['path']))
+ {
+ $url .= $this->uri_parts['path'];
+ }
+ return $url;
+ }
+
+
+ /**
+ * Get a parameter, value is always urlencoded
+ *
+ * @param string name
+ * @param boolean urldecode set to true to decode the value upon return
+ * @return string value false when not found
+ */
+ function getParam ( $name, $urldecode = false )
+ {
+ if (isset($this->param[$name]))
+ {
+ $s = $this->param[$name];
+ }
+ else if (isset($this->param[$this->urlencode($name)]))
+ {
+ $s = $this->param[$this->urlencode($name)];
+ }
+ else
+ {
+ $s = false;
+ }
+ if (!empty($s) && $urldecode)
+ {
+ if (is_array($s))
+ {
+ $s = array_map(array($this,'urldecode'), $s);
+ }
+ else
+ {
+ $s = $this->urldecode($s);
+ }
+ }
+ return $s;
+ }
+
+ /**
+ * Set a parameter
+ *
+ * @param string name
+ * @param string value
+ * @param boolean encoded set to true when the values are already encoded
+ */
+ function setParam ( $name, $value, $encoded = false )
+ {
+ if (!$encoded)
+ {
+ $name_encoded = $this->urlencode($name);
+ if (is_array($value))
+ {
+ foreach ($value as $v)
+ {
+ $this->param[$name_encoded][] = $this->urlencode($v);
+ }
+ }
+ else
+ {
+ $this->param[$name_encoded] = $this->urlencode($value);
+ }
+ }
+ else
+ {
+ $this->param[$name] = $value;
+ }
+ }
+
+
+ /**
+ * Re-encode all parameters so that they are encoded using RFC3986.
+ * Updates the $this->param attribute.
+ */
+ protected function transcodeParams ()
+ {
+ $params = $this->param;
+ $this->param = array();
+
+ foreach ($params as $name=>$value)
+ {
+ if (is_array($value))
+ {
+ $this->param[$this->urltranscode($name)] = array_map(array($this,'urltranscode'), $value);
+ }
+ else
+ {
+ $this->param[$this->urltranscode($name)] = $this->urltranscode($value);
+ }
+ }
+ }
+
+
+
+ /**
+ * Return the body of the OAuth request.
+ *
+ * @return string null when no body
+ */
+ function getBody ()
+ {
+ return $this->body;
+ }
+
+
+ /**
+ * Return the body of the OAuth request.
+ *
+ * @return string null when no body
+ */
+ function setBody ( $body )
+ {
+ $this->body = $body;
+ }
+
+
+ /**
+ * Parse the uri into its parts. Fill in the missing parts.
+ *
+ * @todo check for the use of https, right now we default to http
+ * @todo support for multiple occurences of parameters
+ * @param string $parameters optional extra parameters (from eg the http post)
+ */
+ protected function parseUri ( $parameters )
+ {
+ $ps = parse_url($this->uri);
+
+ // Get the current/requested method
+ if (empty($ps['scheme']))
+ {
+ $ps['scheme'] = 'http';
+ }
+ else
+ {
+ $ps['scheme'] = strtolower($ps['scheme']);
+ }
+
+ // Get the current/requested host
+ if (empty($ps['host']))
+ {
+ if (isset($_SERVER['HTTP_HOST']))
+ {
+ $ps['host'] = $_SERVER['HTTP_HOST'];
+ }
+ else
+ {
+ $ps['host'] = '';
+ }
+ }
+ $ps['host'] = mb_strtolower($ps['host']);
+ if (!preg_match('/^[a-z0-9\.\-]+$/', $ps['host']))
+ {
+ throw new OAuthException('Unsupported characters in host name');
+ }
+
+ // Get the port we are talking on
+ if (empty($ps['port']))
+ {
+ $ps['port'] = $this->defaultPortForScheme($ps['scheme']);
+ }
+
+ if (empty($ps['user']))
+ {
+ $ps['user'] = '';
+ }
+ if (empty($ps['pass']))
+ {
+ $ps['pass'] = '';
+ }
+ if (empty($ps['path']))
+ {
+ $ps['path'] = '/';
+ }
+ if (empty($ps['query']))
+ {
+ $ps['query'] = '';
+ }
+ if (empty($ps['fragment']))
+ {
+ $ps['fragment'] = '';
+ }
+
+ // Now all is complete - parse all parameters
+ foreach (array($ps['query'], $parameters) as $params)
+ {
+ if (strlen($params) > 0)
+ {
+ $params = explode('&', $params);
+ foreach ($params as $p)
+ {
+ @list($name, $value) = explode('=', $p, 2);
+ $this->param[$name] = $value;
+ }
+ }
+ }
+ $this->uri_parts = $ps;
+ }
+
+
+ /**
+ * Return the default port for a scheme
+ *
+ * @param string scheme
+ * @return int
+ */
+ protected function defaultPortForScheme ( $scheme )
+ {
+ switch ($scheme)
+ {
+ case 'http': return 80;
+ case 'https': return 43;
+ default:
+ throw new OAuthException('Unsupported scheme type, expected http or https, got "'.$scheme.'"');
+ break;
+ }
+ }
+
+
+ /**
+ * Encode a string according to the RFC3986
+ *
+ * @param string s
+ * @return string
+ */
+ function urlencode ( $s )
+ {
+ if ($s === false)
+ {
+ return $s;
+ }
+ else
+ {
+ return str_replace('%7E', '~', rawurlencode($s));
+ }
+ }
+
+ /**
+ * Decode a string according to RFC3986.
+ * Also correctly decodes RFC1738 urls.
+ *
+ * @param string s
+ * @return string
+ */
+ function urldecode ( $s )
+ {
+ if ($s === false)
+ {
+ return $s;
+ }
+ else
+ {
+ return rawurldecode($s);
+ }
+ }
+
+ /**
+ * urltranscode - make sure that a value is encoded using RFC3986.
+ * We use a basic urldecode() function so that any use of '+' as the
+ * encoding of the space character is correctly handled.
+ *
+ * @param string s
+ * @return string
+ */
+ function urltranscode ( $s )
+ {
+ if ($s === false)
+ {
+ return $s;
+ }
+ else
+ {
+ return $this->urlencode(urldecode($s));
+ }
+ }
+
+
+ /**
+ * Parse the oauth parameters from the request headers
+ * Looks for something like:
+ *
+ * Authorization: OAuth realm="http://photos.example.net/authorize",
+ * oauth_consumer_key="dpf43f3p2l4k3l03",
+ * oauth_token="nnch734d00sl2jdk",
+ * oauth_signature_method="HMAC-SHA1",
+ * oauth_signature="tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D",
+ * oauth_timestamp="1191242096",
+ * oauth_nonce="kllo9940pd9333jh",
+ * oauth_version="1.0"
+ */
+ private function parseHeaders ()
+ {
+/*
+ $this->headers['Authorization'] = 'OAuth realm="http://photos.example.net/authorize",
+ oauth_consumer_key="dpf43f3p2l4k3l03",
+ oauth_token="nnch734d00sl2jdk",
+ oauth_signature_method="HMAC-SHA1",
+ oauth_signature="tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D",
+ oauth_timestamp="1191242096",
+ oauth_nonce="kllo9940pd9333jh",
+ oauth_version="1.0"';
+*/
+ if (isset($this->headers['Authorization']))
+ {
+ $auth = trim($this->headers['Authorization']);
+ if (strncasecmp($auth, 'OAuth', 4) == 0)
+ {
+ $vs = explode(',', substr($auth, 6));
+ foreach ($vs as $v)
+ {
+ if (strpos($v, '='))
+ {
+ $v = trim($v);
+ list($name,$value) = explode('=', $v, 2);
+ if (!empty($value) && $value{0} == '"' && substr($value, -1) == '"')
+ {
+ $value = substr(substr($value, 1), 0, -1);
+ }
+
+ if (strcasecmp($name, 'realm') == 0)
+ {
+ $this->realm = $value;
+ }
+ else
+ {
+ $this->param[$name] = $value;
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Fetch the content type of the current request
+ *
+ * @return string
+ */
+ private function getRequestContentType ()
+ {
+ $content_type = 'application/octet-stream';
+ if (!empty($_SERVER) && array_key_exists('CONTENT_TYPE', $_SERVER))
+ {
+ list($content_type) = explode(';', $_SERVER['CONTENT_TYPE']);
+ }
+ return trim($content_type);
+ }
+
+
+ /**
+ * Get the body of a POST or PUT.
+ *
+ * Used for fetching the post parameters and to calculate the body signature.
+ *
+ * @return string null when no body present (or wrong content type for body)
+ */
+ private function getRequestBody ()
+ {
+ $body = null;
+ if ($this->method == 'POST' || $this->method == 'PUT')
+ {
+ $body = '';
+ $fh = @fopen('php://input', 'r');
+ if ($fh)
+ {
+ while (!feof($fh))
+ {
+ $s = fread($fh, 1024);
+ if (is_string($s))
+ {
+ $body .= $s;
+ }
+ }
+ fclose($fh);
+ }
+ }
+ return $body;
+ }
+
+
+ /**
+ * Simple function to perform a redirect (GET).
+ * Redirects the User-Agent, does not return.
+ *
+ * @param string uri
+ * @param array params parameters, urlencoded
+ * @exception OAuthException when redirect uri is illegal
+ */
+ public function redirect ( $uri, $params )
+ {
+ if (!empty($params))
+ {
+ $q = array();
+ foreach ($params as $name=>$value)
+ {
+ $q[] = $name.'='.$value;
+ }
+ $q_s = implode('&', $q);
+
+ if (strpos($uri, '?'))
+ {
+ $uri .= '&'.$q_s;
+ }
+ else
+ {
+ $uri .= '?'.$q_s;
+ }
+ }
+
+ // simple security - multiline location headers can inject all kinds of extras
+ $uri = preg_replace('/\s/', '%20', $uri);
+ if (strncasecmp($uri, 'http://', 7) && strncasecmp($uri, 'https://', 8))
+ {
+ if (strpos($uri, '://'))
+ {
+ throw new OAuthException('Illegal protocol in redirect uri '.$uri);
+ }
+ $uri = 'http://'.$uri;
+ }
+
+ header('HTTP/1.1 302 Found');
+ header('Location: '.$uri);
+ echo '';
+ exit();
+ }
+
+}
+
+
+/* vi:set ts=4 sts=4 sw=4 binary noeol: */
+
+?> \ No newline at end of file