From 98fe0ba35c41df1ee1d5eac0366a9e438d54c841 Mon Sep 17 00:00:00 2001 From: nuxsmin Date: Sat, 17 Nov 2018 13:11:58 +0100 Subject: [PATCH] * [FIX] Fixed URL when downloading resources and sysPass id behind a reverse proxy. Thanks to @vmario89 for the feedback. Closes #1102 * [FIX] Fixed wrong behavior when copying to clipboard an account's password through public link * [MOD] Improved URL handling * [MOD] Improved deep links handling Signed-off-by: nuxsmin --- .../web/Controllers/AccountController.php | 51 ++++++++++++++++++- .../Helpers/Account/AccountHelper.php | 3 +- .../web/Controllers/Helpers/LayoutHelper.php | 13 ++--- .../web/Controllers/LoginController.php | 3 +- .../web/Controllers/Traits/JsonTrait.php | 4 +- .../material-blue/views/config/backup.inc | 1 + lib/SP/Bootstrap.php | 26 ++-------- lib/SP/Http/Request.php | 13 +++-- lib/SP/Mvc/Controller/ControllerTrait.php | 22 ++++++-- lib/SP/Mvc/View/Template.php | 7 ++- lib/SP/Services/Auth/LoginService.php | 4 +- public/js/app-main.js | 12 +++-- public/js/app-main.min.js | 26 +++++----- public/js/app-util.js | 22 ++------ public/js/app-util.min.js | 16 +++--- 15 files changed, 138 insertions(+), 85 deletions(-) diff --git a/app/modules/web/Controllers/AccountController.php b/app/modules/web/Controllers/AccountController.php index 34152a5b..68eaa28d 100644 --- a/app/modules/web/Controllers/AccountController.php +++ b/app/modules/web/Controllers/AccountController.php @@ -136,6 +136,8 @@ final class AccountController extends ControllerBase implements CrudControllerIn try { $this->checkSecurityToken($this->previousSk, $this->request); + $this->view->addTemplate('account'); + $accountDetailsResponse = $this->accountService->getById($id); $this->accountService ->withUsersById($accountDetailsResponse) @@ -146,7 +148,6 @@ final class AccountController extends ControllerBase implements CrudControllerIn $accountHelper->setIsView(true); $accountHelper->setViewForAccount($accountDetailsResponse, Acl::ACCOUNT_VIEW); - $this->view->addTemplate('account'); $this->view->assign('title', [ 'class' => 'titleNormal', @@ -169,6 +170,12 @@ final class AccountController extends ControllerBase implements CrudControllerIn $this->eventDispatcher->notifyEvent('exception', new Event($e)); + if ($this->isAjax === false + && !$this->view->isUpgraded() + ) { + $this->upgradeView(); + } + ErrorUtil::showExceptionInView($this->view, $e, 'account'); } } @@ -282,6 +289,12 @@ final class AccountController extends ControllerBase implements CrudControllerIn } catch (\Exception $e) { processException($e); + if ($this->isAjax === false + && !$this->view->isUpgraded() + ) { + $this->upgradeView(); + } + ErrorUtil::showExceptionInView($this->view, $e, 'account'); } } @@ -330,6 +343,12 @@ final class AccountController extends ControllerBase implements CrudControllerIn $this->eventDispatcher->notifyEvent('exception', new Event($e)); + if ($this->isAjax === false + && !$this->view->isUpgraded() + ) { + $this->upgradeView(); + } + ErrorUtil::showExceptionInView($this->view, $e, 'account'); } } @@ -380,6 +399,12 @@ final class AccountController extends ControllerBase implements CrudControllerIn $this->eventDispatcher->notifyEvent('exception', new Event($e)); + if ($this->isAjax === false + && !$this->view->isUpgraded() + ) { + $this->upgradeView(); + } + ErrorUtil::showExceptionInView($this->view, $e, 'account'); } } @@ -427,6 +452,12 @@ final class AccountController extends ControllerBase implements CrudControllerIn $this->eventDispatcher->notifyEvent('exception', new Event($e)); + if ($this->isAjax === false + && !$this->view->isUpgraded() + ) { + $this->upgradeView(); + } + ErrorUtil::showExceptionInView($this->view, $e, 'account'); } } @@ -474,6 +505,12 @@ final class AccountController extends ControllerBase implements CrudControllerIn $this->eventDispatcher->notifyEvent('exception', new Event($e)); + if ($this->isAjax === false + && !$this->view->isUpgraded() + ) { + $this->upgradeView(); + } + ErrorUtil::showExceptionInView($this->view, $e, 'account-editpass'); } } @@ -521,6 +558,12 @@ final class AccountController extends ControllerBase implements CrudControllerIn $this->eventDispatcher->notifyEvent('exception', new Event($e)); + if ($this->isAjax === false + && !$this->view->isUpgraded() + ) { + $this->upgradeView(); + } + ErrorUtil::showExceptionInView($this->view, $e, 'account-history'); } } @@ -557,6 +600,12 @@ final class AccountController extends ControllerBase implements CrudControllerIn $this->eventDispatcher->notifyEvent('exception', new Event($e)); + if ($this->isAjax === false + && !$this->view->isUpgraded() + ) { + $this->upgradeView(); + } + ErrorUtil::showExceptionInView($this->view, $e, 'account-request'); } } diff --git a/app/modules/web/Controllers/Helpers/Account/AccountHelper.php b/app/modules/web/Controllers/Helpers/Account/AccountHelper.php index 0391df0f..961a00e3 100644 --- a/app/modules/web/Controllers/Helpers/Account/AccountHelper.php +++ b/app/modules/web/Controllers/Helpers/Account/AccountHelper.php @@ -24,6 +24,7 @@ namespace SP\Modules\Web\Controllers\Helpers\Account; +use SP\Bootstrap; use SP\Core\Acl\AccountPermissionException; use SP\Core\Acl\Acl; use SP\Core\Acl\ActionsInterface; @@ -322,7 +323,7 @@ final class AccountHelper extends HelperBase { $route = Acl::getActionRoute($this->actionId) . ($this->accountId ? '/' . $this->accountId : ''); - $uri = new Uri('index.php'); + $uri = new Uri(Bootstrap::$WEBROOT . Bootstrap::$SUBURI); $uri->addParam('r', $route); return $uri->getUriSigned($this->configData->getPasswordSalt()); diff --git a/app/modules/web/Controllers/Helpers/LayoutHelper.php b/app/modules/web/Controllers/Helpers/LayoutHelper.php index 1deccf45..fa1af0bb 100644 --- a/app/modules/web/Controllers/Helpers/LayoutHelper.php +++ b/app/modules/web/Controllers/Helpers/LayoutHelper.php @@ -102,10 +102,10 @@ final class LayoutHelper extends HelperBase $this->view->assign('app_website_url', AppInfoInterface::APP_WEBSITE_URL); $this->view->assign('app_blog_url', AppInfoInterface::APP_BLOG_URL); $this->view->assign('app_version', Installer::VERSION_TEXT); - $this->view->assign('logoIcon', Bootstrap::$WEBURI . '/public/images/logo_icon.png'); - $this->view->assign('logoNoText', Bootstrap::$WEBURI . '/public/images/logo_icon.svg'); - $this->view->assign('logo', Bootstrap::$WEBURI . '/public/images/logo_full_bg.png'); - $this->view->assign('logonobg', Bootstrap::$WEBURI . '/public/images/logo_full_nobg.png'); + $this->view->assign('logoIcon', Bootstrap::$WEBROOT . '/public/images/logo_icon.png'); + $this->view->assign('logoNoText', Bootstrap::$WEBROOT . '/public/images/logo_icon.svg'); + $this->view->assign('logo', Bootstrap::$WEBROOT . '/public/images/logo_full_bg.png'); + $this->view->assign('logonobg', Bootstrap::$WEBROOT . '/public/images/logo_full_nobg.png'); $this->view->assign('httpsEnabled', $this->request->isHttps()); $this->view->assign('homeRoute', Acl::getActionRoute(ActionsInterface::ACCOUNT)); @@ -134,8 +134,9 @@ final class LayoutHelper extends HelperBase protected function getResourcesLinks() { $version = VersionUtil::getVersionStringNormalized(); + $uri = Bootstrap::$WEBROOT . Bootstrap::$SUBURI; - $jsUri = new Uri(Bootstrap::$WEBURI . '/index.php'); + $jsUri = new Uri($uri); $jsUri->addParam('_r', 'resource/js'); $jsUri->addParam('_v', md5($version)); @@ -164,7 +165,7 @@ final class LayoutHelper extends HelperBase $resultsAsCards = $this->configData->isResultsAsCards(); } - $cssUri = new Uri(Bootstrap::$WEBURI . '/index.php'); + $cssUri = new Uri($uri); $cssUri->addParam('_r', 'resource/css'); $cssUri->addParam('_v', md5($version . $resultsAsCards)); diff --git a/app/modules/web/Controllers/LoginController.php b/app/modules/web/Controllers/LoginController.php index 59c6ed57..1169e9fa 100644 --- a/app/modules/web/Controllers/LoginController.php +++ b/app/modules/web/Controllers/LoginController.php @@ -24,6 +24,7 @@ namespace SP\Modules\Web\Controllers; +use SP\Bootstrap; use SP\Core\Context\SessionContext; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; @@ -63,7 +64,7 @@ final class LoginController extends ControllerBase $this->checkForwarded(); $redirector = function ($route) use ($from) { - $uri = new Uri('index.php'); + $uri = new Uri(Bootstrap::$SUBURI); $uri->addParam('r', $route); if ($from !== null) { diff --git a/app/modules/web/Controllers/Traits/JsonTrait.php b/app/modules/web/Controllers/Traits/JsonTrait.php index aedd0329..22920800 100644 --- a/app/modules/web/Controllers/Traits/JsonTrait.php +++ b/app/modules/web/Controllers/Traits/JsonTrait.php @@ -79,7 +79,7 @@ trait JsonTrait $jsonResponse->setStatus($status); $jsonResponse->setData($data); - if (property_exists($this, 'session')) { + if (isset($this->session)) { $jsonResponse->setCsrf($this->session->getSecurityKey()); } @@ -112,7 +112,7 @@ trait JsonTrait $jsonResponse->setMessages([$exception->getHint()]); } - if (property_exists($this, 'session')) { + if (isset($this->session)) { $jsonResponse->setCsrf($this->session->getSecurityKey()); } diff --git a/app/modules/web/themes/material-blue/views/config/backup.inc b/app/modules/web/themes/material-blue/views/config/backup.inc index d22f86f5..34a44e83 100644 --- a/app/modules/web/themes/material-blue/views/config/backup.inc +++ b/app/modules/web/themes/material-blue/views/config/backup.inc @@ -3,6 +3,7 @@ * @var \SP\Core\UI\ThemeIcons $icons * @var \SP\Config\ConfigData $configData * @var callable $_getvar + * @var callable $_getRoute * @var \SP\Mvc\View\Template $this */ ?> diff --git a/lib/SP/Bootstrap.php b/lib/SP/Bootstrap.php index 2921e03d..4dc2ef38 100644 --- a/lib/SP/Bootstrap.php +++ b/lib/SP/Bootstrap.php @@ -356,30 +356,14 @@ final class Bootstrap */ private function initPaths() { - self::$SUBURI = str_replace("\\", '/', substr(realpath($this->request->getServer('SCRIPT_FILENAME')), strlen(APP_ROOT))); + self::$SUBURI = '/' . basename($this->request->getServer('SCRIPT_FILENAME')); - $scriptName = $this->request->getServer('REQUEST_URI'); + $uri = $this->request->getServer('REQUEST_URI'); - if (substr($scriptName, -1) === '/') { - $scriptName .= 'index.php'; + $pos = strpos($uri, self::$SUBURI); - // Asegurar que suburi sigue las mismas reglas que scriptName - if (substr(self::$SUBURI, -9) !== 'index.php') { - if (substr(self::$SUBURI, -1) !== '/') { - self::$SUBURI .= '/'; - } - self::$SUBURI .= 'index.php'; - } - } - - if (($pos = strpos($scriptName, self::$SUBURI)) === false) { - $pos = strpos($scriptName, '?'); - } - - self::$WEBROOT = substr($scriptName, 0, $pos); - - if (self::$WEBROOT !== '' && self::$WEBROOT[0] !== '/') { - self::$WEBROOT = '/' . self::$WEBROOT; + if ($pos > 0) { + self::$WEBROOT = substr($uri, 0, $pos); } self::$WEBURI = $this->request->getHttpHost() . self::$WEBROOT; diff --git a/lib/SP/Http/Request.php b/lib/SP/Http/Request.php index 4d6c454f..14a55581 100644 --- a/lib/SP/Http/Request.php +++ b/lib/SP/Http/Request.php @@ -390,7 +390,12 @@ final class Request } if ($result === false) { - throw new SPException('URI string altered'); + throw new SPException( + 'URI string altered', + SPException::ERROR, + null, + 1 + ); } } @@ -416,12 +421,14 @@ final class Request return strtolower($xForward['proto'] . '://' . $xForward['host']); } + $protocol = 'http://'; + // We got called directly if ($this->https) { - return 'https://' . $this->request->server()->get('HTTP_HOST'); + $protocol = 'https://'; } - return 'http://' . $this->request->server()->get('HTTP_HOST'); + return $protocol . $this->request->server()->get('HTTP_HOST'); } /** diff --git a/lib/SP/Mvc/Controller/ControllerTrait.php b/lib/SP/Mvc/Controller/ControllerTrait.php index 9b17082b..659e5371 100644 --- a/lib/SP/Mvc/Controller/ControllerTrait.php +++ b/lib/SP/Mvc/Controller/ControllerTrait.php @@ -24,6 +24,7 @@ namespace SP\Mvc\Controller; +use SP\Bootstrap; use SP\Config\ConfigData; use SP\Core\Context\SessionContext; use SP\Core\Exceptions\SPException; @@ -38,6 +39,7 @@ use SP\Util\Util; * Trait ControllerTrait * * @package SP\Mvc\Controller + * @property ConfigData $configData */ trait ControllerTrait { @@ -84,7 +86,7 @@ trait ControllerTrait $route = $request->analyzeString('r'); $hash = $request->analyzeString('h'); - $uri = new Uri('index.php'); + $uri = new Uri(Bootstrap::$WEBROOT . Bootstrap::$SUBURI); $uri->addParam('_r', 'login'); if ($route && $hash) { @@ -112,10 +114,22 @@ trait ControllerTrait */ protected function checkSecurityToken($previousToken, Request $request) { - $sk = $request->analyzeString('sk'); + if ($request->analyzeString('h') !== null + && $request->analyzeString('from') === null + && isset($this->configData) + ) { + $request->verifySignature($this->configData->getPasswordSalt()); + } else { + $sk = $request->analyzeString('sk'); - if (!$sk || $previousToken !== $sk) { - throw new SPException(__u('Invalid Action')); + if (!$sk || $previousToken !== $sk) { + throw new SPException( + __u('Invalid Action'), + SPException::ERROR, + null, + 1 + ); + } } } diff --git a/lib/SP/Mvc/View/Template.php b/lib/SP/Mvc/View/Template.php index 4c3f6575..dbbeceec 100644 --- a/lib/SP/Mvc/View/Template.php +++ b/lib/SP/Mvc/View/Template.php @@ -29,6 +29,7 @@ defined('APP_ROOT') || die(); use SP\Bootstrap; use SP\Core\Exceptions\FileNotFoundException; use SP\Core\UI\ThemeInterface; +use SP\Http\Uri; /** * Class Template @@ -371,7 +372,11 @@ final class Template }; $_getRoute = function ($path) use ($sk) { - return Bootstrap::$WEBURI . '/index.php?r=' . $path . '&sk=' . $sk; + $uri = new Uri(Bootstrap::$WEBROOT . Bootstrap::$SUBURI); + $uri->addParam('r', $path); + $uri->addParam('sk', $sk); + + return $uri->getUri(); }; ob_start(); diff --git a/lib/SP/Services/Auth/LoginService.php b/lib/SP/Services/Auth/LoginService.php index dfc598d6..db8621d4 100644 --- a/lib/SP/Services/Auth/LoginService.php +++ b/lib/SP/Services/Auth/LoginService.php @@ -173,7 +173,9 @@ final class LoginService extends Service $this->loadUserPreferences(); $this->cleanUserData(); - return new LoginResponse(self::STATUS_PASS, 'index.php?r=' . ($this->from ?: 'index')); + $redirect = 'index.php?r=' . ($this->from ? $this->from . '&sk=' . $this->context->getSecurityKey() : 'index'); + + return new LoginResponse(self::STATUS_PASS, $redirect); } /** diff --git a/public/js/app-main.js b/public/js/app-main.js index 09858e08..da0f2f0e 100644 --- a/public/js/app-main.js +++ b/public/js/app-main.js @@ -128,7 +128,7 @@ sysPass.Main = function () { } $("body").on("click", ".clip-pass-button", function () { - const json = sysPassApp.actions.account.copyPass($(this)).done(function (json) { + const json = oPublic.actions.account.copyPass($(this)).done(function (json) { if (json.status !== 0) { msg.out(json); @@ -165,8 +165,10 @@ sysPass.Main = function () { } ); }).on("click", ".clip-pass-icon", function () { + const $target =$(this.dataset.clipboardTarget); + clipboard - .copy(sysPass.Util.decodeEntities($(this.dataset.clipboardTarget).val())) + .copy(oPublic.util.decodeEntities($target.val())) .then( function () { msg.ok(oPublic.config.LANG[45]); @@ -176,8 +178,10 @@ sysPass.Main = function () { } ); }).on("click", ".clip-pass-field", function () { + const target = document.getElementById(this.dataset.clipboardTarget); + clipboard - .copy(sysPass.Util.decodeEntities(document.getElementById(this.dataset.clipboardTarget).dataset.pass)) + .copy(oPublic.util.decodeEntities(target.dataset.pass)) .then( function () { msg.ok(oPublic.config.LANG[45]); @@ -364,7 +368,7 @@ sysPass.Main = function () { this.warn(description); break; case 10: - sysPassApp.actions.main.logout(); + oPublic.actions.main.logout(); break; case 100: this.ok(description); diff --git a/public/js/app-main.min.js b/public/js/app-main.min.js index c0ff4558..5924d080 100644 --- a/public/js/app-main.min.js +++ b/public/js/app-main.min.js @@ -1,13 +1,13 @@ -sysPass.Main=function(){var k=function(){d.info("checkPluginUpdates");for(var a in b.plugins)"function"===typeof b.plugins[a].checkVersion&&b.plugins[a].checkVersion().then(function(a){0===a.status&&void 0!==a.data.plugin&&e.info(String.format(b.config.LANG[67],a.data.plugin,a.data.remoteVersion))})},l=function(){d.info("bindPassEncrypt");$("body").on("blur",":input[type=password]",function(a){a=$(this);if(!a.hasClass("passwordfield__no-pki"))try{g(a)}catch(c){d.error(c),e.error(c)}}).on("keypress", -":input[type=password]",function(a){if(13===a.keyCode){a.preventDefault();a=$(this);try{g(a)}catch(c){d.error(c),e.error(c)}a.closest("form").submit()}})},m=function(){d.info("initializeClipboard");if(clipboard.isSupported())$("body").on("click",".clip-pass-button",function(){var a=sysPassApp.actions.account.copyPass($(this)).done(function(a){if(0!==a.status)return e.out(a),!1;h.set(a.csrf)});!1!==a&&clipboard.copy(a.responseJSON.data.accpass).then(function(){e.ok(b.config.LANG[45])},function(a){e.error(b.config.LANG[46])})}).on("click", -".dialog-clip-button",function(){var a=$(this.dataset.clipboardTarget);clipboard.copy(a.text().replace(/\r?\n|\r/g)).then(function(){$(".dialog-text").removeClass("dialog-clip-copy");a.addClass("dialog-clip-copy")},function(a){e.error(b.config.LANG[46])})}).on("click",".clip-pass-icon",function(){clipboard.copy(sysPass.Util.decodeEntities($(this.dataset.clipboardTarget).val())).then(function(){e.ok(b.config.LANG[45])},function(a){e.error(b.config.LANG[46])})}).on("click",".clip-pass-field",function(){clipboard.copy(sysPass.Util.decodeEntities(document.getElementById(this.dataset.clipboardTarget).dataset.pass)).then(function(){e.ok(b.config.LANG[45])}, -function(a){e.error(b.config.LANG[46])})});else d.warn(b.config.LANG[65])},g=function(a){d.info("encryptFormValue");var c=a.val();if(""!==c&&parseInt(a.attr("data-length"))!==c.length){if(c.length>b.config.PKI.MAX_SIZE)throw a.val(""),"Data length too big for encrypting";c=b.config.PKI.CRYPTO.encrypt(c);a.val(c);a.attr("data-length",c.length)}},p=function(){d.info("checkLogout");return"login/logout"===n("r")?(e.sticky(b.config.LANG[61],function(){b.util.redirect("index.php?r=login")}),!0):!1},h={current:"", -get:function(){d.info("sk:get");return $("#container").attr("data-sk")},set:function(a){d.info("sk:set");d.debug(a);$("#container").attr("data-sk",a);this.current=a}},d={log:function(a){!0===b.config.DEBUG&&console.log(a)},info:function(a){!0===b.config.DEBUG&&console.info(a)},error:function(a){console.error(a)},warn:function(a){console.warn(a)},debug:function(a){!0===b.config.DEBUG&&console.debug(a)}};Object.freeze(d);toastr.options={closeButton:!0,debug:!1,newestOnTop:!1,progressBar:!1,positionClass:"toast-top-center", -preventDuplicates:!1,onclick:null,showDuration:"300",hideDuration:"1000",timeOut:"5000",extendedTimeOut:"1000",showEasing:"swing",hideEasing:"linear",showMethod:"fadeIn",hideMethod:"fadeOut"};var q=function(){d.info("setupCallbacks");var a=$("#container"),c=a.data("page");if(0"+a.messages.join("
"));switch(c){case 0:this.ok(b);break;case 1:this.error(b);break;case 2:this.warn(b);break;case 10:sysPassApp.actions.main.logout();break; -case 100:this.ok(b);this.sticky(b);break;case 101:this.error(b);this.sticky(b);break;case 102:this.warn(b);this.sticky(b);break;default:this.error(b)}}},html:{error:function(a){return'

