diff --git a/ajax/ajax_getEnvironment.php b/ajax/ajax_getEnvironment.php index 7ac71fad..c84d028d 100644 --- a/ajax/ajax_getEnvironment.php +++ b/ajax/ajax_getEnvironment.php @@ -25,6 +25,7 @@ use SP\Config\Config; use SP\Core\CryptPKI; use SP\Core\Init; +use SP\Core\Plugin\PluginUtil; use SP\Core\Session; use SP\Http\Cookies; use SP\Http\Request; @@ -49,7 +50,8 @@ $data = [ 'check_updates' => Session::getAuthCompleted() && ($Config->isCheckUpdates() || $Config->isChecknotices()) && (Session::getUserData()->isUserIsAdminApp() || Checks::demoIsEnabled()), 'timezone' => date_default_timezone_get(), 'debug' => DEBUG || $Config->isDebug(), - 'cookies_enabled' => Cookies::checkCookies() + 'cookies_enabled' => Cookies::checkCookies(), + 'plugins' => PluginUtil::getEnabledPlugins() ]; try { diff --git a/inc/Base.php b/inc/Base.php index dc7d074c..b3570668 100644 --- a/inc/Base.php +++ b/inc/Base.php @@ -40,7 +40,7 @@ define('LOCALES_PATH', __DIR__ . DIRECTORY_SEPARATOR . 'locales'); define('SQL_PATH', __DIR__ . DIRECTORY_SEPARATOR . 'sql'); define('LOG_FILE', __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'syspass.log'); -define('DEBUG', false); +define('DEBUG', true); // Required random_compat polyfill for random_bytes() and random_int() // @see https://github.com/paragonie/random_compat/tree/v2.0.4#random_compat @@ -65,4 +65,4 @@ require __DIR__ . DIRECTORY_SEPARATOR . 'BaseFunctions.php'; $memInit = memory_get_usage(); // Inicializar sysPass -Init::start(); +Init::start(); \ No newline at end of file diff --git a/inc/SP/Core/Init.class.php b/inc/SP/Core/Init.class.php index dfee7841..d616aecd 100644 --- a/inc/SP/Core/Init.class.php +++ b/inc/SP/Core/Init.class.php @@ -359,35 +359,6 @@ class Init self::$WEBURI .= $protocol . $_SERVER['HTTP_HOST'] . self::$WEBROOT; } - /** - * Iniciar la sesión PHP - * - * @param bool $encrypt Encriptar la sesión de PHP - */ - private static function startSession($encrypt = false) - { - // Evita que javascript acceda a las cookies de sesion de PHP - ini_set('session.cookie_httponly', '1'); - ini_set('session.save_handler', 'files'); - - if ($encrypt === true) { - $Key = SecureKeyCookie::getKey(); - - if ($Key !== false && self::$checkPhpVersion) { - session_set_save_handler(new CryptSessionHandler($Key), true); - } - } - - // Si la sesión no puede ser iniciada, devolver un error 500 - if (session_start() === false) { - Log::writeNewLog(__('Sesión', false), __('La sesión no puede ser inicializada', false)); - - header('HTTP/1.1 500 Internal Server Error'); - - self::initError(__('La sesión no puede ser inicializada'), __('Consulte con el administrador')); - } - } - /** * Devuelve un error utilizando la plantilla de error o en formato JSON * @@ -511,6 +482,35 @@ class Init } } + /** + * Iniciar la sesión PHP + * + * @param bool $encrypt Encriptar la sesión de PHP + */ + private static function startSession($encrypt = false) + { + // Evita que javascript acceda a las cookies de sesion de PHP + ini_set('session.cookie_httponly', '1'); + ini_set('session.save_handler', 'files'); + + if ($encrypt === true) { + $Key = SecureKeyCookie::getKey(); + + if ($Key !== false && self::$checkPhpVersion) { + session_set_save_handler(new CryptSessionHandler($Key), true); + } + } + + // Si la sesión no puede ser iniciada, devolver un error 500 + if (session_start() === false) { + Log::writeNewLog(__('Sesión', false), __('La sesión no puede ser inicializada', false)); + + header('HTTP/1.1 500 Internal Server Error'); + + self::initError(__('La sesión no puede ser inicializada'), __('Consulte con el administrador')); + } + } + /** * Comprobar si el usuario está logado. * diff --git a/inc/SP/Core/Plugin/PluginUtil.class.php b/inc/SP/Core/Plugin/PluginUtil.class.php index b5e731d2..249cb6b7 100644 --- a/inc/SP/Core/Plugin/PluginUtil.class.php +++ b/inc/SP/Core/Plugin/PluginUtil.class.php @@ -28,6 +28,7 @@ use ReflectionClass; use SP\Core\Exceptions\SPException; use SP\Core\Session; use SP\Log\Log; +use SP\Mgmt\Plugins\Plugin; /** * Class PluginUtil @@ -37,7 +38,11 @@ use SP\Log\Log; class PluginUtil { /** - * @var array Plugins ya cargados + * @var array Plugins habilitados + */ + private static $enabledPlugins; + /** + * @var PluginInterface[] Plugins ya cargados */ private static $loadedPlugins = []; /** @@ -99,9 +104,9 @@ class PluginUtil self::$loadedPlugins[$name] = $Plugin; return $Plugin; - } else { - self::$disabledPlugins[] = $name; } + + self::$disabledPlugins[] = $name; } catch (\ReflectionException $e) { Log::writeNewLog(__FUNCTION__, sprintf(__('No es posible cargar el plugin "%s"'), $name)); } catch (SPException $e) { @@ -163,4 +168,22 @@ class PluginUtil return false; } + + /** + * Devolver los plugins habilidatos + * + * @return PluginInterface[] + */ + public static function getEnabledPlugins() + { + if (self::$enabledPlugins !== null) { + return self::$enabledPlugins; + } + + foreach (Plugin::getItem()->getEnabled() as $plugin) { + self::$enabledPlugins[] = $plugin->plugin_name; + } + + return self::$enabledPlugins; + } } \ No newline at end of file diff --git a/inc/SP/Mgmt/Plugins/Plugin.class.php b/inc/SP/Mgmt/Plugins/Plugin.class.php index fccd3cc3..7566fb71 100644 --- a/inc/SP/Mgmt/Plugins/Plugin.class.php +++ b/inc/SP/Mgmt/Plugins/Plugin.class.php @@ -270,4 +270,20 @@ class Plugin extends PluginBase implements ItemInterface return DB::getResultsArray($Data); } + + /** + * Devolver los plugins activados + * + * @return array + */ + public function getEnabled() + { + $query = /** @lang SQL */ + 'SELECT plugin_name FROM plugins WHERE BIN(plugin_enabled) = 1'; + + $Data = new QueryData(); + $Data->setQuery($query); + + return DB::getResultsArray($Data); + } } \ No newline at end of file diff --git a/js/app-main.js b/js/app-main.js index f443591e..019f7e5d 100644 --- a/js/app-main.js +++ b/js/app-main.js @@ -35,7 +35,8 @@ sysPass.Main = function () { TIMEZONE: "", LOCALE: "", DEBUG: "", - COOKIES_ENABLED: false + COOKIES_ENABLED: false, + PLUGINS: [] }; // Atributos del generador de claves @@ -65,6 +66,9 @@ sysPass.Main = function () { // Objeto con las funciones para peticiones de la aplicación var appRequests = {}; + // Objeto con los plugins habilitados + var appPlugins = {}; + // Objeto con las propiedades públicas var oPublic = {}; @@ -288,6 +292,8 @@ sysPass.Main = function () { initializeClipboard(); setupCallbacks(); checkLogout(); + initPlugins(); + checkPluginUpdates(); }); return oPublic; @@ -330,6 +336,7 @@ sysPass.Main = function () { config.DEBUG = json.debug; config.MAX_FILE_SIZE = parseInt(json.max_file_size); config.COOKIES_ENABLED = json.cookies_enabled; + config.PLUGINS = json.plugins; Object.freeze(config); }); @@ -827,5 +834,33 @@ sysPass.Main = function () { return decodeHTMLEntities; })(); + /** + * Inicializar los plugins + */ + var initPlugins = function () { + log.info("initPlugins"); + + for (var plugin in config.PLUGINS) { + if (typeof sysPass.Plugin[plugin] === "function") { + appPlugins[plugin] = sysPass.Plugin[plugin](oProtected); + } + } + }; + + /** + * Comprobar si hay actualizaciones de plugins + */ + var checkPluginUpdates = function () { + log.info("checkPluginUpdates"); + + for (var plugin in appPlugins) { + if (typeof appPlugins[plugin]["checkVersion"] === "function") { + appPlugins[plugin]["checkVersion"]().then(function (data) { + log.info(data); + }) ; + } + } + }; + return init(); }; \ No newline at end of file diff --git a/js/app-main.min.js b/js/app-main.min.js index 9578d107..95679861 100644 --- a/js/app-main.min.js +++ b/js/app-main.min.js @@ -1,23 +1,23 @@ -var $jscomp={scope:{}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(b,f,g){if(g.get||g.set)throw new TypeError("ES3 does not support getters and setters.");b!=Array.prototype&&b!=Object.prototype&&(b[f]=g.value)};$jscomp.getGlobal=function(b){return"undefined"!=typeof window&&window===b?b:"undefined"!=typeof global?global:b};$jscomp.global=$jscomp.getGlobal(this);$jscomp.SYMBOL_PREFIX="jscomp_symbol_"; +var $jscomp={scope:{}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(b,h,d){if(d.get||d.set)throw new TypeError("ES3 does not support getters and setters.");b!=Array.prototype&&b!=Object.prototype&&(b[h]=d.value)};$jscomp.getGlobal=function(b){return"undefined"!=typeof window&&window===b?b:"undefined"!=typeof global&&null!=global?global:b};$jscomp.global=$jscomp.getGlobal(this);$jscomp.SYMBOL_PREFIX="jscomp_symbol_"; $jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.symbolCounter_=0;$jscomp.Symbol=function(b){return $jscomp.SYMBOL_PREFIX+(b||"")+$jscomp.symbolCounter_++}; -$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var b=$jscomp.global.Symbol.iterator;b||(b=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[b]&&$jscomp.defineProperty(Array.prototype,b,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(b){var f=0;return $jscomp.iteratorPrototype(function(){return f"+a.messages.join("
"));switch(b){case 0:k.ok(d);break;case 1:case 2:case 4:k.error(d); -break;case 3:k.warn(d);break;case 10:l.main.logout();break;case 100:k.ok(d);k.sticky(d);break;case 101:k.error(d);k.sticky(d);break;default:k.error(d)}}},html:{error:function(a){return'

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

"}}};Object.freeze(k);var x=function(){h.info("getEnvironment");var a=window.location.pathname.split("/");b.APP_ROOT=window.location.protocol+"//"+window.location.host+function(){for(var b="",e=1;e<=a.length-2;e++)b+="/"+a[e];return b}();var e=m.getRequestOpts(); -e.url="/ajax/ajax_getEnvironment.php";e.method="get";e.useLoading=!1;e.data={isAjax:1};return m.getActionCall(e,function(a){b.LANG=a.lang;b.PK=a.pk;b.CHECK_UPDATES=a.check_updates;b.CRYPT.setPublicKey(a.pk);b.TIMEZONE=a.timezone;b.LOCALE=a.locale;b.DEBUG=a.debug;b.MAX_FILE_SIZE=parseInt(a.max_file_size);b.COOKIES_ENABLED=a.cookies_enabled;Object.freeze(b)})},q={current:"",get:function(){h.info("sk:get");return $("#container").attr("data-sk")},set:function(a){h.info("sk:set");$("#container").attr("data-sk", -a);a.current=a}},y=function(){var a=$("#container");if(!a.hasClass("content-no-auto-resize")){var b=$("#content").height()+200;a.css("height",b)}},z=function(){$("html, body").animate({scrollTop:0},"slow")},A=function(a){for(var b=[],d,c=window.location.href.slice(window.location.href.indexOf("?")+1).split("&"),f=0;fb.MAX_FILE_SIZE)k.error(b.LANG[18]+"
"+r.name+" (Max: "+b.MAX_FILE_SIZE+")");else{var c;a:{c=r.name;for(var g=a.data("files-ext").toLowerCase().split(","),h=0;h<=g.length;h++)if(-1!==c.indexOf(g[h])){c= -!0;break a}c=!1}c?f(e[d]):k.error(b.LANG[19]+"
"+r.name)}}},g=function(a){var b=$("#fileUploadForm");!1===a&&b.hide();a=b.find("input[type='file']");a.on("change",function(){"function"===typeof d.beforeSendAction&&d.beforeSendAction();c(this.files)});return a};window.File&&window.FileList&&window.FileReader?function(){h.info("fileUpload:init");var b=g(!1);a.on("dragover dragenter",function(a){h.info("fileUpload:drag");a.stopPropagation();a.preventDefault()});a.on("drop",function(a){h.info("fileUpload:drop"); -a.stopPropagation();a.preventDefault();"function"===typeof d.beforeSendAction&&d.beforeSendAction();c(a.originalEvent.dataTransfer.files)});a.on("click",function(){b.click()})}():g(!0);return d},D=function(a){h.info("checkPassLevel");f.passLength=a.val().length;v(zxcvbn(a.val()),a)},v=function(a,e){h.info("outputResult");var d=$(".passLevel-"+e.attr("id")),c=a.score;d.show();d.removeClass("weak good strong strongest");0===f.passLength?d.attr("title","").empty():f.passLengtha.secondary?a.calc=a.main/a.rel:a.maina.secondary&&(a.main*=a.factor,g(a));return a},k=function(){f.main=b;f.secondary=d;var e=g(f);a.css({width:e.main,height:e.calc});c.width= -e.main;c.height=e.calc},l=function(){f.main=d;f.secondary=b;var e=g(f);a.css({width:e.calc,height:e.main});c.width=e.calc;c.height=e.main};c.width>b?k():c.height>d&&(h.info("height"),l());return c},E=function(){var a=document.createElement("div");return function(b){b&&"string"===typeof b&&(b=b.replace(/]*>([\S\s]*?)<\/script>/gmi,""),b=b.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi,""),a.innerHTML=b,b=a.textContent,a.textContent="");return b}}();return function(){h.info("init");p={actions:function(){return l}, -triggers:function(){return c},theme:function(){return g},sk:q,msg:k,log:h,passwordData:f,outputResult:v,checkPassLevel:D,encryptFormValue:u,fileUpload:C,redirect:t,scrollUp:z,setContentSize:y};n=$.extend({log:h,config:function(){return b},appTheme:function(){return g},appActions:function(){return l},appTriggers:function(){return c},appRequests:function(){return m},evalAction:H,resizeImage:I},p);Object.freeze(p);Object.freeze(n);c=sysPass.Triggers(n);l=sysPass.Actions(n);m=sysPass.Requests(n);"function"=== -typeof sysPass.Theme&&(g=sysPass.Theme(n));x().then(function(){""!==b.PK&&G();!0===b.CHECK_UPDATES&&l.main.getUpdates();!1===b.COOKIES_ENABLED&&k.sticky(b.LANG[64]);F();w();B()});return p}()}; +$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var b=$jscomp.global.Symbol.iterator;b||(b=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[b]&&$jscomp.defineProperty(Array.prototype,b,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(b){var h=0;return $jscomp.iteratorPrototype(function(){return h"+a.messages.join("
"));switch(b){case 0:k.ok(c); +break;case 1:case 2:case 4:k.error(c);break;case 3:k.warn(c);break;case 10:l.main.logout();break;case 100:k.ok(c);k.sticky(c);break;case 101:k.error(c);k.sticky(c);break;default:k.error(c)}}},html:{error:function(a){return'

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

"}}};Object.freeze(k);var y=function(){g.info("getEnvironment");var a=window.location.pathname.split("/");b.APP_ROOT=window.location.protocol+"//"+window.location.host+function(){for(var b="",e=1;e<=a.length-2;e++)b+="/"+ +a[e];return b}();var e=m.getRequestOpts();e.url="/ajax/ajax_getEnvironment.php";e.method="get";e.useLoading=!1;e.data={isAjax:1};return m.getActionCall(e,function(a){b.LANG=a.lang;b.PK=a.pk;b.CHECK_UPDATES=a.check_updates;b.CRYPT.setPublicKey(a.pk);b.TIMEZONE=a.timezone;b.LOCALE=a.locale;b.DEBUG=a.debug;b.MAX_FILE_SIZE=parseInt(a.max_file_size);b.COOKIES_ENABLED=a.cookies_enabled;b.PLUGINS=a.plugins;Object.freeze(b)})},r={current:"",get:function(){g.info("sk:get");return $("#container").attr("data-sk")}, +set:function(a){g.info("sk:set");$("#container").attr("data-sk",a);a.current=a}},z=function(){var a=$("#container");if(!a.hasClass("content-no-auto-resize")){var b=$("#content").height()+200;a.css("height",b)}},A=function(){$("html, body").animate({scrollTop:0},"slow")},B=function(a){for(var b=[],c,g=window.location.href.slice(window.location.href.indexOf("?")+1).split("&"),f=0;fb.MAX_FILE_SIZE)k.error(b.LANG[18]+"
"+t.name+" (Max: "+b.MAX_FILE_SIZE+")");else{var g;a:{g=t.name;for(var h=a.data("files-ext").toLowerCase().split(","), +d=0;d<=h.length;d++)if(-1!==g.indexOf(h[d])){g=!0;break a}g=!1}g?f(e[c]):k.error(b.LANG[19]+"
"+t.name)}}},d=function(a){var b=$("#fileUploadForm");!1===a&&b.hide();a=b.find("input[type='file']");a.on("change",function(){"function"===typeof c.beforeSendAction&&c.beforeSendAction();h(this.files)});return a};window.File&&window.FileList&&window.FileReader?function(){g.info("fileUpload:init");var b=d(!1);a.on("dragover dragenter",function(a){g.info("fileUpload:drag");a.stopPropagation();a.preventDefault()}); +a.on("drop",function(a){g.info("fileUpload:drop");a.stopPropagation();a.preventDefault();"function"===typeof c.beforeSendAction&&c.beforeSendAction();h(a.originalEvent.dataTransfer.files)});a.on("click",function(){b.click()})}():d(!0);return c},E=function(a){g.info("checkPassLevel");h.passLength=a.val().length;w(zxcvbn(a.val()),a)},w=function(a,e){g.info("outputResult");var c=$(".passLevel-"+e.attr("id")),d=a.score;c.show();c.removeClass("weak good strong strongest");0===h.passLength?c.attr("title", +"").empty():h.passLengtha.secondary?a.calc=a.main/a.rel:a.maina.secondary&&(a.main*=a.factor,h(a));return a},k=function(){f.main=b;f.secondary=c;var e=h(f);a.css({width:e.main, +height:e.calc});d.width=e.main;d.height=e.calc},l=function(){f.main=c;f.secondary=b;var e=h(f);a.css({width:e.calc,height:e.main});d.width=e.calc;d.height=e.main};d.width>b?k():d.height>c&&(g.info("height"),l());return d},F=function(){var a=document.createElement("div");return function(b){b&&"string"===typeof b&&(b=b.replace(/]*>([\S\s]*?)<\/script>/gmi,""),b=b.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi,""),a.innerHTML=b,b=a.textContent,a.textContent="");return b}}(),K=function(){g.info("checkPluginUpdates"); +for(var a in p)"function"===typeof p[a].checkVersion&&p[a].checkVersion().then(function(a){g.info(a)})};return function(){g.info("init");q={actions:function(){return l},triggers:function(){return f},theme:function(){return d},sk:r,msg:k,log:g,passwordData:h,outputResult:w,checkPassLevel:E,encryptFormValue:v,fileUpload:D,redirect:u,scrollUp:A,setContentSize:z};n=$.extend({log:g,config:function(){return b},appTheme:function(){return d},appActions:function(){return l},appTriggers:function(){return f}, +appRequests:function(){return m},evalAction:I,resizeImage:J},q);Object.freeze(q);Object.freeze(n);f=sysPass.Triggers(n);l=sysPass.Actions(n);m=sysPass.Requests(n);"function"===typeof sysPass.Theme&&(d=sysPass.Theme(n));y().then(function(){""!==b.PK&&H();!0===b.CHECK_UPDATES&&l.main.getUpdates();!1===b.COOKIES_ENABLED&&k.sticky(b.LANG[64]);G();x();C();g.info("initPlugins");for(var a in b.PLUGINS)"function"===typeof sysPass.Plugin[a]&&(p[a]=sysPass.Plugin[a](n));K()});return q}()};