diff options
Diffstat (limited to 'OAuth/src/Lib/OAuthRequest.php')
-rw-r--r-- | OAuth/src/Lib/OAuthRequest.php | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/OAuth/src/Lib/OAuthRequest.php b/OAuth/src/Lib/OAuthRequest.php new file mode 100644 index 00000000..5b5050ae --- /dev/null +++ b/OAuth/src/Lib/OAuthRequest.php @@ -0,0 +1,297 @@ +<?php +// vim: foldmethod=marker +/** + * The MIT License + * + * Copyright (c) 2007 Andy Smith + * + * 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. + */ + +namespace MediaWiki\Extensions\OAuth\Lib; + +use MediaWiki\Extensions\OAuth\Lib\OAuthException; +use MediaWiki\Extensions\OAuth\Lib\OAuthUtil; +use MediaWiki\Logger\LoggerFactory; + +class OAuthRequest { + protected $parameters; + protected $http_method; + protected $http_url; + // for debug purposes + public $base_string; + public static $version = '1.0'; + public static $POST_INPUT = 'php://input'; + + /** @var \\Psr\\Log\\LoggerInterface */ + protected $logger; + + function __construct( $http_method, $http_url, $parameters = null ) { + $parameters = ( $parameters ) ? $parameters : array(); + $parameters = array_merge( + OAuthUtil::parse_parameters( parse_url( $http_url, PHP_URL_QUERY ) ), + $parameters + ); + $this->parameters = $parameters; + $this->http_method = $http_method; + $this->http_url = $http_url; + $this->logger = LoggerFactory::getInstance( 'OAuth' ); + } + + /** + * 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 = ( $http_url ) ? $http_url : $scheme . '://' . $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI']; + $http_method = ( $http_method ) ? $http_method : $_SERVER['REQUEST_METHOD']; + + // We weren't handed any parameters, so let's find the ones relevant to + // this request. + // If you run XML-RPC or similar you should use this to provide your own + // parsed parameter-list + if ( !$parameters ) { + // Find request headers + $request_headers = OAuthUtil::get_headers(); + + // Parse the query-string to find GET parameters + $parameters = OAuthUtil::parse_parameters( $_SERVER['QUERY_STRING'] ); + + // It's a POST request of the proper content-type, so parse POST + // parameters and add those overriding any duplicates from GET + if ( $http_method == "POST" && isset( $request_headers['Content-Type'] ) && strstr( + $request_headers['Content-Type'], + 'application/x-www-form-urlencoded' + ) + ) { + $post_data = OAuthUtil::parse_parameters( file_get_contents( self::$POST_INPUT ) ); + $parameters = array_merge( $parameters, $post_data ); + } + + // We have a Authorization-header with OAuth data. Parse the header + // and add those overriding any duplicates from GET or POST + if ( isset( $request_headers['Authorization'] ) && substr( + $request_headers['Authorization'], + 0, + 6 + ) == 'OAuth ' + ) { + $header_parameters = OAuthUtil::split_header( $request_headers['Authorization'] ); + $parameters = array_merge( $parameters, $header_parameters ); + } + } + + return new OAuthRequest( $http_method, $http_url, $parameters ); + } + + /** + * 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 = ( $parameters ) ? $parameters : array(); + $defaults = array( + "oauth_version" => OAuthRequest::$version, + "oauth_nonce" => OAuthRequest::generate_nonce(), + "oauth_timestamp" => OAuthRequest::generate_timestamp(), + "oauth_consumer_key" => $consumer->key + ); + if ( $token ) { + $defaults['oauth_token'] = $token->key; + } + + $parameters = array_merge( $defaults, $parameters ); + + return new OAuthRequest( $http_method, $http_url, $parameters ); + } + + public function set_parameter( $name, $value, $allow_duplicates = true ) { + if ( $allow_duplicates && isset( $this->parameters[$name] ) ) { + // We have already added parameter( s ) with this name, so add to the list + if ( is_scalar( $this->parameters[$name] ) ) { + // This is the first duplicate, so transform scalar ( string ) + // into an array so we can add the duplicates + $this->parameters[$name] = array( $this->parameters[$name] ); + } + + $this->parameters[$name][] = $value; + } else { + $this->parameters[$name] = $value; + } + } + + public function get_parameter( $name ) { + return isset( $this->parameters[$name] ) ? $this->parameters[$name] : null; + } + + public function get_parameters() { + return $this->parameters; + } + + public function unset_parameter( $name ) { + unset( $this->parameters[$name] ); + } + + /** + * The request parameters, sorted and concatenated into a normalized string. + * @return string + */ + public function get_signable_parameters() { + // Grab all parameters + $params = $this->parameters; + + // Remove oauth_signature if present + // Ref: Spec: 9.1.1 ( "The oauth_signature parameter MUST be excluded." ) + if ( isset( $params['oauth_signature'] ) ) { + unset( $params['oauth_signature'] ); + } + + return OAuthUtil::build_http_query( $params ); + } + + /** + * 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() { + $parts = array( + $this->get_normalized_http_method(), + $this->get_normalized_http_url(), + $this->get_signable_parameters() + ); + + $parts = OAuthUtil::urlencode_rfc3986( $parts ); + + 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 ); + + $scheme = ( isset( $parts['scheme'] ) ) ? $parts['scheme'] : 'http'; + $port = ( isset( $parts['port'] ) ) ? $parts['port'] : ( ( $scheme == 'https' ) ? '443' : '80' ); + $host = ( isset( $parts['host'] ) ) ? strtolower( $parts['host'] ) : ''; + $path = ( isset( $parts['path'] ) ) ? $parts['path'] : ''; + + if ( ( $scheme == 'https' && $port != '443' ) || ( $scheme == 'http' && $port != '80' ) ) { + $host = "$host:$port"; + } + + return "$scheme://$host$path"; + } + + /** + * builds a url usable for a GET request + */ + public function to_url() { + $post_data = $this->to_postdata(); + $out = $this->get_normalized_http_url(); + if ( $post_data ) { + $out .= '?' . $post_data; + } + + return $out; + } + + /** + * builds the data one would send in a POST request + */ + public function to_postdata() { + return OAuthUtil::build_http_query( $this->parameters ); + } + + /** + * builds the Authorization: header + */ + public function to_header( $realm = null ) { + $first = true; + if ( $realm ) { + $out = 'Authorization: OAuth realm="' . OAuthUtil::urlencode_rfc3986( $realm ) . '"'; + $first = false; + } else { + $out = 'Authorization: OAuth'; + } + $total = array(); + foreach ( $this->parameters as $k => $v ) { + if ( substr( $k, 0, 5 ) != "oauth" ) { + continue; + } + if ( is_array( $v ) ) { + throw new OAuthException( 'Arrays not supported in headers' ); + } + $out .= ( $first ) ? ' ' : ','; + $out .= OAuthUtil::urlencode_rfc3986( $k ) . '="' . OAuthUtil::urlencode_rfc3986( + $v + ) . '"'; + $first = false; + } + + 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(), + false + ); + $signature = $this->build_signature( $signature_method, $consumer, $token ); + $this->set_parameter( "oauth_signature", $signature, false ); + } + + 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 + */ + private static function generate_nonce() { + $mt = microtime(); + $rand = mt_rand(); + + return md5( $mt . $rand ); // md5s look nicer than numbers + } +} |