![openauth-icon](https://user-images.githubusercontent.com/81188/87538212-25d2ef00-c69c-11ea-87a7-b967826cb669.png)
-### OpenAuth.dev Provider for WoltLab Suite 5
+### OpenAuth.dev Provider for WoltLab Suite
@@ -29,8 +29,8 @@ WIP
You need:
-- A WoltLab Suite installation (5.2.0 or newer)
-- PHP (7.0.22 or newer)
+- A WoltLab Suite installation (5.4.0 or newer)
+- PHP (7.2.24 or newer)
- Activated `fsockopen` (including support for SSL connections) on your webspace/server
- A free user account on [OpenAuth.dev](https://www.openauth.dev), which has been authorized as a developer
diff --git a/constants.php b/constants.php
index 68c6837..797d0c5 100644
--- a/constants.php
+++ b/constants.php
@@ -1,12 +1,5 @@
-
+
diff --git a/files/acp/database/install_dev.openauth.wsc.login.php b/files/acp/database/install_dev.openauth.wsc.login.php
new file mode 100644
index 0000000..e2873a8
--- /dev/null
+++ b/files/acp/database/install_dev.openauth.wsc.login.php
@@ -0,0 +1,41 @@
+columns([
+ IntDatabaseTableColumn::create('openAuthID'),
+ NotNullVarchar255DatabaseTableColumn::create('openAuthAvatar'),
+ TinyintDatabaseTableColumn::create('enableOpenAuthAvatar')
+ ->length(1)
+ ->notNull()
+ ->defaultValue(0),
+ ]),
+];
diff --git a/files/lib/action/OpenAuthAction.class.php b/files/lib/action/OpenAuthAction.class.php
index b15c67d..e0b0135 100644
--- a/files/lib/action/OpenAuthAction.class.php
+++ b/files/lib/action/OpenAuthAction.class.php
@@ -26,200 +26,249 @@
namespace wcf\action;
use Exception;
+use Psr\Http\Client\ClientExceptionInterface;
use wcf\data\user\User;
use wcf\data\user\UserEditor;
-use wcf\system\exception\IllegalLinkException;
+use wcf\form\RegisterForm;
use wcf\system\exception\NamedUserException;
use wcf\system\exception\PermissionDeniedException;
-use wcf\system\exception\SystemException;
use wcf\system\openauth\OpenAuthAPI;
use wcf\system\request\LinkHandler;
-use wcf\system\user\authentication\UserAuthenticationFactory;
+use wcf\system\user\authentication\oauth\exception\StateValidationException;
use wcf\system\WCF;
use wcf\util\HeaderUtil;
-use function hash_equals;
+use function wcf\functions\exception\logThrowable;
class OpenAuthAction extends AbstractAction
{
/**
* @inheritDoc
*/
- public $neededModules = [
- 'OPENAUTH_CLIENT_ID',
- 'OPENAUTH_CLIENT_SECRET'
- ];
+ public $neededModules = ['OPENAUTH_CLIENT_ID', 'OPENAUTH_CLIENT_SECRET'];
+
+ /**
+ * @var string
+ */
+ private const STATE = self::class . "\0state_parameter";
/**
* @inheritDoc
*
- * @throws IllegalLinkException
+ * @throws \wcf\system\exception\PermissionDeniedException
*/
- public function readParameters() {
+ public function readParameters(): void
+ {
parent::readParameters();
if (WCF::getSession()->spiderID) {
- throw new IllegalLinkException();
+ throw new PermissionDeniedException();
}
}
/**
* @inheritDoc
*
- * @throws IllegalLinkException
- * @throws NamedUserException
- * @throws PermissionDeniedException
- * @throws SystemException
- * @throws Exception
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ * @throws \wcf\system\exception\NamedUserException
+ * @throws \wcf\system\exception\PermissionDeniedException
*/
- public function execute()
+ public function execute(): void
{
parent::execute();
- if (isset($_REQUEST['code'])) {
- // check state
- if (
- empty($_REQUEST['state']) ||
- !WCF::getSession()->getVar('__openauthInit') ||
- !hash_equals($_REQUEST['state'], WCF::getSession()->getVar('__openauthInit'))
- ) {
- throw new IllegalLinkException();
- }
-
- WCF::getSession()->unregister('__openauthInit');
-
- // check OAuth code
- $tokenInfo = OpenAuthAPI::getInstance()->checkOAuthCode($_REQUEST['code']);
-
- if ($tokenInfo === null) {
- throw new NamedUserException(WCF::getLanguage()->getDynamicVariable(
- 'wcf.user.3rdparty.openauth.connect.error.configuration')
- );
- }
-
- if (empty($tokenInfo['access_token'])) {
- throw new NamedUserException(WCF::getLanguage()->get(
- 'wcf.user.3rdparty.openauth.connect.error.invalid')
- );
- }
-
- // get user data
- $userData = OpenAuthAPI::getInstance()->getUserInfo($tokenInfo['access_token']);
-
- if ($userData === null) {
- throw new NamedUserException(WCF::getLanguage()->getDynamicVariable(
- 'wcf.user.3rdparty.openauth.connect.error.configuration')
- );
- }
-
- if (empty($userData['sub'])) {
- throw new NamedUserException(WCF::getLanguage()->get(
- 'wcf.user.3rdparty.openauth.connect.error.invalid')
- );
- }
-
- $openAuthUserID = $userData['sub'];
- $openAuthUsername = (!empty($userData['nickname'])) ? $userData['nickname'] : '';
- $openAuthMail = (!empty($userData['email'])) ? $userData['email'] : '';
- $openAuthAvatar = (!empty($userData['picture'])) ? $userData['picture'] : null;
+ try {
+ if (isset($_GET['code'])) {
+ $tokenInfo = OpenAuthAPI::getInstance()->checkOAuthCode($_REQUEST['code']);
- $user = User::getUserByAuthData('openauth:' . $openAuthUserID);
+ if ($tokenInfo === null) {
+ throw new NamedUserException(
+ WCF::getLanguage()->getDynamicVariable('wcf.user.3rdparty.openauth.connect.error.configuration')
+ );
+ }
- if (WCF::getUser()->userID) {
- // user is signed in and would connect
- if ($user->userID) {
- // another account is connected to this openauth account
- throw new NamedUserException(WCF::getLanguage()->getDynamicVariable(
- 'wcf.user.3rdparty.openauth.connect.error.inuse')
+ if (empty($tokenInfo['access_token'])) {
+ throw new NamedUserException(
+ WCF::getLanguage()->get('wcf.user.3rdparty.openauth.connect.error.invalid')
);
}
- WCF::getSession()->register('__openAuthUsername', $openAuthUsername);
- WCF::getSession()->register('__openAuthData', $userData);
+ $this->processUser($this->getUser($tokenInfo['access_token']));
+ } elseif (isset($_GET['error'])) {
+ $this->handleError($_GET['error']);
+ } else {
+ $this->initiate();
+ }
+ } catch (NamedUserException $e) {
+ throw $e;
+ } catch (StateValidationException $e) {
+ throw new NamedUserException(
+ WCF::getLanguage()->getDynamicVariable(
+ 'wcf.user.3rdparty.login.error.stateValidation'
+ )
+ );
+ } catch (Exception $e) {
+ $exceptionID = logThrowable($e);
+
+ $type = 'genericException';
+ if ($e instanceof ClientExceptionInterface) {
+ $type = 'httpError';
+ }
- HeaderUtil::redirect(LinkHandler::getInstance()->getLink('AccountManagement') . '#3rdParty');
+ throw new NamedUserException(
+ WCF::getLanguage()->getDynamicVariable(
+ 'wcf.user.3rdparty.login.error.' . $type,
+ [
+ 'exceptionID' => $exceptionID,
+ ]
+ )
+ );
+ }
+ }
- $this->executed();
+ /**
+ * Initiates the OAuth flow.
+ *
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ * @throws \wcf\system\exception\NamedUserException
+ * @throws \wcf\system\exception\SystemException
+ */
+ protected function initiate(): void
+ {
+ $token = OpenAuthAPI::getInstance()->generateRandom();
+ $scopes = OpenAuthAPI::getInstance()->getScopes();
+ $authorizationUri = OpenAuthAPI::getInstance()->getAuthorizationURI($token, $scopes);
- exit;
- }
+ WCF::getSession()->register(self::STATE, $token);
- if ($user->userID) {
- $userAuthentication = UserAuthenticationFactory::getInstance()->getUserAuthentication();
+ if ($scopes === null) {
+ throw new NamedUserException(
+ WCF::getLanguage()->getDynamicVariable('wcf.user.3rdparty.openauth.connect.error.configuration')
+ );
+ }
- if (null === $userAuthentication) {
- throw new SystemException('No valid authentication instance found.');
- }
+ if ($authorizationUri === null) {
+ throw new NamedUserException(
+ WCF::getLanguage()->getDynamicVariable('wcf.user.3rdparty.openauth.connect.error.configuration')
+ );
+ }
- // login
- if ($userAuthentication->supportsPersistentLogins()) {
- $password = OpenAuthAPI::getInstance()->generateRandom();
- $updateData = [
- 'openAuthAvatar' => $openAuthAvatar,
- 'password' => $password
- ];
+ HeaderUtil::redirect($authorizationUri);
- $userEditor = new UserEditor($user);
- $userEditor->update($updateData);
+ exit;
+ }
- // reload user to retrieve salt
- $user = new User($user->userID);
+ /**
+ * @throws \wcf\system\exception\NamedUserException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ * @throws \wcf\system\exception\SystemException
+ */
+ protected function getUser(string $accessToken): array
+ {
+ $userData = OpenAuthAPI::getInstance()->getUserInfo($accessToken);
- $userAuthentication->storeAccessData($user, $user->username, $password);
- }
+ if ($userData === null) {
+ throw new NamedUserException(
+ WCF::getLanguage()->getDynamicVariable('wcf.user.3rdparty.openauth.connect.error.configuration')
+ );
+ }
- WCF::getSession()->changeUser($user);
- WCF::getSession()->update();
+ if (empty($userData['sub'])) {
+ throw new NamedUserException(
+ WCF::getLanguage()->get('wcf.user.3rdparty.openauth.connect.error.invalid')
+ );
+ }
- HeaderUtil::redirect(LinkHandler::getInstance()->getLink());
+ return $userData;
+ }
- $this->executed();
+ /**
+ * @throws \wcf\system\exception\NamedUserException
+ * @throws \wcf\system\exception\SystemException
+ */
+ protected function processUser(array $userData): void
+ {
+ $user = User::getUserByAuthData('openauth:' . $userData['sub']);
- exit;
+ if ($user->userID) {
+ if (WCF::getUser()->userID) {
+ // This account belongs to an existing user, but we are already logged in.
+ // This can't be handled.
+ throw new NamedUserException(
+ WCF::getLanguage()->getDynamicVariable('wcf.user.3rdparty.facebook.connect.error.inuse')
+ );
}
- // register
- WCF::getSession()->register('__3rdPartyProvider', 'openauth');
- WCF::getSession()->register('__openAuthData', $userData);
- WCF::getSession()->register('__username', $openAuthUsername);
- WCF::getSession()->register('__email', $openAuthMail);
-
- if (REGISTER_USE_CAPTCHA) {
- WCF::getSession()->register('noRegistrationCaptcha', true);
+ // This account belongs to an existing user, we are not logged in.
+ // Perform the login, and update avatar, if there's one.
+ if (!empty($userData['picture'])) {
+ (new UserEditor($user))->update([
+ 'openAuthAvatar' => $userData['picture'],
+ ]);
}
+ WCF::getSession()->changeUser($user);
WCF::getSession()->update();
-
- HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Register'));
-
- $this->executed();
+ HeaderUtil::redirect(LinkHandler::getInstance()->getLink());
exit;
}
- // user declined or another error occured
- if (isset($_GET['error'])) {
- throw new NamedUserException(WCF::getLanguage()->getDynamicVariable('wcf.user.3rdparty.openauth.connect.error.' . $_GET['error']));
- }
+ WCF::getSession()->register('__3rdPartyProvider', 'facebook');
- $state = OpenAuthAPI::getInstance()->generateRandom();
- $scopes = OpenAuthAPI::getInstance()->getScopes();
- $authorizationUri = OpenAuthAPI::getInstance()->getAuthorizationURI($state, $scopes);
+ if (WCF::getUser()->userID) {
+ // This account does not belong to anyone, and we are already logged in.
+ // Thus, we want to connect this account.
+ WCF::getSession()->register('__oauthUser', $userData);
- WCF::getSession()->register('__openauthInit', $state);
+ HeaderUtil::redirect(LinkHandler::getInstance()->getLink('AccountManagement') . '#3rdParty');
- if ($scopes === null) {
- throw new NamedUserException(WCF::getLanguage()->getDynamicVariable('wcf.user.3rdparty.openauth.connect.error.configuration'));
+ exit;
}
- if ($authorizationUri === null) {
- throw new NamedUserException(WCF::getLanguage()->getDynamicVariable('wcf.user.3rdparty.openauth.connect.error.configuration'));
- }
+ // This account does not belong to anyone, and we are not logged in.
+ // Thus, we want to connect this account to a newly registered user.
+ WCF::getSession()->register('__oauthUser', $userData);
+ WCF::getSession()->register('__username', (!empty($userData['nickname'])) ? $userData['nickname'] : '');
+ WCF::getSession()->register('__email', (!empty($userData['email'])) ? $userData['email'] : '');
- HeaderUtil::redirect($authorizationUri);
+ // We assume that bots won't register an external account first, so
+ // we skip the captcha.
+ WCF::getSession()->register('noRegistrationCaptcha', true);
+ WCF::getSession()->update();
- $this->executed();
+ HeaderUtil::redirect(LinkHandler::getInstance()->getControllerLink(RegisterForm::class));
exit;
}
+
+ /**
+ * @throws \wcf\system\exception\NamedUserException
+ */
+ protected function handleError(string $error): void
+ {
+ throw new NamedUserException(WCF::getLanguage()->getDynamicVariable('wcf.user.3rdparty.login.error.' . $error));
+ }
+
+ /**
+ * Validates the state parameter.
+ */
+ protected function validateState(): void
+ {
+ try {
+ if (!isset($_GET['state'])) {
+ throw new StateValidationException('Missing state parameter');
+ }
+
+ if (!($sessionState = WCF::getSession()->getVar(self::STATE))) {
+ throw new StateValidationException('Missing state in session');
+ }
+
+ if (!\hash_equals($sessionState, (string)$_GET['state'])) {
+ throw new StateValidationException('Mismatching state');
+ }
+ } finally {
+ WCF::getSession()->unregister(self::STATE);
+ }
+ }
}
diff --git a/files/lib/action/OpenAuthAvatarDownloadAction.class.php b/files/lib/action/OpenAuthAvatarDownloadAction.class.php
index 2f2045c..ef160de 100644
--- a/files/lib/action/OpenAuthAvatarDownloadAction.class.php
+++ b/files/lib/action/OpenAuthAvatarDownloadAction.class.php
@@ -25,29 +25,33 @@
namespace wcf\action;
+use DomainException;
+use GuzzleHttp\Exception\TransferException;
+use GuzzleHttp\Psr7\Request;
+use GuzzleHttp\RequestOptions;
+use RuntimeException;
use wcf\data\user\avatar\OpenAuthAvatar;
use wcf\data\user\avatar\UserAvatar;
use wcf\data\user\User;
use wcf\data\user\UserEditor;
use wcf\system\exception\IllegalLinkException;
-use wcf\system\exception\PermissionDeniedException;
-use wcf\system\exception\SystemException;
+use wcf\system\io\File;
+use wcf\system\io\http\RedirectGuard;
+use wcf\system\io\HttpFactory;
use wcf\util\FileUtil;
-use wcf\util\HTTPRequest;
-
-use function file_exists;
-use function file_put_contents;
-use function header;
-use function in_array;
-use function mb_strtolower;
-use function md5;
-use function parse_url;
-use function pathinfo;
-use function readfile;
-use function sprintf;
+use wcf\util\Url;
+
+use const IMAGETYPE_GIF;
+use const IMAGETYPE_JPEG;
+use const IMAGETYPE_PNG;
class OpenAuthAvatarDownloadAction extends AbstractAction
{
+ /**
+ * @inheritDoc
+ */
+ public $neededModules = ['OPENAUTH_CLIENT_ID', 'OPENAUTH_CLIENT_SECRET'];
+
/**
* @var int
*/
@@ -68,7 +72,7 @@ class OpenAuthAvatarDownloadAction extends AbstractAction
*
* @throws IllegalLinkException
*/
- public function readParameters()
+ public function readParameters(): void
{
parent::readParameters();
@@ -86,88 +90,139 @@ public function readParameters()
/**
* @inheritDoc
*
- * @throws PermissionDeniedException
- * @throws SystemException
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ * @throws \wcf\system\exception\PermissionDeniedException
+ * @throws \wcf\system\exception\SystemException
*/
- public function execute()
+ public function execute(): void
{
parent::execute();
if (!empty($this->user->openAuthAvatar) && OPENAUTH_CLIENT_ID && OPENAUTH_CLIENT_SECRET) {
- $urlParsed = parse_url($this->user->openAuthAvatar);
- $pathInfo = pathinfo($urlParsed['path']);
-
- if (in_array($pathInfo['extension'], ['jpg', 'png', 'gif'])) {
- $contentType = 'image/png';
- $extension = 'png';
+ $pathInfo = Url::parse($this->user->openAuthAvatar)['path'];
+ if (\in_array($pathInfo['extension'], ['jpg', 'png', 'gif', 'webp'])) {
if ($pathInfo['extension'] === 'jpg') {
$contentType = 'image/jpeg';
$extension = 'jpg';
} elseif ($pathInfo['extension'] === 'gif') {
$contentType = 'image/gif';
$extension = 'gif';
+ } elseif ($pathInfo['extension'] === 'webp') {
+ $contentType = 'image/webp';
+ $extension = 'webp';
+ } else {
+ $contentType = 'image/png';
+ $extension = 'png';
}
- $cachedFilename = sprintf(
- OPENAuthAvatar::OPENAUTH_CACHE_LOCATION,
- md5(mb_strtolower($this->user->openAuthAvatar)),
+ $fileLocation = WCF_DIR . \sprintf(
+ OpenAuthAvatar::OPENAUTH_CACHE_LOCATION,
+ \md5(\mb_strtolower($this->user->openAuthAvatar)),
$extension
);
- if (file_exists(WCF_DIR . $cachedFilename)) {
- @header('content-type: ' . $contentType);
- @readfile(WCF_DIR . $cachedFilename);
+ if (\file_exists($fileLocation)) {
+ $this->executed();
+
+ @\header('content-type: ' . $contentType);
+ @\readfile($fileLocation);
+
exit;
}
try {
- $request = new HTTPRequest($this->user->openAuthAvatar);
- $request->execute();
- $reply = $request->getReply();
-
- $fileExtension = 'png';
- $mimeType = 'image/png';
-
- if (isset($reply['httpHeaders']['content-type'][0])) {
- switch ($reply['httpHeaders']['content-type'][0]) {
- case 'image/jpeg':
- $mimeType = 'image/jpeg';
- $fileExtension = 'jpg';
- break;
- case 'image/gif':
- $mimeType = 'image/gif';
- $fileExtension = 'gif';
- break;
+ // download image
+ $file = null;
+ $response = null;
+ $tmp = FileUtil::getTemporaryFilename('openauth_avatar_');
+
+ try {
+ $file = new File($tmp);
+ $client = HttpFactory::makeClient([
+ RequestOptions::TIMEOUT => 10,
+ RequestOptions::STREAM => true,
+ RequestOptions::ALLOW_REDIRECTS => [
+ 'on_redirect' => new RedirectGuard(),
+ ],
+ ]);
+
+ $request = new Request('GET', $this->user->openAuthAvatar, ['accept' => 'image/*']);
+ $response = $client->send($request);
+
+ while (!$response->getBody()->eof()) {
+ try {
+ $file->write($response->getBody()->read(8192));
+ } catch (RuntimeException $e) {
+ throw new DomainException(
+ 'Failed to read response body.',
+ 0,
+ $e
+ );
+ }
}
+
+ $file->flush();
+ } catch (TransferException $e) {
+ throw new DomainException('Failed to request', 0, $e);
+ } finally {
+ if ($response && $response->getBody()) {
+ $response->getBody()->close();
+ }
+
+ if ($file) {
+ $file->close();
+ }
+ }
+
+ // check file type
+ $imageData = @\getimagesize($tmp);
+
+ if (!$imageData) {
+ throw new DomainException();
+ }
+
+ switch ($imageData[2]) {
+ case IMAGETYPE_PNG:
+ $extension = 'png';
+ break;
+ case IMAGETYPE_GIF:
+ $extension = 'gif';
+ break;
+ case IMAGETYPE_JPEG:
+ $extension = 'jpg';
+ break;
+ default:
+ throw new DomainException();
}
- $cachedFilename = sprintf(
+ $fileLocation = WCF_DIR . \sprintf(
OpenAuthAvatar::OPENAUTH_CACHE_LOCATION,
- md5(mb_strtolower($this->user->openAuthAvatar)),
- $fileExtension
+ \md5(\mb_strtolower($this->user->openAuthAvatar)),
+ $extension
);
- file_put_contents(WCF_DIR . $cachedFilename, $reply['body']);
- FileUtil::makeWritable(WCF_DIR . $cachedFilename);
+ \rename($tmp, $fileLocation);
- @header('content-type: ' . $mimeType);
- @readfile(WCF_DIR . $cachedFilename);
+ // update mtime for correct expiration calculation
+ @\touch($fileLocation);
- exit;
- } catch (SystemException $e) {
- $editor = new UserEditor($this->user);
- $editor->update([
- 'enableOpenAuthAvatar' => 0
- ]);
+ $this->executed();
+
+ @\header('content-type: ' . $imageData['mime']);
+ @\readfile($fileLocation);
- throw $e;
+ exit;
+ } catch (DomainException $e) {
+ (new UserEditor($this->user))->update(['enableOpenAuthAvatar' => 0]);
}
}
}
- @header('content-type: image/svg+xml');
- @readfile(WCF_DIR . 'images/avatars/avatar-default.svg');
+ $this->executed();
+
+ @\header('content-type: image/svg+xml');
+ @\readfile(WCF_DIR . 'images/avatars/avatar-default.svg');
exit;
}
diff --git a/files/lib/data/user/avatar/OpenAuthAvatar.class.php b/files/lib/data/user/avatar/OpenAuthAvatar.class.php
index e0bf87c..04d3a02 100644
--- a/files/lib/data/user/avatar/OpenAuthAvatar.class.php
+++ b/files/lib/data/user/avatar/OpenAuthAvatar.class.php
@@ -2,7 +2,6 @@
/*
* Copyright by The OpenAuth.dev Team.
- * This file is part of dev.openauth.wsc.login.
*
* License: GNU Lesser General Public License v2.1
*
@@ -27,30 +26,20 @@
namespace wcf\data\user\avatar;
use wcf\system\cache\runtime\UserRuntimeCache;
-use wcf\system\exception\SystemException;
use wcf\system\request\LinkHandler;
use wcf\system\WCF;
-use function file_exists;
-use function filemtime;
-use function in_array;
-use function mb_strtolower;
-use function md5;
-use function parse_url;
-use function pathinfo;
-use function sprintf;
-
class OpenAuthAvatar extends DefaultAvatar
{
/**
* @var string
*/
- const OPENAUTH_CACHE_LOCATION = 'images/avatars/openauth/%s.%s';
+ public const OPENAUTH_CACHE_LOCATION = 'images/avatars/openauth/%s.%s';
/**
* @var int
*/
- const OPENAUTH_CACHE_EXPIRE = 7;
+ public const OPENAUTH_CACHE_EXPIRE = 7;
/**
* @var string
@@ -77,38 +66,41 @@ public function __construct($userID)
/**
* @inheritDoc
*
- * @throws SystemException
+ * @throws \wcf\system\exception\SystemException
*/
public function getURL($size = null): string
{
if (empty($this->url)) {
$user = UserRuntimeCache::getInstance()->getObject($this->userID);
+ if (null === $user || !$user->userID) {
+ return '';
+ }
+
if (empty($user->openAuthAvatar)) {
return '';
}
- $urlParsed = parse_url($user->openAuthAvatar);
- $pathInfo = pathinfo($urlParsed['path']);
+ $urlParsed = \parse_url($user->openAuthAvatar);
+ $pathInfo = \pathinfo($urlParsed['path']);
- if (!in_array($pathInfo['extension'], ['jpg', 'png', 'gif'])) {
+ if (!\in_array($pathInfo['extension'], ['jpg', 'png', 'gif'])) {
return '';
}
- $cachedFilename = sprintf(
+ $cachedFilename = \sprintf(
self::OPENAUTH_CACHE_LOCATION,
- md5(mb_strtolower($user->openAuthAvatar)),
+ \md5(\mb_strtolower($user->openAuthAvatar)),
$pathInfo['extension']
);
- if (
- file_exists(WCF_DIR . $cachedFilename) &&
- filemtime(WCF_DIR . $cachedFilename) > (TIME_NOW - (self::OPENAUTH_CACHE_EXPIRE * 86400))
+ if (\file_exists(WCF_DIR . $cachedFilename)
+ && \filemtime(WCF_DIR . $cachedFilename) > (TIME_NOW - (self::OPENAUTH_CACHE_EXPIRE * 86400))
) {
$this->url = WCF::getPath() . $cachedFilename;
} else {
$this->url = LinkHandler::getInstance()->getLink('OpenAuthAvatarDownload', [
- 'forceFrontend' => true
+ 'forceFrontend' => true,
], 'userID=' . $this->userID);
}
}
diff --git a/files/lib/system/event/listener/OpenAuthAccountManagementListener.class.php b/files/lib/system/event/listener/OpenAuthAccountManagementListener.class.php
index 4b34c8c..6bd9f27 100644
--- a/files/lib/system/event/listener/OpenAuthAccountManagementListener.class.php
+++ b/files/lib/system/event/listener/OpenAuthAccountManagementListener.class.php
@@ -28,7 +28,6 @@
use wcf\form\AbstractForm;
use wcf\form\AccountManagementForm;
use wcf\page\AbstractPage;
-use wcf\system\exception\SystemException;
use wcf\system\request\LinkHandler;
use wcf\system\WCF;
use wcf\util\HeaderUtil;
@@ -53,20 +52,22 @@ class OpenAuthAccountManagementListener implements IParameterizedEventListener
/**
* @inheritDoc
+ *
+ * @return void
*/
- public function execute($eventObj, $className, $eventName, array &$parameters)
+ public function execute($eventObj, $className, $eventName, array &$parameters): void
{
if (OPENAUTH_CLIENT_ID === "" && OPENAUTH_CLIENT_SECRET === "") {
return;
}
- $this->$eventName($eventObj);
+ $this->{$eventName}($eventObj);
}
/**
* @see AbstractForm::readFormParameters()
*/
- protected function readFormParameters()
+ protected function readFormParameters(): void
{
if (isset($_POST['openauthDisconnect'])) {
$this->openAuthDisconnect = (int)$_POST['openauthDisconnect'];
@@ -80,43 +81,43 @@ protected function readFormParameters()
/**
* @see AbstractPage::assignVariables()
*/
- protected function assignVariables()
+ protected function assignVariables(): void
{
WCF::getTPL()->assign([
'openAuthConnect' => $this->openAuthConnect,
- 'openAuthDisconnect' => $this->openAuthDisconnect
+ 'openAuthDisconnect' => $this->openAuthDisconnect,
]);
}
/**
* @see AbstractForm::save()
*/
- protected function save(AccountManagementForm $eventObj)
+ protected function save(AccountManagementForm $eventObj): void
{
- if ($this->openAuthConnect && WCF::getSession()->getVar('__openAuthData')) {
- $userData = WCF::getSession()->getVar('__openAuthData');
+ if ($this->openAuthConnect && WCF::getSession()->getVar('__oauthUser')) {
+ $userData = WCF::getSession()->getVar('__oauthUser');
$eventObj->additionalFields['authData'] = 'openauth:' . $userData['sub'];
$eventObj->additionalFields['openAuthID'] = $userData['sub'];
$this->success = 'wcf.user.3rdparty.openauth.connect.success';
- WCF::getSession()->unregister('__openAuthData');
- WCF::getSession()->unregister('__openAuthUsername');
+ WCF::getSession()->unregister('__oauthUser');
} elseif ($this->openAuthDisconnect && StringUtil::startsWith(WCF::getUser()->authData, 'openauth:')) {
$eventObj->additionalFields['authData'] = '';
$eventObj->additionalFields['openAuthID'] = null;
$eventObj->additionalFields['openAuthAvatar'] = null;
$eventObj->additionalFields['enableOpenAuthAvatar'] = 0;
+
$this->success = 'wcf.user.3rdparty.openauth.disconnect.success';
}
}
/**
- * @throws SystemException
+ * @throws \wcf\system\exception\SystemException
*
* @see AbstractForm::saved()
*/
- protected function saved()
+ protected function saved(): void
{
if (!empty($this->success)) {
HeaderUtil::delayedRedirect(
diff --git a/files/lib/system/event/listener/OpenAuthAvatarEditListener.class.php b/files/lib/system/event/listener/OpenAuthAvatarEditListener.class.php
index e6a317a..667725a 100644
--- a/files/lib/system/event/listener/OpenAuthAvatarEditListener.class.php
+++ b/files/lib/system/event/listener/OpenAuthAvatarEditListener.class.php
@@ -31,38 +31,28 @@
use wcf\data\user\UserAction;
use wcf\form\AbstractForm;
use wcf\form\AvatarEditForm;
-use wcf\system\exception\SystemException;
use wcf\system\WCF;
-use function file_exists;
-use function in_array;
-use function mb_strtolower;
-use function md5;
-use function parse_url;
-use function pathinfo;
-use function sprintf;
-use function unlink;
-
class OpenAuthAvatarEditListener implements IParameterizedEventListener
{
/**
* @inheritDoc
+ *
+ * @return void
*/
- public function execute($eventObj, $className, $eventName, array &$parameters)
+ public function execute($eventObj, $className, $eventName, array &$parameters): void
{
if (OPENAUTH_CLIENT_ID === "" && OPENAUTH_CLIENT_SECRET === "") {
return;
}
- $this->$eventName($eventObj);
+ $this->{$eventName}($eventObj);
}
/**
- * @param AvatarEditForm|UserEditForm $eventObj
- *
* @see AbstractPage::readData()
*/
- protected function readData($eventObj)
+ protected function readData($eventObj): void
{
if (empty($_POST)) {
if ($eventObj instanceof UserEditForm) {
@@ -76,22 +66,19 @@ protected function readData($eventObj)
}
/**
- * @param AvatarEditForm|UserEditForm $eventObj
- *
* @see AbstractPage::assignVariables()
*/
- protected function assignVariables($eventObj)
+ protected function assignVariables(AvatarEditForm $eventObj): void
{
$this->readData($eventObj);
}
/**
- * @param AvatarEditForm|UserEditForm $eventObj
- * @throws SystemException
+ * @throws \wcf\system\exception\SystemException
*
* @see AbstractForm::save()
*/
- protected function save($eventObj)
+ protected function save($eventObj): void
{
if (isset($_POST['avatarType'])) {
$data = [];
@@ -119,11 +106,9 @@ protected function save($eventObj)
}
/**
- * @param AvatarEditForm|UserEditForm $eventObj
- *
* @see AbstractForm::saved()
*/
- protected function saved($eventObj)
+ protected function saved(AvatarEditForm $eventObj): void
{
if (isset($_POST['avatarType']) && $_POST['avatarType'] === 'OpenAuth') {
$eventObj->avatarType = 'OpenAuth';
@@ -133,27 +118,27 @@ protected function saved($eventObj)
/**
* Resets openauth avatar after disabling.
*/
- private function resetOpenAuthAvatarCache(User $user)
+ private function resetOpenAuthAvatarCache(User $user): void
{
if (!$user->enableOpenAuthAvatar) {
return;
}
- $urlParsed = parse_url($user->openAuthAvatar);
- $pathInfo = pathinfo($urlParsed['path']);
+ $urlParsed = \parse_url($user->openAuthAvatar);
+ $pathInfo = \pathinfo($urlParsed['path']);
- if (!in_array($pathInfo['extension'], ['jpg', 'png', 'gif'])) {
+ if (!\in_array($pathInfo['extension'], ['jpg', 'png', 'gif'])) {
return;
}
- $cachedFilename = sprintf(
+ $cachedFilename = \sprintf(
OpenAuthAvatar::OPENAUTH_CACHE_LOCATION,
- md5(mb_strtolower($user->openAuthAvatar)),
+ \md5(\mb_strtolower($user->openAuthAvatar)),
$pathInfo['extension']
);
- if (file_exists(WCF_DIR . $cachedFilename)) {
- @unlink(WCF_DIR . $cachedFilename);
+ if (\file_exists(WCF_DIR . $cachedFilename)) {
+ @\unlink(WCF_DIR . $cachedFilename);
}
}
}
diff --git a/files/lib/system/event/listener/OpenAuthRegisterListener.class.php b/files/lib/system/event/listener/OpenAuthRegisterListener.class.php
index 42cc2f1..6a24466 100644
--- a/files/lib/system/event/listener/OpenAuthRegisterListener.class.php
+++ b/files/lib/system/event/listener/OpenAuthRegisterListener.class.php
@@ -28,7 +28,6 @@
use wcf\data\user\option\UserOption;
use wcf\form\RegisterForm;
use wcf\page\AbstractPage;
-use wcf\system\exception\SystemException;
use wcf\system\openauth\OpenAuthAPI;
use wcf\system\WCF;
@@ -47,46 +46,47 @@ class OpenAuthRegisterListener implements IParameterizedEventListener
/**
* @inheritDoc
*/
- public function execute($eventObj, $className, $eventName, array &$parameters)
+ public function execute($eventObj, $className, $eventName, array &$parameters): void
{
if (OPENAUTH_CLIENT_ID === "" && OPENAUTH_CLIENT_SECRET === "") {
return;
}
- $this->$eventName($eventObj, $parameters);
+ $this->{$eventName}($eventObj, $parameters);
}
/**
- * @throws SystemException
+ * @throws \wcf\system\exception\SystemException
*
* @see AbstractForm::submit()
*/
- protected function submit(RegisterForm $eventObj)
+ protected function submit(RegisterForm $eventObj): void
{
$this->readData($eventObj);
}
/**
- * @throws SystemException
+ * @throws \wcf\system\exception\SystemException
*
* @see AbstractPage::readData
*/
- protected function readData(RegisterForm $eventObj)
+ protected function readData(RegisterForm $eventObj): void
{
if ($this->isInitialized) {
return;
}
+
$this->isInitialized = true;
if (WCF::getSession()->getVar('__3rdPartyProvider') !== 'openauth') {
return;
}
- if (empty(WCF::getSession()->getVar('__openAuthData'))) {
+ if (empty(WCF::getSession()->getVar('__oauthUser'))) {
return;
}
- $this->userData = WCF::getSession()->getVar('__openAuthData');
+ $this->userData = WCF::getSession()->getVar('__oauthUser');
foreach (OpenAuthAPI::getInstance()->getUserOptionNames() as $optionName => $dataName) {
if (empty($this->userData[$dataName])) {
@@ -115,8 +115,9 @@ protected function readData(RegisterForm $eventObj)
/**
* @see AbstractForm::save()
+ *
*/
- protected function save(RegisterForm $eventObj)
+ protected function save(RegisterForm $eventObj): void
{
if (empty($this->userData)) {
return;
@@ -131,10 +132,7 @@ protected function save(RegisterForm $eventObj)
}
}
- /**
- * @return void
- */
- protected function registerVia3rdParty(RegisterForm $eventObj, array &$parameters)
+ protected function registerVia3rdParty($eventObj, array &$parameters): void
{
if (empty($this->userData['email_verified'])) {
return;
@@ -154,8 +152,8 @@ protected function registerVia3rdParty(RegisterForm $eventObj, array &$parameter
/**
* @see RegisterForm::saved
*/
- protected function saved()
+ protected function saved(): void
{
- WCF::getSession()->unregister('__openAuthData');
+ WCF::getSession()->unregister('__oauthUser');
}
}
diff --git a/files/lib/system/event/listener/OpenAuthUserProfileListener.class.php b/files/lib/system/event/listener/OpenAuthUserProfileListener.class.php
index 19e6d74..0d72c3b 100644
--- a/files/lib/system/event/listener/OpenAuthUserProfileListener.class.php
+++ b/files/lib/system/event/listener/OpenAuthUserProfileListener.class.php
@@ -32,7 +32,7 @@ class OpenAuthUserProfileListener implements IParameterizedEventListener
/**
* @inheritDoc
*/
- public function execute($eventObj, $className, $eventName, array &$parameters)
+ public function execute($eventObj, $className, $eventName, array &$parameters): void
{
if ($eventObj->enableOpenAuthAvatar) {
$parameters['avatar'] = new OpenAuthAvatar($eventObj->userID);
diff --git a/files/lib/system/openauth/OpenAuthAPI.class.php b/files/lib/system/openauth/OpenAuthAPI.class.php
index a289acb..ed930b3 100644
--- a/files/lib/system/openauth/OpenAuthAPI.class.php
+++ b/files/lib/system/openauth/OpenAuthAPI.class.php
@@ -23,107 +23,65 @@
* copies or substantial portions of the Software.
*/
-namespace wcf\system\openauth;
+namespace wcf\system\openAuth;
use Exception;
+use GuzzleHttp\ClientInterface;
+use GuzzleHttp\Exception\GuzzleException;
+use GuzzleHttp\Psr7\Request;
use wcf\system\exception\SystemException;
+use wcf\system\io\HttpFactory;
use wcf\system\option\user\UserOptionHandler;
use wcf\system\request\LinkHandler;
use wcf\system\SingletonFactory;
-use wcf\util\HTTPRequest;
use wcf\util\JSON;
-use wcf\util\StringUtil;
-
-use function array_intersect;
-use function array_keys;
-use function array_search;
-use function array_values;
-use function http_build_query;
-use function implode;
-use function is_callable;
-use function mb_strlen;
-use function md5;
-use function mt_rand;
-use function openssl_random_pseudo_bytes;
-use function random_bytes;
-use function random_int;
-use function sprintf;
-use function substr;
-use function uniqid;
+
+use function wcf\functions\exception\logThrowable;
class OpenAuthAPI extends SingletonFactory
{
+ protected const OPENAUTH_API_URL = 'https://openauth.dev/%s?clientID=%s';
+
/**
- * @var string
+ * @var ClientInterface
*/
- const OPENAUTH_API_URL = 'https://openauth.dev/%s?clientID=%s';
+ protected $client;
/**
* @var array
*/
protected $configuration;
+ /**
+ * @inheritDoc
+ */
+ public function init(): void
+ {
+ $this->client = HttpFactory::makeClient(['timeout' => 10]);
+ }
+
/**
* Generates a random string, using the best available method.
*
* @throws SystemException
* @throws Exception
+ *
*/
- public static function generateRandom(int $length = 32)
+ public static function generateRandom(?int $length = 32): ?string
{
- if (class_exists('\ParagonIE\ConstantTime\Hex')) {
- $hexFn = '\ParagonIE\ConstantTime\Hex::encode';
- } else {
- $hexFn = '\bin2hex';
- }
-
- if (!null === $length || $length <= 8) {
+ if (!null === $length || (int)$length <= 8) {
$length = 32;
}
- if (is_callable('random_bytes')) {
- return substr($hexFn(random_bytes($length)), -$length, $length);
- }
-
- if (is_callable('openssl_random_pseudo_bytes')) {
- /** @noinspection CryptographicallySecureRandomnessInspection */
- $random = openssl_random_pseudo_bytes($length, $isSourceStrong);
-
- if (false === $isSourceStrong || false === $random) {
- throw new SystemException('IV generation failed');
- }
-
- return substr($hexFn($random), -$length, $length);
- }
-
- if (is_callable('random_int')) {
- $keySpace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
- $str = '';
- $max = mb_strlen($keySpace, '8bit') - 1;
-
- for ($i = 0; $i < $length; ++$i) {
- $str .= $keySpace[random_int(0, $max)];
- }
-
- return $str;
- }
-
- if (is_callable('mt_rand')) {
- return substr(md5(uniqid(mt_rand(), true)), -$length, $length);
- }
-
- if (is_callable('mcrypt_create_iv')) {
- /** @noinspection CryptographicallySecureRandomnessInspection */
- $randomM = mcrypt_create_iv($length, MCRYPT_DEV_RANDOM);
+ $keySpace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ $str = '';
+ $max = \mb_strlen($keySpace, '8bit') - 1;
- if (false === $randomM) {
- throw new SystemException('IV generation failed');
- }
-
- return substr($hexFn($randomM), -$length, $length);
+ for ($i = 0; $i < $length; $i++) {
+ $str .= $keySpace[\random_int(0, $max)];
}
- return StringUtil::getRandomID();
+ return $str;
}
/**
@@ -133,13 +91,10 @@ public static function generateRandom(int $length = 32)
*/
public function getRedirectURI(): string
{
- return LinkHandler::getInstance()->getLink(
- 'OpenAuth',
- [
- 'forceFrontend' => true,
- 'application' => 'wcf'
- ]
- );
+ return LinkHandler::getInstance()->getLink('OpenAuth', [
+ 'forceFrontend' => true,
+ 'application' => 'wcf',
+ ]);
}
/**
@@ -166,37 +121,35 @@ public function getUserOptionNames(): array
* Loads the remote oAuth configuration.
*
* @throws Exception
+ * @throws \GuzzleHttp\Exception\GuzzleException
*/
- public function getOauthConfiguration(string $configurationName): string
+ public function getOauthConfiguration(string $configurationName)
{
if (null === $this->configuration) {
$this->configuration = $this->call(
- sprintf(
- self::OPENAUTH_API_URL,
- '.well-known/openid-configuration',
- OPENAUTH_CLIENT_ID
- )
+ \sprintf(self::OPENAUTH_API_URL, 'open-id-configuration', OPENAUTH_CLIENT_ID)
);
}
if (!empty($this->configuration[$configurationName])) {
- return (string)$this->configuration[$configurationName];
+ return $this->configuration[$configurationName];
}
- return '';
+ return null;
}
/**
* Returns a list of available scopes.
*
* @throws Exception
+ * @throws \GuzzleHttp\Exception\GuzzleException
*/
- public function getScopes(): array
+ public function getScopes(): ?array
{
$scopes = $this->getOauthConfiguration('scopes_supported');
if (null === $scopes) {
- return [];
+ return null;
}
$scopes[] = 'openid';
@@ -206,55 +159,57 @@ public function getScopes(): array
$optionHandler->setInRegistration();
$optionHandler->init();
- $scopesToRemove = array_intersect(array_keys($profileScopes), array_keys($optionHandler->options));
+ $scopesToRemove = \array_intersect(\array_keys($profileScopes), \array_keys($optionHandler->options));
foreach ($scopesToRemove as $scopeToRemove) {
$scope = $profileScopes[$scopeToRemove];
- $key = array_search($scope, $scopes, false);
+ $key = \array_search($scope, $scopes, true);
if ($key !== false) {
unset($scopes[$key]);
}
}
- return array_values($scopes);
+ return \array_values($scopes);
}
/**
* Returns the authorization Uri.
*
* @throws Exception
+ * @throws \GuzzleHttp\Exception\GuzzleException
*/
- public function getAuthorizationURI(string $state, array $scopes = []): string
+ public function getAuthorizationURI(string $state, array $scopes = []): ?string
{
$authorizationEndpoint = $this->getOauthConfiguration('authorization_endpoint');
if (null === $authorizationEndpoint) {
- return '';
+ return null;
}
$requestParameters = [
'response_type' => 'code',
'client_id' => OPENAUTH_CLIENT_ID,
'state' => $state,
- 'scope' => implode(' ', $scopes),
- 'redirect_uri' => $this->getRedirectURI()
+ 'scope' => \implode(' ', $scopes),
+ 'redirect_uri' => $this->getRedirectURI(),
];
- return $authorizationEndpoint . '?' . http_build_query($requestParameters, null);
+ return $authorizationEndpoint . '?' . \http_build_query($requestParameters, null, '&');
}
/**
* Checks if the given oAuth code is valid.
*
* @throws Exception
+ * @throws \GuzzleHttp\Exception\GuzzleException
*/
- public function checkOAuthCode(string $code): array
+ public function checkOAuthCode($code): ?array
{
$tokenEndpoint = $this->getOauthConfiguration('token_endpoint');
if (null === $tokenEndpoint) {
- return [];
+ return null;
}
$params = [
@@ -262,7 +217,7 @@ public function checkOAuthCode(string $code): array
'client_secret' => OPENAUTH_CLIENT_SECRET,
'code' => $code,
'grant_type' => 'authorization_code',
- 'redirect_uri' => $this->getRedirectURI()
+ 'redirect_uri' => $this->getRedirectURI(),
];
return $this->call($tokenEndpoint, $params);
@@ -272,13 +227,14 @@ public function checkOAuthCode(string $code): array
* Returns user information for the given access token from the oAuth server.
*
* @throws Exception
+ * @throws \GuzzleHttp\Exception\GuzzleException
*/
- public function getUserInfo(string $accessToken): array
+ public function getUserInfo(string $accessToken): ?array
{
$userinfoEndpoint = $this->getOauthConfiguration('userinfo_endpoint');
if (null === $userinfoEndpoint) {
- return [];
+ return null;
}
return $this->call($userinfoEndpoint, [], $accessToken);
@@ -288,25 +244,33 @@ public function getUserInfo(string $accessToken): array
* Executes http requests.
*
* @throws Exception
+ * @throws \GuzzleHttp\Exception\GuzzleException
*/
- protected function call(string $url, array $data = [], string $accessToken = null): array
+ protected function call(string $url, array $data = [], ?string $accessToken = null): ?array
{
try {
- $request = new HTTPRequest($url, [], $data);
+ $headers = [
+ 'accept-encoding' => 'gzip',
+ 'accept' => 'application/json',
+ ];
if (null !== $accessToken) {
- $request->addHeader('Authorization', 'Bearer ' . $accessToken);
+ $headers['authorization'] = 'Bearer ' . $accessToken;
}
- $request->execute();
+ $response = $this->client->send(new Request('POST', $url, $headers, $data));
- return JSON::decode($request->getReply()['body']);
- } catch (Exception $e) {
+ if ($response->getStatusCode() === 200) {
+ return JSON::decode((string)$response->getBody());
+ }
+ } catch (GuzzleException $e) {
if (ENABLE_DEBUG_MODE) {
throw $e;
}
- return [];
+ logThrowable($e);
}
+
+ return [];
}
}
diff --git a/files/style/ui/userLoginOpenAuth.scss b/files/style/ui/userLoginOpenAuth.scss
index 5ef0d1a..05f0f6c 100644
--- a/files/style/ui/userLoginOpenAuth.scss
+++ b/files/style/ui/userLoginOpenAuth.scss
@@ -2,9 +2,15 @@
font-family: 'woltauth';
font-weight: normal;
font-style: normal;
- src: url('../font/getFont.php?font=woltauth&type=woff2') format('woff2'),
- url('../font/getFont.php?font=woltauth&type=ttf') format('truetype'),
- url('../font/getFont.php?font=woltauth&type=woff') format('woff');
+ --woltlab-suite-preload: #{preload(
+ getFont("woltauth.woff2", "", "1.0.0"),
+ $as: "font",
+ $crossorigin: true,
+ $type: "font/woff2"
+ )};
+ src: url(getFont("woltauth.woff2", "", "1.0.0")) format("woff2"),
+ url(getFont("woltauth.woff", "", "1.0.0")) format("woff")
+ url(getFont("woltauth.ttf", "", "1.0.0")) format("truetype");
}
.fa-woltauth:before {
diff --git a/install.sql b/install.sql
deleted file mode 100644
index 037063b..0000000
--- a/install.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-ALTER TABLE wcf1_user ADD openAuthID INT(10);
-ALTER TABLE wcf1_user ADD openAuthAvatar VARCHAR(200);
-ALTER TABLE wcf1_user ADD enableOpenAuthAvatar TINYINT(1) NOT NULL DEFAULT 0;
diff --git a/language/de.xml b/language/de.xml
index 30641a9..77e84f2 100644
--- a/language/de.xml
+++ b/language/de.xml
@@ -10,7 +10,7 @@
-
+
session->getVar('__openAuthUsername')}(„{$__wcf->session->getVar('__openAuthUsername')}“){/if} verknüpfen]]>
@@ -28,10 +28,9 @@
-
-
+
diff --git a/language/en.xml b/language/en.xml
index a7a770b..1b73f95 100644
--- a/language/en.xml
+++ b/language/en.xml
@@ -10,7 +10,7 @@
-
+
session->getVar('__openAuthUsername')} “{$__wcf->session->getVar('__openAuthUsername')}”{/if}.]]>
@@ -19,7 +19,7 @@
OpenAuth.dev, therefore your username, your email address and your profile informations have been automatically filled.]]>
-
+
@@ -28,10 +28,9 @@
-
-
+
diff --git a/make.sh b/make.sh
deleted file mode 100644
index 0619b21..0000000
--- a/make.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-PACKAGE_NAME="dev.openauth.wsc.login"
-rm -f acptemplates.tar
-rm -f files.tar
-rm -f templates.tar
-rm -f ${PACKAGE_NAME}.tar
-7z a -ttar -mx=9 acptemplates.tar ./acptemplates/*
-7z a -ttar -mx=9 files.tar ./files/*
-7z a -ttar -mx=9 templates.tar ./templates/*
-7z a -ttar -mx=9 ${PACKAGE_NAME}.tar ./* -x!acptemplates -x!files -x!templates -x!${PACKAGE_NAME}.tar -x!.git -x!.gitignore -x!make.bat -x!make.sh -x!.vscode -x!.idea -x!constants.php
-rm -f acptemplates.tar
-rm -f files.tar
-rm -f templates.tar
diff --git a/option.xml b/option.xml
index c81a993..0ea5555 100644
--- a/option.xml
+++ b/option.xml
@@ -1,5 +1,5 @@
-
+