Oops...
'+b.config.LANG[1]+"
"+a+"

"}}};Object.freeze(e);String.format||(String.format=function(a){var b=Array.prototype.slice.call(arguments,1);return a.replace(/{(\d+)}/g,function(a,c){return"undefined"!==typeof b[c]?b[c]:a})});var r=function(){d.info("getEnvironment");var a=window.location.pathname.split("/"), -c=sysPass.Config();c.setAppRoot(window.location.protocol+"//"+window.location.host+function(){for(var b="",c=1;c<=a.length-2;c++)b+="/"+a[c];return b}());var f=b.requests.getRequestOpts();f.url="/index.php?r=bootstrap/getEnvironment";f.method="get";f.useLoading=!1;f.data={isAjax:1};return b.requests.getActionCall(f,function(a){void 0!==a.data&&(c.setLang(a.data.lang),c.setSessionTimeout(a.data.session_timeout),c.setPkiKey(a.data.pki_key),c.setPkiSize(a.data.pki_max_size),c.setCheckUpdates(a.data.check_updates), -c.setCheckNotices(a.data.check_notices),c.setCheckNotifications(a.data.check_notifications),c.setTimezone(a.data.timezone),c.setLocale(a.data.locale),c.setDebugEnabled(a.data.debug),c.setFileMaxSize(a.data.max_file_size),c.setFileAccountAllowedMime(a.data.files_allowed_mime),c.setFileImportAllowedMime(a.data.import_allowed_mime),c.setCookiesEnabled(a.data.cookies_enabled),c.setPlugins(a.data.plugins),c.setLoggedIn(a.data.loggedin),c.setAuthBasicAutologinEnabled(a.data.authbasic_autologin),c.initialize(), -b.config=c.getConfig())}).fail(function(){e.error("Error while getting sysPass config
Please try again or check web server logs")})},b={config:sysPass.Config().getConfig(),actions:sysPass.Actions(d),triggers:sysPass.Triggers(d),util:sysPass.Util(d),theme:{},plugins:{},sk:h,msg:e,log:d,encryptFormValue:g},n=function(a){for(var b=[],d,e=window.location.href.slice(window.location.href.indexOf("?")+1).split("&"),g=0;gb.config.PKI.MAX_SIZE)throw a.val(""),"Data length too big for encrypting";c=b.config.PKI.CRYPTO.encrypt(c);a.val(c);a.attr("data-length",c.length)}},p=function(){e.info("checkLogout"); +return"login/logout"===n("r")?(f.sticky(b.config.LANG[61],function(){b.util.redirect("index.php?r=login")}),!0):!1},h={current:"",get:function(){e.info("sk:get");return $("#container").attr("data-sk")},set:function(a){e.info("sk:set");e.debug(a);$("#container").attr("data-sk",a);this.current=a}},e={log:function(a){!0===b.config.DEBUG&&console.log(a)},info:function(a){!0===b.config.DEBUG&&console.info(a)},error:function(a){console.error(a)},warn:function(a){console.warn(a)},debug:function(a){!0=== +b.config.DEBUG&&console.debug(a)}};Object.freeze(e);toastr.options={closeButton:!0,debug:!1,newestOnTop:!1,progressBar:!1,positionClass:"toast-top-center",preventDuplicates:!1,onclick:null,showDuration:"300",hideDuration:"1000",timeOut:"5000",extendedTimeOut:"1000",showEasing:"swing",hideEasing:"linear",showMethod:"fadeIn",hideMethod:"fadeOut"};var q=function(){e.info("setupCallbacks");var a=$("#container"),c=a.data("page");if(0"+a.messages.join("
"));switch(c){case 0:this.ok(d);break;case 1:this.error(d);break;case 2:this.warn(d);break;case 10:b.actions.main.logout();break;case 100:this.ok(d);this.sticky(d);break;case 101:this.error(d);this.sticky(d);break;case 102:this.warn(d);this.sticky(d);break;default:this.error(d)}}},html:{error:function(a){return'

