diff --git a/includes/oauth-php/LICENSE b/includes/oauth-php/LICENSE new file mode 100644 index 00000000..fbdcc373 --- /dev/null +++ b/includes/oauth-php/LICENSE @@ -0,0 +1,22 @@ +The MIT License + +Copyright (c) 2007-2009 Mediamatic Lab +Copyright (c) 2010 Corollarium Technologies + +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. \ No newline at end of file diff --git a/includes/oauth-php/README b/includes/oauth-php/README new file mode 100644 index 00000000..ecd68156 --- /dev/null +++ b/includes/oauth-php/README @@ -0,0 +1 @@ +Please see http://code.google.com/p/oauth-php/ for documentation and help. diff --git a/includes/oauth-php/example/client/googledocs.php b/includes/oauth-php/example/client/googledocs.php new file mode 100644 index 00000000..6e9cf3af --- /dev/null +++ b/includes/oauth-php/example/client/googledocs.php @@ -0,0 +1,109 @@ + GOOGLE_CONSUMER_KEY, + 'consumer_secret' => GOOGLE_CONSUMER_SECRET, + 'server_uri' => GOOGLE_OAUTH_HOST, + 'request_token_uri' => GOOGLE_REQUEST_TOKEN_URL, + 'authorize_uri' => GOOGLE_AUTHORIZE_URL, + 'access_token_uri' => GOOGLE_ACCESS_TOKEN_URL +); +// Note: do not use "Session" storage in production. Prefer a database +// storage, such as MySQL. +OAuthStore::instance("Session", $options); + +try +{ + // STEP 1: If we do not have an OAuth token yet, go get one + if (empty($_GET["oauth_token"])) + { + $getAuthTokenParams = array('scope' => + 'http://docs.google.com/feeds/', + 'xoauth_displayname' => 'Oauth test', + 'oauth_callback' => 'http://likeorhate.local/google.php'); + + // get a request token + $tokenResultParams = OAuthRequester::requestRequestToken(GOOGLE_CONSUMER_KEY, 0, $getAuthTokenParams); + + // redirect to the google authorization page, they will redirect back + header("Location: " . GOOGLE_AUTHORIZE_URL . "?btmpl=mobile&oauth_token=" . $tokenResultParams['token']); + } + else { + // STEP 2: Get an access token + $oauthToken = $_GET["oauth_token"]; + + // echo "oauth_verifier = '" . $oauthVerifier . "'
"; + $tokenResultParams = $_GET; + + try { + OAuthRequester::requestAccessToken(GOOGLE_CONSUMER_KEY, $oauthToken, 0, 'POST', $_GET); + } + catch (OAuthException2 $e) + { + var_dump($e); + // Something wrong with the oauth_token. + // Could be: + // 1. Was already ok + // 2. We were not authorized + return; + } + + // make the docs requestrequest. + $request = new OAuthRequester("http://docs.google.com/feeds/documents/private/full", 'GET', $tokenResultParams); + $result = $request->doRequest(0); + if ($result['code'] == 200) { + var_dump($result['body']); + } + else { + echo 'Error'; + } + } +} +catch(OAuthException2 $e) { + echo "OAuthException: " . $e->getMessage(); + var_dump($e); +} +?> \ No newline at end of file diff --git a/includes/oauth-php/example/client/twolegged.php b/includes/oauth-php/example/client/twolegged.php new file mode 100644 index 00000000..a22c4fda --- /dev/null +++ b/includes/oauth-php/example/client/twolegged.php @@ -0,0 +1,67 @@ + $key, 'consumer_secret' => $secret); +OAuthStore::instance("2Leg", $options); + +$method = "GET"; +$params = null; + +try +{ + // Obtain a request object for the request we want to make + $request = new OAuthRequester($url, $method, $params); + + // Sign the request, perform a curl request and return the results, + // throws OAuthException2 exception on an error + // $result is an array of the form: array ('code'=>int, 'headers'=>array(), 'body'=>string) + $result = $request->doRequest(); + + $response = $result['body']; + var_dump($response); +} +catch(OAuthException2 $e) +{ + echo "Exception"; +} + +?> diff --git a/includes/oauth-php/example/client/twoleggedtest.php b/includes/oauth-php/example/client/twoleggedtest.php new file mode 100644 index 00000000..0fc866b0 --- /dev/null +++ b/includes/oauth-php/example/client/twoleggedtest.php @@ -0,0 +1,78 @@ + $key, 'consumer_secret' => $secret); +OAuthStore::instance("2Leg", $options); + +$method = "GET"; +$params = null; + +try +{ + // Obtain a request object for the request we want to make + $request = new OAuthRequester($url, $method, $params); + + // Sign the request, perform a curl request and return the results, + // throws OAuthException2 exception on an error + // $result is an array of the form: array ('code'=>int, 'headers'=>array(), 'body'=>string) + $result = $request->doRequest(); + + $response = $result['body']; + + if ($response != 'oauth_token=requestkey&oauth_token_secret=requestsecret') + { + echo 'Error! $response ' . $response; + } + else + { + } + + + var_dump($response); +} +catch(OAuthException2 $e) +{ + echo "Exception" . $e->getMessage(); +} + +?> diff --git a/includes/oauth-php/example/client/twoleggedtwitter.php b/includes/oauth-php/example/client/twoleggedtwitter.php new file mode 100644 index 00000000..a97b4636 --- /dev/null +++ b/includes/oauth-php/example/client/twoleggedtwitter.php @@ -0,0 +1,69 @@ + TWITTER_CONSUMER_KEY, 'consumer_secret' => TWITTER_CONSUMER_SECRET); +OAuthStore::instance("2Leg", $options); + +try +{ + // Obtain a request object for the request we want to make + $request = new OAuthRequester(TWITTER_REQUEST_TOKEN_URL, "POST"); + $result = $request->doRequest(0); + parse_str($result['body'], $params); + + echo "aa"; + + // now make the request. + $request = new OAuthRequester(TWITTER_PUBLIC_TIMELINE_API, 'GET', $params); + $result = $request->doRequest(); +} +catch(OAuthException2 $e) +{ + echo "Exception" . $e->getMessage(); +} + +?> \ No newline at end of file diff --git a/includes/oauth-php/example/server/INSTALL b/includes/oauth-php/example/server/INSTALL new file mode 100644 index 00000000..249c85e9 --- /dev/null +++ b/includes/oauth-php/example/server/INSTALL @@ -0,0 +1,53 @@ +In this example I assume that oauth-php lives in /home/john/src/oauth-php + + +1) Create a virtual host and set the DB_DSN VARIABLE to the DSN of your (mysql) database. + +Example + + ServerAdmin admin@localhost + ServerName hello.local + DocumentRoot /home/john/src/oauth-php/example/server/www + + UseCanonicalName Off + ServerSignature On + + SetEnv DB_DSN mysql://foo:bar@localhost/oauth_example_server_db + + + Options Indexes FollowSymLinks MultiViews + AllowOverride None + Order allow,deny + Allow from all + + + php_value magic_quotes_gpc 0 + php_value register_globals 0 + php_value session.auto_start 0 + + + + + + +2) Create the database structure for the server: + +# mysql -u foo -p bar -h localhost < /home/john/src/oauth-php/library/store/mysql/mysql.sql + + + +3) Download and install smarty into the smarty/core/smarty directory: + +# cd /home/john/src/oauth-php/example/server/core +# wget 'http://www.smarty.net/do_download.php?download_file=Smarty-2.6.19.tar.gz' +# tar zxf Smarty-2.6.19.tar.gz +# mv Smarty-2.6.19 smarty + + +4) That's it! Point your browser to + + http://hello.local/ + +To get started. + +Arjan Scherpenisse , July 2008 diff --git a/includes/oauth-php/example/server/core/init.php b/includes/oauth-php/example/server/core/init.php new file mode 100644 index 00000000..82c65db0 --- /dev/null +++ b/includes/oauth-php/example/server/core/init.php @@ -0,0 +1,128 @@ + + * + * + * 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. + */ + + +/* + * Simple 'user management' + */ +define ('USERNAME', 'sysadmin'); +define ('PASSWORD', 'sysadmin'); + + +/* + * Always announce XRDS OAuth discovery + */ +header('X-XRDS-Location: http://' . $_SERVER['SERVER_NAME'] . '/services.xrds'); + + +/* + * Initialize the database connection + */ +$info = parse_url(getenv('DB_DSN')); +($GLOBALS['db_conn'] = mysql_connect($info['host'], $info['user'], $info['pass'])) || die(mysql_error()); +mysql_select_db(basename($info['path']), $GLOBALS['db_conn']) || die(mysql_error()); +unset($info); + + +require_once '../../../library/OAuthServer.php'; + +/* + * Initialize OAuth store + */ +require_once '../../../library/OAuthStore.php'; +OAuthStore::instance('MySQL', array('conn' => $GLOBALS['db_conn'])); + + +/* + * Session + */ +session_start(); + + +/* + * Template handling + */ +require_once 'smarty/libs/Smarty.class.php'; +function session_smarty() +{ + if (!isset($GLOBALS['smarty'])) + { + $GLOBALS['smarty'] = new Smarty; + $GLOBALS['smarty']->template_dir = dirname(__FILE__) . '/templates/'; + $GLOBALS['smarty']->compile_dir = dirname(__FILE__) . '/../cache/templates_c'; + } + + return $GLOBALS['smarty']; +} + +function assert_logged_in() +{ + if (empty($_SESSION['authorized'])) + { + $uri = $_SERVER['REQUEST_URI']; + header('Location: /logon?goto=' . urlencode($uri)); + exit(); + } +} + +function assert_request_vars() +{ + foreach(func_get_args() as $a) + { + if (!isset($_REQUEST[$a])) + { + header('HTTP/1.1 400 Bad Request'); + echo 'Bad request.'; + exit; + } + } +} + +function assert_request_vars_all() +{ + foreach($_REQUEST as $row) + { + foreach(func_get_args() as $a) + { + if (!isset($row[$a])) + { + header('HTTP/1.1 400 Bad Request'); + echo 'Bad request.'; + exit; + } + } + } +} + +?> \ No newline at end of file diff --git a/includes/oauth-php/example/server/core/templates/inc/footer.tpl b/includes/oauth-php/example/server/core/templates/inc/footer.tpl new file mode 100644 index 00000000..308b1d01 --- /dev/null +++ b/includes/oauth-php/example/server/core/templates/inc/footer.tpl @@ -0,0 +1,2 @@ + + diff --git a/includes/oauth-php/example/server/core/templates/inc/header.tpl b/includes/oauth-php/example/server/core/templates/inc/header.tpl new file mode 100644 index 00000000..5046f54b --- /dev/null +++ b/includes/oauth-php/example/server/core/templates/inc/header.tpl @@ -0,0 +1,2 @@ + + diff --git a/includes/oauth-php/example/server/core/templates/index.tpl b/includes/oauth-php/example/server/core/templates/index.tpl new file mode 100644 index 00000000..7b065537 --- /dev/null +++ b/includes/oauth-php/example/server/core/templates/index.tpl @@ -0,0 +1,13 @@ +{include file='inc/header.tpl'} + +

OAuth server

+Go to: + + + +Afterwards, make an OAuth test request to http://{$smarty.server.name}/hello to test your connection.

+ +{include file='inc/footer.tpl'} diff --git a/includes/oauth-php/example/server/core/templates/logon.tpl b/includes/oauth-php/example/server/core/templates/logon.tpl new file mode 100644 index 00000000..5ccd432b --- /dev/null +++ b/includes/oauth-php/example/server/core/templates/logon.tpl @@ -0,0 +1,21 @@ +{include file='inc/header.tpl'} + +

Login

+ +
+ + +
+ + +

+ +
+ + +

+ + +
+ +{include file='inc/footer.tpl'} diff --git a/includes/oauth-php/example/server/core/templates/register.tpl b/includes/oauth-php/example/server/core/templates/register.tpl new file mode 100644 index 00000000..0e28c158 --- /dev/null +++ b/includes/oauth-php/example/server/core/templates/register.tpl @@ -0,0 +1,41 @@ +{include file='inc/header.tpl'} + +

Register server

+ +

Register a server which is gonna act as an identity client.

+ +
+ +
+ About You + +

+
+ +

+ +

+
+ +

+
+ +
+ Location Of Your Application Or Site + +

+
+ +

+ +

+
+ +

+
+ +
+ +
+ +{include file='inc/footer.tpl'} diff --git a/includes/oauth-php/example/server/www/hello.php b/includes/oauth-php/example/server/www/hello.php new file mode 100644 index 00000000..12526a92 --- /dev/null +++ b/includes/oauth-php/example/server/www/hello.php @@ -0,0 +1,65 @@ + + * + * + * 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 '../core/init.php'; + +$authorized = false; +$server = new OAuthServer(); +try +{ + if ($server->verifyIfSigned()) + { + $authorized = true; + } +} +catch (OAuthException2 $e) +{ +} + +if (!$authorized) +{ + header('HTTP/1.1 401 Unauthorized'); + header('Content-Type: text/plain'); + + echo "OAuth Verification Failed: " . $e->getMessage(); + die; +} + +// From here on we are authenticated with OAuth. + +header('Content-type: text/plain'); +echo 'Hello, world!'; + +?> \ No newline at end of file diff --git a/includes/oauth-php/example/server/www/index.php b/includes/oauth-php/example/server/www/index.php new file mode 100644 index 00000000..f5cadbe6 --- /dev/null +++ b/includes/oauth-php/example/server/www/index.php @@ -0,0 +1,37 @@ + + * + * + * 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 '../core/init.php'; + +$smarty = session_smarty(); +$smarty->display('index.tpl'); + +?> diff --git a/includes/oauth-php/example/server/www/logon.php b/includes/oauth-php/example/server/www/logon.php new file mode 100644 index 00000000..5c937b71 --- /dev/null +++ b/includes/oauth-php/example/server/www/logon.php @@ -0,0 +1,55 @@ + + * + * + * 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 '../core/init.php'; + +if (isset($_POST['username']) && isset($_POST['password'])) +{ + if ($_POST['username'] == USERNAME && $_POST['password'] == PASSWORD) + { + $_SESSION['authorized'] = true; + if (!empty($_REQUEST['goto'])) + { + header('Location: ' . $_REQUEST['goto']); + die; + } + + echo "Logon succesfull."; + die; + } +} + +$smarty = session_smarty(); +$smarty->display('logon.tpl'); + +?> \ No newline at end of file diff --git a/includes/oauth-php/example/server/www/oauth.php b/includes/oauth-php/example/server/www/oauth.php new file mode 100644 index 00000000..6dafd61b --- /dev/null +++ b/includes/oauth-php/example/server/www/oauth.php @@ -0,0 +1,77 @@ + + * + * + * 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 '../core/init.php'; + +$server = new OAuthServer(); + +switch($_SERVER['PATH_INFO']) +{ +case '/request_token': + $server->requestToken(); + exit; + +case '/access_token': + $server->accessToken(); + exit; + +case '/authorize': + # logon + + assert_logged_in(); + + try + { + $server->authorizeVerify(); + $server->authorizeFinish(true, 1); + } + catch (OAuthException2 $e) + { + header('HTTP/1.1 400 Bad Request'); + header('Content-Type: text/plain'); + + echo "Failed OAuth Request: " . $e->getMessage(); + } + exit; + + +default: + header('HTTP/1.1 500 Internal Server Error'); + header('Content-Type: text/plain'); + echo "Unknown request"; +} + +?> \ No newline at end of file diff --git a/includes/oauth-php/example/server/www/register.php b/includes/oauth-php/example/server/www/register.php new file mode 100644 index 00000000..0a74297b --- /dev/null +++ b/includes/oauth-php/example/server/www/register.php @@ -0,0 +1,29 @@ +updateConsumer($_POST, $user_id, true); + + $c = $store->getConsumer($key, $user_id); + echo 'Your consumer key is: ' . $c['consumer_key'] . '
'; + echo 'Your consumer secret is: ' . $c['consumer_secret'] . '
'; + } + catch (OAuthException2 $e) + { + echo 'Error: ' . $e->getMessage() . '
'; + } +} + + +$smarty = session_smarty(); +$smarty->display('register.tpl'); + +?> \ No newline at end of file diff --git a/includes/oauth-php/example/server/www/services.xrds.php b/includes/oauth-php/example/server/www/services.xrds.php new file mode 100644 index 00000000..0f4bbac7 --- /dev/null +++ b/includes/oauth-php/example/server/www/services.xrds.php @@ -0,0 +1,71 @@ + + * + * + * 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. + */ + +header('Content-Type: application/xrds+xml'); + +$server = $_SERVER['SERVER_NAME']; + +echo '' . "\n"; + +?> + + + xri://$xrds*simple + + http://oauth.net/discovery/1.0 + #main + + + http://oauth.net/core/1.0/endpoint/request + http://oauth.net/core/1.0/parameters/auth-header + http://oauth.net/core/1.0/parameters/uri-query + http://oauth.net/core/1.0/signature/HMAC-SHA1 + http://oauth.net/core/1.0/signature/PLAINTEXT + http:///oauth/request_token + + + http://oauth.net/core/1.0/endpoint/authorize + http://oauth.net/core/1.0/parameters/uri-query + http:///oauth/authorize + + + http://oauth.net/core/1.0/endpoint/access + http://oauth.net/core/1.0/parameters/auth-header + http://oauth.net/core/1.0/parameters/uri-query + http://oauth.net/core/1.0/signature/HMAC-SHA1 + http://oauth.net/core/1.0/signature/PLAINTEXT + http:///oauth/access_token + + + diff --git a/includes/oauth-php/library/OAuthDiscovery.php b/includes/oauth-php/library/OAuthDiscovery.php new file mode 100644 index 00000000..8eee1187 --- /dev/null +++ b/includes/oauth-php/library/OAuthDiscovery.php @@ -0,0 +1,227 @@ + + * @date Sep 4, 2008 5:05:19 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__).'/discovery/xrds_parse.php'; + +require_once dirname(__FILE__).'/OAuthException2.php'; +require_once dirname(__FILE__).'/OAuthRequestLogger.php'; + + +class OAuthDiscovery +{ + /** + * Return a description how we can do a consumer allocation. Prefers static allocation if + * possible. If static allocation is possible + * + * See also: http://oauth.net/discovery/#consumer_identity_types + * + * @param string uri + * @return array provider description + */ + static function discover ( $uri ) + { + // See what kind of consumer allocations are available + $xrds_file = self::discoverXRDS($uri); + if (!empty($xrds_file)) + { + $xrds = xrds_parse($xrds_file); + if (empty($xrds)) + { + throw new OAuthException2('Could not discover OAuth information for '.$uri); + } + } + else + { + throw new OAuthException2('Could not discover XRDS file at '.$uri); + } + + // Fill an OAuthServer record for the uri found + $ps = parse_url($uri); + $host = isset($ps['host']) ? $ps['host'] : 'localhost'; + $server_uri = $ps['scheme'].'://'.$host.'/'; + + $p = array( + 'user_id' => null, + 'consumer_key' => '', + 'consumer_secret' => '', + 'signature_methods' => '', + 'server_uri' => $server_uri, + 'request_token_uri' => '', + 'authorize_uri' => '', + 'access_token_uri' => '' + ); + + + // Consumer identity (out of bounds or static) + if (isset($xrds['consumer_identity'])) + { + // Try to find a static consumer allocation, we like those :) + foreach ($xrds['consumer_identity'] as $ci) + { + if ($ci['method'] == 'static' && !empty($ci['consumer_key'])) + { + $p['consumer_key'] = $ci['consumer_key']; + $p['consumer_secret'] = ''; + } + else if ($ci['method'] == 'oob' && !empty($ci['uri'])) + { + // TODO: Keep this uri somewhere for the user? + $p['consumer_oob_uri'] = $ci['uri']; + } + } + } + + // The token uris + if (isset($xrds['request'][0]['uri'])) + { + $p['request_token_uri'] = $xrds['request'][0]['uri']; + if (!empty($xrds['request'][0]['signature_method'])) + { + $p['signature_methods'] = $xrds['request'][0]['signature_method']; + } + } + if (isset($xrds['authorize'][0]['uri'])) + { + $p['authorize_uri'] = $xrds['authorize'][0]['uri']; + if (!empty($xrds['authorize'][0]['signature_method'])) + { + $p['signature_methods'] = $xrds['authorize'][0]['signature_method']; + } + } + if (isset($xrds['access'][0]['uri'])) + { + $p['access_token_uri'] = $xrds['access'][0]['uri']; + if (!empty($xrds['access'][0]['signature_method'])) + { + $p['signature_methods'] = $xrds['access'][0]['signature_method']; + } + } + return $p; + } + + + /** + * Discover the XRDS file at the uri. This is a bit primitive, you should overrule + * this function so that the XRDS file can be cached for later referral. + * + * @param string uri + * @return string false when no XRDS file found + */ + static protected function discoverXRDS ( $uri, $recur = 0 ) + { + // Bail out when we are following redirects + if ($recur > 10) + { + return false; + } + + $data = self::curl($uri); + + // Check what we got back, could be: + // 1. The XRDS discovery file itself (check content-type) + // 2. The X-XRDS-Location header + + if (is_string($data) && !empty($data)) + { + list($head,$body) = explode("\r\n\r\n", $data); + $body = trim($body); + $m = false; + + // See if we got the XRDS file itself or we have to follow a location header + if ( preg_match('/^Content-Type:\s*application\/xrds+xml/im', $head) + || preg_match('/^<\?xml[^>]*\?>\s* \ No newline at end of file diff --git a/includes/oauth-php/library/OAuthException2.php b/includes/oauth-php/library/OAuthException2.php new file mode 100644 index 00000000..30fc80e8 --- /dev/null +++ b/includes/oauth-php/library/OAuthException2.php @@ -0,0 +1,50 @@ + + * @date Nov 29, 2007 5:33:54 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. + */ + +// TODO: something with the HTTP return code matching to the problem + +require_once dirname(__FILE__) . '/OAuthRequestLogger.php'; + +class OAuthException2 extends Exception +{ + function __construct ( $message ) + { + Exception::__construct($message); + OAuthRequestLogger::addNote('OAuthException2: '.$message); + } + +} + + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/OAuthRequest.php b/includes/oauth-php/library/OAuthRequest.php new file mode 100644 index 00000000..e37e8369 --- /dev/null +++ b/includes/oauth-php/library/OAuthRequest.php @@ -0,0 +1,846 @@ + + * @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__) . '/OAuthException2.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 = null, $parameters = '', $headers = array(), $body = null ) + { + if (is_object($_SERVER)) + { + // Tainted arrays - the normal stuff in anyMeta + if (!$method) { + $method = $_SERVER->REQUEST_METHOD->getRawUnsafe(); + } + if (empty($uri)) { + $uri = $_SERVER->REQUEST_URI->getRawUnsafe(); + } + } + else + { + // non anyMeta systems + if (!$method) { + if (isset($_SERVER['REQUEST_METHOD'])) { + $method = $_SERVER['REQUEST_METHOD']; + } + else { + $method = 'GET'; + } + } + $proto = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http'; + if (empty($uri)) { + if (strpos($_SERVER['REQUEST_URI'], "://") !== false) { + $uri = $_SERVER['REQUEST_URI']; + } + else { + $uri = sprintf('%s://%s%s', $proto, $_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI']); + } + } + } + $headers = OAuthRequestLogger::getAllHeaders(); + $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') + { + // Get the posted body (when available) + if (!isset($headers['X-OAuth-Test'])) + { + $parameters .= $this->getRequestBodyOfMultipart(); + } + } + 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 + * @param string token_type + * @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 != 'requestToken') + { + $required[] = 'oauth_token'; + } + + foreach ($required as $req) + { + if (!isset($this->param[$req])) + { + throw new OAuthException2('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 OAuthException2 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 OAuthException2 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); + $m2 = preg_replace('/[^A-Z0-9]/', '_', $m); + if (file_exists(dirname(__FILE__).'/signature_method/OAuthSignatureMethod_'.$m2.'.php')) + { + $method = $m; + break; + } + } + + if (empty($method)) + { + throw new OAuthException2('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 OAuthException2('Unsupported signature method "'.$m.'".'); + } + return $sig; + } + + + /** + * Perform some sanity checks. + * + * @exception OAuthException2 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 OAuthException2('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. + * + * @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 + $ps['scheme'] = strtolower($ps['scheme']); + + // Get the current/requested host + if (function_exists('mb_strtolower')) + $ps['host'] = mb_strtolower($ps['host']); + else + $ps['host'] = strtolower($ps['host']); + + if (!preg_match('/^[a-z0-9\.\-]+$/', $ps['host'])) + { + throw new OAuthException2('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); + if (!strlen($name)) + { + continue; + } + + if (array_key_exists($name, $this->param)) + { + if (is_array($this->param[$name])) + $this->param[$name][] = $value; + else + $this->param[$name] = array($this->param[$name], $value); + } + else + { + $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 443; + default: + throw new OAuthException2('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(rawurldecode($s)); + // 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; + } + + /** + * Get the body of a POST with multipart/form-data by Edison tsai on 16:52 2010/09/16 + * + * 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 getRequestBodyOfMultipart() + { + $body = null; + if ($this->method == 'POST') + { + $body = ''; + if (is_array($_POST) && count($_POST) > 1) + { + foreach ($_POST AS $k => $v) { + $body .= $k . '=' . $this->urlencode($v) . '&'; + } #end foreach + if(substr($body,-1) == '&') + { + $body = substr($body, 0, strlen($body)-1); + } #end if + } #end if + } #end if + + 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 OAuthException2 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 OAuthException2('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 diff --git a/includes/oauth-php/library/OAuthRequestLogger.php b/includes/oauth-php/library/OAuthRequestLogger.php new file mode 100644 index 00000000..73076000 --- /dev/null +++ b/includes/oauth-php/library/OAuthRequestLogger.php @@ -0,0 +1,316 @@ + + * @date Dec 7, 2007 12:22:43 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. + */ + +class OAuthRequestLogger +{ + static private $logging = 0; + static private $enable_logging = null; + static private $store_log = null; + static private $note = ''; + static private $user_id = null; + static private $request_object = null; + static private $sent = null; + static private $received = null; + static private $log = array(); + + /** + * Start any logging, checks the system configuration if logging is needed. + * + * @param OAuthRequest $request_object + */ + static function start ( $request_object = null ) + { + if (defined('OAUTH_LOG_REQUEST')) + { + if (is_null(OAuthRequestLogger::$enable_logging)) + { + OAuthRequestLogger::$enable_logging = true; + } + if (is_null(OAuthRequestLogger::$store_log)) + { + OAuthRequestLogger::$store_log = true; + } + } + + if (OAuthRequestLogger::$enable_logging && !OAuthRequestLogger::$logging) + { + OAuthRequestLogger::$logging = true; + OAuthRequestLogger::$request_object = $request_object; + ob_start(); + + // Make sure we flush our log entry when we stop the request (eg on an exception) + register_shutdown_function(array('OAuthRequestLogger','flush')); + } + } + + + /** + * Force logging, needed for performing test connects independent from the debugging setting. + * + * @param boolean store_log (optional) true to store the log in the db + */ + static function enableLogging ( $store_log = null ) + { + OAuthRequestLogger::$enable_logging = true; + if (!is_null($store_log)) + { + OAuthRequestLogger::$store_log = $store_log; + } + } + + + /** + * Logs the request to the database, sends any cached output. + * Also called on shutdown, to make sure we always log the request being handled. + */ + static function flush () + { + if (OAuthRequestLogger::$logging) + { + OAuthRequestLogger::$logging = false; + + if (is_null(OAuthRequestLogger::$sent)) + { + // What has been sent to the user-agent? + $data = ob_get_contents(); + if (strlen($data) > 0) + { + ob_end_flush(); + } + elseif (ob_get_level()) + { + ob_end_clean(); + } + $hs = headers_list(); + $sent = implode("\n", $hs) . "\n\n" . $data; + } + else + { + // The request we sent + $sent = OAuthRequestLogger::$sent; + } + + if (is_null(OAuthRequestLogger::$received)) + { + // Build the request we received + $hs0 = self::getAllHeaders(); + $hs = array(); + foreach ($hs0 as $h => $v) + { + $hs[] = "$h: $v"; + } + + $data = ''; + $fh = @fopen('php://input', 'r'); + if ($fh) + { + while (!feof($fh)) + { + $s = fread($fh, 1024); + if (is_string($s)) + { + $data .= $s; + } + } + fclose($fh); + } + $received = implode("\n", $hs) . "\n\n" . $data; + } + else + { + // The answer we received + $received = OAuthRequestLogger::$received; + } + + // The request base string + if (OAuthRequestLogger::$request_object) + { + $base_string = OAuthRequestLogger::$request_object->signatureBaseString(); + } + else + { + $base_string = ''; + } + + // Figure out to what keys we want to log this request + $keys = array(); + if (OAuthRequestLogger::$request_object) + { + $consumer_key = OAuthRequestLogger::$request_object->getParam('oauth_consumer_key', true); + $token = OAuthRequestLogger::$request_object->getParam('oauth_token', true); + + switch (get_class(OAuthRequestLogger::$request_object)) + { + // tokens are access/request tokens by a consumer + case 'OAuthServer': + case 'OAuthRequestVerifier': + $keys['ocr_consumer_key'] = $consumer_key; + $keys['oct_token'] = $token; + break; + + // tokens are access/request tokens to a server + case 'OAuthRequester': + case 'OAuthRequestSigner': + $keys['osr_consumer_key'] = $consumer_key; + $keys['ost_token'] = $token; + break; + } + } + + // Log the request + if (OAuthRequestLogger::$store_log) + { + $store = OAuthStore::instance(); + $store->addLog($keys, $received, $sent, $base_string, OAuthRequestLogger::$note, OAuthRequestLogger::$user_id); + } + + OAuthRequestLogger::$log[] = array( + 'keys' => $keys, + 'received' => $received, + 'sent' => $sent, + 'base_string' => $base_string, + 'note' => OAuthRequestLogger::$note + ); + } + } + + + /** + * Add a note, used by the OAuthException2 to log all exceptions. + * + * @param string note + */ + static function addNote ( $note ) + { + OAuthRequestLogger::$note .= $note . "\n\n"; + } + + /** + * Set the OAuth request object being used + * + * @param OAuthRequest request_object + */ + static function setRequestObject ( $request_object ) + { + OAuthRequestLogger::$request_object = $request_object; + } + + + /** + * Set the relevant user (defaults to the current user) + * + * @param int user_id + */ + static function setUser ( $user_id ) + { + OAuthRequestLogger::$user_id = $user_id; + } + + + /** + * Set the request we sent + * + * @param string request + */ + static function setSent ( $request ) + { + OAuthRequestLogger::$sent = $request; + } + + /** + * Set the reply we received + * + * @param string request + */ + static function setReceived ( $reply ) + { + OAuthRequestLogger::$received = $reply; + } + + + /** + * Get the the log till now + * + * @return array + */ + static function getLog () + { + return OAuthRequestLogger::$log; + } + + + /** + * helper to try to sort out headers for people who aren't running apache, + * or people who are running PHP as FastCGI. + * + * @return array of request headers as associative array. + */ + public static function getAllHeaders() { + $retarr = array(); + $headers = array(); + + if (function_exists('apache_request_headers')) { + $headers = apache_request_headers(); + ksort($headers); + return $headers; + } else { + $headers = array_merge($_ENV, $_SERVER); + + foreach ($headers as $key => $val) { + //we need this header + if (strpos(strtolower($key), 'content-type') !== FALSE) + continue; + if (strtoupper(substr($key, 0, 5)) != "HTTP_") + unset($headers[$key]); + } + } + + //Normalize this array to Cased-Like-This structure. + foreach ($headers AS $key => $value) { + $key = preg_replace('/^HTTP_/i', '', $key); + $key = str_replace( + " ", + "-", + ucwords(strtolower(str_replace(array("-", "_"), " ", $key))) + ); + $retarr[$key] = $value; + } + ksort($retarr); + + return $retarr; + } +} + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/OAuthRequestSigner.php b/includes/oauth-php/library/OAuthRequestSigner.php new file mode 100644 index 00000000..15c0fd88 --- /dev/null +++ b/includes/oauth-php/library/OAuthRequestSigner.php @@ -0,0 +1,215 @@ + + * @date Nov 16, 2007 4:02:49 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__) . '/OAuthStore.php'; +require_once dirname(__FILE__) . '/OAuthRequest.php'; + + +class OAuthRequestSigner extends OAuthRequest +{ + protected $request; + protected $store; + protected $usr_id = 0; + private $signed = false; + + + /** + * Construct the request to be signed. Parses or appends the parameters in the params url. + * When you supply an params array, then the params should not be urlencoded. + * When you supply a string, then it is assumed it is of the type application/x-www-form-urlencoded + * + * @param string request url + * @param string method PUT, GET, POST etc. + * @param mixed params string (for urlencoded data, or array with name/value pairs) + * @param string body optional body for PUT and/or POST requests + */ + function __construct ( $request, $method = null, $params = null, $body = null ) + { + $this->store = OAuthStore::instance(); + + if (is_string($params)) + { + parent::__construct($request, $method, $params); + } + else + { + parent::__construct($request, $method); + if (is_array($params)) + { + foreach ($params as $name => $value) + { + $this->setParam($name, $value); + } + } + } + + // With put/ post we might have a body (not for application/x-www-form-urlencoded requests) + if (strcasecmp($method, 'PUT') == 0 || strcasecmp($method, 'POST') == 0) + { + $this->setBody($body); + } + } + + + /** + * Reset the 'signed' flag, so that any changes in the parameters force a recalculation + * of the signature. + */ + function setUnsigned () + { + $this->signed = false; + } + + + /** + * Sign our message in the way the server understands. + * Set the needed oauth_xxxx parameters. + * + * @param int usr_id (optional) user that wants to sign this request + * @param array secrets secrets used for signing, when empty then secrets will be fetched from the token registry + * @param string name name of the token to be used for signing + * @exception OAuthException2 when there is no oauth relation with the server + * @exception OAuthException2 when we don't support the signing methods of the server + */ + function sign ( $usr_id = 0, $secrets = null, $name = '', $token_type = null) + { + $url = $this->getRequestUrl(); + if (empty($secrets)) + { + // get the access tokens for the site (on an user by user basis) + $secrets = $this->store->getSecretsForSignature($url, $usr_id, $name); + } + if (empty($secrets)) + { + throw new OAuthException2('No OAuth relation with the server for at "'.$url.'"'); + } + + $signature_method = $this->selectSignatureMethod($secrets['signature_methods']); + + $token = isset($secrets['token']) ? $secrets['token'] : ''; + $token_secret = isset($secrets['token_secret']) ? $secrets['token_secret'] : ''; + + if (!$token) { + $token = $this->getParam('oauth_token'); + } + + $this->setParam('oauth_signature_method',$signature_method); + $this->setParam('oauth_signature', ''); + $this->setParam('oauth_nonce', !empty($secrets['nonce']) ? $secrets['nonce'] : uniqid('')); + $this->setParam('oauth_timestamp', !empty($secrets['timestamp']) ? $secrets['timestamp'] : time()); + if ($token_type != 'requestToken') + $this->setParam('oauth_token', $token); + $this->setParam('oauth_consumer_key', $secrets['consumer_key']); + $this->setParam('oauth_version', '1.0'); + + $body = $this->getBody(); + if (!is_null($body)) + { + // We also need to sign the body, use the default signature method + $body_signature = $this->calculateDataSignature($body, $secrets['consumer_secret'], $token_secret, $signature_method); + $this->setParam('xoauth_body_signature', $body_signature, true); + } + + $signature = $this->calculateSignature($secrets['consumer_secret'], $token_secret, $token_type); + $this->setParam('oauth_signature', $signature, true); + // $this->setParam('oauth_signature', urldecode($signature), true); + + $this->signed = true; + $this->usr_id = $usr_id; + } + + + /** + * Builds the Authorization header for the request. + * Adds all oauth_ and xoauth_ parameters to the Authorization header. + * + * @return string + */ + function getAuthorizationHeader () + { + if (!$this->signed) + { + $this->sign($this->usr_id); + } + $h = array(); + $h[] = 'Authorization: OAuth realm=""'; + foreach ($this->param as $name => $value) + { + if (strncmp($name, 'oauth_', 6) == 0 || strncmp($name, 'xoauth_', 7) == 0) + { + $h[] = $name.'="'.$value.'"'; + } + } + $hs = implode(', ', $h); + return $hs; + } + + + /** + * Builds the application/x-www-form-urlencoded parameter string. Can be appended as + * the query part to a GET or inside the request body for a POST. + * + * @param boolean oauth_as_header (optional) set to false to include oauth parameters + * @return string + */ + function getQueryString ( $oauth_as_header = true ) + { + $parms = array(); + foreach ($this->param as $name => $value) + { + if ( !$oauth_as_header + || (strncmp($name, 'oauth_', 6) != 0 && strncmp($name, 'xoauth_', 7) != 0)) + { + if (is_array($value)) + { + foreach ($value as $v) + { + $parms[] = $name.'='.$v; + } + } + else + { + $parms[] = $name.'='.$value; + } + } + } + return implode('&', $parms); + } + +} + + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/OAuthRequestVerifier.php b/includes/oauth-php/library/OAuthRequestVerifier.php new file mode 100644 index 00000000..a5def757 --- /dev/null +++ b/includes/oauth-php/library/OAuthRequestVerifier.php @@ -0,0 +1,306 @@ + + * @date Nov 16, 2007 4:35:03 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__) . '/OAuthStore.php'; +require_once dirname(__FILE__) . '/OAuthRequest.php'; + + +class OAuthRequestVerifier extends OAuthRequest +{ + private $request; + private $store; + private $accepted_signatures = null; + + /** + * Construct the request to be verified + * + * @param string request + * @param string method + * @param array params The request parameters + */ + function __construct ( $uri = null, $method = null, $params = null ) + { + if ($params) { + $encodedParams = array(); + foreach ($params as $key => $value) { + if (preg_match("/^oauth_/", $key)) { + continue; + } + $encodedParams[rawurlencode($key)] = rawurlencode($value); + } + $this->param = array_merge($this->param, $encodedParams); + } + + $this->store = OAuthStore::instance(); + parent::__construct($uri, $method); + + OAuthRequestLogger::start($this); + } + + + /** + * See if the current request is signed with OAuth + * + * @return boolean + */ + static public function requestIsSigned () + { + if (isset($_REQUEST['oauth_signature'])) + { + $signed = true; + } + else + { + $hs = OAuthRequestLogger::getAllHeaders(); + if (isset($hs['Authorization']) && strpos($hs['Authorization'], 'oauth_signature') !== false) + { + $signed = true; + } + else + { + $signed = false; + } + } + return $signed; + } + + + /** + * Verify the request if it seemed to be signed. + * + * @param string token_type the kind of token needed, defaults to 'access' + * @exception OAuthException2 thrown when the request did not verify + * @return boolean true when signed, false when not signed + */ + public function verifyIfSigned ( $token_type = 'access' ) + { + if ($this->getParam('oauth_consumer_key')) + { + OAuthRequestLogger::start($this); + $this->verify($token_type); + $signed = true; + OAuthRequestLogger::flush(); + } + else + { + $signed = false; + } + return $signed; + } + + + + /** + * Verify the request + * + * @param string token_type the kind of token needed, defaults to 'access' (false, 'access', 'request') + * @exception OAuthException2 thrown when the request did not verify + * @return int user_id associated with token (false when no user associated) + */ + public function verify ( $token_type = 'access' ) + { + $retval = $this->verifyExtended($token_type); + return $retval['user_id']; + } + + + /** + * Verify the request + * + * @param string token_type the kind of token needed, defaults to 'access' (false, 'access', 'request') + * @exception OAuthException2 thrown when the request did not verify + * @return array ('user_id' => associated with token (false when no user associated), + * 'consumer_key' => the associated consumer_key) + * + */ + public function verifyExtended ( $token_type = 'access' ) + { + $consumer_key = $this->getParam('oauth_consumer_key'); + $token = $this->getParam('oauth_token'); + $user_id = false; + $secrets = array(); + + if ($consumer_key && ($token_type === false || $token)) + { + $secrets = $this->store->getSecretsForVerify( $this->urldecode($consumer_key), + $this->urldecode($token), + $token_type); + + $this->store->checkServerNonce( $this->urldecode($consumer_key), + $this->urldecode($token), + $this->getParam('oauth_timestamp', true), + $this->getParam('oauth_nonce', true)); + + $oauth_sig = $this->getParam('oauth_signature'); + if (empty($oauth_sig)) + { + throw new OAuthException2('Verification of signature failed (no oauth_signature in request).'); + } + + try + { + $this->verifySignature($secrets['consumer_secret'], $secrets['token_secret'], $token_type); + } + catch (OAuthException2 $e) + { + throw new OAuthException2('Verification of signature failed (signature base string was "'.$this->signatureBaseString().'").' + . " with " . print_r(array($secrets['consumer_secret'], $secrets['token_secret'], $token_type), true)); + } + + // Check the optional body signature + if ($this->getParam('xoauth_body_signature')) + { + $method = $this->getParam('xoauth_body_signature_method'); + if (empty($method)) + { + $method = $this->getParam('oauth_signature_method'); + } + + try + { + $this->verifyDataSignature($this->getBody(), $secrets['consumer_secret'], $secrets['token_secret'], $method, $this->getParam('xoauth_body_signature')); + } + catch (OAuthException2 $e) + { + throw new OAuthException2('Verification of body signature failed.'); + } + } + + // All ok - fetch the user associated with this request + if (isset($secrets['user_id'])) + { + $user_id = $secrets['user_id']; + } + + // Check if the consumer wants us to reset the ttl of this token + $ttl = $this->getParam('xoauth_token_ttl', true); + if (is_numeric($ttl)) + { + $this->store->setConsumerAccessTokenTtl($this->urldecode($token), $ttl); + } + } + else + { + throw new OAuthException2('Can\'t verify request, missing oauth_consumer_key or oauth_token'); + } + return array('user_id' => $user_id, 'consumer_key' => $consumer_key, 'osr_id' => $secrets['osr_id']); + } + + + + /** + * Verify 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 OAuthException2 thrown when the signature method is unknown + * @exception OAuthException2 when not all parts available + * @exception OAuthException2 when signature does not match + */ + public function verifySignature ( $consumer_secret, $token_secret, $token_type = 'access' ) + { + $required = array( + 'oauth_consumer_key', + 'oauth_signature_method', + 'oauth_timestamp', + 'oauth_nonce', + 'oauth_signature' + ); + + if ($token_type !== false) + { + $required[] = 'oauth_token'; + } + + foreach ($required as $req) + { + if (!isset($this->param[$req])) + { + throw new OAuthException2('Can\'t verify request signature, missing parameter "'.$req.'"'); + } + } + + $this->checks(); + + $base = $this->signatureBaseString(); + $this->verifyDataSignature($base, $consumer_secret, $token_secret, $this->param['oauth_signature_method'], $this->param['oauth_signature']); + } + + + + /** + * Verify the signature of a string. + * + * @param string data + * @param string consumer_secret + * @param string token_secret + * @param string signature_method + * @param string signature + * @exception OAuthException2 thrown when the signature method is unknown + * @exception OAuthException2 when signature does not match + */ + public function verifyDataSignature ( $data, $consumer_secret, $token_secret, $signature_method, $signature ) + { + if (is_null($data)) + { + $data = ''; + } + + $sig = $this->getSignatureMethod($signature_method); + if (!$sig->verify($this, $data, $consumer_secret, $token_secret, $signature)) + { + throw new OAuthException2('Signature verification failed ('.$signature_method.')'); + } + } + + /** + * + * @param array $accepted The array of accepted signature methods, or if null is passed + * all supported methods are accepted and there is no filtering. + * + */ + public function setAcceptedSignatureMethods($accepted = null) { + if (is_array($accepted)) + $this->accepted_signatures = $accepted; + else if ($accepted == null) + $this->accepted_signatures = null; + } +} + + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/OAuthRequester.php b/includes/oauth-php/library/OAuthRequester.php new file mode 100644 index 00000000..98f720d2 --- /dev/null +++ b/includes/oauth-php/library/OAuthRequester.php @@ -0,0 +1,521 @@ + + * @date Nov 20, 2007 1:41:38 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__) . '/OAuthRequestSigner.php'; +require_once dirname(__FILE__) . '/body/OAuthBodyContentDisposition.php'; + + +class OAuthRequester extends OAuthRequestSigner +{ + protected $files; + + /** + * Construct a new request signer. Perform the request with the doRequest() method below. + * + * A request can have either one file or a body, not both. + * + * The files array consists of arrays: + * - file the filename/path containing the data for the POST/PUT + * - data data for the file, omit when you have a file + * - mime content-type of the file + * - filename filename for content disposition header + * + * When OAuth (and PHP) can support multipart/form-data then we can handle more than one file. + * For now max one file, with all the params encoded in the query string. + * + * @param string request + * @param string method http method. GET, PUT, POST etc. + * @param array params name=>value array with request parameters + * @param string body optional body to send + * @param array files optional files to send (max 1 till OAuth support multipart/form-data posts) + */ + function __construct ( $request, $method = null, $params = null, $body = null, $files = null ) + { + parent::__construct($request, $method, $params, $body); + + // When there are files, then we can construct a POST with a single file + if (!empty($files)) + { + $empty = true; + foreach ($files as $f) + { + $empty = $empty && empty($f['file']) && !isset($f['data']); + } + + if (!$empty) + { + if (!is_null($body)) + { + throw new OAuthException2('When sending files, you can\'t send a body as well.'); + } + $this->files = $files; + } + } + } + + + /** + * Perform the request, returns the response code, headers and body. + * + * @param int usr_id optional user id for which we make the request + * @param array curl_options optional extra options for curl request + * @param array options options like name and token_ttl + * @exception OAuthException2 when authentication not accepted + * @exception OAuthException2 when signing was not possible + * @return array (code=>int, headers=>array(), body=>string) + */ + function doRequest ( $usr_id = 0, $curl_options = array(), $options = array() ) + { + $name = isset($options['name']) ? $options['name'] : ''; + if (isset($options['token_ttl'])) + { + $this->setParam('xoauth_token_ttl', intval($options['token_ttl'])); + } + + if (!empty($this->files)) + { + // At the moment OAuth does not support multipart/form-data, so try to encode + // the supplied file (or data) as the request body and add a content-disposition header. + list($extra_headers, $body) = OAuthBodyContentDisposition::encodeBody($this->files); + $this->setBody($body); + $curl_options = $this->prepareCurlOptions($curl_options, $extra_headers); + } + $this->sign($usr_id, null, $name); + $text = $this->curl_raw($curl_options); + $result = $this->curl_parse($text); + if ($result['code'] >= 400) + { + throw new OAuthException2('Request failed with code ' . $result['code'] . ': ' . $result['body']); + } + + // Record the token time to live for this server access token, immediate delete iff ttl <= 0 + // Only done on a succesful request. + $token_ttl = $this->getParam('xoauth_token_ttl', false); + if (is_numeric($token_ttl)) + { + $this->store->setServerTokenTtl($this->getParam('oauth_consumer_key',true), $this->getParam('oauth_token',true), $token_ttl); + } + + return $result; + } + + + /** + * Request a request token from the site belonging to consumer_key + * + * @param string consumer_key + * @param int usr_id + * @param array params (optional) extra arguments for when requesting the request token + * @param string method (optional) change the method of the request, defaults to POST (as it should be) + * @param array options (optional) options like name and token_ttl + * @param array curl_options optional extra options for curl request + * @exception OAuthException2 when no key could be fetched + * @exception OAuthException2 when no server with consumer_key registered + * @return array (authorize_uri, token) + */ + static function requestRequestToken ( $consumer_key, $usr_id, $params = null, $method = 'POST', $options = array(), $curl_options = array()) + { + OAuthRequestLogger::start(); + + if (isset($options['token_ttl']) && is_numeric($options['token_ttl'])) + { + $params['xoauth_token_ttl'] = intval($options['token_ttl']); + } + + $store = OAuthStore::instance(); + $r = $store->getServer($consumer_key, $usr_id); + $uri = $r['request_token_uri']; + + $oauth = new OAuthRequester($uri, $method, $params); + $oauth->sign($usr_id, $r, '', 'requestToken'); + $text = $oauth->curl_raw($curl_options); + + if (empty($text)) + { + throw new OAuthException2('No answer from the server "'.$uri.'" while requesting a request token'); + } + $data = $oauth->curl_parse($text); + if ($data['code'] != 200) + { + throw new OAuthException2('Unexpected result from the server "'.$uri.'" ('.$data['code'].') while requesting a request token'); + } + $token = array(); + $params = explode('&', $data['body']); + foreach ($params as $p) + { + @list($name, $value) = explode('=', $p, 2); + $token[$name] = $oauth->urldecode($value); + } + + if (!empty($token['oauth_token']) && !empty($token['oauth_token_secret'])) + { + $opts = array(); + if (isset($options['name'])) + { + $opts['name'] = $options['name']; + } + if (isset($token['xoauth_token_ttl'])) + { + $opts['token_ttl'] = $token['xoauth_token_ttl']; + } + $store->addServerToken($consumer_key, 'request', $token['oauth_token'], $token['oauth_token_secret'], $usr_id, $opts); + } + else + { + throw new OAuthException2('The server "'.$uri.'" did not return the oauth_token or the oauth_token_secret'); + } + + OAuthRequestLogger::flush(); + + // Now we can direct a browser to the authorize_uri + return array( + 'authorize_uri' => $r['authorize_uri'], + 'token' => $token['oauth_token'] + ); + } + + + /** + * Request an access token from the site belonging to consumer_key. + * Before this we got an request token, now we want to exchange it for + * an access token. + * + * @param string consumer_key + * @param string token + * @param int usr_id user requesting the access token + * @param string method (optional) change the method of the request, defaults to POST (as it should be) + * @param array options (optional) extra options for request, eg token_ttl + * @param array curl_options optional extra options for curl request + * + * @exception OAuthException2 when no key could be fetched + * @exception OAuthException2 when no server with consumer_key registered + */ + static function requestAccessToken ( $consumer_key, $token, $usr_id, $method = 'POST', $options = array(), $curl_options = array() ) + { + OAuthRequestLogger::start(); + + $store = OAuthStore::instance(); + $r = $store->getServerTokenSecrets($consumer_key, $token, 'request', $usr_id); + $uri = $r['access_token_uri']; + $token_name = $r['token_name']; + + // Delete the server request token, this one was for one use only + $store->deleteServerToken($consumer_key, $r['token'], 0, true); + + // Try to exchange our request token for an access token + $oauth = new OAuthRequester($uri, $method); + + if (isset($options['oauth_verifier'])) + { + $oauth->setParam('oauth_verifier', $options['oauth_verifier']); + } + if (isset($options['token_ttl']) && is_numeric($options['token_ttl'])) + { + $oauth->setParam('xoauth_token_ttl', intval($options['token_ttl'])); + } + + OAuthRequestLogger::setRequestObject($oauth); + + $oauth->sign($usr_id, $r, '', 'accessToken'); + $text = $oauth->curl_raw($curl_options); + if (empty($text)) + { + throw new OAuthException2('No answer from the server "'.$uri.'" while requesting an access token'); + } + $data = $oauth->curl_parse($text); + + if ($data['code'] != 200) + { + throw new OAuthException2('Unexpected result from the server "'.$uri.'" ('.$data['code'].') while requesting an access token'); + } + + $token = array(); + $params = explode('&', $data['body']); + foreach ($params as $p) + { + @list($name, $value) = explode('=', $p, 2); + $token[$oauth->urldecode($name)] = $oauth->urldecode($value); + } + + if (!empty($token['oauth_token']) && !empty($token['oauth_token_secret'])) + { + $opts = array(); + $opts['name'] = $token_name; + if (isset($token['xoauth_token_ttl'])) + { + $opts['token_ttl'] = $token['xoauth_token_ttl']; + } + $store->addServerToken($consumer_key, 'access', $token['oauth_token'], $token['oauth_token_secret'], $usr_id, $opts); + } + else + { + throw new OAuthException2('The server "'.$uri.'" did not return the oauth_token or the oauth_token_secret'); + } + + OAuthRequestLogger::flush(); + } + + + + /** + * Open and close a curl session passing all the options to the curl libs + * + * @param array opts the curl options. + * @exception OAuthException2 when temporary file for PUT operation could not be created + * @return string the result of the curl action + */ + protected function curl_raw ( $opts = array() ) + { + if (isset($opts[CURLOPT_HTTPHEADER])) + { + $header = $opts[CURLOPT_HTTPHEADER]; + } + else + { + $header = array(); + } + + $ch = curl_init(); + $method = $this->getMethod(); + $url = $this->getRequestUrl(); + $header[] = $this->getAuthorizationHeader(); + $query = $this->getQueryString(); + $body = $this->getBody(); + + $has_content_type = false; + foreach ($header as $h) + { + if (strncasecmp($h, 'Content-Type:', 13) == 0) + { + $has_content_type = true; + } + } + + if (!is_null($body)) + { + if ($method == 'TRACE') + { + throw new OAuthException2('A body can not be sent with a TRACE operation'); + } + + // PUT and POST allow a request body + if (!empty($query)) + { + $url .= '?'.$query; + } + + // Make sure that the content type of the request is ok + if (!$has_content_type) + { + $header[] = 'Content-Type: application/octet-stream'; + $has_content_type = true; + } + + // When PUTting, we need to use an intermediate file (because of the curl implementation) + if ($method == 'PUT') + { + /* + if (version_compare(phpversion(), '5.2.0') >= 0) + { + // Use the data wrapper to create the file expected by the put method + $put_file = fopen('data://application/octet-stream;base64,'.base64_encode($body)); + } + */ + + $put_file = @tmpfile(); + if (!$put_file) + { + throw new OAuthException2('Could not create tmpfile for PUT operation'); + } + fwrite($put_file, $body); + fseek($put_file, 0); + + curl_setopt($ch, CURLOPT_PUT, true); + curl_setopt($ch, CURLOPT_INFILE, $put_file); + curl_setopt($ch, CURLOPT_INFILESIZE, strlen($body)); + } + else + { + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $body); + } + } + else + { + // a 'normal' request, no body to be send + if ($method == 'POST') + { + if (!$has_content_type) + { + $header[] = 'Content-Type: application/x-www-form-urlencoded'; + $has_content_type = true; + } + + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $query); + } + else + { + if (!empty($query)) + { + $url .= '?'.$query; + } + if ($method != 'GET') + { + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); + } + } + } + + curl_setopt($ch, CURLOPT_HTTPHEADER, $header); + curl_setopt($ch, CURLOPT_USERAGENT, 'anyMeta/OAuth 1.0 - ($LastChangedRevision: 174 $)'); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HEADER, true); + curl_setopt($ch, CURLOPT_TIMEOUT, 30); + + foreach ($opts as $k => $v) + { + if ($k != CURLOPT_HTTPHEADER) + { + curl_setopt($ch, $k, $v); + } + } + + $txt = curl_exec($ch); + if ($txt === false) { + $error = curl_error($ch); + curl_close($ch); + throw new OAuthException2('CURL error: ' . $error); + } + curl_close($ch); + + if (!empty($put_file)) + { + fclose($put_file); + } + + // Tell the logger what we requested and what we received back + $data = $method . " $url\n".implode("\n",$header); + if (is_string($body)) + { + $data .= "\n\n".$body; + } + else if ($method == 'POST') + { + $data .= "\n\n".$query; + } + + OAuthRequestLogger::setSent($data, $body); + OAuthRequestLogger::setReceived($txt); + + return $txt; + } + + + /** + * Parse an http response + * + * @param string response the http text to parse + * @return array (code=>http-code, headers=>http-headers, body=>body) + */ + protected function curl_parse ( $response ) + { + if (empty($response)) + { + return array(); + } + + @list($headers,$body) = explode("\r\n\r\n",$response,2); + $lines = explode("\r\n",$headers); + + if (preg_match('@^HTTP/[0-9]\.[0-9] +100@', $lines[0])) + { + /* HTTP/1.x 100 Continue + * the real data is on the next line + */ + @list($headers,$body) = explode("\r\n\r\n",$body,2); + $lines = explode("\r\n",$headers); + } + + // first line of headers is the HTTP response code + $http_line = array_shift($lines); + if (preg_match('@^HTTP/[0-9]\.[0-9] +([0-9]{3})@', $http_line, $matches)) + { + $code = $matches[1]; + } + + // put the rest of the headers in an array + $headers = array(); + foreach ($lines as $l) + { + list($k, $v) = explode(': ', $l, 2); + $headers[strtolower($k)] = $v; + } + + return array( 'code' => $code, 'headers' => $headers, 'body' => $body); + } + + + /** + * Mix the given headers into the headers that were given to curl + * + * @param array curl_options + * @param array extra_headers + * @return array new curl options + */ + protected function prepareCurlOptions ( $curl_options, $extra_headers ) + { + $hs = array(); + if (!empty($curl_options[CURLOPT_HTTPHEADER]) && is_array($curl_options[CURLOPT_HTTPHEADER])) + { + foreach ($curl_options[CURLOPT_HTTPHEADER] as $h) + { + list($opt, $val) = explode(':', $h, 2); + $opt = str_replace(' ', '-', ucwords(str_replace('-', ' ', $opt))); + $hs[$opt] = $val; + } + } + + $curl_options[CURLOPT_HTTPHEADER] = array(); + $hs = array_merge($hs, $extra_headers); + foreach ($hs as $h => $v) + { + $curl_options[CURLOPT_HTTPHEADER][] = "$h: $v"; + } + return $curl_options; + } +} + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/OAuthServer.php b/includes/oauth-php/library/OAuthServer.php new file mode 100644 index 00000000..995ebc5c --- /dev/null +++ b/includes/oauth-php/library/OAuthServer.php @@ -0,0 +1,333 @@ + + * @date Nov 27, 2007 12:36:38 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 'OAuthRequestVerifier.php'; +require_once 'OAuthSession.php'; + +class OAuthServer extends OAuthRequestVerifier +{ + protected $session; + + protected $allowed_uri_schemes = array( + 'http', + 'https' + ); + + protected $disallowed_uri_schemes = array( + 'file', + 'callto', + 'mailto' + ); + + /** + * Construct the request to be verified + * + * @param string request + * @param string method + * @param array params The request parameters + * @param string store The session storage class. + * @param array store_options The session storage class parameters. + * @param array options Extra options: + * - allowed_uri_schemes: list of allowed uri schemes. + * - disallowed_uri_schemes: list of unallowed uri schemes. + * + * e.g. Allow only http and https + * $options = array( + * 'allowed_uri_schemes' => array('http', 'https'), + * 'disallowed_uri_schemes' => array() + * ); + * + * e.g. Disallow callto, mailto and file, allow everything else + * $options = array( + * 'allowed_uri_schemes' => array(), + * 'disallowed_uri_schemes' => array('callto', 'mailto', 'file') + * ); + * + * e.g. Allow everything + * $options = array( + * 'allowed_uri_schemes' => array(), + * 'disallowed_uri_schemes' => array() + * ); + * + */ + function __construct ( $uri = null, $method = null, $params = null, $store = 'SESSION', + $store_options = array(), $options = array() ) + { + parent::__construct($uri, $method, $params); + $this->session = OAuthSession::instance($store, $store_options); + + if (array_key_exists('allowed_uri_schemes', $options) && is_array($options['allowed_uri_schemes'])) { + $this->allowed_uri_schemes = $options['allowed_uri_schemes']; + } + if (array_key_exists('disallowed_uri_schemes', $options) && is_array($options['disallowed_uri_schemes'])) { + $this->disallowed_uri_schemes = $options['disallowed_uri_schemes']; + } + } + + /** + * Handle the request_token request. + * Returns the new request token and request token secret. + * + * TODO: add correct result code to exception + * + * @return string returned request token, false on an error + */ + public function requestToken () + { + OAuthRequestLogger::start($this); + try + { + $this->verify(false); + + $options = array(); + $ttl = $this->getParam('xoauth_token_ttl', false); + if ($ttl) + { + $options['token_ttl'] = $ttl; + } + + // 1.0a Compatibility : associate callback url to the request token + $cbUrl = $this->getParam('oauth_callback', true); + if ($cbUrl) { + $options['oauth_callback'] = $cbUrl; + } + + // Create a request token + $store = OAuthStore::instance(); + $token = $store->addConsumerRequestToken($this->getParam('oauth_consumer_key', true), $options); + $result = 'oauth_callback_confirmed=1&oauth_token='.$this->urlencode($token['token']) + .'&oauth_token_secret='.$this->urlencode($token['token_secret']); + + if (!empty($token['token_ttl'])) + { + $result .= '&xoauth_token_ttl='.$this->urlencode($token['token_ttl']); + } + + $request_token = $token['token']; + + header('HTTP/1.1 200 OK'); + header('Content-Length: '.strlen($result)); + header('Content-Type: application/x-www-form-urlencoded'); + + echo $result; + } + catch (OAuthException2 $e) + { + $request_token = false; + + header('HTTP/1.1 401 Unauthorized'); + header('Content-Type: text/plain'); + + echo "OAuth Verification Failed: " . $e->getMessage(); + } + + OAuthRequestLogger::flush(); + return $request_token; + } + + + /** + * Verify the start of an authorization request. Verifies if the request token is valid. + * Next step is the method authorizeFinish() + * + * Nota bene: this stores the current token, consumer key and callback in the _SESSION + * + * @exception OAuthException2 thrown when not a valid request + * @return array token description + */ + public function authorizeVerify () + { + OAuthRequestLogger::start($this); + + $store = OAuthStore::instance(); + $token = $this->getParam('oauth_token', true); + $rs = $store->getConsumerRequestToken($token); + if (empty($rs)) + { + throw new OAuthException2('Unknown request token "'.$token.'"'); + } + + // We need to remember the callback + $verify_oauth_token = $this->session->get('verify_oauth_token'); + if ( empty($verify_oauth_token) + || strcmp($verify_oauth_token, $rs['token'])) + { + $this->session->set('verify_oauth_token', $rs['token']); + $this->session->set('verify_oauth_consumer_key', $rs['consumer_key']); + $cb = $this->getParam('oauth_callback', true); + if ($cb) + $this->session->set('verify_oauth_callback', $cb); + else + $this->session->set('verify_oauth_callback', $rs['callback_url']); + } + OAuthRequestLogger::flush(); + return $rs; + } + + + /** + * Overrule this method when you want to display a nice page when + * the authorization is finished. This function does not know if the authorization was + * succesfull, you need to check the token in the database. + * + * @param boolean authorized if the current token (oauth_token param) is authorized or not + * @param int user_id user for which the token was authorized (or denied) + * @return string verifier For 1.0a Compatibility + */ + public function authorizeFinish ( $authorized, $user_id ) + { + OAuthRequestLogger::start($this); + + $token = $this->getParam('oauth_token', true); + $verifier = null; + if ($this->session->get('verify_oauth_token') == $token) + { + // Flag the token as authorized, or remove the token when not authorized + $store = OAuthStore::instance(); + + // Fetch the referrer host from the oauth callback parameter + $referrer_host = ''; + $oauth_callback = false; + $verify_oauth_callback = $this->session->get('verify_oauth_callback'); + if (!empty($verify_oauth_callback) && $verify_oauth_callback != 'oob') // OUT OF BAND + { + $oauth_callback = $this->session->get('verify_oauth_callback'); + $ps = parse_url($oauth_callback); + if (isset($ps['host'])) + { + $referrer_host = $ps['host']; + } + } + + if ($authorized) + { + OAuthRequestLogger::addNote('Authorized token "'.$token.'" for user '.$user_id.' with referrer "'.$referrer_host.'"'); + // 1.0a Compatibility : create a verifier code + $verifier = $store->authorizeConsumerRequestToken($token, $user_id, $referrer_host); + } + else + { + OAuthRequestLogger::addNote('Authorization rejected for token "'.$token.'" for user '.$user_id."\nToken has been deleted"); + $store->deleteConsumerRequestToken($token); + } + + if (!empty($oauth_callback)) + { + $params = array('oauth_token' => rawurlencode($token)); + // 1.0a Compatibility : if verifier code has been generated, add it to the URL + if ($verifier) { + $params['oauth_verifier'] = $verifier; + } + + $uri = preg_replace('/\s/', '%20', $oauth_callback); + if (!empty($this->allowed_uri_schemes)) + { + if (!in_array(substr($uri, 0, strpos($uri, '://')), $this->allowed_uri_schemes)) + { + throw new OAuthException2('Illegal protocol in redirect uri '.$uri); + } + } + else if (!empty($this->disallowed_uri_schemes)) + { + if (in_array(substr($uri, 0, strpos($uri, '://')), $this->disallowed_uri_schemes)) + { + throw new OAuthException2('Illegal protocol in redirect uri '.$uri); + } + } + + $this->redirect($oauth_callback, $params); + } + } + OAuthRequestLogger::flush(); + return $verifier; + } + + + /** + * Exchange a request token for an access token. + * The exchange is only succesful iff the request token has been authorized. + * + * Never returns, calls exit() when token is exchanged or when error is returned. + */ + public function accessToken () + { + OAuthRequestLogger::start($this); + + try + { + $this->verify('request'); + + $options = array(); + $ttl = $this->getParam('xoauth_token_ttl', false); + if ($ttl) + { + $options['token_ttl'] = $ttl; + } + + $verifier = $this->getParam('oauth_verifier', false); + if ($verifier) { + $options['verifier'] = $verifier; + } + + $store = OAuthStore::instance(); + $token = $store->exchangeConsumerRequestForAccessToken($this->getParam('oauth_token', true), $options); + $result = 'oauth_token='.$this->urlencode($token['token']) + .'&oauth_token_secret='.$this->urlencode($token['token_secret']); + + if (!empty($token['token_ttl'])) + { + $result .= '&xoauth_token_ttl='.$this->urlencode($token['token_ttl']); + } + + header('HTTP/1.1 200 OK'); + header('Content-Length: '.strlen($result)); + header('Content-Type: application/x-www-form-urlencoded'); + + echo $result; + } + catch (OAuthException2 $e) + { + header('HTTP/1.1 401 Access Denied'); + header('Content-Type: text/plain'); + + echo "OAuth Verification Failed: " . $e->getMessage(); + } + + OAuthRequestLogger::flush(); + exit(); + } +} + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/OAuthSession.php b/includes/oauth-php/library/OAuthSession.php new file mode 100644 index 00000000..80ceeb73 --- /dev/null +++ b/includes/oauth-php/library/OAuthSession.php @@ -0,0 +1,86 @@ + \ No newline at end of file diff --git a/includes/oauth-php/library/OAuthStore.php b/includes/oauth-php/library/OAuthStore.php new file mode 100644 index 00000000..d3df3a0a --- /dev/null +++ b/includes/oauth-php/library/OAuthStore.php @@ -0,0 +1,86 @@ + + * @date Nov 16, 2007 4:03:30 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__) . '/OAuthException2.php'; + +class OAuthStore +{ + static private $instance = false; + + /** + * Request an instance of the OAuthStore + */ + public static function instance ( $store = 'MySQL', $options = array() ) + { + if (!OAuthStore::$instance) + { + // Select the store you want to use + if (strpos($store, '/') === false) + { + $class = 'OAuthStore'.$store; + $file = dirname(__FILE__) . '/store/'.$class.'.php'; + } + else + { + $file = $store; + $store = basename($file, '.php'); + $class = $store; + } + + if (is_file($file)) + { + require_once $file; + + if (class_exists($class)) + { + OAuthStore::$instance = new $class($options); + } + else + { + throw new OAuthException2('Could not find class '.$class.' in file '.$file); + } + } + else + { + throw new OAuthException2('No OAuthStore for '.$store.' (file '.$file.')'); + } + } + return OAuthStore::$instance; + } +} + + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/body/OAuthBodyContentDisposition.php b/includes/oauth-php/library/body/OAuthBodyContentDisposition.php new file mode 100644 index 00000000..02b1e427 --- /dev/null +++ b/includes/oauth-php/library/body/OAuthBodyContentDisposition.php @@ -0,0 +1,129 @@ + + * + * 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. + */ + +class OAuthBodyContentDisposition +{ + /** + * Builds the request string. + * + * The files array can be a combination of the following (either data or file): + * + * file => "path/to/file", filename=, mime=, data= + * + * @param array files (name => filedesc) (not urlencoded) + * @return array (headers, body) + */ + static function encodeBody ( $files ) + { + $headers = array(); + $body = null; + + // 1. Add all the files to the post + if (!empty($files)) + { + foreach ($files as $name => $f) + { + $data = false; + $filename = false; + + if (isset($f['filename'])) + { + $filename = $f['filename']; + } + + if (!empty($f['file'])) + { + $data = @file_get_contents($f['file']); + if ($data === false) + { + throw new OAuthException2(sprintf('Could not read the file "%s" for request body', $f['file'])); + } + if (empty($filename)) + { + $filename = basename($f['file']); + } + } + else if (isset($f['data'])) + { + $data = $f['data']; + } + + // When there is data, add it as a request body, otherwise silently skip the upload + if ($data !== false) + { + if (isset($headers['Content-Disposition'])) + { + throw new OAuthException2('Only a single file (or data) allowed in a signed PUT/POST request body.'); + } + + if (empty($filename)) + { + $filename = 'untitled'; + } + $mime = !empty($f['mime']) ? $f['mime'] : 'application/octet-stream'; + + $headers['Content-Disposition'] = 'attachment; filename="'.OAuthBodyContentDisposition::encodeParameterName($filename).'"'; + $headers['Content-Type'] = $mime; + + $body = $data; + } + + } + + // When we have a body, add the content-length + if (!is_null($body)) + { + $headers['Content-Length'] = strlen($body); + } + } + return array($headers, $body); + } + + + /** + * Encode a parameter's name for use in a multipart header. + * For now we do a simple filter that removes some unwanted characters. + * We might want to implement RFC1522 here. See http://tools.ietf.org/html/rfc1522 + * + * @param string name + * @return string + */ + static function encodeParameterName ( $name ) + { + return preg_replace('/[^\x20-\x7f]|"/', '-', $name); + } +} + + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/body/OAuthBodyMultipartFormdata.php b/includes/oauth-php/library/body/OAuthBodyMultipartFormdata.php new file mode 100644 index 00000000..a869e1e6 --- /dev/null +++ b/includes/oauth-php/library/body/OAuthBodyMultipartFormdata.php @@ -0,0 +1,143 @@ + + * @date Jan 31, 2008 12:50:05 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. + */ + + +class OAuthBodyMultipartFormdata +{ + /** + * Builds the request string. + * + * The files array can be a combination of the following (either data or file): + * + * file => "path/to/file", filename=, mime=, data= + * + * @param array params (name => value) (all names and values should be urlencoded) + * @param array files (name => filedesc) (not urlencoded) + * @return array (headers, body) + */ + static function encodeBody ( $params, $files ) + { + $headers = array(); + $body = ''; + $boundary = 'OAuthRequester_'.md5(uniqid('multipart') . microtime()); + $headers['Content-Type'] = 'multipart/form-data; boundary=' . $boundary; + + + // 1. Add the parameters to the post + if (!empty($params)) + { + foreach ($params as $name => $value) + { + $body .= '--'.$boundary."\r\n"; + $body .= 'Content-Disposition: form-data; name="'.OAuthBodyMultipartFormdata::encodeParameterName(rawurldecode($name)).'"'; + $body .= "\r\n\r\n"; + $body .= urldecode($value); + $body .= "\r\n"; + } + } + + // 2. Add all the files to the post + if (!empty($files)) + { + $untitled = 1; + + foreach ($files as $name => $f) + { + $data = false; + $filename = false; + + if (isset($f['filename'])) + { + $filename = $f['filename']; + } + + if (!empty($f['file'])) + { + $data = @file_get_contents($f['file']); + if ($data === false) + { + throw new OAuthException2(sprintf('Could not read the file "%s" for form-data part', $f['file'])); + } + if (empty($filename)) + { + $filename = basename($f['file']); + } + } + else if (isset($f['data'])) + { + $data = $f['data']; + } + + // When there is data, add it as a form-data part, otherwise silently skip the upload + if ($data !== false) + { + if (empty($filename)) + { + $filename = sprintf('untitled-%d', $untitled++); + } + $mime = !empty($f['mime']) ? $f['mime'] : 'application/octet-stream'; + $body .= '--'.$boundary."\r\n"; + $body .= 'Content-Disposition: form-data; name="'.OAuthBodyMultipartFormdata::encodeParameterName($name).'"; filename="'.OAuthBodyMultipartFormdata::encodeParameterName($filename).'"'."\r\n"; + $body .= 'Content-Type: '.$mime; + $body .= "\r\n\r\n"; + $body .= $data; + $body .= "\r\n"; + } + + } + } + $body .= '--'.$boundary."--\r\n"; + + $headers['Content-Length'] = strlen($body); + return array($headers, $body); + } + + + /** + * Encode a parameter's name for use in a multipart header. + * For now we do a simple filter that removes some unwanted characters. + * We might want to implement RFC1522 here. See http://tools.ietf.org/html/rfc1522 + * + * @param string name + * @return string + */ + static function encodeParameterName ( $name ) + { + return preg_replace('/[^\x20-\x7f]|"/', '-', $name); + } +} + + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/discovery/xrds_parse.php b/includes/oauth-php/library/discovery/xrds_parse.php new file mode 100644 index 00000000..c9cf9499 --- /dev/null +++ b/includes/oauth-php/library/discovery/xrds_parse.php @@ -0,0 +1,304 @@ + + * + * + * 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. + */ + +/* example of use: + +header('content-type: text/plain'); +$file = file_get_contents('../../test/discovery/xrds-magnolia.xrds'); +$xrds = xrds_parse($file); +print_r($xrds); + + */ + +/** + * Parse the xrds file in the argument. The xrds description must have been + * fetched via curl or something else. + * + * TODO: more robust checking, support for more service documents + * TODO: support for URIs to definition instead of local xml:id + * + * @param string data contents of xrds file + * @exception Exception when the file is in an unknown format + * @return array + */ +function xrds_parse ( $data ) +{ + $oauth = array(); + $doc = @DOMDocument::loadXML($data); + if ($doc === false) + { + throw new Exception('Error in XML, can\'t load XRDS document'); + } + + $xpath = new DOMXPath($doc); + $xpath->registerNamespace('xrds', 'xri://$xrds'); + $xpath->registerNamespace('xrd', 'xri://$XRD*($v*2.0)'); + $xpath->registerNamespace('simple', 'http://xrds-simple.net/core/1.0'); + + // Yahoo! uses this namespace, with lowercase xrd in it + $xpath->registerNamespace('xrd2', 'xri://$xrd*($v*2.0)'); + + $uris = xrds_oauth_service_uris($xpath); + + foreach ($uris as $uri) + { + // TODO: support uris referring to service documents outside this one + if ($uri{0} == '#') + { + $id = substr($uri, 1); + $oauth = xrds_xrd_oauth($xpath, $id); + if (is_array($oauth) && !empty($oauth)) + { + return $oauth; + } + } + } + + return false; +} + + +/** + * Parse a XRD definition for OAuth and return the uris etc. + * + * @param XPath xpath + * @param string id + * @return array + */ +function xrds_xrd_oauth ( $xpath, $id ) +{ + $oauth = array(); + $xrd = $xpath->query('//xrds:XRDS/xrd:XRD[@xml:id="'.$id.'"]'); + if ($xrd->length == 0) + { + // Yahoo! uses another namespace + $xrd = $xpath->query('//xrds:XRDS/xrd2:XRD[@xml:id="'.$id.'"]'); + } + + if ($xrd->length >= 1) + { + $x = $xrd->item(0); + $services = array(); + foreach ($x->childNodes as $n) + { + switch ($n->nodeName) + { + case 'Type': + if ($n->nodeValue != 'xri://$xrds*simple') + { + // Not a simple XRDS document + return false; + } + break; + case 'Expires': + $oauth['expires'] = $n->nodeValue; + break; + case 'Service': + list($type,$service) = xrds_xrd_oauth_service($n); + if ($type) + { + $services[$type][xrds_priority($n)][] = $service; + } + break; + } + } + + // Flatten the services on priority + foreach ($services as $type => $service) + { + $oauth[$type] = xrds_priority_flatten($service); + } + } + else + { + $oauth = false; + } + return $oauth; +} + + +/** + * Parse a service definition for OAuth in a simple xrd element + * + * @param DOMElement n + * @return array (type, service desc) + */ +function xrds_xrd_oauth_service ( $n ) +{ + $service = array( + 'uri' => '', + 'signature_method' => array(), + 'parameters' => array() + ); + + $type = false; + foreach ($n->childNodes as $c) + { + $name = $c->nodeName; + $value = $c->nodeValue; + + if ($name == 'URI') + { + $service['uri'] = $value; + } + else if ($name == 'Type') + { + if (strncmp($value, 'http://oauth.net/core/1.0/endpoint/', 35) == 0) + { + $type = basename($value); + } + else if (strncmp($value, 'http://oauth.net/core/1.0/signature/', 36) == 0) + { + $service['signature_method'][] = basename($value); + } + else if (strncmp($value, 'http://oauth.net/core/1.0/parameters/', 37) == 0) + { + $service['parameters'][] = basename($value); + } + else if (strncmp($value, 'http://oauth.net/discovery/1.0/consumer-identity/', 49) == 0) + { + $type = 'consumer_identity'; + $service['method'] = basename($value); + unset($service['signature_method']); + unset($service['parameters']); + } + else + { + $service['unknown'][] = $value; + } + } + else if ($name == 'LocalID') + { + $service['consumer_key'] = $value; + } + else if ($name{0} != '#') + { + $service[strtolower($name)] = $value; + } + } + return array($type, $service); +} + + +/** + * Return the OAuth service uris in order of the priority. + * + * @param XPath xpath + * @return array + */ +function xrds_oauth_service_uris ( $xpath ) +{ + $uris = array(); + $xrd_oauth = $xpath->query('//xrds:XRDS/xrd:XRD/xrd:Service/xrd:Type[.=\'http://oauth.net/discovery/1.0\']'); + if ($xrd_oauth->length > 0) + { + $service = array(); + foreach ($xrd_oauth as $xo) + { + // Find the URI of the service definition + $cs = $xo->parentNode->childNodes; + foreach ($cs as $c) + { + if ($c->nodeName == 'URI') + { + $prio = xrds_priority($xo); + $service[$prio][] = $c->nodeValue; + } + } + } + $uris = xrds_priority_flatten($service); + } + return $uris; +} + + + +/** + * Flatten an array according to the priority + * + * @param array ps buckets per prio + * @return array one dimensional array + */ +function xrds_priority_flatten ( $ps ) +{ + $prio = array(); + $null = array(); + ksort($ps); + foreach ($ps as $idx => $bucket) + { + if (!empty($bucket)) + { + if ($idx == 'null') + { + $null = $bucket; + } + else + { + $prio = array_merge($prio, $bucket); + } + } + } + $prio = array_merge($prio, $bucket); + return $prio; +} + + +/** + * Fetch the priority of a element + * + * @param DOMElement elt + * @return mixed 'null' or int + */ +function xrds_priority ( $elt ) +{ + if ($elt->hasAttribute('priority')) + { + $prio = $elt->getAttribute('priority'); + if (is_numeric($prio)) + { + $prio = intval($prio); + } + } + else + { + $prio = 'null'; + } + return $prio; +} + + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/discovery/xrds_parse.txt b/includes/oauth-php/library/discovery/xrds_parse.txt new file mode 100644 index 00000000..fd867ea9 --- /dev/null +++ b/includes/oauth-php/library/discovery/xrds_parse.txt @@ -0,0 +1,101 @@ +The xrds_parse.php script contains the function: + + function xrds_parse ( $data. ) + +$data Contains the contents of a XRDS XML file. +When the data is invalid XML then this will throw an exception. + +After parsing a XRDS definition it will return a datastructure much like the one below. + +Array +( + [expires] => 2008-04-13T07:34:58Z + [request] => Array + ( + [0] => Array + ( + [uri] => https://ma.gnolia.com/oauth/get_request_token + [signature_method] => Array + ( + [0] => HMAC-SHA1 + [1] => RSA-SHA1 + [2] => PLAINTEXT + ) + + [parameters] => Array + ( + [0] => auth-header + [1] => post-body + [2] => uri-query + ) + ) + ) + + [authorize] => Array + ( + [0] => Array + ( + [uri] => http://ma.gnolia.com/oauth/authorize + [signature_method] => Array + ( + ) + + [parameters] => Array + ( + [0] => auth-header + [1] => uri-query + ) + ) + ) + + [access] => Array + ( + [0] => Array + ( + [uri] => https://ma.gnolia.com/oauth/get_access_token + [signature_method] => Array + ( + [0] => HMAC-SHA1 + [1] => RSA-SHA1 + [2] => PLAINTEXT + ) + + [parameters] => Array + ( + [0] => auth-header + [1] => post-body + [2] => uri-query + ) + ) + ) + + [resource] => Array + ( + [0] => Array + ( + [uri] => + [signature_method] => Array + ( + [0] => HMAC-SHA1 + [1] => RSA-SHA1 + ) + + [parameters] => Array + ( + [0] => auth-header + [1] => post-body + [2] => uri-query + ) + ) + ) + + [consumer_identity] => Array + ( + [0] => Array + ( + [uri] => http://ma.gnolia.com/applications/new + [method] => oob + ) + ) +) + diff --git a/includes/oauth-php/library/session/OAuthSessionAbstract.class.php b/includes/oauth-php/library/session/OAuthSessionAbstract.class.php new file mode 100644 index 00000000..dcc80c1d --- /dev/null +++ b/includes/oauth-php/library/session/OAuthSessionAbstract.class.php @@ -0,0 +1,44 @@ + + * + * The MIT License + * + * Copyright (c) 2010 Corollarium Technologies + * + * 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. + */ + +/** + * This class is used to store Session information on the server. Most + * people will use the $_SESSION based implementation, but you may prefer + * a SQL, Memcache or other implementation. + * + */ +abstract class OAuthSessionAbstract +{ + abstract public function get ( $key ); + abstract public function set ( $key, $data ); +} + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/session/OAuthSessionSESSION.php b/includes/oauth-php/library/session/OAuthSessionSESSION.php new file mode 100644 index 00000000..3201ecbe --- /dev/null +++ b/includes/oauth-php/library/session/OAuthSessionSESSION.php @@ -0,0 +1,63 @@ + + * + * The MIT License + * + * Copyright (c) 2010 Corollarium Technologies + * + * 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__) . '/OAuthSessionAbstract.class.php'; + +class OAuthSessionSESSION extends OAuthSessionAbstract +{ + public function __construct( $options = array() ) + { + } + + /** + * Gets a variable value + * + * @param string $key + * @return The value or null if not set. + */ + public function get ( $key ) + { + return @$_SESSION[$key]; + } + + /** + * Sets a variable value + * + * @param string $key The key + * @param any $data The data + */ + public function set ( $key, $data ) + { + $_SESSION[$key] = $data; + } +} + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/signature_method/OAuthSignatureMethod.class.php b/includes/oauth-php/library/signature_method/OAuthSignatureMethod.class.php new file mode 100644 index 00000000..34ccb428 --- /dev/null +++ b/includes/oauth-php/library/signature_method/OAuthSignatureMethod.class.php @@ -0,0 +1,69 @@ + + * @date Sep 8, 2008 12:04:35 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. + */ + +abstract class OAuthSignatureMethod +{ + /** + * Return the name of this signature + * + * @return string + */ + abstract public function name(); + + /** + * Return the signature for the given request + * + * @param OAuthRequest request + * @param string base_string + * @param string consumer_secret + * @param string token_secret + * @return string + */ + abstract public function signature ( $request, $base_string, $consumer_secret, $token_secret ); + + /** + * Check if the request signature corresponds to the one calculated for the request. + * + * @param OAuthRequest request + * @param string base_string data to be signed, usually the base string, can be a request body + * @param string consumer_secret + * @param string token_secret + * @param string signature from the request, still urlencoded + * @return string + */ + abstract public function verify ( $request, $base_string, $consumer_secret, $token_secret, $signature ); +} + + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/signature_method/OAuthSignatureMethod_HMAC_SHA1.php b/includes/oauth-php/library/signature_method/OAuthSignatureMethod_HMAC_SHA1.php new file mode 100644 index 00000000..e189c938 --- /dev/null +++ b/includes/oauth-php/library/signature_method/OAuthSignatureMethod_HMAC_SHA1.php @@ -0,0 +1,115 @@ + + * @date Sep 8, 2008 12:21:19 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__).'/OAuthSignatureMethod.class.php'; + + +class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod +{ + public function name () + { + return 'HMAC-SHA1'; + } + + + /** + * Calculate the signature using HMAC-SHA1 + * This function is copyright Andy Smith, 2007. + * + * @param OAuthRequest request + * @param string base_string + * @param string consumer_secret + * @param string token_secret + * @return string + */ + function signature ( $request, $base_string, $consumer_secret, $token_secret ) + { + $key = $request->urlencode($consumer_secret).'&'.$request->urlencode($token_secret); + if (function_exists('hash_hmac')) + { + $signature = base64_encode(hash_hmac("sha1", $base_string, $key, true)); + } + else + { + $blocksize = 64; + $hashfunc = 'sha1'; + if (strlen($key) > $blocksize) + { + $key = pack('H*', $hashfunc($key)); + } + $key = str_pad($key,$blocksize,chr(0x00)); + $ipad = str_repeat(chr(0x36),$blocksize); + $opad = str_repeat(chr(0x5c),$blocksize); + $hmac = pack( + 'H*',$hashfunc( + ($key^$opad).pack( + 'H*',$hashfunc( + ($key^$ipad).$base_string + ) + ) + ) + ); + $signature = base64_encode($hmac); + } + return $request->urlencode($signature); + } + + + /** + * Check if the request signature corresponds to the one calculated for the request. + * + * @param OAuthRequest request + * @param string base_string data to be signed, usually the base string, can be a request body + * @param string consumer_secret + * @param string token_secret + * @param string signature from the request, still urlencoded + * @return string + */ + public function verify ( $request, $base_string, $consumer_secret, $token_secret, $signature ) + { + $a = $request->urldecode($signature); + $b = $request->urldecode($this->signature($request, $base_string, $consumer_secret, $token_secret)); + + // We have to compare the decoded values + $valA = base64_decode($a); + $valB = base64_decode($b); + + // Crude binary comparison + return rawurlencode($valA) == rawurlencode($valB); + } +} + + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/signature_method/OAuthSignatureMethod_MD5.php b/includes/oauth-php/library/signature_method/OAuthSignatureMethod_MD5.php new file mode 100644 index 00000000..a0167098 --- /dev/null +++ b/includes/oauth-php/library/signature_method/OAuthSignatureMethod_MD5.php @@ -0,0 +1,95 @@ + + * @date Sep 8, 2008 12:09:43 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__).'/OAuthSignatureMethod.class.php'; + + +class OAuthSignatureMethod_MD5 extends OAuthSignatureMethod +{ + public function name () + { + return 'MD5'; + } + + + /** + * Calculate the signature using MD5 + * Binary md5 digest, as distinct from PHP's built-in hexdigest. + * This function is copyright Andy Smith, 2007. + * + * @param OAuthRequest request + * @param string base_string + * @param string consumer_secret + * @param string token_secret + * @return string + */ + function signature ( $request, $base_string, $consumer_secret, $token_secret ) + { + $s .= '&'.$request->urlencode($consumer_secret).'&'.$request->urlencode($token_secret); + $md5 = md5($base_string); + $bin = ''; + + for ($i = 0; $i < strlen($md5); $i += 2) + { + $bin .= chr(hexdec($md5{$i+1}) + hexdec($md5{$i}) * 16); + } + return $request->urlencode(base64_encode($bin)); + } + + + /** + * Check if the request signature corresponds to the one calculated for the request. + * + * @param OAuthRequest request + * @param string base_string data to be signed, usually the base string, can be a request body + * @param string consumer_secret + * @param string token_secret + * @param string signature from the request, still urlencoded + * @return string + */ + public function verify ( $request, $base_string, $consumer_secret, $token_secret, $signature ) + { + $a = $request->urldecode($signature); + $b = $request->urldecode($this->signature($request, $base_string, $consumer_secret, $token_secret)); + + // We have to compare the decoded values + $valA = base64_decode($a); + $valB = base64_decode($b); + + // Crude binary comparison + return rawurlencode($valA) == rawurlencode($valB); + } +} + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/signature_method/OAuthSignatureMethod_PLAINTEXT.php b/includes/oauth-php/library/signature_method/OAuthSignatureMethod_PLAINTEXT.php new file mode 100644 index 00000000..92ef3086 --- /dev/null +++ b/includes/oauth-php/library/signature_method/OAuthSignatureMethod_PLAINTEXT.php @@ -0,0 +1,80 @@ + + * @date Sep 8, 2008 12:09:43 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__).'/OAuthSignatureMethod.class.php'; + + +class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod +{ + public function name () + { + return 'PLAINTEXT'; + } + + + /** + * Calculate the signature using PLAINTEXT + * + * @param OAuthRequest request + * @param string base_string + * @param string consumer_secret + * @param string token_secret + * @return string + */ + function signature ( $request, $base_string, $consumer_secret, $token_secret ) + { + return $request->urlencode($request->urlencode($consumer_secret).'&'.$request->urlencode($token_secret)); + } + + + /** + * Check if the request signature corresponds to the one calculated for the request. + * + * @param OAuthRequest request + * @param string base_string data to be signed, usually the base string, can be a request body + * @param string consumer_secret + * @param string token_secret + * @param string signature from the request, still urlencoded + * @return string + */ + public function verify ( $request, $base_string, $consumer_secret, $token_secret, $signature ) + { + $a = $request->urldecode($signature); + $b = $request->urldecode($this->signature($request, $base_string, $consumer_secret, $token_secret)); + + return $request->urldecode($a) == $request->urldecode($b); + } +} + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/signature_method/OAuthSignatureMethod_RSA_SHA1.php b/includes/oauth-php/library/signature_method/OAuthSignatureMethod_RSA_SHA1.php new file mode 100644 index 00000000..864dbfbe --- /dev/null +++ b/includes/oauth-php/library/signature_method/OAuthSignatureMethod_RSA_SHA1.php @@ -0,0 +1,139 @@ + + * @date Sep 8, 2008 12:00:14 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__).'/OAuthSignatureMethod.class.php'; + +class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod +{ + public function name() + { + return 'RSA-SHA1'; + } + + + /** + * Fetch the public CERT key for the signature + * + * @param OAuthRequest request + * @return string public key + */ + 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 OAuthException2("OAuthSignatureMethod_RSA_SHA1::fetch_public_cert not implemented"); + } + + + /** + * Fetch the private CERT key for the signature + * + * @param OAuthRequest request + * @return string private key + */ + 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 OAuthException2("OAuthSignatureMethod_RSA_SHA1::fetch_private_cert not implemented"); + } + + + /** + * Calculate the signature using RSA-SHA1 + * This function is copyright Andy Smith, 2008. + * + * @param OAuthRequest request + * @param string base_string + * @param string consumer_secret + * @param string token_secret + * @return string + */ + public function signature ( $request, $base_string, $consumer_secret, $token_secret ) + { + // Fetch the private key cert based on the request + $cert = $this->fetch_private_cert($request); + + // Pull the private key ID from the certificate + $privatekeyid = openssl_get_privatekey($cert); + + // Sign using the key + $sig = false; + $ok = openssl_sign($base_string, $sig, $privatekeyid); + + // Release the key resource + openssl_free_key($privatekeyid); + + return $request->urlencode(base64_encode($sig)); + } + + + /** + * Check if the request signature is the same as the one calculated for the request. + * + * @param OAuthRequest request + * @param string base_string + * @param string consumer_secret + * @param string token_secret + * @param string signature + * @return string + */ + public function verify ( $request, $base_string, $consumer_secret, $token_secret, $signature ) + { + $decoded_sig = base64_decode($request->urldecode($signature)); + + // 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; + } + +} + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/store/OAuthStore2Leg.php b/includes/oauth-php/library/store/OAuthStore2Leg.php new file mode 100644 index 00000000..faab95b0 --- /dev/null +++ b/includes/oauth-php/library/store/OAuthStore2Leg.php @@ -0,0 +1,113 @@ + + * + * 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__) . '/OAuthStoreAbstract.class.php'; + +class OAuthStore2Leg extends OAuthStoreAbstract +{ + protected $consumer_key; + protected $consumer_secret; + protected $signature_method = array('HMAC-SHA1'); + protected $token_type = false; + + /* + * Takes two options: consumer_key and consumer_secret + */ + public function __construct( $options = array() ) + { + if(isset($options['consumer_key']) && isset($options['consumer_secret'])) + { + $this->consumer_key = $options['consumer_key']; + $this->consumer_secret = $options['consumer_secret']; + } + else + { + throw new OAuthException2("OAuthStore2Leg needs consumer_token and consumer_secret"); + } + } + + public function getSecretsForVerify ( $consumer_key, $token, $token_type = 'access' ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function getSecretsForSignature ( $uri, $user_id ) + { + return array( + 'consumer_key' => $this->consumer_key, + 'consumer_secret' => $this->consumer_secret, + 'signature_methods' => $this->signature_method, + 'token' => $this->token_type + ); + } + public function getServerTokenSecrets ( $consumer_key, $token, $token_type, $user_id, $name = '' ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function addServerToken ( $consumer_key, $token_type, $token, $token_secret, $user_id, $options = array() ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + + public function deleteServer ( $consumer_key, $user_id, $user_is_admin = false ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function getServer( $consumer_key, $user_id, $user_is_admin = false ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function getServerForUri ( $uri, $user_id ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function listServerTokens ( $user_id ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function countServerTokens ( $consumer_key ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function getServerToken ( $consumer_key, $token, $user_id ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function deleteServerToken ( $consumer_key, $token, $user_id, $user_is_admin = false ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function setServerTokenTtl ( $consumer_key, $token, $token_ttl ) + { + //This method just needs to exist. It doesn't have to do anything! + } + + public function listServers ( $q = '', $user_id ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function updateServer ( $server, $user_id, $user_is_admin = false ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + + public function updateConsumer ( $consumer, $user_id, $user_is_admin = false ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function deleteConsumer ( $consumer_key, $user_id, $user_is_admin = false ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function getConsumer ( $consumer_key, $user_id, $user_is_admin = false ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function getConsumerStatic () { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + + public function addConsumerRequestToken ( $consumer_key, $options = array() ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function getConsumerRequestToken ( $token ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function deleteConsumerRequestToken ( $token ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function authorizeConsumerRequestToken ( $token, $user_id, $referrer_host = '' ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function countConsumerAccessTokens ( $consumer_key ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function exchangeConsumerRequestForAccessToken ( $token, $options = array() ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function getConsumerAccessToken ( $token, $user_id ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function deleteConsumerAccessToken ( $token, $user_id, $user_is_admin = false ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function setConsumerAccessTokenTtl ( $token, $ttl ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + + public function listConsumers ( $user_id ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function listConsumerApplications( $begin = 0, $total = 25 ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function listConsumerTokens ( $user_id ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + + public function checkServerNonce ( $consumer_key, $token, $timestamp, $nonce ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + + public function addLog ( $keys, $received, $sent, $base_string, $notes, $user_id = null ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + public function listLog ( $options, $user_id ) { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } + + public function install () { throw new OAuthException2("OAuthStore2Leg doesn't support " . __METHOD__); } +} + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/store/OAuthStoreAbstract.class.php b/includes/oauth-php/library/store/OAuthStoreAbstract.class.php new file mode 100644 index 00000000..3bfa2b2b --- /dev/null +++ b/includes/oauth-php/library/store/OAuthStoreAbstract.class.php @@ -0,0 +1,150 @@ + + * + * 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. + */ + +abstract class OAuthStoreAbstract +{ + abstract public function getSecretsForVerify ( $consumer_key, $token, $token_type = 'access' ); + abstract public function getSecretsForSignature ( $uri, $user_id ); + abstract public function getServerTokenSecrets ( $consumer_key, $token, $token_type, $user_id, $name = '' ); + abstract public function addServerToken ( $consumer_key, $token_type, $token, $token_secret, $user_id, $options = array() ); + + abstract public function deleteServer ( $consumer_key, $user_id, $user_is_admin = false ); + abstract public function getServer( $consumer_key, $user_id, $user_is_admin = false ); + abstract public function getServerForUri ( $uri, $user_id ); + abstract public function listServerTokens ( $user_id ); + abstract public function countServerTokens ( $consumer_key ); + abstract public function getServerToken ( $consumer_key, $token, $user_id ); + abstract public function deleteServerToken ( $consumer_key, $token, $user_id, $user_is_admin = false ); + abstract public function listServers ( $q = '', $user_id ); + abstract public function updateServer ( $server, $user_id, $user_is_admin = false ); + + abstract public function updateConsumer ( $consumer, $user_id, $user_is_admin = false ); + abstract public function deleteConsumer ( $consumer_key, $user_id, $user_is_admin = false ); + abstract public function getConsumer ( $consumer_key, $user_id, $user_is_admin = false ); + abstract public function getConsumerStatic (); + + abstract public function addConsumerRequestToken ( $consumer_key, $options = array() ); + abstract public function getConsumerRequestToken ( $token ); + abstract public function deleteConsumerRequestToken ( $token ); + abstract public function authorizeConsumerRequestToken ( $token, $user_id, $referrer_host = '' ); + abstract public function countConsumerAccessTokens ( $consumer_key ); + abstract public function exchangeConsumerRequestForAccessToken ( $token, $options = array() ); + abstract public function getConsumerAccessToken ( $token, $user_id ); + abstract public function deleteConsumerAccessToken ( $token, $user_id, $user_is_admin = false ); + abstract public function setConsumerAccessTokenTtl ( $token, $ttl ); + + abstract public function listConsumers ( $user_id ); + abstract public function listConsumerApplications( $begin = 0, $total = 25 ); + abstract public function listConsumerTokens ( $user_id ); + + abstract public function checkServerNonce ( $consumer_key, $token, $timestamp, $nonce ); + + abstract public function addLog ( $keys, $received, $sent, $base_string, $notes, $user_id = null ); + abstract public function listLog ( $options, $user_id ); + + abstract public function install (); + + /** + * Fetch the current static consumer key for this site, create it when it was not found. + * The consumer secret for the consumer key is always empty. + * + * @return string consumer key + */ + + + /* ** Some handy utility functions ** */ + + /** + * Generate a unique key + * + * @param boolean unique force the key to be unique + * @return string + */ + public function generateKey ( $unique = false ) + { + $key = md5(uniqid(rand(), true)); + if ($unique) + { + list($usec,$sec) = explode(' ',microtime()); + $key .= dechex($usec).dechex($sec); + } + return $key; + } + + /** + * Check to see if a string is valid utf8 + * + * @param string $s + * @return boolean + */ + protected function isUTF8 ( $s ) + { + return preg_match('%(?: + [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte + |\xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs + |[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte + |\xED[\x80-\x9F][\x80-\xBF] # excluding surrogates + |\xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 + |[\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 + |\xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 + )+%xs', $s); + } + + + /** + * Make a string utf8, replacing all non-utf8 chars with a '.' + * + * @param string + * @return string + */ + protected function makeUTF8 ( $s ) + { + if (function_exists('iconv')) + { + do + { + $ok = true; + $text = @iconv('UTF-8', 'UTF-8//TRANSLIT', $s); + if (strlen($text) != strlen($s)) + { + // Remove the offending character... + $s = $text . '.' . substr($s, strlen($text) + 1); + $ok = false; + } + } + while (!$ok); + } + return $s; + } + +} + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/store/OAuthStoreAnyMeta.php b/includes/oauth-php/library/store/OAuthStoreAnyMeta.php new file mode 100644 index 00000000..b619ec03 --- /dev/null +++ b/includes/oauth-php/library/store/OAuthStoreAnyMeta.php @@ -0,0 +1,264 @@ + + * @date Nov 16, 2007 4:03:30 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__) . '/OAuthStoreMySQL.php'; + + +class OAuthStoreAnymeta extends OAuthStoreMySQL +{ + /** + * Construct the OAuthStoreAnymeta + * + * @param array options + */ + function __construct ( $options = array() ) + { + parent::__construct(array('conn' => any_db_conn())); + } + + + /** + * Add an entry to the log table + * + * @param array keys (osr_consumer_key, ost_token, ocr_consumer_key, oct_token) + * @param string received + * @param string sent + * @param string base_string + * @param string notes + * @param int (optional) user_id + */ + public function addLog ( $keys, $received, $sent, $base_string, $notes, $user_id = null ) + { + if (is_null($user_id) && isset($GLOBALS['any_auth'])) + { + $user_id = $GLOBALS['any_auth']->getUserId(); + } + parent::addLog($keys, $received, $sent, $base_string, $notes, $user_id); + } + + + /** + * Get a page of entries from the log. Returns the last 100 records + * matching the options given. + * + * @param array options + * @param int user_id current user + * @return array log records + */ + public function listLog ( $options, $user_id ) + { + $where = array(); + $args = array(); + if (empty($options)) + { + $where[] = 'olg_usa_id_ref = %d'; + $args[] = $user_id; + } + else + { + foreach ($options as $option => $value) + { + if (strlen($value) > 0) + { + switch ($option) + { + case 'osr_consumer_key': + case 'ocr_consumer_key': + case 'ost_token': + case 'oct_token': + $where[] = 'olg_'.$option.' = \'%s\''; + $args[] = $value; + break; + } + } + } + + $where[] = '(olg_usa_id_ref IS NULL OR olg_usa_id_ref = %d)'; + $args[] = $user_id; + } + + $rs = any_db_query_all_assoc(' + SELECT olg_id, + olg_osr_consumer_key AS osr_consumer_key, + olg_ost_token AS ost_token, + olg_ocr_consumer_key AS ocr_consumer_key, + olg_oct_token AS oct_token, + olg_usa_id_ref AS user_id, + olg_received AS received, + olg_sent AS sent, + olg_base_string AS base_string, + olg_notes AS notes, + olg_timestamp AS timestamp, + INET_NTOA(olg_remote_ip) AS remote_ip + FROM oauth_log + WHERE '.implode(' AND ', $where).' + ORDER BY olg_id DESC + LIMIT 0,100', $args); + + return $rs; + } + + + + /** + * Initialise the database + */ + public function install () + { + parent::install(); + + any_db_query("ALTER TABLE oauth_consumer_registry MODIFY ocr_usa_id_ref int(11) unsigned"); + any_db_query("ALTER TABLE oauth_consumer_token MODIFY oct_usa_id_ref int(11) unsigned not null"); + any_db_query("ALTER TABLE oauth_server_registry MODIFY osr_usa_id_ref int(11) unsigned"); + any_db_query("ALTER TABLE oauth_server_token MODIFY ost_usa_id_ref int(11) unsigned not null"); + any_db_query("ALTER TABLE oauth_log MODIFY olg_usa_id_ref int(11) unsigned"); + + any_db_alter_add_fk('oauth_consumer_registry', 'ocr_usa_id_ref', 'any_user_auth(usa_id_ref)', 'on update cascade on delete set null'); + any_db_alter_add_fk('oauth_consumer_token', 'oct_usa_id_ref', 'any_user_auth(usa_id_ref)', 'on update cascade on delete cascade'); + any_db_alter_add_fk('oauth_server_registry', 'osr_usa_id_ref', 'any_user_auth(usa_id_ref)', 'on update cascade on delete set null'); + any_db_alter_add_fk('oauth_server_token', 'ost_usa_id_ref', 'any_user_auth(usa_id_ref)', 'on update cascade on delete cascade'); + any_db_alter_add_fk('oauth_log', 'olg_usa_id_ref', 'any_user_auth(usa_id_ref)', 'on update cascade on delete cascade'); + } + + + + /** Some simple helper functions for querying the mysql db **/ + + /** + * Perform a query, ignore the results + * + * @param string sql + * @param vararg arguments (for sprintf) + */ + protected function query ( $sql ) + { + list($sql, $args) = $this->sql_args(func_get_args()); + any_db_query($sql, $args); + } + + + /** + * Perform a query, ignore the results + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + protected function query_all_assoc ( $sql ) + { + list($sql, $args) = $this->sql_args(func_get_args()); + return any_db_query_all_assoc($sql, $args); + } + + + /** + * Perform a query, return the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + protected function query_row_assoc ( $sql ) + { + list($sql, $args) = $this->sql_args(func_get_args()); + return any_db_query_row_assoc($sql, $args); + } + + + /** + * Perform a query, return the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + protected function query_row ( $sql ) + { + list($sql, $args) = $this->sql_args(func_get_args()); + return any_db_query_row($sql, $args); + } + + + /** + * Perform a query, return the first column of the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return mixed + */ + protected function query_one ( $sql ) + { + list($sql, $args) = $this->sql_args(func_get_args()); + return any_db_query_one($sql, $args); + } + + + /** + * Return the number of rows affected in the last query + * + * @return int + */ + protected function query_affected_rows () + { + return any_db_affected_rows(); + } + + + /** + * Return the id of the last inserted row + * + * @return int + */ + protected function query_insert_id () + { + return any_db_insert_id(); + } + + + private function sql_args ( $args ) + { + $sql = array_shift($args); + if (count($args) == 1 && is_array($args[0])) + { + $args = $args[0]; + } + return array($sql, $args); + } + +} + + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/store/OAuthStoreMySQL.php b/includes/oauth-php/library/store/OAuthStoreMySQL.php new file mode 100644 index 00000000..c568359a --- /dev/null +++ b/includes/oauth-php/library/store/OAuthStoreMySQL.php @@ -0,0 +1,245 @@ + + * @date Nov 16, 2007 4:03:30 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__) . '/OAuthStoreSQL.php'; + + +class OAuthStoreMySQL extends OAuthStoreSQL +{ + /** + * The MySQL connection + */ + protected $conn; + + /** + * Initialise the database + */ + public function install () + { + require_once dirname(__FILE__) . '/mysql/install.php'; + } + + + /* ** Some simple helper functions for querying the mysql db ** */ + + /** + * Perform a query, ignore the results + * + * @param string sql + * @param vararg arguments (for sprintf) + */ + protected function query ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + if (!($res = mysql_query($sql, $this->conn))) + { + $this->sql_errcheck($sql); + } + if (is_resource($res)) + { + mysql_free_result($res); + } + } + + + /** + * Perform a query, ignore the results + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + protected function query_all_assoc ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + if (!($res = mysql_query($sql, $this->conn))) + { + $this->sql_errcheck($sql); + } + $rs = array(); + while ($row = mysql_fetch_assoc($res)) + { + $rs[] = $row; + } + mysql_free_result($res); + return $rs; + } + + + /** + * Perform a query, return the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + protected function query_row_assoc ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + if (!($res = mysql_query($sql, $this->conn))) + { + $this->sql_errcheck($sql); + } + if ($row = mysql_fetch_assoc($res)) + { + $rs = $row; + } + else + { + $rs = false; + } + mysql_free_result($res); + return $rs; + } + + + /** + * Perform a query, return the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + protected function query_row ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + if (!($res = mysql_query($sql, $this->conn))) + { + $this->sql_errcheck($sql); + } + if ($row = mysql_fetch_array($res)) + { + $rs = $row; + } + else + { + $rs = false; + } + mysql_free_result($res); + return $rs; + } + + + /** + * Perform a query, return the first column of the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return mixed + */ + protected function query_one ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + if (!($res = mysql_query($sql, $this->conn))) + { + $this->sql_errcheck($sql); + } + $val = @mysql_result($res, 0, 0); + mysql_free_result($res); + return $val; + } + + + /** + * Return the number of rows affected in the last query + */ + protected function query_affected_rows () + { + return mysql_affected_rows($this->conn); + } + + + /** + * Return the id of the last inserted row + * + * @return int + */ + protected function query_insert_id () + { + return mysql_insert_id($this->conn); + } + + + protected function sql_printf ( $args ) + { + $sql = array_shift($args); + if (count($args) == 1 && is_array($args[0])) + { + $args = $args[0]; + } + $args = array_map(array($this, 'sql_escape_string'), $args); + return vsprintf($sql, $args); + } + + + protected function sql_escape_string ( $s ) + { + if (is_string($s)) + { + return mysql_real_escape_string($s, $this->conn); + } + else if (is_null($s)) + { + return NULL; + } + else if (is_bool($s)) + { + return intval($s); + } + else if (is_int($s) || is_float($s)) + { + return $s; + } + else + { + return mysql_real_escape_string(strval($s), $this->conn); + } + } + + + protected function sql_errcheck ( $sql ) + { + if (mysql_errno($this->conn)) + { + $msg = "SQL Error in OAuthStoreMySQL: ".mysql_error($this->conn)."\n\n" . $sql; + throw new OAuthException2($msg); + } + } +} + + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/store/OAuthStoreMySQLi.php b/includes/oauth-php/library/store/OAuthStoreMySQLi.php new file mode 100644 index 00000000..09d71bfb --- /dev/null +++ b/includes/oauth-php/library/store/OAuthStoreMySQLi.php @@ -0,0 +1,306 @@ + Based on code by Marc Worrell + * + * + * 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. + */ + +/* + * Modified from OAuthStoreMySQL to support MySQLi + */ + +require_once dirname(__FILE__) . '/OAuthStoreMySQL.php'; + + +class OAuthStoreMySQLi extends OAuthStoreMySQL +{ + + public function install() { + $sql = file_get_contents(dirname(__FILE__) . '/mysql/mysql.sql'); + $ps = explode('#--SPLIT--', $sql); + + foreach ($ps as $p) + { + $p = preg_replace('/^\s*#.*$/m', '', $p); + + $this->query($p); + $this->sql_errcheck($p); + } + } + + /** + * Construct the OAuthStoreMySQLi. + * In the options you have to supply either: + * - server, username, password and database (for a mysqli_connect) + * - conn (for the connection to be used) + * + * @param array options + */ + function __construct ( $options = array() ) + { + if (isset($options['conn'])) + { + $this->conn = $options['conn']; + } + else + { + if (isset($options['server'])) + { + $server = $options['server']; + $username = $options['username']; + + if (isset($options['password'])) + { + $this->conn = ($GLOBALS["___mysqli_ston"] = mysqli_connect($server, $username, $options['password'])); + } + else + { + $this->conn = ($GLOBALS["___mysqli_ston"] = mysqli_connect($server, $username)); + } + } + else + { + // Try the default mysql connect + $this->conn = ($GLOBALS["___mysqli_ston"] = mysqli_connect()); + } + + if ($this->conn === false) + { + throw new OAuthException2('Could not connect to MySQL database: ' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false))); + } + + if (isset($options['database'])) + { + /* TODO: security. mysqli_ doesn't seem to have an escape identifier function. + $escapeddb = mysqli_real_escape_string($options['database']); + if (!((bool)mysqli_query( $this->conn, "USE `$escapeddb`" ))) + { + $this->sql_errcheck(); + }*/ + } + $this->query('set character set utf8'); + } + } + + /** + * Perform a query, ignore the results + * + * @param string sql + * @param vararg arguments (for sprintf) + */ + protected function query ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + if (!($res = mysqli_query( $this->conn, $sql))) + { + $this->sql_errcheck($sql); + } + if (!is_bool($res)) + { + ((mysqli_free_result($res) || (is_object($res) && (get_class($res) == "mysqli_result"))) ? true : false); + } + } + + + /** + * Perform a query, ignore the results + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + protected function query_all_assoc ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + if (!($res = mysqli_query( $this->conn, $sql))) + { + $this->sql_errcheck($sql); + } + $rs = array(); + while ($row = mysqli_fetch_assoc($res)) + { + $rs[] = $row; + } + ((mysqli_free_result($res) || (is_object($res) && (get_class($res) == "mysqli_result"))) ? true : false); + return $rs; + } + + + /** + * Perform a query, return the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + protected function query_row_assoc ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + if (!($res = mysqli_query( $this->conn, $sql))) + { + $this->sql_errcheck($sql); + } + if ($row = mysqli_fetch_assoc($res)) + { + $rs = $row; + } + else + { + $rs = false; + } + ((mysqli_free_result($res) || (is_object($res) && (get_class($res) == "mysqli_result"))) ? true : false); + return $rs; + } + + + /** + * Perform a query, return the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + protected function query_row ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + if (!($res = mysqli_query( $this->conn, $sql))) + { + $this->sql_errcheck($sql); + } + if ($row = mysqli_fetch_array($res)) + { + $rs = $row; + } + else + { + $rs = false; + } + ((mysqli_free_result($res) || (is_object($res) && (get_class($res) == "mysqli_result"))) ? true : false); + return $rs; + } + + + /** + * Perform a query, return the first column of the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return mixed + */ + protected function query_one ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + if (!($res = mysqli_query( $this->conn, $sql))) + { + $this->sql_errcheck($sql); + } + if ($row = mysqli_fetch_assoc($res)) + { + $val = array_pop($row); + } + else + { + $val = false; + } + ((mysqli_free_result($res) || (is_object($res) && (get_class($res) == "mysqli_result"))) ? true : false); + return $val; + } + + + /** + * Return the number of rows affected in the last query + */ + protected function query_affected_rows () + { + return mysqli_affected_rows($this->conn); + } + + + /** + * Return the id of the last inserted row + * + * @return int + */ + protected function query_insert_id () + { + return ((is_null($___mysqli_res = mysqli_insert_id($this->conn))) ? false : $___mysqli_res); + } + + + protected function sql_printf ( $args ) + { + $sql = array_shift($args); + if (count($args) == 1 && is_array($args[0])) + { + $args = $args[0]; + } + $args = array_map(array($this, 'sql_escape_string'), $args); + return vsprintf($sql, $args); + } + + + protected function sql_escape_string ( $s ) + { + if (is_string($s)) + { + return mysqli_real_escape_string( $this->conn, $s); + } + else if (is_null($s)) + { + return NULL; + } + else if (is_bool($s)) + { + return intval($s); + } + else if (is_int($s) || is_float($s)) + { + return $s; + } + else + { + return mysqli_real_escape_string( $this->conn, strval($s)); + } + } + + + protected function sql_errcheck ( $sql ) + { + if (((is_object($this->conn)) ? mysqli_errno($this->conn) : (($___mysqli_res = mysqli_connect_errno()) ? $___mysqli_res : false))) + { + $msg = "SQL Error in OAuthStoreMySQL: ".((is_object($this->conn)) ? mysqli_error($this->conn) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false))."\n\n" . $sql; + throw new OAuthException2($msg); + } + } +} + + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/store/OAuthStoreOracle.php b/includes/oauth-php/library/store/OAuthStoreOracle.php new file mode 100644 index 00000000..554792fa --- /dev/null +++ b/includes/oauth-php/library/store/OAuthStoreOracle.php @@ -0,0 +1,1536 @@ + + * @date Aug 6, 2010 + * + * The MIT License + * + * 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__) . '/OAuthStoreAbstract.class.php'; + +abstract class OAuthStoreOracle extends OAuthStoreAbstract { + /** + * Maximum delta a timestamp may be off from a previous timestamp. + * Allows multiple consumers with some clock skew to work with the same token. + * Unit is seconds, default max skew is 10 minutes. + */ + protected $max_timestamp_skew = MAX_TIMESTAMP_SKEW; + + /** + * Default ttl for request tokens + */ + protected $max_request_token_ttl = MAX_REQUEST_TOKEN_TIME; + + + /** + * Construct the OAuthStoreMySQL. + * In the options you have to supply either: + * - server, username, password and database (for a mysql_connect) + * - conn (for the connection to be used) + * + * @param array options + */ + function __construct ( $options = array() ) { + if (isset($options['conn'])) { + $this->conn = $options['conn']; + } + else { + $this->conn=oci_connect(DBUSER,DBPASSWORD,DBHOST); + + if ($this->conn === false) { + throw new OAuthException2('Could not connect to database'); + } + + // $this->query('set character set utf8'); + } + } + + /** + * Find stored credentials for the consumer key and token. Used by an OAuth server + * when verifying an OAuth request. + * + * @param string consumer_key + * @param string token + * @param string token_type false, 'request' or 'access' + * @exception OAuthException2 when no secrets where found + * @return array assoc (consumer_secret, token_secret, osr_id, ost_id, user_id) + */ + public function getSecretsForVerify ($consumer_key, $token, $token_type = 'access' ) { + $sql = "BEGIN SP_GET_SECRETS_FOR_VERIFY(:P_CONSUMER_KEY, :P_TOKEN, :P_TOKEN_TYPE, :P_ROWS, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_CONSUMER_KEY', $consumer_key, 255); + oci_bind_by_name($stmt, ':P_TOKEN', $token, 255); + oci_bind_by_name($stmt, ':P_TOKEN_TYPE', $token_type, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Bind the ref cursor + $p_row = oci_new_cursor($this->conn); + oci_bind_by_name($stmt, ':P_ROWS', $p_row, -1, OCI_B_CURSOR); + + //Execute the statement + oci_execute($stmt); + + // treat the ref cursor as a statement resource + oci_execute($p_row, OCI_DEFAULT); + oci_fetch_all($p_row, $getSecretsForVerifyList, null, null, OCI_FETCHSTATEMENT_BY_ROW); + + $rs =$getSecretsForVerifyList; + if (empty($rs)) { + throw new OAuthException2('The consumer_key "'.$consumer_key.'" token "'.$token.'" combination does not exist or is not enabled.'); + } + + return $rs[0]; + } + + + /** + * Find the server details for signing a request, always looks for an access token. + * The returned credentials depend on which local user is making the request. + * + * The consumer_key must belong to the user or be public (user id is null) + * + * For signing we need all of the following: + * + * consumer_key consumer key associated with the server + * consumer_secret consumer secret associated with this server + * token access token associated with this server + * token_secret secret for the access token + * signature_methods signing methods supported by the server (array) + * + * @todo filter on token type (we should know how and with what to sign this request, and there might be old access tokens) + * @param string uri uri of the server + * @param int user_id id of the logged on user + * @param string name (optional) name of the token (case sensitive) + * @exception OAuthException2 when no credentials found + * @return array + */ + public function getSecretsForSignature ( $uri, $user_id, $name = '' ) { + // Find a consumer key and token for the given uri + $ps = parse_url($uri); + $host = isset($ps['host']) ? $ps['host'] : 'localhost'; + $path = isset($ps['path']) ? $ps['path'] : ''; + + if (empty($path) || substr($path, -1) != '/') { + $path .= '/'; + } + // + $sql = "BEGIN SP_GET_SECRETS_FOR_SIGNATURE(:P_HOST, :P_PATH, :P_USER_ID, :P_NAME, :P_ROWS, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_HOST', $host, 255); + oci_bind_by_name($stmt, ':P_PATH', $path, 255); + oci_bind_by_name($stmt, ':P_USER_ID', $user_id, 20); + oci_bind_by_name($stmt, ':P_NAME', $name, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Bind the ref cursor + $p_row = oci_new_cursor($this->conn); + oci_bind_by_name($stmt, ':P_ROWS', $p_row, -1, OCI_B_CURSOR); + + //Execute the statement + oci_execute($stmt); + + // treat the ref cursor as a statement resource + oci_execute($p_row, OCI_DEFAULT); + oci_fetch_all($p_row, $getSecretsForSignatureList, null, null, OCI_FETCHSTATEMENT_BY_ROW); + $secrets = $getSecretsForSignatureList[0]; + // + // The owner of the consumer_key is either the user or nobody (public consumer key) + /*$secrets = $this->query_row_assoc(' + SELECT ocr_consumer_key as consumer_key, + ocr_consumer_secret as consumer_secret, + oct_token as token, + oct_token_secret as token_secret, + ocr_signature_methods as signature_methods + FROM oauth_consumer_registry + JOIN oauth_consumer_token ON oct_ocr_id_ref = ocr_id + WHERE ocr_server_uri_host = \'%s\' + AND ocr_server_uri_path = LEFT(\'%s\', LENGTH(ocr_server_uri_path)) + AND (ocr_usa_id_ref = %s OR ocr_usa_id_ref IS NULL) + AND oct_usa_id_ref = %d + AND oct_token_type = \'access\' + AND oct_name = \'%s\' + AND oct_token_ttl >= NOW() + ORDER BY ocr_usa_id_ref DESC, ocr_consumer_secret DESC, LENGTH(ocr_server_uri_path) DESC + LIMIT 0,1 + ', $host, $path, $user_id, $user_id, $name + ); + */ + if (empty($secrets)) { + throw new OAuthException2('No server tokens available for '.$uri); + } + $secrets['signature_methods'] = explode(',', $secrets['signature_methods']); + return $secrets; + } + + + /** + * Get the token and token secret we obtained from a server. + * + * @param string consumer_key + * @param string token + * @param string token_type + * @param int user_id the user owning the token + * @param string name optional name for a named token + * @exception OAuthException2 when no credentials found + * @return array + */ + public function getServerTokenSecrets ($consumer_key,$token,$token_type,$user_id,$name = '') + { + if ($token_type != 'request' && $token_type != 'access') + { + throw new OAuthException2('Unkown token type "'.$token_type.'", must be either "request" or "access"'); + } + // + $sql = "BEGIN SP_GET_SERVER_TOKEN_SECRETS(:P_CONSUMER_KEY, :P_TOKEN, :P_TOKEN_TYPE, :P_USER_ID, :P_ROWS, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_CONSUMER_KEY', $consumer_key, 255); + oci_bind_by_name($stmt, ':P_TOKEN', $token, 255); + oci_bind_by_name($stmt, ':P_TOKEN_TYPE', $token_type, 20); + oci_bind_by_name($stmt, ':P_USER_ID', $user_id, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Bind the ref cursor + $p_row = oci_new_cursor($this->conn); + oci_bind_by_name($stmt, ':P_ROWS', $p_row, -1, OCI_B_CURSOR); + + //Execute the statement + oci_execute($stmt); + + // treat the ref cursor as a statement resource + oci_execute($p_row, OCI_DEFAULT); + oci_fetch_all($p_row, $getServerTokenSecretsList, null, null, OCI_FETCHSTATEMENT_BY_ROW); + $r=$getServerTokenSecretsList[0]; + // + // Take the most recent token of the given type + /*$r = $this->query_row_assoc(' + SELECT ocr_consumer_key as consumer_key, + ocr_consumer_secret as consumer_secret, + oct_token as token, + oct_token_secret as token_secret, + oct_name as token_name, + ocr_signature_methods as signature_methods, + ocr_server_uri as server_uri, + ocr_request_token_uri as request_token_uri, + ocr_authorize_uri as authorize_uri, + ocr_access_token_uri as access_token_uri, + IF(oct_token_ttl >= \'9999-12-31\', NULL, UNIX_TIMESTAMP(oct_token_ttl) - UNIX_TIMESTAMP(NOW())) as token_ttl + FROM oauth_consumer_registry + JOIN oauth_consumer_token + ON oct_ocr_id_ref = ocr_id + WHERE ocr_consumer_key = \'%s\' + AND oct_token_type = \'%s\' + AND oct_token = \'%s\' + AND oct_usa_id_ref = %d + AND oct_token_ttl >= NOW() + ', $consumer_key, $token_type, $token, $user_id + );*/ + + if (empty($r)) + { + throw new OAuthException2('Could not find a "'.$token_type.'" token for consumer "'.$consumer_key.'" and user '.$user_id); + } + if (isset($r['signature_methods']) && !empty($r['signature_methods'])) + { + $r['signature_methods'] = explode(',',$r['signature_methods']); + } + else + { + $r['signature_methods'] = array(); + } + return $r; + } + + + /** + * Add a request token we obtained from a server. + * + * @todo remove old tokens for this user and this ocr_id + * @param string consumer_key key of the server in the consumer registry + * @param string token_type one of 'request' or 'access' + * @param string token + * @param string token_secret + * @param int user_id the user owning the token + * @param array options extra options, name and token_ttl + * @exception OAuthException2 when server is not known + * @exception OAuthException2 when we received a duplicate token + */ + public function addServerToken ( $consumer_key, $token_type, $token, $token_secret, $user_id, $options = array() ) + { + if ($token_type != 'request' && $token_type != 'access') + { + throw new OAuthException2('Unknown token type "'.$token_type.'", must be either "request" or "access"'); + } + + // Maximum time to live for this token + if (isset($options['token_ttl']) && is_numeric($options['token_ttl'])) + { + $ttl = intval($options['token_ttl']); + } + else if ($token_type == 'request') + { + $ttl =intval($this->max_request_token_ttl); + } + else + { + $ttl = NULL; + } + + + + // Named tokens, unique per user/consumer key + if (isset($options['name']) && $options['name'] != '') + { + $name = $options['name']; + } + else + { + $name = ''; + } + // + $sql = "BEGIN SP_ADD_SERVER_TOKEN(:P_CONSUMER_KEY, :P_USER_ID, :P_NAME, :P_TOKEN_TYPE, :P_TOKEN, :P_TOKEN_SECRET, :P_TOKEN_INTERVAL_IN_SEC, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_CONSUMER_KEY', $consumer_key, 255); + oci_bind_by_name($stmt, ':P_USER_ID', $user_id, 40); + oci_bind_by_name($stmt, ':P_NAME', $name, 255); + oci_bind_by_name($stmt, ':P_TOKEN_TYPE', $token_type, 20); + oci_bind_by_name($stmt, ':P_TOKEN', $token, 255); + oci_bind_by_name($stmt, ':P_TOKEN_SECRET', $token_secret, 255); + oci_bind_by_name($stmt, ':P_TOKEN_INTERVAL_IN_SEC', $ttl, 40); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Execute the statement + oci_execute($stmt); + // + + + + if (!$result) + { + throw new OAuthException2('Received duplicate token "'.$token.'" for the same consumer_key "'.$consumer_key.'"'); + } + } + + + /** + * Delete a server key. This removes access to that site. + * + * @param string consumer_key + * @param int user_id user registering this server + * @param boolean user_is_admin + */ + public function deleteServer ( $consumer_key, $user_id, $user_is_admin = false ) + { + + $sql = "BEGIN SP_DELETE_SERVER(:P_CONSUMER_KEY, :P_USER_ID, :P_USER_IS_ADMIN, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_CONSUMER_KEY', $consumer_key, 255); + oci_bind_by_name($stmt, ':P_USER_ID', $user_id, 40); + oci_bind_by_name($stmt, ':P_USER_IS_ADMIN', $user_is_admin, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Execute the statement + oci_execute($stmt); + } + + + /** + * Get a server from the consumer registry using the consumer key + * + * @param string consumer_key + * @param int user_id + * @param boolean user_is_admin (optional) + * @exception OAuthException2 when server is not found + * @return array + */ + public function getServer ( $consumer_key, $user_id, $user_is_admin = false ) + { + + // + $sql = "BEGIN SP_GET_SERVER(:P_CONSUMER_KEY, :P_USER_ID, :P_ROWS, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_CONSUMER_KEY', $consumer_key, 255); + oci_bind_by_name($stmt, ':P_USER_ID', $user_id, 40); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Bind the ref cursor + $p_row = oci_new_cursor($this->conn); + oci_bind_by_name($stmt, ':P_ROWS', $p_row, -1, OCI_B_CURSOR); + + //Execute the statement + oci_execute($stmt); + + // treat the ref cursor as a statement resource + oci_execute($p_row, OCI_DEFAULT); + oci_fetch_all($p_row, $getServerList, null, null, OCI_FETCHSTATEMENT_BY_ROW); + $r = $getServerList; + // + if (empty($r)) + { + throw new OAuthException2('No server with consumer_key "'.$consumer_key.'" has been registered (for this user)'); + } + + if (isset($r['signature_methods']) && !empty($r['signature_methods'])) + { + $r['signature_methods'] = explode(',',$r['signature_methods']); + } + else + { + $r['signature_methods'] = array(); + } + return $r; + } + + + + /** + * Find the server details that might be used for a request + * + * The consumer_key must belong to the user or be public (user id is null) + * + * @param string uri uri of the server + * @param int user_id id of the logged on user + * @exception OAuthException2 when no credentials found + * @return array + */ + public function getServerForUri ( $uri, $user_id ) + { + // Find a consumer key and token for the given uri + $ps = parse_url($uri); + $host = isset($ps['host']) ? $ps['host'] : 'localhost'; + $path = isset($ps['path']) ? $ps['path'] : ''; + + if (empty($path) || substr($path, -1) != '/') + { + $path .= '/'; + } + + + // + $sql = "BEGIN SP_GET_SERVER_FOR_URI(:P_HOST, :P_PATH,:P_USER_ID, :P_ROWS, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_HOST', $host, 255); + oci_bind_by_name($stmt, ':P_PATH', $path, 255); + oci_bind_by_name($stmt, ':P_USER_ID', $user_id, 40); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Bind the ref cursor + $p_row = oci_new_cursor($this->conn); + oci_bind_by_name($stmt, ':P_ROWS', $p_row, -1, OCI_B_CURSOR); + + //Execute the statement + oci_execute($stmt); + + // treat the ref cursor as a statement resource + oci_execute($p_row, OCI_DEFAULT); + oci_fetch_all($p_row, $getServerForUriList, null, null, OCI_FETCHSTATEMENT_BY_ROW); + $server = $getServerForUriList; + // + if (empty($server)) + { + throw new OAuthException2('No server available for '.$uri); + } + $server['signature_methods'] = explode(',', $server['signature_methods']); + return $server; + } + + + /** + * Get a list of all server token this user has access to. + * + * @param int usr_id + * @return array + */ + public function listServerTokens ( $user_id ) + { + + $sql = "BEGIN SP_LIST_SERVER_TOKENS(:P_USER_ID, :P_ROWS, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_USER_ID', $user_id, 40); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Bind the ref cursor + $p_row = oci_new_cursor($this->conn); + oci_bind_by_name($stmt, ':P_ROWS', $p_row, -1, OCI_B_CURSOR); + + //Execute the statement + oci_execute($stmt); + + // treat the ref cursor as a statement resource + oci_execute($p_row, OCI_DEFAULT); + oci_fetch_all($p_row, $listServerTokensList, null, null, OCI_FETCHSTATEMENT_BY_ROW); + $ts = $listServerTokensList; + return $ts; + } + + + /** + * Count how many tokens we have for the given server + * + * @param string consumer_key + * @return int + */ + public function countServerTokens ( $consumer_key ) + { + + // + $count =0; + $sql = "BEGIN SP_COUNT_SERVICE_TOKENS(:P_CONSUMER_KEY, :P_COUNT, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_CONSUMER_KEY', $consumer_key, 255); + oci_bind_by_name($stmt, ':P_COUNT', $count, 40); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Execute the statement + oci_execute($stmt); + // + return $count; + } + + + /** + * Get a specific server token for the given user + * + * @param string consumer_key + * @param string token + * @param int user_id + * @exception OAuthException2 when no such token found + * @return array + */ + public function getServerToken ( $consumer_key, $token, $user_id ) + { + + $sql = "BEGIN SP_GET_SERVER_TOKEN(:P_CONSUMER_KEY, :P_USER_ID,:P_TOKEN, :P_ROWS, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_CONSUMER_KEY', $consumer_key, 255); + oci_bind_by_name($stmt, ':P_USER_ID', $user_id, 40); + oci_bind_by_name($stmt, ':P_TOKEN', $token, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Bind the ref cursor + $p_row = oci_new_cursor($this->conn); + oci_bind_by_name($stmt, ':P_ROWS', $p_row, -1, OCI_B_CURSOR); + + //Execute the statement + oci_execute($stmt); + + // treat the ref cursor as a statement resource + oci_execute($p_row, OCI_DEFAULT); + oci_fetch_all($p_row, $getServerTokenList, null, null, OCI_FETCHSTATEMENT_BY_ROW); + $ts = $getServerTokenList; + // + + if (empty($ts)) + { + throw new OAuthException2('No such consumer key ('.$consumer_key.') and token ('.$token.') combination for user "'.$user_id.'"'); + } + return $ts; + } + + + /** + * Delete a token we obtained from a server. + * + * @param string consumer_key + * @param string token + * @param int user_id + * @param boolean user_is_admin + */ + public function deleteServerToken ( $consumer_key, $token, $user_id, $user_is_admin = false ) + { + + // + $sql = "BEGIN SP_DELETE_SERVER_TOKEN(:P_CONSUMER_KEY, :P_USER_ID,:P_TOKEN, :P_USER_IS_ADMIN, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_CONSUMER_KEY', $consumer_key, 255); + oci_bind_by_name($stmt, ':P_USER_ID', $user_id, 40); + oci_bind_by_name($stmt, ':P_TOKEN', $token, 255); + oci_bind_by_name($stmt, ':P_USER_IS_ADMIN', $user_is_admin, 40); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Execute the statement + oci_execute($stmt); + // + + } + + + /** + * Set the ttl of a server access token. This is done when the + * server receives a valid request with a xoauth_token_ttl parameter in it. + * + * @param string consumer_key + * @param string token + * @param int token_ttl + */ + public function setServerTokenTtl ( $consumer_key, $token, $token_ttl ) + { + if ($token_ttl <= 0) + { + // Immediate delete when the token is past its ttl + $this->deleteServerToken($consumer_key, $token, 0, true); + } + else + { + // Set maximum time to live for this token + + // + $sql = "BEGIN SP_SET_SERVER_TOKEN_TTL(:P_TOKEN_TTL, :P_CONSUMER_KEY, :P_TOKEN, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_TOKEN_TTL', $token_ttl, 40); + oci_bind_by_name($stmt, ':P_CONSUMER_KEY', $consumer_key, 255); + oci_bind_by_name($stmt, ':P_TOKEN', $token, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Execute the statement + oci_execute($stmt); + // + } + } + + + /** + * Get a list of all consumers from the consumer registry. + * The consumer keys belong to the user or are public (user id is null) + * + * @param string q query term + * @param int user_id + * @return array + */ + public function listServers ( $q = '', $user_id ) + { + $q = trim(str_replace('%', '', $q)); + $args = array(); + + + // + $sql = "BEGIN SP_LIST_SERVERS(:P_Q, :P_USER_ID, :P_ROWS, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_Q', $q, 255); + oci_bind_by_name($stmt, ':P_USER_ID', $user_id, 40); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Bind the ref cursor + $p_row = oci_new_cursor($this->conn); + oci_bind_by_name($stmt, ':P_ROWS', $p_row, -1, OCI_B_CURSOR); + + //Execute the statement + oci_execute($stmt); + + // treat the ref cursor as a statement resource + oci_execute($p_row, OCI_DEFAULT); + oci_fetch_all($p_row, $listServersList, null, null, OCI_FETCHSTATEMENT_BY_ROW); + $servers = $listServersList; + // + + return $servers; + } + + + /** + * Register or update a server for our site (we will be the consumer) + * + * (This is the registry at the consumers, registering servers ;-) ) + * + * @param array server + * @param int user_id user registering this server + * @param boolean user_is_admin + * @exception OAuthException2 when fields are missing or on duplicate consumer_key + * @return consumer_key + */ + public function updateServer ( $server, $user_id, $user_is_admin = false ) { + foreach (array('consumer_key', 'server_uri') as $f) { + if (empty($server[$f])) { + throw new OAuthException2('The field "'.$f.'" must be set and non empty'); + } + } + $parts = parse_url($server['server_uri']); + $host = (isset($parts['host']) ? $parts['host'] : 'localhost'); + $path = (isset($parts['path']) ? $parts['path'] : '/'); + + if (isset($server['signature_methods'])) { + if (is_array($server['signature_methods'])) { + $server['signature_methods'] = strtoupper(implode(',', $server['signature_methods'])); + } + } + else { + $server['signature_methods'] = ''; + } + // When the user is an admin, then the user can update the user_id of this record + if ($user_is_admin && array_key_exists('user_id', $server)) { + $flag=1; + } + if($flag) { + if (is_null($server['user_id'])) { + $ocr_usa_id_ref= NULL; + } + else { + $ocr_usa_id_ref = $server['user_id']; + } + } + else { + $flag=0; + $ocr_usa_id_ref=$user_id; + } + //sp + $sql = "BEGIN SP_UPDATE_SERVER(:P_CONSUMER_KEY, :P_USER_ID, :P_OCR_ID, :P_USER_IS_ADMIN, + :P_OCR_CONSUMER_SECRET, :P_OCR_SERVER_URI, :P_OCR_SERVER_URI_HOST, :P_OCR_SERVER_URI_PATH, + :P_OCR_REQUEST_TOKEN_URI, :P_OCR_AUTHORIZE_URI, :P_OCR_ACCESS_TOKEN_URI, :P_OCR_SIGNATURE_METHODS, + :P_OCR_USA_ID_REF, :P_UPDATE_P_OCR_USA_ID_REF_FLAG, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + $server['request_token_uri'] = isset($server['request_token_uri']) ? $server['request_token_uri'] : ''; + $server['authorize_uri'] = isset($server['authorize_uri']) ? $server['authorize_uri'] : ''; + $server['access_token_uri'] = isset($server['access_token_uri']) ? $server['access_token_uri'] : ''; + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_CONSUMER_KEY', $server['consumer_key'], 255); + oci_bind_by_name($stmt, ':P_USER_ID', $user_id, 40); + oci_bind_by_name($stmt, ':P_OCR_ID', $server['id'], 40); + oci_bind_by_name($stmt, ':P_USER_IS_ADMIN', $user_is_admin, 40); + oci_bind_by_name($stmt, ':P_OCR_CONSUMER_SECRET', $server['consumer_secret'], 255); + oci_bind_by_name($stmt, ':P_OCR_SERVER_URI', $server['server_uri'], 255); + oci_bind_by_name($stmt, ':P_OCR_SERVER_URI_HOST', strtolower($host), 255); + oci_bind_by_name($stmt, ':P_OCR_SERVER_URI_PATH', $path, 255); + oci_bind_by_name($stmt, ':P_OCR_REQUEST_TOKEN_URI', $server['request_token_uri'], 255); + oci_bind_by_name($stmt, ':P_OCR_AUTHORIZE_URI', $server['authorize_uri'], 255); + oci_bind_by_name($stmt, ':P_OCR_ACCESS_TOKEN_URI', $server['access_token_uri'], 255); + oci_bind_by_name($stmt, ':P_OCR_SIGNATURE_METHODS', $server['signature_methods'], 255); + oci_bind_by_name($stmt, ':P_OCR_USA_ID_REF', $ocr_usa_id_ref, 40); + oci_bind_by_name($stmt, ':P_UPDATE_P_OCR_USA_ID_REF_FLAG', $flag, 40); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Execute the statement + oci_execute($stmt); + + return $server['consumer_key']; + } + + /** + * Insert/update a new consumer with this server (we will be the server) + * When this is a new consumer, then also generate the consumer key and secret. + * Never updates the consumer key and secret. + * When the id is set, then the key and secret must correspond to the entry + * being updated. + * + * (This is the registry at the server, registering consumers ;-) ) + * + * @param array consumer + * @param int user_id user registering this consumer + * @param boolean user_is_admin + * @return string consumer key + */ + public function updateConsumer ( $consumer, $user_id, $user_is_admin = false ) { + $consumer_key = $this->generateKey(true); + $consumer_secret = $this->generateKey(); + + $consumer['callback_uri'] = isset($consumer['callback_uri'])? $consumer['callback_uri']: ''; + $consumer['application_uri'] = isset($consumer['application_uri'])? $consumer['application_uri']: ''; + $consumer['application_title'] = isset($consumer['application_title'])? $consumer['application_title']: ''; + $consumer['application_descr'] = isset($consumer['application_descr'])? $consumer['application_descr']: ''; + $consumer['application_notes'] = isset($consumer['application_notes'])? $consumer['application_notes']: ''; + $consumer['application_type'] = isset($consumer['application_type'])? $consumer['application_type']: ''; + $consumer['application_commercial'] = isset($consumer['application_commercial'])?$consumer['application_commercial']:0; + + //sp + $sql = "BEGIN SP_UPDATE_CONSUMER(:P_OSR_USA_ID_REF, :P_OSR_CONSUMER_KEY, :P_OSR_CONSUMER_SECRET, :P_OSR_REQUESTER_NAME, :P_OSR_REQUESTER_EMAIL, :P_OSR_CALLBACK_URI, :P_OSR_APPLICATION_URI, :P_OSR_APPLICATION_TITLE , :P_OSR_APPLICATION_DESCR, :P_OSR_APPLICATION_NOTES, :P_OSR_APPLICATION_TYPE, :P_OSR_APPLICATION_COMMERCIAL, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_OSR_USA_ID_REF', $user_id, 40); + oci_bind_by_name($stmt, ':P_OSR_CONSUMER_KEY', $consumer_key, 255); + oci_bind_by_name($stmt, ':P_OSR_CONSUMER_SECRET', $consumer_secret, 255); + oci_bind_by_name($stmt, ':P_OSR_REQUESTER_NAME', $consumer['requester_name'], 255); + oci_bind_by_name($stmt, ':P_OSR_REQUESTER_EMAIL', $consumer['requester_email'], 255); + oci_bind_by_name($stmt, ':P_OSR_CALLBACK_URI', $consumer['callback_uri'], 255); + oci_bind_by_name($stmt, ':P_OSR_APPLICATION_URI', $consumer['application_uri'], 255); + oci_bind_by_name($stmt, ':P_OSR_APPLICATION_TITLE', $consumer['application_title'], 255); + oci_bind_by_name($stmt, ':P_OSR_APPLICATION_DESCR', $consumer['application_descr'], 255); + oci_bind_by_name($stmt, ':P_OSR_APPLICATION_NOTES', $consumer['application_notes'], 255); + oci_bind_by_name($stmt, ':P_OSR_APPLICATION_TYPE', $consumer['application_type'], 255); + oci_bind_by_name($stmt, ':P_OSR_APPLICATION_COMMERCIAL', $consumer['application_commercial'], 40); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Execute the statement + oci_execute($stmt); + echo $result; + return $consumer_key; + } + + + + /** + * Delete a consumer key. This removes access to our site for all applications using this key. + * + * @param string consumer_key + * @param int user_id user registering this server + * @param boolean user_is_admin + */ + public function deleteConsumer ( $consumer_key, $user_id, $user_is_admin = false ) + { + + // + $sql = "BEGIN SP_DELETE_CONSUMER(:P_CONSUMER_KEY, :P_USER_ID, :P_USER_IS_ADMIN, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_CONSUMER_KEY', $consumer_key, 255); + oci_bind_by_name($stmt, ':P_USER_ID', $user_id, 40); + oci_bind_by_name($stmt, ':P_USER_IS_ADMIN', $user_is_admin, 40); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Execute the statement + oci_execute($stmt); + // + } + + + + /** + * Fetch a consumer of this server, by consumer_key. + * + * @param string consumer_key + * @param int user_id + * @param boolean user_is_admin (optional) + * @exception OAuthException2 when consumer not found + * @return array + */ + public function getConsumer ( $consumer_key, $user_id, $user_is_admin = false ) { + + $sql = "BEGIN SP_GET_CONSUMER(:P_CONSUMER_KEY, :P_ROWS, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_CONSUMER_KEY', $consumer_key, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Bind the ref cursor + $p_row = oci_new_cursor($this->conn); + oci_bind_by_name($stmt, ':P_ROWS', $p_row, -1, OCI_B_CURSOR); + + //Execute the statement + oci_execute($stmt); + + // treat the ref cursor as a statement resource + oci_execute($p_row, OCI_DEFAULT); + oci_fetch_all($p_row, $getConsumerList, null, null, OCI_FETCHSTATEMENT_BY_ROW); + + $consumer = $getConsumerList; + + if (!is_array($consumer)) { + throw new OAuthException2('No consumer with consumer_key "'.$consumer_key.'"'); + } + + $c = array(); + foreach ($consumer as $key => $value) { + $c[substr($key, 4)] = $value; + } + $c['user_id'] = $c['usa_id_ref']; + + if (!$user_is_admin && !empty($c['user_id']) && $c['user_id'] != $user_id) { + throw new OAuthException2('No access to the consumer information for consumer_key "'.$consumer_key.'"'); + } + return $c; + } + + + /** + * Fetch the static consumer key for this provider. The user for the static consumer + * key is NULL (no user, shared key). If the key did not exist then the key is created. + * + * @return string + */ + public function getConsumerStatic () + { + + // + $sql = "BEGIN SP_GET_CONSUMER_STATIC_SELECT(:P_OSR_CONSUMER_KEY, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_OSR_CONSUMER_KEY', $consumer, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Execute the statement + oci_execute($stmt); + + if (empty($consumer)) + { + $consumer_key = 'sc-'.$this->generateKey(true); + + $sql = "BEGIN SP_CONSUMER_STATIC_SAVE(:P_OSR_CONSUMER_KEY, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_OSR_CONSUMER_KEY', $consumer_key, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Execute the statement + oci_execute($stmt); + + + // Just make sure that if the consumer key is truncated that we get the truncated string + $consumer = $consumer_key; + } + return $consumer; + } + + + /** + * Add an unautorized request token to our server. + * + * @param string consumer_key + * @param array options (eg. token_ttl) + * @return array (token, token_secret) + */ + public function addConsumerRequestToken ( $consumer_key, $options = array() ) + { + $token = $this->generateKey(true); + $secret = $this->generateKey(); + + + if (isset($options['token_ttl']) && is_numeric($options['token_ttl'])) + { + $ttl = intval($options['token_ttl']); + } + else + { + $ttl = $this->max_request_token_ttl; + } + + if (!isset($options['oauth_callback'])) { + // 1.0a Compatibility : store callback url associated with request token + $options['oauth_callback']='oob'; + } + $options_oauth_callback =$options['oauth_callback']; + $sql = "BEGIN SP_ADD_CONSUMER_REQUEST_TOKEN(:P_TOKEN_TTL, :P_CONSUMER_KEY, :P_TOKEN, :P_TOKEN_SECRET, :P_CALLBACK_URL, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_TOKEN_TTL', $ttl, 20); + oci_bind_by_name($stmt, ':P_CONSUMER_KEY', $consumer_key, 255); + oci_bind_by_name($stmt, ':P_TOKEN', $token, 255); + oci_bind_by_name($stmt, ':P_TOKEN_SECRET', $secret, 255); + oci_bind_by_name($stmt, ':P_CALLBACK_URL', $options_oauth_callback, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Execute the statement + oci_execute($stmt); + + + $returnArray= array('token'=>$token, 'token_secret'=>$secret, 'token_ttl'=>$ttl); + return $returnArray; + } + + + /** + * Fetch the consumer request token, by request token. + * + * @param string token + * @return array token and consumer details + */ + public function getConsumerRequestToken ( $token ) + { + + $sql = "BEGIN SP_GET_CONSUMER_REQUEST_TOKEN(:P_TOKEN, :P_ROWS, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_TOKEN', $token, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Bind the ref cursor + $p_row = oci_new_cursor($this->conn); + oci_bind_by_name($stmt, ':P_ROWS', $p_row, -1, OCI_B_CURSOR); + + //Execute the statement + oci_execute($stmt); + + // treat the ref cursor as a statement resource + oci_execute($p_row, OCI_DEFAULT); + + oci_fetch_all($p_row, $rs, null, null, OCI_FETCHSTATEMENT_BY_ROW); + + return $rs[0]; + } + + + /** + * Delete a consumer token. The token must be a request or authorized token. + * + * @param string token + */ + public function deleteConsumerRequestToken ( $token ) + { + + $sql = "BEGIN SP_DEL_CONSUMER_REQUEST_TOKEN(:P_TOKEN, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_TOKEN', $token, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Execute the statement + oci_execute($stmt); + } + + + /** + * Upgrade a request token to be an authorized request token. + * + * @param string token + * @param int user_id user authorizing the token + * @param string referrer_host used to set the referrer host for this token, for user feedback + */ + public function authorizeConsumerRequestToken ( $token, $user_id, $referrer_host = '' ) + { + // 1.0a Compatibility : create a token verifier + $verifier = substr(md5(rand()),0,10); + + $sql = "BEGIN SP_AUTH_CONSUMER_REQ_TOKEN(:P_USER_ID, :P_REFERRER_HOST, :P_VERIFIER, :P_TOKEN, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_USER_ID', $user_id, 255); + oci_bind_by_name($stmt, ':P_REFERRER_HOST', $referrer_host, 255); + oci_bind_by_name($stmt, ':P_VERIFIER', $verifier, 255); + oci_bind_by_name($stmt, ':P_TOKEN', $token, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + + //Execute the statement + oci_execute($stmt); + + return $verifier; + } + + + /** + * Count the consumer access tokens for the given consumer. + * + * @param string consumer_key + * @return int + */ + public function countConsumerAccessTokens ( $consumer_key ) + { + /*$count = $this->query_one(' + SELECT COUNT(ost_id) + FROM oauth_server_token + JOIN oauth_server_registry + ON ost_osr_id_ref = osr_id + WHERE ost_token_type = \'access\' + AND osr_consumer_key = \'%s\' + AND ost_token_ttl >= NOW() + ', $consumer_key); + */ + $sql = "BEGIN SP_COUNT_CONSUMER_ACCESS_TOKEN(:P_CONSUMER_KEY, :P_COUNT, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_CONSUMER_KEY', $consumer_key, 255); + oci_bind_by_name($stmt, ':P_COUNT', $count, 20); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + + //Execute the statement + oci_execute($stmt); + + return $count; + } + + + /** + * Exchange an authorized request token for new access token. + * + * @param string token + * @param array options options for the token, token_ttl + * @exception OAuthException2 when token could not be exchanged + * @return array (token, token_secret) + */ + public function exchangeConsumerRequestForAccessToken ( $token, $options = array() ) + { + $new_token = $this->generateKey(true); + $new_secret = $this->generateKey(); + + $sql = "BEGIN SP_EXCH_CONS_REQ_FOR_ACC_TOKEN(:P_TOKEN_TTL, :P_NEW_TOKEN, :P_TOKEN, :P_TOKEN_SECRET, :P_VERIFIER, :P_OUT_TOKEN_TTL, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_TOKEN_TTL', $options['token_ttl'], 255); + oci_bind_by_name($stmt, ':P_NEW_TOKEN', $new_token, 255); + oci_bind_by_name($stmt, ':P_TOKEN', $token, 255); + oci_bind_by_name($stmt, ':P_TOKEN_SECRET', $new_secret, 255); + oci_bind_by_name($stmt, ':P_VERIFIER', $options['verifier'], 255); + oci_bind_by_name($stmt, ':P_OUT_TOKEN_TTL', $ttl, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + + //Execute the statement + oci_execute($stmt); + + $ret = array('token' => $new_token, 'token_secret' => $new_secret); + if (is_numeric($ttl)) + { + $ret['token_ttl'] = intval($ttl); + } + return $ret; + } + + + /** + * Fetch the consumer access token, by access token. + * + * @param string token + * @param int user_id + * @exception OAuthException2 when token is not found + * @return array token and consumer details + */ + public function getConsumerAccessToken ( $token, $user_id ) + { + + $sql = "BEGIN SP_GET_CONSUMER_ACCESS_TOKEN(:P_USER_ID, :P_TOKEN, :P_ROWS :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_USER_ID',$user_id, 255); + oci_bind_by_name($stmt, ':P_TOKEN', $token, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Bind the ref cursor + $p_row = oci_new_cursor($this->conn); + oci_bind_by_name($stmt, ':P_ROWS', $p_row, -1, OCI_B_CURSOR); + + //Execute the statement + oci_execute($stmt); + + // treat the ref cursor as a statement resource + oci_execute($p_row, OCI_DEFAULT); + oci_fetch_all($p_row, $rs, null, null, OCI_FETCHSTATEMENT_BY_ROW); + if (empty($rs)) + { + throw new OAuthException2('No server_token "'.$token.'" for user "'.$user_id.'"'); + } + return $rs; + } + + + /** + * Delete a consumer access token. + * + * @param string token + * @param int user_id + * @param boolean user_is_admin + */ + public function deleteConsumerAccessToken ( $token, $user_id, $user_is_admin = false ) + { + /*if ($user_is_admin) + { + $this->query(' + DELETE FROM oauth_server_token + WHERE ost_token = \'%s\' + AND ost_token_type = \'access\' + ', $token); + } + else + { + $this->query(' + DELETE FROM oauth_server_token + WHERE ost_token = \'%s\' + AND ost_token_type = \'access\' + AND ost_usa_id_ref = %d + ', $token, $user_id); + }*/ + $sql = "BEGIN SP_DEL_CONSUMER_ACCESS_TOKEN(:P_USER_ID, :P_TOKEN, :P_USER_IS_ADMIN, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_USER_ID', $user_id, 255); + oci_bind_by_name($stmt, ':P_TOKEN', $token, 255); + oci_bind_by_name($stmt, ':P_USER_IS_ADMIN', $user_is_admin, 20); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + + //Execute the statement + oci_execute($stmt); + } + + + /** + * Set the ttl of a consumer access token. This is done when the + * server receives a valid request with a xoauth_token_ttl parameter in it. + * + * @param string token + * @param int ttl + */ + public function setConsumerAccessTokenTtl ( $token, $token_ttl ) + { + if ($token_ttl <= 0) + { + // Immediate delete when the token is past its ttl + $this->deleteConsumerAccessToken($token, 0, true); + } + else + { + // Set maximum time to live for this token + + + $sql = "BEGIN SP_SET_CONSUMER_ACC_TOKEN_TTL(:P_TOKEN, :P_TOKEN_TTL, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_TOKEN', $token, 255); + oci_bind_by_name($stmt, ':P_TOKEN_TTL', $token_ttl, 20); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + + //Execute the statement + oci_execute($stmt); + } + } + + + /** + * Fetch a list of all consumer keys, secrets etc. + * Returns the public (user_id is null) and the keys owned by the user + * + * @param int user_id + * @return array + */ + public function listConsumers ( $user_id ) + { + + $sql = "BEGIN SP_LIST_CONSUMERS(:P_USER_ID, :P_ROWS, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_USER_ID', $user_id, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Bind the ref cursor + $p_row = oci_new_cursor($this->conn); + oci_bind_by_name($stmt, ':P_ROWS', $p_row, -1, OCI_B_CURSOR); + + //Execute the statement + oci_execute($stmt); + + // treat the ref cursor as a statement resource + oci_execute($p_row, OCI_DEFAULT); + oci_fetch_all($p_row, $rs, null, null, OCI_FETCHSTATEMENT_BY_ROW); + + return $rs; + } + + /** + * List of all registered applications. Data returned has not sensitive + * information and therefore is suitable for public displaying. + * + * @param int $begin + * @param int $total + * @return array + */ + public function listConsumerApplications($begin = 0, $total = 25) + { + // TODO + return array(); + } + + /** + * Fetch a list of all consumer tokens accessing the account of the given user. + * + * @param int user_id + * @return array + */ + public function listConsumerTokens ( $user_id ) + { + + $sql = "BEGIN SP_LIST_CONSUMER_TOKENS(:P_USER_ID, :P_ROWS, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_USER_ID', $user_id, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Bind the ref cursor + $p_row = oci_new_cursor($this->conn); + oci_bind_by_name($stmt, ':P_ROWS', $p_row, -1, OCI_B_CURSOR); + + //Execute the statement + oci_execute($stmt); + + // treat the ref cursor as a statement resource + oci_execute($p_row, OCI_DEFAULT); + oci_fetch_all($p_row, $rs, null, null, OCI_FETCHSTATEMENT_BY_ROW); + + return $rs; + } + + + /** + * Check an nonce/timestamp combination. Clears any nonce combinations + * that are older than the one received. + * + * @param string consumer_key + * @param string token + * @param int timestamp + * @param string nonce + * @exception OAuthException2 thrown when the timestamp is not in sequence or nonce is not unique + */ + public function checkServerNonce ( $consumer_key, $token, $timestamp, $nonce ) + { + + $sql = "BEGIN SP_CHECK_SERVER_NONCE(:P_CONSUMER_KEY, :P_TOKEN, :P_TIMESTAMP, :P_MAX_TIMESTAMP_SKEW, :P_NONCE, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_CONSUMER_KEY', $consumer_key, 255); + oci_bind_by_name($stmt, ':P_TOKEN', $token, 255); + oci_bind_by_name($stmt, ':P_TIMESTAMP', $timestamp, 255); + oci_bind_by_name($stmt, ':P_MAX_TIMESTAMP_SKEW', $this->max_timestamp_skew, 20); + oci_bind_by_name($stmt, ':P_NONCE', $nonce, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + + //Execute the statement + oci_execute($stmt); + + } + + + /** + * Add an entry to the log table + * + * @param array keys (osr_consumer_key, ost_token, ocr_consumer_key, oct_token) + * @param string received + * @param string sent + * @param string base_string + * @param string notes + * @param int (optional) user_id + */ + public function addLog ( $keys, $received, $sent, $base_string, $notes, $user_id = null ) + { + $args = array(); + $ps = array(); + foreach ($keys as $key => $value) + { + $args[] = $value; + $ps[] = "olg_$key = '%s'"; + } + + if (!empty($_SERVER['REMOTE_ADDR'])) + { + $remote_ip = $_SERVER['REMOTE_ADDR']; + } + else if (!empty($_SERVER['REMOTE_IP'])) + { + $remote_ip = $_SERVER['REMOTE_IP']; + } + else + { + $remote_ip = '0.0.0.0'; + } + + // Build the SQL + $olg_received = $this->makeUTF8($received); + $olg_sent = $this->makeUTF8($sent); + $olg_base_string = $base_string; + $olg_notes = $this->makeUTF8($notes); + $olg_usa_id_ref = $user_id; + $olg_remote_ip = $remote_ip; + + + + $sql = "BEGIN SP_ADD_LOG(:P_RECEIVED, :P_SENT, :P_BASE_STRING, :P_NOTES, :P_USA_ID_REF, :P_REMOTE_IP, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_RECEIVED', $olg_received, 255); + oci_bind_by_name($stmt, ':P_SENT', $olg_sent, 255); + oci_bind_by_name($stmt, ':P_BASE_STRING', $olg_base_string, 255); + oci_bind_by_name($stmt, ':P_NOTES', $olg_notes, 255); + oci_bind_by_name($stmt, ':P_USA_ID_REF', $olg_usa_id_ref, 255); + oci_bind_by_name($stmt, ':P_REMOTE_IP', $olg_remote_ip, 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + + //Execute the statement + oci_execute($stmt); + } + + + /** + * Get a page of entries from the log. Returns the last 100 records + * matching the options given. + * + * @param array options + * @param int user_id current user + * @return array log records + */ + public function listLog ( $options, $user_id ) + { + + if (empty($options)) + { + $optionsFlag=NULL; + + } + else + { + $optionsFlag=1; + + } + + $sql = "BEGIN SP_LIST_LOG(:P_OPTION_FLAG, :P_USA_ID, :P_OSR_CONSUMER_KEY, :P_OCR_CONSUMER_KEY, :P_OST_TOKEN, :P_OCT_TOKEN, :P_ROWS, :P_RESULT); END;"; + + // parse sql + $stmt = oci_parse($this->conn, $sql) or die ('Can not parse query'); + + // Bind In and Out Variables + oci_bind_by_name($stmt, ':P_OPTION_FLAG', $optionsFlag, 255); + oci_bind_by_name($stmt, ':P_USA_ID', $user_id, 40); + oci_bind_by_name($stmt, ':P_OSR_CONSUMER_KEY', $options['osr_consumer_key'], 255); + oci_bind_by_name($stmt, ':P_OCR_CONSUMER_KEY', $options['ocr_consumer_key'], 255); + oci_bind_by_name($stmt, ':P_OST_TOKEN', $options['ost_token'], 255); + oci_bind_by_name($stmt, ':P_OCT_TOKEN', $options['oct_token'], 255); + oci_bind_by_name($stmt, ':P_RESULT', $result, 20); + + //Bind the ref cursor + $p_row = oci_new_cursor($this->conn); + oci_bind_by_name($stmt, ':P_ROWS', $p_row, -1, OCI_B_CURSOR); + + //Execute the statement + oci_execute($stmt); + + // treat the ref cursor as a statement resource + oci_execute($p_row, OCI_DEFAULT); + oci_fetch_all($p_row, $rs, null, null, OCI_FETCHSTATEMENT_BY_ROW); + + return $rs; + } + + /** + * Initialise the database + */ + public function install () + { + require_once dirname(__FILE__) . '/oracle/install.php'; + } +} + + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/store/OAuthStorePDO.php b/includes/oauth-php/library/store/OAuthStorePDO.php new file mode 100644 index 00000000..821d79b9 --- /dev/null +++ b/includes/oauth-php/library/store/OAuthStorePDO.php @@ -0,0 +1,274 @@ + Based on code by Marc Worrell + * + * + * 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__) . '/OAuthStoreSQL.php'; + + +class OAuthStorePDO extends OAuthStoreSQL +{ + private $conn; // PDO connection + private $lastaffectedrows; + + /** + * Construct the OAuthStorePDO. + * In the options you have to supply either: + * - dsn, username, password and database (for a new PDO connection) + * - conn (for the connection to be used) + * + * @param array options + */ + function __construct ( $options = array() ) + { + if (isset($options['conn'])) + { + $this->conn = $options['conn']; + } + else if (isset($options['dsn'])) + { + try + { + $this->conn = new PDO($options['dsn'], $options['username'], @$options['password']); + } + catch (PDOException $e) + { + throw new OAuthException2('Could not connect to PDO database: ' . $e->getMessage()); + } + + $this->query('set character set utf8'); + } + } + + /** + * Perform a query, ignore the results + * + * @param string sql + * @param vararg arguments (for sprintf) + */ + protected function query ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + try + { + $this->lastaffectedrows = $this->conn->exec($sql); + if ($this->lastaffectedrows === FALSE) { + $this->sql_errcheck($sql); + } + } + catch (PDOException $e) + { + $this->sql_errcheck($sql); + } + } + + + /** + * Perform a query, ignore the results + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + protected function query_all_assoc ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + $result = array(); + + try + { + $stmt = $this->conn->query($sql); + + $result = $stmt->fetchAll(PDO::FETCH_ASSOC); + } + catch (PDOException $e) + { + $this->sql_errcheck($sql); + } + return $result; + } + + + /** + * Perform a query, return the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + protected function query_row_assoc ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + $result = $this->query_all_assoc($sql); + $val = array_pop($result); + return $val; + } + + + /** + * Perform a query, return the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + protected function query_row ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + try + { + $all = $this->conn->query($sql, PDO::FETCH_NUM); + $row = array(); + foreach ($all as $r) { + $row = $r; + break; + } + } + catch (PDOException $e) + { + $this->sql_errcheck($sql); + } + return $row; + } + + + /** + * Perform a query, return the first column of the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return mixed + */ + protected function query_one ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + $row = $this->query_row($sql); + $val = array_pop($row); + return $val; + } + + + /** + * Return the number of rows affected in the last query + */ + protected function query_affected_rows () + { + return $this->lastaffectedrows; + } + + + /** + * Return the id of the last inserted row + * + * @return int + */ + protected function query_insert_id () + { + return $this->conn->lastInsertId(); + } + + + protected function sql_printf ( $args ) + { + $sql = array_shift($args); + if (count($args) == 1 && is_array($args[0])) + { + $args = $args[0]; + } + $args = array_map(array($this, 'sql_escape_string'), $args); + return vsprintf($sql, $args); + } + + + protected function sql_escape_string ( $s ) + { + if (is_string($s)) + { + $s = $this->conn->quote($s); + // kludge. Quote already adds quotes, and this conflicts with OAuthStoreSQL. + // so remove the quotes + $len = mb_strlen($s); + if ($len == 0) + return $s; + + $startcut = 0; + while (isset($s[$startcut]) && $s[$startcut] == '\'') + $startcut++; + + $endcut = $len-1; + while (isset($s[$endcut]) && $s[$endcut] == '\'') + $endcut--; + + $s = mb_substr($s, $startcut, $endcut-$startcut+1); + return $s; + } + else if (is_null($s)) + { + return NULL; + } + else if (is_bool($s)) + { + return intval($s); + } + else if (is_int($s) || is_float($s)) + { + return $s; + } + else + { + return $this->conn->quote(strval($s)); + } + } + + + protected function sql_errcheck ( $sql ) + { + $msg = "SQL Error in OAuthStoreMySQL: ". print_r($this->conn->errorInfo(), true) ."\n\n" . $sql; + $backtrace = debug_backtrace(); + $msg .= "\n\nAt file " . $backtrace[1]['file'] . ", line " . $backtrace[1]['line']; + throw new OAuthException2($msg); + } + + /** + * Initialise the database + */ + public function install () + { + // TODO: this depends on mysql extension + require_once dirname(__FILE__) . '/mysql/install.php'; + } + +} + + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/store/OAuthStorePostgreSQL.php b/includes/oauth-php/library/store/OAuthStorePostgreSQL.php new file mode 100644 index 00000000..04b9f046 --- /dev/null +++ b/includes/oauth-php/library/store/OAuthStorePostgreSQL.php @@ -0,0 +1,1957 @@ + + * @link http://elma.fr + * + * @Id 2010-10-22 10:07:18 ndelanoe $ + * @version $Id: OAuthStorePostgreSQL.php 175 2010-11-24 19:52:24Z brunobg@corollarium.com $ + * + * 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__) . '/OAuthStoreAbstract.class.php'; + + +class OAuthStorePostgreSQL extends OAuthStoreAbstract +{ + /** + * Maximum delta a timestamp may be off from a previous timestamp. + * Allows multiple consumers with some clock skew to work with the same token. + * Unit is seconds, default max skew is 10 minutes. + */ + protected $max_timestamp_skew = 600; + + /** + * Default ttl for request tokens + */ + protected $max_request_token_ttl = 3600; + + /** + * Number of affected rowsby the last queries + */ + private $_lastAffectedRows = 0; + + public function install() + { + throw new OAuthException2('Not yet implemented, see postgresql/pgsql.sql'); + } + + /** + * Construct the OAuthStorePostgrSQL. + * In the options you have to supply either: + * - server, username, password and database (for a pg_connect) + * - connectionString (for a pg_connect) + * - conn (for the connection to be used) + * + * @param array options + */ + function __construct ( $options = array() ) + { + if (isset($options['conn'])) + { + $this->conn = $options['conn']; + } + else + { + if (isset($options['server'])) + { + $host = $options['server']; + $user = $options['username']; + $dbname = $options['database']; + + $connectionString = sprintf('host=%s dbname=%s user=%s', $host, $dbname, $user); + + if (isset($options['password'])) + { + $connectionString .= ' password=' . $options['password']; + } + + $this->conn = pg_connect($connectionString); + } + elseif (isset($options['connectionString'])) + { + $this->conn = pg_connect($options['connectionString']); + } + else { + + // Try the default pg connect + $this->conn = pg_connect(); + } + + if ($this->conn === false) + { + throw new OAuthException2('Could not connect to PostgresSQL database'); + } + } + } + + /** + * Find stored credentials for the consumer key and token. Used by an OAuth server + * when verifying an OAuth request. + * + * @param string consumer_key + * @param string token + * @param string token_type false, 'request' or 'access' + * @exception OAuthException2 when no secrets where found + * @return array assoc (consumer_secret, token_secret, osr_id, ost_id, user_id) + */ + public function getSecretsForVerify ( $consumer_key, $token, $token_type = 'access' ) + { + if ($token_type === false) + { + $rs = $this->query_row_assoc(' + SELECT osr_id, + osr_consumer_key as consumer_key, + osr_consumer_secret as consumer_secret + FROM oauth_server_registry + WHERE osr_consumer_key = \'%s\' + AND osr_enabled = \'1\' + ', + $consumer_key); + + if ($rs) + { + $rs['token'] = false; + $rs['token_secret'] = false; + $rs['user_id'] = false; + $rs['ost_id'] = false; + } + } + else + { + $rs = $this->query_row_assoc(' + SELECT osr_id, + ost_id, + ost_usa_id_ref as user_id, + osr_consumer_key as consumer_key, + osr_consumer_secret as consumer_secret, + ost_token as token, + ost_token_secret as token_secret + FROM oauth_server_registry + JOIN oauth_server_token + ON ost_osr_id_ref = osr_id + WHERE ost_token_type = \'%s\' + AND osr_consumer_key = \'%s\' + AND ost_token = \'%s\' + AND osr_enabled = \'1\' + AND ost_token_ttl >= NOW() + ', + $token_type, $consumer_key, $token); + } + + if (empty($rs)) + { + throw new OAuthException2('The consumer_key "'.$consumer_key.'" token "'.$token.'" combination does not exist or is not enabled.'); + } + return $rs; + } + + /** + * Find the server details for signing a request, always looks for an access token. + * The returned credentials depend on which local user is making the request. + * + * The consumer_key must belong to the user or be public (user id is null) + * + * For signing we need all of the following: + * + * consumer_key consumer key associated with the server + * consumer_secret consumer secret associated with this server + * token access token associated with this server + * token_secret secret for the access token + * signature_methods signing methods supported by the server (array) + * + * @todo filter on token type (we should know how and with what to sign this request, and there might be old access tokens) + * @param string uri uri of the server + * @param int user_id id of the logged on user + * @param string name (optional) name of the token (case sensitive) + * @exception OAuthException2 when no credentials found + * @return array + */ + public function getSecretsForSignature ( $uri, $user_id, $name = '' ) + { + // Find a consumer key and token for the given uri + $ps = parse_url($uri); + $host = isset($ps['host']) ? $ps['host'] : 'localhost'; + $path = isset($ps['path']) ? $ps['path'] : ''; + + if (empty($path) || substr($path, -1) != '/') + { + $path .= '/'; + } + + // The owner of the consumer_key is either the user or nobody (public consumer key) + $secrets = $this->query_row_assoc(' + SELECT ocr_consumer_key as consumer_key, + ocr_consumer_secret as consumer_secret, + oct_token as token, + oct_token_secret as token_secret, + ocr_signature_methods as signature_methods + FROM oauth_consumer_registry + JOIN oauth_consumer_token ON oct_ocr_id_ref = ocr_id + WHERE ocr_server_uri_host = \'%s\' + AND ocr_server_uri_path = SUBSTR(\'%s\', 1, LENGTH(ocr_server_uri_path)) + AND (ocr_usa_id_ref = \'%s\' OR ocr_usa_id_ref IS NULL) + AND oct_usa_id_ref = \'%d\' + AND oct_token_type = \'access\' + AND oct_name = \'%s\' + AND oct_token_ttl >= NOW() + ORDER BY ocr_usa_id_ref DESC, ocr_consumer_secret DESC, LENGTH(ocr_server_uri_path) DESC + LIMIT 1 + ', $host, $path, $user_id, $user_id, $name + ); + + if (empty($secrets)) + { + throw new OAuthException2('No server tokens available for '.$uri); + } + $secrets['signature_methods'] = explode(',', $secrets['signature_methods']); + return $secrets; + } + + /** + * Get the token and token secret we obtained from a server. + * + * @param string consumer_key + * @param string token + * @param string token_type + * @param int user_id the user owning the token + * @param string name optional name for a named token + * @exception OAuthException2 when no credentials found + * @return array + */ + public function getServerTokenSecrets ( $consumer_key, $token, $token_type, $user_id, $name = '' ) + { + if ($token_type != 'request' && $token_type != 'access') + { + throw new OAuthException2('Unkown token type "'.$token_type.'", must be either "request" or "access"'); + } + + // Take the most recent token of the given type + $r = $this->query_row_assoc(' + SELECT ocr_consumer_key as consumer_key, + ocr_consumer_secret as consumer_secret, + oct_token as token, + oct_token_secret as token_secret, + oct_name as token_name, + ocr_signature_methods as signature_methods, + ocr_server_uri as server_uri, + ocr_request_token_uri as request_token_uri, + ocr_authorize_uri as authorize_uri, + ocr_access_token_uri as access_token_uri, + CASE WHEN oct_token_ttl >= \'9999-12-31\' THEN NULL ELSE oct_token_ttl - NOW() END as token_ttl + FROM oauth_consumer_registry + JOIN oauth_consumer_token + ON oct_ocr_id_ref = ocr_id + WHERE ocr_consumer_key = \'%s\' + AND oct_token_type = \'%s\' + AND oct_token = \'%s\' + AND oct_usa_id_ref = \'%d\' + AND oct_token_ttl >= NOW() + ', $consumer_key, $token_type, $token, $user_id + ); + + if (empty($r)) + { + throw new OAuthException2('Could not find a "'.$token_type.'" token for consumer "'.$consumer_key.'" and user '.$user_id); + } + if (isset($r['signature_methods']) && !empty($r['signature_methods'])) + { + $r['signature_methods'] = explode(',',$r['signature_methods']); + } + else + { + $r['signature_methods'] = array(); + } + return $r; + } + + + /** + * Add a request token we obtained from a server. + * + * @todo remove old tokens for this user and this ocr_id + * @param string consumer_key key of the server in the consumer registry + * @param string token_type one of 'request' or 'access' + * @param string token + * @param string token_secret + * @param int user_id the user owning the token + * @param array options extra options, name and token_ttl + * @exception OAuthException2 when server is not known + * @exception OAuthException2 when we received a duplicate token + */ + public function addServerToken ( $consumer_key, $token_type, $token, $token_secret, $user_id, $options = array() ) + { + if ($token_type != 'request' && $token_type != 'access') + { + throw new OAuthException2('Unknown token type "'.$token_type.'", must be either "request" or "access"'); + } + + // Maximum time to live for this token + if (isset($options['token_ttl']) && is_numeric($options['token_ttl'])) + { + $ttl = 'NOW() + INTERVAL \''.intval($options['token_ttl']).' SECOND\''; + } + else if ($token_type == 'request') + { + $ttl = 'NOW() + INTERVAL \''.$this->max_request_token_ttl.' SECOND\''; + } + else + { + $ttl = "'9999-12-31'"; + } + + if (isset($options['server_uri'])) + { + $ocr_id = $this->query_one(' + SELECT ocr_id + FROM oauth_consumer_registry + WHERE ocr_consumer_key = \'%s\' + AND ocr_usa_id_ref = \'%d\' + AND ocr_server_uri = \'%s\' + ', $consumer_key, $user_id, $options['server_uri']); + } + else + { + $ocr_id = $this->query_one(' + SELECT ocr_id + FROM oauth_consumer_registry + WHERE ocr_consumer_key = \'%s\' + AND ocr_usa_id_ref = \'%d\' + ', $consumer_key, $user_id); + } + + if (empty($ocr_id)) + { + throw new OAuthException2('No server associated with consumer_key "'.$consumer_key.'"'); + } + + // Named tokens, unique per user/consumer key + if (isset($options['name']) && $options['name'] != '') + { + $name = $options['name']; + } + else + { + $name = ''; + } + + // Delete any old tokens with the same type and name for this user/server combination + $this->query(' + DELETE FROM oauth_consumer_token + WHERE oct_ocr_id_ref = %d + AND oct_usa_id_ref = \'%d\' + AND oct_token_type::text = LOWER(\'%s\')::text + AND oct_name = \'%s\' + ', + $ocr_id, + $user_id, + $token_type, + $name); + + // Insert the new token + $this->query(' + INSERT INTO + oauth_consumer_token( + oct_ocr_id_ref, + oct_usa_id_ref, + oct_name, + oct_token, + oct_token_secret, + oct_token_type, + oct_timestamp, + oct_token_ttl + ) + VALUES (%d,%d,\'%s\',\'%s\',\'%s\',\'%s\',NOW(),'.$ttl.')', + $ocr_id, + $user_id, + $name, + $token, + $token_secret, + $token_type); + + if (!$this->query_affected_rows()) + { + throw new OAuthException2('Received duplicate token "'.$token.'" for the same consumer_key "'.$consumer_key.'"'); + } + } + + /** + * Delete a server key. This removes access to that site. + * + * @param string consumer_key + * @param int user_id user registering this server + * @param boolean user_is_admin + */ + public function deleteServer ( $consumer_key, $user_id, $user_is_admin = false ) + { + if ($user_is_admin) + { + $this->query(' + DELETE FROM oauth_consumer_registry + WHERE ocr_consumer_key = \'%s\' + AND (ocr_usa_id_ref = \'%d\' OR ocr_usa_id_ref IS NULL) + ', $consumer_key, $user_id); + } + else + { + $this->query(' + DELETE FROM oauth_consumer_registry + WHERE ocr_consumer_key = \'%s\' + AND ocr_usa_id_ref = \'%d\' + ', $consumer_key, $user_id); + } + } + + + /** + * Get a server from the consumer registry using the consumer key + * + * @param string consumer_key + * @param int user_id + * @param boolean user_is_admin (optional) + * @exception OAuthException2 when server is not found + * @return array + */ + public function getServer ( $consumer_key, $user_id, $user_is_admin = false ) + { + $r = $this->query_row_assoc(' + SELECT ocr_id as id, + ocr_usa_id_ref as user_id, + ocr_consumer_key as consumer_key, + ocr_consumer_secret as consumer_secret, + ocr_signature_methods as signature_methods, + ocr_server_uri as server_uri, + ocr_request_token_uri as request_token_uri, + ocr_authorize_uri as authorize_uri, + ocr_access_token_uri as access_token_uri + FROM oauth_consumer_registry + WHERE ocr_consumer_key = \'%s\' + AND (ocr_usa_id_ref = \'%d\' OR ocr_usa_id_ref IS NULL) + ', $consumer_key, $user_id); + + if (empty($r)) + { + throw new OAuthException2('No server with consumer_key "'.$consumer_key.'" has been registered (for this user)'); + } + + if (isset($r['signature_methods']) && !empty($r['signature_methods'])) + { + $r['signature_methods'] = explode(',',$r['signature_methods']); + } + else + { + $r['signature_methods'] = array(); + } + return $r; + } + + + /** + * Find the server details that might be used for a request + * + * The consumer_key must belong to the user or be public (user id is null) + * + * @param string uri uri of the server + * @param int user_id id of the logged on user + * @exception OAuthException2 when no credentials found + * @return array + */ + public function getServerForUri ( $uri, $user_id ) + { + // Find a consumer key and token for the given uri + $ps = parse_url($uri); + $host = isset($ps['host']) ? $ps['host'] : 'localhost'; + $path = isset($ps['path']) ? $ps['path'] : ''; + + if (empty($path) || substr($path, -1) != '/') + { + $path .= '/'; + } + + // The owner of the consumer_key is either the user or nobody (public consumer key) + $server = $this->query_row_assoc(' + SELECT ocr_id as id, + ocr_usa_id_ref as user_id, + ocr_consumer_key as consumer_key, + ocr_consumer_secret as consumer_secret, + ocr_signature_methods as signature_methods, + ocr_server_uri as server_uri, + ocr_request_token_uri as request_token_uri, + ocr_authorize_uri as authorize_uri, + ocr_access_token_uri as access_token_uri + FROM oauth_consumer_registry + WHERE ocr_server_uri_host = \'%s\' + AND ocr_server_uri_path = SUBSTR(\'%s\', 1, LENGTH(ocr_server_uri_path)) + AND (ocr_usa_id_ref = \'%s\' OR ocr_usa_id_ref IS NULL) + ORDER BY ocr_usa_id_ref DESC, consumer_secret DESC, LENGTH(ocr_server_uri_path) DESC + LIMIT 1 + ', $host, $path, $user_id + ); + + if (empty($server)) + { + throw new OAuthException2('No server available for '.$uri); + } + $server['signature_methods'] = explode(',', $server['signature_methods']); + return $server; + } + + /** + * Get a list of all server token this user has access to. + * + * @param int usr_id + * @return array + */ + public function listServerTokens ( $user_id ) + { + $ts = $this->query_all_assoc(' + SELECT ocr_consumer_key as consumer_key, + ocr_consumer_secret as consumer_secret, + oct_id as token_id, + oct_token as token, + oct_token_secret as token_secret, + oct_usa_id_ref as user_id, + ocr_signature_methods as signature_methods, + ocr_server_uri as server_uri, + ocr_server_uri_host as server_uri_host, + ocr_server_uri_path as server_uri_path, + ocr_request_token_uri as request_token_uri, + ocr_authorize_uri as authorize_uri, + ocr_access_token_uri as access_token_uri, + oct_timestamp as timestamp + FROM oauth_consumer_registry + JOIN oauth_consumer_token + ON oct_ocr_id_ref = ocr_id + WHERE oct_usa_id_ref = \'%d\' + AND oct_token_type = \'access\' + AND oct_token_ttl >= NOW() + ORDER BY ocr_server_uri_host, ocr_server_uri_path + ', $user_id); + return $ts; + } + + /** + * Count how many tokens we have for the given server + * + * @param string consumer_key + * @return int + */ + public function countServerTokens ( $consumer_key ) + { + $count = $this->query_one(' + SELECT COUNT(oct_id) + FROM oauth_consumer_token + JOIN oauth_consumer_registry + ON oct_ocr_id_ref = ocr_id + WHERE oct_token_type = \'access\' + AND ocr_consumer_key = \'%s\' + AND oct_token_ttl >= NOW() + ', $consumer_key); + + return $count; + } + + /** + * Get a specific server token for the given user + * + * @param string consumer_key + * @param string token + * @param int user_id + * @exception OAuthException2 when no such token found + * @return array + */ + public function getServerToken ( $consumer_key, $token, $user_id ) + { + $ts = $this->query_row_assoc(' + SELECT ocr_consumer_key as consumer_key, + ocr_consumer_secret as consumer_secret, + oct_token as token, + oct_token_secret as token_secret, + oct_usa_id_ref as usr_id, + ocr_signature_methods as signature_methods, + ocr_server_uri as server_uri, + ocr_server_uri_host as server_uri_host, + ocr_server_uri_path as server_uri_path, + ocr_request_token_uri as request_token_uri, + ocr_authorize_uri as authorize_uri, + ocr_access_token_uri as access_token_uri, + oct_timestamp as timestamp + FROM oauth_consumer_registry + JOIN oauth_consumer_token + ON oct_ocr_id_ref = ocr_id + WHERE ocr_consumer_key = \'%s\' + AND oct_usa_id_ref = \'%d\' + AND oct_token_type = \'access\' + AND oct_token = \'%s\' + AND oct_token_ttl >= NOW() + ', $consumer_key, $user_id, $token); + + if (empty($ts)) + { + throw new OAuthException2('No such consumer key ('.$consumer_key.') and token ('.$token.') combination for user "'.$user_id.'"'); + } + return $ts; + } + + + /** + * Delete a token we obtained from a server. + * + * @param string consumer_key + * @param string token + * @param int user_id + * @param boolean user_is_admin + */ + public function deleteServerToken ( $consumer_key, $token, $user_id, $user_is_admin = false ) + { + if ($user_is_admin) + { + $this->query(' + DELETE FROM oauth_consumer_token + USING oauth_consumer_registry + WHERE + oct_ocr_id_ref = ocr_id + AND ocr_consumer_key = \'%s\' + AND oct_token = \'%s\' + ', $consumer_key, $token); + } + else + { + $this->query(' + DELETE FROM oauth_consumer_token + USING oauth_consumer_registry + WHERE + oct_ocr_id_ref = ocr_id + AND ocr_consumer_key = \'%s\' + AND oct_token = \'%s\' + AND oct_usa_id_ref = \'%d\' + ', $consumer_key, $token, $user_id); + } + } + + /** + * Set the ttl of a server access token. This is done when the + * server receives a valid request with a xoauth_token_ttl parameter in it. + * + * @param string consumer_key + * @param string token + * @param int token_ttl + */ + public function setServerTokenTtl ( $consumer_key, $token, $token_ttl ) + { + if ($token_ttl <= 0) + { + // Immediate delete when the token is past its ttl + $this->deleteServerToken($consumer_key, $token, 0, true); + } + else + { + // Set maximum time to live for this token + $this->query(' + UPDATE oauth_consumer_token + SET ost_token_ttl = (NOW() + INTERVAL \'%d SECOND\') + WHERE ocr_consumer_key = \'%s\' + AND oct_ocr_id_ref = ocr_id + AND oct_token = \'%s\' + ', $token_ttl, $consumer_key, $token); + + // Set maximum time to live for this token + $this->query(' + UPDATE oauth_consumer_registry + SET ost_token_ttl = (NOW() + INTERVAL \'%d SECOND\') + WHERE ocr_consumer_key = \'%s\' + AND oct_ocr_id_ref = ocr_id + AND oct_token = \'%s\' + ', $token_ttl, $consumer_key, $token); + } + } + + /** + * Get a list of all consumers from the consumer registry. + * The consumer keys belong to the user or are public (user id is null) + * + * @param string q query term + * @param int user_id + * @return array + */ + public function listServers ( $q = '', $user_id ) + { + $q = trim(str_replace('%', '', $q)); + $args = array(); + + if (!empty($q)) + { + $where = ' WHERE ( ocr_consumer_key like \'%%%s%%\' + OR ocr_server_uri like \'%%%s%%\' + OR ocr_server_uri_host like \'%%%s%%\' + OR ocr_server_uri_path like \'%%%s%%\') + AND (ocr_usa_id_ref = \'%d\' OR ocr_usa_id_ref IS NULL) + '; + + $args[] = $q; + $args[] = $q; + $args[] = $q; + $args[] = $q; + $args[] = $user_id; + } + else + { + $where = ' WHERE ocr_usa_id_ref = \'%d\' OR ocr_usa_id_ref IS NULL'; + $args[] = $user_id; + } + + $servers = $this->query_all_assoc(' + SELECT ocr_id as id, + ocr_usa_id_ref as user_id, + ocr_consumer_key as consumer_key, + ocr_consumer_secret as consumer_secret, + ocr_signature_methods as signature_methods, + ocr_server_uri as server_uri, + ocr_server_uri_host as server_uri_host, + ocr_server_uri_path as server_uri_path, + ocr_request_token_uri as request_token_uri, + ocr_authorize_uri as authorize_uri, + ocr_access_token_uri as access_token_uri + FROM oauth_consumer_registry + '.$where.' + ORDER BY ocr_server_uri_host, ocr_server_uri_path + ', $args); + return $servers; + } + + /** + * Register or update a server for our site (we will be the consumer) + * + * (This is the registry at the consumers, registering servers ;-) ) + * + * @param array server + * @param int user_id user registering this server + * @param boolean user_is_admin + * @exception OAuthException2 when fields are missing or on duplicate consumer_key + * @return consumer_key + */ + public function updateServer ( $server, $user_id, $user_is_admin = false ) + { + foreach (array('consumer_key', 'server_uri') as $f) + { + if (empty($server[$f])) + { + throw new OAuthException2('The field "'.$f.'" must be set and non empty'); + } + } + + if (!empty($server['id'])) + { + $exists = $this->query_one(' + SELECT ocr_id + FROM oauth_consumer_registry + WHERE ocr_consumer_key = \'%s\' + AND ocr_id <> %d + AND (ocr_usa_id_ref = \'%d\' OR ocr_usa_id_ref IS NULL) + ', $server['consumer_key'], $server['id'], $user_id); + } + else + { + $exists = $this->query_one(' + SELECT ocr_id + FROM oauth_consumer_registry + WHERE ocr_consumer_key = \'%s\' + AND (ocr_usa_id_ref = \'%d\' OR ocr_usa_id_ref IS NULL) + ', $server['consumer_key'], $user_id); + } + + if ($exists) + { + throw new OAuthException2('The server with key "'.$server['consumer_key'].'" has already been registered'); + } + + $parts = parse_url($server['server_uri']); + $host = (isset($parts['host']) ? $parts['host'] : 'localhost'); + $path = (isset($parts['path']) ? $parts['path'] : '/'); + + if (isset($server['signature_methods'])) + { + if (is_array($server['signature_methods'])) + { + $server['signature_methods'] = strtoupper(implode(',', $server['signature_methods'])); + } + } + else + { + $server['signature_methods'] = ''; + } + + // When the user is an admin, then the user can update the user_id of this record + if ($user_is_admin && array_key_exists('user_id', $server)) + { + if (is_null($server['user_id'])) + { + $update_user = ', ocr_usa_id_ref = NULL'; + } + else + { + $update_user = ', ocr_usa_id_ref = \''. intval($server['user_id']) . '\''; + } + } + else + { + $update_user = ''; + } + + if (!empty($server['id'])) + { + // Check if the current user can update this server definition + if (!$user_is_admin) + { + $ocr_usa_id_ref = $this->query_one(' + SELECT ocr_usa_id_ref + FROM oauth_consumer_registry + WHERE ocr_id = %d + ', $server['id']); + + if ($ocr_usa_id_ref != $user_id) + { + throw new OAuthException2('The user "'.$user_id.'" is not allowed to update this server'); + } + } + + // Update the consumer registration + $this->query(' + UPDATE oauth_consumer_registry + SET ocr_consumer_key = \'%s\', + ocr_consumer_secret = \'%s\', + ocr_server_uri = \'%s\', + ocr_server_uri_host = \'%s\', + ocr_server_uri_path = \'%s\', + ocr_timestamp = NOW(), + ocr_request_token_uri = \'%s\', + ocr_authorize_uri = \'%s\', + ocr_access_token_uri = \'%s\', + ocr_signature_methods = \'%s\' + '.$update_user.' + WHERE ocr_id = %d + ', + $server['consumer_key'], + $server['consumer_secret'], + $server['server_uri'], + strtolower($host), + $path, + isset($server['request_token_uri']) ? $server['request_token_uri'] : '', + isset($server['authorize_uri']) ? $server['authorize_uri'] : '', + isset($server['access_token_uri']) ? $server['access_token_uri'] : '', + $server['signature_methods'], + $server['id'] + ); + } + else + { + $update_user_field = ''; + $update_user_value = ''; + if (empty($update_user)) + { + // Per default the user owning the key is the user registering the key + $update_user_field = ', ocr_usa_id_ref'; + $update_user_value = ', ' . intval($user_id); + } + + $this->query(' + INSERT INTO oauth_consumer_registry ( + ocr_consumer_key , + ocr_consumer_secret , + ocr_server_uri , + ocr_server_uri_host , + ocr_server_uri_path , + ocr_timestamp , + ocr_request_token_uri, + ocr_authorize_uri , + ocr_access_token_uri , + ocr_signature_methods' . $update_user_field . ' + ) + VALUES (\'%s\', \'%s\', \'%s\', \'%s\', \'%s\', NOW(), \'%s\', \'%s\', \'%s\', \'%s\''. $update_user_value . ')', + $server['consumer_key'], + $server['consumer_secret'], + $server['server_uri'], + strtolower($host), + $path, + isset($server['request_token_uri']) ? $server['request_token_uri'] : '', + isset($server['authorize_uri']) ? $server['authorize_uri'] : '', + isset($server['access_token_uri']) ? $server['access_token_uri'] : '', + $server['signature_methods'] + ); + + $ocr_id = $this->query_insert_id('oauth_consumer_registry', 'ocr_id'); + } + return $server['consumer_key']; + } + + + /** + * Insert/update a new consumer with this server (we will be the server) + * When this is a new consumer, then also generate the consumer key and secret. + * Never updates the consumer key and secret. + * When the id is set, then the key and secret must correspond to the entry + * being updated. + * + * (This is the registry at the server, registering consumers ;-) ) + * + * @param array consumer + * @param int user_id user registering this consumer + * @param boolean user_is_admin + * @return string consumer key + */ + public function updateConsumer ( $consumer, $user_id, $user_is_admin = false ) + { + if (!$user_is_admin) + { + foreach (array('requester_name', 'requester_email') as $f) + { + if (empty($consumer[$f])) + { + throw new OAuthException2('The field "'.$f.'" must be set and non empty'); + } + } + } + + if (!empty($consumer['id'])) + { + if (empty($consumer['consumer_key'])) + { + throw new OAuthException2('The field "consumer_key" must be set and non empty'); + } + if (!$user_is_admin && empty($consumer['consumer_secret'])) + { + throw new OAuthException2('The field "consumer_secret" must be set and non empty'); + } + + // Check if the current user can update this server definition + if (!$user_is_admin) + { + $osr_usa_id_ref = $this->query_one(' + SELECT osr_usa_id_ref + FROM oauth_server_registry + WHERE osr_id = %d + ', $consumer['id']); + + if ($osr_usa_id_ref != $user_id) + { + throw new OAuthException2('The user "'.$user_id.'" is not allowed to update this consumer'); + } + } + else + { + // User is an admin, allow a key owner to be changed or key to be shared + if (array_key_exists('user_id',$consumer)) + { + if (is_null($consumer['user_id'])) + { + $this->query(' + UPDATE oauth_server_registry + SET osr_usa_id_ref = NULL + WHERE osr_id = %d + ', $consumer['id']); + } + else + { + $this->query(' + UPDATE oauth_server_registry + SET osr_usa_id_ref = \'%d\' + WHERE osr_id = %d + ', $consumer['user_id'], $consumer['id']); + } + } + } + + $this->query(' + UPDATE oauth_server_registry + SET osr_requester_name = \'%s\', + osr_requester_email = \'%s\', + osr_callback_uri = \'%s\', + osr_application_uri = \'%s\', + osr_application_title = \'%s\', + osr_application_descr = \'%s\', + osr_application_notes = \'%s\', + osr_application_type = \'%s\', + osr_application_commercial = IF(%d,\'1\',\'0\'), + osr_timestamp = NOW() + WHERE osr_id = %d + AND osr_consumer_key = \'%s\' + AND osr_consumer_secret = \'%s\' + ', + $consumer['requester_name'], + $consumer['requester_email'], + isset($consumer['callback_uri']) ? $consumer['callback_uri'] : '', + isset($consumer['application_uri']) ? $consumer['application_uri'] : '', + isset($consumer['application_title']) ? $consumer['application_title'] : '', + isset($consumer['application_descr']) ? $consumer['application_descr'] : '', + isset($consumer['application_notes']) ? $consumer['application_notes'] : '', + isset($consumer['application_type']) ? $consumer['application_type'] : '', + isset($consumer['application_commercial']) ? $consumer['application_commercial'] : 0, + $consumer['id'], + $consumer['consumer_key'], + $consumer['consumer_secret'] + ); + + + $consumer_key = $consumer['consumer_key']; + } + else + { + $consumer_key = $this->generateKey(true); + $consumer_secret= $this->generateKey(); + + // When the user is an admin, then the user can be forced to something else that the user + if ($user_is_admin && array_key_exists('user_id',$consumer)) + { + if (is_null($consumer['user_id'])) + { + $owner_id = 'NULL'; + } + else + { + $owner_id = intval($consumer['user_id']); + } + } + else + { + // No admin, take the user id as the owner id. + $owner_id = intval($user_id); + } + + $this->query(' + INSERT INTO oauth_server_registry ( + osr_enabled, + osr_status, + osr_usa_id_ref, + osr_consumer_key, + osr_consumer_secret, + osr_requester_name, + osr_requester_email, + osr_callback_uri, + osr_application_uri, + osr_application_title, + osr_application_descr, + osr_application_notes, + osr_application_type, + osr_application_commercial, + osr_timestamp, + osr_issue_date + ) + VALUES (\'1\', \'active\', \'%s\', \'%s\', \'%s\', \'%s\', \'%s\', \'%s\', \'%s\', \'%s\', \'%s\', \'%s\', \'%s\', \'%d\', NOW(), NOW()) + ', + $owner_id, + $consumer_key, + $consumer_secret, + $consumer['requester_name'], + $consumer['requester_email'], + isset($consumer['callback_uri']) ? $consumer['callback_uri'] : '', + isset($consumer['application_uri']) ? $consumer['application_uri'] : '', + isset($consumer['application_title']) ? $consumer['application_title'] : '', + isset($consumer['application_descr']) ? $consumer['application_descr'] : '', + isset($consumer['application_notes']) ? $consumer['application_notes'] : '', + isset($consumer['application_type']) ? $consumer['application_type'] : '', + isset($consumer['application_commercial']) ? $consumer['application_commercial'] : 0 + ); + } + return $consumer_key; + + } + + /** + * Delete a consumer key. This removes access to our site for all applications using this key. + * + * @param string consumer_key + * @param int user_id user registering this server + * @param boolean user_is_admin + */ + public function deleteConsumer ( $consumer_key, $user_id, $user_is_admin = false ) + { + if ($user_is_admin) + { + $this->query(' + DELETE FROM oauth_server_registry + WHERE osr_consumer_key = \'%s\' + AND (osr_usa_id_ref = \'%d\' OR osr_usa_id_ref IS NULL) + ', $consumer_key, $user_id); + } + else + { + $this->query(' + DELETE FROM oauth_server_registry + WHERE osr_consumer_key = \'%s\' + AND osr_usa_id_ref = \'%d\' + ', $consumer_key, $user_id); + } + } + + /** + * Fetch a consumer of this server, by consumer_key. + * + * @param string consumer_key + * @param int user_id + * @param boolean user_is_admin (optional) + * @exception OAuthException2 when consumer not found + * @return array + */ + public function getConsumer ( $consumer_key, $user_id, $user_is_admin = false ) + { + $consumer = $this->query_row_assoc(' + SELECT * + FROM oauth_server_registry + WHERE osr_consumer_key = \'%s\' + ', $consumer_key); + + if (!is_array($consumer)) + { + throw new OAuthException2('No consumer with consumer_key "'.$consumer_key.'"'); + } + + $c = array(); + foreach ($consumer as $key => $value) + { + $c[substr($key, 4)] = $value; + } + $c['user_id'] = $c['usa_id_ref']; + + if (!$user_is_admin && !empty($c['user_id']) && $c['user_id'] != $user_id) + { + throw new OAuthException2('No access to the consumer information for consumer_key "'.$consumer_key.'"'); + } + return $c; + } + + + /** + * Fetch the static consumer key for this provider. The user for the static consumer + * key is NULL (no user, shared key). If the key did not exist then the key is created. + * + * @return string + */ + public function getConsumerStatic () + { + $consumer = $this->query_one(' + SELECT osr_consumer_key + FROM oauth_server_registry + WHERE osr_consumer_key LIKE \'sc-%%\' + AND osr_usa_id_ref IS NULL + '); + + if (empty($consumer)) + { + $consumer_key = 'sc-'.$this->generateKey(true); + $this->query(' + INSERT INTO oauth_server_registry ( + osr_enabled, + osr_status, + osr_usa_id_ref, + osr_consumer_key, + osr_consumer_secret, + osr_requester_name, + osr_requester_email, + osr_callback_uri, + osr_application_uri, + osr_application_title, + osr_application_descr, + osr_application_notes, + osr_application_type, + osr_application_commercial, + osr_timestamp, + osr_issue_date + ) + VALUES (\'1\',\'active\', NULL, \'%s\', \'\', \'\', \'\', \'\', \'\', \'Static shared consumer key\', \'\', \'Static shared consumer key\', \'\', 0, NOW(), NOW()) + ', + $consumer_key + ); + + // Just make sure that if the consumer key is truncated that we get the truncated string + $consumer = $this->getConsumerStatic(); + } + return $consumer; + } + + /** + * Add an unautorized request token to our server. + * + * @param string consumer_key + * @param array options (eg. token_ttl) + * @return array (token, token_secret) + */ + public function addConsumerRequestToken ( $consumer_key, $options = array() ) + { + $token = $this->generateKey(true); + $secret = $this->generateKey(); + $osr_id = $this->query_one(' + SELECT osr_id + FROM oauth_server_registry + WHERE osr_consumer_key = \'%s\' + AND osr_enabled = \'1\' + ', $consumer_key); + + if (!$osr_id) + { + throw new OAuthException2('No server with consumer_key "'.$consumer_key.'" or consumer_key is disabled'); + } + + if (isset($options['token_ttl']) && is_numeric($options['token_ttl'])) + { + $ttl = intval($options['token_ttl']); + } + else + { + $ttl = $this->max_request_token_ttl; + } + + if (!isset($options['oauth_callback'])) { + // 1.0a Compatibility : store callback url associated with request token + $options['oauth_callback']='oob'; + } + + $this->query(' + INSERT INTO oauth_server_token ( + ost_osr_id_ref, + ost_usa_id_ref, + ost_token, + ost_token_secret, + ost_token_type, + ost_token_ttl, + ost_callback_url + ) + VALUES (%d, \'1\', \'%s\', \'%s\', \'request\', NOW() + INTERVAL \'%d SECOND\', \'%s\')', + $osr_id, $token, $secret, $ttl, $options['oauth_callback']); + + return array('token'=>$token, 'token_secret'=>$secret, 'token_ttl'=>$ttl); + } + + /** + * Fetch the consumer request token, by request token. + * + * @param string token + * @return array token and consumer details + */ + public function getConsumerRequestToken ( $token ) + { + $rs = $this->query_row_assoc(' + SELECT ost_token as token, + ost_token_secret as token_secret, + osr_consumer_key as consumer_key, + osr_consumer_secret as consumer_secret, + ost_token_type as token_type, + ost_callback_url as callback_url, + osr_application_title as application_title, + osr_application_descr as application_descr, + osr_application_uri as application_uri + FROM oauth_server_token + JOIN oauth_server_registry + ON ost_osr_id_ref = osr_id + WHERE ost_token_type = \'request\' + AND ost_token = \'%s\' + AND ost_token_ttl >= NOW() + ', $token); + + return $rs; + } + + /** + * Delete a consumer token. The token must be a request or authorized token. + * + * @param string token + */ + public function deleteConsumerRequestToken ( $token ) + { + $this->query(' + DELETE FROM oauth_server_token + WHERE ost_token = \'%s\' + AND ost_token_type = \'request\' + ', $token); + } + + /** + * Upgrade a request token to be an authorized request token. + * + * @param string token + * @param int user_id user authorizing the token + * @param string referrer_host used to set the referrer host for this token, for user feedback + */ + public function authorizeConsumerRequestToken ( $token, $user_id, $referrer_host = '' ) + { + // 1.0a Compatibility : create a token verifier + $verifier = substr(md5(rand()),0,10); + + $this->query(' + UPDATE oauth_server_token + SET ost_authorized = \'1\', + ost_usa_id_ref = \'%d\', + ost_timestamp = NOW(), + ost_referrer_host = \'%s\', + ost_verifier = \'%s\' + WHERE ost_token = \'%s\' + AND ost_token_type = \'request\' + ', $user_id, $referrer_host, $verifier, $token); + return $verifier; + } + + /** + * Count the consumer access tokens for the given consumer. + * + * @param string consumer_key + * @return int + */ + public function countConsumerAccessTokens ( $consumer_key ) + { + $count = $this->query_one(' + SELECT COUNT(ost_id) + FROM oauth_server_token + JOIN oauth_server_registry + ON ost_osr_id_ref = osr_id + WHERE ost_token_type = \'access\' + AND osr_consumer_key = \'%s\' + AND ost_token_ttl >= NOW() + ', $consumer_key); + + return $count; + } + + /** + * Exchange an authorized request token for new access token. + * + * @param string token + * @param array options options for the token, token_ttl + * @exception OAuthException2 when token could not be exchanged + * @return array (token, token_secret) + */ + public function exchangeConsumerRequestForAccessToken ( $token, $options = array() ) + { + $new_token = $this->generateKey(true); + $new_secret = $this->generateKey(); + + // Maximum time to live for this token + if (isset($options['token_ttl']) && is_numeric($options['token_ttl'])) + { + $ttl_sql = '(NOW() + INTERVAL \''.intval($options['token_ttl']).' SECOND\')'; + } + else + { + $ttl_sql = "'9999-12-31'"; + } + + if (isset($options['verifier'])) { + $verifier = $options['verifier']; + + // 1.0a Compatibility : check token against oauth_verifier + $this->query(' + UPDATE oauth_server_token + SET ost_token = \'%s\', + ost_token_secret = \'%s\', + ost_token_type = \'access\', + ost_timestamp = NOW(), + ost_token_ttl = '.$ttl_sql.' + WHERE ost_token = \'%s\' + AND ost_token_type = \'request\' + AND ost_authorized = \'1\' + AND ost_token_ttl >= NOW() + AND ost_verifier = \'%s\' + ', $new_token, $new_secret, $token, $verifier); + } else { + + // 1.0 + $this->query(' + UPDATE oauth_server_token + SET ost_token = \'%s\', + ost_token_secret = \'%s\', + ost_token_type = \'access\', + ost_timestamp = NOW(), + ost_token_ttl = '.$ttl_sql.' + WHERE ost_token = \'%s\' + AND ost_token_type = \'request\' + AND ost_authorized = \'1\' + AND ost_token_ttl >= NOW() + ', $new_token, $new_secret, $token); + } + + if ($this->query_affected_rows() != 1) + { + throw new OAuthException2('Can\'t exchange request token "'.$token.'" for access token. No such token or not authorized'); + } + + $ret = array('token' => $new_token, 'token_secret' => $new_secret); + $ttl = $this->query_one(' + SELECT (CASE WHEN ost_token_ttl >= \'9999-12-31\' THEN NULL ELSE ost_token_ttl - NOW() END) as token_ttl + FROM oauth_server_token + WHERE ost_token = \'%s\'', $new_token); + + if (is_numeric($ttl)) + { + $ret['token_ttl'] = intval($ttl); + } + return $ret; + } + + /** + * Fetch the consumer access token, by access token. + * + * @param string token + * @param int user_id + * @exception OAuthException2 when token is not found + * @return array token and consumer details + */ + public function getConsumerAccessToken ( $token, $user_id ) + { + $rs = $this->query_row_assoc(' + SELECT ost_token as token, + ost_token_secret as token_secret, + ost_referrer_host as token_referrer_host, + osr_consumer_key as consumer_key, + osr_consumer_secret as consumer_secret, + osr_application_uri as application_uri, + osr_application_title as application_title, + osr_application_descr as application_descr, + osr_callback_uri as callback_uri + FROM oauth_server_token + JOIN oauth_server_registry + ON ost_osr_id_ref = osr_id + WHERE ost_token_type = \'access\' + AND ost_token = \'%s\' + AND ost_usa_id_ref = \'%d\' + AND ost_token_ttl >= NOW() + ', $token, $user_id); + + if (empty($rs)) + { + throw new OAuthException2('No server_token "'.$token.'" for user "'.$user_id.'"'); + } + return $rs; + } + + /** + * Delete a consumer access token. + * + * @param string token + * @param int user_id + * @param boolean user_is_admin + */ + public function deleteConsumerAccessToken ( $token, $user_id, $user_is_admin = false ) + { + if ($user_is_admin) + { + $this->query(' + DELETE FROM oauth_server_token + WHERE ost_token = \'%s\' + AND ost_token_type = \'access\' + ', $token); + } + else + { + $this->query(' + DELETE FROM oauth_server_token + WHERE ost_token = \'%s\' + AND ost_token_type = \'access\' + AND ost_usa_id_ref = \'%d\' + ', $token, $user_id); + } + } + + /** + * Set the ttl of a consumer access token. This is done when the + * server receives a valid request with a xoauth_token_ttl parameter in it. + * + * @param string token + * @param int ttl + */ + public function setConsumerAccessTokenTtl ( $token, $token_ttl ) + { + if ($token_ttl <= 0) + { + // Immediate delete when the token is past its ttl + $this->deleteConsumerAccessToken($token, 0, true); + } + else + { + // Set maximum time to live for this token + $this->query(' + UPDATE oauth_server_token + SET ost_token_ttl = (NOW() + INTERVAL \'%d SECOND\') + WHERE ost_token = \'%s\' + AND ost_token_type = \'access\' + ', $token_ttl, $token); + } + } + + /** + * Fetch a list of all consumer keys, secrets etc. + * Returns the public (user_id is null) and the keys owned by the user + * + * @param int user_id + * @return array + */ + public function listConsumers ( $user_id ) + { + $rs = $this->query_all_assoc(' + SELECT osr_id as id, + osr_usa_id_ref as user_id, + osr_consumer_key as consumer_key, + osr_consumer_secret as consumer_secret, + osr_enabled as enabled, + osr_status as status, + osr_issue_date as issue_date, + osr_application_uri as application_uri, + osr_application_title as application_title, + osr_application_descr as application_descr, + osr_requester_name as requester_name, + osr_requester_email as requester_email, + osr_callback_uri as callback_uri + FROM oauth_server_registry + WHERE (osr_usa_id_ref = \'%d\' OR osr_usa_id_ref IS NULL) + ORDER BY osr_application_title + ', $user_id); + return $rs; + } + + /** + * List of all registered applications. Data returned has not sensitive + * information and therefore is suitable for public displaying. + * + * @param int $begin + * @param int $total + * @return array + */ + public function listConsumerApplications($begin = 0, $total = 25) + { + $rs = $this->query_all_assoc(' + SELECT osr_id as id, + osr_enabled as enabled, + osr_status as status, + osr_issue_date as issue_date, + osr_application_uri as application_uri, + osr_application_title as application_title, + osr_application_descr as application_descr + FROM oauth_server_registry + ORDER BY osr_application_title + '); + // TODO: pagination + return $rs; + } + + + /** + * Fetch a list of all consumer tokens accessing the account of the given user. + * + * @param int user_id + * @return array + */ + public function listConsumerTokens ( $user_id ) + { + $rs = $this->query_all_assoc(' + SELECT osr_consumer_key as consumer_key, + osr_consumer_secret as consumer_secret, + osr_enabled as enabled, + osr_status as status, + osr_application_uri as application_uri, + osr_application_title as application_title, + osr_application_descr as application_descr, + ost_timestamp as timestamp, + ost_token as token, + ost_token_secret as token_secret, + ost_referrer_host as token_referrer_host, + osr_callback_uri as callback_uri + FROM oauth_server_registry + JOIN oauth_server_token + ON ost_osr_id_ref = osr_id + WHERE ost_usa_id_ref = \'%d\' + AND ost_token_type = \'access\' + AND ost_token_ttl >= NOW() + ORDER BY osr_application_title + ', $user_id); + return $rs; + } + + + /** + * Check an nonce/timestamp combination. Clears any nonce combinations + * that are older than the one received. + * + * @param string consumer_key + * @param string token + * @param int timestamp + * @param string nonce + * @exception OAuthException2 thrown when the timestamp is not in sequence or nonce is not unique + */ + public function checkServerNonce ( $consumer_key, $token, $timestamp, $nonce ) + { + $r = $this->query_row(' + SELECT MAX(osn_timestamp), MAX(osn_timestamp) > %d + %d + FROM oauth_server_nonce + WHERE osn_consumer_key = \'%s\' + AND osn_token = \'%s\' + ', $timestamp, $this->max_timestamp_skew, $consumer_key, $token); + + if (!empty($r) && $r[1] === 't') + { + throw new OAuthException2('Timestamp is out of sequence. Request rejected. Got '.$timestamp.' last max is '.$r[0].' allowed skew is '.$this->max_timestamp_skew); + } + + // Insert the new combination + $this->query(' + INSERT INTO oauth_server_nonce ( + osn_consumer_key, + osn_token, + osn_timestamp, + osn_nonce + ) + VALUES (\'%s\', \'%s\', %d, \'%s\')', + $consumer_key, $token, $timestamp, $nonce); + + if ($this->query_affected_rows() == 0) + { + throw new OAuthException2('Duplicate timestamp/nonce combination, possible replay attack. Request rejected.'); + } + + // Clean up all timestamps older than the one we just received + $this->query(' + DELETE FROM oauth_server_nonce + WHERE osn_consumer_key = \'%s\' + AND osn_token = \'%s\' + AND osn_timestamp < %d - %d + ', $consumer_key, $token, $timestamp, $this->max_timestamp_skew); + } + + /** + * Add an entry to the log table + * + * @param array keys (osr_consumer_key, ost_token, ocr_consumer_key, oct_token) + * @param string received + * @param string sent + * @param string base_string + * @param string notes + * @param int (optional) user_id + */ + public function addLog ( $keys, $received, $sent, $base_string, $notes, $user_id = null ) + { + $args = array(); + $ps = array(); + foreach ($keys as $key => $value) + { + $args[] = $value; + $ps[] = "olg_$key = '%s'"; + } + + if (!empty($_SERVER['REMOTE_ADDR'])) + { + $remote_ip = $_SERVER['REMOTE_ADDR']; + } + else if (!empty($_SERVER['REMOTE_IP'])) + { + $remote_ip = $_SERVER['REMOTE_IP']; + } + else + { + $remote_ip = '0.0.0.0'; + } + + // Build the SQL + $ps['olg_received'] = "'%s'"; $args[] = $this->makeUTF8($received); + $ps['olg_sent'] = "'%s'"; $args[] = $this->makeUTF8($sent); + $ps['olg_base_string'] = "'%s'"; $args[] = $base_string; + $ps['olg_notes'] = "'%s'"; $args[] = $this->makeUTF8($notes); + $ps['olg_usa_id_ref'] = "NULLIF('%d', '0')"; $args[] = $user_id; + $ps['olg_remote_ip'] = "NULLIF('%s','0.0.0.0')"; $args[] = $remote_ip; + + $this->query(' + INSERT INTO oauth_log ('.implode(',', array_keys($ps)) . ') + VALUES(' . implode(',', $ps) . ')', + $args + ); + } + + /** + * Get a page of entries from the log. Returns the last 100 records + * matching the options given. + * + * @param array options + * @param int user_id current user + * @return array log records + */ + public function listLog ( $options, $user_id ) + { + $where = array(); + $args = array(); + if (empty($options)) + { + $where[] = 'olg_usa_id_ref = \'%d\''; + $args[] = $user_id; + } + else + { + foreach ($options as $option => $value) + { + if (strlen($value) > 0) + { + switch ($option) + { + case 'osr_consumer_key': + case 'ocr_consumer_key': + case 'ost_token': + case 'oct_token': + $where[] = 'olg_'.$option.' = \'%s\''; + $args[] = $value; + break; + } + } + } + + $where[] = '(olg_usa_id_ref IS NULL OR olg_usa_id_ref = \'%d\')'; + $args[] = $user_id; + } + + $rs = $this->query_all_assoc(' + SELECT olg_id, + olg_osr_consumer_key AS osr_consumer_key, + olg_ost_token AS ost_token, + olg_ocr_consumer_key AS ocr_consumer_key, + olg_oct_token AS oct_token, + olg_usa_id_ref AS user_id, + olg_received AS received, + olg_sent AS sent, + olg_base_string AS base_string, + olg_notes AS notes, + olg_timestamp AS timestamp, + olg_remote_ip AS remote_ip + FROM oauth_log + WHERE '.implode(' AND ', $where).' + ORDER BY olg_id DESC + LIMIT 0,100', $args); + + return $rs; + } + + + /* ** Some simple helper functions for querying the pgsql db ** */ + + /** + * Perform a query, ignore the results + * + * @param string sql + * @param vararg arguments (for sprintf) + */ + protected function query ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + if (!($res = pg_query($this->conn, $sql))) + { + $this->sql_errcheck($sql); + } + $this->_lastAffectedRows = pg_affected_rows($res); + if (is_resource($res)) + { + pg_free_result($res); + } + } + + + /** + * Perform a query, return all rows + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + protected function query_all_assoc ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + if (!($res = pg_query($this->conn, $sql))) + { + $this->sql_errcheck($sql); + } + $rs = array(); + while ($row = pg_fetch_assoc($res)) + { + $rs[] = $row; + } + pg_free_result($res); + return $rs; + } + + + /** + * Perform a query, return the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + protected function query_row_assoc ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + + if (!($res = pg_query($this->conn, $sql))) + { + $this->sql_errcheck($sql); + } + if ($row = pg_fetch_assoc($res)) + { + $rs = $row; + } + else + { + $rs = false; + } + pg_free_result($res); + return $rs; + } + + /** + * Perform a query, return the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + protected function query_row ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + if (!($res = pg_query($this->conn, $sql))) + { + $this->sql_errcheck($sql); + } + if ($row = pg_fetch_array($res)) + { + $rs = $row; + } + else + { + $rs = false; + } + pg_free_result($res); + return $rs; + } + + + /** + * Perform a query, return the first column of the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return mixed + */ + protected function query_one ( $sql ) + { + $sql = $this->sql_printf(func_get_args()); + if (!($res = pg_query($this->conn, $sql))) + { + $this->sql_errcheck($sql); + } + $val = pg_fetch_row($res); + if ($val && isset($val[0])) { + $val = $val[0]; + } + pg_free_result($res); + return $val; + } + + + /** + * Return the number of rows affected in the last query + */ + protected function query_affected_rows () + { + return $this->_lastAffectedRows; + } + + + /** + * Return the id of the last inserted row + * + * @return int + */ + protected function query_insert_id ( $tableName, $primaryKey = null ) + { + $sequenceName = $tableName; + if ($primaryKey) { + $sequenceName .= "_$primaryKey"; + } + $sequenceName .= '_seq'; + + $sql = " + SELECT + CURRVAL('%s') + "; + $args = array($sql, $sequenceName); + $sql = $this->sql_printf($args); + if (!($res = pg_query($this->conn, $sql))) { + return 0; + } + $val = pg_fetch_row($res, 0); + if ($val && isset($val[0])) { + $val = $val[0]; + } + + pg_free_result($res); + return $val; + } + + + protected function sql_printf ( $args ) + { + $sql = array_shift($args); + if (count($args) == 1 && is_array($args[0])) + { + $args = $args[0]; + } + $args = array_map(array($this, 'sql_escape_string'), $args); + return vsprintf($sql, $args); + } + + + protected function sql_escape_string ( $s ) + { + if (is_string($s)) + { + return pg_escape_string($this->conn, $s); + } + else if (is_null($s)) + { + return NULL; + } + else if (is_bool($s)) + { + return intval($s); + } + else if (is_int($s) || is_float($s)) + { + return $s; + } + else + { + return pg_escape_string($this->conn, strval($s)); + } + } + + + protected function sql_errcheck ( $sql ) + { + $msg = "SQL Error in OAuthStorePostgreSQL: ".pg_last_error($this->conn)."\n\n" . $sql; + throw new OAuthException2($msg); + } +} diff --git a/includes/oauth-php/library/store/OAuthStoreSQL.php b/includes/oauth-php/library/store/OAuthStoreSQL.php new file mode 100644 index 00000000..95e0720a --- /dev/null +++ b/includes/oauth-php/library/store/OAuthStoreSQL.php @@ -0,0 +1,1827 @@ + + * @date Nov 16, 2007 4:03:30 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__) . '/OAuthStoreAbstract.class.php'; + + +abstract class OAuthStoreSQL extends OAuthStoreAbstract +{ + /** + * Maximum delta a timestamp may be off from a previous timestamp. + * Allows multiple consumers with some clock skew to work with the same token. + * Unit is seconds, default max skew is 10 minutes. + */ + protected $max_timestamp_skew = 600; + + /** + * Default ttl for request tokens + */ + protected $max_request_token_ttl = 3600; + + + /** + * Construct the OAuthStoreMySQL. + * In the options you have to supply either: + * - server, username, password and database (for a mysql_connect) + * - conn (for the connection to be used) + * + * @param array options + */ + function __construct ( $options = array() ) + { + if (isset($options['conn'])) + { + $this->conn = $options['conn']; + } + else + { + if (isset($options['server'])) + { + $server = $options['server']; + $username = $options['username']; + + if (isset($options['password'])) + { + $this->conn = mysql_connect($server, $username, $options['password']); + } + else + { + $this->conn = mysql_connect($server, $username); + } + } + else + { + // Try the default mysql connect + $this->conn = mysql_connect(); + } + + if ($this->conn === false) + { + throw new OAuthException2('Could not connect to MySQL database: ' . mysql_error()); + } + + if (isset($options['database'])) + { + if (!mysql_select_db($options['database'], $this->conn)) + { + $this->sql_errcheck(); + } + } + $this->query('set character set utf8'); + } + } + + + /** + * Find stored credentials for the consumer key and token. Used by an OAuth server + * when verifying an OAuth request. + * + * @param string consumer_key + * @param string token + * @param string token_type false, 'request' or 'access' + * @exception OAuthException2 when no secrets where found + * @return array assoc (consumer_secret, token_secret, osr_id, ost_id, user_id) + */ + public function getSecretsForVerify ( $consumer_key, $token, $token_type = 'access' ) + { + if ($token_type === false) + { + $rs = $this->query_row_assoc(' + SELECT osr_id, + osr_consumer_key as consumer_key, + osr_consumer_secret as consumer_secret + FROM oauth_server_registry + WHERE osr_consumer_key = \'%s\' + AND osr_enabled = 1 + ', + $consumer_key); + + if ($rs) + { + $rs['token'] = false; + $rs['token_secret'] = false; + $rs['user_id'] = false; + $rs['ost_id'] = false; + } + } + else + { + $rs = $this->query_row_assoc(' + SELECT osr_id, + ost_id, + ost_usa_id_ref as user_id, + osr_consumer_key as consumer_key, + osr_consumer_secret as consumer_secret, + ost_token as token, + ost_token_secret as token_secret + FROM oauth_server_registry + JOIN oauth_server_token + ON ost_osr_id_ref = osr_id + WHERE ost_token_type = \'%s\' + AND osr_consumer_key = \'%s\' + AND ost_token = \'%s\' + AND osr_enabled = 1 + AND ost_token_ttl >= NOW() + ', + $token_type, $consumer_key, $token); + } + + if (empty($rs)) + { + throw new OAuthException2('The consumer_key "'.$consumer_key.'" token "'.$token.'" combination does not exist or is not enabled.'); + } + return $rs; + } + + + /** + * Find the server details for signing a request, always looks for an access token. + * The returned credentials depend on which local user is making the request. + * + * The consumer_key must belong to the user or be public (user id is null) + * + * For signing we need all of the following: + * + * consumer_key consumer key associated with the server + * consumer_secret consumer secret associated with this server + * token access token associated with this server + * token_secret secret for the access token + * signature_methods signing methods supported by the server (array) + * + * @todo filter on token type (we should know how and with what to sign this request, and there might be old access tokens) + * @param string uri uri of the server + * @param int user_id id of the logged on user + * @param string name (optional) name of the token (case sensitive) + * @exception OAuthException2 when no credentials found + * @return array + */ + public function getSecretsForSignature ( $uri, $user_id, $name = '' ) + { + // Find a consumer key and token for the given uri + $ps = parse_url($uri); + $host = isset($ps['host']) ? $ps['host'] : 'localhost'; + $path = isset($ps['path']) ? $ps['path'] : ''; + + if (empty($path) || substr($path, -1) != '/') + { + $path .= '/'; + } + + // The owner of the consumer_key is either the user or nobody (public consumer key) + $secrets = $this->query_row_assoc(' + SELECT ocr_consumer_key as consumer_key, + ocr_consumer_secret as consumer_secret, + oct_token as token, + oct_token_secret as token_secret, + ocr_signature_methods as signature_methods + FROM oauth_consumer_registry + JOIN oauth_consumer_token ON oct_ocr_id_ref = ocr_id + WHERE ocr_server_uri_host = \'%s\' + AND ocr_server_uri_path = LEFT(\'%s\', LENGTH(ocr_server_uri_path)) + AND (ocr_usa_id_ref = \'%d\' OR ocr_usa_id_ref IS NULL) + AND oct_token_type = \'access\' + AND oct_name = \'%s\' + AND oct_token_ttl >= NOW() + ORDER BY ocr_usa_id_ref DESC, ocr_consumer_secret DESC, LENGTH(ocr_server_uri_path) DESC + LIMIT 0,1 + ', $host, $path, $user_id, $name + ); + + if (empty($secrets)) + { + throw new OAuthException2('No server tokens available for '.$uri); + } + $secrets['signature_methods'] = explode(',', $secrets['signature_methods']); + return $secrets; + } + + + /** + * Get the token and token secret we obtained from a server. + * + * @param string consumer_key + * @param string token + * @param string token_type + * @param int user_id the user owning the token + * @param string name optional name for a named token + * @exception OAuthException2 when no credentials found + * @return array + */ + public function getServerTokenSecrets ( $consumer_key, $token, $token_type, $user_id, $name = '' ) + { + if ($token_type != 'request' && $token_type != 'access') + { + throw new OAuthException2('Unkown token type "'.$token_type.'", must be either "request" or "access"'); + } + + // Take the most recent token of the given type + $r = $this->query_row_assoc(' + SELECT ocr_consumer_key as consumer_key, + ocr_consumer_secret as consumer_secret, + oct_token as token, + oct_token_secret as token_secret, + oct_name as token_name, + ocr_signature_methods as signature_methods, + ocr_server_uri as server_uri, + ocr_request_token_uri as request_token_uri, + ocr_authorize_uri as authorize_uri, + ocr_access_token_uri as access_token_uri, + IF(oct_token_ttl >= \'9999-12-31\', NULL, UNIX_TIMESTAMP(oct_token_ttl) - UNIX_TIMESTAMP(NOW())) as token_ttl + FROM oauth_consumer_registry + JOIN oauth_consumer_token + ON oct_ocr_id_ref = ocr_id + WHERE ocr_consumer_key = \'%s\' + AND oct_token_type = \'%s\' + AND oct_token = \'%s\' + AND oct_usa_id_ref = %d + AND oct_token_ttl >= NOW() + ', $consumer_key, $token_type, $token, $user_id + ); + + if (empty($r)) + { + throw new OAuthException2('Could not find a "'.$token_type.'" token for consumer "'.$consumer_key.'" and user '.$user_id); + } + if (isset($r['signature_methods']) && !empty($r['signature_methods'])) + { + $r['signature_methods'] = explode(',',$r['signature_methods']); + } + else + { + $r['signature_methods'] = array(); + } + return $r; + } + + + /** + * Add a request token we obtained from a server. + * + * @todo remove old tokens for this user and this ocr_id + * @param string consumer_key key of the server in the consumer registry + * @param string token_type one of 'request' or 'access' + * @param string token + * @param string token_secret + * @param int user_id the user owning the token + * @param array options extra options, name and token_ttl + * @exception OAuthException2 when server is not known + * @exception OAuthException2 when we received a duplicate token + */ + public function addServerToken ( $consumer_key, $token_type, $token, $token_secret, $user_id, $options = array() ) + { + if ($token_type != 'request' && $token_type != 'access') + { + throw new OAuthException2('Unknown token type "'.$token_type.'", must be either "request" or "access"'); + } + + // Maximum time to live for this token + if (isset($options['token_ttl']) && is_numeric($options['token_ttl'])) + { + $ttl = 'DATE_ADD(NOW(), INTERVAL '.intval($options['token_ttl']).' SECOND)'; + } + else if ($token_type == 'request') + { + $ttl = 'DATE_ADD(NOW(), INTERVAL '.$this->max_request_token_ttl.' SECOND)'; + } + else + { + $ttl = "'9999-12-31'"; + } + + if (isset($options['server_uri'])) + { + $ocr_id = $this->query_one(' + SELECT ocr_id + FROM oauth_consumer_registry + WHERE ocr_consumer_key = \'%s\' + AND ocr_usa_id_ref = %d + AND ocr_server_uri = \'%s\' + ', $consumer_key, $user_id, $options['server_uri']); + } + else + { + $ocr_id = $this->query_one(' + SELECT ocr_id + FROM oauth_consumer_registry + WHERE ocr_consumer_key = \'%s\' + AND ocr_usa_id_ref = %d + ', $consumer_key, $user_id); + } + + if (empty($ocr_id)) + { + throw new OAuthException2('No server associated with consumer_key "'.$consumer_key.'"'); + } + + // Named tokens, unique per user/consumer key + if (isset($options['name']) && $options['name'] != '') + { + $name = $options['name']; + } + else + { + $name = ''; + } + + // Delete any old tokens with the same type and name for this user/server combination + $this->query(' + DELETE FROM oauth_consumer_token + WHERE oct_ocr_id_ref = %d + AND oct_usa_id_ref = %d + AND oct_token_type = LOWER(\'%s\') + AND oct_name = \'%s\' + ', + $ocr_id, + $user_id, + $token_type, + $name); + + // Insert the new token + $this->query(' + INSERT IGNORE INTO oauth_consumer_token + SET oct_ocr_id_ref = %d, + oct_usa_id_ref = %d, + oct_name = \'%s\', + oct_token = \'%s\', + oct_token_secret= \'%s\', + oct_token_type = LOWER(\'%s\'), + oct_timestamp = NOW(), + oct_token_ttl = '.$ttl.' + ', + $ocr_id, + $user_id, + $name, + $token, + $token_secret, + $token_type); + + if (!$this->query_affected_rows()) + { + throw new OAuthException2('Received duplicate token "'.$token.'" for the same consumer_key "'.$consumer_key.'"'); + } + } + + + /** + * Delete a server key. This removes access to that site. + * + * @param string consumer_key + * @param int user_id user registering this server + * @param boolean user_is_admin + */ + public function deleteServer ( $consumer_key, $user_id, $user_is_admin = false ) + { + if ($user_is_admin) + { + $this->query(' + DELETE FROM oauth_consumer_registry + WHERE ocr_consumer_key = \'%s\' + AND (ocr_usa_id_ref = %d OR ocr_usa_id_ref IS NULL) + ', $consumer_key, $user_id); + } + else + { + $this->query(' + DELETE FROM oauth_consumer_registry + WHERE ocr_consumer_key = \'%s\' + AND ocr_usa_id_ref = %d + ', $consumer_key, $user_id); + } + } + + + /** + * Get a server from the consumer registry using the consumer key + * + * @param string consumer_key + * @param int user_id + * @param boolean user_is_admin (optional) + * @exception OAuthException2 when server is not found + * @return array + */ + public function getServer ( $consumer_key, $user_id, $user_is_admin = false ) + { + $r = $this->query_row_assoc(' + SELECT ocr_id as id, + ocr_usa_id_ref as user_id, + ocr_consumer_key as consumer_key, + ocr_consumer_secret as consumer_secret, + ocr_signature_methods as signature_methods, + ocr_server_uri as server_uri, + ocr_request_token_uri as request_token_uri, + ocr_authorize_uri as authorize_uri, + ocr_access_token_uri as access_token_uri + FROM oauth_consumer_registry + WHERE ocr_consumer_key = \'%s\' + AND (ocr_usa_id_ref = %d OR ocr_usa_id_ref IS NULL) + ', $consumer_key, $user_id); + + if (empty($r)) + { + throw new OAuthException2('No server with consumer_key "'.$consumer_key.'" has been registered (for this user)'); + } + + if (isset($r['signature_methods']) && !empty($r['signature_methods'])) + { + $r['signature_methods'] = explode(',',$r['signature_methods']); + } + else + { + $r['signature_methods'] = array(); + } + return $r; + } + + + + /** + * Find the server details that might be used for a request + * + * The consumer_key must belong to the user or be public (user id is null) + * + * @param string uri uri of the server + * @param int user_id id of the logged on user + * @exception OAuthException2 when no credentials found + * @return array + */ + public function getServerForUri ( $uri, $user_id ) + { + // Find a consumer key and token for the given uri + $ps = parse_url($uri); + $host = isset($ps['host']) ? $ps['host'] : 'localhost'; + $path = isset($ps['path']) ? $ps['path'] : ''; + + if (empty($path) || substr($path, -1) != '/') + { + $path .= '/'; + } + + // The owner of the consumer_key is either the user or nobody (public consumer key) + $server = $this->query_row_assoc(' + SELECT ocr_id as id, + ocr_usa_id_ref as user_id, + ocr_consumer_key as consumer_key, + ocr_consumer_secret as consumer_secret, + ocr_signature_methods as signature_methods, + ocr_server_uri as server_uri, + ocr_request_token_uri as request_token_uri, + ocr_authorize_uri as authorize_uri, + ocr_access_token_uri as access_token_uri + FROM oauth_consumer_registry + WHERE ocr_server_uri_host = \'%s\' + AND ocr_server_uri_path = LEFT(\'%s\', LENGTH(ocr_server_uri_path)) + AND (ocr_usa_id_ref = \'%d\' OR ocr_usa_id_ref IS NULL) + ORDER BY ocr_usa_id_ref DESC, consumer_secret DESC, LENGTH(ocr_server_uri_path) DESC + LIMIT 0,1 + ', $host, $path, $user_id + ); + + if (empty($server)) + { + throw new OAuthException2('No server available for '.$uri); + } + $server['signature_methods'] = explode(',', $server['signature_methods']); + return $server; + } + + + /** + * Get a list of all server token this user has access to. + * + * @param int usr_id + * @return array + */ + public function listServerTokens ( $user_id ) + { + $ts = $this->query_all_assoc(' + SELECT ocr_consumer_key as consumer_key, + ocr_consumer_secret as consumer_secret, + oct_id as token_id, + oct_token as token, + oct_token_secret as token_secret, + oct_usa_id_ref as user_id, + ocr_signature_methods as signature_methods, + ocr_server_uri as server_uri, + ocr_server_uri_host as server_uri_host, + ocr_server_uri_path as server_uri_path, + ocr_request_token_uri as request_token_uri, + ocr_authorize_uri as authorize_uri, + ocr_access_token_uri as access_token_uri, + oct_timestamp as timestamp + FROM oauth_consumer_registry + JOIN oauth_consumer_token + ON oct_ocr_id_ref = ocr_id + WHERE oct_usa_id_ref = %d + AND oct_token_type = \'access\' + AND oct_token_ttl >= NOW() + ORDER BY ocr_server_uri_host, ocr_server_uri_path + ', $user_id); + return $ts; + } + + + /** + * Count how many tokens we have for the given server + * + * @param string consumer_key + * @return int + */ + public function countServerTokens ( $consumer_key ) + { + $count = $this->query_one(' + SELECT COUNT(oct_id) + FROM oauth_consumer_token + JOIN oauth_consumer_registry + ON oct_ocr_id_ref = ocr_id + WHERE oct_token_type = \'access\' + AND ocr_consumer_key = \'%s\' + AND oct_token_ttl >= NOW() + ', $consumer_key); + + return $count; + } + + + /** + * Get a specific server token for the given user + * + * @param string consumer_key + * @param string token + * @param int user_id + * @exception OAuthException2 when no such token found + * @return array + */ + public function getServerToken ( $consumer_key, $token, $user_id ) + { + $ts = $this->query_row_assoc(' + SELECT ocr_consumer_key as consumer_key, + ocr_consumer_secret as consumer_secret, + oct_token as token, + oct_token_secret as token_secret, + oct_usa_id_ref as usr_id, + ocr_signature_methods as signature_methods, + ocr_server_uri as server_uri, + ocr_server_uri_host as server_uri_host, + ocr_server_uri_path as server_uri_path, + ocr_request_token_uri as request_token_uri, + ocr_authorize_uri as authorize_uri, + ocr_access_token_uri as access_token_uri, + oct_timestamp as timestamp + FROM oauth_consumer_registry + JOIN oauth_consumer_token + ON oct_ocr_id_ref = ocr_id + WHERE ocr_consumer_key = \'%s\' + AND oct_usa_id_ref = %d + AND oct_token_type = \'access\' + AND oct_token = \'%s\' + AND oct_token_ttl >= NOW() + ', $consumer_key, $user_id, $token); + + if (empty($ts)) + { + throw new OAuthException2('No such consumer key ('.$consumer_key.') and token ('.$token.') combination for user "'.$user_id.'"'); + } + return $ts; + } + + + /** + * Delete a token we obtained from a server. + * + * @param string consumer_key + * @param string token + * @param int user_id + * @param boolean user_is_admin + */ + public function deleteServerToken ( $consumer_key, $token, $user_id, $user_is_admin = false ) + { + if ($user_is_admin) + { + $this->query(' + DELETE oauth_consumer_token + FROM oauth_consumer_token + JOIN oauth_consumer_registry + ON oct_ocr_id_ref = ocr_id + WHERE ocr_consumer_key = \'%s\' + AND oct_token = \'%s\' + ', $consumer_key, $token); + } + else + { + $this->query(' + DELETE oauth_consumer_token + FROM oauth_consumer_token + JOIN oauth_consumer_registry + ON oct_ocr_id_ref = ocr_id + WHERE ocr_consumer_key = \'%s\' + AND oct_token = \'%s\' + AND oct_usa_id_ref = %d + ', $consumer_key, $token, $user_id); + } + } + + + /** + * Set the ttl of a server access token. This is done when the + * server receives a valid request with a xoauth_token_ttl parameter in it. + * + * @param string consumer_key + * @param string token + * @param int token_ttl + */ + public function setServerTokenTtl ( $consumer_key, $token, $token_ttl ) + { + if ($token_ttl <= 0) + { + // Immediate delete when the token is past its ttl + $this->deleteServerToken($consumer_key, $token, 0, true); + } + else + { + // Set maximum time to live for this token + $this->query(' + UPDATE oauth_consumer_token, oauth_consumer_registry + SET ost_token_ttl = DATE_ADD(NOW(), INTERVAL %d SECOND) + WHERE ocr_consumer_key = \'%s\' + AND oct_ocr_id_ref = ocr_id + AND oct_token = \'%s\' + ', $token_ttl, $consumer_key, $token); + } + } + + + /** + * Get a list of all consumers from the consumer registry. + * The consumer keys belong to the user or are public (user id is null) + * + * @param string q query term + * @param int user_id + * @return array + */ + public function listServers ( $q = '', $user_id ) + { + $q = trim(str_replace('%', '', $q)); + $args = array(); + + if (!empty($q)) + { + $where = ' WHERE ( ocr_consumer_key like \'%%%s%%\' + OR ocr_server_uri like \'%%%s%%\' + OR ocr_server_uri_host like \'%%%s%%\' + OR ocr_server_uri_path like \'%%%s%%\') + AND (ocr_usa_id_ref = %d OR ocr_usa_id_ref IS NULL) + '; + + $args[] = $q; + $args[] = $q; + $args[] = $q; + $args[] = $q; + $args[] = $user_id; + } + else + { + $where = ' WHERE ocr_usa_id_ref = %d OR ocr_usa_id_ref IS NULL'; + $args[] = $user_id; + } + + $servers = $this->query_all_assoc(' + SELECT ocr_id as id, + ocr_usa_id_ref as user_id, + ocr_consumer_key as consumer_key, + ocr_consumer_secret as consumer_secret, + ocr_signature_methods as signature_methods, + ocr_server_uri as server_uri, + ocr_server_uri_host as server_uri_host, + ocr_server_uri_path as server_uri_path, + ocr_request_token_uri as request_token_uri, + ocr_authorize_uri as authorize_uri, + ocr_access_token_uri as access_token_uri + FROM oauth_consumer_registry + '.$where.' + ORDER BY ocr_server_uri_host, ocr_server_uri_path + ', $args); + return $servers; + } + + + /** + * Register or update a server for our site (we will be the consumer) + * + * (This is the registry at the consumers, registering servers ;-) ) + * + * @param array server + * @param int user_id user registering this server + * @param boolean user_is_admin + * @exception OAuthException2 when fields are missing or on duplicate consumer_key + * @return consumer_key + */ + public function updateServer ( $server, $user_id, $user_is_admin = false ) + { + foreach (array('consumer_key', 'server_uri') as $f) + { + if (empty($server[$f])) + { + throw new OAuthException2('The field "'.$f.'" must be set and non empty'); + } + } + + if (!empty($server['id'])) + { + $exists = $this->query_one(' + SELECT ocr_id + FROM oauth_consumer_registry + WHERE ocr_consumer_key = \'%s\' + AND ocr_id <> %d + AND (ocr_usa_id_ref = %d OR ocr_usa_id_ref IS NULL) + ', $server['consumer_key'], $server['id'], $user_id); + } + else + { + $exists = $this->query_one(' + SELECT ocr_id + FROM oauth_consumer_registry + WHERE ocr_consumer_key = \'%s\' + AND (ocr_usa_id_ref = %d OR ocr_usa_id_ref IS NULL) + ', $server['consumer_key'], $user_id); + } + + if ($exists) + { + throw new OAuthException2('The server with key "'.$server['consumer_key'].'" has already been registered'); + } + + $parts = parse_url($server['server_uri']); + $host = (isset($parts['host']) ? $parts['host'] : 'localhost'); + $path = (isset($parts['path']) ? $parts['path'] : '/'); + + if (isset($server['signature_methods'])) + { + if (is_array($server['signature_methods'])) + { + $server['signature_methods'] = strtoupper(implode(',', $server['signature_methods'])); + } + } + else + { + $server['signature_methods'] = ''; + } + + // When the user is an admin, then the user can update the user_id of this record + if ($user_is_admin && array_key_exists('user_id', $server)) + { + if (is_null($server['user_id'])) + { + $update_user = ', ocr_usa_id_ref = NULL'; + } + else + { + $update_user = ', ocr_usa_id_ref = '.intval($server['user_id']); + } + } + else + { + $update_user = ''; + } + + if (!empty($server['id'])) + { + // Check if the current user can update this server definition + if (!$user_is_admin) + { + $ocr_usa_id_ref = $this->query_one(' + SELECT ocr_usa_id_ref + FROM oauth_consumer_registry + WHERE ocr_id = %d + ', $server['id']); + + if ($ocr_usa_id_ref != $user_id) + { + throw new OAuthException2('The user "'.$user_id.'" is not allowed to update this server'); + } + } + + // Update the consumer registration + $this->query(' + UPDATE oauth_consumer_registry + SET ocr_consumer_key = \'%s\', + ocr_consumer_secret = \'%s\', + ocr_server_uri = \'%s\', + ocr_server_uri_host = \'%s\', + ocr_server_uri_path = \'%s\', + ocr_timestamp = NOW(), + ocr_request_token_uri = \'%s\', + ocr_authorize_uri = \'%s\', + ocr_access_token_uri = \'%s\', + ocr_signature_methods = \'%s\' + '.$update_user.' + WHERE ocr_id = %d + ', + $server['consumer_key'], + $server['consumer_secret'], + $server['server_uri'], + strtolower($host), + $path, + isset($server['request_token_uri']) ? $server['request_token_uri'] : '', + isset($server['authorize_uri']) ? $server['authorize_uri'] : '', + isset($server['access_token_uri']) ? $server['access_token_uri'] : '', + $server['signature_methods'], + $server['id'] + ); + } + else + { + if (empty($update_user)) + { + // Per default the user owning the key is the user registering the key + $update_user = ', ocr_usa_id_ref = '.intval($user_id); + } + + $this->query(' + INSERT INTO oauth_consumer_registry + SET ocr_consumer_key = \'%s\', + ocr_consumer_secret = \'%s\', + ocr_server_uri = \'%s\', + ocr_server_uri_host = \'%s\', + ocr_server_uri_path = \'%s\', + ocr_timestamp = NOW(), + ocr_request_token_uri = \'%s\', + ocr_authorize_uri = \'%s\', + ocr_access_token_uri = \'%s\', + ocr_signature_methods = \'%s\' + '.$update_user, + $server['consumer_key'], + $server['consumer_secret'], + $server['server_uri'], + strtolower($host), + $path, + isset($server['request_token_uri']) ? $server['request_token_uri'] : '', + isset($server['authorize_uri']) ? $server['authorize_uri'] : '', + isset($server['access_token_uri']) ? $server['access_token_uri'] : '', + $server['signature_methods'] + ); + + $ocr_id = $this->query_insert_id(); + } + return $server['consumer_key']; + } + + + /** + * Insert/update a new consumer with this server (we will be the server) + * When this is a new consumer, then also generate the consumer key and secret. + * Never updates the consumer key and secret. + * When the id is set, then the key and secret must correspond to the entry + * being updated. + * + * (This is the registry at the server, registering consumers ;-) ) + * + * @param array consumer + * @param int user_id user registering this consumer + * @param boolean user_is_admin + * @return string consumer key + */ + public function updateConsumer ( $consumer, $user_id, $user_is_admin = false ) + { + if (!$user_is_admin) + { + foreach (array('requester_name', 'requester_email') as $f) + { + if (empty($consumer[$f])) + { + throw new OAuthException2('The field "'.$f.'" must be set and non empty'); + } + } + } + + if (!empty($consumer['id'])) + { + if (empty($consumer['consumer_key'])) + { + throw new OAuthException2('The field "consumer_key" must be set and non empty'); + } + if (!$user_is_admin && empty($consumer['consumer_secret'])) + { + throw new OAuthException2('The field "consumer_secret" must be set and non empty'); + } + + // Check if the current user can update this server definition + if (!$user_is_admin) + { + $osr_usa_id_ref = $this->query_one(' + SELECT osr_usa_id_ref + FROM oauth_server_registry + WHERE osr_id = %d + ', $consumer['id']); + + if ($osr_usa_id_ref != $user_id) + { + throw new OAuthException2('The user "'.$user_id.'" is not allowed to update this consumer'); + } + } + else + { + // User is an admin, allow a key owner to be changed or key to be shared + if (array_key_exists('user_id',$consumer)) + { + if (is_null($consumer['user_id'])) + { + $this->query(' + UPDATE oauth_server_registry + SET osr_usa_id_ref = NULL + WHERE osr_id = %d + ', $consumer['id']); + } + else + { + $this->query(' + UPDATE oauth_server_registry + SET osr_usa_id_ref = %d + WHERE osr_id = %d + ', $consumer['user_id'], $consumer['id']); + } + } + } + + $this->query(' + UPDATE oauth_server_registry + SET osr_requester_name = \'%s\', + osr_requester_email = \'%s\', + osr_callback_uri = \'%s\', + osr_application_uri = \'%s\', + osr_application_title = \'%s\', + osr_application_descr = \'%s\', + osr_application_notes = \'%s\', + osr_application_type = \'%s\', + osr_application_commercial = IF(%d,1,0), + osr_timestamp = NOW() + WHERE osr_id = %d + AND osr_consumer_key = \'%s\' + AND osr_consumer_secret = \'%s\' + ', + $consumer['requester_name'], + $consumer['requester_email'], + isset($consumer['callback_uri']) ? $consumer['callback_uri'] : '', + isset($consumer['application_uri']) ? $consumer['application_uri'] : '', + isset($consumer['application_title']) ? $consumer['application_title'] : '', + isset($consumer['application_descr']) ? $consumer['application_descr'] : '', + isset($consumer['application_notes']) ? $consumer['application_notes'] : '', + isset($consumer['application_type']) ? $consumer['application_type'] : '', + isset($consumer['application_commercial']) ? $consumer['application_commercial'] : 0, + $consumer['id'], + $consumer['consumer_key'], + $consumer['consumer_secret'] + ); + + + $consumer_key = $consumer['consumer_key']; + } + else + { + $consumer_key = $this->generateKey(true); + $consumer_secret= $this->generateKey(); + + // When the user is an admin, then the user can be forced to something else that the user + if ($user_is_admin && array_key_exists('user_id',$consumer)) + { + if (is_null($consumer['user_id'])) + { + $owner_id = 'NULL'; + } + else + { + $owner_id = intval($consumer['user_id']); + } + } + else + { + // No admin, take the user id as the owner id. + $owner_id = intval($user_id); + } + + $this->query(' + INSERT INTO oauth_server_registry + SET osr_enabled = 1, + osr_status = \'active\', + osr_usa_id_ref = \'%s\', + osr_consumer_key = \'%s\', + osr_consumer_secret = \'%s\', + osr_requester_name = \'%s\', + osr_requester_email = \'%s\', + osr_callback_uri = \'%s\', + osr_application_uri = \'%s\', + osr_application_title = \'%s\', + osr_application_descr = \'%s\', + osr_application_notes = \'%s\', + osr_application_type = \'%s\', + osr_application_commercial = IF(%d,1,0), + osr_timestamp = NOW(), + osr_issue_date = NOW() + ', + $owner_id, + $consumer_key, + $consumer_secret, + $consumer['requester_name'], + $consumer['requester_email'], + isset($consumer['callback_uri']) ? $consumer['callback_uri'] : '', + isset($consumer['application_uri']) ? $consumer['application_uri'] : '', + isset($consumer['application_title']) ? $consumer['application_title'] : '', + isset($consumer['application_descr']) ? $consumer['application_descr'] : '', + isset($consumer['application_notes']) ? $consumer['application_notes'] : '', + isset($consumer['application_type']) ? $consumer['application_type'] : '', + isset($consumer['application_commercial']) ? $consumer['application_commercial'] : 0 + ); + } + return $consumer_key; + + } + + + + /** + * Delete a consumer key. This removes access to our site for all applications using this key. + * + * @param string consumer_key + * @param int user_id user registering this server + * @param boolean user_is_admin + */ + public function deleteConsumer ( $consumer_key, $user_id, $user_is_admin = false ) + { + if ($user_is_admin) + { + $this->query(' + DELETE FROM oauth_server_registry + WHERE osr_consumer_key = \'%s\' + AND (osr_usa_id_ref = %d OR osr_usa_id_ref IS NULL) + ', $consumer_key, $user_id); + } + else + { + $this->query(' + DELETE FROM oauth_server_registry + WHERE osr_consumer_key = \'%s\' + AND osr_usa_id_ref = %d + ', $consumer_key, $user_id); + } + } + + + + /** + * Fetch a consumer of this server, by consumer_key. + * + * @param string consumer_key + * @param int user_id + * @param boolean user_is_admin (optional) + * @exception OAuthException2 when consumer not found + * @return array + */ + public function getConsumer ( $consumer_key, $user_id, $user_is_admin = false ) + { + $consumer = $this->query_row_assoc(' + SELECT * + FROM oauth_server_registry + WHERE osr_consumer_key = \'%s\' + ', $consumer_key); + + if (!is_array($consumer)) + { + throw new OAuthException2('No consumer with consumer_key "'.$consumer_key.'"'); + } + + $c = array(); + foreach ($consumer as $key => $value) + { + $c[substr($key, 4)] = $value; + } + $c['user_id'] = $c['usa_id_ref']; + + if (!$user_is_admin && !empty($c['user_id']) && $c['user_id'] != $user_id) + { + throw new OAuthException2('No access to the consumer information for consumer_key "'.$consumer_key.'"'); + } + return $c; + } + + + /** + * Fetch the static consumer key for this provider. The user for the static consumer + * key is NULL (no user, shared key). If the key did not exist then the key is created. + * + * @return string + */ + public function getConsumerStatic () + { + $consumer = $this->query_one(' + SELECT osr_consumer_key + FROM oauth_server_registry + WHERE osr_consumer_key LIKE \'sc-%%\' + AND osr_usa_id_ref IS NULL + '); + + if (empty($consumer)) + { + $consumer_key = 'sc-'.$this->generateKey(true); + $this->query(' + INSERT INTO oauth_server_registry + SET osr_enabled = 1, + osr_status = \'active\', + osr_usa_id_ref = NULL, + osr_consumer_key = \'%s\', + osr_consumer_secret = \'\', + osr_requester_name = \'\', + osr_requester_email = \'\', + osr_callback_uri = \'\', + osr_application_uri = \'\', + osr_application_title = \'Static shared consumer key\', + osr_application_descr = \'\', + osr_application_notes = \'Static shared consumer key\', + osr_application_type = \'\', + osr_application_commercial = 0, + osr_timestamp = NOW(), + osr_issue_date = NOW() + ', + $consumer_key + ); + + // Just make sure that if the consumer key is truncated that we get the truncated string + $consumer = $this->getConsumerStatic(); + } + return $consumer; + } + + + /** + * Add an unautorized request token to our server. + * + * @param string consumer_key + * @param array options (eg. token_ttl) + * @return array (token, token_secret) + */ + public function addConsumerRequestToken ( $consumer_key, $options = array() ) + { + $token = $this->generateKey(true); + $secret = $this->generateKey(); + $osr_id = $this->query_one(' + SELECT osr_id + FROM oauth_server_registry + WHERE osr_consumer_key = \'%s\' + AND osr_enabled = 1 + ', $consumer_key); + + if (!$osr_id) + { + throw new OAuthException2('No server with consumer_key "'.$consumer_key.'" or consumer_key is disabled'); + } + + if (isset($options['token_ttl']) && is_numeric($options['token_ttl'])) + { + $ttl = intval($options['token_ttl']); + } + else + { + $ttl = $this->max_request_token_ttl; + } + + if (!isset($options['oauth_callback'])) { + // 1.0a Compatibility : store callback url associated with request token + $options['oauth_callback']='oob'; + } + + $this->query(' + INSERT INTO oauth_server_token + SET ost_osr_id_ref = %d, + ost_usa_id_ref = 1, + ost_token = \'%s\', + ost_token_secret = \'%s\', + ost_token_type = \'request\', + ost_token_ttl = DATE_ADD(NOW(), INTERVAL %d SECOND), + ost_callback_url = \'%s\' + ON DUPLICATE KEY UPDATE + ost_osr_id_ref = VALUES(ost_osr_id_ref), + ost_usa_id_ref = VALUES(ost_usa_id_ref), + ost_token = VALUES(ost_token), + ost_token_secret = VALUES(ost_token_secret), + ost_token_type = VALUES(ost_token_type), + ost_token_ttl = VALUES(ost_token_ttl), + ost_callback_url = VALUES(ost_callback_url), + ost_timestamp = NOW() + ', $osr_id, $token, $secret, $ttl, $options['oauth_callback']); + + return array('token'=>$token, 'token_secret'=>$secret, 'token_ttl'=>$ttl); + } + + + /** + * Fetch the consumer request token, by request token. + * + * @param string token + * @return array token and consumer details + */ + public function getConsumerRequestToken ( $token ) + { + $rs = $this->query_row_assoc(' + SELECT ost_token as token, + ost_token_secret as token_secret, + osr_consumer_key as consumer_key, + osr_consumer_secret as consumer_secret, + ost_token_type as token_type, + ost_callback_url as callback_url, + osr_application_title as application_title, + osr_application_descr as application_descr, + osr_application_uri as application_uri + FROM oauth_server_token + JOIN oauth_server_registry + ON ost_osr_id_ref = osr_id + WHERE ost_token_type = \'request\' + AND ost_token = \'%s\' + AND ost_token_ttl >= NOW() + ', $token); + + return $rs; + } + + + /** + * Delete a consumer token. The token must be a request or authorized token. + * + * @param string token + */ + public function deleteConsumerRequestToken ( $token ) + { + $this->query(' + DELETE FROM oauth_server_token + WHERE ost_token = \'%s\' + AND ost_token_type = \'request\' + ', $token); + } + + + /** + * Upgrade a request token to be an authorized request token. + * + * @param string token + * @param int user_id user authorizing the token + * @param string referrer_host used to set the referrer host for this token, for user feedback + */ + public function authorizeConsumerRequestToken ( $token, $user_id, $referrer_host = '' ) + { + // 1.0a Compatibility : create a token verifier + $verifier = substr(md5(rand()),0,10); + + $this->query(' + UPDATE oauth_server_token + SET ost_authorized = 1, + ost_usa_id_ref = %d, + ost_timestamp = NOW(), + ost_referrer_host = \'%s\', + ost_verifier = \'%s\' + WHERE ost_token = \'%s\' + AND ost_token_type = \'request\' + ', $user_id, $referrer_host, $verifier, $token); + return $verifier; + } + + + /** + * Count the consumer access tokens for the given consumer. + * + * @param string consumer_key + * @return int + */ + public function countConsumerAccessTokens ( $consumer_key ) + { + $count = $this->query_one(' + SELECT COUNT(ost_id) + FROM oauth_server_token + JOIN oauth_server_registry + ON ost_osr_id_ref = osr_id + WHERE ost_token_type = \'access\' + AND osr_consumer_key = \'%s\' + AND ost_token_ttl >= NOW() + ', $consumer_key); + + return $count; + } + + + /** + * Exchange an authorized request token for new access token. + * + * @param string token + * @param array options options for the token, token_ttl + * @exception OAuthException2 when token could not be exchanged + * @return array (token, token_secret) + */ + public function exchangeConsumerRequestForAccessToken ( $token, $options = array() ) + { + $new_token = $this->generateKey(true); + $new_secret = $this->generateKey(); + + // Maximum time to live for this token + if (isset($options['token_ttl']) && is_numeric($options['token_ttl'])) + { + $ttl_sql = 'DATE_ADD(NOW(), INTERVAL '.intval($options['token_ttl']).' SECOND)'; + } + else + { + $ttl_sql = "'9999-12-31'"; + } + + if (isset($options['verifier'])) { + $verifier = $options['verifier']; + + // 1.0a Compatibility : check token against oauth_verifier + $this->query(' + UPDATE oauth_server_token + SET ost_token = \'%s\', + ost_token_secret = \'%s\', + ost_token_type = \'access\', + ost_timestamp = NOW(), + ost_token_ttl = '.$ttl_sql.' + WHERE ost_token = \'%s\' + AND ost_token_type = \'request\' + AND ost_authorized = 1 + AND ost_token_ttl >= NOW() + AND ost_verifier = \'%s\' + ', $new_token, $new_secret, $token, $verifier); + } else { + + // 1.0 + $this->query(' + UPDATE oauth_server_token + SET ost_token = \'%s\', + ost_token_secret = \'%s\', + ost_token_type = \'access\', + ost_timestamp = NOW(), + ost_token_ttl = '.$ttl_sql.' + WHERE ost_token = \'%s\' + AND ost_token_type = \'request\' + AND ost_authorized = 1 + AND ost_token_ttl >= NOW() + ', $new_token, $new_secret, $token); + } + + if ($this->query_affected_rows() != 1) + { + throw new OAuthException2('Can\'t exchange request token "'.$token.'" for access token. No such token or not authorized'); + } + + $ret = array('token' => $new_token, 'token_secret' => $new_secret); + $ttl = $this->query_one(' + SELECT IF(ost_token_ttl >= \'9999-12-31\', NULL, UNIX_TIMESTAMP(ost_token_ttl) - UNIX_TIMESTAMP(NOW())) as token_ttl + FROM oauth_server_token + WHERE ost_token = \'%s\'', $new_token); + + if (is_numeric($ttl)) + { + $ret['token_ttl'] = intval($ttl); + } + return $ret; + } + + + /** + * Fetch the consumer access token, by access token. + * + * @param string token + * @param int user_id + * @exception OAuthException2 when token is not found + * @return array token and consumer details + */ + public function getConsumerAccessToken ( $token, $user_id ) + { + $rs = $this->query_row_assoc(' + SELECT ost_token as token, + ost_token_secret as token_secret, + ost_referrer_host as token_referrer_host, + osr_consumer_key as consumer_key, + osr_consumer_secret as consumer_secret, + osr_application_uri as application_uri, + osr_application_title as application_title, + osr_application_descr as application_descr, + osr_callback_uri as callback_uri + FROM oauth_server_token + JOIN oauth_server_registry + ON ost_osr_id_ref = osr_id + WHERE ost_token_type = \'access\' + AND ost_token = \'%s\' + AND ost_usa_id_ref = %d + AND ost_token_ttl >= NOW() + ', $token, $user_id); + + if (empty($rs)) + { + throw new OAuthException2('No server_token "'.$token.'" for user "'.$user_id.'"'); + } + return $rs; + } + + + /** + * Delete a consumer access token. + * + * @param string token + * @param int user_id + * @param boolean user_is_admin + */ + public function deleteConsumerAccessToken ( $token, $user_id, $user_is_admin = false ) + { + if ($user_is_admin) + { + $this->query(' + DELETE FROM oauth_server_token + WHERE ost_token = \'%s\' + AND ost_token_type = \'access\' + ', $token); + } + else + { + $this->query(' + DELETE FROM oauth_server_token + WHERE ost_token = \'%s\' + AND ost_token_type = \'access\' + AND ost_usa_id_ref = %d + ', $token, $user_id); + } + } + + + /** + * Set the ttl of a consumer access token. This is done when the + * server receives a valid request with a xoauth_token_ttl parameter in it. + * + * @param string token + * @param int ttl + */ + public function setConsumerAccessTokenTtl ( $token, $token_ttl ) + { + if ($token_ttl <= 0) + { + // Immediate delete when the token is past its ttl + $this->deleteConsumerAccessToken($token, 0, true); + } + else + { + // Set maximum time to live for this token + $this->query(' + UPDATE oauth_server_token + SET ost_token_ttl = DATE_ADD(NOW(), INTERVAL %d SECOND) + WHERE ost_token = \'%s\' + AND ost_token_type = \'access\' + ', $token_ttl, $token); + } + } + + + /** + * Fetch a list of all consumer keys, secrets etc. + * Returns the public (user_id is null) and the keys owned by the user + * + * @param int user_id + * @return array + */ + public function listConsumers ( $user_id ) + { + $rs = $this->query_all_assoc(' + SELECT osr_id as id, + osr_usa_id_ref as user_id, + osr_consumer_key as consumer_key, + osr_consumer_secret as consumer_secret, + osr_enabled as enabled, + osr_status as status, + osr_issue_date as issue_date, + osr_application_uri as application_uri, + osr_application_title as application_title, + osr_application_descr as application_descr, + osr_requester_name as requester_name, + osr_requester_email as requester_email, + osr_callback_uri as callback_uri + FROM oauth_server_registry + WHERE (osr_usa_id_ref = %d OR osr_usa_id_ref IS NULL) + ORDER BY osr_application_title + ', $user_id); + return $rs; + } + + /** + * List of all registered applications. Data returned has not sensitive + * information and therefore is suitable for public displaying. + * + * @param int $begin + * @param int $total + * @return array + */ + public function listConsumerApplications($begin = 0, $total = 25) + { + $rs = $this->query_all_assoc(' + SELECT osr_id as id, + osr_enabled as enabled, + osr_status as status, + osr_issue_date as issue_date, + osr_application_uri as application_uri, + osr_application_title as application_title, + osr_application_descr as application_descr + FROM oauth_server_registry + ORDER BY osr_application_title + '); + // TODO: pagination + return $rs; + } + + /** + * Fetch a list of all consumer tokens accessing the account of the given user. + * + * @param int user_id + * @return array + */ + public function listConsumerTokens ( $user_id ) + { + $rs = $this->query_all_assoc(' + SELECT osr_consumer_key as consumer_key, + osr_consumer_secret as consumer_secret, + osr_enabled as enabled, + osr_status as status, + osr_application_uri as application_uri, + osr_application_title as application_title, + osr_application_descr as application_descr, + ost_timestamp as timestamp, + ost_token as token, + ost_token_secret as token_secret, + ost_referrer_host as token_referrer_host, + osr_callback_uri as callback_uri + FROM oauth_server_registry + JOIN oauth_server_token + ON ost_osr_id_ref = osr_id + WHERE ost_usa_id_ref = %d + AND ost_token_type = \'access\' + AND ost_token_ttl >= NOW() + ORDER BY osr_application_title + ', $user_id); + return $rs; + } + + + /** + * Check an nonce/timestamp combination. Clears any nonce combinations + * that are older than the one received. + * + * @param string consumer_key + * @param string token + * @param int timestamp + * @param string nonce + * @exception OAuthException2 thrown when the timestamp is not in sequence or nonce is not unique + */ + public function checkServerNonce ( $consumer_key, $token, $timestamp, $nonce ) + { + $r = $this->query_row(' + SELECT MAX(osn_timestamp), MAX(osn_timestamp) > %d + %d + FROM oauth_server_nonce + WHERE osn_consumer_key = \'%s\' + AND osn_token = \'%s\' + ', $timestamp, $this->max_timestamp_skew, $consumer_key, $token); + + if (!empty($r) && $r[1]) + { + throw new OAuthException2('Timestamp is out of sequence. Request rejected. Got '.$timestamp.' last max is '.$r[0].' allowed skew is '.$this->max_timestamp_skew); + } + + // Insert the new combination + $this->query(' + INSERT IGNORE INTO oauth_server_nonce + SET osn_consumer_key = \'%s\', + osn_token = \'%s\', + osn_timestamp = %d, + osn_nonce = \'%s\' + ', $consumer_key, $token, $timestamp, $nonce); + + if ($this->query_affected_rows() == 0) + { + throw new OAuthException2('Duplicate timestamp/nonce combination, possible replay attack. Request rejected.'); + } + + // Clean up all timestamps older than the one we just received + $this->query(' + DELETE FROM oauth_server_nonce + WHERE osn_consumer_key = \'%s\' + AND osn_token = \'%s\' + AND osn_timestamp < %d - %d + ', $consumer_key, $token, $timestamp, $this->max_timestamp_skew); + } + + + /** + * Add an entry to the log table + * + * @param array keys (osr_consumer_key, ost_token, ocr_consumer_key, oct_token) + * @param string received + * @param string sent + * @param string base_string + * @param string notes + * @param int (optional) user_id + */ + public function addLog ( $keys, $received, $sent, $base_string, $notes, $user_id = null ) + { + $args = array(); + $ps = array(); + foreach ($keys as $key => $value) + { + $args[] = $value; + $ps[] = "olg_$key = '%s'"; + } + + if (!empty($_SERVER['REMOTE_ADDR'])) + { + $remote_ip = $_SERVER['REMOTE_ADDR']; + } + else if (!empty($_SERVER['REMOTE_IP'])) + { + $remote_ip = $_SERVER['REMOTE_IP']; + } + else + { + $remote_ip = '0.0.0.0'; + } + + // Build the SQL + $ps[] = "olg_received = '%s'"; $args[] = $this->makeUTF8($received); + $ps[] = "olg_sent = '%s'"; $args[] = $this->makeUTF8($sent); + $ps[] = "olg_base_string= '%s'"; $args[] = $base_string; + $ps[] = "olg_notes = '%s'"; $args[] = $this->makeUTF8($notes); + $ps[] = "olg_usa_id_ref = NULLIF(%d,0)"; $args[] = $user_id; + $ps[] = "olg_remote_ip = IFNULL(INET_ATON('%s'),0)"; $args[] = $remote_ip; + + $this->query('INSERT INTO oauth_log SET '.implode(',', $ps), $args); + } + + + /** + * Get a page of entries from the log. Returns the last 100 records + * matching the options given. + * + * @param array options + * @param int user_id current user + * @return array log records + */ + public function listLog ( $options, $user_id ) + { + $where = array(); + $args = array(); + if (empty($options)) + { + $where[] = 'olg_usa_id_ref = %d'; + $args[] = $user_id; + } + else + { + foreach ($options as $option => $value) + { + if (strlen($value) > 0) + { + switch ($option) + { + case 'osr_consumer_key': + case 'ocr_consumer_key': + case 'ost_token': + case 'oct_token': + $where[] = 'olg_'.$option.' = \'%s\''; + $args[] = $value; + break; + } + } + } + + $where[] = '(olg_usa_id_ref IS NULL OR olg_usa_id_ref = %d)'; + $args[] = $user_id; + } + + $rs = $this->query_all_assoc(' + SELECT olg_id, + olg_osr_consumer_key AS osr_consumer_key, + olg_ost_token AS ost_token, + olg_ocr_consumer_key AS ocr_consumer_key, + olg_oct_token AS oct_token, + olg_usa_id_ref AS user_id, + olg_received AS received, + olg_sent AS sent, + olg_base_string AS base_string, + olg_notes AS notes, + olg_timestamp AS timestamp, + INET_NTOA(olg_remote_ip) AS remote_ip + FROM oauth_log + WHERE '.implode(' AND ', $where).' + ORDER BY olg_id DESC + LIMIT 0,100', $args); + + return $rs; + } + + + /* ** Some simple helper functions for querying the mysql db ** */ + + /** + * Perform a query, ignore the results + * + * @param string sql + * @param vararg arguments (for sprintf) + */ + abstract protected function query ( $sql ); + + + /** + * Perform a query, ignore the results + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + abstract protected function query_all_assoc ( $sql ); + + + /** + * Perform a query, return the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + abstract protected function query_row_assoc ( $sql ); + + /** + * Perform a query, return the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return array + */ + abstract protected function query_row ( $sql ); + + + /** + * Perform a query, return the first column of the first row + * + * @param string sql + * @param vararg arguments (for sprintf) + * @return mixed + */ + abstract protected function query_one ( $sql ); + + + /** + * Return the number of rows affected in the last query + */ + abstract protected function query_affected_rows (); + + + /** + * Return the id of the last inserted row + * + * @return int + */ + abstract protected function query_insert_id (); + + + abstract protected function sql_printf ( $args ); + + + abstract protected function sql_escape_string ( $s ); + + + abstract protected function sql_errcheck ( $sql ); +} + + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/store/OAuthStoreSession.php b/includes/oauth-php/library/store/OAuthStoreSession.php new file mode 100644 index 00000000..4202514a --- /dev/null +++ b/includes/oauth-php/library/store/OAuthStoreSession.php @@ -0,0 +1,157 @@ +session = &$_SESSION['oauth_' . $options['consumer_key']]; + $this->session['consumer_key'] = $options['consumer_key']; + $this->session['consumer_secret'] = $options['consumer_secret']; + $this->session['signature_methods'] = array('HMAC-SHA1'); + $this->session['server_uri'] = $options['server_uri']; + $this->session['request_token_uri'] = $options['request_token_uri']; + $this->session['authorize_uri'] = $options['authorize_uri']; + $this->session['access_token_uri'] = $options['access_token_uri']; + + } + else + { + throw new OAuthException2("OAuthStoreSession needs consumer_token and consumer_secret"); + } + } + + public function getSecretsForVerify ( $consumer_key, $token, $token_type = 'access' ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function getSecretsForSignature ( $uri, $user_id ) + { + return $this->session; + } + + public function getServerTokenSecrets ( $consumer_key, $token, $token_type, $user_id, $name = '') + { + if ($consumer_key != $this->session['consumer_key']) { + return array(); + } + return array( + 'consumer_key' => $consumer_key, + 'consumer_secret' => $this->session['consumer_secret'], + 'token' => $token, + 'token_secret' => $this->session['token_secret'], + 'token_name' => $name, + 'signature_methods' => $this->session['signature_methods'], + 'server_uri' => $this->session['server_uri'], + 'request_token_uri' => $this->session['request_token_uri'], + 'authorize_uri' => $this->session['authorize_uri'], + 'access_token_uri' => $this->session['access_token_uri'], + 'token_ttl' => 3600, + ); + } + + public function addServerToken ( $consumer_key, $token_type, $token, $token_secret, $user_id, $options = array() ) + { + $this->session['token_type'] = $token_type; + $this->session['token'] = $token; + $this->session['token_secret'] = $token_secret; + } + + public function deleteServer ( $consumer_key, $user_id, $user_is_admin = false ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function getServer( $consumer_key, $user_id, $user_is_admin = false ) { + return array( + 'id' => 0, + 'user_id' => $user_id, + 'consumer_key' => $this->session['consumer_key'], + 'consumer_secret' => $this->session['consumer_secret'], + 'signature_methods' => $this->session['signature_methods'], + 'server_uri' => $this->session['server_uri'], + 'request_token_uri' => $this->session['request_token_uri'], + 'authorize_uri' => $this->session['authorize_uri'], + 'access_token_uri' => $this->session['access_token_uri'], + ); + } + + public function getServerForUri ( $uri, $user_id ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function listServerTokens ( $user_id ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function countServerTokens ( $consumer_key ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function getServerToken ( $consumer_key, $token, $user_id ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function deleteServerToken ( $consumer_key, $token, $user_id, $user_is_admin = false ) { + // TODO + } + + public function setServerTokenTtl ( $consumer_key, $token, $token_ttl ) + { + //This method just needs to exist. It doesn't have to do anything! + } + + public function listServers ( $q = '', $user_id ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function updateServer ( $server, $user_id, $user_is_admin = false ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + + public function updateConsumer ( $consumer, $user_id, $user_is_admin = false ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function deleteConsumer ( $consumer_key, $user_id, $user_is_admin = false ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function getConsumer ( $consumer_key, $user_id, $user_is_admin = false ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function getConsumerStatic () { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + + public function addConsumerRequestToken ( $consumer_key, $options = array() ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function getConsumerRequestToken ( $token ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function deleteConsumerRequestToken ( $token ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function authorizeConsumerRequestToken ( $token, $user_id, $referrer_host = '' ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function countConsumerAccessTokens ( $consumer_key ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function exchangeConsumerRequestForAccessToken ( $token, $options = array() ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function getConsumerAccessToken ( $token, $user_id ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function deleteConsumerAccessToken ( $token, $user_id, $user_is_admin = false ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function setConsumerAccessTokenTtl ( $token, $ttl ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + + public function listConsumers ( $user_id ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function listConsumerApplications( $begin = 0, $total = 25 ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function listConsumerTokens ( $user_id ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + + public function checkServerNonce ( $consumer_key, $token, $timestamp, $nonce ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + + public function addLog ( $keys, $received, $sent, $base_string, $notes, $user_id = null ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + public function listLog ( $options, $user_id ) { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } + + public function install () { throw new OAuthException2("OAuthStoreSession doesn't support " . __METHOD__); } +} + +?> \ No newline at end of file diff --git a/includes/oauth-php/library/store/mysql/install.php b/includes/oauth-php/library/store/mysql/install.php new file mode 100644 index 00000000..0015da5e --- /dev/null +++ b/includes/oauth-php/library/store/mysql/install.php @@ -0,0 +1,32 @@ + \ No newline at end of file diff --git a/includes/oauth-php/library/store/mysql/mysql.sql b/includes/oauth-php/library/store/mysql/mysql.sql new file mode 100644 index 00000000..db7f237f --- /dev/null +++ b/includes/oauth-php/library/store/mysql/mysql.sql @@ -0,0 +1,236 @@ +# Datamodel for OAuthStoreMySQL +# +# You need to add the foreign key constraints for the user ids your are using. +# I have commented the constraints out, just look for 'usa_id_ref' to enable them. +# +# The --SPLIT-- markers are used by the install.php script +# +# @version $Id: mysql.sql 156 2010-09-16 15:46:49Z brunobg@corollarium.com $ +# @author Marc Worrell +# + +# Changes: +# +# 2010-09-15 +# ALTER TABLE oauth_server_token MODIFY ost_referrer_host varchar(128) not null default ''; +# +# 2010-07-22 +# ALTER TABLE oauth_consumer_registry DROP INDEX ocr_consumer_key; +# ALTER TABLE oauth_consumer_registry ADD UNIQUE ocr_consumer_key(ocr_consumer_key,ocr_usa_id_ref,ocr_server_uri) +# +# 2010-04-20 (on 103 and 110) +# ALTER TABLE oauth_consumer_registry MODIFY ocr_consumer_key varchar(128) binary not null; +# ALTER TABLE oauth_consumer_registry MODIFY ocr_consumer_secret varchar(128) binary not null; +# +# 2010-04-20 (on 103 and 110) +# ALTER TABLE oauth_server_token ADD ost_verifier char(10); +# ALTER TABLE oauth_server_token ADD ost_callback_url varchar(512); +# +# 2008-10-15 (on r48) Added ttl to consumer and server tokens, added named server tokens +# +# ALTER TABLE oauth_server_token +# ADD ost_token_ttl datetime not null default '9999-12-31', +# ADD KEY (ost_token_ttl); +# +# ALTER TABLE oauth_consumer_token +# ADD oct_name varchar(64) binary not null default '', +# ADD oct_token_ttl datetime not null default '9999-12-31', +# DROP KEY oct_usa_id_ref, +# ADD UNIQUE KEY (oct_usa_id_ref, oct_ocr_id_ref, oct_token_type, oct_name), +# ADD KEY (oct_token_ttl); +# +# 2008-09-09 (on r5) Added referrer host to server access token +# +# ALTER TABLE oauth_server_token ADD ost_referrer_host VARCHAR(128) NOT NULL; +# + + +# +# Log table to hold all OAuth request when you enabled logging +# + +CREATE TABLE IF NOT EXISTS oauth_log ( + olg_id int(11) not null auto_increment, + olg_osr_consumer_key varchar(64) binary, + olg_ost_token varchar(64) binary, + olg_ocr_consumer_key varchar(64) binary, + olg_oct_token varchar(64) binary, + olg_usa_id_ref int(11), + olg_received text not null, + olg_sent text not null, + olg_base_string text not null, + olg_notes text not null, + olg_timestamp timestamp not null default current_timestamp, + olg_remote_ip bigint not null, + + primary key (olg_id), + key (olg_osr_consumer_key, olg_id), + key (olg_ost_token, olg_id), + key (olg_ocr_consumer_key, olg_id), + key (olg_oct_token, olg_id), + key (olg_usa_id_ref, olg_id) + +# , foreign key (olg_usa_id_ref) references any_user_auth (usa_id_ref) +# on update cascade +# on delete cascade +) engine=InnoDB default charset=utf8; + +#--SPLIT-- + +# +# /////////////////// CONSUMER SIDE /////////////////// +# + +# This is a registry of all consumer codes we got from other servers +# The consumer_key/secret is obtained from the server +# We also register the server uri, so that we can find the consumer key and secret +# for a certain server. From that server we can check if we have a token for a +# particular user. + +CREATE TABLE IF NOT EXISTS oauth_consumer_registry ( + ocr_id int(11) not null auto_increment, + ocr_usa_id_ref int(11), + ocr_consumer_key varchar(128) binary not null, + ocr_consumer_secret varchar(128) binary not null, + ocr_signature_methods varchar(255) not null default 'HMAC-SHA1,PLAINTEXT', + ocr_server_uri varchar(255) not null, + ocr_server_uri_host varchar(128) not null, + ocr_server_uri_path varchar(128) binary not null, + + ocr_request_token_uri varchar(255) not null, + ocr_authorize_uri varchar(255) not null, + ocr_access_token_uri varchar(255) not null, + ocr_timestamp timestamp not null default current_timestamp, + + primary key (ocr_id), + unique key (ocr_consumer_key, ocr_usa_id_ref, ocr_server_uri), + key (ocr_server_uri), + key (ocr_server_uri_host, ocr_server_uri_path), + key (ocr_usa_id_ref) + +# , foreign key (ocr_usa_id_ref) references any_user_auth(usa_id_ref) +# on update cascade +# on delete set null +) engine=InnoDB default charset=utf8; + +#--SPLIT-- + +# Table used to sign requests for sending to a server by the consumer +# The key is defined for a particular user. Only one single named +# key is allowed per user/server combination + +CREATE TABLE IF NOT EXISTS oauth_consumer_token ( + oct_id int(11) not null auto_increment, + oct_ocr_id_ref int(11) not null, + oct_usa_id_ref int(11) not null, + oct_name varchar(64) binary not null default '', + oct_token varchar(64) binary not null, + oct_token_secret varchar(64) binary not null, + oct_token_type enum('request','authorized','access'), + oct_token_ttl datetime not null default '9999-12-31', + oct_timestamp timestamp not null default current_timestamp, + + primary key (oct_id), + unique key (oct_ocr_id_ref, oct_token), + unique key (oct_usa_id_ref, oct_ocr_id_ref, oct_token_type, oct_name), + key (oct_token_ttl), + + foreign key (oct_ocr_id_ref) references oauth_consumer_registry (ocr_id) + on update cascade + on delete cascade + +# , foreign key (oct_usa_id_ref) references any_user_auth (usa_id_ref) +# on update cascade +# on delete cascade +) engine=InnoDB default charset=utf8; + +#--SPLIT-- + + +# +# ////////////////// SERVER SIDE ///////////////// +# + +# Table holding consumer key/secret combos an user issued to consumers. +# Used for verification of incoming requests. + +CREATE TABLE IF NOT EXISTS oauth_server_registry ( + osr_id int(11) not null auto_increment, + osr_usa_id_ref int(11), + osr_consumer_key varchar(64) binary not null, + osr_consumer_secret varchar(64) binary not null, + osr_enabled tinyint(1) not null default '1', + osr_status varchar(16) not null, + osr_requester_name varchar(64) not null, + osr_requester_email varchar(64) not null, + osr_callback_uri varchar(255) not null, + osr_application_uri varchar(255) not null, + osr_application_title varchar(80) not null, + osr_application_descr text not null, + osr_application_notes text not null, + osr_application_type varchar(20) not null, + osr_application_commercial tinyint(1) not null default '0', + osr_issue_date datetime not null, + osr_timestamp timestamp not null default current_timestamp, + + primary key (osr_id), + unique key (osr_consumer_key), + key (osr_usa_id_ref) + +# , foreign key (osr_usa_id_ref) references any_user_auth(usa_id_ref) +# on update cascade +# on delete set null +) engine=InnoDB default charset=utf8; + +#--SPLIT-- + +# Nonce used by a certain consumer, every used nonce should be unique, this prevents +# replaying attacks. We need to store all timestamp/nonce combinations for the +# maximum timestamp received. + +CREATE TABLE IF NOT EXISTS oauth_server_nonce ( + osn_id int(11) not null auto_increment, + osn_consumer_key varchar(64) binary not null, + osn_token varchar(64) binary not null, + osn_timestamp bigint not null, + osn_nonce varchar(80) binary not null, + + primary key (osn_id), + unique key (osn_consumer_key, osn_token, osn_timestamp, osn_nonce) +) engine=InnoDB default charset=utf8; + +#--SPLIT-- + +# Table used to verify signed requests sent to a server by the consumer +# When the verification is succesful then the associated user id is returned. + +CREATE TABLE IF NOT EXISTS oauth_server_token ( + ost_id int(11) not null auto_increment, + ost_osr_id_ref int(11) not null, + ost_usa_id_ref int(11) not null, + ost_token varchar(64) binary not null, + ost_token_secret varchar(64) binary not null, + ost_token_type enum('request','access'), + ost_authorized tinyint(1) not null default '0', + ost_referrer_host varchar(128) not null default '', + ost_token_ttl datetime not null default '9999-12-31', + ost_timestamp timestamp not null default current_timestamp, + ost_verifier char(10), + ost_callback_url varchar(512), + + primary key (ost_id), + unique key (ost_token), + key (ost_osr_id_ref), + key (ost_token_ttl), + + foreign key (ost_osr_id_ref) references oauth_server_registry (osr_id) + on update cascade + on delete cascade + +# , foreign key (ost_usa_id_ref) references any_user_auth (usa_id_ref) +# on update cascade +# on delete cascade +) engine=InnoDB default charset=utf8; + + + diff --git a/includes/oauth-php/library/store/oracle/OracleDB/1_Tables/TABLES.sql b/includes/oauth-php/library/store/oracle/OracleDB/1_Tables/TABLES.sql new file mode 100644 index 00000000..3d4fa22d --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/1_Tables/TABLES.sql @@ -0,0 +1,114 @@ +CREATE TABLE oauth_log +( + olg_id number, + olg_osr_consumer_key varchar2(64), + olg_ost_token varchar2(64), + olg_ocr_consumer_key varchar2(64), + olg_oct_token varchar2(64), + olg_usa_id_ref number, + olg_received varchar2(500), + olg_sent varchar2(500), + olg_base_string varchar2(500), + olg_notes varchar2(500), + olg_timestamp date default sysdate, + olg_remote_ip varchar2(50) +); + +alter table oauth_log + add constraint oauth_log_pk primary key (olg_id); + + +CREATE TABLE oauth_consumer_registry +( + ocr_id number, + ocr_usa_id_ref number, + ocr_consumer_key varchar2(64), + ocr_consumer_secret varchar2(64), + ocr_signature_methods varchar2(255)default 'HMAC-SHA1,PLAINTEXT', + ocr_server_uri varchar2(255), + ocr_server_uri_host varchar2(128), + ocr_server_uri_path varchar2(128), + ocr_request_token_uri varchar2(255), + ocr_authorize_uri varchar2(255), + ocr_access_token_uri varchar2(255), + ocr_timestamp date default sysdate +) + +alter table oauth_consumer_registry + add constraint oauth_consumer_registry_pk primary key (ocr_id); + + +CREATE TABLE oauth_consumer_token +( + oct_id number, + oct_ocr_id_ref number, + oct_usa_id_ref number, + oct_name varchar2(64) default '', + oct_token varchar2(64), + oct_token_secret varchar2(64), + oct_token_type varchar2(20), -- enum('request','authorized','access'), + oct_token_ttl date default TO_DATE('9999.12.31', 'yyyy.mm.dd'), + oct_timestamp date default sysdate +); + +alter table oauth_consumer_token + add constraint oauth_consumer_token_pk primary key (oct_id); + + +CREATE TABLE oauth_server_registry +( + osr_id number, + osr_usa_id_ref number, + osr_consumer_key varchar2(64), + osr_consumer_secret varchar2(64), + osr_enabled integer default '1', + osr_status varchar2(16), + osr_requester_name varchar2(64), + osr_requester_email varchar2(64), + osr_callback_uri varchar2(255), + osr_application_uri varchar2(255), + osr_application_title varchar2(80), + osr_application_descr varchar2(500), + osr_application_notes varchar2(500), + osr_application_type varchar2(20), + osr_application_commercial integer default '0', + osr_issue_date date, + osr_timestamp date default sysdate +); + + +alter table oauth_server_registry + add constraint oauth_server_registry_pk primary key (osr_id); + + +CREATE TABLE oauth_server_nonce +( + osn_id number, + osn_consumer_key varchar2(64), + osn_token varchar2(64), + osn_timestamp number, + osn_nonce varchar2(80) +); + +alter table oauth_server_nonce + add constraint oauth_server_nonce_pk primary key (osn_id); + + +CREATE TABLE oauth_server_token +( + ost_id number, + ost_osr_id_ref number, + ost_usa_id_ref number, + ost_token varchar2(64), + ost_token_secret varchar2(64), + ost_token_type varchar2(20), -- enum('request','access'), + ost_authorized integer default '0', + ost_referrer_host varchar2(128), + ost_token_ttl date default TO_DATE('9999.12.31', 'yyyy.mm.dd'), + ost_timestamp date default sysdate, + ost_verifier varchar2(10), + ost_callback_url varchar2(512) +); + +alter table oauth_server_token + add constraint oauth_server_token_pk primary key (ost_id); \ No newline at end of file diff --git a/includes/oauth-php/library/store/oracle/OracleDB/2_Sequences/SEQUENCES.sql b/includes/oauth-php/library/store/oracle/OracleDB/2_Sequences/SEQUENCES.sql new file mode 100644 index 00000000..53e42278 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/2_Sequences/SEQUENCES.sql @@ -0,0 +1,9 @@ +CREATE SEQUENCE SEQ_OCT_ID NOCACHE; + +CREATE SEQUENCE SEQ_OCR_ID NOCACHE; + +CREATE SEQUENCE SEQ_OSR_ID NOCACHE; + +CREATE SEQUENCE SEQ_OSN_ID NOCACHE; + +CREATE SEQUENCE SEQ_OLG_ID NOCACHE; diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_ADD_CONSUMER_REQUEST_TOKEN.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_ADD_CONSUMER_REQUEST_TOKEN.prc new file mode 100644 index 00000000..efb95365 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_ADD_CONSUMER_REQUEST_TOKEN.prc @@ -0,0 +1,71 @@ +CREATE OR REPLACE PROCEDURE SP_ADD_CONSUMER_REQUEST_TOKEN +( +P_TOKEN_TTL IN NUMBER, -- IN SECOND +P_CONSUMER_KEY IN VARCHAR2, +P_TOKEN IN VARCHAR2, +P_TOKEN_SECRET IN VARCHAR2, +P_CALLBACK_URL IN VARCHAR2, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Add an unautorized request token to our server. + +V_OSR_ID NUMBER; +V_OSR_ID_REF NUMBER; + +V_EXC_NO_SERVER_EXIST EXCEPTION; +BEGIN + + P_RESULT := 0; + + BEGIN + SELECT OSR_ID INTO V_OSR_ID + FROM OAUTH_SERVER_REGISTRY + WHERE OSR_CONSUMER_KEY = P_CONSUMER_KEY + AND OSR_ENABLED = 1; + EXCEPTION + WHEN NO_DATA_FOUND THEN + RAISE V_EXC_NO_SERVER_EXIST; + END; + + +BEGIN + SELECT OST_OSR_ID_REF INTO V_OSR_ID_REF + FROM OAUTH_SERVER_TOKEN + WHERE OST_OSR_ID_REF = V_OSR_ID; + + UPDATE OAUTH_SERVER_TOKEN + SET OST_OSR_ID_REF = V_OSR_ID, + OST_USA_ID_REF = 1, + OST_TOKEN = P_TOKEN, + OST_TOKEN_SECRET = P_TOKEN_SECRET, + OST_TOKEN_TYPE = 'REQUEST', + OST_TOKEN_TTL = SYSDATE + (P_TOKEN_TTL/(24*60*60)), + OST_CALLBACK_URL = P_CALLBACK_URL, + OST_TIMESTAMP = SYSDATE + WHERE OST_OSR_ID_REF = V_OSR_ID_REF; + + + EXCEPTION + WHEN NO_DATA_FOUND THEN + + INSERT INTO OAUTH_SERVER_TOKEN + (OST_ID, OST_OSR_ID_REF, OST_USA_ID_REF, OST_TOKEN, OST_TOKEN_SECRET, OST_TOKEN_TYPE, + OST_TOKEN_TTL, OST_CALLBACK_URL) + VALUES + (SEQ_OCT_ID.NEXTVAL, V_OSR_ID, 1, P_TOKEN, P_TOKEN_SECRET, 'REQUEST', SYSDATE + (P_TOKEN_TTL/(24*60*60)), + P_CALLBACK_URL); + + END; + + +EXCEPTION +WHEN V_EXC_NO_SERVER_EXIST THEN +P_RESULT := 2; -- NO_SERVER_EXIST +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_ADD_LOG.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_ADD_LOG.prc new file mode 100644 index 00000000..329499d9 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_ADD_LOG.prc @@ -0,0 +1,31 @@ +CREATE OR REPLACE PROCEDURE SP_ADD_LOG +( +P_RECEIVED IN VARCHAR2, +P_SENT IN VARCHAR2, +P_BASE_STRING IN VARCHAR2, +P_NOTES IN VARCHAR2, +P_USA_ID_REF IN NUMBER, +P_REMOTE_IP IN VARCHAR2, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Add an entry to the log table + +BEGIN + + P_RESULT := 0; + + INSERT INTO oauth_log + (OLG_ID, olg_received, olg_sent, olg_base_string, olg_notes, olg_usa_id_ref, olg_remote_ip) + VALUES + (SEQ_OLG_ID.NEXTVAL, P_RECEIVED, P_SENT, P_BASE_STRING, P_NOTES, NVL(P_USA_ID_REF, 0), P_REMOTE_IP); + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_ADD_SERVER_TOKEN.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_ADD_SERVER_TOKEN.prc new file mode 100644 index 00000000..371134c9 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_ADD_SERVER_TOKEN.prc @@ -0,0 +1,55 @@ +CREATE OR REPLACE PROCEDURE SP_ADD_SERVER_TOKEN +( +P_CONSUMER_KEY IN VARCHAR2, +P_USER_ID IN NUMBER, +P_NAME IN VARCHAR2, +P_TOKEN_TYPE IN VARCHAR2, +P_TOKEN IN VARCHAR2, +P_TOKEN_SECRET IN VARCHAR2, +P_TOKEN_INTERVAL_IN_SEC IN NUMBER, +P_RESULT OUT NUMBER +) +AS + + -- Add a request token we obtained from a server. +V_OCR_ID NUMBER; +V_TOKEN_TTL DATE; + +V_EXC_INVALID_CONSUMER_KEY EXCEPTION; +BEGIN +P_RESULT := 0; + + BEGIN + SELECT OCR_ID INTO V_OCR_ID FROM OAUTH_CONSUMER_REGISTRY + WHERE OCR_CONSUMER_KEY = P_CONSUMER_KEY AND OCR_USA_ID_REF = P_USER_ID; + EXCEPTION + WHEN NO_DATA_FOUND THEN + RAISE V_EXC_INVALID_CONSUMER_KEY; + END; + + DELETE FROM OAUTH_CONSUMER_TOKEN + WHERE OCT_OCR_ID_REF = V_OCR_ID + AND OCT_USA_ID_REF = P_USER_ID + AND UPPER(OCT_TOKEN_TYPE) = UPPER(P_TOKEN_TYPE) + AND OCT_NAME = P_NAME; + + IF P_TOKEN_INTERVAL_IN_SEC IS NOT NULL THEN + V_TOKEN_TTL := SYSDATE + (P_TOKEN_INTERVAL_IN_SEC/(24*60*60)); + ELSE + V_TOKEN_TTL := TO_DATE('9999.12.31', 'yyyy.mm.dd'); + END IF; + + INSERT INTO OAUTH_CONSUMER_TOKEN + (OCT_ID, OCT_OCR_ID_REF,OCT_USA_ID_REF, OCT_NAME, OCT_TOKEN, OCT_TOKEN_SECRET, OCT_TOKEN_TYPE, OCT_TIMESTAMP, OCT_TOKEN_TTL) + VALUES + (SEQ_OCT_ID.NEXTVAL, V_OCR_ID, P_USER_ID, P_NAME, P_TOKEN, P_TOKEN_SECRET, UPPER(P_TOKEN_TYPE), SYSDATE, V_TOKEN_TTL); + +EXCEPTION +WHEN V_EXC_INVALID_CONSUMER_KEY THEN +P_RESULT := 2; -- INVALID_CONSUMER_KEY +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_AUTH_CONSUMER_REQ_TOKEN.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_AUTH_CONSUMER_REQ_TOKEN.prc new file mode 100644 index 00000000..c3693491 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_AUTH_CONSUMER_REQ_TOKEN.prc @@ -0,0 +1,32 @@ +CREATE OR REPLACE PROCEDURE SP_AUTH_CONSUMER_REQ_TOKEN +( +P_USER_ID IN NUMBER, +P_REFERRER_HOST IN VARCHAR2, +P_VERIFIER IN VARCHAR2, +P_TOKEN IN VARCHAR2, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Fetch the consumer request token, by request token. +BEGIN +P_RESULT := 0; + + +UPDATE OAUTH_SERVER_TOKEN + SET OST_AUTHORIZED = 1, + OST_USA_ID_REF = P_USER_ID, + OST_TIMESTAMP = SYSDATE, + OST_REFERRER_HOST = P_REFERRER_HOST, + OST_VERIFIER = P_VERIFIER + WHERE OST_TOKEN = P_TOKEN + AND OST_TOKEN_TYPE = 'REQUEST'; + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_CHECK_SERVER_NONCE.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_CHECK_SERVER_NONCE.prc new file mode 100644 index 00000000..444a70fc --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_CHECK_SERVER_NONCE.prc @@ -0,0 +1,81 @@ +CREATE OR REPLACE PROCEDURE SP_CHECK_SERVER_NONCE +( +P_CONSUMER_KEY IN VARCHAR2, +P_TOKEN IN VARCHAR2, +P_TIMESTAMP IN NUMBER, +P_MAX_TIMESTAMP_SKEW IN NUMBER, +P_NONCE IN VARCHAR2, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Check an nonce/timestamp combination. Clears any nonce combinations + -- that are older than the one received. +V_IS_MAX NUMBER; +V_MAX_TIMESTAMP NUMBER; +V_IS_DUPLICATE_TIMESTAMP NUMBER; + +V_EXC_INVALID_TIMESTAMP EXCEPTION; +V_EXC_DUPLICATE_TIMESTAMP EXCEPTION; +BEGIN + + P_RESULT := 0; + + BEGIN + SELECT MAX(OSN_TIMESTAMP), + CASE + WHEN MAX(OSN_TIMESTAMP) > (P_TIMESTAMP + P_MAX_TIMESTAMP_SKEW) THEN 1 ELSE 0 + END "IS_MAX" INTO V_MAX_TIMESTAMP, V_IS_MAX + FROM OAUTH_SERVER_NONCE + WHERE OSN_CONSUMER_KEY = P_CONSUMER_KEY + AND OSN_TOKEN = P_TOKEN; + + IF V_IS_MAX = 1 THEN + RAISE V_EXC_INVALID_TIMESTAMP; + END IF; + + EXCEPTION + WHEN NO_DATA_FOUND THEN + NULL; + END; + + BEGIN + SELECT 1 INTO V_IS_DUPLICATE_TIMESTAMP FROM DUAL WHERE EXISTS + (SELECT OSN_ID FROM OAUTH_SERVER_NONCE + WHERE OSN_CONSUMER_KEY = P_CONSUMER_KEY + AND OSN_TOKEN = P_TOKEN + AND OSN_TIMESTAMP = P_TIMESTAMP + AND OSN_NONCE = P_NONCE); + + IF V_IS_DUPLICATE_TIMESTAMP = 1 THEN + RAISE V_EXC_DUPLICATE_TIMESTAMP; + END IF; + EXCEPTION + WHEN NO_DATA_FOUND THEN + NULL; + END; + + -- Insert the new combination + INSERT INTO OAUTH_SERVER_NONCE + (OSN_ID, OSN_CONSUMER_KEY, OSN_TOKEN, OSN_TIMESTAMP, OSN_NONCE) + VALUES + (SEQ_OSN_ID.NEXTVAL, P_CONSUMER_KEY, P_TOKEN, P_TIMESTAMP, P_NONCE); + + -- Clean up all timestamps older than the one we just received + DELETE FROM OAUTH_SERVER_NONCE + WHERE OSN_CONSUMER_KEY = P_CONSUMER_KEY + AND OSN_TOKEN = P_TOKEN + AND OSN_TIMESTAMP < (P_TIMESTAMP - P_MAX_TIMESTAMP_SKEW); + + +EXCEPTION +WHEN V_EXC_INVALID_TIMESTAMP THEN +P_RESULT := 2; -- INVALID_TIMESTAMP +WHEN V_EXC_DUPLICATE_TIMESTAMP THEN +P_RESULT := 3; -- DUPLICATE_TIMESTAMP +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_CONSUMER_STATIC_SAVE.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_CONSUMER_STATIC_SAVE.prc new file mode 100644 index 00000000..047c77bf --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_CONSUMER_STATIC_SAVE.prc @@ -0,0 +1,28 @@ +CREATE OR REPLACE PROCEDURE SP_CONSUMER_STATIC_SAVE +( +P_OSR_CONSUMER_KEY IN VARCHAR2, +P_RESULT OUT NUMBER +) +AS + +-- PROCEDURE TO Fetch the static consumer key for this provider. +BEGIN +P_RESULT := 0; + + + INSERT INTO OAUTH_SERVER_REGISTRY + (OSR_ID, OSR_ENABLED, OSR_STATUS, OSR_USA_ID_REF, OSR_CONSUMER_KEY, OSR_CONSUMER_SECRET, OSR_REQUESTER_NAME, OSR_REQUESTER_EMAIL, OSR_CALLBACK_URI, + OSR_APPLICATION_URI, OSR_APPLICATION_TITLE, OSR_APPLICATION_DESCR, OSR_APPLICATION_NOTES, + OSR_APPLICATION_TYPE, OSR_APPLICATION_COMMERCIAL, OSR_TIMESTAMP,OSR_ISSUE_DATE) + VALUES + (SEQ_OSR_ID.NEXTVAL, 1, 'ACTIVE', NULL, P_OSR_CONSUMER_KEY, '\', '\', '\', '\', '\', + 'STATIC SHARED CONSUMER KEY', '\', 'STATIC SHARED CONSUMER KEY', '\', 0, SYSDATE, SYSDATE); + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_COUNT_CONSUMER_ACCESS_TOKEN.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_COUNT_CONSUMER_ACCESS_TOKEN.prc new file mode 100644 index 00000000..f7099b97 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_COUNT_CONSUMER_ACCESS_TOKEN.prc @@ -0,0 +1,27 @@ +CREATE OR REPLACE PROCEDURE SP_COUNT_CONSUMER_ACCESS_TOKEN +( +P_CONSUMER_KEY IN VARCHAR2, +P_COUNT OUT NUMBER, +P_RESULT OUT NUMBER +) +AS +-- PROCEDURE TO Count the consumer access tokens for the given consumer. +BEGIN +P_RESULT := 0; + +SELECT COUNT(OST_ID) INTO P_COUNT + FROM OAUTH_SERVER_TOKEN + JOIN OAUTH_SERVER_REGISTRY + ON OST_OSR_ID_REF = OSR_ID + WHERE OST_TOKEN_TYPE = 'ACCESS' + AND OSR_CONSUMER_KEY = P_CONSUMER_KEY + AND OST_TOKEN_TTL >= SYSDATE; + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_COUNT_SERVICE_TOKENS.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_COUNT_SERVICE_TOKENS.prc new file mode 100644 index 00000000..c73b3668 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_COUNT_SERVICE_TOKENS.prc @@ -0,0 +1,28 @@ +CREATE OR REPLACE PROCEDURE SP_COUNT_SERVICE_TOKENS +( +P_CONSUMER_KEY IN VARCHAR2, +P_COUNT OUT NUMBER, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Count how many tokens we have for the given server +BEGIN +P_RESULT := 0; + + SELECT COUNT(OCT_ID) INTO P_COUNT + FROM OAUTH_CONSUMER_TOKEN + JOIN OAUTH_CONSUMER_REGISTRY + ON OCT_OCR_ID_REF = OCR_ID + WHERE OCT_TOKEN_TYPE = 'ACCESS' + AND OCR_CONSUMER_KEY = P_CONSUMER_KEY + AND OCT_TOKEN_TTL >= SYSDATE; + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_DELETE_CONSUMER.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_DELETE_CONSUMER.prc new file mode 100644 index 00000000..3f18562e --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_DELETE_CONSUMER.prc @@ -0,0 +1,35 @@ +CREATE OR REPLACE PROCEDURE SP_DELETE_CONSUMER +( +P_CONSUMER_KEY IN VARCHAR2, +P_USER_ID IN NUMBER, +P_USER_IS_ADMIN IN NUMBER, --0:NO; 1:YES +P_RESULT OUT NUMBER +) +AS + + -- Delete a consumer key. This removes access to our site for all applications using this key. + +BEGIN +P_RESULT := 0; + +IF P_USER_IS_ADMIN = 1 THEN + + DELETE FROM OAUTH_SERVER_REGISTRY + WHERE OSR_CONSUMER_KEY = P_CONSUMER_KEY + AND (OSR_USA_ID_REF = P_USER_ID OR OSR_USA_ID_REF IS NULL); + +ELSIF P_USER_IS_ADMIN = 0 THEN + + DELETE FROM OAUTH_SERVER_REGISTRY + WHERE OSR_CONSUMER_KEY = P_CONSUMER_KEY + AND OSR_USA_ID_REF = P_USER_ID; + +END IF; + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_DELETE_SERVER.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_DELETE_SERVER.prc new file mode 100644 index 00000000..ba259dee --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_DELETE_SERVER.prc @@ -0,0 +1,35 @@ +CREATE OR REPLACE PROCEDURE SP_DELETE_SERVER +( +P_CONSUMER_KEY IN VARCHAR2, +P_USER_ID IN NUMBER, +P_USER_IS_ADMIN IN NUMBER, --0:NO; 1:YES +P_RESULT OUT NUMBER +) +AS + + -- Delete a server key. This removes access to that site. + +BEGIN +P_RESULT := 0; + +IF P_USER_IS_ADMIN = 1 THEN + + DELETE FROM OAUTH_CONSUMER_REGISTRY + WHERE OCR_CONSUMER_KEY = P_CONSUMER_KEY + AND (OCR_USA_ID_REF = P_USER_ID OR OCR_USA_ID_REF IS NULL); + +ELSIF P_USER_IS_ADMIN = 0 THEN + + DELETE FROM OAUTH_CONSUMER_REGISTRY + WHERE OCR_CONSUMER_KEY = P_CONSUMER_KEY + AND OCR_USA_ID_REF = P_USER_ID; + +END IF; + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_DELETE_SERVER_TOKEN.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_DELETE_SERVER_TOKEN.prc new file mode 100644 index 00000000..de9d4500 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_DELETE_SERVER_TOKEN.prc @@ -0,0 +1,37 @@ +CREATE OR REPLACE PROCEDURE SP_DELETE_SERVER_TOKEN +( +P_CONSUMER_KEY IN VARCHAR2, +P_USER_ID IN NUMBER, +P_TOKEN IN VARCHAR2, +P_USER_IS_ADMIN IN NUMBER, --0:NO; 1:YES +P_RESULT OUT NUMBER +) +AS + + -- Delete a token we obtained from a server. + +BEGIN +P_RESULT := 0; + +IF P_USER_IS_ADMIN = 1 THEN + + DELETE FROM OAUTH_CONSUMER_TOKEN + WHERE OCT_TOKEN = P_TOKEN + AND OCT_OCR_ID_REF IN (SELECT OCR_ID FROM OAUTH_CONSUMER_REGISTRY WHERE OCR_CONSUMER_KEY = P_CONSUMER_KEY); + +ELSIF P_USER_IS_ADMIN = 0 THEN + + DELETE FROM OAUTH_CONSUMER_TOKEN + WHERE OCT_TOKEN = P_TOKEN + AND OCT_USA_ID_REF = P_USER_ID + AND OCT_OCR_ID_REF IN (SELECT OCR_ID FROM OAUTH_CONSUMER_REGISTRY WHERE OCR_CONSUMER_KEY = P_CONSUMER_KEY); + +END IF; + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_DEL_CONSUMER_ACCESS_TOKEN.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_DEL_CONSUMER_ACCESS_TOKEN.prc new file mode 100644 index 00000000..4281bdb9 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_DEL_CONSUMER_ACCESS_TOKEN.prc @@ -0,0 +1,33 @@ +CREATE OR REPLACE PROCEDURE SP_DEL_CONSUMER_ACCESS_TOKEN +( +P_USER_ID IN NUMBER, +P_TOKEN IN VARCHAR2, +P_USER_IS_ADMIN IN NUMBER, -- 1:YES; 0:NO +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Delete a consumer access token. + +BEGIN + + P_RESULT := 0; + + IF P_USER_IS_ADMIN = 1 THEN + DELETE FROM OAUTH_SERVER_TOKEN + WHERE OST_TOKEN = P_TOKEN + AND OST_TOKEN_TYPE = 'ACCESS'; + ELSE + DELETE FROM OAUTH_SERVER_TOKEN + WHERE OST_TOKEN = P_TOKEN + AND OST_TOKEN_TYPE = 'ACCESS' + AND OST_USA_ID_REF = P_USER_ID; + END IF; + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_DEL_CONSUMER_REQUEST_TOKEN.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_DEL_CONSUMER_REQUEST_TOKEN.prc new file mode 100644 index 00000000..01678d6b --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_DEL_CONSUMER_REQUEST_TOKEN.prc @@ -0,0 +1,25 @@ +CREATE OR REPLACE PROCEDURE SP_DEL_CONSUMER_REQUEST_TOKEN +( +P_TOKEN IN VARCHAR2, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Delete a consumer token. The token must be a request or authorized token. + +BEGIN + + P_RESULT := 0; + + DELETE FROM OAUTH_SERVER_TOKEN + WHERE OST_TOKEN = P_TOKEN + AND OST_TOKEN_TYPE = 'REQUEST'; + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_EXCH_CONS_REQ_FOR_ACC_TOKEN.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_EXCH_CONS_REQ_FOR_ACC_TOKEN.prc new file mode 100644 index 00000000..66a53ed8 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_EXCH_CONS_REQ_FOR_ACC_TOKEN.prc @@ -0,0 +1,96 @@ +CREATE OR REPLACE PROCEDURE SP_EXCH_CONS_REQ_FOR_ACC_TOKEN +( +P_TOKEN_TTL IN NUMBER, -- IN SECOND +P_NEW_TOKEN IN VARCHAR2, +P_TOKEN IN VARCHAR2, +P_TOKEN_SECRET IN VARCHAR2, +P_VERIFIER IN VARCHAR2, +P_OUT_TOKEN_TTL OUT NUMBER, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Add an unautorized request token to our server. + +V_TOKEN_EXIST NUMBER; + + +V_EXC_NO_TOKEN_EXIST EXCEPTION; +BEGIN + + P_RESULT := 0; + + IF P_VERIFIER IS NOT NULL THEN + + BEGIN + SELECT 1 INTO V_TOKEN_EXIST FROM DUAL WHERE EXISTS + (SELECT OST_TOKEN FROM OAUTH_SERVER_TOKEN + WHERE OST_TOKEN = P_TOKEN + AND OST_TOKEN_TYPE = 'REQUEST' + AND OST_AUTHORIZED = 1 + AND OST_TOKEN_TTL >= SYSDATE + AND OST_VERIFIER = P_VERIFIER); + EXCEPTION + WHEN NO_DATA_FOUND THEN + RAISE V_EXC_NO_TOKEN_EXIST; + END; + + UPDATE OAUTH_SERVER_TOKEN + SET OST_TOKEN = P_NEW_TOKEN, + OST_TOKEN_SECRET = P_TOKEN_SECRET, + OST_TOKEN_TYPE = 'ACCESS', + OST_TIMESTAMP = SYSDATE, + OST_TOKEN_TTL = NVL(SYSDATE + (P_TOKEN_TTL/(24*60*60)), TO_DATE('9999.12.31', 'yyyy.mm.dd')) + WHERE OST_TOKEN = P_TOKEN + AND OST_TOKEN_TYPE = 'REQUEST' + AND OST_AUTHORIZED = 1 + AND OST_TOKEN_TTL >= SYSDATE + AND OST_VERIFIER = P_VERIFIER; + + ELSE + BEGIN + SELECT 1 INTO V_TOKEN_EXIST FROM DUAL WHERE EXISTS + (SELECT OST_TOKEN FROM OAUTH_SERVER_TOKEN + WHERE OST_TOKEN = P_TOKEN + AND OST_TOKEN_TYPE = 'REQUEST' + AND OST_AUTHORIZED = 1 + AND OST_TOKEN_TTL >= SYSDATE); + EXCEPTION + WHEN NO_DATA_FOUND THEN + RAISE V_EXC_NO_TOKEN_EXIST; + END; + + UPDATE OAUTH_SERVER_TOKEN + SET OST_TOKEN = P_NEW_TOKEN, + OST_TOKEN_SECRET = P_TOKEN_SECRET, + OST_TOKEN_TYPE = 'ACCESS', + OST_TIMESTAMP = SYSDATE, + OST_TOKEN_TTL = NVL(SYSDATE + (P_TOKEN_TTL/(24*60*60)), TO_DATE('9999.12.31', 'yyyy.mm.dd')) + WHERE OST_TOKEN = P_TOKEN + AND OST_TOKEN_TYPE = 'REQUEST' + AND OST_AUTHORIZED = 1 + AND OST_TOKEN_TTL >= SYSDATE; + + + END IF; + + SELECT CASE + WHEN OST_TOKEN_TTL >= TO_DATE('9999.12.31', 'yyyy.mm.dd') THEN NULL ELSE (OST_TOKEN_TTL - SYSDATE)*24*60*60 + END "TOKEN_TTL" INTO P_OUT_TOKEN_TTL + FROM OAUTH_SERVER_TOKEN + WHERE OST_TOKEN = P_NEW_TOKEN; + + + + + + +EXCEPTION +WHEN V_EXC_NO_TOKEN_EXIST THEN +P_RESULT := 2; -- NO_TOKEN_EXIST +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_CONSUMER.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_CONSUMER.prc new file mode 100644 index 00000000..4225ff21 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_CONSUMER.prc @@ -0,0 +1,41 @@ +CREATE OR REPLACE PROCEDURE SP_GET_CONSUMER +( +P_CONSUMER_KEY IN STRING, +P_ROWS OUT TYPES.REF_CURSOR, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Fetch a consumer of this server, by consumer_key. +BEGIN +P_RESULT := 0; + +OPEN P_ROWS FOR + SELECT OSR_ID "osr_id", + OSR_USA_ID_REF "osr_usa_id_ref", + OSR_CONSUMER_KEY "osr_consumer_key", + OSR_CONSUMER_SECRET "osr_consumer_secret", + OSR_ENABLED "osr_enabled", + OSR_STATUS "osr_status", + OSR_REQUESTER_NAME "osr_requester_name", + OSR_REQUESTER_EMAIL "osr_requester_email", + OSR_CALLBACK_URI "osr_callback_uri", + OSR_APPLICATION_URI "osr_application_uri", + OSR_APPLICATION_TITLE "osr_application_title", + OSR_APPLICATION_DESCR "osr_application_descr", + OSR_APPLICATION_NOTES "osr_application_notes", + OSR_APPLICATION_TYPE "osr_application_type", + OSR_APPLICATION_COMMERCIAL "osr_application_commercial", + OSR_ISSUE_DATE "osr_issue_date", + OSR_TIMESTAMP "osr_timestamp" + FROM OAUTH_SERVER_REGISTRY + WHERE OSR_CONSUMER_KEY = P_CONSUMER_KEY; + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_CONSUMER_ACCESS_TOKEN.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_CONSUMER_ACCESS_TOKEN.prc new file mode 100644 index 00000000..0db2ea9c --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_CONSUMER_ACCESS_TOKEN.prc @@ -0,0 +1,43 @@ +CREATE OR REPLACE PROCEDURE SP_GET_CONSUMER_ACCESS_TOKEN +( +P_USER_ID IN NUMBER, +P_TOKEN IN VARCHAR2, +P_ROWS OUT TYPES.REF_CURSOR, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Fetch the consumer access token, by access token. + +BEGIN + + P_RESULT := 0; + + + OPEN P_ROWS FOR + SELECT OST_TOKEN "token", + OST_TOKEN_SECRET "token_secret", + OST_REFERRER_HOST "token_referrer_host", + OSR_CONSUMER_KEY "consumer_key", + OSR_CONSUMER_SECRET "consumer_secret", + OSR_APPLICATION_URI "application_uri", + OSR_APPLICATION_TITLE "application_title", + OSR_APPLICATION_DESCR "application_descr", + OSR_CALLBACK_URI "callback_uri" + FROM OAUTH_SERVER_TOKEN + JOIN OAUTH_SERVER_REGISTRY + ON OST_OSR_ID_REF = OSR_ID + WHERE OST_TOKEN_TYPE = 'ACCESS' + AND OST_TOKEN = P_TOKEN + AND OST_USA_ID_REF = P_USER_ID + AND OST_TOKEN_TTL >= SYSDATE; + + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_CONSUMER_REQUEST_TOKEN.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_CONSUMER_REQUEST_TOKEN.prc new file mode 100644 index 00000000..6d3b5906 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_CONSUMER_REQUEST_TOKEN.prc @@ -0,0 +1,41 @@ +CREATE OR REPLACE PROCEDURE SP_GET_CONSUMER_REQUEST_TOKEN +( +P_TOKEN IN VARCHAR2, +P_ROWS OUT TYPES.REF_CURSOR, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Fetch the consumer request token, by request token. +BEGIN +P_RESULT := 0; + +OPEN P_ROWS FOR + +SELECT OST_TOKEN "token", + OST_TOKEN_SECRET "token_secret", + OSR_CONSUMER_KEY "consumer_key", + OSR_CONSUMER_SECRET "consumer_secret", + OST_TOKEN_TYPE "token_type", + OST_CALLBACK_URL "callback_url", + OSR_APPLICATION_TITLE "application_title", + OSR_APPLICATION_DESCR "application_descr", + OSR_APPLICATION_URI "application_uri" + FROM OAUTH_SERVER_TOKEN + JOIN OAUTH_SERVER_REGISTRY + ON OST_OSR_ID_REF = OSR_ID + WHERE OST_TOKEN_TYPE = 'REQUEST' + AND OST_TOKEN = P_TOKEN + AND OST_TOKEN_TTL >= SYSDATE; + + + + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_CONSUMER_STATIC_SELECT.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_CONSUMER_STATIC_SELECT.prc new file mode 100644 index 00000000..1126ef6a --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_CONSUMER_STATIC_SELECT.prc @@ -0,0 +1,25 @@ +CREATE OR REPLACE PROCEDURE SP_GET_CONSUMER_STATIC_SELECT +( +P_OSR_CONSUMER_KEY OUT VARCHAR2, +P_RESULT OUT NUMBER +) +AS + +-- PROCEDURE TO Fetch the static consumer key for this provider. +BEGIN +P_RESULT := 0; + + + SELECT OSR_CONSUMER_KEY INTO P_OSR_CONSUMER_KEY + FROM OAUTH_SERVER_REGISTRY + WHERE OSR_CONSUMER_KEY LIKE 'sc-%%' + AND OSR_USA_ID_REF IS NULL; + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SECRETS_FOR_SIGNATURE.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SECRETS_FOR_SIGNATURE.prc new file mode 100644 index 00000000..2af78475 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SECRETS_FOR_SIGNATURE.prc @@ -0,0 +1,43 @@ +CREATE OR REPLACE PROCEDURE SP_GET_SECRETS_FOR_SIGNATURE +( +P_HOST IN VARCHAR2, +P_PATH IN VARCHAR2, +P_USER_ID IN NUMBER, +P_NAME IN VARCHAR2, +P_ROWS OUT TYPES.REF_CURSOR, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Find the server details for signing a request, always looks for an access token. + -- The returned credentials depend on which local user is making the request. +BEGIN +P_RESULT := 0; + + OPEN P_ROWS FOR + SELECT * FROM ( + SELECT OCR_CONSUMER_KEY "consumer_key", + OCR_CONSUMER_SECRET "consumer_secret", + OCT_TOKEN "token", + OCT_TOKEN_SECRET "token_secret", + OCR_SIGNATURE_METHODS "signature_methods" + FROM OAUTH_CONSUMER_REGISTRY + JOIN OAUTH_CONSUMER_TOKEN ON OCT_OCR_ID_REF = OCR_ID + WHERE OCR_SERVER_URI_HOST = P_HOST + AND OCR_SERVER_URI_PATH = SUBSTR(P_PATH, 1, LENGTH(OCR_SERVER_URI_PATH)) + AND (OCR_USA_ID_REF = P_USER_ID OR OCR_USA_ID_REF IS NULL) + AND OCT_USA_ID_REF = P_USER_ID + AND OCT_TOKEN_TYPE = 'ACCESS' + AND OCT_NAME = P_NAME + AND OCT_TOKEN_TTL >= SYSDATE + ORDER BY OCR_USA_ID_REF DESC, OCR_CONSUMER_SECRET DESC, LENGTH(OCR_SERVER_URI_PATH) DESC + ) WHERE ROWNUM<=1; + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SECRETS_FOR_VERIFY.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SECRETS_FOR_VERIFY.prc new file mode 100644 index 00000000..4fbb435c --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SECRETS_FOR_VERIFY.prc @@ -0,0 +1,52 @@ +CREATE OR REPLACE PROCEDURE SP_GET_SECRETS_FOR_VERIFY +( +P_CONSUMER_KEY IN VARCHAR2, +P_TOKEN IN VARCHAR2, +P_TOKEN_TYPE IN VARCHAR2, +P_ROWS OUT TYPES.REF_CURSOR, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE to Find stored credentials for the consumer key and token. Used by an OAuth server + -- when verifying an OAuth request. + +BEGIN +P_RESULT := 0; + +IF P_TOKEN_TYPE IS NULL THEN + OPEN P_ROWS FOR + SELECT OSR.OSR_ID "osr_id", + OSR.OSR_CONSUMER_KEY "consumer_key", + OSR.OSR_CONSUMER_SECRET "consumer_secret" + FROM OAUTH_SERVER_REGISTRY OSR + WHERE OSR.OSR_CONSUMER_KEY = P_CONSUMER_KEY + AND OSR.OSR_ENABLED = 1; +ELSE + OPEN P_ROWS FOR + SELECT OSR.OSR_ID "osr_id", + OST.OST_ID "ost_id", + OST.OST_USA_ID_REF "user_id", + OSR.OSR_CONSUMER_KEY "consumer_key", + OSR.OSR_CONSUMER_SECRET "consumer_secret", + OST.OST_TOKEN "token", + OST.OST_TOKEN_SECRET "token_secret" + FROM OAUTH_SERVER_REGISTRY OSR, OAUTH_SERVER_TOKEN OST + WHERE OST.OST_OSR_ID_REF = OSR.OSR_ID + AND upper(OST.OST_TOKEN_TYPE) = upper(P_TOKEN_TYPE) + AND OSR.OSR_CONSUMER_KEY = P_CONSUMER_KEY + AND OST.OST_TOKEN = P_TOKEN + AND OSR.OSR_ENABLED = 1 + AND OST.OST_TOKEN_TTL >= SYSDATE; + +END IF; + + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SERVER.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SERVER.prc new file mode 100644 index 00000000..af7d2755 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SERVER.prc @@ -0,0 +1,35 @@ +CREATE OR REPLACE PROCEDURE SP_GET_SERVER +( +P_CONSUMER_KEY IN VARCHAR2, +P_USER_ID IN NUMBER, +P_ROWS OUT TYPES.REF_CURSOR, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Get a server from the consumer registry using the consumer key +BEGIN +P_RESULT := 0; + +OPEN P_ROWS FOR + SELECT OCR_ID "id", + OCR_USA_ID_REF "user_id", + OCR_CONSUMER_KEY "consumer_key", + OCR_CONSUMER_SECRET "consumer_secret", + OCR_SIGNATURE_METHODS "signature_methods", + OCR_SERVER_URI "server_uri", + OCR_REQUEST_TOKEN_URI "request_token_uri", + OCR_AUTHORIZE_URI "authorize_uri", + OCR_ACCESS_TOKEN_URI "access_token_uri" + FROM OAUTH_CONSUMER_REGISTRY + WHERE OCR_CONSUMER_KEY = P_CONSUMER_KEY + AND (OCR_USA_ID_REF = P_USER_ID OR OCR_USA_ID_REF IS NULL); + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SERVER_FOR_URI.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SERVER_FOR_URI.prc new file mode 100644 index 00000000..d838b511 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SERVER_FOR_URI.prc @@ -0,0 +1,41 @@ +CREATE OR REPLACE PROCEDURE SP_GET_SERVER_FOR_URI +( +P_HOST IN VARCHAR2, +P_PATH IN VARCHAR2, +P_USER_ID IN NUMBER, +P_ROWS OUT TYPES.REF_CURSOR, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Find the server details that might be used for a request +BEGIN +P_RESULT := 0; + +OPEN P_ROWS FOR +SELECT * FROM ( + SELECT OCR_ID "id", + OCR_USA_ID_REF "user_id", + OCR_CONSUMER_KEY "consumer_key", + OCR_CONSUMER_SECRET "consumer_secret", + OCR_SIGNATURE_METHODS "signature_methods", + OCR_SERVER_URI "server_uri", + OCR_REQUEST_TOKEN_URI "request_token_uri", + OCR_AUTHORIZE_URI "authorize_uri", + OCR_ACCESS_TOKEN_URI "access_token_uri" + FROM OAUTH_CONSUMER_REGISTRY + WHERE OCR_SERVER_URI_HOST = P_HOST + AND OCR_SERVER_URI_PATH = SUBSTR(P_PATH, 1, LENGTH(OCR_SERVER_URI_PATH)) + AND (OCR_USA_ID_REF = P_USER_ID OR OCR_USA_ID_REF IS NULL) + ORDER BY ocr_usa_id_ref DESC, OCR_CONSUMER_KEY DESC, LENGTH(ocr_server_uri_path) DESC +) WHERE ROWNUM<=1; + + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SERVER_TOKEN.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SERVER_TOKEN.prc new file mode 100644 index 00000000..fefbe8ac --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SERVER_TOKEN.prc @@ -0,0 +1,45 @@ +CREATE OR REPLACE PROCEDURE SP_GET_SERVER_TOKEN +( +P_CONSUMER_KEY IN VARCHAR2, +P_USER_ID IN NUMBER, +P_TOKEN IN VARCHAR2, +P_ROWS OUT TYPES.REF_CURSOR, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Get a specific server token for the given user +BEGIN +P_RESULT := 0; + +OPEN P_ROWS FOR + SELECT OCR_CONSUMER_KEY "consumer_key", + OCR_CONSUMER_SECRET "consumer_secret", + OCT_TOKEN "token", + OCT_TOKEN_SECRET "token_secret", + OCT_USA_ID_REF "usr_id", + OCR_SIGNATURE_METHODS "signature_methods", + OCR_SERVER_URI "server_uri", + OCR_SERVER_URI_HOST "server_uri_host", + OCR_SERVER_URI_PATH "server_uri_path", + OCR_REQUEST_TOKEN_URI "request_token_uri", + OCR_AUTHORIZE_URI "authorize_uri", + OCR_ACCESS_TOKEN_URI "access_token_uri", + OCT_TIMESTAMP "timestamp" + FROM OAUTH_CONSUMER_REGISTRY + JOIN OAUTH_CONSUMER_TOKEN + ON OCT_OCR_ID_REF = OCR_ID + WHERE OCR_CONSUMER_KEY = P_CONSUMER_KEY + AND OCT_USA_ID_REF = P_USER_ID + AND OCT_TOKEN_TYPE = 'ACCESS' + AND OCT_TOKEN = P_TOKEN + AND OCT_TOKEN_TTL >= SYSDATE; + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SERVER_TOKEN_SECRETS.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SERVER_TOKEN_SECRETS.prc new file mode 100644 index 00000000..95eec885 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_GET_SERVER_TOKEN_SECRETS.prc @@ -0,0 +1,47 @@ +CREATE OR REPLACE PROCEDURE SP_GET_SERVER_TOKEN_SECRETS +( +P_CONSUMER_KEY IN VARCHAR2, +P_TOKEN IN VARCHAR2, +P_TOKEN_TYPE IN VARCHAR2, +P_USER_ID IN NUMBER, +P_ROWS OUT TYPES.REF_CURSOR, +P_RESULT OUT NUMBER +) +AS + + -- Get the token and token secret we obtained from a server. + +BEGIN +P_RESULT := 0; + + + OPEN P_ROWS FOR + SELECT OCR.OCR_CONSUMER_KEY "consumer_key", + OCR.OCR_CONSUMER_SECRET "consumer_secret", + OCT.OCT_TOKEN "token", + OCT.OCT_TOKEN_SECRET "token_secret", + OCT.OCT_NAME "token_name", + OCR.OCR_SIGNATURE_METHODS "signature_methods", + OCR.OCR_SERVER_URI "server_uri", + OCR.OCR_REQUEST_TOKEN_URI "request_token_uri", + OCR.OCR_AUTHORIZE_URI "authorize_uri", + OCR.OCR_ACCESS_TOKEN_URI "access_token_uri", + CASE WHEN OCT.OCT_TOKEN_TTL >= TO_DATE('9999.12.31', 'yyyy.mm.dd') THEN NULL + ELSE OCT.OCT_TOKEN_TTL - SYSDATE + END "token_ttl" + FROM OAUTH_CONSUMER_REGISTRY OCR, OAUTH_CONSUMER_TOKEN OCT + WHERE OCT.OCT_OCR_ID_REF = OCR_ID + AND OCR.OCR_CONSUMER_KEY = P_CONSUMER_KEY + AND upper(OCT.OCT_TOKEN_TYPE) = upper(P_TOKEN_TYPE) + AND OCT.OCT_TOKEN = P_TOKEN + AND OCT.OCT_USA_ID_REF = P_USER_ID + AND OCT.OCT_TOKEN_TTL >= SYSDATE; + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_LIST_CONSUMERS.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_LIST_CONSUMERS.prc new file mode 100644 index 00000000..bb424655 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_LIST_CONSUMERS.prc @@ -0,0 +1,41 @@ +CREATE OR REPLACE PROCEDURE SP_LIST_CONSUMERS +( +P_USER_ID IN NUMBER, +P_ROWS OUT TYPES.REF_CURSOR, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Fetch a list of all consumer keys, secrets etc. + -- Returns the public (user_id is null) and the keys owned by the user + +BEGIN + + P_RESULT := 0; + + OPEN P_ROWS FOR + SELECT OSR_ID "id", + OSR_USA_ID_REF "user_id", + OSR_CONSUMER_KEY "consumer_key", + OSR_CONSUMER_SECRET "consumer_secret", + OSR_ENABLED "enabled", + OSR_STATUS "status", + OSR_ISSUE_DATE "issue_date", + OSR_APPLICATION_URI "application_uri", + OSR_APPLICATION_TITLE "application_title", + OSR_APPLICATION_DESCR "application_descr", + OSR_REQUESTER_NAME "requester_name", + OSR_REQUESTER_EMAIL "requester_email", + OSR_CALLBACK_URI "callback_uri" + FROM OAUTH_SERVER_REGISTRY + WHERE (OSR_USA_ID_REF = P_USER_ID OR OSR_USA_ID_REF IS NULL) + ORDER BY OSR_APPLICATION_TITLE; + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_LIST_CONSUMER_TOKENS.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_LIST_CONSUMER_TOKENS.prc new file mode 100644 index 00000000..dae9c72c --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_LIST_CONSUMER_TOKENS.prc @@ -0,0 +1,43 @@ +CREATE OR REPLACE PROCEDURE SP_LIST_CONSUMER_TOKENS +( +P_USER_ID IN NUMBER, +P_ROWS OUT TYPES.REF_CURSOR, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Fetch a list of all consumer tokens accessing the account of the given user. + +BEGIN + + P_RESULT := 0; + + OPEN P_ROWS FOR + SELECT OSR_CONSUMER_KEY "consumer_key", + OSR_CONSUMER_SECRET "consumer_secret", + OSR_ENABLED "enabled", + OSR_STATUS "status", + OSR_APPLICATION_URI "application_uri", + OSR_APPLICATION_TITLE "application_title", + OSR_APPLICATION_DESCR "application_descr", + OST_TIMESTAMP "timestamp", + OST_TOKEN "token", + OST_TOKEN_SECRET "token_secret", + OST_REFERRER_HOST "token_referrer_host", + OSR_CALLBACK_URI "callback_uri" + FROM OAUTH_SERVER_REGISTRY + JOIN OAUTH_SERVER_TOKEN + ON OST_OSR_ID_REF = OSR_ID + WHERE OST_USA_ID_REF = P_USER_ID + AND OST_TOKEN_TYPE = 'ACCESS' + AND OST_TOKEN_TTL >= SYSDATE + ORDER BY OSR_APPLICATION_TITLE; + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_LIST_LOG.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_LIST_LOG.prc new file mode 100644 index 00000000..275950e4 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_LIST_LOG.prc @@ -0,0 +1,75 @@ +CREATE OR REPLACE PROCEDURE SP_LIST_LOG +( +P_OPTION_FLAG IN NUMBER, -- 0:NULL; 1:OTHERWISE +P_USA_ID IN NUMBER, +P_OSR_CONSUMER_KEY IN VARCHAR2, +P_OCR_CONSUMER_KEY IN VARCHAR2, +P_OST_TOKEN IN VARCHAR2, +P_OCT_TOKEN IN VARCHAR2, +P_ROWS OUT TYPES.REF_CURSOR, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Get a page of entries from the log. Returns the last 100 records + -- matching the options given. + +BEGIN + + P_RESULT := 0; + + IF P_OPTION_FLAG IS NULL OR P_OPTION_FLAG = 0 THEN + OPEN P_ROWS FOR + SELECT * FROM ( + SELECT OLG_ID "olg_id", + OLG_OSR_CONSUMER_KEY "osr_consumer_key", + OLG_OST_TOKEN "ost_token", + OLG_OCR_CONSUMER_KEY "ocr_consumer_key", + OLG_OCT_TOKEN "oct_token", + OLG_USA_ID_REF "user_id", + OLG_RECEIVED "received", + OLG_SENT "sent", + OLG_BASE_STRING "base_string", + OLG_NOTES "notes", + OLG_TIMESTAMP "timestamp", + -- INET_NTOA(OLG_REMOTE_IP) "remote_ip" + OLG_REMOTE_IP "remote_ip" + FROM OAUTH_LOG + WHERE OLG_USA_ID_REF = P_USA_ID + ORDER BY OLG_ID DESC + ) WHERE ROWNUM<=100; + ELSE + OPEN P_ROWS FOR + SELECT * FROM ( + SELECT OLG_ID "olg_id", + OLG_OSR_CONSUMER_KEY "osr_consumer_key", + OLG_OST_TOKEN "ost_token", + OLG_OCR_CONSUMER_KEY "ocr_consumer_key", + OLG_OCT_TOKEN "oct_token", + OLG_USA_ID_REF "user_id", + OLG_RECEIVED "received", + OLG_SENT "sent", + OLG_BASE_STRING "base_string", + OLG_NOTES "notes", + OLG_TIMESTAMP "timestamp", + -- INET_NTOA(OLG_REMOTE_IP) "remote_ip" + OLG_REMOTE_IP "remote_ip" + FROM OAUTH_LOG + WHERE OLG_OSR_CONSUMER_KEY = P_OSR_CONSUMER_KEY + AND OLG_OCR_CONSUMER_KEY = P_OCR_CONSUMER_KEY + AND OLG_OST_TOKEN = P_OST_TOKEN + AND OLG_OCT_TOKEN = P_OCT_TOKEN + AND (OLG_USA_ID_REF IS NULL OR OLG_USA_ID_REF = P_USA_ID) + ORDER BY OLG_ID DESC + ) WHERE ROWNUM<=100; + + END IF; + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_LIST_SERVERS.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_LIST_SERVERS.prc new file mode 100644 index 00000000..51dd39a0 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_LIST_SERVERS.prc @@ -0,0 +1,66 @@ +CREATE OR REPLACE PROCEDURE SP_LIST_SERVERS +( +P_Q IN VARCHAR2, +P_USER_ID IN NUMBER, +P_ROWS OUT TYPES.REF_CURSOR, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Get a list of all consumers from the consumer registry. +BEGIN +P_RESULT := 0; + +IF P_Q IS NOT NULL THEN + + OPEN P_ROWS FOR + SELECT OCR_ID "id", + OCR_USA_ID_REF "user_id", + OCR_CONSUMER_KEY "consumer_key", + OCR_CONSUMER_SECRET "consumer_secret", + OCR_SIGNATURE_METHODS "signature_methods", + OCR_SERVER_URI "server_uri", + OCR_SERVER_URI_HOST "server_uri_host", + OCR_SERVER_URI_PATH "server_uri_path", + OCR_REQUEST_TOKEN_URI "request_token_uri", + OCR_AUTHORIZE_URI "authorize_uri", + OCR_ACCESS_TOKEN_URI "access_token_uri" + FROM OAUTH_CONSUMER_REGISTRY + WHERE ( OCR_CONSUMER_KEY LIKE '%'|| P_Q ||'%' + OR OCR_SERVER_URI LIKE '%'|| P_Q ||'%' + OR OCR_SERVER_URI_HOST LIKE '%'|| P_Q ||'%' + OR OCR_SERVER_URI_PATH LIKE '%'|| P_Q ||'%') + AND (OCR_USA_ID_REF = P_USER_ID OR OCR_USA_ID_REF IS NULL) + ORDER BY OCR_SERVER_URI_HOST, OCR_SERVER_URI_PATH; + +ELSE + + OPEN P_ROWS FOR + SELECT OCR_ID "id", + OCR_USA_ID_REF "user_id", + OCR_CONSUMER_KEY "consumer_key", + OCR_CONSUMER_SECRET "consumer_secret", + OCR_SIGNATURE_METHODS "signature_methods", + OCR_SERVER_URI "server_uri", + OCR_SERVER_URI_HOST "server_uri_host", + OCR_SERVER_URI_PATH "server_uri_path", + OCR_REQUEST_TOKEN_URI "request_token_uri", + OCR_AUTHORIZE_URI "authorize_uri", + OCR_ACCESS_TOKEN_URI "access_token_uri" + FROM OAUTH_CONSUMER_REGISTRY + WHERE OCR_USA_ID_REF = P_USER_ID OR OCR_USA_ID_REF IS NULL + ORDER BY OCR_SERVER_URI_HOST, OCR_SERVER_URI_PATH; + +END IF; + + + + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_LIST_SERVER_TOKENS.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_LIST_SERVER_TOKENS.prc new file mode 100644 index 00000000..baa62c02 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_LIST_SERVER_TOKENS.prc @@ -0,0 +1,45 @@ +CREATE OR REPLACE PROCEDURE SP_LIST_SERVER_TOKENS +( +P_USER_ID IN NUMBER, +P_ROWS OUT TYPES.REF_CURSOR, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Find the server details that might be used for a request +BEGIN +P_RESULT := 0; + +OPEN P_ROWS FOR + SELECT OCR_CONSUMER_KEY "consumer_key", + OCR_CONSUMER_SECRET "consumer_secret", + OCT_ID "token_id", + OCT_TOKEN "token", + OCT_TOKEN_SECRET "token_secret", + OCT_USA_ID_REF "user_id", + OCR_SIGNATURE_METHODS "signature_methods", + OCR_SERVER_URI "server_uri", + OCR_SERVER_URI_HOST "server_uri_host", + OCR_SERVER_URI_PATH "server_uri_path", + OCR_REQUEST_TOKEN_URI "request_token_uri", + OCR_AUTHORIZE_URI "authorize_uri", + OCR_ACCESS_TOKEN_URI "access_token_uri", + OCT_TIMESTAMP "timestamp" + FROM OAUTH_CONSUMER_REGISTRY + JOIN OAUTH_CONSUMER_TOKEN + ON OCT_OCR_ID_REF = OCR_ID + WHERE OCT_USA_ID_REF = P_USER_ID + AND OCT_TOKEN_TYPE = 'ACCESS' + AND OCT_TOKEN_TTL >= SYSDATE + ORDER BY OCR_SERVER_URI_HOST, OCR_SERVER_URI_PATH; + + + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_SET_CONSUMER_ACC_TOKEN_TTL.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_SET_CONSUMER_ACC_TOKEN_TTL.prc new file mode 100644 index 00000000..e5a96c96 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_SET_CONSUMER_ACC_TOKEN_TTL.prc @@ -0,0 +1,28 @@ +CREATE OR REPLACE PROCEDURE SP_SET_CONSUMER_ACC_TOKEN_TTL +( +P_TOKEN IN VARCHAR2, +P_TOKEN_TTL IN NUMBER, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Set the ttl of a consumer access token. This is done when the + -- server receives a valid request with a xoauth_token_ttl parameter in it. + +BEGIN + + P_RESULT := 0; + + UPDATE OAUTH_SERVER_TOKEN + SET OST_TOKEN_TTL = SYSDATE + (P_TOKEN_TTL/(24*60*60)) + WHERE OST_TOKEN = P_TOKEN + AND OST_TOKEN_TYPE = 'ACCESS'; + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_SET_SERVER_TOKEN_TTL.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_SET_SERVER_TOKEN_TTL.prc new file mode 100644 index 00000000..34a99de0 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_SET_SERVER_TOKEN_TTL.prc @@ -0,0 +1,29 @@ +CREATE OR REPLACE PROCEDURE SP_SET_SERVER_TOKEN_TTL +( +P_TOKEN_TTL IN NUMBER, -- IN SECOND +P_CONSUMER_KEY IN VARCHAR2, +P_TOKEN IN VARCHAR2, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Set the ttl of a server access token. + +BEGIN + + P_RESULT := 0; + + +UPDATE OAUTH_CONSUMER_TOKEN +SET OCT_TOKEN_TTL = SYSDATE + (P_TOKEN_TTL/(24*60*60)) -- DATE_ADD(NOW(), INTERVAL %D SECOND) +WHERE OCT_TOKEN = P_TOKEN +AND OCT_OCR_ID_REF IN (SELECT OCR_ID FROM OAUTH_CONSUMER_REGISTRY WHERE OCR_CONSUMER_KEY = P_CONSUMER_KEY); + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_UPDATE_CONSUMER.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_UPDATE_CONSUMER.prc new file mode 100644 index 00000000..a79e64c3 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_UPDATE_CONSUMER.prc @@ -0,0 +1,40 @@ +CREATE OR REPLACE PROCEDURE SP_UPDATE_CONSUMER +( +P_OSR_USA_ID_REF IN NUMBER, +P_OSR_CONSUMER_KEY IN VARCHAR2, +P_OSR_CONSUMER_SECRET IN VARCHAR2, +P_OSR_REQUESTER_NAME IN VARCHAR2, +P_OSR_REQUESTER_EMAIL IN VARCHAR2, +P_OSR_CALLBACK_URI IN VARCHAR2, +P_OSR_APPLICATION_URI IN VARCHAR2, +P_OSR_APPLICATION_TITLE IN VARCHAR2, +P_OSR_APPLICATION_DESCR IN VARCHAR2, +P_OSR_APPLICATION_NOTES IN VARCHAR2, +P_OSR_APPLICATION_TYPE IN VARCHAR2, +P_OSR_APPLICATION_COMMERCIAL IN INTEGER, +P_RESULT OUT NUMBER +) +AS + + -- PROCEDURE TO Insert a new consumer with this server (we will be the server) +BEGIN +P_RESULT := 0; + + + INSERT INTO OAUTH_SERVER_REGISTRY + ( OSR_ID, OSR_ENABLED, OSR_STATUS,OSR_USA_ID_REF,OSR_CONSUMER_KEY, OSR_CONSUMER_SECRET,OSR_REQUESTER_NAME, + OSR_REQUESTER_EMAIL, OSR_CALLBACK_URI, OSR_APPLICATION_URI, OSR_APPLICATION_TITLE, OSR_APPLICATION_DESCR, + OSR_APPLICATION_NOTES, OSR_APPLICATION_TYPE, OSR_APPLICATION_COMMERCIAL, OSR_TIMESTAMP, OSR_ISSUE_DATE) + VALUES + ( SEQ_OSR_ID.NEXTVAL, 1, 'ACTIVE', P_OSR_USA_ID_REF, P_OSR_CONSUMER_KEY, P_OSR_CONSUMER_SECRET,P_OSR_REQUESTER_NAME, + P_OSR_REQUESTER_EMAIL, P_OSR_CALLBACK_URI, P_OSR_APPLICATION_URI, P_OSR_APPLICATION_TITLE, P_OSR_APPLICATION_DESCR, + P_OSR_APPLICATION_NOTES, P_OSR_APPLICATION_TYPE, P_OSR_APPLICATION_COMMERCIAL, SYSDATE, SYSDATE); + + +EXCEPTION +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_UPDATE_SERVER.prc b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_UPDATE_SERVER.prc new file mode 100644 index 00000000..7826eb62 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/OracleDB/3_Procedures/SP_UPDATE_SERVER.prc @@ -0,0 +1,139 @@ +CREATE OR REPLACE PROCEDURE SP_UPDATE_SERVER +( +P_CONSUMER_KEY IN VARCHAR2, +P_USER_ID IN NUMBER, +P_OCR_ID IN NUMBER, +P_USER_IS_ADMIN IN NUMBER, -- 0:NO; 1:YES; +P_OCR_CONSUMER_SECRET IN VARCHAR2, +P_OCR_SERVER_URI IN VARCHAR2, +P_OCR_SERVER_URI_HOST IN VARCHAR2, +P_OCR_SERVER_URI_PATH IN VARCHAR2, +P_OCR_REQUEST_TOKEN_URI IN VARCHAR2, +P_OCR_AUTHORIZE_URI IN VARCHAR2, +P_OCR_ACCESS_TOKEN_URI IN VARCHAR2, +P_OCR_SIGNATURE_METHODS IN VARCHAR2, +P_OCR_USA_ID_REF IN NUMBER, +P_UPDATE_P_OCR_USA_ID_REF_FLAG IN NUMBER, -- 1:TRUE; 0:FALSE +P_RESULT OUT NUMBER +) +AS + + -- Add a request token we obtained from a server. +V_OCR_ID_EXIST NUMBER; +V_OCR_USA_ID_REF NUMBER; + +V_EXC_DUPLICATE_CONSUMER_KEY EXCEPTION; +V_EXC_UNAUTHORISED_USER_ID EXCEPTION; +BEGIN +P_RESULT := 0; + +V_OCR_USA_ID_REF := P_OCR_USA_ID_REF; + + IF P_OCR_ID IS NOT NULL THEN + BEGIN + SELECT 1 INTO V_OCR_ID_EXIST FROM DUAL WHERE EXISTS + (SELECT OCR_ID FROM OAUTH_CONSUMER_REGISTRY + WHERE OCR_CONSUMER_KEY = P_CONSUMER_KEY + AND OCR_ID != P_OCR_ID + AND (OCR_USA_ID_REF = P_USER_ID OR OCR_USA_ID_REF IS NULL)); + + EXCEPTION + WHEN NO_DATA_FOUND THEN + V_OCR_ID_EXIST :=0; + END; + ELSE + BEGIN + SELECT 1 INTO V_OCR_ID_EXIST FROM DUAL WHERE EXISTS + (SELECT OCR_ID FROM OAUTH_CONSUMER_REGISTRY + WHERE OCR_CONSUMER_KEY = P_CONSUMER_KEY + AND (OCR_USA_ID_REF = P_USER_ID OR OCR_USA_ID_REF IS NULL)); + + EXCEPTION + WHEN NO_DATA_FOUND THEN + V_OCR_ID_EXIST :=0; + END; + END IF; + + IF V_OCR_ID_EXIST = 1 THEN + RAISE V_EXC_DUPLICATE_CONSUMER_KEY; + END IF; + + + IF P_OCR_ID IS NOT NULL THEN + IF P_USER_IS_ADMIN != 1 THEN + BEGIN + SELECT OCR_USA_ID_REF INTO V_OCR_USA_ID_REF + FROM OAUTH_CONSUMER_REGISTRY + WHERE OCR_ID = P_OCR_ID; + + EXCEPTION + WHEN NO_DATA_FOUND THEN + NULL; + END; + + IF V_OCR_USA_ID_REF != P_USER_ID THEN + RAISE V_EXC_UNAUTHORISED_USER_ID; + END IF; + END IF; + + IF P_UPDATE_P_OCR_USA_ID_REF_FLAG = 0 THEN + + UPDATE OAUTH_CONSUMER_REGISTRY + SET OCR_CONSUMER_KEY = P_CONSUMER_KEY, + OCR_CONSUMER_SECRET = P_OCR_CONSUMER_SECRET, + OCR_SERVER_URI = P_OCR_SERVER_URI, + OCR_SERVER_URI_HOST = P_OCR_SERVER_URI_HOST, + OCR_SERVER_URI_PATH = P_OCR_SERVER_URI_PATH, + OCR_TIMESTAMP = SYSDATE, + OCR_REQUEST_TOKEN_URI = P_OCR_REQUEST_TOKEN_URI, + OCR_AUTHORIZE_URI = P_OCR_AUTHORIZE_URI, + OCR_ACCESS_TOKEN_URI = P_OCR_ACCESS_TOKEN_URI, + OCR_SIGNATURE_METHODS = P_OCR_SIGNATURE_METHODS + WHERE OCR_ID = P_OCR_ID; + + ELSIF P_UPDATE_P_OCR_USA_ID_REF_FLAG = 1 THEN + UPDATE OAUTH_CONSUMER_REGISTRY + SET OCR_CONSUMER_KEY = P_CONSUMER_KEY, + OCR_CONSUMER_SECRET = P_OCR_CONSUMER_SECRET, + OCR_SERVER_URI = P_OCR_SERVER_URI, + OCR_SERVER_URI_HOST = P_OCR_SERVER_URI_HOST, + OCR_SERVER_URI_PATH = P_OCR_SERVER_URI_PATH, + OCR_TIMESTAMP = SYSDATE, + OCR_REQUEST_TOKEN_URI = P_OCR_REQUEST_TOKEN_URI, + OCR_AUTHORIZE_URI = P_OCR_AUTHORIZE_URI, + OCR_ACCESS_TOKEN_URI = P_OCR_ACCESS_TOKEN_URI, + OCR_SIGNATURE_METHODS = P_OCR_SIGNATURE_METHODS, + OCR_USA_ID_REF = P_OCR_USA_ID_REF + WHERE OCR_ID = P_OCR_ID; + + END IF; + + ELSE + IF P_UPDATE_P_OCR_USA_ID_REF_FLAG = 0 THEN + V_OCR_USA_ID_REF := P_USER_ID; + END IF; + + INSERT INTO OAUTH_CONSUMER_REGISTRY + (OCR_ID, OCR_CONSUMER_KEY ,OCR_CONSUMER_SECRET, OCR_SERVER_URI, OCR_SERVER_URI_HOST, OCR_SERVER_URI_PATH, + OCR_TIMESTAMP, OCR_REQUEST_TOKEN_URI, OCR_AUTHORIZE_URI, OCR_ACCESS_TOKEN_URI, OCR_SIGNATURE_METHODS, + OCR_USA_ID_REF) + VALUES + (SEQ_OCR_ID.NEXTVAL, P_CONSUMER_KEY, P_OCR_CONSUMER_SECRET, P_OCR_SERVER_URI, P_OCR_SERVER_URI_HOST, P_OCR_SERVER_URI_PATH, + SYSDATE, P_OCR_REQUEST_TOKEN_URI, P_OCR_AUTHORIZE_URI, P_OCR_ACCESS_TOKEN_URI, P_OCR_SIGNATURE_METHODS, + V_OCR_USA_ID_REF); + + END IF; + + +EXCEPTION +WHEN V_EXC_DUPLICATE_CONSUMER_KEY THEN +P_RESULT := 2; -- DUPLICATE_CONSUMER_KEY +WHEN V_EXC_UNAUTHORISED_USER_ID THEN +P_RESULT := 3; -- UNAUTHORISED_USER_ID + +WHEN OTHERS THEN +-- CALL THE FUNCTION TO LOG ERRORS +ROLLBACK; +P_RESULT := 1; -- ERROR +END; +/ diff --git a/includes/oauth-php/library/store/oracle/install.php b/includes/oauth-php/library/store/oracle/install.php new file mode 100644 index 00000000..5a80f040 --- /dev/null +++ b/includes/oauth-php/library/store/oracle/install.php @@ -0,0 +1,28 @@ + \ No newline at end of file diff --git a/includes/oauth-php/library/store/postgresql/pgsql.sql b/includes/oauth-php/library/store/postgresql/pgsql.sql new file mode 100644 index 00000000..8f0e4d3e --- /dev/null +++ b/includes/oauth-php/library/store/postgresql/pgsql.sql @@ -0,0 +1,166 @@ +# +# Log table to hold all OAuth request when you enabled logging +# + +CREATE TABLE oauth_log ( + olg_id serial primary key, + olg_osr_consumer_key varchar(64), + olg_ost_token varchar(64), + olg_ocr_consumer_key varchar(64), + olg_oct_token varchar(64), + olg_usa_id_ref text, + olg_received text not null, + olg_sent text not null, + olg_base_string text not null, + olg_notes text not null, + olg_timestamp timestamp not null default current_timestamp, + olg_remote_ip inet not null +); + +COMMENT ON TABLE oauth_log IS 'Log table to hold all OAuth request when you enabled logging'; + + +# +# /////////////////// CONSUMER SIDE /////////////////// +# + +# This is a registry of all consumer codes we got from other servers +# The consumer_key/secret is obtained from the server +# We also register the server uri, so that we can find the consumer key and secret +# for a certain server. From that server we can check if we have a token for a +# particular user. + +CREATE TABLE oauth_consumer_registry ( + ocr_id serial primary key, + ocr_usa_id_ref text, + ocr_consumer_key varchar(128) not null, + ocr_consumer_secret varchar(128) not null, + ocr_signature_methods varchar(255) not null default 'HMAC-SHA1,PLAINTEXT', + ocr_server_uri varchar(255) not null, + ocr_server_uri_host varchar(128) not null, + ocr_server_uri_path varchar(128) not null, + + ocr_request_token_uri varchar(255) not null, + ocr_authorize_uri varchar(255) not null, + ocr_access_token_uri varchar(255) not null, + ocr_timestamp timestamp not null default current_timestamp, + + unique (ocr_consumer_key, ocr_usa_id_ref, ocr_server_uri) +); + +COMMENT ON TABLE oauth_consumer_registry IS 'This is a registry of all consumer codes we got from other servers'; + +# Table used to sign requests for sending to a server by the consumer +# The key is defined for a particular user. Only one single named +# key is allowed per user/server combination + +-- Create enum type token_type +CREATE TYPE consumer_token_type AS ENUM ( + 'request', + 'authorized', + 'access' +); + +CREATE TABLE oauth_consumer_token ( + oct_id serial primary key, + oct_ocr_id_ref integer not null, + oct_usa_id_ref text not null, + oct_name varchar(64) not null default '', + oct_token varchar(64) not null, + oct_token_secret varchar(64) not null, + oct_token_type consumer_token_type, + oct_token_ttl timestamp not null default timestamp '9999-12-31', + oct_timestamp timestamp not null default current_timestamp, + + unique (oct_ocr_id_ref, oct_token), + unique (oct_usa_id_ref, oct_ocr_id_ref, oct_token_type, oct_name), + + foreign key (oct_ocr_id_ref) references oauth_consumer_registry (ocr_id) + on update cascade + on delete cascade +); + + +COMMENT ON TABLE oauth_consumer_token IS 'Table used to sign requests for sending to a server by the consumer'; + +# +# ////////////////// SERVER SIDE ///////////////// +# + +# Table holding consumer key/secret combos an user issued to consumers. +# Used for verification of incoming requests. + +CREATE TABLE oauth_server_registry ( + osr_id serial primary key, + osr_usa_id_ref text, + osr_consumer_key varchar(64) not null, + osr_consumer_secret varchar(64) not null, + osr_enabled boolean not null default true, + osr_status varchar(16) not null, + osr_requester_name varchar(64) not null, + osr_requester_email varchar(64) not null, + osr_callback_uri varchar(255) not null, + osr_application_uri varchar(255) not null, + osr_application_title varchar(80) not null, + osr_application_descr text not null, + osr_application_notes text not null, + osr_application_type varchar(20) not null, + osr_application_commercial boolean not null default false, + osr_issue_date timestamp not null, + osr_timestamp timestamp not null default current_timestamp, + + unique (osr_consumer_key) +); + + +COMMENT ON TABLE oauth_server_registry IS 'Table holding consumer key/secret combos an user issued to consumers'; + +# Nonce used by a certain consumer, every used nonce should be unique, this prevents +# replaying attacks. We need to store all timestamp/nonce combinations for the +# maximum timestamp received. + +CREATE TABLE oauth_server_nonce ( + osn_id serial primary key, + osn_consumer_key varchar(64) not null, + osn_token varchar(64) not null, + osn_timestamp bigint not null, + osn_nonce varchar(80) not null, + + unique (osn_consumer_key, osn_token, osn_timestamp, osn_nonce) +); + + +COMMENT ON TABLE oauth_server_nonce IS 'Nonce used by a certain consumer, every used nonce should be unique, this prevents replaying attacks'; + +# Table used to verify signed requests sent to a server by the consumer +# When the verification is succesful then the associated user id is returned. + +-- Create enum type token_type +CREATE TYPE server_token_type AS ENUM ( + 'request', + 'access' +); + +CREATE TABLE oauth_server_token ( + ost_id serial primary key, + ost_osr_id_ref integer not null, + ost_usa_id_ref text not null, + ost_token varchar(64) not null, + ost_token_secret varchar(64) not null, + ost_token_type server_token_type, + ost_authorized boolean not null default false, + ost_referrer_host varchar(128) not null default '', + ost_token_ttl timestamp not null default timestamp '9999-12-31', + ost_timestamp timestamp not null default current_timestamp, + ost_verifier char(10), + ost_callback_url varchar(512), + + unique (ost_token), + + foreign key (ost_osr_id_ref) references oauth_server_registry (osr_id) + on update cascade + on delete cascade +); + + +COMMENT ON TABLE oauth_server_token IS 'Table used to verify signed requests sent to a server by the consumer'; diff --git a/includes/oauth-php/test/discovery/xrds-fireeagle.xrds b/includes/oauth-php/test/discovery/xrds-fireeagle.xrds new file mode 100644 index 00000000..0f5eba22 --- /dev/null +++ b/includes/oauth-php/test/discovery/xrds-fireeagle.xrds @@ -0,0 +1,78 @@ + + + + + + + xri://$xrds*simple + 2008-04-15T00:25:30-07:00 + + + + http://oauth.net/core/1.0/endpoint/request + + http://oauth.net/core/1.0/parameters/auth-header + http://oauth.net/core/1.0/parameters/post-body + http://oauth.net/core/1.0/parameters/uri-query + http://oauth.net/core/1.0/signature/HMAC-SHA1 + http://oauth.net/core/1.0/signature/PLAINTEXT + + https://fireeagle.yahooapis.com/oauth/request_token + + + + + http://oauth.net/core/1.0/endpoint/authorize + + http://oauth.net/core/1.0/parameters/auth-header + http://oauth.net/core/1.0/parameters/uri-query + + https://fireeagle.yahooapis.com/oauth/access_token + + + + + http://oauth.net/core/1.0/endpoint/access + + http://oauth.net/core/1.0/parameters/auth-header + http://oauth.net/core/1.0/parameters/post-body + http://oauth.net/core/1.0/parameters/uri-query + http://oauth.net/core/1.0/signature/HMAC-SHA1 + http://oauth.net/core/1.0/signature/PLAINTEXT + + http://fireeagle.yahoo.net/oauth/authorize + + + + + http://oauth.net/core/1.0/endpoint/resource + + http://oauth.net/core/1.0/parameters/auth-header + http://oauth.net/core/1.0/parameters/post-body + http://oauth.net/core/1.0/parameters/uri-query + http://oauth.net/core/1.0/signature/HMAC-SHA1 + http://oauth.net/core/1.0/signature/PLAINTEXT + + + + + + + http://oauth.net/discovery/1.0/consumer-identity/oob + https://fireeagle.yahoo.net/developer/create + + + + + + + xri://$xrds*simple + + + + http://oauth.net/discovery/1.0 + #oauth + + + + \ No newline at end of file diff --git a/includes/oauth-php/test/discovery/xrds-getsatisfaction.xrds b/includes/oauth-php/test/discovery/xrds-getsatisfaction.xrds new file mode 100644 index 00000000..ab94b5be --- /dev/null +++ b/includes/oauth-php/test/discovery/xrds-getsatisfaction.xrds @@ -0,0 +1,73 @@ + + + + + xri://$xrds*simple + 2008-04-30T23:59:59Z + + + + http://oauth.net/core/1.0/endpoint/request + + http://oauth.net/core/1.0/parameters/auth-header + http://oauth.net/core/1.0/signature/HMAC-SHA1 + + http://getsatisfaction.com/api/request_token + + + + http://oauth.net/core/1.0/endpoint/authorize + + http://oauth.net/core/1.0/parameters/uri-query + + http://getsatisfaction.com/api/authorize + + + + + http://oauth.net/core/1.0/endpoint/access + + http://oauth.net/core/1.0/parameters/auth-header + http://oauth.net/core/1.0/signature/HMAC-SHA1 + + http://getsatisfaction.com/api/access_token + + + + + + http://oauth.net/core/1.0/endpoint/resource + + http://oauth.net/core/1.0/parameters/auth-header + http://oauth.net/core/1.0/signature/HMAC-SHA1 + + + + + + + http://oauth.net/discovery/1.0/consumer-identity/oob + http://getsatisfaction.com/me/extensions/new + + + + + + + xri://$xrds*simple + + + + http://oauth.net/discovery/1.0 + #oauth + + + + \ No newline at end of file diff --git a/includes/oauth-php/test/discovery/xrds-magnolia.xrds b/includes/oauth-php/test/discovery/xrds-magnolia.xrds new file mode 100644 index 00000000..361b5c9a --- /dev/null +++ b/includes/oauth-php/test/discovery/xrds-magnolia.xrds @@ -0,0 +1,81 @@ + + + + + + + xri://$xrds*simple + 2008-04-13T07:34:58Z + + + + http://oauth.net/core/1.0/endpoint/request + + http://oauth.net/core/1.0/parameters/auth-header + http://oauth.net/core/1.0/parameters/post-body + http://oauth.net/core/1.0/parameters/uri-query + http://oauth.net/core/1.0/signature/HMAC-SHA1 + http://oauth.net/core/1.0/signature/RSA-SHA1 + http://oauth.net/core/1.0/signature/PLAINTEXT + + https://ma.gnolia.com/oauth/get_request_token + + + + + http://oauth.net/core/1.0/endpoint/authorize + + http://oauth.net/core/1.0/parameters/auth-header + http://oauth.net/core/1.0/parameters/uri-query + + https://ma.gnolia.com/oauth/authorize + http://ma.gnolia.com/oauth/authorize + + + + + http://oauth.net/core/1.0/endpoint/access + + http://oauth.net/core/1.0/parameters/auth-header + http://oauth.net/core/1.0/parameters/post-body + http://oauth.net/core/1.0/parameters/uri-query + http://oauth.net/core/1.0/signature/HMAC-SHA1 + http://oauth.net/core/1.0/signature/RSA-SHA1 + http://oauth.net/core/1.0/signature/PLAINTEXT + + https://ma.gnolia.com/oauth/get_access_token + + + + + http://oauth.net/core/1.0/endpoint/resource + + http://oauth.net/core/1.0/parameters/auth-header + http://oauth.net/core/1.0/parameters/post-body + http://oauth.net/core/1.0/parameters/uri-query + http://oauth.net/core/1.0/signature/HMAC-SHA1 + http://oauth.net/core/1.0/signature/RSA-SHA1 + + + + + + + http://oauth.net/discovery/1.0/consumer-identity/oob + http://ma.gnolia.com/applications/new + + + + + + + xri://$xrds*simple + + + + http://oauth.net/discovery/1.0 + #oauth + + + + \ No newline at end of file diff --git a/includes/oauth-php/test/oauth_test.php b/includes/oauth-php/test/oauth_test.php new file mode 100644 index 00000000..c7d174b8 --- /dev/null +++ b/includes/oauth-php/test/oauth_test.php @@ -0,0 +1,188 @@ + + * @date Nov 29, 2007 3:46:56 PM + * @see http://wiki.oauth.net/TestCases + * + * 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__) . '/../library/OAuthRequest.php'; +require_once dirname(__FILE__) . '/../library/OAuthRequester.php'; +require_once dirname(__FILE__) . '/../library/OAuthRequestSigner.php'; +require_once dirname(__FILE__) . '/../library/OAuthRequestVerifier.php'; + +if (!function_exists('getallheaders')) +{ + function getallheaders() + { + return array(); + } +} + + +oauth_test(); + +function oauth_test () +{ + error_reporting(E_ALL); + + header('Content-Type: text/plain; charset=utf-8'); + + echo "Performing OAuth module tests.\n\n"; + echo "See also: http://wiki.oauth.net/TestCases\n\n"; + + assert_options(ASSERT_CALLBACK, 'oauth_assert_handler'); + assert_options(ASSERT_WARNING, 0); + + $req = new OAuthRequest('http://www.example.com', 'GET'); + + echo "***** Parameter Encoding *****\n\n"; + + assert('$req->urlencode(\'abcABC123\') == \'abcABC123\''); + assert('$req->urlencode(\'-._~\') == \'-._~\''); + assert('$req->urlencode(\'%\') == \'%25\''); + assert('$req->urlencode(\'&=*\') == \'%26%3D%2A\''); + assert('$req->urlencode(\'&=*\') == \'%26%3D%2A\''); + assert('$req->urlencode("\n") == \'%0A\''); + assert('$req->urlencode(" ") == \'%20\''); + assert('$req->urlencode("\x7f") == \'%7F\''); + + + echo "***** Normalize Request Parameters *****\n\n"; + + $req = new OAuthRequest('http://example.com/?name', 'GET'); + assert('$req->getNormalizedParams() == \'name=\''); + + $req = new OAuthRequest('http://example.com/?a=b', 'GET'); + assert('$req->getNormalizedParams() == \'a=b\''); + + $req = new OAuthRequest('http://example.com/?a=b&c=d', 'GET'); + assert('$req->getNormalizedParams() == \'a=b&c=d\''); + + // At this moment we don't support two parameters with the same name + // so I changed this test case to "a=" and "b=" and not "a=" and "a=" + $req = new OAuthRequest('http://example.com/?b=x!y&a=x+y', 'GET'); + assert('$req->getNormalizedParams() == \'a=x%2By&b=x%21y\''); + + $req = new OAuthRequest('http://example.com/?x!y=a&x=a', 'GET'); + assert('$req->getNormalizedParams() == \'x=a&x%21y=a\''); + + + echo "***** Base String *****\n\n"; + + $req = new OAuthRequest('http://example.com/?n=v', 'GET'); + assert('$req->signatureBaseString() == \'GET&http%3A%2F%2Fexample.com%2F&n%3Dv\''); + + $req = new OAuthRequest( + 'https://photos.example.net/request_token', + 'POST', + 'oauth_version=1.0&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_timestamp=1191242090&oauth_nonce=hsu94j3884jdopsl&oauth_signature_method=PLAINTEXT&oauth_signature=ignored', + array('X-OAuth-Test' => true)); + assert('$req->signatureBaseString() == \'POST&https%3A%2F%2Fphotos.example.net%2Frequest_token&oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dhsu94j3884jdopsl%26oauth_signature_method%3DPLAINTEXT%26oauth_timestamp%3D1191242090%26oauth_version%3D1.0\''); + + $req = new OAuthRequest( + 'http://photos.example.net/photos?file=vacation.jpg&size=original&oauth_version=1.0&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_token=nnch734d00sl2jdk&oauth_timestamp=1191242096&oauth_nonce=kllo9940pd9333jh&oauth_signature=ignored&oauth_signature_method=HMAC-SHA1', + 'GET'); + assert('$req->signatureBaseString() == \'GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal\''); + + + echo "***** HMAC-SHA1 *****\nRequest signing\n"; + + OAuthStore::instance('MySQL', array('conn'=>false)); + $req = new OAuthRequestSigner('http://photos.example.net/photos?file=vacation.jpg&size=original', 'GET'); + + assert('$req->urldecode($req->calculateDataSignature(\'bs\', \'cs\', \'\', \'HMAC-SHA1\')) == \'egQqG5AJep5sJ7anhXju1unge2I=\''); + assert('$req->urldecode($req->calculateDataSignature(\'bs\', \'cs\', \'ts\', \'HMAC-SHA1\')) == \'VZVjXceV7JgPq/dOTnNmEfO0Fv8=\''); + + $secrets = array( + 'consumer_key' => 'dpf43f3p2l4k3l03', + 'consumer_secret' => 'kd94hf93k423kf44', + 'token' => 'nnch734d00sl2jdk', + 'token_secret' => 'pfkkdhi9sl3r4s00', + 'signature_methods' => array('HMAC-SHA1'), + 'nonce' => 'kllo9940pd9333jh', + 'timestamp' => '1191242096' + ); + $req->sign(0, $secrets); + assert('$req->getParam(\'oauth_signature\', true) == \'tR3+Ty81lMeYAr/Fid0kMTYa/WM=\''); + + echo "***** HMAC-SHA1 *****\nRequest verification\n"; + + $req = new OAuthRequestVerifier( + 'http://photos.example.net/photos?file=vacation.jpg&size=original' + .'&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_token=nnch734d00sl2jdk' + .'&oauth_signature_method=HMAC-SHA1&oauth_nonce=kllo9940pd9333jh' + .'&oauth_timestamp=1191242096&oauth_version=1.0' + .'&oauth_signature='.rawurlencode('tR3+Ty81lMeYAr/Fid0kMTYa/WM=') + , 'GET'); + + $req->verifySignature('kd94hf93k423kf44', 'pfkkdhi9sl3r4s00'); + + echo "\n"; + echo "***** Yahoo! test case ******\n\n"; + + OAuthStore::instance('MySQL', array('conn'=>false)); + $req = new OAuthRequestSigner('http://example.com:80/photo', 'GET'); + + $req->setParam('title', 'taken with a 30% orange filter'); + $req->setParam('file', 'mountain & water view'); + $req->setParam('format', 'jpeg'); + $req->setParam('include', array('date','aperture')); + + $secrets = array( + 'consumer_key' => '1234=asdf=4567', + 'consumer_secret' => 'erks823*43=asd&123ls%23', + 'token' => 'asdf-4354=asew-5698', + 'token_secret' => 'dis9$#$Js009%==', + 'signature_methods' => array('HMAC-SHA1'), + 'nonce' => '3jd834jd9', + 'timestamp' => '12303202302' + ); + $req->sign(0, $secrets); + + // echo "Basestring:\n",$req->signatureBaseString(), "\n\n"; + + //echo "queryString:\n",$req->getQueryString(), "\n\n"; + assert('$req->getQueryString() == \'title=taken%20with%20a%2030%25%20orange%20filter&file=mountain%20%26%20water%20view&format=jpeg&include=date&include=aperture\''); + + //echo "oauth_signature:\n",$req->getParam('oauth_signature', true),"\n\n"; + assert('$req->getParam(\'oauth_signature\', true) == \'jMdUSR1vOr3SzNv3gZ5DDDuGirA=\''); + + echo "\n\nFinished.\n"; +} + + +function oauth_assert_handler ( $file, $line, $code ) +{ + echo "\nAssertion failed in $file:$line + $code\n\n"; +} + +/* vi:set ts=4 sts=4 sw=4 binary noeol: */ + +?> \ No newline at end of file diff --git a/sources/source-NextCaller.module b/sources/source-NextCaller.module index e7fb27ef..2cb6fd4f 100644 --- a/sources/source-NextCaller.module +++ b/sources/source-NextCaller.module @@ -1,57 +1,94 @@ array( - 'description' => 'Auth Token from NextCaller Dashboard', - 'type' => 'textarea' - ), - 'Ignore_Keywords' => array( - 'description' => 'If this source provides CNAM including any of the keywords listed here, the CNAM will be ignored and other sources will be used to find the value.
Separate keywords with commas.', - 'type' => 'textarea', - 'default' => 'unavailable, unknown' - ) - ); - - function get_caller_id($thenumber, $run_param=array()) { - - $caller_id = null; - $this->DebugPrint("Searching Nextcaller ... "); - - $url = "https://api.nextcaller.com/v1/auth?format=json&auth_code=".$run_param['Auth_Code']; - $o = json_decode($this->get_url_contents($url),TRUE); - - if(!empty($o['access_token'])) { - $url = "https://api.nextcaller.com/v1/users?phone=".$thenumber."&format=json&access_token=".$o['access_token']; - $o = json_decode($this->get_url_contents($url),TRUE); - foreach($o as $user) { - if($user['member']) { - if (strlen($user['name']) > 1) { - // convert list of ignore keywords into array - $key_words = array(); - $temp_array = explode(',',(isset($run_param['Ignore_Keywords'])?$run_param['Ignore_Keywords']:$source_param['Ignore_Keywords']['default'])); - foreach($temp_array as $val) { - $key_words[] = trim($val); - } - - // Remove all ignore keywords from the retuned CNAM string and compare the before and after. - $test_string = str_ireplace($key_words,'',$user['name']); - if($test_string == $user['name']) { - $this->DebugPrint("CNAM determined good."); - return($user['name']); - } else { - $this->DebugPrint("CNAM contains flagged key words, returning nothing."); - } - } + public $description = "https://www.nextcaller.com This data source returns CNAM data for any NANPA phone number (any number that starts with +1)."; + public $version_requirement = "2.11"; + public $source_param = array( + 'Auth_Code' => array( + 'description' => 'Auth Token from NextCaller Dashboard', + 'type' => 'textarea' + ), + 'Auth_Secret' => array( + 'description' => 'Consumer Secret', + 'type' => 'textarea' + ), + 'Ignore_Keywords' => array( + 'description' => 'If this source provides CNAM including any of the keywords listed here, the CNAM will be ignored and other sources will be used to find the value.
Separate keywords with commas.', + 'type' => 'textarea', + 'default' => 'unavailable, unknown' + ) + ); + +function __construct() { + require_once(dirname(dirname(__FILE__)) . "/includes/oauth-php/library/OAuthStore.php"); + require_once(dirname(dirname(__FILE__)) . "/includes/oauth-php/library/OAuthRequester.php"); + } + + function get_caller_id($thenumber, $run_param=array()) { + + $caller_id = null; + $this->DebugPrint("Searching Nextcaller ... "); + + $key = $run_param['Auth_Code']; // this is your consumer key + $secret = $run_param['Auth_Secret']; // this is your secret key + if ($secret && $key) { + $options = array( 'consumer_key' => $key, 'consumer_secret' => $secret ); + OAuthStore::instance("2Leg", $options ); + + $url = "https://api.nextcaller.com/v2/records/?phone=".$thenumber."&format=json"; // this is the URL of the request + $method = "GET"; // you can also use POST instead + $params = null; + $response = null; + try { + // Obtain a request object for the request we want to make + $request = new OAuthRequester($url, $method, $params); + + // Sign the request, perform a curl request and return the results, + // throws OAuthException2 exception on an error + // $result is an array of the form: array ('code'=>int, 'headers'=>array(), 'body'=>string) + $result = $request->doRequest(); + + $response = $result['body']; + //$this->DebugPrint($response); + } catch(OAuthException2 $e) { + $this->DebugPrint("OAuth Exception 2."); + } + $o = json_decode($response,TRUE); + $this->DebugPrint(print_r($o,TRUE)); + + $user = $o["records"][0]; + $this->DebugPrint($user); + if (strlen($user['name']) > 1) { + // convert list of ignore keywords into array + $key_words = array(); + $temp_array = explode(',',(isset($run_param['Ignore_Keywords'])?$run_param['Ignore_Keywords']:$source_param['Ignore_Keywords']['default'])); + foreach($temp_array as $val) { + $key_words[] = trim($val); + } + + // Remove all ignore keywords from the retuned CNAM string and compare the before and after. + $test_string = str_ireplace($key_words,'',$user['name']); + if($test_string == $user['name']) { + $this->DebugPrint("CNAM determined good."); + return($user['name']); + } else { + $this->DebugPrint("CNAM contains flagged key words, returning nothing."); } } $this->DebugPrint("CNAM not found."); + return false; } else { - $this->DebugPrint("Access Token Error."); + $this->DebugPrint("Missing Auth code and/or Auth Secret."); } - return false; - } + } } \ No newline at end of file