From 9275f45e42118f6863dfce19ba19ec8fc0063535 Mon Sep 17 00:00:00 2001 From: wilsonge Date: Sun, 4 Jun 2017 11:27:57 +0100 Subject: [PATCH] Replace oAuth1 and oAuth2 clients with the framework packages --- composer.json | 4 + composer.lock | 107 +++- libraries/joomla/oauth2/client.php | 388 --------------- libraries/vendor/composer/autoload_psr4.php | 2 + libraries/vendor/composer/autoload_static.php | 10 + libraries/vendor/composer/installed.json | 107 ++++ libraries/vendor/joomla/oauth1/LICENSE | 340 +++++++++++++ .../joomla/oauth1/src/Client.php} | 324 ++++++------ libraries/vendor/joomla/oauth2/LICENSE | 340 +++++++++++++ libraries/vendor/joomla/oauth2/src/Client.php | 398 +++++++++++++++ .../joomla/oauth1/JOAuth1ClientTest.php | 369 -------------- .../oauth1/stubs/JOAuth1ClientInspector.php | 55 --- .../joomla/oauth2/JOauth2ClientTest.php | 463 ------------------ 13 files changed, 1475 insertions(+), 1432 deletions(-) delete mode 100644 libraries/joomla/oauth2/client.php create mode 100644 libraries/vendor/joomla/oauth1/LICENSE rename libraries/{joomla/oauth1/client.php => vendor/joomla/oauth1/src/Client.php} (58%) create mode 100644 libraries/vendor/joomla/oauth2/LICENSE create mode 100644 libraries/vendor/joomla/oauth2/src/Client.php delete mode 100644 tests/unit/suites/libraries/joomla/oauth1/JOAuth1ClientTest.php delete mode 100644 tests/unit/suites/libraries/joomla/oauth1/stubs/JOAuth1ClientInspector.php delete mode 100644 tests/unit/suites/libraries/joomla/oauth2/JOauth2ClientTest.php diff --git a/composer.json b/composer.json index 9b0fefaf59b..0a0c73edad1 100644 --- a/composer.json +++ b/composer.json @@ -18,6 +18,8 @@ "joomla/event": "dist", "joomla/http": "dist", "joomla/image": "dist", + "joomla/oauth1": "dist", + "joomla/oauth2": "dist", "joomla/mediawiki": "dist", "joomla/registry": "dist", "joomla/session": "dist", @@ -50,6 +52,8 @@ "joomla/http": "~2.0@dev", "joomla/image": "~2.0@dev", "joomla/ldap": "~1.1", + "joomla/oauth1": "~2.0@dev", + "joomla/oauth2": "~2.0@dev", "joomla/registry": "~2.0@dev", "joomla/session": "~2.0@dev", "joomla/string": "~2.0@dev", diff --git a/composer.lock b/composer.lock index e332b33d88a..225f419e326 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "a2d4a73be913adacb075a90dca9096cc", + "content-hash": "48bfaafe8baa33842e617863b280b2cf", "packages": [ { "name": "composer/ca-bundle", @@ -741,6 +741,109 @@ ], "time": "2014-04-10T03:07:59+00:00" }, + { + "name": "joomla/oauth1", + "version": "dev-2.0-dev", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/oauth1.git", + "reference": "7855fee23cbe1afe28121b9729e4a03c78de18ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/oauth1/zipball/7855fee23cbe1afe28121b9729e4a03c78de18ba", + "reference": "7855fee23cbe1afe28121b9729e4a03c78de18ba", + "shasum": "" + }, + "require": { + "joomla/application": "~1.0|~2.0", + "joomla/http": "^1.2.2|~2.0", + "joomla/input": "~1.2|~2.0", + "joomla/registry": "^1.4.5|~2.0", + "joomla/session": "~1.0|~2.0", + "paragonie/random_compat": "~1.0|~2.0", + "php": "^5.5.9|~7.0" + }, + "require-dev": { + "joomla/event": "~1.0|~2.0", + "joomla/test": "~1.0", + "phpunit/phpunit": "^4.8.35|^5.4.3|~6.0", + "squizlabs/php_codesniffer": "1.*" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\OAuth1\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0+" + ], + "description": "Joomla OAuth1 Package", + "homepage": "https://github.com/joomla-framework/oauth1", + "keywords": [ + "framework", + "joomla", + "oauth1" + ], + "time": "2017-05-27T01:17:14+00:00" + }, + { + "name": "joomla/oauth2", + "version": "dev-2.0-dev", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/oauth2.git", + "reference": "85837a6c6b05070f60b9ec784f1f95a3301ac162" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/oauth2/zipball/85837a6c6b05070f60b9ec784f1f95a3301ac162", + "reference": "85837a6c6b05070f60b9ec784f1f95a3301ac162", + "shasum": "" + }, + "require": { + "joomla/application": "~1.0|~2.0", + "joomla/http": "^1.2.2|~2.0", + "joomla/input": "~1.2|~2.0", + "joomla/session": "~1.0|~2.0", + "php": "^5.5.9|~7.0" + }, + "require-dev": { + "joomla/test": "~1.0", + "phpunit/phpunit": "^4.8.35|^5.4.3|~6.0", + "squizlabs/php_codesniffer": "1.*" + }, + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Joomla\\OAuth2\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0+" + ], + "description": "Joomla OAuth2 Package", + "homepage": "https://github.com/joomla-framework/oauth2", + "keywords": [ + "framework", + "joomla", + "oauth2" + ], + "time": "2017-05-27T01:17:23+00:00" + }, { "name": "joomla/registry", "version": "dev-2.0-dev", @@ -3285,6 +3388,8 @@ "joomla/event": 20, "joomla/http": 20, "joomla/image": 20, + "joomla/oauth1": 20, + "joomla/oauth2": 20, "joomla/registry": 20, "joomla/session": 20, "joomla/string": 20, diff --git a/libraries/joomla/oauth2/client.php b/libraries/joomla/oauth2/client.php deleted file mode 100644 index 30dec1b5431..00000000000 --- a/libraries/joomla/oauth2/client.php +++ /dev/null @@ -1,388 +0,0 @@ -options = isset($options) ? $options : new Registry; - $this->http = isset($http) ? $http : new JHttp($this->options); - $this->application = isset($application) ? $application : new JApplicationWeb; - $this->input = isset($input) ? $input : $this->application->input; - } - - /** - * Get the access token or redict to the authentication URL. - * - * @return string The access token - * - * @since 12.3 - * @throws RuntimeException - */ - public function authenticate() - { - if ($data['code'] = $this->input->get('code', false, 'raw')) - { - $data['grant_type'] = 'authorization_code'; - $data['redirect_uri'] = $this->getOption('redirecturi'); - $data['client_id'] = $this->getOption('clientid'); - $data['client_secret'] = $this->getOption('clientsecret'); - $response = $this->http->post($this->getOption('tokenurl'), $data); - - if ($response->code >= 200 && $response->code < 400) - { - if (strpos($response->headers['Content-Type'], 'application/json') === 0) - { - $token = array_merge(json_decode($response->body, true), array('created' => time())); - } - else - { - parse_str($response->body, $token); - $token = array_merge($token, array('created' => time())); - } - - $this->setToken($token); - - return $token; - } - else - { - throw new RuntimeException('Error code ' . $response->code . ' received requesting access token: ' . $response->body . '.'); - } - } - - if ($this->getOption('sendheaders')) - { - $this->application->redirect($this->createUrl()); - } - - return false; - } - - /** - * Verify if the client has been authenticated - * - * @return boolean Is authenticated - * - * @since 12.3 - */ - public function isAuthenticated() - { - $token = $this->getToken(); - - if (!$token || !array_key_exists('access_token', $token)) - { - return false; - } - elseif (array_key_exists('expires_in', $token) && $token['created'] + $token['expires_in'] < time() + 20) - { - return false; - } - else - { - return true; - } - } - - /** - * Create the URL for authentication. - * - * @return JHttpResponse The HTTP response - * - * @since 12.3 - * @throws InvalidArgumentException - */ - public function createUrl() - { - if (!$this->getOption('authurl') || !$this->getOption('clientid')) - { - throw new InvalidArgumentException('Authorization URL and client_id are required'); - } - - $url = $this->getOption('authurl'); - - if (strpos($url, '?')) - { - $url .= '&'; - } - else - { - $url .= '?'; - } - - $url .= 'response_type=code'; - $url .= '&client_id=' . urlencode($this->getOption('clientid')); - - if ($this->getOption('redirecturi')) - { - $url .= '&redirect_uri=' . urlencode($this->getOption('redirecturi')); - } - - if ($this->getOption('scope')) - { - $scope = is_array($this->getOption('scope')) ? implode(' ', $this->getOption('scope')) : $this->getOption('scope'); - $url .= '&scope=' . urlencode($scope); - } - - if ($this->getOption('state')) - { - $url .= '&state=' . urlencode($this->getOption('state')); - } - - if (is_array($this->getOption('requestparams'))) - { - foreach ($this->getOption('requestparams') as $key => $value) - { - $url .= '&' . $key . '=' . urlencode($value); - } - } - - return $url; - } - - /** - * Send a signed Oauth request. - * - * @param string $url The URL for the request. - * @param mixed $data The data to include in the request - * @param array $headers The headers to send with the request - * @param string $method The method with which to send the request - * @param int $timeout The timeout for the request - * - * @return string The URL. - * - * @since 12.3 - * @throws InvalidArgumentException - * @throws RuntimeException - */ - public function query($url, $data = null, $headers = array(), $method = 'get', $timeout = null) - { - $token = $this->getToken(); - - if (array_key_exists('expires_in', $token) && $token['created'] + $token['expires_in'] < time() + 20) - { - if (!$this->getOption('userefresh')) - { - return false; - } - - $token = $this->refreshToken($token['refresh_token']); - } - - if (!$this->getOption('authmethod') || $this->getOption('authmethod') == 'bearer') - { - $headers['Authorization'] = 'Bearer ' . $token['access_token']; - } - elseif ($this->getOption('authmethod') == 'get') - { - if (strpos($url, '?')) - { - $url .= '&'; - } - else - { - $url .= '?'; - } - - $url .= $this->getOption('getparam') ? $this->getOption('getparam') : 'access_token'; - $url .= '=' . $token['access_token']; - } - - switch ($method) - { - case 'head': - case 'get': - case 'delete': - case 'trace': - $response = $this->http->$method($url, $headers, $timeout); - break; - case 'post': - case 'put': - case 'patch': - $response = $this->http->$method($url, $data, $headers, $timeout); - break; - default: - throw new InvalidArgumentException('Unknown HTTP request method: ' . $method . '.'); - } - - if ($response->code < 200 || $response->code >= 400) - { - throw new RuntimeException('Error code ' . $response->code . ' received requesting data: ' . $response->body . '.'); - } - - return $response; - } - - /** - * Get an option from the JOAuth2Client instance. - * - * @param string $key The name of the option to get - * - * @return mixed The option value - * - * @since 12.3 - */ - public function getOption($key) - { - return $this->options->get($key); - } - - /** - * Set an option for the JOAuth2Client instance. - * - * @param string $key The name of the option to set - * @param mixed $value The option value to set - * - * @return JOAuth2Client This object for method chaining - * - * @since 12.3 - */ - public function setOption($key, $value) - { - $this->options->set($key, $value); - - return $this; - } - - /** - * Get the access token from the JOAuth2Client instance. - * - * @return array The access token - * - * @since 12.3 - */ - public function getToken() - { - return $this->getOption('accesstoken'); - } - - /** - * Set an option for the JOAuth2Client instance. - * - * @param array $value The access token - * - * @return JOAuth2Client This object for method chaining - * - * @since 12.3 - */ - public function setToken($value) - { - if (is_array($value) && !array_key_exists('expires_in', $value) && array_key_exists('expires', $value)) - { - $value['expires_in'] = $value['expires']; - unset($value['expires']); - } - - $this->setOption('accesstoken', $value); - - return $this; - } - - /** - * Refresh the access token instance. - * - * @param string $token The refresh token - * - * @return array The new access token - * - * @since 12.3 - * @throws Exception - * @throws RuntimeException - */ - public function refreshToken($token = null) - { - if (!$this->getOption('userefresh')) - { - throw new RuntimeException('Refresh token is not supported for this OAuth instance.'); - } - - if (!$token) - { - $token = $this->getToken(); - - if (!array_key_exists('refresh_token', $token)) - { - throw new RuntimeException('No refresh token is available.'); - } - - $token = $token['refresh_token']; - } - - $data['grant_type'] = 'refresh_token'; - $data['refresh_token'] = $token; - $data['client_id'] = $this->getOption('clientid'); - $data['client_secret'] = $this->getOption('clientsecret'); - $response = $this->http->post($this->getOption('tokenurl'), $data); - - if ($response->code >= 200 || $response->code < 400) - { - if (strpos($response->headers['Content-Type'], 'application/json') === 0) - { - $token = array_merge(json_decode($response->body, true), array('created' => time())); - } - else - { - parse_str($response->body, $token); - $token = array_merge($token, array('created' => time())); - } - - $this->setToken($token); - - return $token; - } - else - { - throw new Exception('Error code ' . $response->code . ' received refreshing token: ' . $response->body . '.'); - } - } -} diff --git a/libraries/vendor/composer/autoload_psr4.php b/libraries/vendor/composer/autoload_psr4.php index 5cf014cc3a3..3c9c761077a 100644 --- a/libraries/vendor/composer/autoload_psr4.php +++ b/libraries/vendor/composer/autoload_psr4.php @@ -19,6 +19,8 @@ return array( 'Joomla\\String\\' => array($vendorDir . '/joomla/string/src'), 'Joomla\\Session\\' => array($vendorDir . '/joomla/session/src'), 'Joomla\\Registry\\' => array($vendorDir . '/joomla/registry/src'), + 'Joomla\\OAuth2\\' => array($vendorDir . '/joomla/oauth2/src'), + 'Joomla\\OAuth1\\' => array($vendorDir . '/joomla/oauth1/src'), 'Joomla\\Ldap\\Tests\\' => array($vendorDir . '/joomla/ldap/Tests'), 'Joomla\\Ldap\\' => array($vendorDir . '/joomla/ldap/src'), 'Joomla\\Input\\Tests\\' => array($vendorDir . '/joomla/input/Tests'), diff --git a/libraries/vendor/composer/autoload_static.php b/libraries/vendor/composer/autoload_static.php index 90e188ed774..03bb8e2c242 100644 --- a/libraries/vendor/composer/autoload_static.php +++ b/libraries/vendor/composer/autoload_static.php @@ -52,6 +52,8 @@ class ComposerStaticInit423c8facdf90155590c7b49e979f3a1e 'Joomla\\String\\' => 14, 'Joomla\\Session\\' => 15, 'Joomla\\Registry\\' => 16, + 'Joomla\\OAuth2\\' => 14, + 'Joomla\\OAuth1\\' => 14, 'Joomla\\Ldap\\Tests\\' => 18, 'Joomla\\Ldap\\' => 12, 'Joomla\\Input\\Tests\\' => 19, @@ -126,6 +128,14 @@ class ComposerStaticInit423c8facdf90155590c7b49e979f3a1e array ( 0 => __DIR__ . '/..' . '/joomla/registry/src', ), + 'Joomla\\OAuth2\\' => + array ( + 0 => __DIR__ . '/..' . '/joomla/oauth2/src', + ), + 'Joomla\\OAuth1\\' => + array ( + 0 => __DIR__ . '/..' . '/joomla/oauth1/src', + ), 'Joomla\\Ldap\\Tests\\' => array ( 0 => __DIR__ . '/..' . '/joomla/ldap/Tests', diff --git a/libraries/vendor/composer/installed.json b/libraries/vendor/composer/installed.json index 6f107322d6b..f97f4105f8d 100644 --- a/libraries/vendor/composer/installed.json +++ b/libraries/vendor/composer/installed.json @@ -1539,5 +1539,112 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com" + }, + { + "name": "joomla/oauth1", + "version": "dev-2.0-dev", + "version_normalized": "dev-2.0-dev", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/oauth1.git", + "reference": "7855fee23cbe1afe28121b9729e4a03c78de18ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/oauth1/zipball/7855fee23cbe1afe28121b9729e4a03c78de18ba", + "reference": "7855fee23cbe1afe28121b9729e4a03c78de18ba", + "shasum": "" + }, + "require": { + "joomla/application": "~1.0|~2.0", + "joomla/http": "^1.2.2|~2.0", + "joomla/input": "~1.2|~2.0", + "joomla/registry": "^1.4.5|~2.0", + "joomla/session": "~1.0|~2.0", + "paragonie/random_compat": "~1.0|~2.0", + "php": "^5.5.9|~7.0" + }, + "require-dev": { + "joomla/event": "~1.0|~2.0", + "joomla/test": "~1.0", + "phpunit/phpunit": "^4.8.35|^5.4.3|~6.0", + "squizlabs/php_codesniffer": "1.*" + }, + "time": "2017-05-27T01:17:14+00:00", + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Joomla\\OAuth1\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0+" + ], + "description": "Joomla OAuth1 Package", + "homepage": "https://github.com/joomla-framework/oauth1", + "keywords": [ + "framework", + "joomla", + "oauth1" + ] + }, + { + "name": "joomla/oauth2", + "version": "dev-2.0-dev", + "version_normalized": "dev-2.0-dev", + "source": { + "type": "git", + "url": "https://github.com/joomla-framework/oauth2.git", + "reference": "85837a6c6b05070f60b9ec784f1f95a3301ac162" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/joomla-framework/oauth2/zipball/85837a6c6b05070f60b9ec784f1f95a3301ac162", + "reference": "85837a6c6b05070f60b9ec784f1f95a3301ac162", + "shasum": "" + }, + "require": { + "joomla/application": "~1.0|~2.0", + "joomla/http": "^1.2.2|~2.0", + "joomla/input": "~1.2|~2.0", + "joomla/session": "~1.0|~2.0", + "php": "^5.5.9|~7.0" + }, + "require-dev": { + "joomla/test": "~1.0", + "phpunit/phpunit": "^4.8.35|^5.4.3|~6.0", + "squizlabs/php_codesniffer": "1.*" + }, + "time": "2017-05-27T01:17:23+00:00", + "type": "joomla-package", + "extra": { + "branch-alias": { + "dev-2.0-dev": "2.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Joomla\\OAuth2\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0+" + ], + "description": "Joomla OAuth2 Package", + "homepage": "https://github.com/joomla-framework/oauth2", + "keywords": [ + "framework", + "joomla", + "oauth2" + ] } ] diff --git a/libraries/vendor/joomla/oauth1/LICENSE b/libraries/vendor/joomla/oauth1/LICENSE new file mode 100644 index 00000000000..df50810b857 --- /dev/null +++ b/libraries/vendor/joomla/oauth1/LICENSE @@ -0,0 +1,340 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/libraries/joomla/oauth1/client.php b/libraries/vendor/joomla/oauth1/src/Client.php similarity index 58% rename from libraries/joomla/oauth1/client.php rename to libraries/vendor/joomla/oauth1/src/Client.php index 4ca5ae07c6b..1d83040a84e 100644 --- a/libraries/joomla/oauth1/client.php +++ b/libraries/vendor/joomla/oauth1/src/Client.php @@ -1,88 +1,106 @@ options = isset($options) ? $options : new Registry; - $this->client = isset($client) ? $client : JHttpFactory::getHttp($this->options); - $this->application = isset($application) ? $application : new JApplicationWeb; - $this->input = isset($input) ? $input : $this->application->input; - $this->version = isset($version) ? $version : '1.0a'; + if (!is_array($options) && !($options instanceof \ArrayAccess)) + { + throw new \InvalidArgumentException( + 'The options param must be an array or implement the ArrayAccess interface.' + ); + } + + $this->application = $application; + $this->client = $client instanceof Http ? $client : HttpFactory::getHttp($options); + $this->input = $input instanceof Input ? $input : $application->input; + $this->options = $options; + $this->version = $version; } /** - * Method to for the oauth flow. + * Method to form the oauth flow. * - * @return array Contains access token key, secret and verifier. + * @return string The access token. * - * @since 13.1 - * @throws DomainException + * @since 1.0 + * @throws \DomainException */ public function authenticate() { @@ -95,10 +113,8 @@ abstract class JOAuth1Client { return $this->token; } - else - { - $this->token = null; - } + + $this->token = null; } // Check for callback. @@ -111,27 +127,20 @@ abstract class JOAuth1Client $verifier = $this->input->get('oauth_token'); } - if (empty($verifier)) - { - // Generate a request token. - $this->_generateRequestToken(); - - // Authenticate the user and authorise the app. - $this->_authorise(); - } - - // Callback - else + if (!empty($verifier)) { $session = $this->application->getSession(); // Get token form session. - $this->token = array('key' => $session->get('oauth_token.key', null), 'secret' => $session->get('oauth_token.secret', null)); + $this->token = [ + 'key' => $session->get('oauth_token.key'), + 'secret' => $session->get('oauth_token.secret') + ]; // Verify the returned request token. if (strcmp($this->token['key'], $this->input->get('oauth_token')) !== 0) { - throw new DomainException('Bad session!'); + throw new \DomainException('Bad session!'); } // Set token verifier for 1.0a. @@ -141,11 +150,17 @@ abstract class JOAuth1Client } // Generate access token. - $this->_generateAccessToken(); + $this->generateAccessToken(); // Return the access token. return $this->token; } + + // Generate a request token. + $this->generateRequestToken(); + + // Authenticate the user and authorise the app. + $this->authorise(); } /** @@ -153,21 +168,17 @@ abstract class JOAuth1Client * * @return void * - * @since 13.1 - * @throws DomainException + * @since 1.0 + * @throws \DomainException */ - private function _generateRequestToken() + private function generateRequestToken() { + $parameters = []; + // Set the callback URL. if ($this->getOption('callback')) { - $parameters = array( - 'oauth_callback' => $this->getOption('callback'), - ); - } - else - { - $parameters = array(); + $parameters['oauth_callback'] = $this->getOption('callback'); } // Make an OAuth request for the Request Token. @@ -177,11 +188,11 @@ abstract class JOAuth1Client if (strcmp($this->version, '1.0a') === 0 && strcmp($params['oauth_callback_confirmed'], 'true') !== 0) { - throw new DomainException('Bad request token!'); + throw new \DomainException('Bad request token!'); } // Save the request token. - $this->token = array('key' => $params['oauth_token'], 'secret' => $params['oauth_token_secret']); + $this->token = ['key' => $params['oauth_token'], 'secret' => $params['oauth_token_secret']]; // Save the request token in session $session = $this->application->getSession(); @@ -194,9 +205,9 @@ abstract class JOAuth1Client * * @return void * - * @since 13.1 + * @since 1.0 */ - private function _authorise() + private function authorise() { $url = $this->getOption('authoriseURL') . '?oauth_token=' . $this->token['key']; @@ -217,18 +228,18 @@ abstract class JOAuth1Client * * @return void * - * @since 13.1 + * @since 1.0 */ - private function _generateAccessToken() + private function generateAccessToken() { // Set the parameters. - $parameters = array( - 'oauth_token' => $this->token['key'], - ); + $parameters = [ + 'oauth_token' => $this->token['key'] + ]; if (strcmp($this->version, '1.0a') === 0) { - $parameters = array_merge($parameters, array('oauth_verifier' => $this->token['verifier'])); + $parameters = array_merge($parameters, ['oauth_verifier' => $this->token['verifier']]); } // Make an OAuth request for the Access Token. @@ -237,7 +248,7 @@ abstract class JOAuth1Client parse_str($response->body, $params); // Save the access token. - $this->token = array('key' => $params['oauth_token'], 'secret' => $params['oauth_token_secret']); + $this->token = ['key' => $params['oauth_token'], 'secret' => $params['oauth_token_secret']]; } /** @@ -249,21 +260,21 @@ abstract class JOAuth1Client * @param mixed $data The POST request data. * @param array $headers An array of name-value pairs to include in the header of the request * - * @return JHttpResponse + * @return \Joomla\Http\Response * - * @since 13.1 - * @throws DomainException + * @since 1.0 + * @throws \DomainException */ - public function oauthRequest($url, $method, $parameters, $data = array(), $headers = array()) + public function oauthRequest($url, $method, $parameters, $data = [], $headers = []) { // Set the parameters. - $defaults = array( - 'oauth_consumer_key' => $this->getOption('consumer_key'), + $defaults = [ + 'oauth_consumer_key' => $this->getOption('consumer_key'), 'oauth_signature_method' => 'HMAC-SHA1', - 'oauth_version' => '1.0', - 'oauth_nonce' => $this->generateNonce(), - 'oauth_timestamp' => time(), - ); + 'oauth_version' => '1.0', + 'oauth_nonce' => $this->generateNonce(), + 'oauth_timestamp' => time() + ]; $parameters = array_merge($parameters, $defaults); @@ -279,7 +290,7 @@ abstract class JOAuth1Client } // Sign the request. - $oauth_headers = $this->_signRequest($url, $method, $oauth_headers); + $oauth_headers = $this->signRequest($url, $method, $oauth_headers); // Get parameters for the Authorisation header. if (is_array($data)) @@ -291,19 +302,18 @@ abstract class JOAuth1Client switch ($method) { case 'GET': - $url = $this->toUrl($url, $data); - $response = $this->client->get($url, array('Authorization' => $this->_createHeader($oauth_headers))); + $url = $this->toUrl($url, $data); + $response = $this->client->get($url, ['Authorization' => $this->createHeader($oauth_headers)]); break; + case 'POST': - $headers = array_merge($headers, array('Authorization' => $this->_createHeader($oauth_headers))); - $response = $this->client->post($url, $data, $headers); - break; case 'PUT': - $headers = array_merge($headers, array('Authorization' => $this->_createHeader($oauth_headers))); - $response = $this->client->put($url, $data, $headers); + $headers = array_merge($headers, ['Authorization' => $this->createHeader($oauth_headers)]); + $response = $this->client->{strtolower($method)}($url, $data, $headers); break; + case 'DELETE': - $headers = array_merge($headers, array('Authorization' => $this->_createHeader($oauth_headers))); + $headers = array_merge($headers, ['Authorization' => $this->createHeader($oauth_headers)]); $response = $this->client->delete($url, $headers); break; } @@ -317,26 +327,26 @@ abstract class JOAuth1Client /** * Method to validate a response. * - * @param string $url The request URL. - * @param JHttpResponse $response The response to validate. + * @param string $url The request URL. + * @param Response $response The response to validate. * * @return void * - * @since 13.1 - * @throws DomainException + * @since 1.0 + * @throws \DomainException */ abstract public function validateResponse($url, $response); /** * Method used to create the header for the POST request. * - * @param array $parameters Array containing request parameters. + * @param array $parameters Array containing request parameters. * * @return string The header. * - * @since 13.1 + * @since 1.0 */ - private function _createHeader($parameters) + private function createHeader($parameters) { $header = 'OAuth '; @@ -363,7 +373,7 @@ abstract class JOAuth1Client * * @return string The formed URL. * - * @since 13.1 + * @since 1.0 */ public function toUrl($url, $parameters) { @@ -371,16 +381,18 @@ abstract class JOAuth1Client { if (is_array($value)) { - foreach ($value as $v) + foreach ($value as $k => $v) { if (strpos($url, '?') === false) { - $url .= '?' . $key . '=' . $v; + $url .= '?'; } else { - $url .= '&' . $key . '=' . $v; + $url .= '&'; } + + $url .= $key . '=' . $v; } } else @@ -392,12 +404,14 @@ abstract class JOAuth1Client if (strpos($url, '?') === false) { - $url .= '?' . $key . '=' . $value; + $url .= '?'; } else { - $url .= '&' . $key . '=' . $value; + $url .= '&'; } + + $url .= $key . '=' . $value; } } @@ -411,20 +425,20 @@ abstract class JOAuth1Client * @param string $method The request method. * @param array $parameters Array containing request parameters. * - * @return array + * @return array The array containing the request parameters, including signature. * - * @since 13.1 + * @since 1.0 */ - private function _signRequest($url, $method, $parameters) + private function signRequest($url, $method, $parameters) { // Create the signature base string. - $base = $this->_baseString($url, $method, $parameters); + $base = $this->baseString($url, $method, $parameters); $parameters['oauth_signature'] = $this->safeEncode( base64_encode( - hash_hmac('sha1', $base, $this->_prepareSigningKey(), true) - ) - ); + hash_hmac('sha1', $base, $this->prepareSigningKey(), true) + ) + ); return $parameters; } @@ -438,9 +452,9 @@ abstract class JOAuth1Client * * @return string The base string. * - * @since 13.1 + * @since 1.0 */ - private function _baseString($url, $method, $parameters) + private function baseString($url, $method, $parameters) { // Sort the parameters alphabetically uksort($parameters, 'strcmp'); @@ -452,27 +466,28 @@ abstract class JOAuth1Client if (is_array($value)) { - foreach ($value as $v) + foreach ($value as $k => $v) { - $v = $this->safeEncode($v); + $v = $this->safeEncode($v); $kv[] = "{$key}={$v}"; } } else { $value = $this->safeEncode($value); - $kv[] = "{$key}={$value}"; + $kv[] = "{$key}={$value}"; } } + // Form the parameter string. $params = implode('&', $kv); // Signature base string elements. - $base = array( + $base = [ $method, $url, - $params, - ); + $params + ]; // Return the base string. return implode('&', $this->safeEncode($base)); @@ -486,26 +501,25 @@ abstract class JOAuth1Client * * @return string $data encoded in a way compatible with OAuth. * - * @since 13.1 + * @since 1.0 */ public function safeEncode($data) { if (is_array($data)) { - return array_map(array($this, 'safeEncode'), $data); + return array_map([$this, 'safeEncode'], $data); } - elseif (is_scalar($data)) + + if (is_scalar($data)) { return str_ireplace( - array('+', '%7E'), - array(' ', '~'), + ['+', '%7E'], + [' ', '~'], rawurlencode($data) - ); - } - else - { - return ''; + ); } + + return ''; } /** @@ -513,15 +527,12 @@ abstract class JOAuth1Client * * @return string The current nonce. * - * @since 13.1 + * @since 1.0 */ public static function generateNonce() { - $mt = microtime(); - $rand = JCrypt::genRandomBytes(); - // The md5s look nicer than numbers. - return md5($mt . $rand); + return md5(microtime() . random_bytes(16)); } /** @@ -529,9 +540,9 @@ abstract class JOAuth1Client * * @return string The prepared signing key. * - * @since 13.1 + * @since 1.0 */ - private function _prepareSigningKey() + private function prepareSigningKey() { return $this->safeEncode($this->getOption('consumer_secret')) . '&' . $this->safeEncode(($this->token) ? $this->token['secret'] : ''); } @@ -542,37 +553,38 @@ abstract class JOAuth1Client * * @return array The decoded JSON response * - * @since 13.1 + * @since 1.0 */ abstract public function verifyCredentials(); /** - * Get an option from the JOauth1aClient instance. + * Get an option from the OAuth1 Client instance. * - * @param string $key The name of the option to get + * @param string $key The name of the option to get + * @param mixed $default Optional default value if the option does not exist * * @return mixed The option value * - * @since 13.1 + * @since 1.0 */ - public function getOption($key) + public function getOption($key, $default = null) { - return $this->options->get($key); + return isset($this->options[$key]) ? $this->options[$key] : $default; } /** - * Set an option for the JOauth1aClient instance. + * Set an option for the OAuth1 Client instance. * * @param string $key The name of the option to set * @param mixed $value The option value to set * - * @return JOAuth1Client This object for method chaining + * @return $this * - * @since 13.1 + * @since 1.0 */ public function setOption($key, $value) { - $this->options->set($key, $value); + $this->options[$key] = $value; return $this; } @@ -582,7 +594,7 @@ abstract class JOAuth1Client * * @return array The oauth token key and secret. * - * @since 13.1 + * @since 1.0 */ public function getToken() { @@ -594,9 +606,9 @@ abstract class JOAuth1Client * * @param array $token The access token key and secret. * - * @return JOAuth1Client This object for method chaining. + * @return $this * - * @since 13.1 + * @since 1.0 */ public function setToken($token) { diff --git a/libraries/vendor/joomla/oauth2/LICENSE b/libraries/vendor/joomla/oauth2/LICENSE new file mode 100644 index 00000000000..df50810b857 --- /dev/null +++ b/libraries/vendor/joomla/oauth2/LICENSE @@ -0,0 +1,340 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/libraries/vendor/joomla/oauth2/src/Client.php b/libraries/vendor/joomla/oauth2/src/Client.php new file mode 100644 index 00000000000..6de5cb3ef5b --- /dev/null +++ b/libraries/vendor/joomla/oauth2/src/Client.php @@ -0,0 +1,398 @@ +options = $options; + $this->http = $http instanceof Http ? $http : HttpFactory::getHttp($this->options); + $this->input = $input instanceof Input ? $input : ($application instanceof AbstractWebApplication ? $application->input : new Input); + $this->application = $application; + } + + /** + * Get the access token or redirect to the authentication URL. + * + * @return string The access token + * + * @since 1.0 + * @throws \RuntimeException + */ + public function authenticate() + { + if ($data['code'] = $this->input->get('code', false, 'raw')) + { + $data['grant_type'] = 'authorization_code'; + $data['redirect_uri'] = $this->getOption('redirecturi'); + $data['client_id'] = $this->getOption('clientid'); + $data['client_secret'] = $this->getOption('clientsecret'); + $response = $this->http->post($this->getOption('tokenurl'), $data); + + if (!($response->code >= 200 && $response->code < 400)) + { + throw new \RuntimeException('Error code ' . $response->code . ' received requesting access token: ' . $response->body . '.'); + } + + if (strpos($response->headers['Content-Type'], 'application/json') !== false) + { + $token = array_merge(json_decode($response->body, true), array('created' => time())); + } + else + { + parse_str($response->body, $token); + $token = array_merge($token, array('created' => time())); + } + + $this->setToken($token); + + return $token; + } + + if ($this->getOption('sendheaders')) + { + if (!($this->application instanceof AbstractWebApplication)) + { + throw new \RuntimeException('AbstractWebApplication object required for authentication process.'); + } + + $this->application->redirect($this->createUrl()); + } + + return false; + } + + /** + * Verify if the client has been authenticated + * + * @return boolean Is authenticated + * + * @since 1.0 + */ + public function isAuthenticated() + { + $token = $this->getToken(); + + if (!$token || !array_key_exists('access_token', $token)) + { + return false; + } + + if (array_key_exists('expires_in', $token) && $token['created'] + $token['expires_in'] < time() + 20) + { + return false; + } + + return true; + } + + /** + * Create the URL for authentication. + * + * @return string The URL for authentication + * + * @since 1.0 + * @throws \InvalidArgumentException + */ + public function createUrl() + { + if (!$this->getOption('authurl') || !$this->getOption('clientid')) + { + throw new \InvalidArgumentException('Authorization URL and client_id are required'); + } + + $url = $this->getOption('authurl'); + $url .= (strpos($url, '?') !== false) ? '&' : '?'; + $url .= 'response_type=code'; + $url .= '&client_id=' . urlencode($this->getOption('clientid')); + + if ($this->getOption('redirecturi')) + { + $url .= '&redirect_uri=' . urlencode($this->getOption('redirecturi')); + } + + if ($this->getOption('scope')) + { + $scope = is_array($this->getOption('scope')) ? implode(' ', $this->getOption('scope')) : $this->getOption('scope'); + $url .= '&scope=' . urlencode($scope); + } + + if ($this->getOption('state')) + { + $url .= '&state=' . urlencode($this->getOption('state')); + } + + if (is_array($this->getOption('requestparams'))) + { + foreach ($this->getOption('requestparams') as $key => $value) + { + $url .= '&' . $key . '=' . urlencode($value); + } + } + + return $url; + } + + /** + * Send a signed OAuth request. + * + * @param string $url The URL for the request + * @param mixed $data Either an associative array or a string to be sent with the request + * @param array $headers The headers to send with the request + * @param string $method The method with which to send the request + * @param integer $timeout The timeout for the request + * + * @return \Joomla\Http\Response + * + * @since 1.0 + * @throws \InvalidArgumentException + * @throws \RuntimeException + */ + public function query($url, $data = null, $headers = array(), $method = 'get', $timeout = null) + { + $token = $this->getToken(); + + if (array_key_exists('expires_in', $token) && $token['created'] + $token['expires_in'] < time() + 20) + { + if (!$this->getOption('userefresh')) + { + return false; + } + + $token = $this->refreshToken($token['refresh_token']); + } + + if (!$this->getOption('authmethod') || $this->getOption('authmethod') == 'bearer') + { + $headers['Authorization'] = 'Bearer ' . $token['access_token']; + } + elseif ($this->getOption('authmethod') == 'get') + { + if (strpos($url, '?')) + { + $url .= '&'; + } + else + { + $url .= '?'; + } + + $url .= $this->getOption('getparam') ? $this->getOption('getparam') : 'access_token'; + $url .= '=' . $token['access_token']; + } + + switch ($method) + { + case 'head': + case 'get': + case 'delete': + case 'trace': + $response = $this->http->$method($url, $headers, $timeout); + break; + + case 'post': + case 'put': + case 'patch': + $response = $this->http->$method($url, $data, $headers, $timeout); + break; + + default: + throw new \InvalidArgumentException('Unknown HTTP request method: ' . $method . '.'); + } + + if ($response->code < 200 || $response->code >= 400) + { + throw new \RuntimeException('Error code ' . $response->code . ' received requesting data: ' . $response->body . '.'); + } + + return $response; + } + + /** + * Get an option from the OAuth2 Client instance. + * + * @param string $key The name of the option to get + * @param mixed $default Optional default value, returned if the requested option does not exist. + * + * @return mixed The option value + * + * @since 1.0 + */ + public function getOption($key, $default = null) + { + return isset($this->options[$key]) ? $this->options[$key] : $default; + } + + /** + * Set an option for the OAuth2 Client instance. + * + * @param string $key The name of the option to set + * @param mixed $value The option value to set + * + * @return Client This object for method chaining + * + * @since 1.0 + */ + public function setOption($key, $value) + { + $this->options[$key] = $value; + + return $this; + } + + /** + * Get the access token from the Client instance. + * + * @return array The access token + * + * @since 1.0 + */ + public function getToken() + { + return $this->getOption('accesstoken'); + } + + /** + * Set an option for the Client instance. + * + * @param array $value The access token + * + * @return Client This object for method chaining + * + * @since 1.0 + */ + public function setToken($value) + { + if (is_array($value) && !array_key_exists('expires_in', $value) && array_key_exists('expires', $value)) + { + $value['expires_in'] = $value['expires']; + unset($value['expires']); + } + + $this->setOption('accesstoken', $value); + + return $this; + } + + /** + * Refresh the access token instance. + * + * @param string $token The refresh token + * + * @return array The new access token + * + * @since 1.0 + * @throws \Exception + * @throws \RuntimeException + */ + public function refreshToken($token = null) + { + if (!$this->getOption('userefresh')) + { + throw new \RuntimeException('Refresh token is not supported for this OAuth instance.'); + } + + if (!$token) + { + $token = $this->getToken(); + + if (!array_key_exists('refresh_token', $token)) + { + throw new \RuntimeException('No refresh token is available.'); + } + + $token = $token['refresh_token']; + } + + $data['grant_type'] = 'refresh_token'; + $data['refresh_token'] = $token; + $data['client_id'] = $this->getOption('clientid'); + $data['client_secret'] = $this->getOption('clientsecret'); + $response = $this->http->post($this->getOption('tokenurl'), $data); + + if (!($response->code >= 200 || $response->code < 400)) + { + throw new \Exception('Error code ' . $response->code . ' received refreshing token: ' . $response->body . '.'); + } + + if (strpos($response->headers['Content-Type'], 'application/json') !== false) + { + $token = array_merge(json_decode($response->body, true), array('created' => time())); + } + else + { + parse_str($response->body, $token); + $token = array_merge($token, array('created' => time())); + } + + $this->setToken($token); + + return $token; + } +} diff --git a/tests/unit/suites/libraries/joomla/oauth1/JOAuth1ClientTest.php b/tests/unit/suites/libraries/joomla/oauth1/JOAuth1ClientTest.php deleted file mode 100644 index 49f7e84adb0..00000000000 --- a/tests/unit/suites/libraries/joomla/oauth1/JOAuth1ClientTest.php +++ /dev/null @@ -1,369 +0,0 @@ -saveFactoryState(); - $this->backupServer = $_SERVER; - - $_SERVER['HTTP_HOST'] = 'example.com'; - $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0'; - $_SERVER['REQUEST_URI'] = '/index.php'; - $_SERVER['SCRIPT_NAME'] = '/index.php'; - - $key = "TEST_KEY"; - $secret = "TEST_SECRET"; - - $this->options = new Registry; - $this->client = $this->getMockBuilder('JHttp')->setMethods(array('get', 'post', 'delete', 'put'))->getMock(); - $this->input = new JInput(array()); - $this->application = $this->getMockWeb(); - - JFactory::$application = $this->application; - - $this->options->set('consumer_key', $key); - $this->options->set('consumer_secret', $secret); - $this->object = new JOAuth1ClientInspector($this->options, $this->client, $this->input, $this->application); - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - * - * @return void - */ - protected function tearDown() - { - $_SERVER = $this->backupServer; - unset($this->backupServer); - $this->restoreFactoryState(); - unset($this->options); - unset($this->client); - unset($this->input); - unset($this->application); - unset($this->object); - } - - /** - * Provides test data. - * - * @return array - * - * @since 13.1 - */ - public function seedAuthenticate() - { - // Token, fail and oauth version. - return array( - array(array('key' => 'valid', 'secret' => 'valid'), false, '1.0'), - array(null, false, '1.0'), - array(null, false, '1.0a'), - array(null, true, '1.0a') - ); - } - - /** - * Tests the authenticate method - * - * @param array $token The passed token. - * @param boolean $fail Mark if should fail or not. - * @param string $version Specify oauth version 1.0 or 1.0a. - * - * @return void - * - * @dataProvider seedAuthenticate - * @since 13.1 - */ - public function testAuthenticate($token, $fail, $version) - { - // Already got some credentials stored? - if (!is_null($token)) - { - $this->object->setToken($token); - $result = $this->object->authenticate(); - $this->assertEquals($result, $token); - } - else - { - $this->object->setOption('requestTokenURL', 'https://example.com/request_token'); - $this->object->setOption('authoriseURL', 'https://example.com/authorize'); - $this->object->setOption('accessTokenURL', 'https://example.com/access_token'); - - // Request token. - $returnData = new stdClass; - $returnData->code = 200; - $returnData->body = 'oauth_token=token&oauth_token_secret=secret&oauth_callback_confirmed=true'; - - $this->client->expects($this->at(0)) - ->method('post') - ->with($this->object->getOption('requestTokenURL')) - ->willReturn($returnData); - - $input = TestReflection::getValue($this->object, 'input'); - TestReflection::setValue($this->object, 'input', $input); - - if (strcmp($version, '1.0a') === 0) - { - $this->object->setOption('callback', 'TEST_URL'); - } - $this->object->authenticate(); - - $token = $this->object->getToken(); - $this->assertEquals($token['key'], 'token'); - $this->assertEquals($token['secret'], 'secret'); - - // Access token. - $input = TestReflection::getValue($this->object, 'input'); - - if (strcmp($version, '1.0a') === 0) - { - TestReflection::setValue($this->object, 'version', $version); - $data = array('oauth_verifier' => 'verifier', 'oauth_token' => 'token'); - } - else - { - TestReflection::setValue($this->object, 'version', $version); - $data = array('oauth_token' => 'token'); - } - TestReflection::setValue($input, 'data', $data); - - // Get mock session - $mockSession = $this->getMockBuilder('JSession') - ->setMethods(['get']) - ->disableOriginalConstructor() - ->getMock(); - - if ($fail) - { - $mockSession->expects($this->at(0)) - ->method('get') - ->with('oauth_token.key', null) - ->willReturn('bad'); - - $mockSession->expects($this->at(1)) - ->method('get') - ->with('oauth_token.secret', null) - ->willReturn('session'); - - $this->application = $this->getMockWeb(['session' => $mockSession]); - - JFactory::$application = $this->application; - - TestReflection::setValue($this->object, 'application', $this->application); - - $this->setExpectedException('DomainException'); - - $this->object->authenticate(); - } - - $mockSession->expects($this->at(0)) - ->method('get') - ->with('oauth_token.key', null) - ->willReturn('token'); - - $mockSession->expects($this->at(1)) - ->method('get') - ->with('oauth_token.secret', null) - ->willReturn('secret'); - - $this->application = $this->getMockWeb(['session' => $mockSession]); - - JFactory::$application = $this->application; - - TestReflection::setValue($this->object, 'application', $this->application); - - $returnData = new stdClass; - $returnData->code = 200; - $returnData->body = 'oauth_token=token_key&oauth_token_secret=token_secret'; - - $this->client->expects($this->at(0)) - ->method('post') - ->with($this->object->getOption('accessTokenURL')) - ->willReturn($returnData); - - $result = $this->object->authenticate(); - - $this->assertEquals($result['key'], 'token_key'); - $this->assertEquals($result['secret'], 'token_secret'); - } - } - - /** - * Tests the _generateRequestToken method - failure - * - * @return void - * - * @since 13.1 - * @expectedException DomainException - */ - public function testGenerateRequestTokenFailure() - { - $this->object->setOption('requestTokenURL', 'https://example.com/request_token'); - - $returnData = new stdClass; - $returnData->code = 200; - $returnData->body = 'oauth_token=token&oauth_token_secret=secret&oauth_callback_confirmed=false'; - - $this->client->expects($this->at(0)) - ->method('post') - ->with($this->object->getOption('requestTokenURL')) - ->will($this->returnValue($returnData)); - - TestReflection::invoke($this->object, '_generateRequestToken'); - } - - /** - * Provides test data. - * - * @return array - * - * @since 13.1 - */ - public function seedOauthRequest() - { - // Method - return array( - array('GET'), - array('PUT'), - array('DELETE') - ); - } - - /** - * Tests the oauthRequest method - * - * @param string $method The request method. - * - * @dataProvider seedOauthRequest - * @return void - * - * @since 13.1 - */ - public function testOauthRequest($method) - { - $returnData = new stdClass; - $returnData->code = 200; - $returnData->body = $this->sampleString; - - if (strcmp($method, 'PUT') === 0) - { - $data = array('key1' => 'value1', 'key2' => 'value2'); - $this->client->expects($this->at(0)) - ->method($method, $data) - ->with('www.example.com') - ->will($this->returnValue($returnData)); - - $this->assertThat( - $this->object->oauthRequest('www.example.com', $method, array('oauth_token' => '1235'), $data, array('Content-Type' => 'multipart/form-data')), - $this->equalTo($returnData) - ); - - } - else - { - $this->client->expects($this->at(0)) - ->method($method) - ->with('www.example.com') - ->will($this->returnValue($returnData)); - - $this->assertThat( - $this->object->oauthRequest('www.example.com', $method, array('oauth_token' => '1235'), array(), array('Content-Type' => 'multipart/form-data')), - $this->equalTo($returnData) - ); - } - } - - /** - * Tests the safeEncode - * - * @return void - * - * @since 13.1 - */ - public function testSafeEncodeEmpty() - { - $this->assertThat( - $this->object->safeEncode(null), - $this->equalTo('') - ); - } -} diff --git a/tests/unit/suites/libraries/joomla/oauth1/stubs/JOAuth1ClientInspector.php b/tests/unit/suites/libraries/joomla/oauth1/stubs/JOAuth1ClientInspector.php deleted file mode 100644 index f283d03a026..00000000000 --- a/tests/unit/suites/libraries/joomla/oauth1/stubs/JOAuth1ClientInspector.php +++ /dev/null @@ -1,55 +0,0 @@ -token['key'], 'valid')) - { - return true; - } - - return false; - } - - /** - * Method to validate a response. - * - * @param string $url The request URL. - * @param JHttpResponse $response The response to validate. - * - * @return void - * - * @since 13.1 - * @throws DomainException - */ - public function validateResponse($url, $response) - { - if ($response->code < 200 || $response->code > 399) - { - throw new DomainException($response->body); - } - } -} diff --git a/tests/unit/suites/libraries/joomla/oauth2/JOauth2ClientTest.php b/tests/unit/suites/libraries/joomla/oauth2/JOauth2ClientTest.php deleted file mode 100644 index ea8739ba3a8..00000000000 --- a/tests/unit/suites/libraries/joomla/oauth2/JOauth2ClientTest.php +++ /dev/null @@ -1,463 +0,0 @@ -backupServer = $_SERVER; - $_SERVER['HTTP_HOST'] = 'mydomain.com'; - $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0'; - $_SERVER['REQUEST_URI'] = '/index.php'; - $_SERVER['SCRIPT_NAME'] = '/index.php'; - - $this->options = new Registry; - $this->http = $this->getMockBuilder('JHttp') - ->setMethods(array('head', 'get', 'delete', 'trace', 'post', 'put', 'patch')) - ->setConstructorArgs(array($this->options)) - ->getMock(); - $array = array(); - $this->input = new JInput($array); - $this->application = $this->getMockWeb(); - $this->object = new JOAuth2Client($this->options, $this->http, $this->input, $this->application); - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - * - * @return void - * - * @see \PHPUnit\Framework\TestCase::tearDown() - * @since 3.6 - */ - protected function tearDown() - { - $_SERVER = $this->backupServer; - unset($this->backupServer); - unset($this->options); - unset($this->input); - unset($this->http); - unset($this->application); - unset($this->object); - parent::tearDown(); - } - - /** - * Tests the auth method - * - * @group JOAuth2 - * @return void - */ - public function testAuth() - { - $this->object->setOption('authurl', 'https://accounts.google.com/o/oauth2/auth'); - $this->object->setOption('clientid', '01234567891011.apps.googleusercontent.com'); - $this->object->setOption('scope', array('https://www.googleapis.com/auth/adsense', 'https://www.googleapis.com/auth/calendar')); - $this->object->setOption('redirecturi', 'http://localhost/oauth'); - $this->object->setOption('requestparams', array('access_type' => 'offline', 'approval_prompt' => 'auto')); - $this->object->setOption('sendheaders', true); - - $this->object->authenticate(); - $this->assertEquals(0, static::$closed); - - $this->object->setOption('tokenurl', 'https://accounts.google.com/o/oauth2/token'); - $this->object->setOption('clientsecret', 'jeDs8rKw_jDJW8MMf-ff8ejs'); - $this->input->set('code', '4/wEr_dK8SDkjfpwmc98KejfiwJP-f4wm.kdowmnr82jvmeisjw94mKFIJE48mcEM'); - - $this->http->expects($this->once())->method('post')->will($this->returnCallback('encodedGrantOauthCallback')); - $result = $this->object->authenticate(); - $this->assertEquals('accessvalue', $result['access_token']); - $this->assertEquals('refreshvalue', $result['refresh_token']); - $this->assertEquals(3600, $result['expires_in']); - $this->assertLessThanOrEqual(1, time() - $result['created']); - } - - /** - * Tests the auth method with JSON data - * - * @group JOAuth2 - * @return void - */ - public function testAuthJson() - { - $this->object->setOption('tokenurl', 'https://accounts.google.com/o/oauth2/token'); - $this->object->setOption('clientsecret', 'jeDs8rKw_jDJW8MMf-ff8ejs'); - $this->input->set('code', '4/wEr_dK8SDkjfpwmc98KejfiwJP-f4wm.kdowmnr82jvmeisjw94mKFIJE48mcEM'); - - $this->http->expects($this->once())->method('post')->will($this->returnCallback('jsonGrantOauthCallback')); - $result = $this->object->authenticate(); - $this->assertEquals('accessvalue', $result['access_token']); - $this->assertEquals('refreshvalue', $result['refresh_token']); - $this->assertEquals(3600, $result['expires_in']); - $this->assertLessThanOrEqual(1, time() - $result['created']); - } - - /** - * Tests the isauth method - * - * @group JOAuth2 - * @return void - */ - public function testIsAuth() - { - $this->assertEquals(false, $this->object->isAuthenticated()); - - $token['access_token'] = 'accessvalue'; - $token['refresh_token'] = 'refreshvalue'; - $token['created'] = time(); - $token['expires_in'] = 3600; - $this->object->setToken($token); - - $this->assertTrue($this->object->isAuthenticated()); - - $token['created'] = time() - 4000; - $token['expires_in'] = 3600; - $this->object->setToken($token); - - $this->assertFalse($this->object->isAuthenticated()); - } - - /** - * Tests the auth method - * - * @group JOAuth2 - * @return void - */ - public function testCreateUrl() - { - $this->object->setOption('authurl', 'https://accounts.google.com/o/oauth2/auth'); - $this->object->setOption('clientid', '01234567891011.apps.googleusercontent.com'); - $this->object->setOption('scope', array('https://www.googleapis.com/auth/adsense', 'https://www.googleapis.com/auth/calendar')); - $this->object->setOption('state', '123456'); - $this->object->setOption('redirecturi', 'http://localhost/oauth'); - $this->object->setOption('requestparams', array('access_type' => 'offline', 'approval_prompt' => 'auto')); - - $url = $this->object->createUrl(); - $expected = 'https://accounts.google.com/o/oauth2/auth?response_type=code'; - $expected .= '&client_id=01234567891011.apps.googleusercontent.com'; - $expected .= '&redirect_uri=http%3A%2F%2Flocalhost%2Foauth'; - $expected .= '&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadsense'; - $expected .= '+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar'; - $expected .= '&state=123456&access_type=offline&approval_prompt=auto'; - $this->assertEquals($expected, $url); - } - - /** - * Tests the auth method - * - * @group JOAuth2 - * @return void - */ - public function testQuery() - { - $token['access_token'] = 'accessvalue'; - $token['refresh_token'] = 'refreshvalue'; - $token['created'] = time() - 1800; - $token['expires_in'] = 600; - $this->object->setToken($token); - - $result = $this->object->query('https://www.googleapis.com/auth/calendar', array('param' => 'value'), array(), 'get'); - $this->assertFalse($result); - - $token['expires_in'] = 3600; - $this->object->setToken($token); - - $this->http->expects($this->once())->method('post')->will($this->returnCallback('queryOauthCallback')); - $result = $this->object->query('https://www.googleapis.com/auth/calendar', array('param' => 'value'), array(), 'post'); - $this->assertEquals($result->body, 'Lorem ipsum dolor sit amet.'); - $this->assertEquals(200, $result->code); - - $this->object->setOption('authmethod', 'get'); - $this->http->expects($this->once())->method('get')->will($this->returnCallback('getOauthCallback')); - $result = $this->object->query('https://www.googleapis.com/auth/calendar', array('param' => 'value'), array(), 'get'); - $this->assertEquals($result->body, 'Lorem ipsum dolor sit amet.'); - $this->assertEquals(200, $result->code); - } - - /** - * Tests the setOption method - * - * @group JOAuth2 - * @return void - */ - public function testSetOption() - { - $this->object->setOption('key', 'value'); - - $this->assertThat( - $this->options->get('key'), - $this->equalTo('value') - ); - } - - /** - * Tests the getOption method - * - * @group JOAuth2 - * @return void - */ - public function testGetOption() - { - $this->options->set('key', 'value'); - - $this->assertThat( - $this->object->getOption('key'), - $this->equalTo('value') - ); - } - - /** - * Tests the setToken method - * - * @group JOAuth2 - * @return void - */ - public function testSetToken() - { - $this->object->setToken(array('access_token' => 'RANDOM STRING OF DATA')); - - $this->assertThat( - $this->options->get('accesstoken'), - $this->equalTo(array('access_token' => 'RANDOM STRING OF DATA')) - ); - - $this->object->setToken(array('access_token' => 'RANDOM STRING OF DATA', 'expires_in' => 3600)); - - $this->assertThat( - $this->options->get('accesstoken'), - $this->equalTo(array('access_token' => 'RANDOM STRING OF DATA', 'expires_in' => 3600)) - ); - - $this->object->setToken(array('access_token' => 'RANDOM STRING OF DATA', 'expires' => 3600)); - - $this->assertThat( - $this->options->get('accesstoken'), - $this->equalTo(array('access_token' => 'RANDOM STRING OF DATA', 'expires_in' => 3600)) - ); - } - - /** - * Tests the getToken method - * - * @group JOAuth2 - * @return void - */ - public function testGetToken() - { - $this->options->set('accesstoken', array('access_token' => 'RANDOM STRING OF DATA')); - - $this->assertThat( - $this->object->getToken(), - $this->equalTo(array('access_token' => 'RANDOM STRING OF DATA')) - ); - } - - /** - * Tests the refreshToken method - * - * @group JOAuth2 - * @return void - */ - public function testRefreshToken() - { - $this->object->setOption('tokenurl', 'https://accounts.google.com/o/oauth2/token'); - $this->object->setOption('clientid', '01234567891011.apps.googleusercontent.com'); - $this->object->setOption('clientsecret', 'jeDs8rKw_jDJW8MMf-ff8ejs'); - $this->object->setOption('redirecturi', 'http://localhost/oauth'); - $this->object->setOption('userefresh', true); - $this->object->setToken(array('access_token' => 'RANDOM STRING OF DATA', 'expires' => 3600, 'refresh_token' => ' RANDOM STRING OF DATA')); - - $this->http->expects($this->once())->method('post')->will($this->returnCallback('encodedGrantOauthCallback')); - $result = $this->object->refreshToken(); - $this->assertEquals('accessvalue', $result['access_token']); - $this->assertEquals('refreshvalue', $result['refresh_token']); - $this->assertEquals(3600, $result['expires_in']); - $this->assertLessThanOrEqual(1, time() - $result['created']); - } - - /** - * Tests the refreshToken method with JSON - * - * @group JOAuth2 - * @return void - */ - public function testRefreshTokenJson() - { - $this->object->setOption('tokenurl', 'https://accounts.google.com/o/oauth2/token'); - $this->object->setOption('clientid', '01234567891011.apps.googleusercontent.com'); - $this->object->setOption('clientsecret', 'jeDs8rKw_jDJW8MMf-ff8ejs'); - $this->object->setOption('redirecturi', 'http://localhost/oauth'); - $this->object->setOption('userefresh', true); - $this->object->setToken(array('access_token' => 'RANDOM STRING OF DATA', 'expires' => 3600, 'refresh_token' => ' RANDOM STRING OF DATA')); - - $this->http->expects($this->once())->method('post')->will($this->returnCallback('jsonGrantOauthCallback')); - $result = $this->object->refreshToken(); - $this->assertEquals('accessvalue', $result['access_token']); - $this->assertEquals('refreshvalue', $result['refresh_token']); - $this->assertEquals(3600, $result['expires_in']); - $this->assertLessThanOrEqual(1, time() - $result['created']); - } - - /** - * @param integer $code The exit code (optional; default is 0). - */ - public static function mockClose($code = 0) - { - self::$closed = $code; - } -} - -/** - * Dummy - * - * @param string $url Path to the resource. - * @param mixed $data Either an associative array or a string to be sent with the request. - * @param array $headers An array of name-value pairs to include in the header of the request - * @param integer $timeout Read timeout in seconds. - * - * @return JHttpResponse - * - * @since 12.3 - */ -function encodedGrantOauthCallback($url, $data, array $headers = null, $timeout = null) -{ - $response = new stdClass; - - $response->code = 200; - $response->headers = array('Content-Type' => 'x-www-form-urlencoded'); - $response->body = 'access_token=accessvalue&refresh_token=refreshvalue&expires_in=3600'; - - return $response; -} - -/** - * Dummy - * - * @param string $url Path to the resource. - * @param mixed $data Either an associative array or a string to be sent with the request. - * @param array $headers An array of name-value pairs to include in the header of the request - * @param integer $timeout Read timeout in seconds. - * - * @return JHttpResponse - * - * @since 12.3 - */ -function jsonGrantOauthCallback($url, $data, array $headers = null, $timeout = null) -{ - - $response = new stdClass; - - $response->code = 200; - $response->headers = array('Content-Type' => 'application/json'); - $response->body = '{"access_token":"accessvalue","refresh_token":"refreshvalue","expires_in":3600}'; - - return $response; -} - -/** - * Dummy - * - * @param string $url Path to the resource. - * @param mixed $data Either an associative array or a string to be sent with the request. - * @param array $headers An array of name-value pairs to include in the header of the request - * @param integer $timeout Read timeout in seconds. - * - * @return JHttpResponse - * - * @since 12.3 - */ -function queryOauthCallback($url, $data, array $headers = null, $timeout = null) -{ - $response = new stdClass; - - $response->code = 200; - $response->headers = array('Content-Type' => 'text/html'); - $response->body = 'Lorem ipsum dolor sit amet.'; - - return $response; -} - -/** - * Dummy - * - * @param string $url Path to the resource. - * @param array $headers An array of name-value pairs to include in the header of the request. - * @param integer $timeout Read timeout in seconds. - * - * @return JHttpResponse - * - * @since 12.3 - */ -function getOauthCallback($url, array $headers = null, $timeout = null) -{ - $response = new stdClass; - - $response->code = 200; - $response->headers = array('Content-Type' => 'text/html'); - $response->body = 'Lorem ipsum dolor sit amet.'; - - return $response; -}