Oops...
'+b.config.LANG[1]+"
"+a+"

"}}};Object.freeze(f);String.format||(String.format=function(a){var c=Array.prototype.slice.call(arguments, +1);return a.replace(/{(\d+)}/g,function(a,b){return"undefined"!==typeof c[b]?c[b]:a})});var r=function(){e.info("getEnvironment");var a=window.location.pathname.split("/"),c=sysPass.Config();c.setAppRoot(window.location.protocol+"//"+window.location.host+function(){for(var c="",b=1;b<=a.length-2;b++)c+="/"+a[b];return c}());var d=b.requests.getRequestOpts();d.url="/index.php?r=bootstrap/getEnvironment";d.method="get";d.useLoading=!1;d.data={isAjax:1};return b.requests.getActionCall(d,function(a){void 0!== +a.data&&(c.setLang(a.data.lang),c.setSessionTimeout(a.data.session_timeout),c.setPkiKey(a.data.pki_key),c.setPkiSize(a.data.pki_max_size),c.setCheckUpdates(a.data.check_updates),c.setCheckNotices(a.data.check_notices),c.setCheckNotifications(a.data.check_notifications),c.setTimezone(a.data.timezone),c.setLocale(a.data.locale),c.setDebugEnabled(a.data.debug),c.setFileMaxSize(a.data.max_file_size),c.setFileAccountAllowedMime(a.data.files_allowed_mime),c.setFileImportAllowedMime(a.data.import_allowed_mime), +c.setCookiesEnabled(a.data.cookies_enabled),c.setPlugins(a.data.plugins),c.setLoggedIn(a.data.loggedin),c.setAuthBasicAutologinEnabled(a.data.authbasic_autologin),c.initialize(),b.config=c.getConfig())}).fail(function(){f.error("Error while getting sysPass config
Please try again or check web server logs")})},b={config:sysPass.Config().getConfig(),actions:sysPass.Actions(e),triggers:sysPass.Triggers(e),util:sysPass.Util(e),theme:{},plugins:{},sk:h,msg:f,log:e,encryptFormValue:g},n=function(a){for(var c= +[],b,e=window.location.href.slice(window.location.href.indexOf("?")+1).split("&"),f=0;f]*>([\S\s]*?)<\/script>/gmi, ""); - str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, ""); - element.innerHTML = str; - str = element.textContent; - element.textContent = ""; - } - - return str; - } - - return decodeHTMLEntities; + const decodeEntities = function (str) { + return $('