diff --git a/CHANGELOG b/CHANGELOG index 94d763c4e..55eeb64dd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -350,6 +350,8 @@ -------------------------------------------------------------------------------- - add Slim middleware for Basic authentication (can be used by extensions) - rest api endpoint 'statstotal' returns number of groups and categories +- add new command line program utils/console +- major code polishing -------------------------------------------------------------------------------- Changes in version 5.1.42 diff --git a/build.xml b/build.xml index 34f22a802..fcb335e52 100644 --- a/build.xml +++ b/build.xml @@ -90,6 +90,9 @@ + + + diff --git a/composer-dist.json b/composer-dist.json index e108080b0..ef9159626 100644 --- a/composer-dist.json +++ b/composer-dist.json @@ -22,7 +22,16 @@ "psr-4": { "SeedDMS\\Console\\": "seeddms/utils" }, - "classmap": ["seeddms/inc/inc.ClassTranslator.php", "seeddms/inc/inc.ClassSettings.php", "seeddms/inc/inc.Version.php", "seeddms/inc/inc.ClassViewCommon.php", "seeddms/inc/inc.ClassControllerCommon.php", "seeddms/inc/inc.ClassController.php"] + "classmap": [ + "seeddms/inc/inc.ClassTranslator.php", + "seeddms/inc/inc.ClassSettings.php", + "seeddms/inc/inc.Version.php", + "seeddms/inc/inc.ClassViewCommon.php", + "seeddms/inc/inc.ClassControllerCommon.php", + "seeddms/inc/inc.ClassController.php", + "seeddms/inc/inc.ClassSession.php", + "seeddms/inc/inc.ClassUtilities.php" + ] }, "require": { "pear/http_request2": "^2", diff --git a/composer.json b/composer.json index c032385d5..e28f81eaf 100644 --- a/composer.json +++ b/composer.json @@ -20,10 +20,19 @@ } }, "autoload": { - "psr-4": { - "Seeddms\\Console\\": "utils" - }, - "classmap": ["inc/inc.ClassTranslator.php", "inc/inc.ClassSettings.php", "inc/inc.Version.php", "inc/inc.ClassViewCommon.php", "inc/inc.ClassControllerCommon.php", "inc/inc.ClassController.php"] + "psr-4": { + "Seeddms\\Console\\": "utils" + }, + "classmap": [ + "inc/inc.ClassTranslator.php", + "inc/inc.ClassSettings.php", + "inc/inc.Version.php", + "inc/inc.ClassViewCommon.php", + "inc/inc.ClassControllerCommon.php", + "inc/inc.ClassController.php", + "inc/inc.ClassSession.php", + "inc/inc.ClassUtilities.php" + ] }, "require": { "php": ">=8.2.0", diff --git a/inc/inc.Authentication.php b/inc/inc.Authentication.php index 58e150672..aea48fa82 100644 --- a/inc/inc.Authentication.php +++ b/inc/inc.Authentication.php @@ -12,6 +12,8 @@ * @version Release: @package_version@ */ +use Seeddms\Seeddms\Session; + require_once("inc.ClassSession.php"); require_once("inc.ClassAccessOperation.php"); @@ -27,7 +29,7 @@ $isajax = isset($_GET['action']) && ($_GET['action'] != 'show'); if (!isset($_COOKIE["mydms_session"])) { if($settings->_enableGuestLogin && $settings->_enableGuestAutoLogin) { - $session = new SeedDMS_Session($db); + $session = new Session($db); if(!$dms_session = $session->create(array('userid'=>$settings->_guestID, 'theme'=>$settings->_theme, 'lang'=>$settings->_language))) { if(!$isajax) header("Location: " . $settings->_httpRoot . "out/out.Login.php?referuri=".$refer); @@ -50,7 +52,7 @@ if (!isset($_COOKIE["mydms_session"])) { $lang = $settings->_language; $user->setLanguage($lang); } - $session = new SeedDMS_Session($db); + $session = new Session($db); if(!$dms_session = $session->create(array('userid'=>$user->getID(), 'theme'=>$theme, 'lang'=>$lang))) { if(!$isajax) header("Location: " . $settings->_httpRoot . "out/out.Login.php?referuri=".$refer); @@ -65,7 +67,7 @@ if (!isset($_COOKIE["mydms_session"])) { } else { /* Load session */ $dms_session = $_COOKIE["mydms_session"]; - $session = new SeedDMS_Session($db); + $session = new Session($db); if(!$resArr = $session->load($dms_session)) { setcookie("mydms_session", $dms_session, time()-3600, $settings->_httpRoot); //delete cookie if(!$isajax) diff --git a/inc/inc.ClassAuthenticationMiddleware.php b/inc/inc.ClassAuthenticationMiddleware.php index f406747cf..62795e4bf 100644 --- a/inc/inc.ClassAuthenticationMiddleware.php +++ b/inc/inc.ClassAuthenticationMiddleware.php @@ -30,6 +30,8 @@ * @link https://www.seeddms.org Main Site */ +use Seeddms\Seeddms\Session; + /* Middleware for authentication based on session */ class SeedDMS_Auth_Middleware_Session { /* {{{ */ @@ -67,8 +69,8 @@ class SeedDMS_Auth_Middleware_Session { /* {{{ */ } $logger->log("Invoke AuthSessionMiddleware for method " . $request->getMethod() . " on '" . $request->getUri()->getPath() . "'", PEAR_LOG_INFO); - require_once("inc/inc.ClassSession.php"); - $session = new SeedDMS_Session($dms->getDb()); +// require_once("inc/inc.ClassSession.php"); + $session = new Session($dms->getDb()); if (isset($_COOKIE["mydms_session"])) { $dms_session = $_COOKIE["mydms_session"]; $logger->log("Session key: " . $dms_session, PEAR_LOG_DEBUG); diff --git a/inc/inc.ClassExtensionMgr.php b/inc/inc.ClassExtensionMgr.php index e199e9836..e9402e31f 100644 --- a/inc/inc.ClassExtensionMgr.php +++ b/inc/inc.ClassExtensionMgr.php @@ -14,6 +14,10 @@ * @version Release: @package_version@ */ +namespace Seeddms\Seeddms; + +use Seeddms\Seeddms\Utilities; + /** * Class to represent an extension manager * @@ -25,7 +29,7 @@ * @copyright 2011 Uwe Steinmann * @version Release: @package_version@ */ -class SeedDMS_Extension_Mgr { +class ExtensionMgr { /** * @var string $extdir directory where extensions are located * @access protected @@ -179,6 +183,10 @@ class SeedDMS_Extension_Mgr { return $this->cachedir."/extensions.php"; } /* }}} */ + public function setRepositoryUrl($reposurl) { /* {{{ */ + $this->reposurl = $reposurl; + } /* }}} */ + /** * Get the configuration of extensions * @@ -262,14 +270,14 @@ $EXT_CONF = '.var_export($EXT_CONF, true).';'); unlink ($destination); } - $zip = new ZipArchive(); - if (!$zip->open($destination, ZIPARCHIVE::CREATE)) { + $zip = new \ZipArchive(); + if (!$zip->open($destination, \ZipArchive::CREATE)) { return false; } $source = str_replace('\\', '/', realpath($source)); if (is_dir($source) === true) { - $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST); + $files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source), \RecursiveIteratorIterator::SELF_FIRST); if ($include_dir) { $arr = explode("/",$source); @@ -330,7 +338,7 @@ $EXT_CONF = '.var_export($EXT_CONF, true).';'); $tmpfile = $this->cachedir."/".$extname."-".$version.".zip"; } - if(!SeedDMS_Extension_Mgr::Zip($this->extdir."/".$extname, $tmpfile)) { + if(!ExtensionMgr::Zip($this->extdir."/".$extname, $tmpfile)) { return false; } // $cmd = "cd ".$this->extdir."/".$extname."; zip -r ".$tmpfile." ."; @@ -406,14 +414,19 @@ $EXT_CONF = '.var_export($EXT_CONF, true).';'); } /* }}} */ /** - * Check content of extension directory or configuration of extension + * Check configuration of extension * - * @param string|array $dir full path to extension directory or extension name - * or an array containing the configuration. - * @param array $options array with options elements 'noconstraints' and 'nofiles'. - * Set 'noconstraints' to true if - * constraints to local seeddms installation shall not be checked. Set 'nofiles' - * to true to turn off checking of files + * This method checks if the configurations of an extension is complete + * and all dependencies specified in the configuration are met. + * + * @param string $extname not used anymore. Was previously use to store + * result of the check into $this->configcache, but this method can be + * used for installed extensions and those in the repository, which makes + * the use of a cache useless. + * @param array $extconf extension configuration to be checked + * @param array $options array with option element 'noconstraints'. + * Set 'noconstraints' to true if constraints to local seeddms + * installation shall not be checked. * @return boolean true if check was successful, otherwise false */ public function checkExtensionByName($extname, $extconf, $options=array()) { /* {{{ */ @@ -444,7 +457,7 @@ $EXT_CONF = '.var_export($EXT_CONF, true).';'); foreach($extconf['constraints']['depends'] as $dkey=>$dval) { switch($dkey) { case 'seeddms': - $version = new SeedDMS_Version; + $version = new Version; if(is_array($dval)) { $fullfill = false; foreach($dval as $ddval) { @@ -521,13 +534,13 @@ $EXT_CONF = '.var_export($EXT_CONF, true).';'); $newdir = addDirSep($this->cachedir)."ext.new"; /* First remove a left over from a previous extension */ if(file_exists($newdir)) { - SeedDMS_Utils::rrmdir($newdir); + Utilities::rrmdir($newdir); } if(!mkdir($newdir, 0755)) { $this->errmsgs[] = "Cannot create temp. extension directory"; return false; } - $zip = new ZipArchive; + $zip = new \ZipArchive; $res = $zip->open($file); if ($res === TRUE) { $zip->extractTo($newdir); @@ -541,7 +554,7 @@ $EXT_CONF = '.var_export($EXT_CONF, true).';'); /* Check if extension is complete and fullfills the constraints */ if(!self::checkExtensionByDir($newdir)) { - SeedDMS_Utils::rrmdir($newdir); + Utilities::rrmdir($newdir); return false; } @@ -552,11 +565,11 @@ $EXT_CONF = '.var_export($EXT_CONF, true).';'); if(!is_dir($this->extdir)) { if(!mkdir($this->extdir, 0755)) { $this->errmsgs[] = "Cannot create extension directory"; - SeedDMS_Utils::rrmdir($newdir); + Utilities::rrmdir($newdir); return false; } } elseif(is_dir($this->extdir ."/". $extname)) { - SeedDMS_Utils::rrmdir($this->extdir ."/". $extname); + Utilities::rrmdir($this->extdir ."/". $extname); } /* Move the temp. created ext directory to the final location */ /* rename() may fail if dirs are moved from one device to another. @@ -578,7 +591,7 @@ $EXT_CONF = '.var_export($EXT_CONF, true).';'); * has been copied. */ $this->errmsgs[] = "Cannot move temp. extension directory to final destination"; - SeedDMS_Utils::rrmdir($this->extdir ."/". $extname); + Utilities::rrmdir($this->extdir ."/". $extname); return false; } @@ -592,7 +605,7 @@ $EXT_CONF = '.var_export($EXT_CONF, true).';'); * single lines. Each line is either a comment if it starts with an '#' * or a json encoded array containing the extension configuration. * - * Run SeedDMS_Extension_Mgr::updateExtensionList() to ensure the + * Run Seeddms\Seeddms\ExtensionMgr::updateExtensionList() to ensure the * currently cached extension list file is up to date. * * @return string[] list of json strings or comments @@ -612,7 +625,7 @@ $EXT_CONF = '.var_export($EXT_CONF, true).';'); * a list of extension configurations. Only the most recent version * of an extension will be included. * - * Run SeedDMS_Extension_Mgr::updateExtensionList() to ensure the + * Run Seeddms\Seeddms\ExtensionMgr::updateExtensionList() to ensure the * currently cached extension list file is up to date. * * @return array[] list of extension configurations @@ -644,7 +657,7 @@ $EXT_CONF = '.var_export($EXT_CONF, true).';'); * a list of extension configurations. Only those extensions will * be included which maches the given name. * - * Run SeedDMS_Extension_Mgr::updateExtensionList() to ensure the + * Run Seeddms\Seeddms\ExtensionMgr::updateExtensionList() to ensure the * currently cached extension list file is up to date. * * @return array[] list of extension configurations @@ -660,13 +673,16 @@ $EXT_CONF = '.var_export($EXT_CONF, true).';'); } } } - uksort($result, function($a, $b){return SeedDMS_Extension_Mgr::cmpVersion($b, $a);}); + uksort($result, function($a, $b){return ExtensionMgr::cmpVersion($b, $a);}); return $result; } /* }}} */ /** * Import list of extension from repository * + * Will also update the list in the cache, which is used by getExtensionList() + * and getExtensionListByName(). + * * @param boolean $force force download even if file already exists */ public function updateExtensionList($version='', $force=false) { /* {{{ */ @@ -704,9 +720,13 @@ $EXT_CONF = '.var_export($EXT_CONF, true).';'); */ public function getExtensionFromRepository($file) { /* {{{ */ $content = file_get_contents($this->reposurl."/".$file, false, $this->getStreamContext()); - $tmpfile = tempnam(sys_get_temp_dir(), ''); - file_put_contents($tmpfile, $content); - return $tmpfile; + if ($content) { + $tmpfile = tempnam(sys_get_temp_dir(), ''); + file_put_contents($tmpfile, $content); + return $tmpfile; + } else { + return false; + } } /* }}} */ /** @@ -730,3 +750,5 @@ $EXT_CONF = '.var_export($EXT_CONF, true).';'); return $this->errmsgs; } /* }}} */ } + +class_alias('Seeddms\Seeddms\ExtensionMgr', 'SeedDMS_Extension_Mgr'); diff --git a/inc/inc.ClassSession.php b/inc/inc.ClassSession.php index e1f1c1b8e..9ae55d518 100644 --- a/inc/inc.ClassSession.php +++ b/inc/inc.ClassSession.php @@ -15,6 +15,8 @@ * @version Release: @package_version@ */ +namespace Seeddms\Seeddms; + /** * Class to represent a session * @@ -29,7 +31,7 @@ * @copyright 2011 Uwe Steinmann * @version Release: @package_version@ */ -class SeedDMS_Session { +class Session { /** * @var object $db reference to database object. This must be an instance * of {@link SeedDMS_Core_DatabaseAccess}. @@ -53,7 +55,7 @@ class SeedDMS_Session { * Create a new instance of the session handler * * @param object $db object to access the underlying database - * @return object instance of SeedDMS_Session + * @return object instance of Seeddms\Seeddms\Session */ function __construct($db) { /* {{{ */ $this->db = $db; @@ -417,6 +419,8 @@ class SeedDMS_Session { } +class_alias('Seeddms\Seeddms\Session', 'SeedDMS_Session'); + /** * Class for managing sessions * @@ -428,7 +432,7 @@ class SeedDMS_Session { * @copyright 2014 Uwe Steinmann * @version Release: @package_version@ */ -class SeedDMS_SessionMgr { +class SessionMgr { /** * @var object $db reference to database object. This must be an instance * of {@link SeedDMS_Core_DatabaseAccess}. @@ -440,7 +444,7 @@ class SeedDMS_SessionMgr { * Create a new instance of the session manager * * @param object $db object to access the underlying database - * @return object instance of SeedDMS_SessionMgr + * @return object instance of Seeddms\Seeddms\SessionMgr */ function __construct($db) { /* {{{ */ $this->db = $db; @@ -478,7 +482,7 @@ class SeedDMS_SessionMgr { return false; $sessions = array(); foreach($resArr as $rec) { - $session = new SeedDMS_Session($this->db); + $session = new Session($this->db); $session->load($rec['id']); $sessions[] = $session; } @@ -501,7 +505,7 @@ class SeedDMS_SessionMgr { return false; $sessions = array(); foreach($resArr as $rec) { - $session = new SeedDMS_Session($this->db); + $session = new Session($this->db); $session->load($rec['id']); $sessions[] = $session; } @@ -523,7 +527,7 @@ class SeedDMS_SessionMgr { return false; $sessions = array(); foreach($resArr as $rec) { - $session = new SeedDMS_Session($this->db); + $session = new Session($this->db); $session->load($rec['id']); $sessions[] = $session; } @@ -531,3 +535,5 @@ class SeedDMS_SessionMgr { } /* }}} */ } + +class_alias('Seeddms\Seeddms\SessionMgr', 'SeedDMS_SessionMgr'); diff --git a/inc/inc.ClassSettings.php b/inc/inc.ClassSettings.php index 4804eb46c..d386e3c9f 100644 --- a/inc/inc.ClassSettings.php +++ b/inc/inc.ClassSettings.php @@ -1977,3 +1977,4 @@ class Settings { /* {{{ */ } /* }}} */ +class_alias('Seeddms\Seeddms\Settings', 'SeedDMS_Settings'); diff --git a/inc/inc.ClassTranslator.php b/inc/inc.ClassTranslator.php index ef2e5577e..6c0aaab4a 100644 --- a/inc/inc.ClassTranslator.php +++ b/inc/inc.ClassTranslator.php @@ -21,7 +21,7 @@ use SeedDMS_Core_AttributeDefinition; * @category DMS * @package SeedDMS * @author Uwe Steinmann - * @copyright Copyright (C) 2011 Uwe Steinmann + * @copyright Copyright (C) 2025 Uwe Steinmann * @version Release: @package_version@ */ class Translator { /* {{{ */ diff --git a/inc/inc.ClassUtilities.php b/inc/inc.ClassUtilities.php new file mode 100644 index 000000000..eeb853c62 --- /dev/null +++ b/inc/inc.ClassUtilities.php @@ -0,0 +1,94 @@ + + * @copyright Copyright (C) 2025 Uwe Steinmann + * @version Release: @package_version@ + */ + +namespace Seeddms\Seeddms; + +/** + * Class with various methods + * + * @category DMS + * @package SeedDMS + * @author Uwe Steinmann + * @copyright Copyright (C) 2025 Uwe Steinmann + * @version Release: @package_version@ + */ +class Utilities { /* {{{ */ + + /** + * Recursively remove a directory on disc + * + * @param string $dir name of directory + */ + static public function rrmdir($dir) { /* {{{ */ + if (is_dir($dir)) { + $objects = scandir($dir); + foreach ($objects as $object) { + if ($object != "." && $object != "..") { + if (filetype($dir."/".$object) == "dir") self::rrmdir($dir."/".$object); else unlink($dir."/".$object); + } + } + reset($objects); + rmdir($dir); + } + } /* }}} */ + + /** + * Create a random string + * + * @param integer $n number of chars + * @param string $alph alphabet used as source for chars + * @return string random string + */ + static public function makeRandomString($n, $alph = "0123456789abcdefghijklmnopqrstuvwxyz") { /* {{{ */ + $s = ""; + for ($i = 0; $i != $n; ++$i) + $s .= $alph[mt_rand(0, 35)]; + return $s; + } /* }}} */ + + /** + * Create a real uniqid for cryptographic purposes + * + * @ return string + */ + static public function uniqidReal($lenght = 13) { /* {{{ */ + // uniqid gives 13 chars, but you could adjust it to your needs. + if (function_exists("random_bytes")) { + $bytes = random_bytes(ceil($lenght / 2)); + } elseif (function_exists("openssl_random_pseudo_bytes")) { + $bytes = openssl_random_pseudo_bytes(ceil($lenght / 2)); + } else { + throw new Exception("no cryptographically secure random function available"); + } + return substr(bin2hex($bytes), 0, $lenght); + } /* }}} */ + + /** + * Return nonce for CSP + * + * @return string + */ + static public function createNonce() { /* {{{ */ + $length = 16; + $usable = true; + $bytes = openssl_random_pseudo_bytes($length, $usable); + if ($usable === false) { + // weak + // @TODO do something? + } + return base64_encode($bytes); + } /* }}} */ + +} /* }}} */ + +class_alias('Seeddms\Seeddms\Utilities', 'SeedDMS_Utils'); diff --git a/inc/inc.Language.php b/inc/inc.Language.php index c9f3e609e..0a63bf0a4 100644 --- a/inc/inc.Language.php +++ b/inc/inc.Language.php @@ -23,6 +23,10 @@ use Seeddms\Seeddms\Translator; $translator = new Translator($settings); $translator->init(); +/* All remaining functions in this file are deprecated and should + * not be used anymore. Use instead the equivalent methods in class + * Translator; + */ function getAvailableLanguages() { /* {{{ */ trigger_error("getAvailableLanguages() is deprecated.", E_USER_DEPRECATED); foreach(debug_backtrace() as $n) { diff --git a/inc/inc.Utils.php b/inc/inc.Utils.php index 98c87485d..98bb539f5 100644 --- a/inc/inc.Utils.php +++ b/inc/inc.Utils.php @@ -650,7 +650,7 @@ function checkFormKey($formid='', $method='POST') { /* {{{ */ * quota is reached. Negative values indicate a disk usage above quota. */ function checkQuota($user) { /* {{{ */ - global $settings, $dms; + global $settings; /* check if quota is turn off system wide */ if($settings->_quota == 0) @@ -1025,39 +1025,6 @@ function resolveTask($task) { /* {{{ */ return $task; } /* }}} */ -/** - * Return nonce for CSP - * - * @return string - */ -function createNonce() { /* {{{ */ - $length = 16; - $usable = true; - $bytes = openssl_random_pseudo_bytes($length, $usable); - if ($usable === false) { - // weak - // @TODO do something? - } - return base64_encode($bytes); -} /* }}} */ - -/** - * Create a real uniqid for cryptographic purposes - * - * @ return string - */ -function uniqidReal($lenght = 13) { - // uniqid gives 13 chars, but you could adjust it to your needs. - if (function_exists("random_bytes")) { - $bytes = random_bytes(ceil($lenght / 2)); - } elseif (function_exists("openssl_random_pseudo_bytes")) { - $bytes = openssl_random_pseudo_bytes(ceil($lenght / 2)); - } else { - throw new Exception("no cryptographically secure random function available"); - } - return substr(bin2hex($bytes), 0, $lenght); -} - /** * Compare function for sorting users by login * @@ -1290,47 +1257,7 @@ function getMandatoryApprovers($folder, $document, $user) { /* {{{ */ return $approvers; } /* }}} */ -/** - * Class with various utility methods - * - * This class will sooner or later comprise the functions above - * - */ -class SeedDMS_Utils { /* {{{ */ - - /** - * Recursively remove a directory on disc - * - * @param string $dir name of directory - */ - static public function rrmdir($dir) { /* {{{ */ - if (is_dir($dir)) { - $objects = scandir($dir); - foreach ($objects as $object) { - if ($object != "." && $object != "..") { - if (filetype($dir."/".$object) == "dir") self::rrmdir($dir."/".$object); else unlink($dir."/".$object); - } - } - reset($objects); - rmdir($dir); - } - } /* }}} */ - - /** - * Create a random string - * - * @param integer $n number of chars - * @param string $alph alphabet used as source for chars - * @return string random string - */ - static public function makeRandomString($n, $alph = "0123456789abcdefghijklmnopqrstuvwxyz") { /* {{{ */ - $s = ""; - for ($i = 0; $i != $n; ++$i) - $s .= $alph[mt_rand(0, 35)]; - return $s; - } /* }}} */ - -} /* }}} */ +require_once "inc/inc.ClassUtilities.php"; /** * Class for creating encrypted api keys diff --git a/inc/inc.Version.php b/inc/inc.Version.php index 2a11a1185..e951d66d7 100644 --- a/inc/inc.Version.php +++ b/inc/inc.Version.php @@ -18,7 +18,9 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -class SeedDMS_Version { /* {{{ */ +namespace Seeddms\Seeddms; + +class Version { /* {{{ */ const _number = "6.0.36"; const _string = "SeedDMS"; @@ -47,7 +49,7 @@ class SeedDMS_Version { /* {{{ */ function banner() { /* {{{ */ return self::_string .", ". self::_number; - } + } /* }}} */ /** * Compare two version @@ -84,3 +86,4 @@ class SeedDMS_Version { /* {{{ */ } /* }}} */ +class_alias('Seeddms\Seeddms\Version', 'SeedDMS_Version'); diff --git a/op/op.Ajax.php b/op/op.Ajax.php index efcb954d0..432fd5bd1 100644 --- a/op/op.Ajax.php +++ b/op/op.Ajax.php @@ -29,6 +29,8 @@ require_once("../inc/inc.ClassUI.php"); require_once("../inc/inc.ClassController.php"); require_once("../inc/inc.Notification.php"); +use Seeddms\Seeddms\Session; + require_once("../inc/inc.ClassSession.php"); require_once("../inc/inc.ClassPasswordStrength.php"); require_once("../inc/inc.ClassPasswordHistoryManager.php"); @@ -36,7 +38,7 @@ require_once("../inc/inc.ClassPasswordHistoryManager.php"); /* Load session */ if (isset($_COOKIE["mydms_session"])) { $dms_session = $_COOKIE["mydms_session"]; - $session = new SeedDMS_Session($db); + $session = new Session($db); if(!$resArr = $session->load($dms_session)) { header('Content-Type: application/json'); echo json_encode(array('error'=>1)); diff --git a/op/op.Login.php b/op/op.Login.php index f8a3d3632..135c5aefc 100644 --- a/op/op.Login.php +++ b/op/op.Login.php @@ -18,6 +18,8 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +use Seeddms\Seeddms\Session; + include("../inc/inc.Settings.php"); include("../inc/inc.Utils.php"); include("../inc/inc.LogInit.php"); @@ -67,7 +69,7 @@ if(isset($_REQUEST["lang"]) && strlen($_REQUEST["lang"])>0 && is_numeric(array_s $lang = (string) $_REQUEST["lang"]; } -$session = new SeedDMS_Session($db); +$session = new Session($db); // TODO: by the PHP manual: The superglobals $_GET and $_REQUEST are already decoded. // Using urldecode() on an element in $_GET or $_REQUEST could have unexpected and dangerous results. diff --git a/op/op.Logout.php b/op/op.Logout.php index 70d089139..6acc9166b 100644 --- a/op/op.Logout.php +++ b/op/op.Logout.php @@ -23,12 +23,14 @@ include("../inc/inc.Utils.php"); include("../inc/inc.LogInit.php"); include("../inc/inc.Language.php"); include("../inc/inc.Init.php"); -include("../inc/inc.Extension.php"); +//include("../inc/inc.Extension.php"); include("../inc/inc.ClassSession.php"); include("../inc/inc.ClassController.php"); include("../inc/inc.DBInit.php"); include("../inc/inc.Authentication.php"); +use Seeddms\Seeddms\Session; + $tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); $controller = Controller::factory($tmp[1], array('dms'=>$dms, 'user'=>$user)); @@ -36,7 +38,7 @@ $controller = Controller::factory($tmp[1], array('dms'=>$dms, 'user'=>$user)); if(isset($_COOKIE['mydms_session'])) { $dms_session = $_COOKIE["mydms_session"]; - $session = new SeedDMS_Session($db); + $session = new Session($db); $session->load($dms_session); // If setting the user id to 0 worked, it would be a way to logout a diff --git a/restapi/index.php b/restapi/index.php index dc369221f..2b9d98444 100644 --- a/restapi/index.php +++ b/restapi/index.php @@ -25,6 +25,7 @@ use Psr\Http\Server\MiddlewareInterface; use DI\ContainerBuilder; use Slim\Factory\AppFactory; use Seeddms\Seeddms\Translator; +use Seeddms\Seeddms\Session; final class JsonRenderer { /* {{{ */ public function json( @@ -274,7 +275,7 @@ final class SeedDMS_RestapiController { /* {{{ */ return $this->renderer->json($response, array('success'=>false, 'message'=>'Login failed', 'data'=>''))->withStatus(403); } else { require_once("../inc/inc.ClassSession.php"); - $session = new SeedDMS_Session($dms->getDb()); + $session = new Session($dms->getDb()); if(!$id = $session->create(array('userid'=>$userobj->getId(), 'theme'=>$userobj->getTheme(), 'lang'=>$userobj->getLanguage()))) { return $this->renderer->json($response, array('success'=>false, 'message'=>'Creating session failed', 'data'=>''))->withStatus(500); } @@ -301,7 +302,7 @@ final class SeedDMS_RestapiController { /* {{{ */ $dms_session = $_COOKIE["mydms_session"]; $db = $dms->getDb(); - $session = new SeedDMS_Session($db); + $session = new Session($db); $session->load($dms_session); // If setting the user id to 0 worked, it would be a way to logout a @@ -3271,7 +3272,7 @@ class RestapiAuthMiddleware implements MiddlewareInterface { /* {{{ */ } else { $logger->log("Checking for valid session", PEAR_LOG_INFO); require_once("../inc/inc.ClassSession.php"); - $session = new SeedDMS_Session($dms->getDb()); + $session = new Session($dms->getDb()); if (isset($_COOKIE["mydms_session"])) { $logger->log("Found cookie for session", PEAR_LOG_INFO); $dms_session = $_COOKIE["mydms_session"]; diff --git a/utils/Commands/CheckextensionCommand.php b/utils/Commands/CheckextensionCommand.php new file mode 100644 index 000000000..564882d27 --- /dev/null +++ b/utils/Commands/CheckextensionCommand.php @@ -0,0 +1,71 @@ +settings = $settings; + $this->logger = $logger; + $this->translator = $translator; + $this->extmgr = $extmgr; + parent::__construct(); + } + + protected function configure() + { + $this->setName('ext:check') + ->setDescription('Check extensions') + ->setHelp('Checks all installed extensions for completeness and dependencies.') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $settings = $this->settings; + $logger = $this->logger; + $translator = $this->translator; + $extmgr = $this->extmgr; + + $output->writeln("Using configuration from '".$settings->_configFilePath."'.", OutputInterface::VERBOSITY_VERBOSE); + + $extconfs = $extmgr->getExtensionConfiguration(); + foreach ($extconfs as $extname=>$extconf) { + if($extmgr->checkExtensionByDir($extname)) { + $output->writeln(sprintf("%s", $extname)); + } else { + $output->writeln(sprintf("%s", $extname)); + $errmsgs = $extmgr->getErrorMsgs(); + foreach($errmsgs as $errmsg) { + $output->writeln(sprintf("%s", $errmsg)); + } + } + } + return Command::SUCCESS; + } +} + +// vim: ts=4 sw=4 expandtab diff --git a/utils/Commands/ClearcacheCommand.php b/utils/Commands/ClearcacheCommand.php index 0aae1c010..7627d2321 100644 --- a/utils/Commands/ClearcacheCommand.php +++ b/utils/Commands/ClearcacheCommand.php @@ -6,6 +6,8 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Console\Question\ConfirmationQuestion; use Seeddms\Seeddms\Settings; use Seeddms\Seeddms\Translator; @@ -33,9 +35,10 @@ class ClearcacheCommand extends Command protected function configure() { $this->setName('cache:clear') - ->setDescription('Clears the cache') - ->setHelp('Clears all cache or those specified.') - ->addOption('cache', '', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Remove files from cache.', null) + ->setDescription('Clear cache') + ->setHelp('Clears either all caches or those specified with option --cache. Think twice before you clear a cache with previews. Depending on the number of documents in your DMS, it may take a long time to recreate the cache.') + ->addOption('cache', '', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Remove files from this cache.', null) + ->addOption('force', '', InputOption::VALUE_NONE, 'Force operation, do not ask') ; } @@ -52,6 +55,14 @@ class ClearcacheCommand extends Command return Command::FAILURE; } + if (!$input->getOption('force')) { + $helper = new QuestionHelper(); + $question = new ConfirmationQuestion('Do you really want to clear the cache? ', false); + if (!$helper->ask($input, $output, $question)) { + return Command::SUCCESS; + } + } + require_once('inc/inc.DBInit.php'); $post = array_flip($input->getOption('cache')); diff --git a/utils/Commands/DownloadextensionCommand.php b/utils/Commands/DownloadextensionCommand.php new file mode 100644 index 000000000..0b0c81b4e --- /dev/null +++ b/utils/Commands/DownloadextensionCommand.php @@ -0,0 +1,140 @@ +settings = $settings; + $this->logger = $logger; + $this->translator = $translator; + $this->extmgr = $extmgr; + parent::__construct(); + } + + protected function configure() + { + $this->setName('ext:download') + ->setDescription('Download extension from repository') + ->setHelp('') + ->addOption('url', '', InputOption::VALUE_REQUIRED, 'Url of repository.', null) + ->addOption('name', '', InputOption::VALUE_REQUIRED, 'Name of extension.', null) + ->addOption('extversion', '', InputOption::VALUE_REQUIRED, 'Version of extension.', null) + ->addOption('no-upload', '', InputOption::VALUE_NONE, 'Just download extension file') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $settings = $this->settings; + $logger = $this->logger; + $translator = $this->translator; + $extmgr = $this->extmgr; + + $output->writeln("Using configuration from '".$settings->_configFilePath."'.", OutputInterface::VERBOSITY_VERBOSE); + + if (!is_writable($settings->_cacheDir)) { + $output->writeln(sprintf("The cache dir '%s' is not writable for the system user running this script.", $settings->_cacheDir)); + return Command::FAILURE; + } + + $reposurl = $input->getOption('url'); + if($reposurl) + $extmgr->setRepositoryUrl($reposurl); + + $extname = $input->getOption('name'); + if (!$extname) { + $output->writeln(sprintf("You must specify an extension name.")); + return Command::FAILURE; + } + $extversion = $input->getOption('extversion'); + $noupload = $input->getOption('no-upload'); + + /* Get a list of available extensions from the repository */ + if($ret = $extmgr->updateExtensionList('', true)) { + // list of installed extensions + $extconfs = $extmgr->getExtensionConfiguration(); + // list of extensions in repository, this will just return the + // latest version of an extension + $list = $extmgr->getExtensionList(); + if (isset($list[$extname])) { + /* if specific version is not requested, then take the + * last version of the extension. + */ + if (!$extversion) + $extversion = $list[$extname]['version']; + $extversions = $extmgr->getExtensionListByName($extname); + if (isset($extversions[$extversion])) { + if ($tmpfile = $extmgr->getExtensionFromRepository($extversions[$extversion]['filename'])) { + $output->writeln(sprintf("Downloaded extension file '%s'", $extversions[$extversion]['filename'])); + if (!$noupload) { + if (isset($extconfs[$extname])) { + if (\Seeddms\Seeddms\ExtensionMgr::cmpVersion($extconfs[$extname]['version'], $extversion) > 0) { + $helper = new QuestionHelper(); + $question = new ConfirmationQuestion(sprintf("You are updating extension '%s' with an older version %s < %s. Do you want to proceed? ", $extname, $extversion, $extconfs[$extname]['version']), false); + if (!$helper->ask($input, $output, $question)) { + unlink($tmpfile); + return Command::SUCCESS; + } + } + $output->writeln(sprintf("Updating existing extension '%s' with version %s", $extname, $extversion)); + } else { + $output->writeln(sprintf("Installing new extension '%s' with version %s", $extname, $extversion)); + } + if (!$extmgr->updateExtension($tmpfile)) { + foreach ($extmgr->getErrorMsgs() as $msg) { + $output->writeln(sprintf("%s", $msg)); + } + unlink($tmpfile); + return Command::FAILURE; + } else { + unlink($tmpfile); + } + } else { + rename($tmpfile, $extversions[$extversion]['filename']); + } + } else { + $output->writeln(sprintf("Could not download file '%s'", $list[$extname]['filename'])); + } + return Command::SUCCESS; + } else { + $output->writeln(sprintf("Requested version '%s' of extension '%s' does not exist in repository.", $extversion, $extname)); + return Command::FAILURE; + } + } else { + $output->writeln(sprintf("Extension '%s' does not exist in repository.", $extname)); + return Command::FAILURE; + } + } else { + $output->writeln(sprintf("Could not get extension list from repository.", $filename)); + return Command::FAILURE; + } + } +} + +// vim: ts=4 sw=4 expandtab diff --git a/utils/Commands/ListcacheCommand.php b/utils/Commands/ListcacheCommand.php index d42a6e649..d01651d20 100644 --- a/utils/Commands/ListcacheCommand.php +++ b/utils/Commands/ListcacheCommand.php @@ -6,6 +6,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Helper\Table; use Seeddms\Seeddms\Settings; use Seeddms\Seeddms\Translator; @@ -48,36 +49,39 @@ class ListcacheCommand extends Command $outformat = '%-20s %-40s %15s %7d'; require_once('inc/inc.DBInit.php'); - $cachedir = $settings->_cacheDir; - $totalc = 0; - $totalspace = 0; - // Preview for png, pdf, and txt */ - foreach(['png', 'pdf', 'txt'] as $t) { - $path = addDirSep($cachedir).$t; - if(file_exists($path)) { - $space = dskspace($path); - $fi = new FilesystemIterator($path, FilesystemIterator::SKIP_DOTS); - $c = iterator_count($fi); - } else { - $space = $c = 0; - } - $totalc += $c; - $totalspace += $space; - $output->writeln(sprintf($outformat, 'preview'.$t, $translator->translate('preview_'.$t), SeedDMS_Core_File::format_filesize($space), $c)); - } + $cachedir = $settings->_cacheDir; + $totalc = 0; + $totalspace = 0; + $tabledata = []; + // Preview for png, pdf, and txt */ + foreach(['png', 'pdf', 'txt'] as $t) { + $path = addDirSep($cachedir).$t; + if(file_exists($path)) { + $space = dskspace($path); + $fi = new FilesystemIterator($path, FilesystemIterator::SKIP_DOTS); + $c = iterator_count($fi); + } else { + $space = $c = 0; + } + $totalc += $c; + $totalspace += $space; +// $output->writeln(sprintf($outformat, 'preview'.$t, $translator->translate('preview_'.$t), SeedDMS_Core_File::format_filesize($space), $c)); + $tabledata[] = ['preview'.$t, $translator->translate('preview_'.$t), SeedDMS_Core_File::format_filesize($space), $c]; + } - /* Javascript */ - $path = addDirSep($cachedir).'js'; - if(file_exists($path)) { - $space = dskspace($path); - $fi = new FilesystemIterator($path, FilesystemIterator::SKIP_DOTS); - $c = iterator_count($fi); - } else { - $space = $c = 0; - } - $totalc += $c; - $totalspace += $space; - $output->writeln(sprintf($outformat, 'js', $translator->translate('temp_jscode'), SeedDMS_Core_File::format_filesize($space), $c)); + /* Javascript */ + $path = addDirSep($cachedir).'js'; + if(file_exists($path)) { + $space = dskspace($path); + $fi = new FilesystemIterator($path, FilesystemIterator::SKIP_DOTS); + $c = iterator_count($fi); + } else { + $space = $c = 0; + } + $totalc += $c; + $totalspace += $space; +// $output->writeln(sprintf($outformat, 'js', $translator->translate('temp_jscode'), SeedDMS_Core_File::format_filesize($space), $c)); + $tabledata[] = ['js', $translator->translate('temp_jscode'), SeedDMS_Core_File::format_filesize($space), $c]; $caches = []; /* Create a dummy view for passing it to additionalCache() */ @@ -90,8 +94,14 @@ class ListcacheCommand extends Command } } foreach($caches as $cache) { - $output->writeln(sprintf($outformat, $cache[0], $cache[1], SeedDMS_Core_File::format_filesize($cache[2]), $cache[3])); +// $output->writeln(sprintf($outformat, $cache[0], $cache[1], SeedDMS_Core_File::format_filesize($cache[2]), $cache[3])); + $tabledata[] = [$cache[0], $cache[1], SeedDMS_Core_File::format_filesize($cache[2]), $cache[3]]; } + $table = new Table($output); + $table + ->setHeaders(['Cache', 'Name', 'Size', 'Count']) + ->setRows($tabledata); + $table->render(); // print_r($caches); return Command::SUCCESS; diff --git a/utils/Commands/ListextensionCommand.php b/utils/Commands/ListextensionCommand.php index 6e9fc1bd2..b6b7bcf28 100644 --- a/utils/Commands/ListextensionCommand.php +++ b/utils/Commands/ListextensionCommand.php @@ -60,8 +60,8 @@ class ListextensionCommand extends Command $enabled = 0; $disabled = 0; $haserror = 0; - $extconf = $extmgr->getExtensionConfiguration(); - foreach ($extconf as $extname=>$extconf) { + $extconfs = $extmgr->getExtensionConfiguration(); + foreach ($extconfs as $extname=>$extconf) { if (!$settings->extensionIsDisabled($extname)) { $enabled++; $output->writeln(sprintf(''.$outformat.'', '*', $extname, $extconf['version'], $extconf['releasedate'])); diff --git a/utils/Commands/PackageextensionCommand.php b/utils/Commands/PackageextensionCommand.php index 7a8fef84d..e4e5ffe7f 100644 --- a/utils/Commands/PackageextensionCommand.php +++ b/utils/Commands/PackageextensionCommand.php @@ -38,8 +38,8 @@ class PackageextensionCommand extends Command protected function configure() { $this->setName('ext:package') - ->setDescription('Package extension as a zip file. If --output-dir is given, the zip file will be placed into this directory otherwise it will be saved in the current directory. The name of the zip file will be -.zip. If such a file already exists, it will be deleted and recreated.') - ->setHelp('Creates a zip file of an extension, which can be uploaded into SeedDMS.') + ->setDescription('Package extension as a zip file') + ->setHelp('Creates a zip file of an extension, which can be uploaded into SeedDMS. If --output-dir is given, the zip file will be placed into this directory otherwise it will be saved in the current directory. The name of the zip file will be -.zip. If such a file already exists, it will be deleted and recreated.') ->addOption('name', '', InputOption::VALUE_REQUIRED, 'Name of extension.', null) ->addOption('output-dir', '', InputOption::VALUE_REQUIRED, 'Name of directory where the zip file is saved.', null) ; diff --git a/utils/Commands/RepositoryextensionCommand.php b/utils/Commands/RepositoryextensionCommand.php new file mode 100644 index 000000000..f50e5d247 --- /dev/null +++ b/utils/Commands/RepositoryextensionCommand.php @@ -0,0 +1,103 @@ +settings = $settings; + $this->logger = $logger; + $this->translator = $translator; + $this->extmgr = $extmgr; + parent::__construct(); + } + + protected function configure() + { + $this->setName('ext:repository') + ->setDescription('Get list of extensions from repository') + ->setHelp('') + ->addOption('url', '', InputOption::VALUE_REQUIRED, 'Url of repository.', null) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $settings = $this->settings; + $logger = $this->logger; + $translator = $this->translator; + $extmgr = $this->extmgr; + + $output->writeln("Using configuration from '".$settings->_configFilePath."'.", OutputInterface::VERBOSITY_VERBOSE); + + $reposurl = $input->getOption('url'); + if($reposurl) + $extmgr->setRepositoryUrl($reposurl); + + /* Get a list of available extensions from the repository */ + if($ret = $extmgr->updateExtensionList('', true)) { +// $output->writeln(sprintf("Updated extension list from repository.")); + // list of installed extensions + $extconfs = $extmgr->getExtensionConfiguration(); + // list of extensions in repository, this will just return the + // latest version of an extension + $list = $extmgr->getExtensionList(); +// print_r($list); + $tabledata = []; + foreach($list as $extname=>$data) { + $extversions = $extmgr->getExtensionListByName($extname); +// print_r($extversions); + $allowedversions = []; + foreach($extversions as $version=>$extversion) { + $check = $extmgr->checkExtensionByName($extname, $extversion); + if ($check) { + $allowedversions[] = ''.$version.''; + } else { + $allowedversions[] = ''.$version.''; + } + } + $tabledata[$extname] = [ + $extname, + $data['title'], + new TableCell(implode("\n", $allowedversions), ['rowspan' => count($allowedversions)]), + isset($extconfs[$extname]['version']) ? $extconfs[$extname]['version'] : '']; + } + $table = new Table($output); + $table + ->setHeaders(['Name', 'Title', 'Rep. ver.', 'Inst. ver.']) + ->setRows($tabledata); + $table->render(); + return Command::SUCCESS; + } else { + $output->writeln(sprintf("Could not get extension list from repository.")); + return Command::FAILURE; + } + } +} + +// vim: ts=4 sw=4 expandtab diff --git a/utils/Commands/StatsCommand.php b/utils/Commands/StatsCommand.php index e1df7257d..322960384 100644 --- a/utils/Commands/StatsCommand.php +++ b/utils/Commands/StatsCommand.php @@ -6,9 +6,13 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Helper\TableCell; +use Symfony\Component\Console\Helper\TableSeparator; use Seeddms\Seeddms\Settings; use Seeddms\Seeddms\Translator; +use SeedDMS_Core_File; use Log_file; class StatsCommand extends Command @@ -30,9 +34,9 @@ class StatsCommand extends Command protected function configure() { $this->setName('dms:stats') - ->setDescription('Prints Statistics') - ->setHelp('Demonstration of custom commands created by Symfony Console component.') - ->addOption('json', '', InputOption::VALUE_NONE, 'Export data as json') + ->setDescription('Print statistics') + ->setHelp('Outputs the number of documents, folders, users, etc. in total and how many of them are owned by they users.') + ->addOption('json', '', InputOption::VALUE_NONE, 'Print data as json instead of a table') ; } @@ -45,7 +49,7 @@ class StatsCommand extends Command require_once('inc/inc.DBInit.php'); foreach (array('docstotal'=>'documents', 'folderstotal'=>'folders', 'userstotal'=>'users', 'groupstotal'=>'groups', 'categoriestotal'=>'categories') as $type=>$name) { - $stats[$type] = $dms->getStatisticalData($type); + $stats['total'][substr($type, 0, -5)] = $dms->getStatisticalData($type); } foreach (array('docsperuser'=>'documents', 'foldersperuser'=>'folders','sizeperuser'=>'size') as $type=>$name) { $stats[$type] = $dms->getStatisticalData($type); @@ -54,26 +58,49 @@ class StatsCommand extends Command if ($input->getOption('json')) { $output->writeln(json_encode($stats)); } else { - $outformat = '%-30s %-10d'; - $output->writeln(sprintf($outformat, 'Documents', $stats['docstotal'])); - $output->writeln(sprintf($outformat, 'Folders', $stats['folderstotal'])); - $output->writeln(sprintf($outformat, 'Users', $stats['userstotal'])); - $output->writeln(sprintf($outformat, 'Groups', $stats['groupstotal'])); - $output->writeln(sprintf($outformat, 'Categories', $stats['categoriestotal'])); - $output->writeln(''); - $output->writeln('Documents per user:'); - foreach($stats['docsperuser'] as $d) { - $output->writeln(sprintf($outformat, $d['key'], $d['total'])); - } - $output->writeln(''); - $output->writeln('Folders per user:'); - foreach($stats['foldersperuser'] as $d) { - $output->writeln(sprintf($outformat, $d['key'], $d['total'])); - } - $output->writeln(''); - $output->writeln('Size per user:'); - foreach($stats['sizeperuser'] as $d) { - $output->writeln(sprintf($outformat, $d['key'], $d['total'])); + if(1) { + $table = new Table($output); + $table->setHeaders(['Name', 'Count/Size']); + foreach($stats['total'] as $k=>$v) + $table->addRow([$k, $v]); + $table->addRow(new TableSeparator()); + $table->addRow([new TableCell($translator->translate('chart_docsperuser_title'), ['colspan' => 2])]); + $table->addRow(new TableSeparator()); + foreach($stats['docsperuser'] as $v) + $table->addRow([$v['key'], $v['total']]); + $table->addRow(new TableSeparator()); + $table->addRow([new TableCell($translator->translate('chart_foldersperuser_title'), ['colspan' => 2])]); + $table->addRow(new TableSeparator()); + foreach($stats['foldersperuser'] as $v) + $table->addRow([$v['key'], $v['total']]); + $table->addRow(new TableSeparator()); + $table->addRow([new TableCell($translator->translate('chart_sizeperuser_title'), ['colspan' => 2])]); + $table->addRow(new TableSeparator()); + foreach($stats['sizeperuser'] as $v) + $table->addRow([$v['key'], SeedDMS_Core_File::format_filesize((int)$v['total'])]); + $table->render(); + } else { + $outformat = '%-30s %-10d'; + $output->writeln(sprintf($outformat, 'Documents', $stats['docstotal'])); + $output->writeln(sprintf($outformat, 'Folders', $stats['folderstotal'])); + $output->writeln(sprintf($outformat, 'Users', $stats['userstotal'])); + $output->writeln(sprintf($outformat, 'Groups', $stats['groupstotal'])); + $output->writeln(sprintf($outformat, 'Categories', $stats['categoriestotal'])); + $output->writeln(''); + $output->writeln('Documents per user:'); + foreach($stats['docsperuser'] as $d) { + $output->writeln(sprintf($outformat, $d['key'], $d['total'])); + } + $output->writeln(''); + $output->writeln('Folders per user:'); + foreach($stats['foldersperuser'] as $d) { + $output->writeln(sprintf($outformat, $d['key'], $d['total'])); + } + $output->writeln(''); + $output->writeln('Size per user:'); + foreach($stats['sizeperuser'] as $d) { + $output->writeln(sprintf($outformat, $d['key'], $d['total'])); + } } } return Command::SUCCESS; diff --git a/utils/Commands/UpdateextensionCommand.php b/utils/Commands/UpdateextensionCommand.php new file mode 100644 index 000000000..e73e4afc1 --- /dev/null +++ b/utils/Commands/UpdateextensionCommand.php @@ -0,0 +1,163 @@ +settings = $settings; + $this->logger = $logger; + $this->translator = $translator; + $this->extmgr = $extmgr; + parent::__construct(); + } + + protected function configure() + { + $this->setName('ext:update') + ->setDescription('Check for extension upates') + ->setHelp('') + ->addOption('url', '', InputOption::VALUE_REQUIRED, 'Url of repository.', null) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $settings = $this->settings; + $logger = $this->logger; + $translator = $this->translator; + $extmgr = $this->extmgr; + + $output->writeln("Using configuration from '".$settings->_configFilePath."'.", OutputInterface::VERBOSITY_VERBOSE); + + if (!is_writable($settings->_cacheDir)) { + $output->writeln(sprintf("The cache dir '%s' is not writable for the system user running this script.", $settings->_cacheDir)); + return Command::FAILURE; + } + + $reposurl = $input->getOption('url'); + if($reposurl) + $extmgr->setRepositoryUrl($reposurl); + + $updates = []; + $installs = []; + /* Get a list of available extensions from the repository */ + if($ret = $extmgr->updateExtensionList('', true)) { + // list of installed extensions + $extconfs = $extmgr->getExtensionConfiguration(); + // list of extensions in repository, this will just return the + // latest version of an extension + $list = $extmgr->getExtensionList(); + foreach($list as $extname=>$data) { + $extversions = $extmgr->getExtensionListByName($extname); +// $updates[$extname] = []; +// $installs[$extname] = []; + foreach($extversions as $version=>$extversion) { + /* Only version which pass the check will be offered for + * update or install. + */ + $check = $extmgr->checkExtensionByName($extname, $extversion); + if ($check) { + if (isset($extconfs[$extname])) { + if (\Seeddms\Seeddms\ExtensionMgr::cmpVersion($version, $extconfs[$extname]['version']) > 0) { + $updates[$extname][$version] = $extversion; + } + } else { + $installs[$extname][$version] = $extversion; + } + } + } + } + $helper = new QuestionHelper(); + if($updates) { + $output->writeln(sprintf("%d extensions can be updated.", count($updates))); + foreach($updates as $extname=>$update) { + $availableversions = array_keys($update); + if ($update) { + $output->writeln(sprintf("Extension '%s' can be updated from %s to %s.", $extname, $extconfs[$extname]['version'], implode(', ', $availableversions))); + $question = new Question(sprintf("Enter version to update: "), ''); + if ($answer = $helper->ask($input, $output, $question)) { + if (in_array($answer, $availableversions)) { + $output->writeln(sprintf("Update extension '%s' to version %s.", $extname, $answer)); + if ($tmpfile = $extmgr->getExtensionFromRepository($update[$answer]['filename'])) { + + if (0&&!$extmgr->updateExtension($tmpfile)) { + foreach ($extmgr->getErrorMsgs() as $msg) { + $output->writeln(sprintf("%s", $msg)); + } + unlink($tmpfile); + return Command::FAILURE; + } else { + unlink($tmpfile); + } + } + } else { + $output->writeln(sprintf("Invalid version %s.", $answer)); + } + } + } + } + } + if($installs) { + $output->writeln(sprintf("%d extensions can be installed.", count($installs))); + foreach($installs as $extname=>$install) { + $availableversions = array_keys($install); + if ($install) { + $output->writeln(sprintf("Extension '%s' can be installed as version %s.", $extname, implode(', ', $availableversions))); + $question = new Question(sprintf("Enter version to install: "), ''); + if ($answer = $helper->ask($input, $output, $question)) { + if (in_array($answer, $availableversions)) { + $output->writeln(sprintf("Install extension '%s' to version %s.", $extname, $answer)); + if ($tmpfile = $extmgr->getExtensionFromRepository($install[$answer]['filename'])) { + + if (0&&!$extmgr->updateExtension($tmpfile)) { + foreach ($extmgr->getErrorMsgs() as $msg) { + $output->writeln(sprintf("%s", $msg)); + } + unlink($tmpfile); + return Command::FAILURE; + } else { + unlink($tmpfile); + } + } + } else { + $output->writeln(sprintf("Invalid version %s.", $answer)); + } + } + } + } + } + return Command::SUCCESS; + } else { + $output->writeln(sprintf("Could not get extension list from repository.")); + return Command::FAILURE; + } + } +} + +// vim: ts=4 sw=4 expandtab diff --git a/utils/Commands/UploadextensionCommand.php b/utils/Commands/UploadextensionCommand.php new file mode 100644 index 000000000..4873bc545 --- /dev/null +++ b/utils/Commands/UploadextensionCommand.php @@ -0,0 +1,78 @@ +settings = $settings; + $this->logger = $logger; + $this->translator = $translator; + $this->extmgr = $extmgr; + parent::__construct(); + } + + protected function configure() + { + $this->setName('ext:upload') + ->setDescription('Upload extension') + ->setHelp('Uploads an extensions, which replaces an exiting extension or inserts a new extension.') + ->addOption('file', '', InputOption::VALUE_REQUIRED, 'Filename of zipped extension.', null) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $settings = $this->settings; + $logger = $this->logger; + $translator = $this->translator; + $extmgr = $this->extmgr; + + $output->writeln("Using configuration from '".$settings->_configFilePath."'.", OutputInterface::VERBOSITY_VERBOSE); +/* + if (!is_writable($settings->_configFilePath)) { + $output->writeln(sprintf("The configuration file '%s' is not writable by the system user running this script.", $settings->_configFilePath)); + return Command::FAILURE; + } + */ + if (!is_writable($settings->_cacheDir)) { + $output->writeln(sprintf("The cache dir '%s' is not writable for the system user running this script.", $settings->_cacheDir)); + return Command::FAILURE; + } + + $filename = $input->getOption('file'); + if (!$extmgr->updateExtension($filename)) { + foreach ($extmgr->getErrorMsgs() as $msg) { + $output->writeln(sprintf("%s", $msg)); + } + return Command::FAILURE; + } + + return Command::SUCCESS; + } +} + +// vim: ts=4 sw=4 expandtab diff --git a/utils/console b/utils/console index 2cf31546b..ed7d3c0d8 100755 --- a/utils/console +++ b/utils/console @@ -1,8 +1,8 @@ #!/usr/bin/env php add(new ClearcacheCommand($settings, $logger, $translator)); $application->add(new ListcacheCommand($settings, $logger, $translator)); $application->add(new ListextensionCommand($settings, $logger, $translator, $extmgr)); $application->add(new ConfigureextensionCommand($settings, $logger, $translator, $extmgr)); +$application->add(new UploadextensionCommand($settings, $logger, $translator, $extmgr)); $application->add(new PackageextensionCommand($settings, $logger, $translator, $extmgr)); $application->add(new ReloadextensionCommand($settings, $logger, $translator, $extmgr)); +$application->add(new CheckextensionCommand($settings, $logger, $translator, $extmgr)); +$application->add(new RepositoryextensionCommand($settings, $logger, $translator, $extmgr)); +$application->add(new UpdateextensionCommand($settings, $logger, $translator, $extmgr)); +$application->add(new DownloadextensionCommand($settings, $logger, $translator, $extmgr)); if(isset($GLOBALS['SEEDDMS_HOOKS']['console'])) { foreach($GLOBALS['SEEDDMS_HOOKS']['console'] as $hookObj) { diff --git a/views/bootstrap/class.Bootstrap.php b/views/bootstrap/class.Bootstrap.php index d3985eedc..603fe7200 100644 --- a/views/bootstrap/class.Bootstrap.php +++ b/views/bootstrap/class.Bootstrap.php @@ -19,6 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +use Seeddms\Seeddms\Utilities; class SeedDMS_Theme_Style extends SeedDMS_View_Common { /** @@ -180,7 +181,7 @@ background-image: linear-gradient(to bottom, #882222, #111111);; } /* }}} */ function htmlAddJsHeader($script) { /* {{{ */ - $nonce = createNonce(); + $nonce = Utilities::createNonce(); $this->nonces[] = $nonce; $this->extraheader['js'] .= ''."\n"; } /* }}} */ diff --git a/views/bootstrap/class.Session.php b/views/bootstrap/class.Session.php index d1d3a036e..4859d094b 100644 --- a/views/bootstrap/class.Session.php +++ b/views/bootstrap/class.Session.php @@ -13,10 +13,7 @@ * @version Release: @package_version@ */ -/** - * Include parent class - */ -//require_once("class.Bootstrap.php"); +use Seeddms\Seeddms\SessionMgr; /** * Class which outputs the html page for clipboard view @@ -44,7 +41,7 @@ class SeedDMS_View_Session extends SeedDMS_Theme_Style { $dms = $this->params['dms']; $user = $this->params['user']; - $sessionmgr = new SeedDMS_SessionMgr($dms->getDB()); + $sessionmgr = new SessionMgr($dms->getDB()); /* Get only sessions which has been active in the last 3600 sec. */ $sessions = $sessionmgr->getLastAccessedSessions(date('Y-m-d H:i:s', time()-3600)); if(!$sessions) diff --git a/views/bootstrap/class.UserList.php b/views/bootstrap/class.UserList.php index eb7fa2f76..45f085a33 100644 --- a/views/bootstrap/class.UserList.php +++ b/views/bootstrap/class.UserList.php @@ -13,10 +13,7 @@ * @version Release: @package_version@ */ -/** - * Include parent class - */ -//require_once("class.Bootstrap.php"); +use Seeddms\Seeddms\SessionMgr; /** * Class which outputs the html page for UserList view @@ -60,7 +57,7 @@ class SeedDMS_View_UserList extends SeedDMS_Theme_Style { $this->pageNavigation("", "admin_tools"); $this->contentHeading(getMLText("user_list")); - $sessionmgr = new SeedDMS_SessionMgr($dms->getDB()); + $sessionmgr = new SessionMgr($dms->getDB()); ?> diff --git a/views/bootstrap/class.UsrMgr.php b/views/bootstrap/class.UsrMgr.php index 65270d8e2..7846775d0 100644 --- a/views/bootstrap/class.UsrMgr.php +++ b/views/bootstrap/class.UsrMgr.php @@ -13,6 +13,8 @@ * @version Release: @package_version@ */ +use Seeddms\Seeddms\SessionMgr; + /** * Include parent class */ @@ -101,7 +103,7 @@ $(document).ready( function() { $workflowmode = $this->params['workflowmode']; if($seluser) { - $sessionmgr = new SeedDMS_SessionMgr($dms->getDB()); + $sessionmgr = new SessionMgr($dms->getDB()); $this->contentHeading(getMLText("user_info")); echo "\n"; diff --git a/views/bootstrap4/class.Bootstrap4.php b/views/bootstrap4/class.Bootstrap4.php index 1a5d2e910..5d0db75de 100644 --- a/views/bootstrap4/class.Bootstrap4.php +++ b/views/bootstrap4/class.Bootstrap4.php @@ -19,6 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +use Seeddms\Seeddms\Utilities; class SeedDMS_Theme_Style extends SeedDMS_View_Common { /** @@ -182,7 +183,7 @@ background-image: linear-gradient(to bottom, #882222, #111111);; } /* }}} */ function htmlAddJsHeader($script) { /* {{{ */ - $nonce = createNonce(); + $nonce = Utilities::createNonce(); $this->nonces[] = $nonce; $this->extraheader['js'] .= ''."\n"; } /* }}} */