From 9573d473e94fac3bccbd6ca267292483691e31d7 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 7 Nov 2024 13:52:43 +0100 Subject: [PATCH 001/208] do not show chart by category if there are no categories --- CHANGELOG | 1 + views/bootstrap/class.Charts.php | 32 ++++++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 862228a5c..67ea1efaf 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- Changes in version 5.1.37 -------------------------------------------------------------------------------- +- do not show chart by category if there are no categories -------------------------------------------------------------------------------- Changes in version 5.1.36 diff --git a/views/bootstrap/class.Charts.php b/views/bootstrap/class.Charts.php index 7cc076860..e9f7f6749 100644 --- a/views/bootstrap/class.Charts.php +++ b/views/bootstrap/class.Charts.php @@ -13,11 +13,6 @@ * @version Release: @package_version@ */ -/** - * Include parent class - */ -//require_once("class.Bootstrap.php"); - /** * Class which outputs the html page for Charts view * @@ -229,8 +224,28 @@ $(document).ready( function() { } } /* }}} */ - function show() { /* {{{ */ - $this->dms = $this->params['dms']; + /** + * Check if it makes sense to show the chart + * + * e.g. it doesn't make sense to show the documents by category if + * there are no categories. + * + * @param string $type + * @return boolean + */ + private function showChart($type) { /* {{{ */ + $dms = $this->params['dms']; + if($type == 'docspercategory') { + if($cats = $dms->getDocumentCategories()) + return true; + else + return false; + } + return true; + } /* }}} */ + + public function show() { /* {{{ */ + $dms = $this->params['dms']; $user = $this->params['user']; $data = $this->params['data']; $type = $this->params['type']; @@ -251,7 +266,8 @@ $(document).ready( function() { $this->contentHeading(getMLText("chart_selection")); $this->contentContainerStart(); foreach(array('docsperuser', 'foldersperuser', 'sizeperuser', 'sizepermonth','docspermimetype', 'docspercategory', 'docsperstatus', 'docspermonth', 'docsaccumulated') as $atype) { - echo "
".getMLText('chart_'.$atype.'_title')."
\n"; + if($this->showChart($atype)) + echo "
".getMLText('chart_'.$atype.'_title')."
\n"; } $this->contentContainerEnd(); $this->columnEnd(); From bbfd144906e08c01a419ed4d053fd7998b056940 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 11 Nov 2024 09:29:41 +0100 Subject: [PATCH 002/208] optimize counting tasks --- views/bootstrap/class.Tasks.php | 32 ++++++++++++++++++++++++++ views/bootstrap/styles/application.js | 14 +++++------ views/bootstrap4/styles/application.js | 14 +++++------ 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/views/bootstrap/class.Tasks.php b/views/bootstrap/class.Tasks.php index 05887b94c..f28876dc5 100644 --- a/views/bootstrap/class.Tasks.php +++ b/views/bootstrap/class.Tasks.php @@ -112,6 +112,38 @@ class SeedDMS_View_Tasks extends SeedDMS_Theme_Style { return $tasks; } /* }}} */ + /** + * Returns the number of tasks + * + * @return array list of tasks an its number + */ + function countTasks() { /* {{{ */ + $dms = $this->params['dms']; + $user = $this->params['user']; + $enablereceiptworkflow = $this->params['enablereceiptworkflow']; + $enablerevisionworkflow = $this->params['enablerevisionworkflow']; + $workflowmode = $this->params['workflowmode']; + $tasksinmenu = $this->params['tasksinmenu']; + + $startts = microtime(true); + $tasks = array(); + if($workflowmode == 'traditional' || $workflowmode == 'traditional_only_approval') + if(!$tasksinmenu || in_array('approval', $tasksinmenu)) { + $tasks['approval'] = $dms->countTasks('ApproveByMe', $user); + } + if($workflowmode == 'traditional') + if(!$tasksinmenu || in_array('review', $tasksinmenu)) { + $tasks['review'] = $dms->countTasks('ReviewByMe', $user); + } + if($workflowmode == 'advanced') + if(!$tasksinmenu || in_array('workflow', $tasksinmenu)) { + $tasks['workflow'] = $dms->countTasks('WorkflowByMe', $user); + } + + header('Content-Type: application/json'); + echo json_encode(array('error'=>0, 'data'=>$tasks, 'processing_time'=>microtime(true)-$startts)); + } /* }}} */ + /** * Returns the html needed for the task list in the menu * diff --git a/views/bootstrap/styles/application.js b/views/bootstrap/styles/application.js index 42d384e66..ab620ee06 100644 --- a/views/bootstrap/styles/application.js +++ b/views/bootstrap/styles/application.js @@ -1618,17 +1618,17 @@ $(document).ready(function() { /* {{{ */ $.ajax({url: seeddms_webroot+'out/out.Tasks.php', type: 'GET', dataType: "json", - data: {action: 'mytasks'}, + data: {action: 'counttasks'}, success: function(data) { if(data) { - if((typeof data.data.approval != 'undefined' && approval_count != data.data.approval.length) || - (typeof data.data.review != 'undefined' && review_count != data.data.review.length) || - (typeof data.data.workflow != 'undefined' && workflow_count != data.data.workflow.length)) { + if((typeof data.data.approval != 'undefined' && approval_count != data.data.approval) || + (typeof data.data.review != 'undefined' && review_count != data.data.review) || + (typeof data.data.workflow != 'undefined' && workflow_count != data.data.workflow)) { // $("#menu-tasks").html('Loading').hide().load('../out/out.Tasks.php?action=menutasks').fadeIn('500') $('#menu-tasks > div.ajax').trigger('update', {folderid: seeddms_folder}); - approval_count = typeof data.data.approval != 'undefined' ? data.data.approval.length : 0; - review_count = typeof data.data.review != 'undefined' ? data.data.review.length : 0; - workflow_count = typeof data.data.workflow != 'undefined' ? data.data.workflow.length : 0; + approval_count = typeof data.data.approval != 'undefined' ? data.data.approval : 0; + review_count = typeof data.data.review != 'undefined' ? data.data.review : 0; + workflow_count = typeof data.data.workflow != 'undefined' ? data.data.workflow : 0; } } }, diff --git a/views/bootstrap4/styles/application.js b/views/bootstrap4/styles/application.js index 6daecdcfb..221cc4b92 100644 --- a/views/bootstrap4/styles/application.js +++ b/views/bootstrap4/styles/application.js @@ -1697,17 +1697,17 @@ $(document).ready(function() { /* {{{ */ $.ajax({url: seeddms_webroot+'out/out.Tasks.php', type: 'GET', dataType: "json", - data: {action: 'mytasks'}, + data: {action: 'counttasks'}, success: function(data) { if(data) { - if((typeof data.data.approval != 'undefined' && approval_count != data.data.approval.length) || - (typeof data.data.review != 'undefined' && review_count != data.data.review.length) || - (typeof data.data.workflow != 'undefined' && workflow_count != data.data.workflow.length)) { + if((typeof data.data.approval != 'undefined' && approval_count != data.data.approval) || + (typeof data.data.review != 'undefined' && review_count != data.data.review) || + (typeof data.data.workflow != 'undefined' && workflow_count != data.data.workflow)) { // $("#menu-tasks").html('Loading').hide().load('../out/out.Tasks.php?action=menutasks').fadeIn('500') $('#menu-tasks > div.ajax').trigger('update', {folderid: seeddms_folder}); - approval_count = typeof data.data.approval != 'undefined' ? data.data.approval.length : 0; - review_count = typeof data.data.review != 'undefined' ? data.data.review.length : 0; - workflow_count = typeof data.data.workflow != 'undefined' ? data.data.workflow.length : 0; + approval_count = typeof data.data.approval != 'undefined' ? data.data.approval : 0; + review_count = typeof data.data.review != 'undefined' ? data.data.review : 0; + workflow_count = typeof data.data.workflow != 'undefined' ? data.data.workflow : 0; } } }, From ea5d4651e52b13c345f6cbfc96b39e3ee18a5512 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 11 Nov 2024 09:36:11 +0100 Subject: [PATCH 003/208] fix merge errors --- views/bootstrap/class.Tasks.php | 37 --------------------------------- 1 file changed, 37 deletions(-) diff --git a/views/bootstrap/class.Tasks.php b/views/bootstrap/class.Tasks.php index b359f66fe..4c778b8cd 100644 --- a/views/bootstrap/class.Tasks.php +++ b/views/bootstrap/class.Tasks.php @@ -208,43 +208,6 @@ class SeedDMS_View_Tasks extends SeedDMS_Theme_Style { $workflowmode = $this->params['workflowmode']; $tasksinmenu = $this->params['tasksinmenu']; - $startts = microtime(true); - $tasks = array(); - if($workflowmode == 'traditional' || $workflowmode == 'traditional_only_approval') - if(!$tasksinmenu || in_array('approval', $tasksinmenu)) { - $tasks['approval'] = $dms->countTasks('ApproveByMe', $user); - } - if($workflowmode == 'traditional') - if(!$tasksinmenu || in_array('review', $tasksinmenu)) { - $tasks['review'] = $dms->countTasks('ReviewByMe', $user); - } - if($workflowmode == 'advanced') - if(!$tasksinmenu || in_array('workflow', $tasksinmenu)) { - $tasks['workflow'] = $dms->countTasks('WorkflowByMe', $user); - } - - header('Content-Type: application/json'); - echo json_encode(array('error'=>0, 'data'=>$tasks, 'processing_time'=>microtime(true)-$startts)); - } /* }}} */ - - /** - * Returns the html needed for the task list in the menu - * - * This function renders the tasks in a way suitable to be - * used as a menu - * - * @param array $clipboard clipboard containing two arrays for both - * documents and folders. - * @return string html code - */ - function countTasks() { /* {{{ */ - $dms = $this->params['dms']; - $user = $this->params['user']; - $enablereceiptworkflow = $this->params['enablereceiptworkflow']; - $enablerevisionworkflow = $this->params['enablerevisionworkflow']; - $workflowmode = $this->params['workflowmode']; - $tasksinmenu = $this->params['tasksinmenu']; - $startts = microtime(true); $tasks = array(); if($workflowmode == 'traditional' || $workflowmode == 'traditional_only_approval') From 8afef964403c71aac6fa7d1a030a3d4e1176ffbf Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 11 Nov 2024 09:48:40 +0100 Subject: [PATCH 004/208] do not show expired documents in menu tasks --- views/bootstrap/class.Tasks.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/views/bootstrap/class.Tasks.php b/views/bootstrap/class.Tasks.php index f28876dc5..e6f8c2328 100644 --- a/views/bootstrap/class.Tasks.php +++ b/views/bootstrap/class.Tasks.php @@ -45,7 +45,7 @@ class SeedDMS_View_Tasks extends SeedDMS_Theme_Style { $tasks['rejected'] = array(); if($workflowmode == 'traditional' || $workflowmode == 'traditional_only_approval') { - $resArr = $dms->getDocumentList('ApproveByMe', $user); + $resArr = $dms->getDocumentList('ApproveByMe', $user, false, '', '', false); if($resArr) { $docs = array(); foreach ($resArr as $res) { @@ -61,7 +61,7 @@ class SeedDMS_View_Tasks extends SeedDMS_Theme_Style { $tasks['approval'][] = array('id'=>$doc->getId(), 'name'=>$doc->getName()); } if($workflowmode == 'traditional') { - $resArr = $dms->getDocumentList('ReviewByMe', $user); + $resArr = $dms->getDocumentList('ReviewByMe', $user, false, '', '', false); if($resArr) { $docs = array(); foreach ($resArr as $res) { From 35fa11a7c28c9fbd26c1da7da98f8eea661c23dc Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 11 Nov 2024 10:47:51 +0100 Subject: [PATCH 005/208] remove code from seeddms 6 --- views/bootstrap/class.Tasks.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/views/bootstrap/class.Tasks.php b/views/bootstrap/class.Tasks.php index e6f8c2328..cfcb6c1be 100644 --- a/views/bootstrap/class.Tasks.php +++ b/views/bootstrap/class.Tasks.php @@ -120,8 +120,6 @@ class SeedDMS_View_Tasks extends SeedDMS_Theme_Style { function countTasks() { /* {{{ */ $dms = $this->params['dms']; $user = $this->params['user']; - $enablereceiptworkflow = $this->params['enablereceiptworkflow']; - $enablerevisionworkflow = $this->params['enablerevisionworkflow']; $workflowmode = $this->params['workflowmode']; $tasksinmenu = $this->params['tasksinmenu']; From cef5e73ba59390114b184e6b6ce8e40a266ad65f Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 11 Nov 2024 10:48:21 +0100 Subject: [PATCH 006/208] set parameter tasksinmenu --- out/out.Tasks.php | 1 + 1 file changed, 1 insertion(+) diff --git a/out/out.Tasks.php b/out/out.Tasks.php index 272799e4f..1660d7677 100644 --- a/out/out.Tasks.php +++ b/out/out.Tasks.php @@ -38,6 +38,7 @@ if($view) { $view->setParam('previewWidthList', $settings->_previewWidthList); $view->setParam('timeout', $settings->_cmdTimeout); $view->setParam('xsendfile', $settings->_enableXsendfile); + $view->setParam('tasksinmenu', []); $view($_GET); exit; } From bb0f34a05a851446af697019a97ad80623c31cea Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 13 Nov 2024 12:51:08 +0100 Subject: [PATCH 007/208] fix title of page --- views/bootstrap/class.Dashboard.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/bootstrap/class.Dashboard.php b/views/bootstrap/class.Dashboard.php index c03c022b1..3cfcd4c78 100644 --- a/views/bootstrap/class.Dashboard.php +++ b/views/bootstrap/class.Dashboard.php @@ -156,7 +156,7 @@ class SeedDMS_View_Dashboard extends SeedDMS_Theme_Style { $timeout = $this->params['timeout']; $xsendfile = $this->params['xsendfile']; - $this->htmlStartPage(getMLText("calendar")); + $this->htmlStartPage(getMLText("dashboard")); $this->globalNavigation(); $this->contentStart(); From 964bed081dff4d3fc1f64128d772de80fb2c1e13 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 13 Nov 2024 22:30:15 +0100 Subject: [PATCH 008/208] check for function system() --- views/bootstrap/class.Info.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/bootstrap/class.Info.php b/views/bootstrap/class.Info.php index f0f880e0d..119f85f10 100644 --- a/views/bootstrap/class.Info.php +++ b/views/bootstrap/class.Info.php @@ -116,7 +116,7 @@ class SeedDMS_View_Info extends SeedDMS_Theme_Style { $this->contentHeading(getMLText("missing_php_functions_and_classes")); $missingfunc = []; - foreach(array('proc_open', 'openssl_cipher_iv_length') as $funcname) { + foreach(array('proc_open', 'openssl_cipher_iv_length', 'system') as $funcname) { if(!function_exists($funcname)) { $missingfunc[] = $funcname; //getMLText('func_'.$funcname."_missing") } From f5db14dd74ac5825426808b66ba4f5ae8efef610 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 13 Nov 2024 22:31:13 +0100 Subject: [PATCH 009/208] pass propper parameter to hook cleanUpDocument --- restapi/index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/restapi/index.php b/restapi/index.php index cf251d832..b8621008d 100644 --- a/restapi/index.php +++ b/restapi/index.php @@ -795,7 +795,7 @@ class RestapiController { /* {{{ */ return $response->withJson(array('success'=>false, 'message'=>'Upload failed', 'data'=>''), 500); } else { if($controller->hasHook('cleanUpDocument')) { - $controller->callHook('cleanUpDocument', $document, $file); + $controller->callHook('cleanUpDocument', $document, ['ѕource'=>'restapi', 'type'=>$userfiletype, 'name'=>$origfilename]); } // Send notification to subscribers of folder. if($notifier) { @@ -967,7 +967,7 @@ class RestapiController { /* {{{ */ } else { unlink($temp); if($controller->hasHook('cleanUpDocument')) { - $controller->callHook('cleanUpDocument', $document, $file_info); + $controller->callHook('cleanUpDocument', $document, ['ѕource'=>'restapi', 'type'=>$userfiletype, 'name'=>$origfilename]); } // Send notification to subscribers. if($notifier) { From f6f7fe0ab65e7bc50849426ff1a7d95185409894 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 13 Nov 2024 22:31:55 +0100 Subject: [PATCH 010/208] https status must be 400 instead of 200 in case of an error --- restapi/index.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/restapi/index.php b/restapi/index.php index b8621008d..2548d737c 100644 --- a/restapi/index.php +++ b/restapi/index.php @@ -2346,7 +2346,7 @@ class RestapiController { /* {{{ */ $params = $request->getParsedBody(); if (empty($params['userid'])) { - return $response->withJson(array('success'=>false, 'message'=>'Missing userid', 'data'=>''), 500); + return $response->withJson(array('success'=>false, 'message'=>'Missing userid', 'data'=>''), 400); } $userId = $params['userid']; if(ctype_digit($userId)) @@ -2404,9 +2404,9 @@ class RestapiController { /* {{{ */ if($check !== true) return $check; $params = $request->getParsedBody(); - if (empty($params['enable'])) + if (!isset($params['enable'])) { - return $response->withJson(array('success'=>false, 'message'=>'You must supply an "enable" value', 'data'=>''), 200); + return $response->withJson(array('success'=>false, 'message'=>'You must supply an "enable" value', 'data'=>''), 400); } $inherit = false; @@ -2474,12 +2474,12 @@ class RestapiController { /* {{{ */ { if ($params['id'] == null) { - return $response->withJson(array('success'=>false, 'message'=>'Please PUT the user or group Id', 'data'=>''), 200); + return $response->withJson(array('success'=>false, 'message'=>'Please PUT the user or group Id', 'data'=>''), 400); } if ($params['mode'] == null) { - return $response->withJson(array('success'=>false, 'message'=>'Please PUT the access mode', 'data'=>''), 200); + return $response->withJson(array('success'=>false, 'message'=>'Please PUT the access mode', 'data'=>''), 400); } $modeInput = $params['mode']; From e6c7ebaaec3521d4c0953450abb4f441a4add311 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 14 Nov 2024 14:34:47 +0100 Subject: [PATCH 011/208] fixed wrong constraint in table tblUserSubstitutes --- install/create_tables-innodb.sql | 2 +- install/update-6.0.0/update.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/install/create_tables-innodb.sql b/install/create_tables-innodb.sql index 541b95f42..7e9e1e720 100644 --- a/install/create_tables-innodb.sql +++ b/install/create_tables-innodb.sql @@ -100,7 +100,7 @@ CREATE TABLE `tblUserSubstitutes` ( PRIMARY KEY (`id`), UNIQUE KEY `user` (`user`,`substitute`), CONSTRAINT `tblUserSubstitutes_user` FOREIGN KEY (`user`) REFERENCES `tblUsers` (`id`) ON DELETE CASCADE, - CONSTRAINT `tblUserSubstitutes_substitute` FOREIGN KEY (`user`) REFERENCES `tblUsers` (`id`) ON DELETE CASCADE + CONSTRAINT `tblUserSubstitutes_substitute` FOREIGN KEY (`substitute`) REFERENCES `tblUsers` (`id`) ON DELETE CASCADE ); -- -------------------------------------------------------- diff --git a/install/update-6.0.0/update.sql b/install/update-6.0.0/update.sql index 74d8eb548..d1f26e99a 100644 --- a/install/update-6.0.0/update.sql +++ b/install/update-6.0.0/update.sql @@ -41,7 +41,7 @@ CREATE TABLE `tblUserSubstitutes` ( PRIMARY KEY (`id`), UNIQUE (`user`, `substitute`), CONSTRAINT `tblUserSubstitutes_user` FOREIGN KEY (`user`) REFERENCES `tblUsers` (`id`) ON DELETE CASCADE, - CONSTRAINT `tblUserSubstitutes_substitute` FOREIGN KEY (`user`) REFERENCES `tblUsers` (`id`) ON DELETE CASCADE + CONSTRAINT `tblUserSubstitutes_substitute` FOREIGN KEY (`substitute`) REFERENCES `tblUsers` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `tblDocumentCheckOuts` ( From b9d5c312117d350f6c2d65c0b934c6df818e7bc1 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Sat, 16 Nov 2024 09:50:42 +0100 Subject: [PATCH 012/208] move rrmdir() into own class in inc.Utils.php --- inc/inc.ClassExtensionMgr.php | 23 +++++------------------ inc/inc.Utils.php | 28 ++++++++++++++++++++++++++++ op/op.ImportFS.php | 7 ++++--- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/inc/inc.ClassExtensionMgr.php b/inc/inc.ClassExtensionMgr.php index 22eda0f75..fc5eceebd 100644 --- a/inc/inc.ClassExtensionMgr.php +++ b/inc/inc.ClassExtensionMgr.php @@ -490,19 +490,6 @@ class SeedDMS_Extension_Mgr { return $this->configcache[$extname]; } /* }}} */ - static protected 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); - } - } /* }}} */ - /** * Update an extension * @@ -518,7 +505,7 @@ class SeedDMS_Extension_Mgr { $newdir = addDirSep($this->cachedir)."ext.new"; /* First remove a left over from a previous extension */ if(file_exists($newdir)) { - self::rrmdir($newdir); + SeedDMS_Utils::rrmdir($newdir); } if(!mkdir($newdir, 0755)) { $this->errmsgs[] = "Cannot create temp. extension directory"; @@ -538,7 +525,7 @@ class SeedDMS_Extension_Mgr { /* Check if extension is complete and fullfills the constraints */ if(!self::checkExtensionByDir($newdir)) { - self::rrmdir($newdir); + SeedDMS_Utils::rrmdir($newdir); return false; } @@ -549,11 +536,11 @@ class SeedDMS_Extension_Mgr { if(!is_dir($this->extdir)) { if(!mkdir($this->extdir, 0755)) { $this->errmsgs[] = "Cannot create extension directory"; - self::rrmdir($newdir); + SeedDMS_Utils::rrmdir($newdir); return false; } } elseif(is_dir($this->extdir ."/". $extname)) { - $this->rrmdir($this->extdir ."/". $extname); + SeedDMS_Utils::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. @@ -575,7 +562,7 @@ class SeedDMS_Extension_Mgr { * has been copied. */ $this->errmsgs[] = "Cannot move temp. extension directory to final destination"; - $this->rrmdir($this->extdir ."/". $extname); + SeedDMS_Utils::rrmdir($this->extdir ."/". $extname); return false; } diff --git a/inc/inc.Utils.php b/inc/inc.Utils.php index 5449e176b..d42938604 100644 --- a/inc/inc.Utils.php +++ b/inc/inc.Utils.php @@ -1231,6 +1231,34 @@ 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); + } + } /* }}} */ + +} /* }}} */ + /** * Class for creating encrypted api keys * diff --git a/op/op.ImportFS.php b/op/op.ImportFS.php index d5f3f90c2..0ebd62aa5 100644 --- a/op/op.ImportFS.php +++ b/op/op.ImportFS.php @@ -239,9 +239,10 @@ if($newfolder) { $session->setSplashMsg(array('type'=>'error', 'msg'=>getMLText('error_importfs'))); else { if(isset($_GET['remove']) && $_GET["remove"]) { - $cmd = 'rm -rf '.$dirname; - $ret = null; - system($cmd, $ret); + SeedDMS_Utils::rrmdir($dirname); +// $cmd = 'rm -rf '.$dirname; +// $ret = null; +// system($cmd, $ret); } $session->setSplashMsg(array('type'=>'success', 'msg'=>getMLText('splash_importfs', array('docs'=>$doccount, 'folders'=>$foldercount)))); } From 7e4b4fd3ea00265a9f7ed01f0adae762f5fad795 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Sun, 17 Nov 2024 10:23:45 +0100 Subject: [PATCH 013/208] add methods changeUserQuota, setFolderOwner, setFolderOwner --- restapi/index.php | 129 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/restapi/index.php b/restapi/index.php index 2548d737c..f62aba596 100644 --- a/restapi/index.php +++ b/restapi/index.php @@ -2194,6 +2194,92 @@ class RestapiController { /* {{{ */ return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); } /* }}} */ + /** + * Updates the quota of an existing account + * + * @param $id The user name or numerical identifier + */ + function changeUserQuota($request, $response, $args) { /* {{{ */ + $dms = $this->container->dms; + $userobj = $this->container->userobj; + + $check = $this->checkIfAdmin($request, $response); + if($check !== true) + return $check; + + $params = $request->getParsedBody(); + if ($params['quota'] == null) { + return $response->withJson(array('success'=>false, 'message'=>'You must supply a new quota', 'data'=>''), 400); + } + + $newQuota = $params['quota']; + + if(ctype_digit($args['id'])) + $account = $dms->getUser($args['id']); + else { + $account = $dms->getUserByLogin($args['id']); + } + + /** + * User not found + */ + if (!$account) { + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'User not found.'), 404); + return; + } + + $operation = $account->setQuota($newQuota); + + if (!$operation){ + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'Could not change quota.'), 404); + } + + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); + } /* }}} */ + + function changeUserHomefolder($request, $response, $args) { /* {{{ */ + $dms = $this->container->dms; + $userobj = $this->container->userobj; + + $check = $this->checkIfAdmin($request, $response); + if($check !== true) + return $check; + + $params = $request->getParsedBody(); + if ($params['homefolder'] == null) { + return $response->withJson(array('success'=>false, 'message'=>'You must supply a new home folder', 'data'=>''), 400); + } + + $newHomefolderId = (int) $params['homefolder']; + $newHomefolder = $dms->getFolder($newHomefolderId); + if (!$newHomefolder) { + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'Folder not found.'), 404); + return; + } + + if(ctype_digit($args['id'])) + $account = $dms->getUser($args['id']); + else { + $account = $dms->getUserByLogin($args['id']); + } + + /** + * User not found + */ + if (!$account) { + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'User not found.'), 404); + return; + } + + $operation = $account->setHomeFolder($newHomefolder->getId()); + + if (!$operation){ + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'Could not change homefolder.'), 404); + } + + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); + } /* }}} */ + function getUserById($request, $response, $args) { /* {{{ */ $dms = $this->container->dms; $userobj = $this->container->userobj; @@ -2435,6 +2521,46 @@ class RestapiController { /* {{{ */ } } /* }}} */ + function setFolderOwner($request, $response, $args) { /* {{{ */ + $dms = $this->container->dms; + $userobj = $this->container->userobj; + + if(!$userobj) { + return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + } + if(!$userobj->isAdmin()) { + return $response->withJson(array('success'=>false, 'message'=>'No access on folder', 'data'=>''), 403); + } + + if(!ctype_digit($args['id']) || $args['id'] == 0) { + return $response->withJson(array('success'=>false, 'message'=>'No folder given', 'data'=>''), 400); + return; + } + if(!ctype_digit($args['userid']) || $args['userid'] == 0) { + return $response->withJson(array('success'=>false, 'message'=>'No user given', 'data'=>''), 400); + return; + } + $owner = $dms->getUser($args['userid']); + $folder = $dms->getFolder($args['id']); + if($folder && $owner) { + if($folder->getAccessMode($userobj, 'setDocumentOwner') > M_READ) { + if ($folder->setOwner($owner)){ + return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 201); + } else { + return $response->withJson(array('success'=>false, 'message'=>'Could not set owner of folder', 'data'=>''), 500); + } + } else { + return $response->withJson(array('success'=>false, 'message'=>'No access on folder', 'data'=>''), 403); + } + } else { + if(!$doc) + return $response->withJson(array('success'=>false, 'message'=>'No such folder', 'data'=>''), 404); + if(!$owner) + return $response->withJson(array('success'=>false, 'message'=>'No such user', 'data'=>''), 404); + return $response->withJson(array('success'=>false, 'message'=>'Could not find user or folder', 'data'=>''), 500); + } + } /* }}} */ + function addUserAccessToFolder($request, $response, $args) { /* {{{ */ return $this->changeFolderAccess($request, $response, $args, 'add', 'user'); } /* }}} */ @@ -2972,6 +3098,8 @@ $app->post('/users', \RestapiController::class.':createUser'); $app->get('/users/{id}', \RestapiController::class.':getUserById'); $app->put('/users/{id}/disable', \RestapiController::class.':setDisabledUser'); $app->put('/users/{id}/password', \RestapiController::class.':changeUserPassword'); +$app->put('/users/{id}/quota', \RestapiController::class.':changeUserQuota'); +$app->put('/users/{id}/homefolder', \RestapiController::class.':changeUserHomefolder'); $app->post('/groups', \RestapiController::class.':createGroup'); $app->get('/groups', \RestapiController::class.':getGroups'); $app->delete('/groups/{id}', \RestapiController::class.':deleteGroup'); @@ -2979,6 +3107,7 @@ $app->get('/groups/{id}', \RestapiController::class.':getGroup'); $app->put('/groups/{id}/addUser', \RestapiController::class.':addUserToGroup'); $app->put('/groups/{id}/removeUser', \RestapiController::class.':removeUserFromGroup'); $app->put('/folder/{id}/setInherit', \RestapiController::class.':setFolderInheritsAccess'); +$app->put('/folder/{id}/owner/{userid}', \RestapiController::class.':setFolderOwner'); $app->put('/folder/{id}/access/group/add', \RestapiController::class.':addGroupAccessToFolder'); // $app->put('/folder/{id}/access/user/add', \RestapiController::class.':addUserAccessToFolder'); // $app->put('/folder/{id}/access/group/remove', \RestapiController::class.':removeGroupAccessFromFolder'); From 7da7d2e4a11a178fbe48baa77d01c1009317ee4f Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Sun, 17 Nov 2024 10:27:51 +0100 Subject: [PATCH 014/208] __getUserData() returns quota --- restapi/index.php | 1 + 1 file changed, 1 insertion(+) diff --git a/restapi/index.php b/restapi/index.php index f62aba596..26743ab39 100644 --- a/restapi/index.php +++ b/restapi/index.php @@ -169,6 +169,7 @@ class RestapiController { /* {{{ */ 'login'=>$u->getLogin(), 'email'=>$u->getEmail(), 'language' => $u->getLanguage(), + 'quota' => $u->getQuota(), 'theme' => $u->getTheme(), 'role' => $u->getRole() == SeedDMS_Core_User::role_admin ? 'admin' : ($u->getRole() == SeedDMS_Core_User::role_guest ? 'guest' : 'user'), 'hidden'=>$u->isHidden() ? true : false, From 26ca0d9c4db169e8ec3c0ae75a8984f6c5e68224 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Sun, 17 Nov 2024 19:44:20 +0100 Subject: [PATCH 015/208] minor change of users/{id}/homefolder --- restapi/index.php | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/restapi/index.php b/restapi/index.php index 26743ab39..ae5067442 100644 --- a/restapi/index.php +++ b/restapi/index.php @@ -170,6 +170,7 @@ class RestapiController { /* {{{ */ 'email'=>$u->getEmail(), 'language' => $u->getLanguage(), 'quota' => $u->getQuota(), + 'homefolder' => $u->getHomeFolder(), 'theme' => $u->getTheme(), 'role' => $u->getRole() == SeedDMS_Core_User::role_admin ? 'admin' : ($u->getRole() == SeedDMS_Core_User::role_guest ? 'guest' : 'user'), 'hidden'=>$u->isHidden() ? true : false, @@ -2246,18 +2247,6 @@ class RestapiController { /* {{{ */ if($check !== true) return $check; - $params = $request->getParsedBody(); - if ($params['homefolder'] == null) { - return $response->withJson(array('success'=>false, 'message'=>'You must supply a new home folder', 'data'=>''), 400); - } - - $newHomefolderId = (int) $params['homefolder']; - $newHomefolder = $dms->getFolder($newHomefolderId); - if (!$newHomefolder) { - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'Folder not found.'), 404); - return; - } - if(ctype_digit($args['id'])) $account = $dms->getUser($args['id']); else { @@ -2272,6 +2261,16 @@ class RestapiController { /* {{{ */ return; } + if(!ctype_digit($args['folderid']) || $args['folderid'] == 0) { + return $response->withJson(array('success'=>false, 'message'=>'No homefolder given', 'data'=>''), 400); + return; + } + $newHomefolder = $dms->getFolder($args['folderid']); + if (!$newHomefolder) { + return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'Folder not found.'), 404); + return; + } + $operation = $account->setHomeFolder($newHomefolder->getId()); if (!$operation){ @@ -3100,7 +3099,7 @@ $app->get('/users/{id}', \RestapiController::class.':getUserById'); $app->put('/users/{id}/disable', \RestapiController::class.':setDisabledUser'); $app->put('/users/{id}/password', \RestapiController::class.':changeUserPassword'); $app->put('/users/{id}/quota', \RestapiController::class.':changeUserQuota'); -$app->put('/users/{id}/homefolder', \RestapiController::class.':changeUserHomefolder'); +$app->put('/users/{id}/homefolder/{folderid}', \RestapiController::class.':changeUserHomefolder'); $app->post('/groups', \RestapiController::class.':createGroup'); $app->get('/groups', \RestapiController::class.':getGroups'); $app->delete('/groups/{id}', \RestapiController::class.':deleteGroup'); From 0161da61436393b4c90138b71e81a7e00e21db4b Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 18 Nov 2024 10:03:32 +0100 Subject: [PATCH 016/208] return id of owner when getting document/folder data --- restapi/index.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/restapi/index.php b/restapi/index.php index ae5067442..55260ae0b 100644 --- a/restapi/index.php +++ b/restapi/index.php @@ -56,7 +56,8 @@ class RestapiController { /* {{{ */ 'name'=>$document->getName(), 'comment'=>$document->getComment(), 'keywords'=>$document->getKeywords(), - 'categories'=>$tmp + 'categories'=>$tmp, + 'owner'=>(int)$document->getOwner()->getId() ); return $data; } /* }}} */ @@ -142,6 +143,7 @@ class RestapiController { /* {{{ */ 'name'=>$folder->getName(), 'comment'=>$folder->getComment(), 'date'=>date('Y-m-d H:i:s', $folder->getDate()), + 'owner'=>(int)$folder->getOwner()->getId() ); $attributes = $this->__getAttributesData($folder); if($attributes) { From 4a3cdf24b51649a6c644f64d89c9b81607b76651 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 27 Nov 2024 19:08:14 +0100 Subject: [PATCH 017/208] fix typo in comment --- views/bootstrap/class.Bootstrap.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/views/bootstrap/class.Bootstrap.php b/views/bootstrap/class.Bootstrap.php index 69ccb126a..9b69f4f8a 100644 --- a/views/bootstrap/class.Bootstrap.php +++ b/views/bootstrap/class.Bootstrap.php @@ -1736,7 +1736,7 @@ $(document).ready(function() { /** * This function is deprecated. Don't use it anymore. There is a generic * folderSelected and documentSelected function in application.js - * If you extra functions to be called then define them in your own js code + * If you need extra functions to be called then define them in your own js code */ function printDocumentChooserJs($form, $formname='') { /* {{{ */ if(!$formname) @@ -1802,7 +1802,7 @@ function folderSelected(id, name) { /** * This function is deprecated. Don't use it anymore. There is a generic * folderSelected and documentSelected function in application.js - * If you extra functions to be called then define them in your own js code + * If you need extra functions to be called then define them in your own js code */ function printFolderChooserJs($form, $formname='') { /* {{{ */ if(!$formname) From 2fb41d1f40432e9ae8cde277b77c51ce3933a68d Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 27 Nov 2024 19:09:57 +0100 Subject: [PATCH 018/208] new method showConfigFolder() --- views/bootstrap/class.Settings.php | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/views/bootstrap/class.Settings.php b/views/bootstrap/class.Settings.php index 8e59afb35..1c316eb3f 100644 --- a/views/bootstrap/class.Settings.php +++ b/views/bootstrap/class.Settings.php @@ -258,6 +258,35 @@ class SeedDMS_View_Settings extends SeedDMS_Theme_Style { params['settings']; + $dms = $this->params['dms']; +?> + "> + + +{"_".$name})) + $selections = $settings->{"_".$name}; + else + $selections = explode(',', $settings->{"_".$name}); + echo ""; +?> + + +params['settings']; $dms = $this->params['dms']; From ae22f5aba6b485732bbe518782ba4ce29a7a3700 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 27 Nov 2024 19:10:26 +0100 Subject: [PATCH 019/208] fix typo in comment --- views/bootstrap4/class.Bootstrap4.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/views/bootstrap4/class.Bootstrap4.php b/views/bootstrap4/class.Bootstrap4.php index bfdb1be46..ebafc2524 100644 --- a/views/bootstrap4/class.Bootstrap4.php +++ b/views/bootstrap4/class.Bootstrap4.php @@ -1749,7 +1749,7 @@ $(document).ready(function() { /** * This function is deprecated. Don't use it anymore. There is a generic * folderSelected and documentSelected function in application.js - * If you extra functions to be called then define them in your own js code + * If you need extra functions to be called then define them in your own js code */ function printDocumentChooserJs($form, $formname='') { /* {{{ */ if(!$formname) @@ -1818,7 +1818,7 @@ function folderSelected(id, name) { /** * This function is deprecated. Don't use it anymore. There is a generic * folderSelected and documentSelected function in application.js - * If you extra functions to be called then define them in your own js code + * If you need extra functions to be called then define them in your own js code */ function printFolderChooserJs($form, $formname='') { /* {{{ */ if(!$formname) From 5221f9756e467e48aa16b09de0c1058af2476134 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 27 Nov 2024 19:11:00 +0100 Subject: [PATCH 020/208] new config option to exclude folders from dashboard --- CHANGELOG | 2 ++ inc/inc.ClassSettings.php | 5 +++++ op/op.Settings.php | 1 + out/out.Dashboard.php | 1 + views/bootstrap/class.Dashboard.php | 18 ++++++++++++++++++ views/bootstrap/class.Settings.php | 1 + 6 files changed, 28 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 67ea1efaf..68d4836b8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,8 @@ Changes in version 5.1.37 -------------------------------------------------------------------------------- - do not show chart by category if there are no categories +- documents in certain folders can be excluded from dashboard, could be useful + for folders containing archived documents -------------------------------------------------------------------------------- Changes in version 5.1.36 diff --git a/inc/inc.ClassSettings.php b/inc/inc.ClassSettings.php index b58f704bf..5cc4e84d3 100644 --- a/inc/inc.ClassSettings.php +++ b/inc/inc.ClassSettings.php @@ -279,6 +279,8 @@ class Settings { /* {{{ */ var $_maxRecursiveCount = 10000; // number of days in the past of the dashboard var $_daysPastDashboard = 7; + // list of folders not considered for dashboard + var $_excludeFoldersDashboard = ''; // enable/disable help var $_enableHelp = true; // enable/disable language selection menu @@ -566,6 +568,8 @@ class Settings { /* {{{ */ $this->_enableRecursiveCount = Settings::boolVal($tab["enableRecursiveCount"]); $this->_maxRecursiveCount = intval($tab["maxRecursiveCount"]); $this->_daysPastDashboard = intval($tab["daysPastDashboard"]); + if(trim(strval($tab["excludeFoldersDashboard"]))) + $this->_excludeFoldersDashboard = explode(',',strval($tab["excludeFoldersDashboard"])); $this->_enableHelp = Settings::boolVal($tab["enableHelp"]); $this->_enableLanguageSelector = Settings::boolVal($tab["enableLanguageSelector"]); $this->_enableThemeSelector = Settings::boolVal($tab["enableThemeSelector"]); @@ -976,6 +980,7 @@ class Settings { /* {{{ */ $this->setXMLAttributValue($node, "enableRecursiveCount", $this->_enableRecursiveCount); $this->setXMLAttributValue($node, "maxRecursiveCount", $this->_maxRecursiveCount); $this->setXMLAttributValue($node, "daysPastDashboard", $this->_daysPastDashboard); + $this->setXMLAttributValue($node, "excludeFoldersDashboard", implode(',', $this->_excludeFoldersDashboard)); $this->setXMLAttributValue($node, "enableHelp", $this->_enableHelp); $this->setXMLAttributValue($node, "enableLanguageSelector", $this->_enableLanguageSelector); $this->setXMLAttributValue($node, "enableThemeSelector", $this->_enableThemeSelector); diff --git a/op/op.Settings.php b/op/op.Settings.php index 5a010bd40..704eb8da2 100644 --- a/op/op.Settings.php +++ b/op/op.Settings.php @@ -148,6 +148,7 @@ if ($action == "saveSettings") setBoolValue("enableRecursiveCount"); setIntValue("maxRecursiveCount"); setIntValue("daysPastDashboard"); + setArrayValue("excludeFoldersDashboard"); setBoolValue("enableLanguageSelector"); setBoolValue("enableHelp"); setBoolValue("enableThemeSelector"); diff --git a/out/out.Dashboard.php b/out/out.Dashboard.php index 8a72456fd..7755131de 100644 --- a/out/out.Dashboard.php +++ b/out/out.Dashboard.php @@ -25,6 +25,7 @@ if($view) { $view->setParam('convertToPdf', $settings->_convertToPdf); $view->setParam('timeout', $settings->_cmdTimeout); $view->setParam('dayspastdashboard', (int) $settings->_daysPastDashboard); + $view->setParam('excludedfolders', $settings->_excludeFoldersDashboard); $view->setParam('accessobject', $accessop); $view->setParam('xsendfile', $settings->_enableXsendfile); $view($_GET); diff --git a/views/bootstrap/class.Dashboard.php b/views/bootstrap/class.Dashboard.php index 3cfcd4c78..ddf80f235 100644 --- a/views/bootstrap/class.Dashboard.php +++ b/views/bootstrap/class.Dashboard.php @@ -69,6 +69,7 @@ class SeedDMS_View_Dashboard extends SeedDMS_Theme_Style { $previewconverters = $this->params['previewConverters']; $timeout = $this->params['timeout']; $dayspastdashboard = $this->params['dayspastdashboard']; + $excludedfolders = $this->params['excludedfolders']; $xsendfile = $this->params['xsendfile']; $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); @@ -80,6 +81,11 @@ class SeedDMS_View_Dashboard extends SeedDMS_Theme_Style { echo $this->contentHeading(getMLText('new_documents')); $documents = $dms->getLatestChanges('newdocuments', mktime(0, 0, 0)-$dayspastdashboard*86400, time()); $documents = SeedDMS_Core_DMS::filterAccess($documents, $user, M_READ); + foreach($documents as $i=>$doc) { + $fl = explode(':', $doc->getFolderList()); + if(array_diff($fl, $excludedfolders)) + unset($documents[$i]); + } if (count($documents) > 0) { $this->printList($documents, $previewer); } @@ -94,6 +100,7 @@ class SeedDMS_View_Dashboard extends SeedDMS_Theme_Style { $previewconverters = $this->params['previewConverters']; $timeout = $this->params['timeout']; $dayspastdashboard = $this->params['dayspastdashboard']; + $excludedfolders = $this->params['excludedfolders']; $xsendfile = $this->params['xsendfile']; $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); @@ -105,6 +112,11 @@ class SeedDMS_View_Dashboard extends SeedDMS_Theme_Style { echo $this->contentHeading(getMLText('updated_documents')); $documents = $dms->getLatestChanges('updateddocuments', mktime(0, 0, 0)-$dayspastdashboard*86400, time()); $documents = SeedDMS_Core_DMS::filterAccess($documents, $user, M_READ); + foreach($documents as $i=>$doc) { + $fl = explode(':', $doc->getFolderList()); + if(array_diff($fl, $excludedfolders)) + unset($documents[$i]); + } if (count($documents) > 0) { $this->printList($documents, $previewer); } @@ -119,6 +131,7 @@ class SeedDMS_View_Dashboard extends SeedDMS_Theme_Style { $previewconverters = $this->params['previewConverters']; $timeout = $this->params['timeout']; $dayspastdashboard = $this->params['dayspastdashboard']; + $excludedfolders = $this->params['excludedfolders']; $xsendfile = $this->params['xsendfile']; $previewer = new SeedDMS_Preview_Previewer($cachedir, $previewwidth, $timeout, $xsendfile); @@ -130,6 +143,11 @@ class SeedDMS_View_Dashboard extends SeedDMS_Theme_Style { echo $this->contentHeading(getMLText('status_change')); $documents = $dms->getLatestChanges('statuschange', mktime(0, 0, 0)-$dayspastdashboard*86400, time()); $documents = SeedDMS_Core_DMS::filterAccess($documents, $user, M_READ); + foreach($documents as $i=>$doc) { + $fl = explode(':', $doc->getFolderList()); + if(array_diff($fl, $excludedfolders)) + unset($documents[$i]); + } if (count($documents) > 0) { $this->printList($documents, $previewer); } diff --git a/views/bootstrap/class.Settings.php b/views/bootstrap/class.Settings.php index 1c316eb3f..079fddb0d 100644 --- a/views/bootstrap/class.Settings.php +++ b/views/bootstrap/class.Settings.php @@ -467,6 +467,7 @@ if(($kkk = $this->callHook('getFullSearchEngine')) && is_array($kkk)) showConfigCheckbox('settings_enableRecursiveCount', 'enableRecursiveCount'); ?> showConfigText('settings_maxRecursiveCount', 'maxRecursiveCount'); ?> showConfigText('settings_daysPastDashboard', 'daysPastDashboard'); ?> +showConfigFolder('settings_excludeFoldersDashboard', 'excludeFoldersDashboard'); ?> showConfigCheckbox('settings_enableLanguageSelector', 'enableLanguageSelector'); ?> showConfigCheckbox('settings_enableHelp', 'enableHelp'); ?> showConfigCheckbox('settings_enableThemeSelector', 'enableThemeSelector'); ?> From a787d614048028babe0f8af076d486c389c002d5 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Sat, 7 Dec 2024 19:09:01 +0100 Subject: [PATCH 021/208] add conversion for webp and avif images --- inc/inc.ClassConversionServiceImageToImage.php | 6 ++++++ inc/inc.ConversionInit.php | 2 ++ 2 files changed, 8 insertions(+) diff --git a/inc/inc.ClassConversionServiceImageToImage.php b/inc/inc.ClassConversionServiceImageToImage.php index ca2120c15..7f691e9b0 100644 --- a/inc/inc.ClassConversionServiceImageToImage.php +++ b/inc/inc.ClassConversionServiceImageToImage.php @@ -94,6 +94,12 @@ class SeedDMS_ConversionServiceImageToImage extends SeedDMS_ConversionServiceBas case 'image/gif': $im = @imagecreatefromgif($infile); break; + case 'image/webp': + $im = @imagecreatefromwebp($infile); + break; + case 'image/avif': + $im = @imagecreatefromavif($infile); + break; } if($im) { $width = imagesx($im); diff --git a/inc/inc.ConversionInit.php b/inc/inc.ConversionInit.php index 3e384025b..f5cce91c3 100644 --- a/inc/inc.ConversionInit.php +++ b/inc/inc.ConversionInit.php @@ -63,6 +63,8 @@ if (extension_loaded('gd') || extension_loaded('imagick')) { $conversionmgr->addService(new SeedDMS_ConversionServiceImageToImage('image/png', 'image/png'))->setLogger($logger); $conversionmgr->addService(new SeedDMS_ConversionServiceImageToImage('image/jpg', 'image/png'))->setLogger($logger); $conversionmgr->addService(new SeedDMS_ConversionServiceImageToImage('image/gif', 'image/png'))->setLogger($logger); + $conversionmgr->addService(new SeedDMS_ConversionServiceImageToImage('image/webp', 'image/png'))->setLogger($logger); + $conversionmgr->addService(new SeedDMS_ConversionServiceImageToImage('image/avif', 'image/png'))->setLogger($logger); } if (extension_loaded('imagick')) { From abe6b94b3e8a1d6a87025716e470269915a1d7b3 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 10 Dec 2024 15:04:20 +0100 Subject: [PATCH 022/208] propperly check if a fulltext service exists --- inc/inc.ClassFulltextService.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/inc.ClassFulltextService.php b/inc/inc.ClassFulltextService.php index 286444a45..b729a3d8a 100644 --- a/inc/inc.ClassFulltextService.php +++ b/inc/inc.ClassFulltextService.php @@ -209,7 +209,7 @@ class SeedDMS_FulltextService { if($this->index) return $this->index; - if($this->services[0]) { + if($this->services) { if($recreate) $this->index = $this->services[0]['Indexer']::create($this->services[0]['Conf']); else @@ -222,7 +222,7 @@ class SeedDMS_FulltextService { public function Search() { /* {{{ */ if($this->search) return $this->search; - if($this->services[0]) { + if($this->services) { $this->search = new $this->services[0]['Search']($this->index); return $this->search; } else { From b6dcff3fe3b3b2aad78609e20f6bf8dacd56294f Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 11 Dec 2024 14:46:12 +0100 Subject: [PATCH 023/208] upgrade from slim 3 to slim 4 --- composer-dist.json | 4 +- inc/inc.ClassAuthenticationMiddleware.php | 16 +- index.php | 50 +- restapi/index.php | 1358 ++++++++++++--------- 4 files changed, 800 insertions(+), 628 deletions(-) diff --git a/composer-dist.json b/composer-dist.json index 93c4e2203..a5b830e5e 100644 --- a/composer-dist.json +++ b/composer-dist.json @@ -8,7 +8,7 @@ "robthree/twofactorauth": "^1.5", "sabre/dav": "^4.", "sabre/xml": "*", - "slim/slim": "^3.0", + "slim/slim": "^4.0", "erusev/parsedown": "*", "erusev/parsedown-extra": "*", "pear/log": "*", @@ -20,6 +20,7 @@ "alecrabbit/php-console-colour": "*", "zf1/zend-search-lucene": "*", "symfony/http-foundation": "^5.4", + "php-di/php-di": "^6.4", "seeddms/core": "dev-master", "seeddms/lucene": "dev-master", "seeddms/preview": "dev-master", @@ -66,5 +67,4 @@ } } ] - } diff --git a/inc/inc.ClassAuthenticationMiddleware.php b/inc/inc.ClassAuthenticationMiddleware.php index fa8d0fdc7..97e74c55f 100644 --- a/inc/inc.ClassAuthenticationMiddleware.php +++ b/inc/inc.ClassAuthenticationMiddleware.php @@ -48,18 +48,18 @@ class SeedDMS_Auth_Middleware_Session { /* {{{ */ * * @return \Psr\Http\Message\ResponseInterface */ - public function __invoke($request, $response, $next) { + public function __invoke($request, $handler) { // $this->container has the DI - $dms = $this->container->dms; - $settings = $this->container->config; - $logger = $this->container->logger; + $dms = $this->container->get('dms'); + $settings = $this->container->get('config'); + $logger = $this->container->get('logger'); $userobj = null; if ($this->container->has('userobj')) { - $userobj = $this->container->userobj; + $userobj = $this->container->get('userobj'); } if ($userobj) { - $response = $next($request, $response); + $response = $handler->handle($request); return $response; } @@ -100,9 +100,9 @@ class SeedDMS_Auth_Middleware_Session { /* {{{ */ } else { return $response->withStatus(403); } - $this->container['userobj'] = $userobj; + $this->container->set('userobj', $userobj); - $response = $next($request, $response); + $response = $handler->handle($request); return $response; } } /* }}} */ diff --git a/index.php b/index.php index b6fa64a0d..bf780ef9a 100644 --- a/index.php +++ b/index.php @@ -31,6 +31,9 @@ require "inc/inc.Settings.php"; +use DI\ContainerBuilder; +use Slim\Factory\AppFactory; + if(true) { require_once("inc/inc.Utils.php"); require_once("inc/inc.LogInit.php"); @@ -39,7 +42,9 @@ if(true) { require_once("inc/inc.Extension.php"); require_once("inc/inc.DBInit.php"); - $c = new \Slim\Container(); //Create Your container + $containerBuilder = new \DI\ContainerBuilder(); + $c = $containerBuilder->build(); + /* $c['notFoundHandler'] = function ($c) use ($settings, $dms) { return function ($request, $response) use ($c, $settings, $dms) { $uri = $request->getUri(); @@ -62,25 +67,42 @@ if(true) { ->withHeader('Location', isset($settings->_siteDefaultPage) && strlen($settings->_siteDefaultPage)>0 ? $settings->_httpRoot.$settings->_siteDefaultPage : $settings->_httpRoot."out/out.ViewFolder.php"); }; }; - $app = new \Slim\App($c); + */ + AppFactory::setContainer($c); + $app = AppFactory::create(); + /* put lots of data into the container, because if slim instanciates + * a class by itself (with the help from the DI container), it will + * pass the container to the constructor of the instanciated class. + */ $container = $app->getContainer(); - $container['dms'] = $dms; - $container['config'] = $settings; - $container['conversionmgr'] = $conversionmgr; - $container['logger'] = $logger; - $container['fulltextservice'] = $fulltextservice; - $container['notifier'] = $notifier; - $container['authenticator'] = $authenticator; + $container->set('dms', $dms); + $container->set('config', $settings); + $container->set('conversionmgr', $conversionmgr); + $container->set('logger', $logger); + $container->set('fulltextservice', $fulltextservice); + $container->set('notifier', $notifier); + $container->set('authenticator', $authenticator); + if(isset($GLOBALS['SEEDDMS_HOOKS']['initDMS'])) { + foreach($GLOBALS['SEEDDMS_HOOKS']['initDMS'] as $hookObj) { + if (method_exists($hookObj, 'addMiddleware')) { + $hookObj->addMiddleware($app); + } + } + } + + $app->get('/', function($request, $response) { + return $response + ->withHeader('Location', '/out/out.ViewFolder.php') + ->withStatus(302); + + }); if(isset($GLOBALS['SEEDDMS_HOOKS']['initDMS'])) { foreach($GLOBALS['SEEDDMS_HOOKS']['initDMS'] as $hookObj) { if (method_exists($hookObj, 'addRoute')) { + // FIXME: pass $app only just like initRestAPI. $app has a container + // which contains all other objects $hookObj->addRoute(array('dms'=>$dms, 'app'=>$app, 'settings'=>$settings, 'conversionmgr'=>$conversionmgr, 'authenticator'=>$authenticator, 'fulltextservice'=>$fulltextservice, 'logger'=>$logger)); -// } else { -// include("inc/inc.Authentication.php"); -// if (method_exists($hookObj, 'addRouteAfterAuthentication')) { -// $hookObj->addRouteAfterAuthentication(array('dms'=>$dms, 'app'=>$app, 'settings'=>$settings, 'user'=>$user)); -// } } } } diff --git a/restapi/index.php b/restapi/index.php index 55260ae0b..c5d92c03e 100644 --- a/restapi/index.php +++ b/restapi/index.php @@ -18,13 +18,40 @@ require_once("../inc/inc.ClassController.php"); require "vendor/autoload.php"; use Psr\Container\ContainerInterface; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\RequestHandlerInterface; +use Psr\Http\Server\MiddlewareInterface; +use DI\ContainerBuilder; +use Slim\Factory\AppFactory; -class RestapiController { /* {{{ */ +final class JsonRenderer +{ + public function json( + ResponseInterface $response, + array $data = null + ): ResponseInterface { + $response = $response->withHeader('Content-Type', 'application/json'); + + $response->getBody()->write( + (string)json_encode( + $data, + JSON_UNESCAPED_SLASHES | JSON_PARTIAL_OUTPUT_ON_ERROR + ) + ); + + return $response; + } +} + +final class SeedDMS_RestapiController { /* {{{ */ protected $container; + protected $renderer; - // constructor receives container instance - public function __construct(ContainerInterface $container) { + // constructor receives container and renderer instance by DI + public function __construct(ContainerInterface $container, JsonRenderer $renderer) { $this->container = $container; + $this->renderer = $renderer; } protected function __getAttributesData($obj) { /* {{{ */ @@ -219,15 +246,15 @@ class RestapiController { /* {{{ */ function doLogin($request, $response) { /* {{{ */ global $session; - $dms = $this->container->dms; - $settings = $this->container->config; - $logger = $this->container->logger; - $authenticator = $this->container->authenticator; + $dms = $this->container->get('dms'); + $settings = $this->container->get('config'); + $logger = $this->container->get('logger'); + $authenticator = $this->container->get('authenticator'); $params = $request->getParsedBody(); if(empty($params['user']) || empty($params['pass'])) { $logger->log("Login without username or password failed", PEAR_LOG_INFO); - return $response->withJson(array('success'=>false, 'message'=>'No user or password given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No user or password given', 'data'=>''))->withStatus(400); } $username = $params['user']; $password = $params['pass']; @@ -236,12 +263,12 @@ class RestapiController { /* {{{ */ if(!$userobj) { setcookie("mydms_session", '', time()-3600, $settings->_httpRoot); $logger->log("Login with user name '".$username."' failed", PEAR_LOG_ERR); - return $response->withJson(array('success'=>false, 'message'=>'Login failed', 'data'=>''), 403); + 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()); if(!$id = $session->create(array('userid'=>$userobj->getId(), 'theme'=>$userobj->getTheme(), 'lang'=>$userobj->getLanguage()))) { - return $response->withJson(array('success'=>false, 'message'=>'Creating session failed', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Creating session failed', 'data'=>''))->withStatus(500); } // Set the session cookie. @@ -253,14 +280,14 @@ class RestapiController { /* {{{ */ $dms->setUser($userobj); $logger->log("Login with user name '".$username."' successful", PEAR_LOG_INFO); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$this->__getUserData($userobj)), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$this->__getUserData($userobj)))->withStatus(200); } } /* }}} */ function doLogout($request, $response) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; - $settings = $this->container->config; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); + $settings = $this->container->get('config'); if(isset($_COOKIE['mydms_session'])) { $dms_session = $_COOKIE["mydms_session"]; @@ -280,42 +307,42 @@ class RestapiController { /* {{{ */ } setcookie("mydms_session", '', time()-3600, $settings->_httpRoot); } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(200); } /* }}} */ function setFullName($request, $response) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); return; } $params = $request->getParsedBody(); $userobj->setFullName($params['fullname']); $data = $this->__getUserData($userobj); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); } /* }}} */ function setEmail($request, $response) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); return; } $params = $request->getParsedBody(); $userobj->setEmail($params['email']); $data = $this->__getUserData($userobj); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); } /* }}} */ function getLockedDocuments($request, $response) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(false !== ($documents = $dms->getDocumentsLockedByUser($userobj))) { $documents = SeedDMS_Core_DMS::filterAccess($documents, $userobj, M_READ); @@ -326,16 +353,16 @@ class RestapiController { /* {{{ */ $recs[] = $this->__getLatestVersionData($lc); } } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$recs))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'', 'data'=>''))->withStatus(500); } } /* }}} */ function getFolder($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; - $settings = $this->container->config; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); + $settings = $this->container->get('config'); $params = $request->getQueryParams(); $forcebyname = isset($params['forcebyname']) ? $params['forcebyname'] : 0; @@ -351,26 +378,26 @@ class RestapiController { /* {{{ */ if($folder) { if($folder->getAccessMode($userobj) >= M_READ) { $data = $this->__getFolderData($folder); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No such folder', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such folder', 'data'=>''))->withStatus(404); } } /* }}} */ function getFolderParent($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $id = $args['id']; if($id == 0) { - return $response->withJson(array('success'=>true, 'message'=>'id is 0', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'id is 0', 'data'=>''))->withStatus(200); } $root = $dms->getRootFolder(); if($root->getId() == $id) { - return $response->withJson(array('success'=>true, 'message'=>'id is root folder', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'id is root folder', 'data'=>''))->withStatus(200); } $folder = $dms->getFolder($id); if($folder) { @@ -378,24 +405,24 @@ class RestapiController { /* {{{ */ if($parent) { if($parent->getAccessMode($userobj) >= M_READ) { $rec = $this->__getFolderData($parent); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$rec), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$rec))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No such folder', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such folder', 'data'=>''))->withStatus(404); } } /* }}} */ function getFolderPath($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(empty($args['id'])) { - return $response->withJson(array('success'=>true, 'message'=>'id is 0', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'id is 0', 'data'=>''))->withStatus(200); } $folder = $dms->getFolder($args['id']); if($folder) { @@ -405,40 +432,40 @@ class RestapiController { /* {{{ */ foreach($path as $element) { $data[] = array('id'=>$element->getId(), 'name'=>$element->getName()); } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No such folder', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such folder', 'data'=>''))->withStatus(404); } } /* }}} */ function getFolderAttributes($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $folder = $dms->getFolder($args['id']); if($folder) { if ($folder->getAccessMode($userobj) >= M_READ) { $attributes = $this->__getAttributesData($folder); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$attributes), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$attributes))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No such folder', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such folder', 'data'=>''))->withStatus(404); } } /* }}} */ function getFolderChildren($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(empty($args['id'])) { $folder = $dms->getRootFolder(); $recs = array($this->$this->__getFolderData($folder)); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$recs))->withStatus(200); } else { $folder = $dms->getFolder($args['id']); if($folder) { @@ -457,30 +484,30 @@ class RestapiController { /* {{{ */ $recs[] = $this->__getLatestVersionData($lc); } } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$recs))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No such folder', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such folder', 'data'=>''))->withStatus(404); } } } /* }}} */ function createFolder($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; - $settings = $this->container->config; - $logger = $this->container->logger; - $fulltextservice = $this->container->fulltextservice; - $notifier = $this->container->notifier; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); + $settings = $this->container->get('config'); + $logger = $this->container->get('logger'); + $fulltextservice = $this->container->get('fulltextservice'); + $notifier = $this->container->get('notifier'); if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); } if(!ctype_digit($args['id']) || $args['id'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No parent folder given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No parent folder given', 'data'=>''))->withStatus(400); return; } $parent = $dms->getFolder($args['id']); @@ -492,7 +519,7 @@ class RestapiController { /* {{{ */ if(isset($params['sequence'])) { $sequence = str_replace(',', '.', $params["sequence"]); if (!is_numeric($sequence)) - return $response->withJson(array('success'=>false, 'message'=>getMLText("invalid_sequence"), 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>getMLText("invalid_sequence"), 'data'=>''))->withStatus(400); } else { $dd = $parent->getSubFolders('s'); if(count($dd) > 1) @@ -515,7 +542,7 @@ class RestapiController { /* {{{ */ /* Check if name already exists in the folder */ if(!$settings->_enableDuplicateSubFolderNames) { if($parent->hasSubFolderByName($params['name'])) { - return $response->withJson(array('success'=>false, 'message'=>getMLText("subfolder_duplicate_name"), 'data'=>''), 409); + return $this->renderer->json($response, array('success'=>false, 'message'=>getMLText("subfolder_duplicate_name"), 'data'=>''))->withStatus(409); } } @@ -536,35 +563,35 @@ class RestapiController { /* {{{ */ if($notifier) { $notifier->sendNewFolderMail($folder, $userobj); } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$rec), 201); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$rec))->withStatus(201); } else { - return $response->withJson(array('success'=>false, 'message'=>'Could not create folder', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not create folder', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'Missing folder name', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Missing folder name', 'data'=>''))->withStatus(400); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access on destination folder', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access on destination folder', 'data'=>''))->withStatus(403); } } else { - return $response->withJson(array('success'=>false, 'message'=>'Could not find parent folder', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not find parent folder', 'data'=>''))->withStatus(404); } } /* }}} */ function moveFolder($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); } if(!ctype_digit($args['id']) || $args['id'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No source folder given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No source folder given', 'data'=>''))->withStatus(400); } if(!ctype_digit($args['folderid']) || $args['folderid'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No destination folder given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No destination folder given', 'data'=>''))->withStatus(400); } $mfolder = $dms->getFolder($args['id']); @@ -573,82 +600,82 @@ class RestapiController { /* {{{ */ if($folder = $dms->getFolder($args['folderid'])) { if($folder->getAccessMode($userobj, 'moveFolder') >= M_READWRITE) { if($mfolder->setParent($folder)) { - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'Error moving folder', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Error moving folder', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access on destination folder', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access on destination folder', 'data'=>''))->withStatus(403); } } else { if($folder === null) $status = 404; else $status = 500; - return $response->withJson(array('success'=>false, 'message'=>'No destination folder', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No destination folder', 'data'=>''))->withStatus($status); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($mfolder === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No folder', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No folder', 'data'=>''))->withStatus($status); } } /* }}} */ function deleteFolder($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); } if(!ctype_digit($args['id']) || $args['id'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'id is 0', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'id is 0', 'data'=>''))->withStatus(400); } $mfolder = $dms->getFolder($args['id']); if($mfolder) { if ($mfolder->getAccessMode($userobj, 'removeFolder') >= M_READWRITE) { if($mfolder->remove()) { - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'Error deleting folder', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Error deleting folder', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($mfolder === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No folder', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No folder', 'data'=>''))->withStatus($status); } } /* }}} */ function uploadDocument($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; - $settings = $this->container->config; - $notifier = $this->container->notifier; - $fulltextservice = $this->container->fulltextservice; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); + $settings = $this->container->get('config'); + $notifier = $this->container->get('notifier'); + $fulltextservice = $this->container->get('fulltextservice'); if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); } if(!ctype_digit($args['id']) || $args['id'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No parent folder id given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No parent folder id given', 'data'=>''))->withStatus(400); } if($settings->_quota > 0) { $remain = checkQuota($userobj); if ($remain < 0) { - return $response->withJson(array('success'=>false, 'message'=>'Quota exceeded', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Quota exceeded', 'data'=>''))->withStatus(400); } } @@ -663,7 +690,7 @@ class RestapiController { /* {{{ */ if(isset($params['sequence'])) { $sequence = str_replace(',', '.', $params["sequence"]); if (!is_numeric($sequence)) - return $response->withJson(array('success'=>false, 'message'=>getMLText("invalid_sequence"), 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>getMLText("invalid_sequence"), 'data'=>''))->withStatus(400); } else { $dd = $mfolder->getDocuments('s'); if(count($dd) > 1) @@ -674,7 +701,7 @@ class RestapiController { /* {{{ */ if(isset($params['expdate'])) { $tmp = explode('-', $params["expdate"]); if(count($tmp) != 3) - return $response->withJson(array('success'=>false, 'message'=>getMLText('malformed_expiration_date'), 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>getMLText('malformed_expiration_date'), 'data'=>''))->withStatus(400); $expires = mktime(0,0,0, $tmp[1], $tmp[2], $tmp[0]); } else $expires = 0; @@ -700,15 +727,15 @@ class RestapiController { /* {{{ */ if($attrdef) { if($attribute) { if(!$attrdef->validate($attribute)) { - return $response->withJson(array('success'=>false, 'message'=>getAttributeValidationText($attrdef->getValidationError(), $attrdef->getName(), $attribute), 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>getAttributeValidationText($attrdef->getValidationError(), $attrdef->getName(), $attribute), 'data'=>''))->withStatus(400); } } elseif($attrdef->getMinValues() > 0) { - return $response->withJson(array('success'=>false, 'message'=>getMLText("attr_min_values", array("attrname"=>$attrdef->getName())), 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>getMLText("attr_min_values", array("attrname"=>$attrdef->getName())), 'data'=>''))->withStatus(400); } } } if (count($uploadedFiles) == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No file detected', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No file detected', 'data'=>''))->withStatus(400); } $file_info = array_pop($uploadedFiles); if ($origfilename == null) @@ -718,7 +745,7 @@ class RestapiController { /* {{{ */ /* Check if name already exists in the folder */ if(!$settings->_enableDuplicateDocNames) { if($mfolder->hasDocumentByName($docname)) { - return $response->withJson(array('success'=>false, 'message'=>getMLText("document_duplicate_name"), 'data'=>''), 409); + return $this->renderer->json($response, array('success'=>false, 'message'=>getMLText("document_duplicate_name"), 'data'=>''))->withStatus(409); } } // Get the list of reviewers and approvers for this document. @@ -796,7 +823,7 @@ class RestapiController { /* {{{ */ $errmsg = $err; } unlink($temp); - return $response->withJson(array('success'=>false, 'message'=>'Upload failed', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Upload failed', 'data'=>''))->withStatus(500); } else { if($controller->hasHook('cleanUpDocument')) { $controller->callHook('cleanUpDocument', $document, ['ѕource'=>'restapi', 'type'=>$userfiletype, 'name'=>$origfilename]); @@ -806,7 +833,7 @@ class RestapiController { /* {{{ */ $notifier->sendNewDocumentMail($document, $userobj); } unlink($temp); - return $response->withJson(array('success'=>true, 'message'=>'Upload succeded', 'data'=>$this->__getLatestVersionData($document->getLatestContent())), 201); + return $this->renderer->json($response, array('success'=>true, 'message'=>'Upload succeded', 'data'=>$this->__getLatestVersionData($document->getLatestContent())))->withStatus(201); } /* $res = $mfolder->addDocument($docname, $comment, $expires, $owner ? $owner : $userobj, $keywords, $cats, $temp, $origfilename ? $origfilename : basename($temp), $fileType, $userfiletype, $sequence, array(), array(), $reqversion, $version_comment, $attributes); @@ -816,49 +843,49 @@ class RestapiController { /* {{{ */ if($notifier) { $notifier->sendNewDocumentMail($doc, $userobj); } - return $response->withJson(array('success'=>true, 'message'=>'Upload succeded', 'data'=>$this->__getLatestVersionData($doc->getLatestContent())), 201); + return $this->renderer->json($response, array('success'=>true, 'message'=>'Upload succeded', 'data'=>$this->__getLatestVersionData($doc->getLatestContent())))->withStatus(201); } else { - return $response->withJson(array('success'=>false, 'message'=>'Upload failed', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Upload failed', 'data'=>''))->withStatus(500); } */ } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($mfolder === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No folder', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No folder', 'data'=>''))->withStatus($status); } } /* }}} */ function updateDocument($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; - $settings = $this->container->config; - $notifier = $this->container->notifier; - $fulltextservice = $this->container->fulltextservice; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); + $settings = $this->container->get('config'); + $notifier = $this->container->get('notifier'); + $fulltextservice = $this->container->get('fulltextservice'); if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); } if(!ctype_digit($args['id']) || $args['id'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No document id given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document id given', 'data'=>''))->withStatus(400); } if($settings->_quota > 0) { $remain = checkQuota($userobj); if ($remain < 0) { - return $response->withJson(array('success'=>false, 'message'=>'Quota exceeded', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Quota exceeded', 'data'=>''))->withStatus(400); } } $document = $dms->getDocument($args['id']); if($document) { if ($document->getAccessMode($userobj, 'updateDocument') < M_READWRITE) { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } $params = $request->getParsedBody(); @@ -873,16 +900,16 @@ class RestapiController { /* {{{ */ if($attrdef) { if($attribute) { if(!$attrdef->validate($attribute)) { - return $response->withJson(array('success'=>false, 'message'=>getAttributeValidationText($attrdef->getValidationError(), $attrdef->getName(), $attribute), 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>getAttributeValidationText($attrdef->getValidationError(), $attrdef->getName(), $attribute), 'data'=>''))->withStatus(400); } } elseif($attrdef->getMinValues() > 0) { - return $response->withJson(array('success'=>false, 'message'=>getMLText("attr_min_values", array("attrname"=>$attrdef->getName())), 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>getMLText("attr_min_values", array("attrname"=>$attrdef->getName())), 'data'=>''))->withStatus(400); } } } $uploadedFiles = $request->getUploadedFiles(); if (count($uploadedFiles) == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No file detected', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No file detected', 'data'=>''))->withStatus(400); } $file_info = array_pop($uploadedFiles); if ($origfilename == null) @@ -892,13 +919,13 @@ class RestapiController { /* {{{ */ /* Check if the uploaded file is identical to last version */ $lc = $document->getLatestContent(); if($lc->getChecksum() == SeedDMS_Core_File::checksum($temp)) { - return $response->withJson(array('success'=>false, 'message'=>'Uploaded file identical to last version', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Uploaded file identical to last version', 'data'=>''))->withStatus(400); } if($document->isLocked()) { $lockingUser = $document->getLockingUser(); if(($lockingUser->getID() != $userobj->getID()) && ($document->getAccessMode($userobj) != M_ALL)) { - return $response->withJson(array('success'=>false, 'message'=>'Document is locked', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Document is locked', 'data'=>''))->withStatus(400); } else $document->setLocked(false); } @@ -967,7 +994,7 @@ class RestapiController { /* {{{ */ } else { $errmsg = $err; } - return $response->withJson(array('success'=>false, 'message'=>'Upload failed: '.$errmsg, 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Upload failed: '.$errmsg, 'data'=>''))->withStatus(500); } else { unlink($temp); if($controller->hasHook('cleanUpDocument')) { @@ -981,10 +1008,10 @@ class RestapiController { /* {{{ */ } $rec = array('id'=>(int)$document->getId(), 'name'=>$document->getName(), 'version'=>$document->getLatestContent()->getVersion()); - return $response->withJson(array('success'=>true, 'message'=>'Upload succeded', 'data'=>$rec), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'Upload succeded', 'data'=>$rec))->withStatus(200); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document', 'data'=>''))->withStatus(404); } } /* }}} */ @@ -992,23 +1019,23 @@ class RestapiController { /* {{{ */ * Old upload method which uses put instead of post */ function uploadDocumentPut($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; - $settings = $this->container->config; - $notifier = $this->container->notifier; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); + $settings = $this->container->get('config'); + $notifier = $this->container->get('notifier'); if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); } if(!ctype_digit($args['id']) || $args['id'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No document id given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document id given', 'data'=>''))->withStatus(400); } if($settings->_quota > 0) { $remain = checkQuota($userobj); if ($remain < 0) { - return $response->withJson(array('success'=>false, 'message'=>'Quota exceeded', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Quota exceeded', 'data'=>''))->withStatus(400); } } @@ -1031,7 +1058,7 @@ class RestapiController { /* {{{ */ /* Check if name already exists in the folder */ if(!$settings->_enableDuplicateDocNames) { if($mfolder->hasDocumentByName($docname)) { - return $response->withJson(array('success'=>false, 'message'=>getMLText("document_duplicate_name"), 'data'=>''), 409); + return $this->renderer->json($response, array('success'=>false, 'message'=>getMLText("document_duplicate_name"), 'data'=>''))->withStatus(409); } } $res = $mfolder->addDocument($docname, '', 0, $userobj, '', array(), $temp, $origfilename ? $origfilename : basename($temp), $fileType, $userfiletype, 0); @@ -1042,32 +1069,32 @@ class RestapiController { /* {{{ */ $notifier->sendNewDocumentMail($doc, $userobj); } $rec = array('id'=>(int)$doc->getId(), 'name'=>$doc->getName()); - return $response->withJson(array('success'=>true, 'message'=>'Upload succeded', 'data'=>$rec), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'Upload succeded', 'data'=>$rec))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'Upload failed', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Upload failed', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($mfolder === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No folder', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No folder', 'data'=>''))->withStatus($status); } } /* }}} */ function uploadDocumentFile($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); } if(!ctype_digit($args['id']) || $args['id'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No document id given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document id given', 'data'=>''))->withStatus(400); } $document = $dms->getDocument($args['id']); if($document) { @@ -1081,7 +1108,7 @@ class RestapiController { /* {{{ */ $version = empty($params['version']) ? 0 : $params['version']; $public = empty($params['public']) ? 'false' : $params['public']; if (count($uploadedFiles) == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No file detected', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No file detected', 'data'=>''))->withStatus(400); } $file_info = array_pop($uploadedFiles); if ($origfilename == null) @@ -1098,36 +1125,36 @@ class RestapiController { /* {{{ */ $fileType, $userfiletype, $version, $public); unlink($temp); if($res) { - return $response->withJson(array('success'=>true, 'message'=>'Upload succeded', 'data'=>$res), 201); + return $this->renderer->json($response, array('success'=>true, 'message'=>'Upload succeded', 'data'=>$res))->withStatus(201); } else { - return $response->withJson(array('success'=>false, 'message'=>'Upload failed', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Upload failed', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($document === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No such document', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such document', 'data'=>''))->withStatus($status); } } /* }}} */ function addDocumentLink($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); } if(!ctype_digit($args['id']) || $args['id'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No source document given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No source document given', 'data'=>''))->withStatus(400); return; } if(!ctype_digit($args['documentid']) || $args['documentid'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No target document given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No target document given', 'data'=>''))->withStatus(400); return; } $sourcedoc = $dms->getDocument($args['id']); @@ -1137,21 +1164,21 @@ class RestapiController { /* {{{ */ $params = $request->getParsedBody(); $public = !isset($params['public']) ? true : false; if ($sourcedoc->addDocumentLink($targetdoc->getId(), $userobj->getID(), $public)){ - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 201); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(201); } else { - return $response->withJson(array('success'=>false, 'message'=>'Could not create document link', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not create document link', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access on source document', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access on source document', 'data'=>''))->withStatus(403); } } else { - return $response->withJson(array('success'=>false, 'message'=>'Could not find source or target document', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not find source or target document', 'data'=>''))->withStatus(500); } } /* }}} */ function getDocument($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $document = $dms->getDocument($args['id']); if($document) { @@ -1159,53 +1186,53 @@ class RestapiController { /* {{{ */ $lc = $document->getLatestContent(); if($lc) { $data = $this->__getLatestVersionData($lc); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($document === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document', 'data'=>''))->withStatus($status); } } /* }}} */ function deleteDocument($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!ctype_digit($args['id'])) { - return $response->withJson(array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''))->withStatus(400); } $document = $dms->getDocument($args['id']); if($document) { if ($document->getAccessMode($userobj, 'deleteDocument') >= M_READWRITE) { if($document->remove()) { - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'Error removing document', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Error removing document', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($document === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document', 'data'=>''))->withStatus($status); } } /* }}} */ function moveDocument($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $document = $dms->getDocument($args['id']); if($document) { @@ -1213,35 +1240,35 @@ class RestapiController { /* {{{ */ if($folder = $dms->getFolder($args['folderid'])) { if($folder->getAccessMode($userobj, 'moveDocument') >= M_READWRITE) { if($document->setFolder($folder)) { - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'Error moving document', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Error moving document', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access on destination folder', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access on destination folder', 'data'=>''))->withStatus(403); } } else { if($folder === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No destination folder', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No destination folder', 'data'=>''))->withStatus($status); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($document === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document', 'data'=>''))->withStatus($status); } } /* }}} */ function getDocumentContent($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $document = $dms->getDocument($args['id']); if($document) { @@ -1255,7 +1282,7 @@ class RestapiController { /* {{{ */ $file = $dms->contentDir . $lc->getPath(); if(!($fh = @fopen($file, 'rb'))) { - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'', 'data'=>''))->withStatus(500); } $stream = new \Slim\Http\Stream($fh); // create a stream instance for the response body @@ -1271,24 +1298,24 @@ class RestapiController { /* {{{ */ sendFile($dms->contentDir . $lc->getPath()); } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($document === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document', 'data'=>''))->withStatus($status); } } /* }}} */ function getDocumentVersions($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $document = $dms->getDocument($args['id']); if($document) { @@ -1298,25 +1325,25 @@ class RestapiController { /* {{{ */ foreach($lcs as $lc) { $recs[] = $this->__getDocumentVersionData($lc); } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$recs))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($document === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document', 'data'=>''))->withStatus($status); } } /* }}} */ function getDocumentVersion($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!ctype_digit($args['id']) || !ctype_digit($args['version'])) { - return $response->withJson(array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''))->withStatus(400); } $document = $dms->getDocument($args['id']); @@ -1331,7 +1358,7 @@ class RestapiController { /* {{{ */ $file = $dms->contentDir . $lc->getPath(); if(!($fh = @fopen($file, 'rb'))) { - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'', 'data'=>''))->withStatus(500); } $stream = new \Slim\Http\Stream($fh); // create a stream instance for the response body @@ -1347,23 +1374,23 @@ class RestapiController { /* {{{ */ sendFile($dms->contentDir . $lc->getPath()); } else { - return $response->withJson(array('success'=>false, 'message'=>'No such version', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such version', 'data'=>''))->withStatus(404); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($document === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document', 'data'=>''))->withStatus($status); } } /* }}} */ function updateDocumentVersion($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $document = $dms->getDocument($args['id']); if($document) { @@ -1373,29 +1400,29 @@ class RestapiController { /* {{{ */ $params = $request->getParsedBody(); if (isset($params['comment'])) { $lc->setComment($params['comment']); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(200); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No such version', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such version', 'data'=>''))->withStatus(404); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($document === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document', 'data'=>''))->withStatus($status); } } /* }}} */ function getDocumentFiles($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!ctype_digit($args['id'])) { - return $response->withJson(array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''))->withStatus(400); } $document = $dms->getDocument($args['id']); @@ -1407,25 +1434,25 @@ class RestapiController { /* {{{ */ foreach($files as $file) { $recs[] = $this->__getDocumentFileData($file); } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$recs))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($document === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document', 'data'=>''))->withStatus($status); } } /* }}} */ function getDocumentFile($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!ctype_digit($args['id']) || !ctype_digit($args['fileid'])) { - return $response->withJson(array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''))->withStatus(400); } $document = $dms->getDocument($args['id']); @@ -1436,7 +1463,7 @@ class RestapiController { /* {{{ */ if($lc) { $file = $dms->contentDir . $lc->getPath(); if(!($fh = @fopen($file, 'rb'))) { - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'', 'data'=>''))->withStatus(500); } $stream = new \Slim\Http\Stream($fh); // create a stream instance for the response body @@ -1452,26 +1479,26 @@ class RestapiController { /* {{{ */ sendFile($dms->contentDir . $lc->getPath()); } else { - return $response->withJson(array('success'=>false, 'message'=>'No document file', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document file', 'data'=>''))->withStatus(404); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($document === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document', 'data'=>''))->withStatus($status); } } /* }}} */ function getDocumentLinks($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!ctype_digit($args['id'])) { - return $response->withJson(array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''))->withStatus(400); } $document = $dms->getDocument($args['id']); @@ -1483,43 +1510,43 @@ class RestapiController { /* {{{ */ foreach($links as $link) { $recs[] = $this->__getDocumentLinkData($link); } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$recs))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($document === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document', 'data'=>''))->withStatus($status); } } /* }}} */ function getDocumentAttributes($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $document = $dms->getDocument($args['id']); if($document) { if ($document->getAccessMode($userobj) >= M_READ) { $attributes = $this->__getAttributesData($document); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$attributes), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$attributes))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($document === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document', 'data'=>''))->withStatus($status); } } /* }}} */ function getDocumentContentAttributes($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $document = $dms->getDocument($args['id']); if($document) { @@ -1529,33 +1556,33 @@ class RestapiController { /* {{{ */ if($version) { if($version->getAccessMode($userobj) >= M_READ) { $attributes = $this->__getAttributesData($version); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$attributes), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$attributes))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No access on version', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access on version', 'data'=>''))->withStatus(403); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No version', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No version', 'data'=>''))->withStatus(404); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($document === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document', 'data'=>''))->withStatus($status); } } /* }}} */ function getDocumentPreview($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; - $settings = $this->container->config; - $conversionmgr = $this->container->conversionmgr; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); + $settings = $this->container->get('config'); + $conversionmgr = $this->container->get('conversionmgr'); if(!ctype_digit($args['id'])) { - return $response->withJson(array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''))->withStatus(400); } $document = $dms->getDocument($args['id']); @@ -1582,7 +1609,7 @@ class RestapiController { /* {{{ */ $file = $previewer->getFileName($object, $args['width']).".png"; if(!($fh = @fopen($file, 'rb'))) { - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'', 'data'=>''))->withStatus(500); } $stream = new \Slim\Http\Stream($fh); // create a stream instance for the response body @@ -1593,31 +1620,31 @@ class RestapiController { /* {{{ */ ->withHeader('Content-Length', $previewer->getFilesize($object)) ->withBody($stream); } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($document === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No document', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document', 'data'=>''))->withStatus($status); } } /* }}} */ function addDocumentCategory($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); } if(!ctype_digit($args['id']) || $args['id'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No document given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document given', 'data'=>''))->withStatus(400); return; } if(!ctype_digit($args['catid']) || $args['catid'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No category given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No category given', 'data'=>''))->withStatus(400); return; } $cat = $dms->getDocumentCategory($args['catid']); @@ -1625,54 +1652,54 @@ class RestapiController { /* {{{ */ if($doc && $cat) { if($doc->getAccessMode($userobj, 'addDocumentCategory') >= M_READ) { if ($doc->addCategories([$cat])){ - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 201); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(201); } else { - return $response->withJson(array('success'=>false, 'message'=>'Could not add document category', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not add document category', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access on document', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access on document', 'data'=>''))->withStatus(403); } } else { if(!$doc) - return $response->withJson(array('success'=>false, 'message'=>'No such document', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such document', 'data'=>''))->withStatus(404); if(!$cat) - return $response->withJson(array('success'=>false, 'message'=>'No such category', 'data'=>''), 404); - return $response->withJson(array('success'=>false, 'message'=>'Could not find category or document', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such category', 'data'=>''))->withStatus(404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not find category or document', 'data'=>''))->withStatus(500); } } /* }}} */ function removeDocumentCategory($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!ctype_digit($args['id']) || !ctype_digit($args['catid'])) { - return $response->withJson(array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''))->withStatus(400); } $document = $dms->getDocument($args['id']); if(!$document) - return $response->withJson(array('success'=>false, 'message'=>'No such document', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such document', 'data'=>''))->withStatus(404); $category = $dms->getDocumentCategory($args['catid']); if(!$category) - return $response->withJson(array('success'=>false, 'message'=>'No such category', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such category', 'data'=>''))->withStatus(404); if ($document->getAccessMode($userobj, 'removeDocumentCategory') >= M_READWRITE) { $ret = $document->removeCategories(array($category)); if ($ret) - return $response->withJson(array('success'=>true, 'message'=>'Deleted category successfully.', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'Deleted category successfully.', 'data'=>''))->withStatus(200); else - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } /* }}} */ function removeDocumentCategories($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!ctype_digit($args['id'])) { - return $response->withJson(array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''))->withStatus(400); } $document = $dms->getDocument($args['id']); @@ -1680,38 +1707,38 @@ class RestapiController { /* {{{ */ if($document) { if ($document->getAccessMode($userobj, 'removeDocumentCategory') >= M_READWRITE) { if($document->setCategories(array())) - return $response->withJson(array('success'=>true, 'message'=>'Deleted categories successfully.', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'Deleted categories successfully.', 'data'=>''))->withStatus(200); else - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'', 'data'=>''))->withStatus(500); } else { - return $response->withJson(array('success'=>false, 'message'=>'No access', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access', 'data'=>''))->withStatus(403); } } else { if($document === null) $status=404; else $status=500; - return $response->withJson(array('success'=>false, 'message'=>'No such document', 'data'=>''), $status); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such document', 'data'=>''))->withStatus($status); } } /* }}} */ function setDocumentOwner($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); } if(!$userobj->isAdmin()) { - return $response->withJson(array('success'=>false, 'message'=>'No access on document', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access on document', 'data'=>''))->withStatus(403); } if(!ctype_digit($args['id']) || $args['id'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No document given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document given', 'data'=>''))->withStatus(400); return; } if(!ctype_digit($args['userid']) || $args['userid'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No user given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No user given', 'data'=>''))->withStatus(400); return; } $owner = $dms->getUser($args['userid']); @@ -1719,94 +1746,94 @@ class RestapiController { /* {{{ */ if($doc && $owner) { if($doc->getAccessMode($userobj, 'setDocumentOwner') > M_READ) { if ($doc->setOwner($owner)){ - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 201); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(201); } else { - return $response->withJson(array('success'=>false, 'message'=>'Could not set owner of document', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not set owner of document', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access on document', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access on document', 'data'=>''))->withStatus(403); } } else { if(!$doc) - return $response->withJson(array('success'=>false, 'message'=>'No such document', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such document', 'data'=>''))->withStatus(404); if(!$owner) - return $response->withJson(array('success'=>false, 'message'=>'No such user', 'data'=>''), 404); - return $response->withJson(array('success'=>false, 'message'=>'Could not find user or document', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such user', 'data'=>''))->withStatus(404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not find user or document', 'data'=>''))->withStatus(500); } } /* }}} */ function setDocumentAttribute($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; - $logger = $this->container->logger; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); + $logger = $this->container->get('logger'); if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); return; } if(!ctype_digit($args['id']) || $args['id'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No document given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document given', 'data'=>''))->withStatus(400); return; } if(!ctype_digit($args['attrdefid']) || $args['attrdefid'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No attribute definition id given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No attribute definition id given', 'data'=>''))->withStatus(400); return; } $attrdef = $dms->getAttributeDefinition($args['attrdefid']); $doc = $dms->getDocument($args['id']); if($doc && $attrdef) { if($attrdef->getObjType() !== SeedDMS_Core_AttributeDefinition::objtype_document) { - return $response->withJson(array('success'=>false, 'message'=>'Attribute definition "'.$attrdef->getName().'" not suitable for documents', 'data'=>''), 409); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Attribute definition "'.$attrdef->getName().'" not suitable for documents', 'data'=>''))->withStatus(409); } $params = $request->getParsedBody(); if(!isset($params['value'])) { - return $response->withJson(array('success'=>false, 'message'=>'Attribute value not set', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Attribute value not set', 'data'=>''))->withStatus(400); } $new = $doc->getAttributeValue($attrdef) ? true : false; if(!$attrdef->validate($params['value'], $doc, $new)) { - return $response->withJson(array('success'=>false, 'message'=>'Validation of attribute value failed: '.$attrdef->getValidationError(), 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Validation of attribute value failed: '.$attrdef->getValidationError(), 'data'=>''))->withStatus(400); } if($doc->getAccessMode($userobj, 'setDocumentAttribute') > M_READ) { if ($doc->setAttributeValue($attrdef, $params['value'])) { $logger->log("Setting attribute '".$attrdef->getName()."' (".$attrdef->getId().") to '".$params['value']."' successful", PEAR_LOG_INFO); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 201); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(201); } else { - return $response->withJson(array('success'=>false, 'message'=>'Could not set attribute value of document', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not set attribute value of document', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access on document', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access on document', 'data'=>''))->withStatus(403); } } else { if(!$doc) - return $response->withJson(array('success'=>false, 'message'=>'No such document', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such document', 'data'=>''))->withStatus(404); if(!$attrdef) - return $response->withJson(array('success'=>false, 'message'=>'No such attr definition', 'data'=>''), 404); - return $response->withJson(array('success'=>false, 'message'=>'Could not find user or document', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such attr definition', 'data'=>''))->withStatus(404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not find user or document', 'data'=>''))->withStatus(500); } } /* }}} */ function setDocumentContentAttribute($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; - $logger = $this->container->logger; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); + $logger = $this->container->get('logger'); if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); return; } if(!ctype_digit($args['id']) || $args['id'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No document given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No document given', 'data'=>''))->withStatus(400); return; } if(!ctype_digit($args['version']) || $args['version'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No version number given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No version number given', 'data'=>''))->withStatus(400); return; } if(!ctype_digit($args['attrdefid']) || $args['attrdefid'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No attribute definition id given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No attribute definition id given', 'data'=>''))->withStatus(400); return; } $attrdef = $dms->getAttributeDefinition($args['attrdefid']); @@ -1814,100 +1841,100 @@ class RestapiController { /* {{{ */ $version = $doc->getContentByVersion($args['version']); if($doc && $attrdef && $version) { if($attrdef->getObjType() !== SeedDMS_Core_AttributeDefinition::objtype_documentcontent) { - return $response->withJson(array('success'=>false, 'message'=>'Attribute definition "'.$attrdef->getName().'" not suitable for document versions', 'data'=>''), 409); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Attribute definition "'.$attrdef->getName().'" not suitable for document versions', 'data'=>''))->withStatus(409); } $params = $request->getParsedBody(); if(!isset($params['value'])) { - return $response->withJson(array('success'=>false, 'message'=>'Attribute value not set', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Attribute value not set', 'data'=>''))->withStatus(400); } $new = $version->getAttributeValue($attrdef) ? true : false; if(!$attrdef->validate($params['value'], $version, $new)) { - return $response->withJson(array('success'=>false, 'message'=>'Validation of attribute value failed: '.$attrdef->getValidationError(), 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Validation of attribute value failed: '.$attrdef->getValidationError(), 'data'=>''))->withStatus(400); } if($doc->getAccessMode($userobj, 'setDocumentContentAttribute') > M_READ) { if ($version->setAttributeValue($attrdef, $params['value'])) { $logger->log("Setting attribute '".$attrdef->getName()."' (".$attrdef->getId().") to '".$params['value']."' successful", PEAR_LOG_INFO); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 201); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(201); } else { - return $response->withJson(array('success'=>false, 'message'=>'Could not set attribute value of document content', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not set attribute value of document content', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access on document', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access on document', 'data'=>''))->withStatus(403); } } else { if(!$doc) - return $response->withJson(array('success'=>false, 'message'=>'No such document', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such document', 'data'=>''))->withStatus(404); if(!$version) - return $response->withJson(array('success'=>false, 'message'=>'No such version', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such version', 'data'=>''))->withStatus(404); if(!$attrdef) - return $response->withJson(array('success'=>false, 'message'=>'No such attr definition', 'data'=>''), 404); - return $response->withJson(array('success'=>false, 'message'=>'Could not find user or document', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such attr definition', 'data'=>''))->withStatus(404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not find user or document', 'data'=>''))->withStatus(500); } } /* }}} */ function setFolderAttribute($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; - $logger = $this->container->logger; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); + $logger = $this->container->get('logger'); if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); return; } if(!ctype_digit($args['id']) || $args['id'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No folder given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No folder given', 'data'=>''))->withStatus(400); return; } if(!ctype_digit($args['attrdefid']) || $args['attrdefid'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No attribute definition id given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No attribute definition id given', 'data'=>''))->withStatus(400); return; } $attrdef = $dms->getAttributeDefinition($args['attrdefid']); $obj = $dms->getFolder($args['id']); if($obj && $attrdef) { if($attrdef->getObjType() !== SeedDMS_Core_AttributeDefinition::objtype_folder) { - return $response->withJson(array('success'=>false, 'message'=>'Attribute definition "'.$attrdef->getName().'" not suitable for folders', 'data'=>''), 409); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Attribute definition "'.$attrdef->getName().'" not suitable for folders', 'data'=>''))->withStatus(409); } $params = $request->getParsedBody(); if(!isset($params['value'])) { - return $response->withJson(array('success'=>false, 'message'=>'Attribute value not set', 'data'=>''.$request->getHeader('Content-Type')[0]), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Attribute value not set', 'data'=>''.$request->getHeader('Content-Type')[0]))->withStatus(400); } if(strlen($params['value'])) { $new = $obj->getAttributeValue($attrdef) ? true : false; if(!$attrdef->validate($params['value'], $obj, $new)) { - return $response->withJson(array('success'=>false, 'message'=>'Validation of attribute value failed: '.$attrdef->getValidationError(), 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Validation of attribute value failed: '.$attrdef->getValidationError(), 'data'=>''))->withStatus(400); } } if($obj->getAccessMode($userobj, 'setFolderAttribute') > M_READ) { if ($obj->setAttributeValue($attrdef, $params['value'])) { $logger->log("Setting attribute '".$attrdef->getName()."' (".$attrdef->getId().") to '".$params['value']."' successful", PEAR_LOG_INFO); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 201); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(201); } else { - return $response->withJson(array('success'=>false, 'message'=>'Could not set attribute value of folder', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not set attribute value of folder', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access on folder', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access on folder', 'data'=>''))->withStatus(403); } } else { if(!$obj) - return $response->withJson(array('success'=>false, 'message'=>'No such folder', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such folder', 'data'=>''))->withStatus(404); if(!$attrdef) - return $response->withJson(array('success'=>false, 'message'=>'No such attr definition', 'data'=>''), 404); - return $response->withJson(array('success'=>false, 'message'=>'Could not find user or folder', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such attr definition', 'data'=>''))->withStatus(404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not find user or folder', 'data'=>''))->withStatus(500); } } /* }}} */ function getAccount($request, $response) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if($userobj) { - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$this->__getUserData($userobj)), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$this->__getUserData($userobj)))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); } } /* }}} */ @@ -1918,8 +1945,8 @@ class RestapiController { /* {{{ */ * return a list of words only. */ function doSearch($request, $response) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $params = $request->getQueryParams(); $querystr = $params['query']; @@ -1944,7 +1971,7 @@ class RestapiController { /* {{{ */ $resArr = $dms->search($sparams); // $resArr = $dms->search($querystr, $limit, $offset, 'AND', $searchin, null, null, array(), array('hour'=>1, 'minute'=>0, 'second'=>0, 'year'=>date('Y')-1, 'month'=>date('m'), 'day'=>date('d')), array(), array(), array(), array(), array(), $objects); if($resArr === false) { - return $response->withJson(array(), 200); + return $this->renderer->json($response, array())->withStatus(200); } $entries = array(); $count = 0; @@ -2001,7 +2028,7 @@ class RestapiController { /* {{{ */ if($recs) // array_unshift($recs, array('type'=>'', 'id'=>0, 'name'=>$querystr, 'comment'=>'')); array_unshift($recs, ' '.$querystr); - return $response->withJson($recs, 200); + return $this->renderer->json($response, $recs)->withStatus(200); break; default: $recs = array(); @@ -2017,7 +2044,7 @@ class RestapiController { /* {{{ */ $recs[] = $this->__getFolderData($folder); } } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs)); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$recs)); break; } } /* }}} */ @@ -2027,8 +2054,8 @@ class RestapiController { /* {{{ */ * */ function doSearchByAttr($request, $response) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $params = $request->getQueryParams(); $attrname = $params['name']; @@ -2070,26 +2097,28 @@ class RestapiController { /* {{{ */ $recs[] = $this->__getFolderData($folder); } } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$recs), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$recs))->withStatus(200); } /* }}} */ function checkIfAdmin($request, $response) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + if(!$this->container->has('userobj')) + echo "no user object"; - if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + if(!$this->container->has('userobj') || !($userobj = $this->container->get('userobj'))) { + return $this->renderer->json($response, ['success'=>false, 'message'=>'Not logged in', 'data'=>''])->withStatus(403); } + if(!$userobj->isAdmin()) { - return $response->withJson(array('success'=>false, 'message'=>'You must be logged in with an administrator account to access this resource', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'You must be logged in with an administrator account to access this resource', 'data'=>''))->withStatus(403); } return true; } /* }}} */ function getUsers($request, $response) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) return $check; @@ -2099,12 +2128,12 @@ class RestapiController { /* {{{ */ foreach($users as $u) $data[] = $this->__getUserData($u); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); } /* }}} */ function createUser($request, $response) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) @@ -2112,12 +2141,12 @@ class RestapiController { /* {{{ */ $params = $request->getParsedBody(); if(empty(trim($params['user']))) { - return $response->withJson(array('success'=>false, 'message'=>'Missing user login', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Missing user login', 'data'=>''))->withStatus(400); } $userName = $params['user']; $password = isset($params['pass']) ? $params['pass'] : ''; if(empty(trim($params['name']))) { - return $response->withJson(array('success'=>false, 'message'=>'Missing full user name', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Missing full user name', 'data'=>''))->withStatus(400); } $fullname = $params['name']; $email = isset($params['email']) ? $params['email'] : ''; @@ -2129,16 +2158,16 @@ class RestapiController { /* {{{ */ $newAccount = $dms->addUser($userName, seed_pass_hash($password), $fullname, $email, $language, $theme, $comment, $roleid); if ($newAccount === false) { - return $response->withJson(array('success'=>false, 'message'=>'Account could not be created, maybe it already exists', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Account could not be created, maybe it already exists', 'data'=>''))->withStatus(500); } $result = $this->__getUserData($newAccount); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$result), 201); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$result))->withStatus(201); } /* }}} */ function deleteUser($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) @@ -2146,12 +2175,12 @@ class RestapiController { /* {{{ */ if($user = $dms->getUser($args['id'])) { if($result = $user->remove($userobj, $userobj)) { - return $response->withJson(array('success'=>$result, 'message'=>'', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>$result, 'message'=>'', 'data'=>''))->withStatus(200); } else { - return $response->withJson(array('success'=>$result, 'message'=>'Could not delete user', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>$result, 'message'=>'Could not delete user', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No such user', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such user', 'data'=>''))->withStatus(404); } } /* }}} */ @@ -2161,8 +2190,8 @@ class RestapiController { /* {{{ */ * @param $id The user name or numerical identifier */ function changeUserPassword($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) @@ -2170,7 +2199,7 @@ class RestapiController { /* {{{ */ $params = $request->getParsedBody(); if ($params['password'] == null) { - return $response->withJson(array('success'=>false, 'message'=>'You must supply a new password', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'You must supply a new password', 'data'=>''))->withStatus(400); } $newPassword = $params['password']; @@ -2185,17 +2214,17 @@ class RestapiController { /* {{{ */ * User not found */ if (!$account) { - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'User not found.'), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'', 'data'=>'User not found.'))->withStatus(404); return; } $operation = $account->setPwd(seed_pass_hash($newPassword)); if (!$operation){ - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'Could not change password.'), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'', 'data'=>'Could not change password.'))->withStatus(404); } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(200); } /* }}} */ /** @@ -2204,8 +2233,8 @@ class RestapiController { /* {{{ */ * @param $id The user name or numerical identifier */ function changeUserQuota($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) @@ -2213,7 +2242,7 @@ class RestapiController { /* {{{ */ $params = $request->getParsedBody(); if ($params['quota'] == null) { - return $response->withJson(array('success'=>false, 'message'=>'You must supply a new quota', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'You must supply a new quota', 'data'=>''))->withStatus(400); } $newQuota = $params['quota']; @@ -2228,22 +2257,22 @@ class RestapiController { /* {{{ */ * User not found */ if (!$account) { - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'User not found.'), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'', 'data'=>'User not found.'))->withStatus(404); return; } $operation = $account->setQuota($newQuota); if (!$operation){ - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'Could not change quota.'), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'', 'data'=>'Could not change quota.'))->withStatus(404); } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(200); } /* }}} */ function changeUserHomefolder($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) @@ -2259,32 +2288,32 @@ class RestapiController { /* {{{ */ * User not found */ if (!$account) { - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'User not found.'), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'', 'data'=>'User not found.'))->withStatus(404); return; } if(!ctype_digit($args['folderid']) || $args['folderid'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No homefolder given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No homefolder given', 'data'=>''))->withStatus(400); return; } $newHomefolder = $dms->getFolder($args['folderid']); if (!$newHomefolder) { - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'Folder not found.'), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'', 'data'=>'Folder not found.'))->withStatus(404); return; } $operation = $account->setHomeFolder($newHomefolder->getId()); if (!$operation){ - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'Could not change homefolder.'), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'', 'data'=>'Could not change homefolder.'))->withStatus(404); } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(200); } /* }}} */ function getUserById($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) @@ -2296,22 +2325,22 @@ class RestapiController { /* {{{ */ } if($account) { $data = $this->__getUserData($account); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No such user', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such user', 'data'=>''))->withStatus(404); } } /* }}} */ function setDisabledUser($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) return $check; $params = $request->getParsedBody(); if (!isset($params['disable'])) { - return $response->withJson(array('success'=>false, 'message'=>'You must supply a disabled state', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'You must supply a disabled state', 'data'=>''))->withStatus(400); } $isDisabled = false; @@ -2329,15 +2358,15 @@ class RestapiController { /* {{{ */ if($account) { $account->setDisabled($isDisabled); $data = $this->__getUserData($account); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No such user', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such user', 'data'=>''))->withStatus(404); } } /* }}} */ function getGroups($request, $response) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) @@ -2348,19 +2377,19 @@ class RestapiController { /* {{{ */ foreach($groups as $u) $data[] = $this->__getGroupData($u); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); } /* }}} */ function createGroup($request, $response) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) return $check; $params = $request->getParsedBody(); if (empty($params['name'])) { - return $response->withJson(array('success'=>false, 'message'=>'Need a group name.', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Need a group name.', 'data'=>''))->withStatus(400); } $groupName = $params['name']; @@ -2368,16 +2397,16 @@ class RestapiController { /* {{{ */ $newGroup = $dms->addGroup($groupName, $comment); if ($newGroup === false) { - return $response->withJson(array('success'=>false, 'message'=>'Group could not be created, maybe it already exists', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Group could not be created, maybe it already exists', 'data'=>''))->withStatus(500); } // $result = array('id'=>(int)$newGroup->getID()); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$this->__getGroupData($newGroup)), 201); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$this->__getGroupData($newGroup)))->withStatus(201); } /* }}} */ function deleteGroup($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) @@ -2385,18 +2414,18 @@ class RestapiController { /* {{{ */ if($group = $dms->getGroup($args['id'])) { if($result = $group->remove($userobj)) { - return $response->withJson(array('success'=>$result, 'message'=>'', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>$result, 'message'=>'', 'data'=>''))->withStatus(200); } else { - return $response->withJson(array('success'=>$result, 'message'=>'Could not delete group', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>$result, 'message'=>'Could not delete group', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No such group', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such group', 'data'=>''))->withStatus(404); } } /* }}} */ function getGroup($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) @@ -2412,15 +2441,15 @@ class RestapiController { /* {{{ */ foreach ($group->getUsers() as $user) { $data['users'][] = array('id' => (int)$user->getID(), 'login' => $user->getLogin()); } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No such group', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such group', 'data'=>''))->withStatus(404); } } /* }}} */ function changeGroupMembership($request, $response, $args, $operationType) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) @@ -2434,7 +2463,7 @@ class RestapiController { /* {{{ */ $params = $request->getParsedBody(); if (empty($params['userid'])) { - return $response->withJson(array('success'=>false, 'message'=>'Missing userid', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Missing userid', 'data'=>''))->withStatus(400); } $userId = $params['userid']; if(ctype_digit($userId)) @@ -2465,7 +2494,7 @@ class RestapiController { /* {{{ */ { $message = 'Could not remove user from group.'; } - return $response->withJson(array('success'=>false, 'message'=>'Something went wrong. ' . $message, 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Something went wrong. ' . $message, 'data'=>''))->withStatus(500); } $data = $this->__getGroupData($group); @@ -2473,7 +2502,7 @@ class RestapiController { /* {{{ */ foreach ($group->getUsers() as $userObj) { $data['users'][] = array('id' => (int)$userObj->getID(), 'login' => $userObj->getLogin()); } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); } /* }}} */ function addUserToGroup($request, $response, $args) { /* {{{ */ @@ -2485,8 +2514,8 @@ class RestapiController { /* {{{ */ } /* }}} */ function setFolderInheritsAccess($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) @@ -2494,7 +2523,7 @@ class RestapiController { /* {{{ */ $params = $request->getParsedBody(); if (!isset($params['enable'])) { - return $response->withJson(array('success'=>false, 'message'=>'You must supply an "enable" value', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'You must supply an "enable" value', 'data'=>''))->withStatus(400); } $inherit = false; @@ -2517,29 +2546,29 @@ class RestapiController { /* {{{ */ // reread from db $folder = $dms->getFolder($folderId); $success = ($folder->inheritsAccess() == $inherit); - return $response->withJson(array('success'=>$success, 'message'=>'', 'data'=>$data), 200); + return $this->renderer->json($response, array('success'=>$success, 'message'=>'', 'data'=>$data))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No such folder', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such folder', 'data'=>''))->withStatus(404); } } /* }}} */ function setFolderOwner($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!$userobj) { - return $response->withJson(array('success'=>false, 'message'=>'Not logged in', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); } if(!$userobj->isAdmin()) { - return $response->withJson(array('success'=>false, 'message'=>'No access on folder', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access on folder', 'data'=>''))->withStatus(403); } if(!ctype_digit($args['id']) || $args['id'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No folder given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No folder given', 'data'=>''))->withStatus(400); return; } if(!ctype_digit($args['userid']) || $args['userid'] == 0) { - return $response->withJson(array('success'=>false, 'message'=>'No user given', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No user given', 'data'=>''))->withStatus(400); return; } $owner = $dms->getUser($args['userid']); @@ -2547,19 +2576,19 @@ class RestapiController { /* {{{ */ if($folder && $owner) { if($folder->getAccessMode($userobj, 'setDocumentOwner') > M_READ) { if ($folder->setOwner($owner)){ - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 201); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(201); } else { - return $response->withJson(array('success'=>false, 'message'=>'Could not set owner of folder', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not set owner of folder', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No access on folder', 'data'=>''), 403); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No access on folder', 'data'=>''))->withStatus(403); } } else { if(!$doc) - return $response->withJson(array('success'=>false, 'message'=>'No such folder', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such folder', 'data'=>''))->withStatus(404); if(!$owner) - return $response->withJson(array('success'=>false, 'message'=>'No such user', 'data'=>''), 404); - return $response->withJson(array('success'=>false, 'message'=>'Could not find user or folder', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such user', 'data'=>''))->withStatus(404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not find user or folder', 'data'=>''))->withStatus(500); } } /* }}} */ @@ -2580,8 +2609,8 @@ class RestapiController { /* {{{ */ } /* }}} */ function changeFolderAccess($request, $response, $args, $operationType, $userOrGroup) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) @@ -2593,7 +2622,7 @@ class RestapiController { /* {{{ */ $folder = $dms->getfolderByName($args['id']); } if (!$folder) { - return $response->withJson(array('success'=>false, 'message'=>'No such folder', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such folder', 'data'=>''))->withStatus(404); } $params = $request->getParsedBody(); @@ -2602,12 +2631,12 @@ class RestapiController { /* {{{ */ { if ($params['id'] == null) { - return $response->withJson(array('success'=>false, 'message'=>'Please PUT the user or group Id', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Please PUT the user or group Id', 'data'=>''))->withStatus(400); } if ($params['mode'] == null) { - return $response->withJson(array('success'=>false, 'message'=>'Please PUT the access mode', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Please PUT the access mode', 'data'=>''))->withStatus(400); } $modeInput = $params['mode']; @@ -2677,47 +2706,47 @@ class RestapiController { /* {{{ */ { $message = 'Could not remove user/group access from this folder.'; } - return $response->withJson(array('success'=>false, 'message'=>'Something went wrong. ' . $message, 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Something went wrong. ' . $message, 'data'=>''))->withStatus(500); } $data = array(); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); } /* }}} */ function getCategories($request, $response) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(false === ($categories = $dms->getDocumentCategories())) { - return $response->withJson(array('success'=>false, 'message'=>'Could not get categories', 'data'=>null), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not get categories', 'data'=>null))->withStatus(500); } $data = []; foreach($categories as $category) $data[] = $this->__getCategoryData($category); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); } /* }}} */ function getCategory($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); if(!ctype_digit($args['id'])) { - return $response->withJson(array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''))->withStatus(400); } $category = $dms->getDocumentCategory($args['id']); if($category) { - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$this->__getCategoryData($category)), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$this->__getCategoryData($category)))->withStatus(200); } else { - return $response->withJson(array('success'=>false, 'message'=>'No such category', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such category', 'data'=>''))->withStatus(404); } } /* }}} */ function createCategory($request, $response) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; - $logger = $this->container->logger; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); + $logger = $this->container->get('logger'); $check = $this->checkIfAdmin($request, $response); if($check !== true) @@ -2725,25 +2754,25 @@ class RestapiController { /* {{{ */ $params = $request->getParsedBody(); if (empty($params['name'])) { - return $response->withJson(array('success'=>false, 'message'=>'Need a category.', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Need a category.', 'data'=>''))->withStatus(400); } $catobj = $dms->getDocumentCategoryByName($params['name']); if($catobj) { - return $response->withJson(array('success'=>false, 'message'=>'Category already exists', 'data'=>''), 409); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Category already exists', 'data'=>''))->withStatus(409); } else { if($data = $dms->addDocumentCategory($params['name'])) { $logger->log("Creating category '".$data->getName()."' (".$data->getId().") successful", PEAR_LOG_INFO); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$this->__getCategoryData($data)), 201); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$this->__getCategoryData($data)))->withStatus(201); } else { - return $response->withJson(array('success'=>false, 'message'=>'Could not add category', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not add category', 'data'=>''))->withStatus(500); } } } /* }}} */ function deleteCategory($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) @@ -2751,12 +2780,12 @@ class RestapiController { /* {{{ */ if($category = $dms->getDocumentCategory($args['id'])) { if($result = $category->remove()) { - return $response->withJson(array('success'=>$result, 'message'=>'', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>$result, 'message'=>'', 'data'=>''))->withStatus(200); } else { - return $response->withJson(array('success'=>$result, 'message'=>'Could not delete category', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>$result, 'message'=>'Could not delete category', 'data'=>''))->withStatus(500); } } else { - return $response->withJson(array('success'=>false, 'message'=>'No such category', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such category', 'data'=>''))->withStatus(404); } } /* }}} */ @@ -2766,21 +2795,21 @@ class RestapiController { /* {{{ */ * @param $id The user name or numerical identifier */ function changeCategoryName($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) return $check; if(!ctype_digit($args['id'])) { - return $response->withJson(array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''))->withStatus(400); } $params = $request->getParsedBody(); if (empty($params['name'])) { - return $response->withJson(array('success'=>false, 'message'=>'You must supply a new name', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'You must supply a new name', 'data'=>''))->withStatus(400); } $newname = $params['name']; @@ -2791,26 +2820,26 @@ class RestapiController { /* {{{ */ * Category not found */ if (!$category) { - return $response->withJson(array('success'=>false, 'message'=>'No such category', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such category', 'data'=>''))->withStatus(404); } if (!$category->setName($newname)) { - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'Could not change name.'), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'', 'data'=>'Could not change name.'))->withStatus(400); } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$this->__getCategoryData($category)), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$this->__getCategoryData($category)))->withStatus(200); } /* }}} */ function getAttributeDefinitions($request, $response) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $attrdefs = $dms->getAllAttributeDefinitions(); $data = []; foreach($attrdefs as $attrdef) $data[] = $this->__getAttributeDefinitionData($attrdef); - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); } /* }}} */ /** @@ -2819,20 +2848,20 @@ class RestapiController { /* {{{ */ * @param $id The user name or numerical identifier */ function changeAttributeDefinitionName($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) return $check; if(!ctype_digit($args['id'])) { - return $response->withJson(array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''))->withStatus(400); } $params = $request->getParsedBody(); - if ($params['name'] == null) { - return $response->withJson(array('success'=>false, 'message'=>'You must supply a new name', 'data'=>''), 400); + if (!isset($params['name']) || $params['name'] == null) { + return $this->renderer->json($response, array('success'=>false, 'message'=>'You must supply a new name', 'data'=>''))->withStatus(400); } $newname = $params['name']; @@ -2843,20 +2872,20 @@ class RestapiController { /* {{{ */ * Attribute definition not found */ if (!$attrdef) { - return $response->withJson(array('success'=>false, 'message'=>'No such attribute defintion', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such attribute defintion', 'data'=>''))->withStatus(404); } if (!$attrdef->setName($newname)) { - return $response->withJson(array('success'=>false, 'message'=>'', 'data'=>'Could not change name.'), 400); + return $this->renderer->json($response, array('success'=>false, 'message'=>'', 'data'=>'Could not change name.'))->withStatus(400); return; } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$this->__getAttributeDefinitionData($attrdef)), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$this->__getAttributeDefinitionData($attrdef)))->withStatus(200); } /* }}} */ function clearFolderAccessList($request, $response, $args) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); + $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); if($check !== true) @@ -2868,17 +2897,16 @@ class RestapiController { /* {{{ */ $folder = $dms->getFolderByName($args['id']); } if (!$folder) { - return $response->withJson(array('success'=>false, 'message'=>'No such folder', 'data'=>''), 404); + return $this->renderer->json($response, array('success'=>false, 'message'=>'No such folder', 'data'=>''))->withStatus(404); } if (!$folder->clearAccessList()) { - return $response->withJson(array('success'=>false, 'message'=>'Something went wrong. Could not clear access list for this folder.', 'data'=>''), 500); + return $this->renderer->json($response, array('success'=>false, 'message'=>'Something went wrong. Could not clear access list for this folder.', 'data'=>''))->withStatus(500); } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>''), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>''))->withStatus(200); } /* }}} */ function getStatsTotal($request, $response) { /* {{{ */ - $dms = $this->container->dms; - $userobj = $this->container->userobj; + $dms = $this->container->get('dms'); $check = $this->checkIfAdmin($request, $response); if($check !== true) return $check; @@ -2889,33 +2917,34 @@ class RestapiController { /* {{{ */ $data[$type] = $total; } - return $response->withJson(array('success'=>true, 'message'=>'', 'data'=>$data), 200); + return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); } /* }}} */ } /* }}} */ -class TestController { /* {{{ */ +final class SeedDMS_TestController { /* {{{ */ protected $container; + protected $renderer; // constructor receives container instance - public function __construct(ContainerInterface $container) { + public function __construct(ContainerInterface $container, JsonRenderer $renderer) { $this->container = $container; + $this->renderer = $renderer; } public function echoData($request, $response, $args) { /* {{{ */ - return $response->withJson(array('success'=>true, 'message'=>'This is the result of the echo call.', 'data'=>$args['data']), 200); + return $this->renderer->json($response, ['success'=>true, 'message'=>'This is the result of the echo call.', 'data'=>$args['data']]); } /* }}} */ public function version($request, $response, $args) { /* {{{ */ - $logger = $this->container->logger; + $logger = $this->container->get('logger'); $v = new SeedDMS_Version(); - return $response->withJson(array('success'=>true, 'message'=>'This is '.$v->banner(), 'data'=>['major'=>$v->majorVersion(), 'minor'=>$v->minorVersion(), 'subminor'=>$v->subminorVersion()]), 200); + return $this->renderer->json($response, ['success'=>true, 'message'=>'This is '.$v->banner(), 'data'=>['major'=>$v->majorVersion(), 'minor'=>$v->minorVersion(), 'subminor'=>$v->subminorVersion()]]); } /* }}} */ } /* }}} */ -/* Middleware for authentication */ -class RestapiAuth { /* {{{ */ +class RestapiCorsMiddleware implements MiddlewareInterface { /* {{{ */ private $container; @@ -2923,67 +2952,146 @@ class RestapiAuth { /* {{{ */ $this->container = $container; } + /** + * Example middleware invokable class + * + * @return \Psr\Http\Message\ResponseInterface + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + $response = $handler->handle($request); + $response = $response + ->withHeader('Access-Control-Allow-Origin', $request->getHeader('Origin') ? $request->getHeader('Origin') : '*') + ->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization') + ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS'); + return $response; + } +} /* }}} */ + +/* Middleware for authentication */ +class RestapiAuthMiddleware implements MiddlewareInterface { /* {{{ */ + + private $container; + + private $responsefactory; + + public function __construct($container, $responsefactory) { + $this->container = $container; + $this->responsefactory = $responsefactory; + } + /** * Example middleware invokable class * * @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request - * @param \Psr\Http\Message\ResponseInterface $response PSR7 response - * @param callable $next Next middleware + * @param \Psr\Http\Server\RequestHandlerInterface $handler * * @return \Psr\Http\Message\ResponseInterface */ - public function __invoke($request, $response, $next) + public function process( + ServerRequestInterface $request, + RequestHandlerInterface $handler): ResponseInterface { // $this->container has the DI - $dms = $this->container->dms; - $settings = $this->container->config; - $logger = $this->container->logger; + $dms = $this->container->get('dms'); + $settings = $this->container->get('config'); + $logger = $this->container->get('logger'); + + $logger->log("Invoke AuthMiddleware for method ".$request->getMethod()." on '".$request->getUri()->getPath()."'".(isset($environment['HTTP_ORIGIN']) ? " with origin ".$environment['HTTP_ORIGIN'] : ''), PEAR_LOG_INFO); + $userobj = null; + /* Do not rely on $userobj being an object. It can be true, if a + * former authentication middleware has allowed access without + * authentification as a user. The paperless extension does this, + * for some endpoints, e.g. to get some general api information. + */ if($this->container->has('userobj')) - $userobj = $this->container->userobj; + $userobj = $this->container->get('userobj'); if($userobj) { - $response = $next($request, $response); + $logger->log("Already authenticated. Pass on to next middleware", PEAR_LOG_INFO); + $response = $handler->handle($request); return $response; } - $logger->log("Invoke middleware for method ".$request->getMethod()." on '".$request->getUri()->getPath()."'", PEAR_LOG_INFO); - $logger->log("Access with method ".$request->getMethod()." on '".$request->getUri()->getPath()."'".(isset($this->container->environment['HTTP_ORIGIN']) ? " with origin ".$this->container->environment['HTTP_ORIGIN'] : ''), PEAR_LOG_INFO); - if($settings->_apiOrigin && isset($this->container->environment['HTTP_ORIGIN'])) { + //$environment = $this->container->environment; // Slim 3 + $environment = $request->getServerParams(); + + if($settings->_apiOrigin && isset($environment['HTTP_ORIGIN'])) { $logger->log("Checking origin", PEAR_LOG_DEBUG); $origins = explode(',', $settings->_apiOrigin); - if(!in_array($this->container->environment['HTTP_ORIGIN'], $origins)) { - return $response->withStatus(403); + if(!in_array($environment['HTTP_ORIGIN'], $origins)) { + $response = $this->responsefactory->createResponse(); + $response = $response->withHeader('Content-Type', 'application/json'); + $response = $response->withStatus(403); + $response->getBody()->write( + (string)json_encode( + ['success'=>false, 'message'=>'Invalid origin', 'data'=>''], + JSON_UNESCAPED_SLASHES | JSON_PARTIAL_OUTPUT_ON_ERROR + ) + ); + return $response; } } /* The preflight options request doesn't have authorization in the header. So * don't even try to authorize. */ + $path = $environment['PATH_INFO'] ?? ''; if($request->getMethod() == 'OPTIONS') { $logger->log("Received preflight options request", PEAR_LOG_DEBUG); - } elseif(!in_array($request->getUri()->getPath(), array('login')) && substr($request->getUri()->getPath(), 0, 5) != 'echo/' && $request->getUri()->getPath() != 'version') { + } elseif(!in_array($path, array('/login')) && substr($path, 0, 6) != '/echo/' && $path != '/version') { $userobj = null; - if(!empty($this->container->environment['HTTP_AUTHORIZATION']) && !empty($settings->_apiKey) && !empty($settings->_apiUserId)) { - $logger->log("Authorization key: ".$this->container->environment['HTTP_AUTHORIZATION'], PEAR_LOG_DEBUG); - if($settings->_apiKey == $this->container->environment['HTTP_AUTHORIZATION']) { + $logger->log(var_export($environment, true), PEAR_LOG_DEBUG); + if(!empty($environment['HTTP_AUTHORIZATION']) && !empty($settings->_apiKey) && !empty($settings->_apiUserId)) { + $logger->log("Authorization key: ".$environment['HTTP_AUTHORIZATION'], PEAR_LOG_DEBUG); + if($settings->_apiKey == $environment['HTTP_AUTHORIZATION']) { if(!($userobj = $dms->getUser($settings->_apiUserId))) { - return $response->withJson(array('success'=>false, 'message'=>'Invalid user associated with api key', 'data'=>''), 403); + $response = $this->responsefactory->createResponse(); + $response = $response->withHeader('Content-Type', 'application/json'); + $response = $response->withStatus(403); + $response->getBody()->write( + (string)json_encode( + ['success'=>false, 'message'=>'Invalid user associated with api key', 'data'=>''], + JSON_UNESCAPED_SLASHES | JSON_PARTIAL_OUTPUT_ON_ERROR + ) + ); + return $response; } } else { - return $response->withJson(array('success'=>false, 'message'=>'Wrong api key', 'data'=>''), 403); + $response = $this->responsefactory->createResponse(); + $response = $response->withHeader('Content-Type', 'application/json'); + $response = $response->withStatus(403); + $response->getBody()->write( + (string)json_encode( + ['success'=>false, 'message'=>'Wrong api key', 'data'=>''], + JSON_UNESCAPED_SLASHES | JSON_PARTIAL_OUTPUT_ON_ERROR + ) + ); + return $response; } $logger->log("Login with apikey as '".$userobj->getLogin()."' successful", PEAR_LOG_INFO); } else { + $logger->log("Checking for valid session", PEAR_LOG_INFO); require_once("../inc/inc.ClassSession.php"); $session = new SeedDMS_Session($dms->getDb()); if (isset($_COOKIE["mydms_session"])) { + $logger->log("Found cookie for session", PEAR_LOG_INFO); $dms_session = $_COOKIE["mydms_session"]; $logger->log("Session key: ".$dms_session, PEAR_LOG_DEBUG); if(!$resArr = $session->load($dms_session)) { /* Delete Cookie */ setcookie("mydms_session", $dms_session, time()-3600, $settings->_httpRoot); $logger->log("Session for id '".$dms_session."' has gone", PEAR_LOG_ERR); - return $response->withJson(array('success'=>false, 'message'=>'Session has gone', 'data'=>''), 403); + $response = $this->responsefactory->createResponse(); + $response = $response->withHeader('Content-Type', 'application/json'); + $response = $response->withStatus(403); + $response->getBody()->write( + (string)json_encode( + ['success'=>false, 'message'=>'Session has gone', 'data'=>''], + JSON_UNESCAPED_SLASHES | JSON_PARTIAL_OUTPUT_ON_ERROR + ) + ); + return $response; } /* Load user data */ @@ -2993,41 +3101,85 @@ class RestapiAuth { /* {{{ */ setcookie("mydms_session", $dms_session, time()-3600, $settings->_httpRoot); if($settings->_enableGuestLogin) { if(!($userobj = $dms->getUser($settings->_guestID))) - return $response->withJson(array('success'=>false, 'message'=>'Could not get guest login', 'data'=>''), 403); + $response = $this->responsefactory->createResponse(); + $response = $response->withHeader('Content-Type', 'application/json'); + $response = $response->withStatus(403); + $response->getBody()->write( + (string)json_encode( + ['success'=>false, 'message'=>'Could not get guest login', 'data'=>''], + JSON_UNESCAPED_SLASHES | JSON_PARTIAL_OUTPUT_ON_ERROR + ) + ); + return $response; } else - return $response->withJson(array('success'=>false, 'message'=>'Login as guest disabled', 'data'=>''), 403); + $response = $this->responsefactory->createResponse(); + $response = $response->withHeader('Content-Type', 'application/json'); + $response = $response->withStatus(403); + $response->getBody()->write( + (string)json_encode( + ['success'=>false, 'message'=>'Login as guest disable', 'data'=>''], + JSON_UNESCAPED_SLASHES | JSON_PARTIAL_OUTPUT_ON_ERROR + ) + ); + return $response; } + $logger->log("Authorization as user '".$userobj->getLogin()."'", PEAR_LOG_DEBUG); if($userobj->isAdmin()) { if($resArr["su"]) { - if(!($userobj = $dms->getUser($resArr["su"]))) - return $response->withJson(array('success'=>false, 'message'=>'Cannot substitute user', 'data'=>''), 403); + if(!($userobj = $dms->getUser($resArr["su"]))) { + $response = $this->responsefactory->createResponse(); + $response = $response->withHeader('Content-Type', 'application/json'); + $response = $response->withStatus(403); + $response->getBody()->write( + (string)json_encode( + ['success'=>false, 'message'=>'Cannot substitute user', 'data'=>''], + JSON_UNESCAPED_SLASHES | JSON_PARTIAL_OUTPUT_ON_ERROR + ) + ); + return $response; + } } } -// $logger->log("Login with user name '".$userobj->getLogin()."' successful", PEAR_LOG_INFO); + $logger->log("Login with user name '".$userobj->getLogin()."' successful", PEAR_LOG_INFO); $dms->setUser($userobj); } else { - return $response->withJson(array('success'=>false, 'message'=>'Missing session cookie', 'data'=>''), 403); + $response = $this->responsefactory->createResponse(); + $response = $response->withHeader('Content-Type', 'application/json'); + $response = $response->withStatus(403); + $response->getBody()->write( + (string)json_encode( + ['success'=>false, 'message'=>'Missing session cookie', 'data'=>''], + JSON_UNESCAPED_SLASHES | JSON_PARTIAL_OUTPUT_ON_ERROR + ) + ); + return $response; } } - $this->container['userobj'] = $userobj; + $this->container->set('userobj', $userobj); } - $response = $next($request, $response); + $response = $handler->handle($request); + $logger->log("End AuthMiddleware for method ".$request->getMethod()." on '".$request->getUri()->getPath()."'", PEAR_LOG_INFO); return $response; } } /* }}} */ -$app = new \Slim\App(); +$containerBuilder = new ContainerBuilder(); +$c = $containerBuilder->build(); +AppFactory::setContainer($c); +$app = AppFactory::create(); $container = $app->getContainer(); -$container['dms'] = $dms; -$container['config'] = $settings; -$container['conversionmgr'] = $conversionmgr; -$container['logger'] = $logger; -$container['fulltextservice'] = $fulltextservice; -$container['notifier'] = $notifier; -$container['authenticator'] = $authenticator; +$container->set('dms', $dms); +$container->set('config', $settings); +$container->set('conversionmgr', $conversionmgr); +$container->set('logger', $logger); +$container->set('fulltextservice', $fulltextservice); +$container->set('notifier', $notifier); +$container->set('authenticator', $authenticator); -$app->add(new RestapiAuth($container)); +$app->setBasePath($settings->_httpRoot."restapi/index.php"); + +$app->add(new RestapiAuthMiddleware($container, $app->getResponseFactory())); if(isset($GLOBALS['SEEDDMS_HOOKS']['initRestAPI'])) { foreach($GLOBALS['SEEDDMS_HOOKS']['initRestAPI'] as $hookObj) { @@ -3037,94 +3189,92 @@ if(isset($GLOBALS['SEEDDMS_HOOKS']['initRestAPI'])) { } } +$app->addErrorMiddleware(true, true, true); + +$app->add(new RestapiCorsMiddleware($container)); + // Make CORS preflighted request possible $app->options('/{routes:.+}', function ($request, $response, $args) { return $response; }); -$app->add(function ($req, $res, $next) { - $response = $next($req, $res); - return $response - ->withHeader('Access-Control-Allow-Origin', $req->getHeader('Origin') ? $req->getHeader('Origin') : '*') - ->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization') - ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS'); -}); + // use post for create operation // use get for retrieval operation // use put for update operation // use delete for delete operation -$app->post('/login', \RestapiController::class.':doLogin'); -$app->get('/logout', \RestapiController::class.':doLogout'); -$app->get('/account', \RestapiController::class.':getAccount'); -$app->get('/search', \RestapiController::class.':doSearch'); -$app->get('/searchbyattr', \RestapiController::class.':doSearchByAttr'); -$app->get('/folder', \RestapiController::class.':getFolder'); -$app->get('/folder/{id}', \RestapiController::class.':getFolder'); -$app->post('/folder/{id}/move/{folderid}', \RestapiController::class.':moveFolder'); -$app->delete('/folder/{id}', \RestapiController::class.':deleteFolder'); -$app->get('/folder/{id}/children', \RestapiController::class.':getFolderChildren'); -$app->get('/folder/{id}/parent', \RestapiController::class.':getFolderParent'); -$app->get('/folder/{id}/path', \RestapiController::class.':getFolderPath'); -$app->get('/folder/{id}/attributes', \RestapiController::class.':getFolderAttributes'); -$app->put('/folder/{id}/attribute/{attrdefid}', \RestapiController::class.':setFolderAttribute'); -$app->post('/folder/{id}/folder', \RestapiController::class.':createFolder'); -$app->put('/folder/{id}/document', \RestapiController::class.':uploadDocumentPut'); -$app->post('/folder/{id}/document', \RestapiController::class.':uploadDocument'); -$app->get('/document/{id}', \RestapiController::class.':getDocument'); -$app->post('/document/{id}/attachment', \RestapiController::class.':uploadDocumentFile'); -$app->post('/document/{id}/update', \RestapiController::class.':updateDocument'); -$app->delete('/document/{id}', \RestapiController::class.':deleteDocument'); -$app->post('/document/{id}/move/{folderid}', \RestapiController::class.':moveDocument'); -$app->get('/document/{id}/content', \RestapiController::class.':getDocumentContent'); -$app->get('/document/{id}/versions', \RestapiController::class.':getDocumentVersions'); -$app->get('/document/{id}/version/{version}', \RestapiController::class.':getDocumentVersion'); -$app->put('/document/{id}/version/{version}', \RestapiController::class.':updateDocumentVersion'); -$app->get('/document/{id}/version/{version}/attributes', \RestapiController::class.':getDocumentContentAttributes'); -$app->put('/document/{id}/version/{version}/attribute/{attrdefid}', \RestapiController::class.':setDocumentContentAttribute'); -$app->get('/document/{id}/files', \RestapiController::class.':getDocumentFiles'); -$app->get('/document/{id}/file/{fileid}', \RestapiController::class.':getDocumentFile'); -$app->get('/document/{id}/links', \RestapiController::class.':getDocumentLinks'); -$app->post('/document/{id}/link/{documentid}', \RestapiController::class.':addDocumentLink'); -$app->get('/document/{id}/attributes', \RestapiController::class.':getDocumentAttributes'); -$app->put('/document/{id}/attribute/{attrdefid}', \RestapiController::class.':setDocumentAttribute'); -$app->get('/document/{id}/preview/{version}/{width}', \RestapiController::class.':getDocumentPreview'); -$app->delete('/document/{id}/categories', \RestapiController::class.':removeDocumentCategories'); -$app->delete('/document/{id}/category/{catid}', \RestapiController::class.':removeDocumentCategory'); -$app->post('/document/{id}/category/{catid}', \RestapiController::class.':addDocumentCategory'); -$app->put('/document/{id}/owner/{userid}', \RestapiController::class.':setDocumentOwner'); -$app->put('/account/fullname', \RestapiController::class.':setFullName'); -$app->put('/account/email', \RestapiController::class.':setEmail'); -$app->get('/account/documents/locked', \RestapiController::class.':getLockedDocuments'); -$app->get('/users', \RestapiController::class.':getUsers'); -$app->delete('/users/{id}', \RestapiController::class.':deleteUser'); -$app->post('/users', \RestapiController::class.':createUser'); -$app->get('/users/{id}', \RestapiController::class.':getUserById'); -$app->put('/users/{id}/disable', \RestapiController::class.':setDisabledUser'); -$app->put('/users/{id}/password', \RestapiController::class.':changeUserPassword'); -$app->put('/users/{id}/quota', \RestapiController::class.':changeUserQuota'); -$app->put('/users/{id}/homefolder/{folderid}', \RestapiController::class.':changeUserHomefolder'); -$app->post('/groups', \RestapiController::class.':createGroup'); -$app->get('/groups', \RestapiController::class.':getGroups'); -$app->delete('/groups/{id}', \RestapiController::class.':deleteGroup'); -$app->get('/groups/{id}', \RestapiController::class.':getGroup'); -$app->put('/groups/{id}/addUser', \RestapiController::class.':addUserToGroup'); -$app->put('/groups/{id}/removeUser', \RestapiController::class.':removeUserFromGroup'); -$app->put('/folder/{id}/setInherit', \RestapiController::class.':setFolderInheritsAccess'); -$app->put('/folder/{id}/owner/{userid}', \RestapiController::class.':setFolderOwner'); -$app->put('/folder/{id}/access/group/add', \RestapiController::class.':addGroupAccessToFolder'); // -$app->put('/folder/{id}/access/user/add', \RestapiController::class.':addUserAccessToFolder'); // -$app->put('/folder/{id}/access/group/remove', \RestapiController::class.':removeGroupAccessFromFolder'); -$app->put('/folder/{id}/access/user/remove', \RestapiController::class.':removeUserAccessFromFolder'); -$app->put('/folder/{id}/access/clear', \RestapiController::class.':clearFolderAccessList'); -$app->get('/categories', \RestapiController::class.':getCategories'); -$app->get('/categories/{id}', \RestapiController::class.':getCategory'); -$app->delete('/categories/{id}', \RestapiController::class.':deleteCategory'); -$app->post('/categories', \RestapiController::class.':createCategory'); -$app->put('/categories/{id}/name', \RestapiController::class.':changeCategoryName'); -$app->get('/attributedefinitions', \RestapiController::class.':getAttributeDefinitions'); -$app->put('/attributedefinitions/{id}/name', \RestapiController::class.':changeAttributeDefinitionName'); -$app->get('/echo/{data}', \TestController::class.':echoData'); -$app->get('/version', \TestController::class.':version'); -$app->get('/statstotal', \RestapiController::class.':getStatsTotal'); +$app->post('/login', \SeedDMS_RestapiController::class.':doLogin'); +$app->get('/logout', \SeedDMS_RestapiController::class.':doLogout'); +$app->get('/account', \SeedDMS_RestapiController::class.':getAccount'); +$app->get('/search', \SeedDMS_RestapiController::class.':doSearch'); +$app->get('/searchbyattr', \SeedDMS_RestapiController::class.':doSearchByAttr'); +$app->get('/folder', \SeedDMS_RestapiController::class.':getFolder'); +$app->get('/folder/{id}', \SeedDMS_RestapiController::class.':getFolder'); +$app->post('/folder/{id}/move/{folderid}', \SeedDMS_RestapiController::class.':moveFolder'); +$app->delete('/folder/{id}', \SeedDMS_RestapiController::class.':deleteFolder'); +$app->get('/folder/{id}/children', \SeedDMS_RestapiController::class.':getFolderChildren'); +$app->get('/folder/{id}/parent', \SeedDMS_RestapiController::class.':getFolderParent'); +$app->get('/folder/{id}/path', \SeedDMS_RestapiController::class.':getFolderPath'); +$app->get('/folder/{id}/attributes', \SeedDMS_RestapiController::class.':getFolderAttributes'); +$app->put('/folder/{id}/attribute/{attrdefid}', \SeedDMS_RestapiController::class.':setFolderAttribute'); +$app->post('/folder/{id}/folder', \SeedDMS_RestapiController::class.':createFolder'); +$app->put('/folder/{id}/document', \SeedDMS_RestapiController::class.':uploadDocumentPut'); +$app->post('/folder/{id}/document', \SeedDMS_RestapiController::class.':uploadDocument'); +$app->get('/document/{id}', \SeedDMS_RestapiController::class.':getDocument'); +$app->post('/document/{id}/attachment', \SeedDMS_RestapiController::class.':uploadDocumentFile'); +$app->post('/document/{id}/update', \SeedDMS_RestapiController::class.':updateDocument'); +$app->delete('/document/{id}', \SeedDMS_RestapiController::class.':deleteDocument'); +$app->post('/document/{id}/move/{folderid}', \SeedDMS_RestapiController::class.':moveDocument'); +$app->get('/document/{id}/content', \SeedDMS_RestapiController::class.':getDocumentContent'); +$app->get('/document/{id}/versions', \SeedDMS_RestapiController::class.':getDocumentVersions'); +$app->get('/document/{id}/version/{version}', \SeedDMS_RestapiController::class.':getDocumentVersion'); +$app->put('/document/{id}/version/{version}', \SeedDMS_RestapiController::class.':updateDocumentVersion'); +$app->get('/document/{id}/version/{version}/attributes', \SeedDMS_RestapiController::class.':getDocumentContentAttributes'); +$app->put('/document/{id}/version/{version}/attribute/{attrdefid}', \SeedDMS_RestapiController::class.':setDocumentContentAttribute'); +$app->get('/document/{id}/files', \SeedDMS_RestapiController::class.':getDocumentFiles'); +$app->get('/document/{id}/file/{fileid}', \SeedDMS_RestapiController::class.':getDocumentFile'); +$app->get('/document/{id}/links', \SeedDMS_RestapiController::class.':getDocumentLinks'); +$app->post('/document/{id}/link/{documentid}', \SeedDMS_RestapiController::class.':addDocumentLink'); +$app->get('/document/{id}/attributes', \SeedDMS_RestapiController::class.':getDocumentAttributes'); +$app->put('/document/{id}/attribute/{attrdefid}', \SeedDMS_RestapiController::class.':setDocumentAttribute'); +$app->get('/document/{id}/preview/{version}/{width}', \SeedDMS_RestapiController::class.':getDocumentPreview'); +$app->delete('/document/{id}/categories', \SeedDMS_RestapiController::class.':removeDocumentCategories'); +$app->delete('/document/{id}/category/{catid}', \SeedDMS_RestapiController::class.':removeDocumentCategory'); +$app->post('/document/{id}/category/{catid}', \SeedDMS_RestapiController::class.':addDocumentCategory'); +$app->put('/document/{id}/owner/{userid}', \SeedDMS_RestapiController::class.':setDocumentOwner'); +$app->put('/account/fullname', \SeedDMS_RestapiController::class.':setFullName'); +$app->put('/account/email', \SeedDMS_RestapiController::class.':setEmail'); +$app->get('/account/documents/locked', \SeedDMS_RestapiController::class.':getLockedDocuments'); +$app->get('/users', \SeedDMS_RestapiController::class.':getUsers'); +$app->delete('/users/{id}', \SeedDMS_RestapiController::class.':deleteUser'); +$app->post('/users', \SeedDMS_RestapiController::class.':createUser'); +$app->get('/users/{id}', \SeedDMS_RestapiController::class.':getUserById'); +$app->put('/users/{id}/disable', \SeedDMS_RestapiController::class.':setDisabledUser'); +$app->put('/users/{id}/password', \SeedDMS_RestapiController::class.':changeUserPassword'); +$app->put('/users/{id}/quota', \SeedDMS_RestapiController::class.':changeUserQuota'); +$app->put('/users/{id}/homefolder/{folderid}', \SeedDMS_RestapiController::class.':changeUserHomefolder'); +$app->post('/groups', \SeedDMS_RestapiController::class.':createGroup'); +$app->get('/groups', \SeedDMS_RestapiController::class.':getGroups'); +$app->delete('/groups/{id}', \SeedDMS_RestapiController::class.':deleteGroup'); +$app->get('/groups/{id}', \SeedDMS_RestapiController::class.':getGroup'); +$app->put('/groups/{id}/addUser', \SeedDMS_RestapiController::class.':addUserToGroup'); +$app->put('/groups/{id}/removeUser', \SeedDMS_RestapiController::class.':removeUserFromGroup'); +$app->put('/folder/{id}/setInherit', \SeedDMS_RestapiController::class.':setFolderInheritsAccess'); +$app->put('/folder/{id}/owner/{userid}', \SeedDMS_RestapiController::class.':setFolderOwner'); +$app->put('/folder/{id}/access/group/add', \SeedDMS_RestapiController::class.':addGroupAccessToFolder'); // +$app->put('/folder/{id}/access/user/add', \SeedDMS_RestapiController::class.':addUserAccessToFolder'); // +$app->put('/folder/{id}/access/group/remove', \SeedDMS_RestapiController::class.':removeGroupAccessFromFolder'); +$app->put('/folder/{id}/access/user/remove', \SeedDMS_RestapiController::class.':removeUserAccessFromFolder'); +$app->put('/folder/{id}/access/clear', \SeedDMS_RestapiController::class.':clearFolderAccessList'); +$app->get('/categories', \SeedDMS_RestapiController::class.':getCategories'); +$app->get('/categories/{id}', \SeedDMS_RestapiController::class.':getCategory'); +$app->delete('/categories/{id}', \SeedDMS_RestapiController::class.':deleteCategory'); +$app->post('/categories', \SeedDMS_RestapiController::class.':createCategory'); +$app->put('/categories/{id}/name', \SeedDMS_RestapiController::class.':changeCategoryName'); +$app->get('/attributedefinitions', \SeedDMS_RestapiController::class.':getAttributeDefinitions'); +$app->put('/attributedefinitions/{id}/name', \SeedDMS_RestapiController::class.':changeAttributeDefinitionName'); +$app->get('/echo/{data}', \SeedDMS_TestController::class.':echoData'); +$app->get('/version', \SeedDMS_TestController::class.':version'); +$app->get('/statstotal', \SeedDMS_RestapiController::class.':getStatsTotal'); if(isset($GLOBALS['SEEDDMS_HOOKS']['initRestAPI'])) { foreach($GLOBALS['SEEDDMS_HOOKS']['initRestAPI'] as $hookObj) { From df5c81334ed3d8bed106350e0277d10bffd74499 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 11 Dec 2024 14:46:41 +0100 Subject: [PATCH 024/208] add changes for 5.1.37 --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 68d4836b8..018a877e4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,6 +4,7 @@ - do not show chart by category if there are no categories - documents in certain folders can be excluded from dashboard, could be useful for folders containing archived documents +- migrate from Slim 3 to Slim 4 (check for extension updates) -------------------------------------------------------------------------------- Changes in version 5.1.36 From 774d17c3f9c1f366ca99e30879d448a9d4a099dc Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 11 Dec 2024 15:58:11 +0100 Subject: [PATCH 025/208] suppress errors when loading html file --- inc/inc.ClassConversionServiceHtmlToText.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/inc/inc.ClassConversionServiceHtmlToText.php b/inc/inc.ClassConversionServiceHtmlToText.php index c9342e564..6130777d5 100644 --- a/inc/inc.ClassConversionServiceHtmlToText.php +++ b/inc/inc.ClassConversionServiceHtmlToText.php @@ -35,7 +35,9 @@ class SeedDMS_ConversionServiceHtmlToText extends SeedDMS_ConversionServiceBase public function convert($infile, $target = null, $params = array()) { $d = new DOMDocument; + libxml_use_internal_errors(true); $d->loadHTMLFile($infile); + libxml_clear_errors(); $body = $d->getElementsByTagName('body')->item(0); $str = ''; foreach($body->childNodes as $childNode) { From 755f601d7b7d40af8c7c205e0c39a8e3b16a0d6b Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Sat, 14 Dec 2024 19:19:24 +0100 Subject: [PATCH 026/208] add attachment from dropfolder dir --- op/op.AddFile.php | 88 ++++++++++++++++++++++++------- views/bootstrap/class.AddFile.php | 33 +++++++++--- 2 files changed, 95 insertions(+), 26 deletions(-) diff --git a/op/op.AddFile.php b/op/op.AddFile.php index 77ba5bc2d..2cbbb5b45 100644 --- a/op/op.AddFile.php +++ b/op/op.AddFile.php @@ -51,6 +51,47 @@ if ($document->getAccessMode($user, 'addDocumentFile') < M_READWRITE) { UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("access_denied")); } +function reArrayFiles(&$file_post) { + $file_ary = array(); + $file_count = count($file_post['name']); + $file_keys = array_keys($file_post); + + for ($i=0; $i<$file_count; $i++) { + if($file_post['error'][$i] != 4) { // no file uploaded + foreach ($file_keys as $key) { + $file_ary[$i][$key] = $file_post[$key][$i]; + } + $file_ary[$i]['source'] = 'upload'; + } + } + + return $file_ary; +} + +if(!empty($_FILES['userfile'])) { + $file_ary = reArrayFiles($_FILES['userfile']); +} else { + $file_ary = array(); +} + +if($settings->_dropFolderDir) { + if(isset($_POST["dropfolderfileaddfileform"]) && $_POST["dropfolderfileaddfileform"]) { + $fullfile = $settings->_dropFolderDir.'/'.$user->getLogin().'/'.$_POST["dropfolderfileaddfileform"]; + if(file_exists($fullfile)) { + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $mimetype = finfo_file($finfo, $fullfile); + $file_ary[] = array( + 'tmp_name' => $fullfile, + 'type' => $mimetype, + 'name' => $_POST["dropfolderfileaddfileform"], + 'size' => filesize($fullfile), + 'error' => 0, + 'source' => 'dropfolder' + ); + } + } +} + $prefix = 'userfile'; if(isset($_POST[$prefix.'-fine-uploader-uuids']) && $_POST[$prefix.'-fine-uploader-uuids']) { $uuids = explode(';', $_POST[$prefix.'-fine-uploader-uuids']); @@ -60,34 +101,43 @@ if(isset($_POST[$prefix.'-fine-uploader-uuids']) && $_POST[$prefix.'-fine-upload if(file_exists($fullfile)) { $finfo = finfo_open(FILEINFO_MIME_TYPE); $mimetype = finfo_file($finfo, $fullfile); - $_FILES["userfile"]['tmp_name'][] = $fullfile; - $_FILES["userfile"]['type'][] = $mimetype; - $_FILES["userfile"]['name'][] = isset($names[$i]) ? $names[$i] : $uuid; - $_FILES["userfile"]['size'][] = filesize($fullfile); - $_FILES["userfile"]['error'][] = 0; + $file_ary[] = array( + 'tmp_name' => $fullfile, + 'type' => $mimetype, + 'name' => isset($names[$i]) ? $names[$i] : $uuid, + 'size' => filesize($fullfile), + 'error' => 0, + 'source' => 'upload', + ); } } } +if(!$file_ary) { + UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("uploading_failed")); +} + $maxuploadsize = SeedDMS_Core_File::parse_filesize($settings->_maxUploadSize); -for ($file_num=0;$file_num $document->getName())),getMLText("uploading_zerosize")); +foreach($file_ary as $file) { + if($file['error']==1) { + UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("uploading_maxsize")); } - if ($maxuploadsize && $_FILES["userfile"]["size"][$file_num] > $maxuploadsize) { - UI::exitError(getMLText("folder_title", array("documentname" => $document->getName())),getMLText("uploading_maxsize")); - } - if (is_uploaded_file($_FILES["userfile"]["tmp_name"][$file_num]) && $_FILES['userfile']['error'][$file_num] != 0){ + if($file['error']!=0) { UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("uploading_failed")); } - if($_FILES["userfile"]["error"][$file_num]) { - UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("error_occured")); + if ($file["size"]==0) { + UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("uploading_zerosize")); } + if ($maxuploadsize && $file["size"] > $maxuploadsize) { + UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("uploading_maxsize")); + } +} - if(count($_FILES["userfile"]["tmp_name"]) == 1 && !empty($_POST['name'])) +foreach($file_ary as $file) { + if(count($file_ary) == 1 && !empty($_POST['name'])) $name = $_POST["name"]; else - $name = $_FILES["userfile"]['name'][$file_num]; + $name = $file['name']; $comment = $_POST["comment"]; $version = (int) $_POST["version"]; $public = (isset($_POST["public"]) && $_POST["public"] == 'true') ? 1 : 0; @@ -99,9 +149,9 @@ for ($file_num=0;$file_numparams['enablelargefileupload']; $partitionsize = $this->params['partitionsize']; $maxuploadsize = $this->params['maxuploadsize']; + $dropfolderdir = $this->params['dropfolderdir']; + header('Content-Type: application/javascript; charset=UTF-8'); parent::jsTranslations(array('js_form_error', 'js_form_errors')); if($enablelargefileupload) $this->printFineUploaderJs($this->params['settings']->_httpRoot.'op/op.UploadChunks.php', $partitionsize, $maxuploadsize); + if($dropfolderdir) { + $this->printDropFolderChooserJs("addfileform"); + } $this->printFileChooserJs(); ?> @@ -58,14 +63,18 @@ $(document).ready( function() { } return false; }, ""); - $("#form1").validate({ + $("#addfileform").validate({ debug: false, ignore: ":hidden:not(.do_validate)", submitHandler: function(form) { - userfileuploader.uploadStoredFiles(); + /* fileuploader may not have any files if drop folder is used */ + if(userfileuploader.getUploads().length) + userfileuploader.uploadStoredFiles(); + else + form.submit(); }, - fineuploaderuuids: { - fineuploader: [ userfileuploader ] + 'userfile-fine-uploader-uuids': { + fineuploader: [ userfileuploader, $('#dropfolderfileaddfileform') ] } 'userfile[]': { - required: true + require_from_group: [1, ".fileupload-group"], + maxsize: + }, + dropfolderfileaddfileform: { + require_from_group: [1, ".fileupload-group"] } params['enablelargefileupload']; $uploadedattachmentispublic = $this->params['uploadedattachmentispublic']; $maxuploadsize = $this->params['maxuploadsize']; + $dropfolderdir = $this->params['dropfolderdir']; $this->htmlAddHeader(''."\n", 'js'); $this->htmlAddHeader(''."\n", 'js'); @@ -132,7 +146,7 @@ $(document).ready( function() { ?> -
+ contentContainerStart(); @@ -140,6 +154,12 @@ $(document).ready( function() { getMLText("local_file"), ($enablelargefileupload ? $this->getFineUploaderHtml() : $this->getFileChooserHtml('userfile[]', false)) ); + if($dropfolderdir) { + $this->formField( + getMLText("dropfolder_file"), + $this->getDropFolderChooserHtml("addfileform") + ); + } $options = array(); $options[] = array("", getMLText('document')); $versions = $document->getContent(); @@ -198,4 +218,3 @@ $(document).ready( function() { } /* }}} */ } -?> From 9762db9f26c61bd85b2cf68bccb663b556daa548 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 17 Dec 2024 17:44:20 +0100 Subject: [PATCH 027/208] fix passing version to addContent() --- controllers/class.UpdateDocument.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/class.UpdateDocument.php b/controllers/class.UpdateDocument.php index 4f6013256..0b350b604 100644 --- a/controllers/class.UpdateDocument.php +++ b/controllers/class.UpdateDocument.php @@ -57,7 +57,7 @@ class SeedDMS_Controller_UpdateDocument extends SeedDMS_Controller_Common { $content = $this->callHook('updateDocument'); if($content === null) { $filesize = SeedDMS_Core_File::fileSize($userfiletmp); - if($contentResult=$document->addContent($comment, $user, $userfiletmp, utf8_basename($userfilename), $filetype, $userfiletype, $reviewers, $approvers, $version=0, $attributes, $workflow)) { + if($contentResult=$document->addContent($comment, $user, $userfiletmp, utf8_basename($userfilename), $filetype, $userfiletype, $reviewers, $approvers, 0, $attributes, $workflow)) { if ($this->hasParam('expires')) { if($document->setExpires($this->getParam('expires'))) { From 0abffe1f3ddbf20e51d8d77977984719b2e3e727 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 17 Dec 2024 18:15:05 +0100 Subject: [PATCH 028/208] get missing parameters in countTasks() --- views/bootstrap/class.Tasks.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/views/bootstrap/class.Tasks.php b/views/bootstrap/class.Tasks.php index 7ce7a3e8d..4c778b8cd 100644 --- a/views/bootstrap/class.Tasks.php +++ b/views/bootstrap/class.Tasks.php @@ -203,6 +203,8 @@ class SeedDMS_View_Tasks extends SeedDMS_Theme_Style { function countTasks() { /* {{{ */ $dms = $this->params['dms']; $user = $this->params['user']; + $enablereceiptworkflow = $this->params['enablereceiptworkflow']; + $enablerevisionworkflow = $this->params['enablerevisionworkflow']; $workflowmode = $this->params['workflowmode']; $tasksinmenu = $this->params['tasksinmenu']; From 05400afbcdafc3f7d90fc42241cc8a1f1000da18 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 20 Dec 2024 08:04:15 +0100 Subject: [PATCH 029/208] require guzzlehttp/psr7 --- composer-dist.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer-dist.json b/composer-dist.json index a5b830e5e..8166b952d 100644 --- a/composer-dist.json +++ b/composer-dist.json @@ -9,6 +9,7 @@ "sabre/dav": "^4.", "sabre/xml": "*", "slim/slim": "^4.0", + "guzzlehttp/psr7": "*", "erusev/parsedown": "*", "erusev/parsedown-extra": "*", "pear/log": "*", From 682cb8904f3c57a8a8fca3c236671626bb52847f Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 20 Dec 2024 08:05:11 +0100 Subject: [PATCH 030/208] rename showConfigFolder() to showConfigFolderNoTree() --- views/bootstrap/class.Settings.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/views/bootstrap/class.Settings.php b/views/bootstrap/class.Settings.php index 079fddb0d..007fdf035 100644 --- a/views/bootstrap/class.Settings.php +++ b/views/bootstrap/class.Settings.php @@ -258,7 +258,7 @@ class SeedDMS_View_Settings extends SeedDMS_Theme_Style { params['settings']; $dms = $this->params['dms']; ?> @@ -467,7 +467,7 @@ if(($kkk = $this->callHook('getFullSearchEngine')) && is_array($kkk)) showConfigCheckbox('settings_enableRecursiveCount', 'enableRecursiveCount'); ?> showConfigText('settings_maxRecursiveCount', 'maxRecursiveCount'); ?> showConfigText('settings_daysPastDashboard', 'daysPastDashboard'); ?> -showConfigFolder('settings_excludeFoldersDashboard', 'excludeFoldersDashboard'); ?> +showConfigFolderNoTree('settings_excludeFoldersDashboard', 'excludeFoldersDashboard'); ?> showConfigCheckbox('settings_enableLanguageSelector', 'enableLanguageSelector'); ?> showConfigCheckbox('settings_enableHelp', 'enableHelp'); ?> showConfigCheckbox('settings_enableThemeSelector', 'enableThemeSelector'); ?> From 226d2f01f44a52af984bed4d4e809cccce786855 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 20 Dec 2024 13:26:21 +0100 Subject: [PATCH 031/208] set $_excludeFoldersDashboard to empty array --- inc/inc.ClassSettings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/inc.ClassSettings.php b/inc/inc.ClassSettings.php index 5cc4e84d3..bc4a181b6 100644 --- a/inc/inc.ClassSettings.php +++ b/inc/inc.ClassSettings.php @@ -280,7 +280,7 @@ class Settings { /* {{{ */ // number of days in the past of the dashboard var $_daysPastDashboard = 7; // list of folders not considered for dashboard - var $_excludeFoldersDashboard = ''; + var $_excludeFoldersDashboard = []; // enable/disable help var $_enableHelp = true; // enable/disable language selection menu From cad3258a98d9cabaedc8a1006665347b8af84109 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 23 Dec 2024 16:16:36 +0100 Subject: [PATCH 032/208] array_diff must be array_intersect for excluding documents in certain folders --- views/bootstrap/class.Dashboard.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/views/bootstrap/class.Dashboard.php b/views/bootstrap/class.Dashboard.php index ddf80f235..0e8dc40a2 100644 --- a/views/bootstrap/class.Dashboard.php +++ b/views/bootstrap/class.Dashboard.php @@ -83,7 +83,7 @@ class SeedDMS_View_Dashboard extends SeedDMS_Theme_Style { $documents = SeedDMS_Core_DMS::filterAccess($documents, $user, M_READ); foreach($documents as $i=>$doc) { $fl = explode(':', $doc->getFolderList()); - if(array_diff($fl, $excludedfolders)) + if(array_intersect($fl, $excludedfolders)) unset($documents[$i]); } if (count($documents) > 0) { @@ -114,7 +114,7 @@ class SeedDMS_View_Dashboard extends SeedDMS_Theme_Style { $documents = SeedDMS_Core_DMS::filterAccess($documents, $user, M_READ); foreach($documents as $i=>$doc) { $fl = explode(':', $doc->getFolderList()); - if(array_diff($fl, $excludedfolders)) + if(array_intersect($fl, $excludedfolders)) unset($documents[$i]); } if (count($documents) > 0) { @@ -145,7 +145,7 @@ class SeedDMS_View_Dashboard extends SeedDMS_Theme_Style { $documents = SeedDMS_Core_DMS::filterAccess($documents, $user, M_READ); foreach($documents as $i=>$doc) { $fl = explode(':', $doc->getFolderList()); - if(array_diff($fl, $excludedfolders)) + if(array_intersect($fl, $excludedfolders)) unset($documents[$i]); } if (count($documents) > 0) { From 267c8c468b91693f0f2e4b5fb16a783bacf487fc Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 26 Dec 2024 08:37:33 +0100 Subject: [PATCH 033/208] do not check cache in checkExtensionByName() --- inc/inc.ClassExtensionMgr.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/inc.ClassExtensionMgr.php b/inc/inc.ClassExtensionMgr.php index fc5eceebd..3b1033364 100644 --- a/inc/inc.ClassExtensionMgr.php +++ b/inc/inc.ClassExtensionMgr.php @@ -402,7 +402,7 @@ class SeedDMS_Extension_Mgr { */ public function checkExtensionByName($extname, $extconf, $options=array()) { /* {{{ */ if(isset($this->configcache[$extname])) { - return $this->configcache[$extname]; +// return $this->configcache[$extname]; } $this->errmsgs = array(); From 7cb75bf51877bbdb28fabf626d532d8df9f3ee37 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Sun, 29 Dec 2024 08:06:56 +0100 Subject: [PATCH 034/208] skip footer in mail with recent changes --- inc/inc.Tasks.php | 1 + 1 file changed, 1 insertion(+) diff --git a/inc/inc.Tasks.php b/inc/inc.Tasks.php index 0e2bca4c4..3443cbf2d 100644 --- a/inc/inc.Tasks.php +++ b/inc/inc.Tasks.php @@ -813,6 +813,7 @@ class SeedDMS_RecentChangesTask extends SeedDMS_SchedulerTaskBase { /* {{{ */ $params['__body__'] = $body; $params['__body_html__'] = $bodyhtml; + $params['__skip_footer__'] = true; $params['sitename'] = $settings->_siteName; $email->toIndividual('', $u, 'recentchanges_mail_subject', '', $params); From ee6d2f15fcaab369f513ba0a021ffbe55a3df127 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 2 Jan 2025 14:40:49 +0100 Subject: [PATCH 035/208] fix getting uploaded files --- restapi/index.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/restapi/index.php b/restapi/index.php index c5d92c03e..5bf11d548 100644 --- a/restapi/index.php +++ b/restapi/index.php @@ -775,7 +775,9 @@ final class SeedDMS_RestapiController { /* {{{ */ $workflow = array_shift($workflows); } } - $temp = $file_info->file; + $temp = tempnam(sys_get_temp_dir(), 'FOO'); + file_put_contents($temp, (string) $file_info->getStream()); + $finfo = finfo_open(FILEINFO_MIME_TYPE); $userfiletype = finfo_file($finfo, $temp); $fileType = ".".pathinfo($origfilename, PATHINFO_EXTENSION); @@ -914,7 +916,8 @@ final class SeedDMS_RestapiController { /* {{{ */ $file_info = array_pop($uploadedFiles); if ($origfilename == null) $origfilename = $file_info->getClientFilename(); - $temp = $file_info->file; + $temp = tempnam(sys_get_temp_dir(), 'FOO'); + file_put_contents($temp, (string) $file_info->getStream()); /* Check if the uploaded file is identical to last version */ $lc = $document->getLatestContent(); @@ -1047,7 +1050,7 @@ final class SeedDMS_RestapiController { /* {{{ */ $keywords = isset($params['keywords']) ? $params['keywords'] : ''; $origfilename = isset($params['origfilename']) ? $params['origfilename'] : null; $content = $request->getBody(); - $temp = tempnam('/tmp', 'lajflk'); + $temp = tempnam(sys_get_temp_dir(), 'lajflk'); $handle = fopen($temp, "w"); fwrite($handle, $content); fclose($handle); @@ -1115,7 +1118,8 @@ final class SeedDMS_RestapiController { /* {{{ */ $origfilename = $file_info->getClientFilename(); if (trim($docname) == '') $docname = $origfilename; - $temp = $file_info->file; + $temp = tempnam(sys_get_temp_dir(), 'FOO'); + file_put_contents($temp, (string) $file_info->getStream()); $finfo = finfo_open(FILEINFO_MIME_TYPE); $userfiletype = finfo_file($finfo, $temp); $fileType = ".".pathinfo($origfilename, PATHINFO_EXTENSION); From e9783c882d3dd7bb2eddd0f0a5212711edad8174 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 16 Jan 2025 09:16:59 +0100 Subject: [PATCH 036/208] first column number is 1 not 0 --- inc/inc.ClassDownloadMgr.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/inc.ClassDownloadMgr.php b/inc/inc.ClassDownloadMgr.php index 78d07d8cb..39620581a 100644 --- a/inc/inc.ClassDownloadMgr.php +++ b/inc/inc.ClassDownloadMgr.php @@ -84,7 +84,7 @@ class SeedDMS_Download_Mgr { $sheet = $objPHPExcel->setActiveSheetIndex(0); $i = 1; - $col = 0; + $col = 1; foreach($this->header as $h) $sheet->setCellValueByColumnAndRow($col++, $i, $h); foreach($this->extraheader as $h) @@ -97,7 +97,7 @@ class SeedDMS_Download_Mgr { $reviewStatus = $item->getReviewStatus(); $approvalStatus = $item->getApprovalStatus(); - $col = 0; + $col = 1; $sheet->setCellValueByColumnAndRow($col++, $i, $document->getID()); $sheet->setCellValueByColumnAndRow($col++, $i, $document->getName()); $sheet->setCellValueByColumnAndRow($col++, $i, $document->getID()."-".$item->getOriginalFileName()); From 53cbe64222f5b9aa49e281cb0ab22c93844dcfb0 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 17 Jan 2025 13:12:22 +0100 Subject: [PATCH 037/208] add 'add' button before 'list' button --- views/bootstrap/class.SchedulerTaskMgr.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/bootstrap/class.SchedulerTaskMgr.php b/views/bootstrap/class.SchedulerTaskMgr.php index f03f2ac08..3262301bf 100644 --- a/views/bootstrap/class.SchedulerTaskMgr.php +++ b/views/bootstrap/class.SchedulerTaskMgr.php @@ -619,11 +619,11 @@ $(document).ready( function() { echo ""; echo ""; print "
"; + print ""; $t = $scheduler->getTasksByExtension($extname, $taskname); if($t) { print ""; } - print ""; print "
"; echo ""; echo ""; From f024da6fc2470d36c12bc1c4c9fde441813391f0 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 17 Jan 2025 13:48:46 +0100 Subject: [PATCH 038/208] add examples on how to use the rest api --- doc/README.Restapi | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 doc/README.Restapi diff --git a/doc/README.Restapi b/doc/README.Restapi new file mode 100644 index 000000000..d34aa07b2 --- /dev/null +++ b/doc/README.Restapi @@ -0,0 +1,55 @@ +# How to access the Rest API + +Below are various examples on how to access the Rest API. Some of them +start by calling the `login` endpoint which creates a cookie based +session which is stored in a local file named `cookies.txt`. +The authentication is done with the user `admin`. You may use any other +user as well. + +You may as well pass `-H Authorization: ` instead of `-b cookies.txt` +to `curl` after setting the api key in the configuration of your SeedDMS. +Of course, in that case you will not need the initial call of the `login` +endpoint. + +The examples often use the `jq` programm for formating the returned +json data. + +## Initial test + +The `echo` endpoint does not require any authentication. + +``` +#!/bin/sh +BASEURL="https://your-domain/" + +curl --silent -X GET ${BASEURL}restapi/index.php/echo/test | jq '.' + +``` + +## Getting list of users + +``` +#!/bin/sh +BASEURL="https://your-domain/" + +curl --silent -F "user=admin" -F "pass=admin" -b cookies.txt -c cookies.txt ${BASEURL}restapi/index.php/login | jq + +curl --silent -b cookies.txt -X GET "${BASEURL}restapi/index.php/users" | jq '.' +``` + +## Getting meta data of a folder + +``` +#!/bin/sh +BASEURL="https://your-domain/" + +curl --silent -H "Authorization: " -X GET "${BASEURL}restapi/index.php/folder/1" | jq '.' +``` +## Notes + +Make sure to encode the data properly when using restapi functions which uses +put. If you use curl with PHP, then encode the data as the following + + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded')); + From 05835e8d3dd194ac72385392980559bc7951ecb7 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 17 Jan 2025 14:08:10 +0100 Subject: [PATCH 039/208] set title of sheet in export file, only export documents --- inc/inc.ClassDownloadMgr.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/inc/inc.ClassDownloadMgr.php b/inc/inc.ClassDownloadMgr.php index 39620581a..45b5f9edb 100644 --- a/inc/inc.ClassDownloadMgr.php +++ b/inc/inc.ClassDownloadMgr.php @@ -82,6 +82,7 @@ class SeedDMS_Download_Mgr { $objPHPExcel = new PhpOffice\PhpSpreadsheet\Spreadsheet(); $objPHPExcel->getProperties()->setCreator("SeedDMS")->setTitle("Metadata"); $sheet = $objPHPExcel->setActiveSheetIndex(0); + $sheet->setTitle(getMLText('documents')); $i = 1; $col = 1; @@ -91,6 +92,7 @@ class SeedDMS_Download_Mgr { $sheet->setCellValueByColumnAndRow($col++, $i, $h); $i++; foreach($items as $item) { + if($item->isType('documentcontent')) { $document = $item->getDocument(); $dms = $document->_dms; $status = $item->getStatus(); @@ -174,6 +176,7 @@ class SeedDMS_Download_Mgr { $i = max($l, $k); $i++; } + } $objWriter = new PhpOffice\PhpSpreadsheet\Writer\Xlsx($objPHPExcel); $objWriter->save($file); From 588c7fa7987eb9447064e45ff21e727d86f00782 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 17 Jan 2025 14:08:54 +0100 Subject: [PATCH 040/208] rename file --- doc/{README.Restapi => README.Restapi.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename doc/{README.Restapi => README.Restapi.md} (100%) diff --git a/doc/README.Restapi b/doc/README.Restapi.md similarity index 100% rename from doc/README.Restapi rename to doc/README.Restapi.md From d8f7d473cb6e6ce86bfd73f8a6298b24726bd6b8 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 23 Jan 2025 14:10:15 +0100 Subject: [PATCH 041/208] do not log environment anymore --- restapi/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/restapi/index.php b/restapi/index.php index 5bf11d548..d20795e33 100644 --- a/restapi/index.php +++ b/restapi/index.php @@ -3045,7 +3045,7 @@ class RestapiAuthMiddleware implements MiddlewareInterface { /* {{{ */ $logger->log("Received preflight options request", PEAR_LOG_DEBUG); } elseif(!in_array($path, array('/login')) && substr($path, 0, 6) != '/echo/' && $path != '/version') { $userobj = null; - $logger->log(var_export($environment, true), PEAR_LOG_DEBUG); +// $logger->log(var_export($environment, true), PEAR_LOG_DEBUG); if(!empty($environment['HTTP_AUTHORIZATION']) && !empty($settings->_apiKey) && !empty($settings->_apiUserId)) { $logger->log("Authorization key: ".$environment['HTTP_AUTHORIZATION'], PEAR_LOG_DEBUG); if($settings->_apiKey == $environment['HTTP_AUTHORIZATION']) { From ceddf4d5bfc3b8a3a8139ca47085bcfcb5826b54 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 24 Jan 2025 11:32:08 +0100 Subject: [PATCH 042/208] do not show content container if form has no visible fields --- views/bootstrap/class.ReceiptDocument.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/views/bootstrap/class.ReceiptDocument.php b/views/bootstrap/class.ReceiptDocument.php index 74cbc9ce1..db8f2fab8 100644 --- a/views/bootstrap/class.ReceiptDocument.php +++ b/views/bootstrap/class.ReceiptDocument.php @@ -117,7 +117,8 @@ $(document).ready(function() { contentContainerStart(); + if (!$noreceiptcomment || $receiptreject) + $this->contentContainerStart(); if(!$noreceiptcomment) { $this->formField( getMLText("comment"), @@ -149,7 +150,8 @@ $(document).ready(function() { } else { echo ''; } - $this->contentContainerEnd(); + if (!$noreceiptcomment || $receiptreject) + $this->contentContainerEnd(); $this->formSubmit(getMLText('submit_receipt'), $receipttype.'Receipt'); ?> @@ -164,4 +166,3 @@ $(document).ready(function() { $this->htmlEndPage(); } /* }}} */ } -?> From 1033fee1b3cbba220b1172c38a393f1e6211cb73 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Sat, 25 Jan 2025 12:40:58 +0100 Subject: [PATCH 043/208] add method sendToAllReceiptMail() --- inc/inc.ClassNotificationService.php | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/inc/inc.ClassNotificationService.php b/inc/inc.ClassNotificationService.php index 2fd9b22d0..4da8218da 100644 --- a/inc/inc.ClassNotificationService.php +++ b/inc/inc.ClassNotificationService.php @@ -1471,6 +1471,35 @@ class SeedDMS_NotificationService { $this->toGroup($user, $recipient, $subject, $message, $params, SeedDMS_NotificationService::RECV_RECIPIENT); } /* }}} */ + /** + * Send a request receipt notification to all recipients of the document content + * + * This method can be called when the status of a document content changes + * to 'released'. The recipients haven't been informed when the + * document content was created but not immediatly released. + */ + public function sendToAllReceiptMail($content, $user) { /* {{{ */ + $dms = $content->getDMS(); + + $receiptStatus = $content->getReceiptStatus(); + if (!empty($receiptStatus)) { + foreach ($receiptStatus as $r) { + if($r['status'] == 0) { + switch ($r["type"]) { + case 0: // Recipient is an individual. + if($recipient = $dms->getUser($r["required"])) + $this->sendAddReceiptMail($content, $user, $recipient); + break; + case 1: // Recipient is a group. + if($recipient = $dms->getGroup($r["required"])) + $this->sendAddReceiptMail($content, $user, $recipient); + break; + } + } + } + } + } /* }}} */ + public function sendChangedDocumentOwnerMail($document, $user, $oldowner) { /* {{{ */ if($oldowner->getID() != $document->getOwner()->getID()) { $notifyList = $document->getNotifyList(); From ec6c4855fcd1ef28557516639a8dfb02ac5f7561 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Sat, 25 Jan 2025 12:42:08 +0100 Subject: [PATCH 044/208] send request receipt notification only if document is released --- op/op.AddDocument.php | 13 ++++++++++++- op/op.ApproveDocument.php | 7 +++++++ op/op.OverrideContentStatus.php | 11 +++++++++-- op/op.SetRecipients.php | 24 ++++++++++++++++-------- op/op.UpdateDocument.php | 9 +++++++++ 5 files changed, 53 insertions(+), 11 deletions(-) diff --git a/op/op.AddDocument.php b/op/op.AddDocument.php index 0d5790dff..03f47c1fa 100644 --- a/op/op.AddDocument.php +++ b/op/op.AddDocument.php @@ -498,9 +498,20 @@ foreach($file_ary as $file) { if($controller->hasHook('cleanUpDocument')) { $controller->callHook('cleanUpDocument', $document, $file); } - // Send notification to subscribers of folder. if($notifier) { + // Send notification to subscribers of folder. $notifier->sendNewDocumentMail($document, $user); + + // Send notifcation to recipients of document + $content = $document->getLatestContent(); + $status = $content->getStatus(); + if ($status["status"] == S_RELEASED) { + if ($settings->_enableNotificationAppRev) { + if ($notifier) { + $notifier->sendToAllReceiptMail($content, $user); + } + } + } } if($settings->_removeFromDropFolder) { if(file_exists($userfiletmp)) { diff --git a/op/op.ApproveDocument.php b/op/op.ApproveDocument.php index 617b9da4b..6572e794d 100644 --- a/op/op.ApproveDocument.php +++ b/op/op.ApproveDocument.php @@ -111,6 +111,13 @@ if(!$controller()) { $notifier->sendSubmittedApprovalMail($latestContent, $user, $approvelog ? $approvelog[0] : false); if($controller->oldstatus != $controller->newstatus) $notifier->sendChangedDocumentStatusMail($latestContent, $user, $controller->oldstatus); + if ($controller->newstatus == S_RELEASED) { + if ($settings->_enableNotificationAppRev) { + if ($notifier) { + $notifier->sendToAllReceiptMail($content, $user); + } + } + } } } diff --git a/op/op.OverrideContentStatus.php b/op/op.OverrideContentStatus.php index 253926e56..dd5a74f42 100644 --- a/op/op.OverrideContentStatus.php +++ b/op/op.OverrideContentStatus.php @@ -85,9 +85,16 @@ if ($overrideStatus != $overallStatus["status"]) { if (!$content->setStatus($overrideStatus, $comment, $user)) { UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("error_occured")); } else { - // Send notification to subscribers. - if($notifier) { + if ($notifier) { + // Send notification to subscribers. $notifier->sendChangedDocumentStatusMail($content, $user, $overallStatus["status"]); + + // Send request for receipt notification + if ($overrideStatus == S_RELEASED) { + if ($settings->_enableNotificationAppRev) { + $notifier->sendToAllReceiptMail($content, $user); + } + } } } } diff --git a/op/op.SetRecipients.php b/op/op.SetRecipients.php index 2806e73af..778d8d3e0 100644 --- a/op/op.SetRecipients.php +++ b/op/op.SetRecipients.php @@ -69,6 +69,8 @@ foreach ($docAccess["groups"] as $i=>$da) { $accessIndex["g"][$da->getID()] = $da; } +$status = $content->getStatus(); + // Retrieve list of currently assigned recipients, along with // their latest status. $receiptStatus = $content->getReceiptStatus(); @@ -137,10 +139,13 @@ foreach ($pIndRev as $p) { // email error break; default: - // Send an email notification to the new recipient. - if($settings->_enableNotificationAppRev) { - if ($notifier) { - $notifier->sendAddReceiptMail($content, $user, $accessIndex["i"][$p]); + // Send an email notification to the new recipient only if the document + // is already released + if ($status["status"] == S_RELEASED) { + if($settings->_enableNotificationAppRev) { + if ($notifier) { + $notifier->sendAddReceiptMail($content, $user, $accessIndex["i"][$p]); + } } } break; @@ -218,10 +223,13 @@ foreach ($pGrpRev as $p) { // email error break; default: - // Send an email notification to the new recipient. - if($settings->_enableNotificationAppRev) { - if ($notifier) { - $notifier->sendAddReceiptMail($content, $user, $accessIndex["g"][$p]); + // Send an email notification to the new recipient only if the document + // is already released + if ($status["status"] == S_RELEASED) { + if($settings->_enableNotificationAppRev) { + if ($notifier) { + $notifier->sendAddReceiptMail($content, $user, $accessIndex["g"][$p]); + } } } break; diff --git a/op/op.UpdateDocument.php b/op/op.UpdateDocument.php index a1a798f38..19b32b145 100644 --- a/op/op.UpdateDocument.php +++ b/op/op.UpdateDocument.php @@ -403,6 +403,15 @@ default: $notifier->sendNewDocumentVersionMail($document, $user); $notifier->sendChangedExpiryMail($document, $user, $oldexpires); + + $status = $content->getStatus(); + if ($status["status"] == S_RELEASED) { + if ($settings->_enableNotificationAppRev) { + if ($notifier) { + $notifier->sendToAllReceiptMail($content, $user); + } + } + } } if($settings->_removeFromDropFolder) { From fe88895808f9517d6df6bb076aabacfdeb3571b7 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Sun, 26 Jan 2025 19:51:52 +0100 Subject: [PATCH 045/208] add changes for 6.0.30 --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 7e503845b..a979decef 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,7 @@ -------------------------------------------------------------------------------- - merge changes up to 5.1.37 - receipt comment can be disabled +- send request receipt notification only when document is released -------------------------------------------------------------------------------- Changes in version 6.0.29 From 612f297926b15cc4769dac3e37e0d8bb7512cd2a Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 28 Jan 2025 17:37:09 +0100 Subject: [PATCH 046/208] fix loading more entries at end of page --- views/bootstrap/class.ViewFolder.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/views/bootstrap/class.ViewFolder.php b/views/bootstrap/class.ViewFolder.php index 59f47ea31..f9aafe4b1 100644 --- a/views/bootstrap/class.ViewFolder.php +++ b/views/bootstrap/class.ViewFolder.php @@ -156,12 +156,12 @@ function loadMoreObjects(element, limit, orderby) { element.prop("disabled",true); var folder = element.data('folder') var offset = element.data('offset') -// var limit = element.data('limit') url = seeddms_webroot+"out/out.ViewFolder.php?action=entries&folderid="+folder+"&offset="+offset+"&limit="+limit+"&orderby="+orderby; $.ajax({ type: 'GET', url: url, dataType: 'json', + async: false, success: function(data){ $('#viewfolder-table').append(data.html); if(data.count <= 0) { @@ -176,7 +176,7 @@ function loadMoreObjects(element, limit, orderby) { }); } $(window).scroll(function() { - if($(window).scrollTop() + $(window).height() == $(document).height()) { + if($(window).scrollTop() + $(window).height() + 3 >= $(document).height()) { loadMoreObjects($('#loadmore'), $('#loadmore').data('limit'), $('#loadmore').data('orderby')); } }); From 77df75a038ced9a6ba511bae5b6d1c0ec420b120 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 28 Jan 2025 17:38:05 +0100 Subject: [PATCH 047/208] add changes for 5.1.37 --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 018a877e4..7450d2774 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,8 @@ - documents in certain folders can be excluded from dashboard, could be useful for folders containing archived documents - migrate from Slim 3 to Slim 4 (check for extension updates) +- fix reloading more entries in list of folders/documents at end of page if + maxItemsPerPage is set -------------------------------------------------------------------------------- Changes in version 5.1.36 From be1ebce45f6c037c0f90325adde55dd06677c9ad Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 29 Jan 2025 10:23:57 +0100 Subject: [PATCH 048/208] fix errors --- restapi/swagger.yaml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/restapi/swagger.yaml b/restapi/swagger.yaml index f19c5299c..f035159fe 100644 --- a/restapi/swagger.yaml +++ b/restapi/swagger.yaml @@ -13,9 +13,6 @@ info: license: name: "Apache 2.0" url: "http://www.apache.org/licenses/LICENSE-2.0.html" -servers: - - url: - description: Current host server host: "" basePath: "_httpRoot; ?>restapi/index.php" tags: @@ -1510,7 +1507,7 @@ paths: produces: - "application/json" consumes: - - "application/x-www-form-urlencoded" + - "multipart/form-data" parameters: - name: "id" in: "path" From a0df82c2e73c8139489c8480caa34271486c4552 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 29 Jan 2025 10:24:52 +0100 Subject: [PATCH 049/208] add example of PHP FPM handler --- restapi/.htaccess | 3 +++ 1 file changed, 3 insertions(+) diff --git a/restapi/.htaccess b/restapi/.htaccess index 0151827f6..682a4d98a 100644 --- a/restapi/.htaccess +++ b/restapi/.htaccess @@ -2,7 +2,10 @@ RewriteEngine on RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] +# Apache module SetHandler application/x-httpd-php +# PHP FPM on Debian +#SetHandler "proxy:unix:/var/run/php/php8.2-fpm.sock|fcgi://localhost/" Header set Access-Control-Allow-Origin "*" Header set Access-Control-Allow-Methods "GET" From dd13504fefbd37e5f2b34d718183c8c53fdbfcd9 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 29 Jan 2025 10:25:26 +0100 Subject: [PATCH 050/208] fix xss attack --- views/bootstrap/class.Bootstrap.php | 2 +- views/bootstrap/class.EditDocument.php | 2 +- views/bootstrap/class.Search.php | 8 ++++---- views/bootstrap4/class.Bootstrap4.php | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/views/bootstrap/class.Bootstrap.php b/views/bootstrap/class.Bootstrap.php index 9b69f4f8a..7d7f4408d 100644 --- a/views/bootstrap/class.Bootstrap.php +++ b/views/bootstrap/class.Bootstrap.php @@ -3277,7 +3277,7 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) $content .= "
"; foreach($categories as $category) { $color = substr(md5($category->getName()), 0, 6); - $content .= "".$category->getName()." "; + $content .= "".htmlspecialchars($category->getName())." "; } } if(!empty($extracontent['bottom_title'])) diff --git a/views/bootstrap/class.EditDocument.php b/views/bootstrap/class.EditDocument.php index 48c1d47c0..5d4746e33 100644 --- a/views/bootstrap/class.EditDocument.php +++ b/views/bootstrap/class.EditDocument.php @@ -139,7 +139,7 @@ $(document).ready( function() { if(!$nodocumentformfields || !in_array('categories', $nodocumentformfields)) { $options = array(); foreach($categories as $category) { - $options[] = array($category->getID(), $category->getName(), in_array($category, $document->getCategories())); + $options[] = array($category->getID(), htmlspecialchars($category->getName()), in_array($category, $document->getCategories())); } $this->formField( getMLText("categories"), diff --git a/views/bootstrap/class.Search.php b/views/bootstrap/class.Search.php index e602de15d..12c64f56f 100644 --- a/views/bootstrap/class.Search.php +++ b/views/bootstrap/class.Search.php @@ -369,9 +369,9 @@ $(document).ready(function() { } } if($removecategory) { - $this->setParam('batchmsg', getMLText('batch_remove_category_msg', ['count'=>$j, 'catname'=>$changecategory->getName()])); + $this->setParam('batchmsg', getMLText('batch_remove_category_msg', ['count'=>$j, 'catname'=>htmlspecialchars($changecategory->getName())])); } else { - $this->setParam('batchmsg', getMLText('batch_add_category_msg', ['count'=>$j, 'catname'=>$changecategory->getName()])); + $this->setParam('batchmsg', getMLText('batch_add_category_msg', ['count'=>$j, 'catname'=>htmlspecialchars($changecategory->getName())])); } } else { } @@ -710,7 +710,7 @@ $(document).ready(function() { $allcategories = $dms->getDocumentCategories(); if($allcategories) { foreach($allcategories as $acategory) { - $options[] = array($acategory->getID(), $acategory->getName(), in_array($acategory->getId(), $tmpcatids)); + $options[] = array($acategory->getID(), htmlspecialchars($acategory->getName()), in_array($acategory->getId(), $tmpcatids)); } $this->formField( getMLText("categories"), @@ -947,7 +947,7 @@ $(document).ready(function() { $options = array(); $allcategories = $dms->getDocumentCategories(); foreach($allcategories as $acategory) { - $options[] = array($acategory->getID(), $acategory->getName(), in_array($acategory->getId(), $tmpcatids)); + $options[] = array($acategory->getID(), htmlspecialchars($acategory->getName()), in_array($acategory->getId(), $tmpcatids)); } $this->formField( getMLText("category_filter"), diff --git a/views/bootstrap4/class.Bootstrap4.php b/views/bootstrap4/class.Bootstrap4.php index ebafc2524..93ffc29f2 100644 --- a/views/bootstrap4/class.Bootstrap4.php +++ b/views/bootstrap4/class.Bootstrap4.php @@ -3326,7 +3326,7 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) $content .= "
"; foreach($categories as $category) { $color = substr(md5($category->getName()), 0, 6); - $content .= "".$category->getName()." "; + $content .= "".htmlspecialchars($category->getName())." "; } } if(!empty($extracontent['bottom_title'])) From aa6454fce9c7bc2d6fb4a9b029e640d7db6f2684 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 29 Jan 2025 10:25:55 +0100 Subject: [PATCH 051/208] add changes for 5.1.37 --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 7450d2774..d34962e65 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -7,6 +7,7 @@ - migrate from Slim 3 to Slim 4 (check for extension updates) - fix reloading more entries in list of folders/documents at end of page if maxItemsPerPage is set +- prevent xss attack -------------------------------------------------------------------------------- Changes in version 5.1.36 From f2e5faf80b80c75d2c2e1b396cd65caebb36146b Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 29 Jan 2025 14:57:37 +0100 Subject: [PATCH 052/208] use type: 'string' instead 'file' --- restapi/swagger.yaml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/restapi/swagger.yaml b/restapi/swagger.yaml index f035159fe..08cb1dcd1 100644 --- a/restapi/swagger.yaml +++ b/restapi/swagger.yaml @@ -562,7 +562,8 @@ paths: "200": description: "preview image file" schema: - type: "file" + type: "string" + format: "binary" "403": description: "No access" schema: @@ -595,7 +596,8 @@ paths: "200": description: "content file" schema: - type: "file" + type: "string" + format: "binary" "403": description: "No access" schema: @@ -634,7 +636,8 @@ paths: "200": description: "attached file" schema: - type: "file" + type: "string" + format: "binary" "403": description: "No access" schema: @@ -673,7 +676,8 @@ paths: "200": description: "content file" schema: - type: "file" + type: "string" + format: "binary" "403": description: "No access" schema: From 675bcf66ac6d3b75d7e3ff98321b9fdac9f989fe Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 30 Jan 2025 14:51:44 +0100 Subject: [PATCH 053/208] add warning about cleared environment when running php-fpm --- doc/README.Converters | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/README.Converters b/doc/README.Converters index dfa22f0c4..c7946a83c 100644 --- a/doc/README.Converters +++ b/doc/README.Converters @@ -18,6 +18,13 @@ Please note, that when ever a command outputs anything to stderr, this will considered as a failure of the command. Most command line programs have a parameter (.e.g. `-q`) to suppress such an output. +If you run php-fpm you may encounter problems with charsets based on +UTF-8. Programms like `catdoc` read LANG from the environment to +set the correct encoding of the output. php-fpm often clears the +environment and programms like `catdoc` will not longer output any +UTF-8 chars. In such a case you may want to set `clear_env=no` in +php-fpm's configuration. + Conversion to text for fulltext search ======================================= From 1ad8fbcb2a1461ff60f4fcae215184335a4c81ff Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 30 Jan 2025 14:53:59 +0100 Subject: [PATCH 054/208] more info for debian users --- doc/README.Converters | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/README.Converters b/doc/README.Converters index c7946a83c..8f83c1307 100644 --- a/doc/README.Converters +++ b/doc/README.Converters @@ -23,7 +23,8 @@ UTF-8. Programms like `catdoc` read LANG from the environment to set the correct encoding of the output. php-fpm often clears the environment and programms like `catdoc` will not longer output any UTF-8 chars. In such a case you may want to set `clear_env=no` in -php-fpm's configuration. +php-fpm's configuration. On Debian this is done in the file +`/etc/php//fpm/pool.d/www.conf`. Search for `clear_env`. Conversion to text for fulltext search ======================================= From 325a180ff854d437f99ce631b4e59865e072c780 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 31 Jan 2025 09:53:58 +0100 Subject: [PATCH 055/208] lots of formatting fixes --- restapi/index.php | 158 +++++++++++++++++++--------------------------- 1 file changed, 65 insertions(+), 93 deletions(-) diff --git a/restapi/index.php b/restapi/index.php index d20795e33..4a6bf11f2 100644 --- a/restapi/index.php +++ b/restapi/index.php @@ -25,24 +25,21 @@ use Psr\Http\Server\MiddlewareInterface; use DI\ContainerBuilder; use Slim\Factory\AppFactory; -final class JsonRenderer -{ +final class JsonRenderer { /* {{{ */ public function json( ResponseInterface $response, array $data = null ): ResponseInterface { $response = $response->withHeader('Content-Type', 'application/json'); - - $response->getBody()->write( - (string)json_encode( - $data, - JSON_UNESCAPED_SLASHES | JSON_PARTIAL_OUTPUT_ON_ERROR - ) - ); - + $response->getBody()->write( + (string)json_encode( + $data, + JSON_UNESCAPED_SLASHES | JSON_PARTIAL_OUTPUT_ON_ERROR + ) + ); return $response; } -} +} /* }}} */ final class SeedDMS_RestapiController { /* {{{ */ protected $container; @@ -1730,12 +1727,9 @@ final class SeedDMS_RestapiController { /* {{{ */ $dms = $this->container->get('dms'); $userobj = $this->container->get('userobj'); - if(!$userobj) { - return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); - } - if(!$userobj->isAdmin()) { - return $this->renderer->json($response, array('success'=>false, 'message'=>'No access on document', 'data'=>''))->withStatus(403); - } + $check = $this->checkIfAdmin($request, $response); + if ($check !== true) + return $check; if(!ctype_digit($args['id']) || $args['id'] == 0) { return $this->renderer->json($response, array('success'=>false, 'message'=>'No document given', 'data'=>''))->withStatus(400); @@ -2106,8 +2100,8 @@ final class SeedDMS_RestapiController { /* {{{ */ function checkIfAdmin($request, $response) { /* {{{ */ $dms = $this->container->get('dms'); - if(!$this->container->has('userobj')) - echo "no user object"; +// if(!$this->container->has('userobj')) +// echo "no user object"; if(!$this->container->has('userobj') || !($userobj = $this->container->get('userobj'))) { return $this->renderer->json($response, ['success'=>false, 'message'=>'Not logged in', 'data'=>''])->withStatus(403); @@ -2245,7 +2239,7 @@ final class SeedDMS_RestapiController { /* {{{ */ return $check; $params = $request->getParsedBody(); - if ($params['quota'] == null) { + if ($params['quota'] == null || !ctype_digit($params['quota'])) { return $this->renderer->json($response, array('success'=>false, 'message'=>'You must supply a new quota', 'data'=>''))->withStatus(400); } @@ -2434,6 +2428,7 @@ final class SeedDMS_RestapiController { /* {{{ */ $check = $this->checkIfAdmin($request, $response); if($check !== true) return $check; + if(ctype_digit($args['id'])) $group = $dms->getGroup($args['id']); else { @@ -2456,21 +2451,21 @@ final class SeedDMS_RestapiController { /* {{{ */ $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); - if($check !== true) + if ($check !== true) return $check; - if(ctype_digit($args['id'])) + if (ctype_digit($args['id'])) $group = $dms->getGroup($args['id']); else { $group = $dms->getGroupByName($args['id']); } - $params = $request->getParsedBody(); + $params = $request->getParsedBody(); if (empty($params['userid'])) { return $this->renderer->json($response, array('success'=>false, 'message'=>'Missing userid', 'data'=>''))->withStatus(400); } $userId = $params['userid']; - if(ctype_digit($userId)) + if (ctype_digit($userId)) $user = $dms->getUser($userId); else { $user = $dms->getUserByLogin($userId); @@ -2482,20 +2477,16 @@ final class SeedDMS_RestapiController { /* {{{ */ $operationResult = false; - if ($operationType == 'add') - { + if ($operationType == 'add') { $operationResult = $group->addUser($user); } - if ($operationType == 'remove') - { + if ($operationType == 'remove') { $operationResult = $group->removeUser($user); } - if ($operationResult === false) - { + if ($operationResult === false) { $message = 'Could not add user to the group.'; - if ($operationType == 'remove') - { + if ($operationType == 'remove') { $message = 'Could not remove user from group.'; } return $this->renderer->json($response, array('success'=>false, 'message'=>'Something went wrong. ' . $message, 'data'=>''))->withStatus(500); @@ -2522,8 +2513,9 @@ final class SeedDMS_RestapiController { /* {{{ */ $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); - if($check !== true) + if ($check !== true) return $check; + $params = $request->getParsedBody(); if (!isset($params['enable'])) { @@ -2560,12 +2552,9 @@ final class SeedDMS_RestapiController { /* {{{ */ $dms = $this->container->get('dms'); $userobj = $this->container->get('userobj'); - if(!$userobj) { - return $this->renderer->json($response, array('success'=>false, 'message'=>'Not logged in', 'data'=>''))->withStatus(403); - } - if(!$userobj->isAdmin()) { - return $this->renderer->json($response, array('success'=>false, 'message'=>'No access on folder', 'data'=>''))->withStatus(403); - } + $check = $this->checkIfAdmin($request, $response); + if ($check !== true) + return $check; if(!ctype_digit($args['id']) || $args['id'] == 0) { return $this->renderer->json($response, array('success'=>false, 'message'=>'No folder given', 'data'=>''))->withStatus(400); @@ -2631,51 +2620,40 @@ final class SeedDMS_RestapiController { /* {{{ */ $params = $request->getParsedBody(); $userOrGroupIdInput = $params['id']; - if ($operationType == 'add') - { - if ($params['id'] == null) - { + if ($operationType == 'add') { + if ($params['id'] == null) { return $this->renderer->json($response, array('success'=>false, 'message'=>'Please PUT the user or group Id', 'data'=>''))->withStatus(400); } - if ($params['mode'] == null) - { + if ($params['mode'] == null) { return $this->renderer->json($response, array('success'=>false, 'message'=>'Please PUT the access mode', 'data'=>''))->withStatus(400); } $modeInput = $params['mode']; $mode = M_NONE; - if ($modeInput == 'read') - { + if ($modeInput == 'read') { $mode = M_READ; } - if ($modeInput == 'readwrite') - { + if ($modeInput == 'readwrite') { $mode = M_READWRITE; } - if ($modeInput == 'all') - { + if ($modeInput == 'all') { $mode = M_ALL; } } - $userOrGroupId = $userOrGroupIdInput; - if(!ctype_digit($userOrGroupIdInput) && $userOrGroup == 'user') - { + if (!ctype_digit($userOrGroupIdInput) && $userOrGroup == 'user') { $userOrGroupObj = $dms->getUserByLogin($userOrGroupIdInput); } - if(!ctype_digit($userOrGroupIdInput) && $userOrGroup == 'group') - { + if (!ctype_digit($userOrGroupIdInput) && $userOrGroup == 'group') { $userOrGroupObj = $dms->getGroupByName($userOrGroupIdInput); } - if(ctype_digit($userOrGroupIdInput) && $userOrGroup == 'user') - { + if (ctype_digit($userOrGroupIdInput) && $userOrGroup == 'user') { $userOrGroupObj = $dms->getUser($userOrGroupIdInput); } - if(ctype_digit($userOrGroupIdInput) && $userOrGroup == 'group') - { + if (ctype_digit($userOrGroupIdInput) && $userOrGroup == 'group') { $userOrGroupObj = $dms->getGroup($userOrGroupIdInput); } if (!$userOrGroupObj) { @@ -2685,29 +2663,23 @@ final class SeedDMS_RestapiController { /* {{{ */ $operationResult = false; - if ($operationType == 'add' && $userOrGroup == 'user') - { + if ($operationType == 'add' && $userOrGroup == 'user') { $operationResult = $folder->addAccess($mode, $userOrGroupId, true); } - if ($operationType == 'remove' && $userOrGroup == 'user') - { + if ($operationType == 'remove' && $userOrGroup == 'user') { $operationResult = $folder->removeAccess($userOrGroupId, true); } - if ($operationType == 'add' && $userOrGroup == 'group') - { + if ($operationType == 'add' && $userOrGroup == 'group') { $operationResult = $folder->addAccess($mode, $userOrGroupId, false); } - if ($operationType == 'remove' && $userOrGroup == 'group') - { + if ($operationType == 'remove' && $userOrGroup == 'group') { $operationResult = $folder->removeAccess($userOrGroupId, false); } - if ($operationResult === false) - { + if ($operationResult === false) { $message = 'Could not add user/group access to this folder.'; - if ($operationType == 'remove') - { + if ($operationType == 'remove') { $message = 'Could not remove user/group access from this folder.'; } return $this->renderer->json($response, array('success'=>false, 'message'=>'Something went wrong. ' . $message, 'data'=>''))->withStatus(500); @@ -2721,11 +2693,12 @@ final class SeedDMS_RestapiController { /* {{{ */ $dms = $this->container->get('dms'); $userobj = $this->container->get('userobj'); - if(false === ($categories = $dms->getDocumentCategories())) { + if (false === ($categories = $dms->getDocumentCategories())) { return $this->renderer->json($response, array('success'=>false, 'message'=>'Could not get categories', 'data'=>null))->withStatus(500); } + $data = []; - foreach($categories as $category) + foreach ($categories as $category) $data[] = $this->__getCategoryData($category); return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); @@ -2735,12 +2708,12 @@ final class SeedDMS_RestapiController { /* {{{ */ $dms = $this->container->get('dms'); $userobj = $this->container->get('userobj'); - if(!ctype_digit($args['id'])) { + if (!ctype_digit($args['id'])) { return $this->renderer->json($response, array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''))->withStatus(400); } $category = $dms->getDocumentCategory($args['id']); - if($category) { + if ($category) { return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$this->__getCategoryData($category)))->withStatus(200); } else { return $this->renderer->json($response, array('success'=>false, 'message'=>'No such category', 'data'=>''))->withStatus(404); @@ -2753,7 +2726,7 @@ final class SeedDMS_RestapiController { /* {{{ */ $logger = $this->container->get('logger'); $check = $this->checkIfAdmin($request, $response); - if($check !== true) + if ($check !== true) return $check; $params = $request->getParsedBody(); @@ -2762,7 +2735,7 @@ final class SeedDMS_RestapiController { /* {{{ */ } $catobj = $dms->getDocumentCategoryByName($params['name']); - if($catobj) { + if ($catobj) { return $this->renderer->json($response, array('success'=>false, 'message'=>'Category already exists', 'data'=>''))->withStatus(409); } else { if($data = $dms->addDocumentCategory($params['name'])) { @@ -2779,11 +2752,11 @@ final class SeedDMS_RestapiController { /* {{{ */ $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); - if($check !== true) + if ($check !== true) return $check; - if($category = $dms->getDocumentCategory($args['id'])) { - if($result = $category->remove()) { + if ($category = $dms->getDocumentCategory($args['id'])) { + if ($result = $category->remove()) { return $this->renderer->json($response, array('success'=>$result, 'message'=>'', 'data'=>''))->withStatus(200); } else { return $this->renderer->json($response, array('success'=>$result, 'message'=>'Could not delete category', 'data'=>''))->withStatus(500); @@ -2803,16 +2776,15 @@ final class SeedDMS_RestapiController { /* {{{ */ $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); - if($check !== true) + if ($check !== true) return $check; - if(!ctype_digit($args['id'])) { + if (!ctype_digit($args['id'])) { return $this->renderer->json($response, array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''))->withStatus(400); } $params = $request->getParsedBody(); - if (empty($params['name'])) - { + if (empty($params['name'])) { return $this->renderer->json($response, array('success'=>false, 'message'=>'You must supply a new name', 'data'=>''))->withStatus(400); } @@ -2840,7 +2812,7 @@ final class SeedDMS_RestapiController { /* {{{ */ $attrdefs = $dms->getAllAttributeDefinitions(); $data = []; - foreach($attrdefs as $attrdef) + foreach ($attrdefs as $attrdef) $data[] = $this->__getAttributeDefinitionData($attrdef); return $this->renderer->json($response, array('success'=>true, 'message'=>'', 'data'=>$data))->withStatus(200); @@ -2856,10 +2828,10 @@ final class SeedDMS_RestapiController { /* {{{ */ $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); - if($check !== true) + if ($check !== true) return $check; - if(!ctype_digit($args['id'])) { + if (!ctype_digit($args['id'])) { return $this->renderer->json($response, array('success'=>false, 'message'=>'Invalid parameter', 'data'=>''))->withStatus(400); } @@ -2892,12 +2864,12 @@ final class SeedDMS_RestapiController { /* {{{ */ $userobj = $this->container->get('userobj'); $check = $this->checkIfAdmin($request, $response); - if($check !== true) + if ($check !== true) return $check; - if(ctype_digit($args['id'])) + if (ctype_digit($args['id'])) { $folder = $dms->getFolder($args['id']); - else { + } else { $folder = $dms->getFolderByName($args['id']); } if (!$folder) { @@ -2912,11 +2884,11 @@ final class SeedDMS_RestapiController { /* {{{ */ function getStatsTotal($request, $response) { /* {{{ */ $dms = $this->container->get('dms'); $check = $this->checkIfAdmin($request, $response); - if($check !== true) + if ($check !== true) return $check; $data = []; - foreach(array('docstotal', 'folderstotal', 'userstotal') as $type) { + foreach (array('docstotal', 'folderstotal', 'userstotal') as $type) { $total = $dms->getStatisticalData($type); $data[$type] = $total; } From 327b1c4284e64566bbd3b514709db5274166045e Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 31 Jan 2025 09:54:21 +0100 Subject: [PATCH 056/208] add some missing functions --- restapi/swagger.yaml | 288 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) diff --git a/restapi/swagger.yaml b/restapi/swagger.yaml index 08cb1dcd1..3eaf7fed9 100644 --- a/restapi/swagger.yaml +++ b/restapi/swagger.yaml @@ -403,6 +403,92 @@ paths: $ref: "#/definitions/ApiResponse" security: - api_key: [] + /users/{id}/quota: + put: + tags: + - "user" + summary: "Change quota of user by ID" + description: "Change the quota of a single user" + operationId: "changeUserQuota" + produces: + - "application/json" + consumes: + - "application/x-www-form-urlencoded" + parameters: + - name: "id" + in: "path" + description: "ID of user" + required: true + type: "integer" + format: "int64" + - name: "quota" + in: "formData" + required: true + type: "integer" + format: "int64" + description: "New quota" + responses: + "200": + description: "successful operation" + schema: + $ref: "#/definitions/ApiResponse" + "400": + description: "Invalid parameter" + schema: + $ref: "#/definitions/ApiResponse" + "403": + description: "No access" + schema: + $ref: "#/definitions/ApiResponse" + "404": + description: "User not found" + schema: + $ref: "#/definitions/ApiResponse" + security: + - api_key: [] + /users/{id}/homefolder/{folderid}: + put: + tags: + - "user" + summary: "Change quota of user by ID" + description: "Change the quota of a single user" + operationId: "changeUserHomefolder" + produces: + - "application/json" + consumes: + - "application/x-www-form-urlencoded" + parameters: + - name: "id" + in: "path" + description: "ID of user" + required: true + type: "integer" + format: "int64" + - name: "folderid" + in: "path" + description: "ID of folder" + required: true + type: "integer" + format: "int64" + responses: + "200": + description: "successful operation" + schema: + $ref: "#/definitions/ApiResponse" + "400": + description: "Invalid parameter" + schema: + $ref: "#/definitions/ApiResponse" + "403": + description: "No access" + schema: + $ref: "#/definitions/ApiResponse" + "404": + description: "User or folder not found" + schema: + $ref: "#/definitions/ApiResponse" + security: + - api_key: [] /groups: get: tags: @@ -463,6 +549,161 @@ paths: $ref: "#/definitions/ApiResponse" security: - api_key: [] + /groups/{id}: + get: + tags: + - "group" + summary: "Find group by ID" + description: "Returns a single group" + operationId: "getGroupById" + produces: + - "application/json" + parameters: + - name: "id" + in: "path" + description: "ID of group to return" + required: true + type: "integer" + format: "int64" + responses: + "200": + description: "successful operation" + schema: + $ref: "#/definitions/ApiResponseUser" + "404": + description: "Group not found" + schema: + $ref: "#/definitions/ApiResponse" + security: + - api_key: [] + delete: + tags: + - "group" + summary: "Delete group by ID" + description: "Delete a single group" + operationId: "deleteGroupById" + produces: + - "application/json" + parameters: + - name: "id" + in: "path" + description: "ID of group to delete" + required: true + type: "integer" + format: "int64" + responses: + "200": + description: "successful operation" + schema: + $ref: "#/definitions/ApiResponse" + "500": + description: "Error deleting group" + schema: + $ref: "#/definitions/ApiResponse" + "403": + description: "No access" + schema: + $ref: "#/definitions/ApiResponse" + "404": + description: "Group not found" + schema: + $ref: "#/definitions/ApiResponse" + security: + - api_key: [] + /groups/{id}/addUser: + put: + tags: + - "group" + summary: "Add user to group" + description: "Adds an existing user as a new member of a group" + operationId: "addUserToGroup" + produces: + - "application/json" + consumes: + - "application/x-www-form-urlencoded" + parameters: + - name: "id" + in: "path" + description: "ID of group" + required: true + type: "integer" + format: "int64" + - name: "userid" + in: "formData" + description: "ID of user" + required: true + type: "integer" + format: "int64" + responses: + "200": + description: "successful operation" + schema: + $ref: "#/definitions/ApiResponse" + "400": + description: "Invalid parameter" + schema: + $ref: "#/definitions/ApiResponse" + "403": + description: "No access" + schema: + $ref: "#/definitions/ApiResponse" + "404": + description: "User or group not found" + schema: + $ref: "#/definitions/ApiResponse" + "500": + description: "Internal error" + schema: + $ref: "#/definitions/ApiResponse" + security: + - api_key: [] + /groups/{id}/removeUser: + put: + tags: + - "group" + summary: "Remove user from group" + description: "Remove a user as a new member of a group" + operationId: "removeUserToGroup" + produces: + - "application/json" + consumes: + - "application/x-www-form-urlencoded" + parameters: + - name: "id" + in: "path" + description: "ID of group" + required: true + type: "integer" + format: "int64" + - name: "userid" + in: "formData" + description: "ID of user" + required: true + type: "integer" + format: "int64" + responses: + "200": + description: "successful operation" + schema: + $ref: "#/definitions/ApiResponse" + "400": + description: "Invalid parameter" + schema: + $ref: "#/definitions/ApiResponse" + "403": + description: "No access" + schema: + $ref: "#/definitions/ApiResponse" + "404": + description: "User or group not found" + schema: + $ref: "#/definitions/ApiResponse" + "500": + description: "Internal error" + schema: + $ref: "#/definitions/ApiResponse" + security: + - api_key: [] /document/{id}: get: tags: @@ -1558,6 +1799,53 @@ paths: $ref: "#/definitions/ApiResponse" security: - api_key: [] + /folder/{id}/owner/{userid}: + post: + tags: + - "folder" + summary: "Set owner of folder" + description: "Set owner of folder" + operationId: "setFolderOwner" + produces: + - "application/json" + consumes: + - "application/x-www-form-urlencoded" + parameters: + - name: "id" + in: "path" + description: "ID of folder." + type: "integer" + required: true + format: "int64" + - name: "userid" + in: "path" + description: "ID of user." + type: "integer" + required: true + format: "int64" + responses: + "201": + description: "successful operation" + schema: + $ref: "#/definitions/ApiResponse" + "400": + description: "No folder or user given" + schema: + $ref: "#/definitions/ApiResponse" + "403": + description: "No access" + schema: + $ref: "#/definitions/ApiResponse" + "404": + description: "Folder not found" + schema: + $ref: "#/definitions/ApiResponse" + "500": + description: "Internal error" + schema: + $ref: "#/definitions/ApiResponse" + security: + - api_key: [] /categories: get: tags: From 4316b1afeeb2de6bb37cad3f4e099789354c4f52 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 31 Jan 2025 10:14:40 +0100 Subject: [PATCH 057/208] fix definition of echo endpoint --- restapi/swagger.yaml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/restapi/swagger.yaml b/restapi/swagger.yaml index 3eaf7fed9..5fc22fa8b 100644 --- a/restapi/swagger.yaml +++ b/restapi/swagger.yaml @@ -2071,15 +2071,21 @@ paths: description: "Invalid status value" security: - api_key: [] - /echo: + /echo/{data}: get: tags: - "misc" - summary: "Return what was send in the body" - description: "Just returns the body content" + summary: "Return what was send in the path" + description: "Just returns the path" operationId: "echoData" produces: - "application/json" + parameters: + - name: "data" + in: "path" + description: "Data to be echoed" + required: true + type: "string" responses: "200": description: "successful operation" From 325498e63a40e876fc8e9b7b5d385f7d08b83c06 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 09:52:10 +0100 Subject: [PATCH 058/208] fix evaluation of _ldapMailField --- inc/inc.ClassLdapAuthentication.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/inc.ClassLdapAuthentication.php b/inc/inc.ClassLdapAuthentication.php index 0f2ab27c1..7ca786a1b 100644 --- a/inc/inc.ClassLdapAuthentication.php +++ b/inc/inc.ClassLdapAuthentication.php @@ -29,12 +29,12 @@ class SeedDMS_LdapAuthentication extends SeedDMS_Authentication { var $settings; protected function addUser($username, $info) { - $mailfield = !empty($settings->_ldapMailField) ? $settings->_ldapMailField : 'mail'; + $mailfield = !empty($this->settings->_ldapMailField) ? $this->settings->_ldapMailField : 'mail'; return $this->dms->addUser($username, null, $info['cn'][0], isset($info[$mailfield]) ? $info[$mailfield][0] : '', $this->settings->_language, $this->settings->_theme, "User was added from LDAP"); } protected function updateUser($user, $info) { - $mailfield = !empty($settings->_ldapMailField) ? $settings->_ldapMailField : 'mail'; + $mailfield = !empty($this->settings->_ldapMailField) ? $this->settings->_ldapMailField : 'mail'; if(isset($info['cn'][0]) && ($info['cn'][0] != $user->getFullName())) { $user->setFullName($info['cn'][0]); } From ab729a3f21f8507a7df1d93c5bb135b18817b6c9 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 09:52:39 +0100 Subject: [PATCH 059/208] fix stringToArray() --- inc/inc.ClassSettings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/inc.ClassSettings.php b/inc/inc.ClassSettings.php index bc4a181b6..6b7c41303 100644 --- a/inc/inc.ClassSettings.php +++ b/inc/inc.ClassSettings.php @@ -452,7 +452,7 @@ class Settings { /* {{{ */ * */ function stringToArray($value) { /* {{{ */ - return explode(";", $Value); + return explode(";", $value); } /* }}} */ /** From 712df50a9c24ffe2be5b88807e2e5301f1dfc8ae Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 10:14:51 +0100 Subject: [PATCH 060/208] fix checking if user is already in list of notifiers (sendReplaceContentMail) --- inc/inc.ClassNotificationService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/inc.ClassNotificationService.php b/inc/inc.ClassNotificationService.php index 93de68c01..aed192af5 100644 --- a/inc/inc.ClassNotificationService.php +++ b/inc/inc.ClassNotificationService.php @@ -571,7 +571,7 @@ class SeedDMS_NotificationService { * the currently logged in user is not the * owner and the owner is not already in the list of notifiers. */ - if($user->getID() != $content->getUser()->getID() && $content->getUser()->getID() != $document->getOwner()->getID() && false === SeedDMS_Core_DMS::inList($content->getUser(), $nl['users'])) + if($user->getID() != $content->getUser()->getID() && $content->getUser()->getID() != $document->getOwner()->getID() && false === SeedDMS_Core_DMS::inList($content->getUser(), $notifyList['users'])) $this->toIndividual($user, $content->getUser(), $subject, $message, $params, SeedDMS_NotificationService::RECV_UPLOADER); } /* }}} */ From a6d67be34e2750c30556e7397379310f8809e1be Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 10:17:22 +0100 Subject: [PATCH 061/208] add class variable $_force_from --- inc/inc.ClassEmailNotify.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/inc/inc.ClassEmailNotify.php b/inc/inc.ClassEmailNotify.php index 8e870625d..798b91f5b 100644 --- a/inc/inc.ClassEmailNotify.php +++ b/inc/inc.ClassEmailNotify.php @@ -46,6 +46,8 @@ class SeedDMS_EmailNotify extends SeedDMS_Notify { protected $from_address; + protected $force_from; + protected $lazy_ssl; protected $debug; From 07d9047b2e0d39476fb7fddb54057ce22412161c Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 10:22:27 +0100 Subject: [PATCH 062/208] add class variables $filenames, $header, $extraheader --- inc/inc.ClassDownloadMgr.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/inc/inc.ClassDownloadMgr.php b/inc/inc.ClassDownloadMgr.php index 45b5f9edb..97b5020c3 100644 --- a/inc/inc.ClassDownloadMgr.php +++ b/inc/inc.ClassDownloadMgr.php @@ -45,6 +45,18 @@ class SeedDMS_Download_Mgr { */ protected $extracols; + /** + * @var array $header list of entries in header (first line) + * @access protected + */ + protected $header; + + /** + * @var array $extraheader list of extra entries in header + * @access protected + */ + protected $extraheader; + /** * @var array $rawcontents list of content used instead of document content * @access protected @@ -55,7 +67,7 @@ class SeedDMS_Download_Mgr { * @var array $filenames filename used in archive * @access protected */ - protected $filnames; + protected $filenames; function __construct($tmpdir = '') { $this->tmpdir = $tmpdir; @@ -64,6 +76,7 @@ class SeedDMS_Download_Mgr { $this->extracols = array(); $this->rawcontents = array(); $this->extraheader = array(); + $this->filenames = array(); } public function addHeader($extraheader) { /* {{{ */ From eb64f09375cf69f62073ff7544bc0fe2a22928b6 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 10:23:22 +0100 Subject: [PATCH 063/208] add class variable $user --- inc/inc.ClassCalendar.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/inc/inc.ClassCalendar.php b/inc/inc.ClassCalendar.php index 63face820..f81bc0ba3 100644 --- a/inc/inc.ClassCalendar.php +++ b/inc/inc.ClassCalendar.php @@ -33,6 +33,11 @@ class SeedDMS_Calendar { */ protected $db; + /** + * Instanz of user + */ + protected $user; + public function __construct($db, $user) { /* {{{ */ $this->db = $db; $this->user = $user; From 0abcfb4d1244597a3d1e5e74d73564185c601dca Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 10:27:35 +0100 Subject: [PATCH 064/208] remove trailing white space --- op/op.TransferDocument.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/op/op.TransferDocument.php b/op/op.TransferDocument.php index a5bd98337..f71b5380d 100644 --- a/op/op.TransferDocument.php +++ b/op/op.TransferDocument.php @@ -80,6 +80,3 @@ $session->setSplashMsg(array('type'=>'success', 'msg'=>getMLText('splash_transfe add_log_line("?documentid=".$documentid); header("Location:../out/out.ViewFolder.php?folderid=".$folder->getID()); - -?> - From c56d18299cbaa3a46f3b535ad8d0519df0adfae3 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 12:09:10 +0100 Subject: [PATCH 065/208] remove no longer needed method _printMessage() --- op/op.ChangePassword.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/op/op.ChangePassword.php b/op/op.ChangePassword.php index 9c386635e..ad711b4b2 100644 --- a/op/op.ChangePassword.php +++ b/op/op.ChangePassword.php @@ -28,16 +28,6 @@ include("../inc/inc.ClassSession.php"); include("../inc/inc.DBInit.php"); include("../inc/inc.ClassUI.php"); -function _printMessage($heading, $message) { - - UI::htmlStartPage($heading, "password"); - UI::globalBanner(); - UI::pageNavigation($heading); - UI::contentContainer($message."

" . getMLText("login") . "

\n"); - UI::htmlEndPage(); - return; -} - /* Check if the form data comes from a trusted request */ if(!checkFormKey('changepassword')) { UI::exitError(getMLText("folder_title", array("foldername" => getMLText("invalid_request_token"))),getMLText("invalid_request_token")); From 8cc6a417c846103b559c1e81e491e6d01d4f0af1 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 12:09:46 +0100 Subject: [PATCH 066/208] add class variables _smtpForceFrom and _smtpLazySSL --- inc/inc.ClassSettings.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/inc/inc.ClassSettings.php b/inc/inc.ClassSettings.php index 6b7c41303..01437f18e 100644 --- a/inc/inc.ClassSettings.php +++ b/inc/inc.ClassSettings.php @@ -348,6 +348,10 @@ class Settings { /* {{{ */ var $_smtpPort = null; // SMTP : send from var $_smtpSendFrom = null; + // SMTP : force send from + var $_smtpForceFrom = false; + // SMTP : allow self signed certificates + var $_smtpLazySSL = false; // SMTP : user var $_smtpUser = null; // SMTP : password From cd448c160b8b878d55474a67b69d1cd287577066 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 12:10:18 +0100 Subject: [PATCH 067/208] add visibility of methods --- inc/inc.ClassUI.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/inc/inc.ClassUI.php b/inc/inc.ClassUI.php index 4ef18e5a8..367b17386 100644 --- a/inc/inc.ClassUI.php +++ b/inc/inc.ClassUI.php @@ -44,7 +44,7 @@ class UI extends UI_Default { * @param array $params parameter passed to constructor of view class * @return object an object of a class implementing the view */ - static function factory($theme, $class='', $params=array()) { /* {{{ */ + static public function factory($theme, $class='', $params=array()) { /* {{{ */ global $settings, $session, $extMgr, $request, $logger, $notifier; if(!$class) { $class = 'Bootstrap'; @@ -174,7 +174,7 @@ class UI extends UI_Default { return null; } /* }}} */ - static function getStyles() { /* {{{ */ + static public function getStyles() { /* {{{ */ global $settings; $themes = array(); @@ -191,7 +191,7 @@ class UI extends UI_Default { return $themes; } /* }}} */ - static function exitError($pagetitle, $error, $noexit=false, $plain=false) { + static public function exitError($pagetitle, $error, $noexit=false, $plain=false) { global $theme, $dms, $user, $settings; $accessop = new SeedDMS_AccessOperation($dms, null, $user, $settings); $view = UI::factory($theme, 'ErrorDlg'); From e3b6c2f5b6c9d10fa4c59950e8c24a16ebd5d751 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 12:10:38 +0100 Subject: [PATCH 068/208] remove no longer needed function _printMessage() --- op/op.PasswordForgotten.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/op/op.PasswordForgotten.php b/op/op.PasswordForgotten.php index 03ae90ac0..a77341174 100644 --- a/op/op.PasswordForgotten.php +++ b/op/op.PasswordForgotten.php @@ -31,15 +31,6 @@ include("../inc/inc.ClassUI.php"); include $settings->_rootDir . "languages/" . $settings->_language . "/lang.inc"; -function _printMessage($heading, $message) { - UI::htmlStartPage($heading, "password"); - UI::globalBanner(); - UI::pageNavigation($heading); - UI::contentContainer($message."

" . getMLText("login") . "

\n"); - UI::htmlEndPage(); - return; -} - if (isset($_POST["email"])) { $email = $_POST["email"]; } @@ -68,5 +59,3 @@ if($user) { } header('Location: ../out/out.PasswordSend.php'); -exit; -?> From 6b325cb4dfc8f0bd92287c306a06bdb1b0989c3e Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 12:11:39 +0100 Subject: [PATCH 069/208] remove trailing white space --- op/op.AttributeMgr.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/op/op.AttributeMgr.php b/op/op.AttributeMgr.php index 8eccffc1d..e025ab38f 100644 --- a/op/op.AttributeMgr.php +++ b/op/op.AttributeMgr.php @@ -218,6 +218,3 @@ else if ($action == "removeattrvalue") { } header("Location:../out/out.AttributeMgr.php?attrdefid=".$attrdefid); - -?> - From a2804d252a46432160792a4bc208e7dfdc86d553 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 12:14:07 +0100 Subject: [PATCH 070/208] very old file which is no longer needed --- op/op.CreateSubFolderIndex.php | 114 --------------------------------- 1 file changed, 114 deletions(-) delete mode 100644 op/op.CreateSubFolderIndex.php diff --git a/op/op.CreateSubFolderIndex.php b/op/op.CreateSubFolderIndex.php deleted file mode 100644 index 1a58535e5..000000000 --- a/op/op.CreateSubFolderIndex.php +++ /dev/null @@ -1,114 +0,0 @@ -isAdmin()) { - UI::contentContainer("

Permission denied.

"); - UI::htmlPageEnd(); - exit; -} - -function getTime() { - if (function_exists('microtime')) { - $tm = microtime(); - $tm = explode(' ', $tm); - return (float) sprintf('%f', $tm[1] + $tm[0]); - } - return time(); -} - - -// ------------------------------------- Suche starten -------------------------------------------- - -UI::contentContainerStart(); - -$startTime = getTime(); -$results = array(); -//searchInFolder($startFolder); - -// -// Construct the SQL query that will be used to search the database. -// - -// Create the keyword search string. This search spans up to three columns -// in the database: keywords, name and comment. - -// -// The base query. -// -$searchQuery = "SELECT `tblDocuments`.* FROM `tblDocuments` "; - -// Send the search query to the database. -$resArr = $db->getResultArray($searchQuery); -// Assemble the results into an array of MyDMS Document objects. -if (!is_bool($resArr) && count($resArr)>0) { - echo "
    "; - foreach($resArr as $docArr) { - $doc = new SeedDMS_Core_Document($docArr["id"], - $docArr["name"], - $docArr["comment"], - $docArr["date"], - $docArr["expires"], - $docArr["owner"], - $docArr["folder"], - $docArr["inheritAccess"], - $docArr["defaultAccess"], - $docArr["lockUser"], - $docArr["keywords"], - $docArr["sequence"]); - // Make sure that the folder search path is also updated. - $folder = $doc->getFolder(); - $path = $folder->getPath(); - $flist = ""; - foreach ($path as $f) { - $flist .= ":".$f->getID(); - } - if (strlen($flist)>1) { - $flist .= ":"; - } - $queryStr = "UPDATE tblDocuments SET folderList = '" . $flist . "' WHERE id = ". $doc->getID(); - $db->getResult($queryStr); - echo "
  1. Updating docID '".$doc->getID()."' -- '".$flist."'
  2. "; - } - echo "
"; -} - -$searchTime = getTime() - $startTime; -$searchTime = round($searchTime, 2); -echo "

"; -printMLText("search_time", array("time" => $searchTime)); - -UI::contentContainerEnd(); -UI::htmlEndPage(); -?> From b45bfc6035948761a1f8ad79594939f3d47c295c Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 12:18:15 +0100 Subject: [PATCH 071/208] add comment with info why seeddms core is still explicitly included --- inc/inc.Init.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/inc/inc.Init.php b/inc/inc.Init.php index 4df107c9d..66a569d06 100644 --- a/inc/inc.Init.php +++ b/inc/inc.Init.php @@ -32,6 +32,10 @@ use Symfony\Component\HttpFoundation\Request; +/* Actually not needed anymore, but some old extension may still use + * S_RELEASED, S_REJECTED, etc. from SeedDMS_Core_Document. So we keep + * it for a while. Should be removed von 6.0.31 and 5.1.38 is released. + */ if (!empty($settings->_coreDir)) { require_once $settings->_coreDir . '/Core.php'; } else { From 665deb059571744600fdc24bce0e809fa0d96d86 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 14:43:08 +0100 Subject: [PATCH 072/208] update translation --- languages/ar_EG/lang.inc | 11 +++++++++++ languages/bg_BG/lang.inc | 11 +++++++++++ languages/ca_ES/lang.inc | 11 +++++++++++ languages/cs_CZ/lang.inc | 11 +++++++++++ languages/de_DE/lang.inc | 13 ++++++++++++- languages/el_GR/lang.inc | 11 +++++++++++ languages/en_GB/lang.inc | 13 ++++++++++++- languages/es_ES/lang.inc | 11 +++++++++++ languages/fr_FR/lang.inc | 11 +++++++++++ languages/hr_HR/lang.inc | 11 +++++++++++ languages/hu_HU/lang.inc | 11 +++++++++++ languages/id_ID/lang.inc | 11 +++++++++++ languages/it_IT/lang.inc | 11 +++++++++++ languages/ko_KR/lang.inc | 11 +++++++++++ languages/lo_LA/lang.inc | 11 +++++++++++ languages/nb_NO/lang.inc | 11 +++++++++++ languages/nl_NL/lang.inc | 11 +++++++++++ languages/pl_PL/lang.inc | 11 +++++++++++ languages/pt_BR/lang.inc | 11 +++++++++++ languages/ro_RO/lang.inc | 11 +++++++++++ languages/ru_RU/lang.inc | 11 +++++++++++ languages/sk_SK/lang.inc | 11 +++++++++++ languages/sv_SE/lang.inc | 11 +++++++++++ languages/tr_TR/lang.inc | 11 +++++++++++ languages/uk_UA/lang.inc | 11 +++++++++++ languages/zh_CN/lang.inc | 11 +++++++++++ languages/zh_TW/lang.inc | 11 +++++++++++ 27 files changed, 299 insertions(+), 2 deletions(-) diff --git a/languages/ar_EG/lang.inc b/languages/ar_EG/lang.inc index f39d21d80..c3b7cad5e 100644 --- a/languages/ar_EG/lang.inc +++ b/languages/ar_EG/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => 'توثيق ذو عاملين', +'2_factor_auth_code' => '', '2_factor_auth_info' => 'معلومات عن توثيق ذو عاملين', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -553,6 +554,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1282,6 +1285,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: [name] - تم ازالة مسار العمل من اصدار المستند', 'removeFolderFromDropFolder' => 'إزالة مجلد من إسقاط لائحة', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'ازالة الملفات المختارة', 'remove_review_log' => '', @@ -1464,6 +1468,7 @@ URL: [url]', 'select_category' => 'اضغط لاختيار قسم', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'اختيار مجموعة', 'select_groups' => 'اضغط لاختيار مجموعة', 'select_grp_approvers' => 'اضغط لاختيار مجموعة الموافقون', @@ -1511,7 +1516,9 @@ URL: [url]', 'service_name' => '', 'sessions' => 'صفوف', 'setDateFromFile' => 'وضع تاريخ من الملف', +'setDateFromFile_desc' => '', 'setDateFromFolder' => 'تحديد التاريخ من المجلد', +'setDateFromFolder_desc' => '', 'settings' => 'الإعدادات', 'settings_activate_module' => 'Activate module', 'settings_activate_php_extension' => 'Activate PHP extension', @@ -1609,6 +1616,8 @@ URL: [url]', 'settings_delete_install_folder' => 'مسح مثبت المجلد', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'تعطيل التحرير الذاتي', 'settings_disableSelfEdit_desc' => 'تعطيل التحرير الذاتي', 'settings_disable_install' => 'تعطيل التثبيت', @@ -1733,6 +1742,8 @@ URL: [url]', 'settings_encryptionKey' => 'مفتاح التشفير', 'settings_encryptionKey_desc' => 'مفتاح التشفير', 'settings_error' => 'خطأ', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'قم بتوسيع شجرة المجلد', 'settings_expandFolderTree_desc' => 'قم بتوسيع شجرة المجلد', 'settings_expandFolderTree_val0' => 'قم بتوسيع شجرة المجلد قيمة0', diff --git a/languages/bg_BG/lang.inc b/languages/bg_BG/lang.inc index f911b0e82..3b9d0dc6c 100644 --- a/languages/bg_BG/lang.inc +++ b/languages/bg_BG/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => '', +'2_factor_auth_code' => '', '2_factor_auth_info' => '', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -491,6 +492,8 @@ $text = array( 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1151,6 +1154,7 @@ $text = array( 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '', 'removeFolderFromDropFolder' => '', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => '', 'remove_review_log' => '', @@ -1306,6 +1310,7 @@ $text = array( 'select_category' => 'Изберете категория', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => '', 'select_groups' => 'Кликни да избереш групи', 'select_grp_approvers' => 'Кликни да избереш група утвърждаващи', @@ -1353,7 +1358,9 @@ $text = array( 'service_name' => '', 'sessions' => '', 'setDateFromFile' => '', +'setDateFromFile_desc' => '', 'setDateFromFolder' => '', +'setDateFromFolder_desc' => '', 'settings' => 'Настройки', 'settings_activate_module' => 'Активирай модул', 'settings_activate_php_extension' => 'Активирай разширение на PHP', @@ -1451,6 +1458,8 @@ $text = array( 'settings_delete_install_folder' => 'Изтрийте ENABLE_INSTALL_TOOL в папка конфигурация, за да започнете да използвате системата', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Изключи собствено редактиране', 'settings_disableSelfEdit_desc' => 'Ако е включено, потребителите няма да могат да редактират своята информация', 'settings_disable_install' => 'Изтрийте ENABLE_INSTALL_TOOL ако е возможно', @@ -1575,6 +1584,8 @@ $text = array( 'settings_encryptionKey' => 'Кодиращ ключ', 'settings_encryptionKey_desc' => 'Този стринг се използва за създаване на уникален идентификатор, който добавен като невидимо поле към формуляр, предотвратява CSRF атаки.', 'settings_error' => 'Грешка', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Разгърни дървото с папките', 'settings_expandFolderTree_desc' => 'Разгръщане на дървото с папките', 'settings_expandFolderTree_val0' => 'започвайки от сгънато дърво', diff --git a/languages/ca_ES/lang.inc b/languages/ca_ES/lang.inc index 0dcb534e3..24130159a 100644 --- a/languages/ca_ES/lang.inc +++ b/languages/ca_ES/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => '', +'2_factor_auth_code' => '', '2_factor_auth_info' => '', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -496,6 +497,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1156,6 +1159,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '', 'removeFolderFromDropFolder' => 'Esborrar carpeta després de la importació', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => '', 'remove_review_log' => '', @@ -1311,6 +1315,7 @@ URL: [url]', 'select_category' => 'Prem per seleccionar la categoria', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Seleccionar grup', 'select_groups' => '', 'select_grp_approvers' => '', @@ -1358,7 +1363,9 @@ URL: [url]', 'service_name' => '', 'sessions' => '', 'setDateFromFile' => '', +'setDateFromFile_desc' => '', 'setDateFromFolder' => '', +'setDateFromFolder_desc' => '', 'settings' => 'Settings', 'settings_activate_module' => 'Activate module', 'settings_activate_php_extension' => 'Activate PHP extension', @@ -1456,6 +1463,8 @@ URL: [url]', 'settings_delete_install_folder' => '', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => '', 'settings_disableSelfEdit_desc' => '', 'settings_disable_install' => '', @@ -1580,6 +1589,8 @@ URL: [url]', 'settings_encryptionKey' => '', 'settings_encryptionKey_desc' => '', 'settings_error' => 'Error', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => '', 'settings_expandFolderTree_desc' => '', 'settings_expandFolderTree_val0' => '', diff --git a/languages/cs_CZ/lang.inc b/languages/cs_CZ/lang.inc index 4c393dada..cf9fc6807 100644 --- a/languages/cs_CZ/lang.inc +++ b/languages/cs_CZ/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => 'dvoufaktorové ověření', +'2_factor_auth_code' => '', '2_factor_auth_info' => 'Tento systém vyžaduje dvoufaktorové ověření. Na svém mobilním telefonu budete potřebovat Google Authenticator. Níže vidíte dva QR kódy. Správný je vaše současné tajemství. Vlevo můžete nastavit nové tajemství. Pokud nastavíte nové tajemství, ujistěte se, že jste jej znovu otestovali pomocí služby Google Authenticator.', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -577,6 +578,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1328,6 +1331,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: [name] - Odstraněno workflow z verze dokumentu', 'removeFolderFromDropFolder' => 'Odstranit složku po nahrání', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'Odstranit označené soubory', 'remove_review_log' => '', @@ -1531,6 +1535,7 @@ URL: [url]', 'select_category' => 'Kliknutím vybrat kategorii', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Vybrat skupinu', 'select_groups' => 'Kliknutím vybrat skupiny', 'select_grp_approvers' => 'Kliknutím vybrat skupinu schvalovatele', @@ -1583,7 +1588,9 @@ Jméno: [username] 'service_name' => '', 'sessions' => 'seance', 'setDateFromFile' => '', +'setDateFromFile_desc' => '', 'setDateFromFolder' => '', +'setDateFromFolder_desc' => '', 'settings' => 'Nastavení', 'settings_activate_module' => 'Aktivovat modul', 'settings_activate_php_extension' => 'Aktivovat PHP extension', @@ -1681,6 +1688,8 @@ Jméno: [username] 'settings_delete_install_folder' => 'Chcete-li použít SeedDMS, musíte v konfiguračním adresáři odstranit soubor ENABLE_INSTALL_TOOL', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Zakázat vlastní úpravy', 'settings_disableSelfEdit_desc' => 'Je-li zaškrtnuto, uživatel nemůže upravit svůj vlastní profil', 'settings_disable_install' => 'Pokud je to možné, smažte soubor ENABLE_INSTALL_TOOL', @@ -1805,6 +1814,8 @@ Jméno: [username] 'settings_encryptionKey' => 'Šifrovací klíč', 'settings_encryptionKey_desc' => 'Tento řetězec se používá k vytvoření jedinečného identifikátoru, který je přidán jako skryté pole formuláře, aby se zabránilo útokům CSRF.', 'settings_error' => 'Chyba', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Rozbalit strom složek', 'settings_expandFolderTree_desc' => 'Rozbalení stromu složek', 'settings_expandFolderTree_val0' => 'začít se skrytým stromem', diff --git a/languages/de_DE/lang.inc b/languages/de_DE/lang.inc index f6ce149df..aefc52c49 100644 --- a/languages/de_DE/lang.inc +++ b/languages/de_DE/lang.inc @@ -19,10 +19,11 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (3418), dgrutsch (22) +// Translators: Admin (3429), dgrutsch (22) $text = array( '2_factor_auth' => '2-Faktor Authentifizierung', +'2_factor_auth_code' => '2ter Faktor', '2_factor_auth_info' => 'Dieses System erfordert 2-Faktor-Authentifikation. Dazu brauchen Sie einen Authenticator auf Ihrem Mobiltelefon. Unten sehen Sie zwei QR-Codes. Der rechte Code beinhaltet Ihren aktuellen geheimen Schlüssel. Auf der linken Seite wird ein neuer Schlüssel angezeigt. Wenn Sie den neuen Schlüssel speichern, dann stellen Sie zuvor sicher, dass sie ihn mit Ihrem bevorzugten Authenticator (z.B. andOTP) zuvor eingescant haben.', '2_fact_auth_current_secret' => 'Aktuelles Geheimnis', '2_fact_auth_new_secret' => 'Neues Geheimnis', @@ -711,6 +712,8 @@ URL: [url]

', 'download_header_document_name' => 'Dokumentenname', 'download_header_document_no' => 'Dokumenten-Nr.', 'download_header_filename' => 'Dateiname', +'download_header_folder_name' => 'Ordnername', +'download_header_folder_no' => 'Ordner-ID', 'download_header_internal_version' => 'Int. Version', 'download_header_reviewer' => 'Prüfer', 'download_header_review_comment' => 'Prüfkommentar', @@ -1617,6 +1620,7 @@ Benutzer: [username]
URL: [url]

', 'removed_workflow_email_subject' => '[sitename]: [name] - Workflow von Dokumentenversion', 'removeFolderFromDropFolder' => 'Ordner nach Import entfernen', +'removeFolderFromDropFolder_desc' => 'Schalten Sie dies ein, um den importierten Ordner im Ablageordner auf der Festplatte zu löschen.', 'remove_approval_log' => 'Einzelne Freigabe entfernen', 'remove_marked_files' => 'Markierte Dateien löschen', 'remove_review_log' => 'Einzelne Prüfung entfernen', @@ -1920,6 +1924,7 @@ URL: [url]

', 'select_category' => 'Klicken zur Auswahl einer Kategorie', 'select_created' => 'Klicken zur Auswahl des Erstellungsdatums', 'select_documents_for_process' => 'Dokumente auswählen', +'select_folder' => 'Ordner auswählen', 'select_group' => 'Gruppe auswählen', 'select_groups' => 'Klicken zur Auswahl einer Gruppe', 'select_grp_approvers' => 'Klicken zur Auswahl einer Freigabegruppe', @@ -1974,7 +1979,9 @@ Sollten Sie kein Passwort bekommen haben, dann nutzen Sie bitte die Passwort-Ver 'service_name' => 'Service-Name', 'sessions' => 'Benutzer Online', 'setDateFromFile' => 'Datum von importierter Datei übernehmen', +'setDateFromFile_desc' => 'Übernimmt das Datum der zu importierenden Datei als Datum des Dokuments in SeedDMS', 'setDateFromFolder' => 'Datum von importierten Verzeichnis übernehmen', +'setDateFromFolder_desc' => 'Übernimmt das Datum des zu importierenden Ordners als Datum des Ordners in SeedDMS', 'settings' => 'Einstellungen', 'settings_activate_module' => 'Modul aktivieren', 'settings_activate_php_extension' => 'PHP-Erweiterung aktivieren', @@ -2072,6 +2079,8 @@ Sollten Sie kein Passwort bekommen haben, dann nutzen Sie bitte die Passwort-Ver 'settings_delete_install_folder' => 'Um SeedDMS nutzen zu können, müssen Sie die Datei ENABLE_INSTALL_TOOL aus dem Konfigurationsverzeichnis löschen.', 'settings_disableChangePassword' => 'Kein Ändern des eigenen Passworts', 'settings_disableChangePassword_desc' => 'Anwählen, um das Ändern des eigenen Passworts zu unterbinden. Schalten Sie dies ein, wenn LDAP-Authentifizierung verwendet wird. Es verhindert, dass Benutzer ein Passwort in der Datenbank setzen und damit die LDAP-Authentifizierung umgehen.', +'settings_disableReceiptComment' => 'Kommentar für Empfangsbestätigung ausschalten', +'settings_disableReceiptComment_desc' => 'Wenn Sie dies einschalten wird bei der Empfangsbestätigung kein Kommentar abgefragt.', 'settings_disableSelfEdit' => 'Kein Ändern des eigenen Profils', 'settings_disableSelfEdit_desc' => 'Anwählen, um das Ändern des eigenen Profiles zu verhindern.', 'settings_disable_install' => 'Lösche ENABLE_INSTALL_TOOL wenn möglich', @@ -2196,6 +2205,8 @@ Sollten Sie kein Passwort bekommen haben, dann nutzen Sie bitte die Passwort-Ver 'settings_encryptionKey' => 'Verschlüsselungs-Sequenz', 'settings_encryptionKey_desc' => 'Diese Zeichenkette wird verwendet um eine eindeutige Kennung zu erzeugen, die als verstecktes Feld in einem Formular untergebracht wird. Sie dient zur Verhinderung von CSRF-Attacken.', 'settings_error' => 'Fehler', +'settings_excludeFoldersDashboard' => 'Ordner nicht für das Dashboard berücksichtigen', +'settings_excludeFoldersDashboard_desc' => 'Diese Ordner werden bei der Ausgabe der Dokumente auf dem Dashboard nicht berücksichtigt. Das kann z.B. für archivierte Dokumente oder Dokumente im Mülleimer sinnvoll sein.', 'settings_expandFolderTree' => 'Dokumenten-Baum', 'settings_expandFolderTree_desc' => 'Auswählen, wie der Dokumenten-Baum nach der Anmeldung angezeigt wird.', 'settings_expandFolderTree_val0' => 'versteckt', diff --git a/languages/el_GR/lang.inc b/languages/el_GR/lang.inc index ab6d39068..d91e033b2 100644 --- a/languages/el_GR/lang.inc +++ b/languages/el_GR/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => '', +'2_factor_auth_code' => '', '2_factor_auth_info' => '', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -491,6 +492,8 @@ $text = array( 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1162,6 +1165,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '', 'removeFolderFromDropFolder' => '', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => '', 'remove_review_log' => '', @@ -1317,6 +1321,7 @@ URL: [url]', 'select_category' => 'Επιλογή κατηγορίας', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Επιλογή ομάδας', 'select_groups' => '', 'select_grp_approvers' => '', @@ -1364,7 +1369,9 @@ URL: [url]', 'service_name' => '', 'sessions' => '', 'setDateFromFile' => '', +'setDateFromFile_desc' => '', 'setDateFromFolder' => '', +'setDateFromFolder_desc' => '', 'settings' => 'Ρυθμίσεις', 'settings_activate_module' => '', 'settings_activate_php_extension' => '', @@ -1462,6 +1469,8 @@ URL: [url]', 'settings_delete_install_folder' => '', 'settings_disableChangePassword' => 'Disable changing password', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => '', 'settings_disableSelfEdit_desc' => '', 'settings_disable_install' => '', @@ -1586,6 +1595,8 @@ URL: [url]', 'settings_encryptionKey' => '', 'settings_encryptionKey_desc' => '', 'settings_error' => '', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => '', 'settings_expandFolderTree_desc' => '', 'settings_expandFolderTree_val0' => '', diff --git a/languages/en_GB/lang.inc b/languages/en_GB/lang.inc index 2a0a078ab..4bcb98fa2 100644 --- a/languages/en_GB/lang.inc +++ b/languages/en_GB/lang.inc @@ -19,10 +19,11 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (2517), archonwang (3), dgrutsch (9), netixw (14) +// Translators: Admin (2528), archonwang (3), dgrutsch (9), netixw (14) $text = array( '2_factor_auth' => '2-factor authentication', +'2_factor_auth_code' => '2nd factor', '2_factor_auth_info' => 'This system enforces 2 factor authentication. You will need an Authenticator on your mobile phone. Below you see two QR codes. The right one is your current secret. On the left you can set a new secret. If you set a new secret make sure to rescan it with your preffered authenticator, e.g. andOTP.', '2_fact_auth_current_secret' => 'Current secret', '2_fact_auth_new_secret' => 'New secret', @@ -711,6 +712,8 @@ URL: [url]

', 'download_header_document_name' => 'Document name', 'download_header_document_no' => 'Document no', 'download_header_filename' => 'File name', +'download_header_folder_name' => 'Folder name', +'download_header_folder_no' => 'Folder no.', 'download_header_internal_version' => 'Int. version', 'download_header_reviewer' => 'Reviewer', 'download_header_review_comment' => 'Review comment', @@ -1619,6 +1622,7 @@ User: [username]
URL: [url]

', 'removed_workflow_email_subject' => '[sitename]: [name] - Removed workflow from document version', 'removeFolderFromDropFolder' => 'Remove folder after import', +'removeFolderFromDropFolder_desc' => 'Enable this if you want the folder which was imported to be removed from the drop folder.', 'remove_approval_log' => 'Remove approval', 'remove_marked_files' => 'Remove marked files', 'remove_review_log' => 'Remove review', @@ -1922,6 +1926,7 @@ URL: [url]

', 'select_category' => 'Click to select category', 'select_created' => 'Click to select date of creation', 'select_documents_for_process' => 'Select documents', +'select_folder' => 'Select folder', 'select_group' => 'Select group', 'select_groups' => 'Click to select groups', 'select_grp_approvers' => 'Click to select group approver', @@ -1976,7 +1981,9 @@ If you did not receive a password, please use the password forgotten function on 'service_name' => 'Name of service', 'sessions' => 'Users online', 'setDateFromFile' => 'Take over date from imported file', +'setDateFromFile_desc' => 'Take over the date of the imported file as the date of the document in SeedDMS', 'setDateFromFolder' => 'Take over date from imported folder', +'setDateFromFolder_desc' => 'Take over the date of the imported directory as the date of the folder in SeedDMS', 'settings' => 'Settings', 'settings_activate_module' => 'Activate module', 'settings_activate_php_extension' => 'Activate PHP extension', @@ -2074,6 +2081,8 @@ If you did not receive a password, please use the password forgotten function on 'settings_delete_install_folder' => 'In order to use SeedDMS, you must delete the file ENABLE_INSTALL_TOOL in the configuration directory', 'settings_disableChangePassword' => 'Disallow changing own password', 'settings_disableChangePassword_desc' => 'If checked the user cannot change his/her password. Turn this on if LDAP authentication is used. It prevents setting a database password and circumvent LDAP authentication.', +'settings_disableReceiptComment' => 'Disable comment for reception', +'settings_disableReceiptComment_desc' => 'Turning this on will disable comments for receptions.', 'settings_disableSelfEdit' => 'Disable Self Edit', 'settings_disableSelfEdit_desc' => 'If checked user cannot edit his own profile', 'settings_disable_install' => 'Delete file ENABLE_INSTALL_TOOL if possible', @@ -2198,6 +2207,8 @@ If you did not receive a password, please use the password forgotten function on 'settings_encryptionKey' => 'Encryption key', 'settings_encryptionKey_desc' => 'This string is used for creating a unique identifier being added as a hidden field to a form in order to prevent CSRF attacks.', 'settings_error' => 'Error', +'settings_excludeFoldersDashboard' => 'Exclude folders from dashboard', +'settings_excludeFoldersDashboard_desc' => 'This folders will not be checked for documents shown on the dashboard. This can be useful for archived documents or documents in the trash.', 'settings_expandFolderTree' => 'Expand Folder Tree', 'settings_expandFolderTree_desc' => 'Expand Folder Tree', 'settings_expandFolderTree_val0' => 'start with tree hidden', diff --git a/languages/es_ES/lang.inc b/languages/es_ES/lang.inc index 3bb397c6b..3e0b3ce16 100644 --- a/languages/es_ES/lang.inc +++ b/languages/es_ES/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => 'Autenticación de doble factor', +'2_factor_auth_code' => '', '2_factor_auth_info' => '', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -566,6 +567,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1305,6 +1308,7 @@ nURL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: [name] - Eliminar flujo de trabajo de la versión del documento', 'removeFolderFromDropFolder' => 'Eliminar carpeta después de importar', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'Eliminar ficheros marcados', 'remove_review_log' => '', @@ -1487,6 +1491,7 @@ URL: [url]', 'select_category' => 'Haga Click para seleccionar categoría', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Seleccionar Grupo', 'select_groups' => 'Haga Click para seleccionar grupos', 'select_grp_approvers' => 'Haga Click para seleccionar grupo de aprobadores', @@ -1534,7 +1539,9 @@ URL: [url]', 'service_name' => '', 'sessions' => '', 'setDateFromFile' => 'Obtiene la fecha del archivo importado', +'setDateFromFile_desc' => '', 'setDateFromFolder' => 'Obtiene la fecha de la carpeta importada', +'setDateFromFolder_desc' => '', 'settings' => 'Configuración', 'settings_activate_module' => 'Activar módulo', 'settings_activate_php_extension' => 'Activar extensión PHP', @@ -1632,6 +1639,8 @@ URL: [url]', 'settings_delete_install_folder' => 'Para utilizar SeedDMS, debe eliminar el archivo ENABLE_INSTALL_TOOL de la carpeta de configuración', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Deshabilitar autoedición', 'settings_disableSelfEdit_desc' => 'Si está seleccionado el usuario no podrá editar su propio perfil', 'settings_disable_install' => 'Eliminar el archivo ENABLE_INSTALL_TOOL se es posible', @@ -1756,6 +1765,8 @@ URL: [url]', 'settings_encryptionKey' => 'Clave de cifrado', 'settings_encryptionKey_desc' => 'Esta cadena se utiliza para crear un identificador único añadido como campo oculto a formularios para prevenir ataques CSRF.', 'settings_error' => 'Error', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Expandir árbol de carpetas', 'settings_expandFolderTree_desc' => 'Expandir árbol de carpetas', 'settings_expandFolderTree_val0' => 'Comenzar con el árbol oculto', diff --git a/languages/fr_FR/lang.inc b/languages/fr_FR/lang.inc index 6e8b56642..36e6c0328 100644 --- a/languages/fr_FR/lang.inc +++ b/languages/fr_FR/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => 'Authentification forte', +'2_factor_auth_code' => '', '2_factor_auth_info' => 'Ce système requiert une authentification à deux facteurs. Cela nécessite l’installation de Google Authenticator sur votre téléphone mobile. Ci-dessous sont visibles deux QR codes. Celui de droite correspond à votre clé secrète actuelle. Celui de gauche permet de définir une nouvelle clé secrète. Lorsque vous définissez une nouvelle clé secrète, assurez-vous de la scanner avec Google Authenticator.', '2_fact_auth_current_secret' => 'Clé secrète actuelle', '2_fact_auth_new_secret' => 'Nouvelle clé secrète', @@ -681,6 +682,8 @@ URL : [url]

', 'download_header_document_name' => 'Nom du document', 'download_header_document_no' => 'N° du document', 'download_header_filename' => 'Nom du fichier', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => 'Version interne', 'download_header_reviewer' => 'Examinateur', 'download_header_review_comment' => 'Commentaire de vérification', @@ -1572,6 +1575,7 @@ Utilisateur : [username]
URL : [url]

', 'removed_workflow_email_subject' => '[sitename] : [name] - Workflow retiré de la version du doument', 'removeFolderFromDropFolder' => 'Suppression du dossier après importation', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => 'Approbation retirée', 'remove_marked_files' => 'Supprimer les fichiers sélectionnés', 'remove_review_log' => 'Vérification retirée', @@ -1869,6 +1873,7 @@ URL : [url]

', 'select_category' => 'Cliquer pour choisir une catégorie', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Sélectionner un groupe', 'select_groups' => 'Cliquer pour choisir un groupe', 'select_grp_approvers' => 'Cliquer pour choisir un groupe d\'approbateur', @@ -1921,7 +1926,9 @@ Nom : [username] 'service_name' => '', 'sessions' => 'Utilisateurs en ligne', 'setDateFromFile' => 'Reprendre la date du fichier importé', +'setDateFromFile_desc' => '', 'setDateFromFolder' => 'Reprendre la date du dossier importé', +'setDateFromFolder_desc' => '', 'settings' => 'Configuration', 'settings_activate_module' => 'Activez le module', 'settings_activate_php_extension' => 'Activez l\'extension PHP', @@ -2019,6 +2026,8 @@ Nom : [username] 'settings_delete_install_folder' => 'Pour utiliser SeedDMS, vous devez supprimer le fichier ENABLE_INSTALL_TOOL dans le répertoire de configuration', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Désactiver auto modification', 'settings_disableSelfEdit_desc' => 'Si coché, l\'utilisateur ne peut pas éditer son profil', 'settings_disable_install' => 'Si possible, supprimer le fichier ENABLE_INSTALL_TOOL', @@ -2143,6 +2152,8 @@ Nom : [username] 'settings_encryptionKey' => 'Clé de cryptage', 'settings_encryptionKey_desc' => 'Cette chaîne est utilisée pour créer un identifiant unique étant ajouté comme champ masqué à un formulaire afin de prévenir des attaques CSRF.', 'settings_error' => 'Erreur', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Dérouler l\'arborescence des dossiers', 'settings_expandFolderTree_desc' => 'Dérouler l\'arborescence des dossiers', 'settings_expandFolderTree_val0' => 'Démarrer avec l\'arborescence cachée', diff --git a/languages/hr_HR/lang.inc b/languages/hr_HR/lang.inc index d560fae41..4b63b9d31 100644 --- a/languages/hr_HR/lang.inc +++ b/languages/hr_HR/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => '2-faktorska autentikacija', +'2_factor_auth_code' => '', '2_factor_auth_info' => '', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -565,6 +566,8 @@ Internet poveznica: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1301,6 +1304,7 @@ Internet poveznica: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: [name] - Uklonjeni tok rada iz ove verzije dokumenta', 'removeFolderFromDropFolder' => '', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'Ukloni označene datoteke', 'remove_review_log' => '', @@ -1500,6 +1504,7 @@ Internet poveznica: [url]', 'select_category' => 'Kliknite za odabir kategorije', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Izaberi grupu', 'select_groups' => 'Kliknite za odabir grupa', 'select_grp_approvers' => 'Kliknite za odabir validatora grupe', @@ -1547,7 +1552,9 @@ Internet poveznica: [url]', 'service_name' => '', 'sessions' => '', 'setDateFromFile' => '', +'setDateFromFile_desc' => '', 'setDateFromFolder' => '', +'setDateFromFolder_desc' => '', 'settings' => 'Postavke', 'settings_activate_module' => 'Aktiviraj modul', 'settings_activate_php_extension' => 'Aktiviraj PHP ekstenziju', @@ -1645,6 +1652,8 @@ Internet poveznica: [url]', 'settings_delete_install_folder' => 'Da bi koristili ProsperaDMS, morate izbrisati datoteku ENABLE_INSTALL_TOOL u mapi konfiguracije', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Onemogućite samostalno uređivanje', 'settings_disableSelfEdit_desc' => 'Ako je označeno, korisnik ne može uređivati svoj vlastiti profil', 'settings_disable_install' => 'Ako je moguće, izbrišite datoteku ENABLE_INSTALL_TOOL', @@ -1769,6 +1778,8 @@ Internet poveznica: [url]', 'settings_encryptionKey' => 'Ključ za šifriranje', 'settings_encryptionKey_desc' => 'Ovaj string se koristi za izradu jedinstvenog identifikatora koji će biti dodan kao skriveno polje u formularu kako bi se spriječili CSRF napadi.', 'settings_error' => 'Greška', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Proširi stablo mape', 'settings_expandFolderTree_desc' => 'Proširi stablo mape', 'settings_expandFolderTree_val0' => 'započni sa skrivenim stablom', diff --git a/languages/hu_HU/lang.inc b/languages/hu_HU/lang.inc index 628b2c6fa..e06e181ee 100644 --- a/languages/hu_HU/lang.inc +++ b/languages/hu_HU/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => 'Kétfaktoros azonosítás', +'2_factor_auth_code' => '', '2_factor_auth_info' => 'A rendszernek két faktoros hitelesítése van. Szükséged lesz a Google Authenticator-ra a mobil telefonodon. Lejebb látható két QR kód. A jobb oldali a saját jelszavát, a baloldali egy új titkos jelszót tartalmaz. Ha új jelszót szeretne beállítani, szkennelje be újra a Goolge Authenticator-al.', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -560,6 +561,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1296,6 +1299,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: [name] - Dokumentum változatból eltávolított munkafolyamat', 'removeFolderFromDropFolder' => '', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'Megjelölt állományok eltávolítása', 'remove_review_log' => '', @@ -1477,6 +1481,7 @@ URL: [url]', 'select_category' => 'Kattintson a kategória kiválasztásához', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Csoport kiválasztása', 'select_groups' => 'Kattintson a csoportok kijelöléséhez', 'select_grp_approvers' => 'Kattintson a csoport jóváhagyó kijelöléséhez', @@ -1524,7 +1529,9 @@ URL: [url]', 'service_name' => '', 'sessions' => '', 'setDateFromFile' => '', +'setDateFromFile_desc' => '', 'setDateFromFolder' => '', +'setDateFromFolder_desc' => '', 'settings' => 'Beállítások', 'settings_activate_module' => 'Modul aktiválása', 'settings_activate_php_extension' => 'PHP kiterjesztés aktiválása', @@ -1622,6 +1629,8 @@ URL: [url]', 'settings_delete_install_folder' => 'A SeedDMS használatához törölnie kell a konfigurációs könyvtárban található ENABLE_INSTALL_TOOL állományt.', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Saját adatok szerkesztésének tiltása', 'settings_disableSelfEdit_desc' => 'Ha be van jelölve a felhasználó nem szerkesztheti saját profilját', 'settings_disable_install' => 'Törölje az ENABLE_INSTALL_TOOL állományt, ha lehetséges', @@ -1746,6 +1755,8 @@ URL: [url]', 'settings_encryptionKey' => 'Titkosító kulcs', 'settings_encryptionKey_desc' => 'Ez a karaktersorozat használható egyedi azonosító létrehozásához amely rejtett mezőként lesz hozzáadva az űrlapokhoz a CSRF támadások megelőzésére.', 'settings_error' => 'Hiba', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Mappa fastruktúra kibontása', 'settings_expandFolderTree_desc' => 'Mappa fastruktúra kibontása', 'settings_expandFolderTree_val0' => 'indulás rejtett fastruktúrával', diff --git a/languages/id_ID/lang.inc b/languages/id_ID/lang.inc index d5a5e4a59..31a9a6c22 100644 --- a/languages/id_ID/lang.inc +++ b/languages/id_ID/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => '', +'2_factor_auth_code' => '', '2_factor_auth_info' => '', '2_fact_auth_current_secret' => 'Kunci rahasi saat ini', '2_fact_auth_new_secret' => '', @@ -615,6 +616,8 @@ URL: [url]

', 'download_header_document_name' => 'Nama dokumen', 'download_header_document_no' => 'Nomor Dokumen', 'download_header_filename' => 'Nama berkas', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => 'Int. versi', 'download_header_reviewer' => 'Pengulas', 'download_header_review_comment' => '', @@ -1405,6 +1408,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '', 'removeFolderFromDropFolder' => 'Hapus folder setelah diimpor', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => 'Hapus persetujuan', 'remove_marked_files' => 'Hapus file yang ditandai', 'remove_review_log' => 'Hapus ulasan', @@ -1560,6 +1564,7 @@ URL: [url]', 'select_category' => 'Klik untuk memilih kategori', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Pilih group', 'select_groups' => 'Klik untuk memilih groups', 'select_grp_approvers' => 'Klik untuk memilih group approver', @@ -1614,7 +1619,9 @@ Jika Anda tidak menerima kata sandi, silakan gunakan fitur lupa kata sandi di ha 'service_name' => '', 'sessions' => 'Pengguna Online', 'setDateFromFile' => 'Ambil alih tanggal dari file yang diimpor', +'setDateFromFile_desc' => '', 'setDateFromFolder' => 'Ambil alih tanggal dari folder yang diimpor', +'setDateFromFolder_desc' => '', 'settings' => 'Pengaturan', 'settings_activate_module' => 'Aktifkan modul', 'settings_activate_php_extension' => 'Aktifkan ekstensi PHP', @@ -1712,6 +1719,8 @@ Jika Anda tidak menerima kata sandi, silakan gunakan fitur lupa kata sandi di ha 'settings_delete_install_folder' => 'Untuk menggunakan SeedDMS, Anda harus menghapus file ENABLE_INSTALL_TOOL di direktori konfigurasi', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => '', 'settings_disableSelfEdit_desc' => 'Jika dicentang, pengguna tidak dapat mengedit profilnya sendiri', 'settings_disable_install' => '', @@ -1836,6 +1845,8 @@ Jika Anda tidak menerima kata sandi, silakan gunakan fitur lupa kata sandi di ha 'settings_encryptionKey' => '', 'settings_encryptionKey_desc' => '', 'settings_error' => 'Galat', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => '', 'settings_expandFolderTree_desc' => '', 'settings_expandFolderTree_val0' => '', diff --git a/languages/it_IT/lang.inc b/languages/it_IT/lang.inc index 9ec80118e..307c5478e 100644 --- a/languages/it_IT/lang.inc +++ b/languages/it_IT/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => 'Autorizzazione a due fattori', +'2_factor_auth_code' => '', '2_factor_auth_info' => 'Questo sistema usa autenticazione a due fattori. Sarà necessario il “Google Authenticator” sul tuo telephono cellulare. Qui potete vedere due codici QR. Quello di destra è il tuo segreto. è sulla sinistra chè un nuovo segreto. Se si imposta un nuovo segreto per assicurarsi si deve scansione con “Google Authenticator” di nuovo.', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -570,6 +571,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1314,6 +1317,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: [name] - Flusso di lavoro rimosso dalla versione del documento', 'removeFolderFromDropFolder' => 'Rimuovi la cartella di pubblicazione dopo l\'importazione', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'Rimuovi i files contrassegnati', 'remove_review_log' => '', @@ -1518,6 +1522,7 @@ URL: [url]', 'select_category' => 'Clicca per selezionare la categoria', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Seleziona gruppo', 'select_groups' => 'Clicca per selezionare i gruppi', 'select_grp_approvers' => 'Seleziona gruppo approvatore', @@ -1570,7 +1575,9 @@ Name: [username] 'service_name' => '', 'sessions' => 'Utenti online', 'setDateFromFile' => 'Prende la data dal file importato', +'setDateFromFile_desc' => '', 'setDateFromFolder' => 'Prende la data dalla cartella importata', +'setDateFromFolder_desc' => '', 'settings' => 'Impostazioni', 'settings_activate_module' => 'Attivazione modulo', 'settings_activate_php_extension' => 'Attivazione estensione PHP', @@ -1668,6 +1675,8 @@ Name: [username] 'settings_delete_install_folder' => 'Per poter usare SeedDMS, devi cancellare il file ENABLE_INSTALL_TOOL nella cartella di configurazione.', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Disabilita auto-modifica', 'settings_disableSelfEdit_desc' => 'Se selezionato l\'utente non può modificare il proprio profilo', 'settings_disable_install' => 'Prova ad eliminare il file ENABLE_INSTALL_TOOL se possibile', @@ -1792,6 +1801,8 @@ Name: [username] 'settings_encryptionKey' => 'Chiave di criptazione', 'settings_encryptionKey_desc' => 'La chiave viene usata per creare un identificatore unico da aggiungere come campo nascosto ad un formulario per protezione da attacchi CSRF.', 'settings_error' => 'Errore', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Espandi l\'albero delle cartelle', 'settings_expandFolderTree_desc' => 'Espandi la struttura ad albero delle cartelle', 'settings_expandFolderTree_val0' => 'Inizia con l\'albero nascosto', diff --git a/languages/ko_KR/lang.inc b/languages/ko_KR/lang.inc index 70c7d978e..03c949fb0 100644 --- a/languages/ko_KR/lang.inc +++ b/languages/ko_KR/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => '이중 인증', +'2_factor_auth_code' => '', '2_factor_auth_info' => '', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -566,6 +567,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1295,6 +1298,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename] : [name] - 문서 버전에서 제거 된 워크플로우', 'removeFolderFromDropFolder' => '', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => '마크 파일을 제거', 'remove_review_log' => '', @@ -1494,6 +1498,7 @@ URL : [url]', 'select_category' => '범주를 선택합니다', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => '', 'select_groups' => '그룹을 선택합니다', 'select_grp_approvers' => '그룹 승인을 선택합니다', @@ -1541,7 +1546,9 @@ URL : [url]', 'service_name' => '', 'sessions' => '', 'setDateFromFile' => '', +'setDateFromFile_desc' => '', 'setDateFromFolder' => '', +'setDateFromFolder_desc' => '', 'settings' => '설정', 'settings_activate_module' => '모듈 활성화', 'settings_activate_php_extension' => 'PHP 확장 활성화', @@ -1639,6 +1646,8 @@ URL : [url]', 'settings_delete_install_folder' => 'SeedDMS을 사용하려면 구성 디렉토리의 파일 ENABLE_INSTALL_TOOL을 삭제해야합니다', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => '자체 수정 불가', 'settings_disableSelfEdit_desc' => '확인시 사용자가 자신의 프로필을 편집 할 수 없음', 'settings_disable_install' => 'ENABLE_INSTALL_TOOL 삭제', @@ -1763,6 +1772,8 @@ URL : [url]', 'settings_encryptionKey' => '암호화 키', 'settings_encryptionKey_desc' => '이 문자열은 CSRF 공격을 방지하기 위해 formular에 숨겨진 필드로 추가되는 고유 식별자를 만드는 데 사용된다.', 'settings_error' => '오류', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => '폴더 트리 확장', 'settings_expandFolderTree_desc' => '폴더 트리 확장', 'settings_expandFolderTree_val0' => '숨겨진 Tree로 시작', diff --git a/languages/lo_LA/lang.inc b/languages/lo_LA/lang.inc index 2709a4f36..10a3d5a44 100644 --- a/languages/lo_LA/lang.inc +++ b/languages/lo_LA/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => 'ການກວດສອບແບບ 2 ປັດໃຈ', +'2_factor_auth_code' => '', '2_factor_auth_info' => 'ລະບົບນີ້ໄຊ້ການກວດສອບແບບ 02 ປັດໃຈ. ເຈົ້າຈະຕ້ອງມີ Google Authenticator ໃນໂທລະສັບມືຖືຂອງທ່ານ. ດ້ານລຸ່ມແມ່ນມີ QR Codes ສອງແບບ ທາງດ້ານຂວາຈະມີຄວາມເປັນສ່ວນຕົວຂອງເຈົ້າ, ສ່ວນດ້ານຊ້າຍຂອງເຈົ້າແມ່ນຈະສາມາດຕັ້ງຄ່າຄວາມເປັນສ່ວນຕົວໄຫມ່. ຖ້າເຈົ້າຕັ້ງຄ່າຄວາມເປັນສ່ວນຕົວໄຫມ່ຮຽບຮ້ອຍ ແລ້ວນັ້ນໃຫ້ແນ່ໃຈວ່າໄດ້ສະແກນອີກຄັ້ງດ້ວຍ Google Authenticator', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -563,6 +564,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1311,6 +1314,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]:[name] - ຍ້າຍການເຮັດວຽກ (ເວີກໂຟລ) ອອກຈາກເວີຊັ້ນຂອງເອກະສານ', 'removeFolderFromDropFolder' => 'ຍ້າຍໂຟລເດີຫຼັງຈາກນຳຂໍ້ມູນເຂົ້າ', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'ລົບໄຟລທີມີເຄື່ອງໝາຍໄວ້', 'remove_review_log' => '', @@ -1515,6 +1519,7 @@ URL: [url]', 'select_category' => 'ຄິກເພື່ອເລືອກປະເພດ', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => '', 'select_groups' => 'ຄິກເລືອກກຸ່ມ', 'select_grp_approvers' => 'ຄິກເພືອເລືອກຜູ້ອະນຸມັດກຸ່ມ', @@ -1567,7 +1572,9 @@ URL: [url]', 'service_name' => '', 'sessions' => 'ຜູ້ໄຊ້ອອນລາຍ', 'setDateFromFile' => '', +'setDateFromFile_desc' => '', 'setDateFromFolder' => '', +'setDateFromFolder_desc' => '', 'settings' => 'ການຕັ້ງຄ່າ', 'settings_activate_module' => 'ເປີດໄຊ້ງານໂມດູນ', 'settings_activate_php_extension' => 'ຂະຫຍາຍພື້ນທີການໄຊ້ງານຂອງ PHP', @@ -1665,6 +1672,8 @@ URL: [url]', 'settings_delete_install_folder' => 'ໃນການໄຊ້ SeedDMS, ເຈົ້າຈະຕ້ອງລົບໄຟລ ເປີດໄຊ້ງານ_ຕິດຕັ້ງ_ເຄື່ອງມືໃນການບໍລິຫານ ການກຳນົດຄ່າ', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'ແກ້ໄຂການປິດໄຊ້ງານດ້ວຍຕົວເອງ', 'settings_disableSelfEdit_desc' => 'ກວດຄືນເບິ່ງວ່າຍ້ອນຫຍັງຜູ້ນຳໄຊ້ຈື່ງບໍ່ສາມາດແກ້ໄຂໂປລໄຟລຂອງພວກເຂົາໄດ້', 'settings_disable_install' => 'ຖ້າເປັນໄປໄດ້ ລົບໄຟລເປີດໄຊ້ງານ-ຕິດຕັ້ງ-ເຄື່ອງມື ຖ້າເປັນໄປໄດ້', @@ -1789,6 +1798,8 @@ URL: [url]', 'settings_encryptionKey' => 'ກະແຈການເຂົ້າລະຫັດລັບ', 'settings_encryptionKey_desc' => 'ສະຕິງນີ້ໄຊ້ສຳຫຼັບສ້າງຕົວ', 'settings_error' => 'ຄວາມຜິດພາດ', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'ຂະຫຍານທີໂຟລເດີ', 'settings_expandFolderTree_desc' => 'ຂະຫຍານທີໂຟລເດີ', 'settings_expandFolderTree_val0' => 'ການເລີ່ມຕົ້ນດ້ວຍສາຂາຍ່ອຍ', diff --git a/languages/nb_NO/lang.inc b/languages/nb_NO/lang.inc index f6a3f27c6..a0c903070 100644 --- a/languages/nb_NO/lang.inc +++ b/languages/nb_NO/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => '2-trinns autentisering', +'2_factor_auth_code' => '', '2_factor_auth_info' => 'Dette systemet håndhever 2-faktor autentisering. Du trenger Google Authenticator på mobiltelefonen din. Nedenfor ser du to QR-koder. Den rette er din nåværende hemmelighet. På venstre side kan du angi en ny hemmelighet. Hvis du angir en ny hemmelighet, må du huske å skanne den på nytt med Google Authenticator.', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -577,6 +578,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1326,6 +1329,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: [name] - Fjernet arbeidsflyt fra dokumentversjonen', 'removeFolderFromDropFolder' => 'Fjern mappe etter import', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'Fjern markerte filer', 'remove_review_log' => '', @@ -1530,6 +1534,7 @@ URL: [url]', 'select_category' => 'Klikk for å velge kategori', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Klikk for å velge gruppe', 'select_groups' => 'Klikk for å velge grupper', 'select_grp_approvers' => 'Klikk for å velge gruppe godkjennere', @@ -1580,7 +1585,9 @@ Bruker: [username] 'service_name' => '', 'sessions' => 'Brukere innlogget', 'setDateFromFile' => 'Overta dato fra importert fil', +'setDateFromFile_desc' => '', 'setDateFromFolder' => 'Overta dato fra importert mappe', +'setDateFromFolder_desc' => '', 'settings' => 'Innstillinger', 'settings_activate_module' => 'Aktiver modul', 'settings_activate_php_extension' => 'Aktiver PHP-utvidelse', @@ -1678,6 +1685,8 @@ Bruker: [username] 'settings_delete_install_folder' => 'For å bruke SeedDMS, må du slette filen ENABLE_INSTALL_TOOL i konfigurasjonsmappen', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Deaktiver selvredigering', 'settings_disableSelfEdit_desc' => 'Hvis merket kan brukeren ikke redigere sin egen profil', 'settings_disable_install' => 'Slett filen ENABLE_INSTALL_TOOL hvis mulig', @@ -1802,6 +1811,8 @@ Bruker: [username] 'settings_encryptionKey' => 'Krypteringsnøkkel', 'settings_encryptionKey_desc' => 'Denne strengen brukes til å lage en unik identifikator som blir lagt til som et skjult felt til et skjema for å forhindre CSRF-angrep.', 'settings_error' => 'Feil', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Utvid mappetreet', 'settings_expandFolderTree_desc' => 'Utvid mappetreet', 'settings_expandFolderTree_val0' => 'starte med treet gjemt', diff --git a/languages/nl_NL/lang.inc b/languages/nl_NL/lang.inc index bc880cf9c..595219ab2 100644 --- a/languages/nl_NL/lang.inc +++ b/languages/nl_NL/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => '2-factor-authenticatie', +'2_factor_auth_code' => '', '2_factor_auth_info' => 'Dit systeem werkt met 2-factor-authenticatie. U heeft de Google Authenticator nodig op uw mobiele telfoon. Hieronder staan 2 QR-codes. De rechter is uw huidige geheime code. Met de linker kunt u een nieuwe geheime code instellen. Denk erom de nieuwe code opnieuw te scannen met Googke Authenticator.', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -570,6 +571,8 @@ URL: [url]', 'download_header_document_name' => 'Naam document', 'download_header_document_no' => 'Document nr.', 'download_header_filename' => 'Filenaam', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => 'Interne versie', 'download_header_reviewer' => 'Beoordelaar', 'download_header_review_comment' => 'Commentaar bij beoordeling', @@ -1324,6 +1327,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: [name] - Workflow verwijderd van document versie', 'removeFolderFromDropFolder' => 'Map verwijderen uit Dropfilder', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'Geselecteerde bestanden worden verwijderd', 'remove_review_log' => '', @@ -1527,6 +1531,7 @@ URL: [url]', 'select_category' => 'klik om categorie te selecteren', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Selecteer groep', 'select_groups' => 'Klik om groep te selecteren', 'select_grp_approvers' => 'Klik om beoordelaars te selecteren', @@ -1579,7 +1584,9 @@ Name: [username] 'service_name' => '', 'sessions' => 'sessies', 'setDateFromFile' => 'Gebruik de datum van de geïmporteerde file', +'setDateFromFile_desc' => '', 'setDateFromFolder' => 'Gebruik de datum van de geïmporteerde map', +'setDateFromFolder_desc' => '', 'settings' => 'Instellingen', 'settings_activate_module' => 'Activeer module', 'settings_activate_php_extension' => 'Activeer PHP uitbreiding', @@ -1677,6 +1684,8 @@ Name: [username] 'settings_delete_install_folder' => 'Om SeedDMS te kunnen gebruiken moet het bestand ENABLE_INSTALL_TOOL uit de configuratiemap verwijderd worden.', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Uitschakelen Eigenprofiel wijzigen', 'settings_disableSelfEdit_desc' => 'Indien aangevinkt kan de gebruiker zijn eigen profiel niet wijzigen.', 'settings_disable_install' => 'Verwijder het bestand ENABLE_INSTALL_TOOL indien mogelijk', @@ -1801,6 +1810,8 @@ Name: [username] 'settings_encryptionKey' => 'Sleutel voor encryptie', 'settings_encryptionKey_desc' => 'Deze string wordt gebruikt om een unieke identificatie als onzichtbaar veld aan een formulier toe te voegen om CSRF aanvallen tegen te gaan.', 'settings_error' => 'Fout', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Uitvouwen mappenstructuur', 'settings_expandFolderTree_desc' => 'Uitvouwen mappenstructuur', 'settings_expandFolderTree_val0' => 'begin met verborgen structuur', diff --git a/languages/pl_PL/lang.inc b/languages/pl_PL/lang.inc index 4678dcf5b..5d841621c 100644 --- a/languages/pl_PL/lang.inc +++ b/languages/pl_PL/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => 'Uwierzytelnianie dwuetapowe', +'2_factor_auth_code' => '', '2_factor_auth_info' => 'Uwierzytelnianie dwuetapowe', '2_fact_auth_current_secret' => 'Obecny poufny kod', '2_fact_auth_new_secret' => 'Nowy poufny kod', @@ -553,6 +554,8 @@ URL: [url]', 'download_header_document_name' => 'Nazwa dokumentu', 'download_header_document_no' => 'Numer dokumentu', 'download_header_filename' => 'Nazwa pliku', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => 'Wersja wewnętrzna', 'download_header_reviewer' => 'Recenzent', 'download_header_review_comment' => 'Komentarz recezenta', @@ -1290,6 +1293,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: [name] - Usunięty przepływ dokumentu z wersji dokumentu', 'removeFolderFromDropFolder' => 'Usuń folder po imporcie', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'Usuń zaznaczone pliki', 'remove_review_log' => '', @@ -1458,6 +1462,7 @@ URL: [url]', 'select_category' => 'Kliknij by wybrać kategorię', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Wybierz grupę', 'select_groups' => 'Kliknij by wybrać grupy', 'select_grp_approvers' => 'Kliknij by wybrać grupę zatwierdzającą', @@ -1510,7 +1515,9 @@ Name: [username] 'service_name' => '', 'sessions' => 'Sesja', 'setDateFromFile' => 'Przejmij datę z importowanego pliku', +'setDateFromFile_desc' => '', 'setDateFromFolder' => 'Przejmij datę z importowanego folderu', +'setDateFromFolder_desc' => '', 'settings' => 'Ustawienia', 'settings_activate_module' => 'Aktywuj moduł', 'settings_activate_php_extension' => 'Aktywuj rozszerzenie PHP', @@ -1608,6 +1615,8 @@ Name: [username] 'settings_delete_install_folder' => 'Aby móc używać SeedDMS, musisz usunąć plik ENABLE_INSTALL_TOOL znajdujący się w katalogu konfiguracyjnym', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Wyłącz auto edycję', 'settings_disableSelfEdit_desc' => 'Jeśli zaznaczone, użytkownik nie może zmieniać własnych danych', 'settings_disable_install' => 'Usuń plik ENABLE_INSTALL_TOOL jeśli to możliwe', @@ -1732,6 +1741,8 @@ Name: [username] 'settings_encryptionKey' => 'Klucz szyfrujący', 'settings_encryptionKey_desc' => 'Ten ciąg znaków jest używany do tworzenia unikatowego identyfikatora dodawanego jako ukryte pole do formularza aby zapobiec atakom CSRF.', 'settings_error' => 'Błąd', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Rozwiń drzewo katalogów', 'settings_expandFolderTree_desc' => 'Rozwiń drzewo katalogów', 'settings_expandFolderTree_val0' => 'Rozpocznij z ukrytym drzewem', diff --git a/languages/pt_BR/lang.inc b/languages/pt_BR/lang.inc index 6a3990787..7dc593b9e 100644 --- a/languages/pt_BR/lang.inc +++ b/languages/pt_BR/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => 'Autenticação de dois fatores', +'2_factor_auth_code' => '', '2_factor_auth_info' => 'Este sistema impõe a autenticação de 2 fatores. Você precisará do Google Authenticator no seu celular. Abaixo você vê dois códigos QR. O caminho certo é o seu atual segredo. À esquerda, você pode definir um novo segredo. Se você definir um novo segredo, verifique novamente com o Google Authenticator.', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -577,6 +578,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1331,6 +1334,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: [name] - Fluxo de trabalho removido da versão do documento', 'removeFolderFromDropFolder' => 'Remover pasta após a importação', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'Remover arquivos marcados', 'remove_review_log' => '', @@ -1534,6 +1538,7 @@ URL: [url]', 'select_category' => 'Clique para selecionar a categoria', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Selecione o grupo', 'select_groups' => 'Clique para selecionar os grupos', 'select_grp_approvers' => 'Clique para selecionar o grupo aprovador', @@ -1586,7 +1591,9 @@ Nome: [username] 'service_name' => '', 'sessions' => 'Online', 'setDateFromFile' => 'Assumir a data do arquivo importado', +'setDateFromFile_desc' => '', 'setDateFromFolder' => 'Assumir a data da pasta importada', +'setDateFromFolder_desc' => '', 'settings' => 'Configurações', 'settings_activate_module' => 'Ativar módulo', 'settings_activate_php_extension' => 'Ativar extensão PHP', @@ -1684,6 +1691,8 @@ Nome: [username] 'settings_delete_install_folder' => 'Para utilizar Sistema GED, você deve excluir o arquivo ENABLE_INSTALL_TOOL do diretório de configuração', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Desativar Auto Editar', 'settings_disableSelfEdit_desc' => 'Se selecionado o usuário não poderá editar seu próprio perfil', 'settings_disable_install' => 'Elimine o arquivo ENABLE_INSTALL_TOOL se possível', @@ -1808,6 +1817,8 @@ Nome: [username] 'settings_encryptionKey' => 'Chave de criptografia', 'settings_encryptionKey_desc' => 'Esta cadeia é usada para a criação de um identificador único a ser adicionado como um campo oculto para formular, a fim de evitar ataques CSRF.', 'settings_error' => 'Erro', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Expandir a árvore de pastas', 'settings_expandFolderTree_desc' => 'Expanda a Árvore de Pastas', 'settings_expandFolderTree_val0' => 'começar com a árvore escondida', diff --git a/languages/ro_RO/lang.inc b/languages/ro_RO/lang.inc index 5bbb8bb58..17621bbb1 100644 --- a/languages/ro_RO/lang.inc +++ b/languages/ro_RO/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => '', +'2_factor_auth_code' => '', '2_factor_auth_info' => '', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -565,6 +566,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1302,6 +1305,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: [name] - Workflow eliminat din versiunea documentului', 'removeFolderFromDropFolder' => '', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'Eliminați fișierele marcate', 'remove_review_log' => '', @@ -1501,6 +1505,7 @@ URL: [url]', 'select_category' => 'Click pentru a selecta categoria', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Selecteaza grupul', 'select_groups' => 'Click pentru a selecta grupuri', 'select_grp_approvers' => 'Click pentru a selecta grupul de aprobatori', @@ -1548,7 +1553,9 @@ URL: [url]', 'service_name' => '', 'sessions' => '', 'setDateFromFile' => '', +'setDateFromFile_desc' => '', 'setDateFromFolder' => '', +'setDateFromFolder_desc' => '', 'settings' => 'Setări', 'settings_activate_module' => 'Activați modulul', 'settings_activate_php_extension' => 'Activați extensia PHP', @@ -1646,6 +1653,8 @@ URL: [url]', 'settings_delete_install_folder' => 'Pentru a utiliza SeedDMS, trebuie să ștergeți fișierul ENABLE_INSTALL_TOOL din directorul de configurare', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Dezactivați Auto Editarea', 'settings_disableSelfEdit_desc' => 'Dacă este bifată, utilizatorul nu va putea să-și editeze profilul', 'settings_disable_install' => 'Ștergeți fișierul ENABLE_INSTALL_TOOL dacă este posibil', @@ -1770,6 +1779,8 @@ URL: [url]', 'settings_encryptionKey' => 'Cheia de criptare', 'settings_encryptionKey_desc' => 'Acest șir este utilizat pentru crearea unui identificator unic ce este adăugat ca un câmp ascuns pentru un formular, cu scopul de a preveni atacurile CSRF.', 'settings_error' => 'Eroare', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Expandați ierarhia Folderului', 'settings_expandFolderTree_desc' => 'Expandați ierarhia Folderului', 'settings_expandFolderTree_val0' => 'începeți cu ierarhia ascunsă', diff --git a/languages/ru_RU/lang.inc b/languages/ru_RU/lang.inc index b930cc732..526f7ee3b 100644 --- a/languages/ru_RU/lang.inc +++ b/languages/ru_RU/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => 'Двухфакторная аутентификация', +'2_factor_auth_code' => '', '2_factor_auth_info' => 'Использовать усиленную проверку подлинности', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -565,6 +566,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1304,6 +1307,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: удалён процесс из версии документа «[name]»', 'removeFolderFromDropFolder' => '', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'Удалить выбранные файлы', 'remove_review_log' => '', @@ -1508,6 +1512,7 @@ URL: [url]', 'select_category' => 'Выберите категорию', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Выберите группу', 'select_groups' => 'Выберите группы', 'select_grp_approvers' => 'Выберите утверждающую группу', @@ -1555,7 +1560,9 @@ URL: [url]', 'service_name' => '', 'sessions' => '', 'setDateFromFile' => '', +'setDateFromFile_desc' => '', 'setDateFromFolder' => '', +'setDateFromFolder_desc' => '', 'settings' => 'Настройки', 'settings_activate_module' => 'Активировать модуль', 'settings_activate_php_extension' => 'Активировать расширение PHP', @@ -1653,6 +1660,8 @@ URL: [url]', 'settings_delete_install_folder' => 'Удалите ENABLE_INSTALL_TOOL в каталоге конфигурации, для того что бы начать использовать систему', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Отключить собственное редактирование', 'settings_disableSelfEdit_desc' => 'Если включено, пользователи не смогут изменять информацию о себе.', 'settings_disable_install' => 'Удалить ENABLE_INSTALL_TOOL, если возможно', @@ -1777,6 +1786,8 @@ URL: [url]', 'settings_encryptionKey' => 'Ключ шифрования', 'settings_encryptionKey_desc' => 'Строка используется для создания уникального идентификатора, добавляемого как скрытые поля к формулярам, для предотвращения CSRF-атак.', 'settings_error' => 'Ошибка', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Разворачивать дерево каталогов', 'settings_expandFolderTree_desc' => 'Разворачивать дерево каталогов.', 'settings_expandFolderTree_val0' => 'Начинать со свёрнутого дерева', diff --git a/languages/sk_SK/lang.inc b/languages/sk_SK/lang.inc index abb9b9bc6..4e943e161 100644 --- a/languages/sk_SK/lang.inc +++ b/languages/sk_SK/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => '2-faktorové overovanie', +'2_factor_auth_code' => '', '2_factor_auth_info' => 'This system enforces 2 factor authentication. You will need the Google Authenticator on your mobile phone. Below you see two QR codes. The right one is your current secret. On the left you can set a new secret. If you set a new secret make sure to rescan it with Google Authenticator.', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -577,6 +578,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1332,6 +1335,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: [name] - Removed workflow from document version', 'removeFolderFromDropFolder' => 'Po importe odstrániť zložku', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'Odstrániť označené súbory', 'remove_review_log' => '', @@ -1536,6 +1540,7 @@ URL: [url]', 'select_category' => 'Vyber kategóriu', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Vybrať skupinu', 'select_groups' => 'Kliknutím vyberte skupiny', 'select_grp_approvers' => 'Kliknutím vyberte schvaľovateľa skupiny', @@ -1588,7 +1593,9 @@ Meno: [username] 'service_name' => '', 'sessions' => 'Používatelia online', 'setDateFromFile' => 'Prebrať dátumy z importovaných súborov', +'setDateFromFile_desc' => '', 'setDateFromFolder' => 'Prebrať dátumy z importovaných zložiek', +'setDateFromFolder_desc' => '', 'settings' => 'Nastavenia', 'settings_activate_module' => 'Aktivovať modul', 'settings_activate_php_extension' => 'Aktivovať PHP rozšírenie', @@ -1686,6 +1693,8 @@ Meno: [username] 'settings_delete_install_folder' => 'In order to use SeedDMS, you must delete the file ENABLE_INSTALL_TOOL in the configuration directory', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Disable Self Edit', 'settings_disableSelfEdit_desc' => 'If checked user cannot edit his own profile', 'settings_disable_install' => 'Delete file ENABLE_INSTALL_TOOL if possible', @@ -1810,6 +1819,8 @@ Meno: [username] 'settings_encryptionKey' => 'Encryption key', 'settings_encryptionKey_desc' => 'This string is used for creating a unique identifier being added as a hidden field to a form in order to prevent CSRF attacks.', 'settings_error' => 'Chyba', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Rozbaliť', 'settings_expandFolderTree_desc' => 'Rozbaliť strom zložiek', 'settings_expandFolderTree_val0' => 'začať so skrytou stromovou štruktúrou', diff --git a/languages/sv_SE/lang.inc b/languages/sv_SE/lang.inc index a35605926..b2a9aa40d 100644 --- a/languages/sv_SE/lang.inc +++ b/languages/sv_SE/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => '2-faktors autentisering', +'2_factor_auth_code' => '', '2_factor_auth_info' => 'För stöd av 2-faktors autentisering behöver du Google Authenticator installerad på din mobiltelefon. Nedan ser du två QR-koder. Den högra är din hemliga kod och till vänster kan du skapa en ny kod. Om du skapar en ny kod måste du skanna den på nytt med Google Authenticator.', '2_fact_auth_current_secret' => '', @@ -571,6 +572,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1305,6 +1308,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: [name] - Arbetsflöde borttaget från dokumentversion', 'removeFolderFromDropFolder' => 'Radera katalog efter import', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'Ta bort markerade filer', 'remove_review_log' => '', @@ -1509,6 +1513,7 @@ URL: [url]', 'select_category' => 'Klicka för att välja en kategori', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Välj grupp', 'select_groups' => 'Välj grupper', 'select_grp_approvers' => 'Välj en grupp som ska godkänna', @@ -1561,7 +1566,9 @@ Kommentar: [comment]', 'service_name' => '', 'sessions' => 'Användare online', 'setDateFromFile' => '', +'setDateFromFile_desc' => '', 'setDateFromFolder' => '', +'setDateFromFolder_desc' => '', 'settings' => 'Inställningar', 'settings_activate_module' => 'Aktivera modul', 'settings_activate_php_extension' => 'Aktivera PHP-extension', @@ -1659,6 +1666,8 @@ Kommentar: [comment]', 'settings_delete_install_folder' => 'För att kunna använda LetoDMS måste du ta bort filen ENABLE_INSTALL_TOOL som finns i konfigurationsmappen.', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Inaktivera själveditering', 'settings_disableSelfEdit_desc' => 'Om ikryssad kan användare inte ändra sin egen profil.', 'settings_disable_install' => 'Ta bort filen ENABLE_INSTALL_TOOL, om det är möjligt.', @@ -1783,6 +1792,8 @@ Kommentar: [comment]', 'settings_encryptionKey' => 'Krypteringsnyckel', 'settings_encryptionKey_desc' => 'Denna sträng används för att generera en unik identifierare, som är inrymd som ett dolt fält i ett formulär. Det används för att förhindra CSRF-attacker.', 'settings_error' => 'Fel', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Expandera katalogträd', 'settings_expandFolderTree_desc' => 'Expandera katalogträd', 'settings_expandFolderTree_val0' => 'Börja med dolt träd', diff --git a/languages/tr_TR/lang.inc b/languages/tr_TR/lang.inc index 06652db3a..0a4273dbb 100644 --- a/languages/tr_TR/lang.inc +++ b/languages/tr_TR/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => 'İki faktörlü yetkilendirme', +'2_factor_auth_code' => '', '2_factor_auth_info' => '', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -559,6 +560,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1296,6 +1299,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: [name] - Doküman versiyonundan iş akışı silindi', 'removeFolderFromDropFolder' => '', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'İşaretli dosyaları sil', 'remove_review_log' => '', @@ -1478,6 +1482,7 @@ URL: [url]', 'select_category' => 'Kategori seçmek için tıklayın', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => 'Grup Seç', 'select_groups' => 'Grup seçmek için tıklayın', 'select_grp_approvers' => 'Grup onaylayıcı seçmek için tıklayın', @@ -1525,7 +1530,9 @@ URL: [url]', 'service_name' => '', 'sessions' => '', 'setDateFromFile' => '', +'setDateFromFile_desc' => '', 'setDateFromFolder' => '', +'setDateFromFolder_desc' => '', 'settings' => 'Ayarlar', 'settings_activate_module' => 'Modülü etkinleştir', 'settings_activate_php_extension' => 'PHP uzantısını etkinleştir', @@ -1623,6 +1630,8 @@ URL: [url]', 'settings_delete_install_folder' => 'SeedDMS kullanabilmeniz için konfigürasyon (conf) dizini içindeki ENABLE_INSTALL_TOOL dosyasını silmelisiniz', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Kendi kendine Düzenlemeyi Kapat', 'settings_disableSelfEdit_desc' => 'Seçilirse kullanıcı kendi profil ayarlarını değiştiremez.', 'settings_disable_install' => 'ENABLE_INSTALL_TOOL dosyasını silmeyi dene', @@ -1747,6 +1756,8 @@ URL: [url]', 'settings_encryptionKey' => 'Şifreleme anahtarı', 'settings_encryptionKey_desc' => 'Bu string, CSRF ataklarını önlemek için eşsiz id olarak kaydedilir.', 'settings_error' => 'Hata', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Klasör Ağacını Genişlet', 'settings_expandFolderTree_desc' => 'Klasör Ağacını Genişlet', 'settings_expandFolderTree_val0' => 'ağaç yapısı gizli olarak başlat', diff --git a/languages/uk_UA/lang.inc b/languages/uk_UA/lang.inc index ac84bed85..5a6048d50 100644 --- a/languages/uk_UA/lang.inc +++ b/languages/uk_UA/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => '', +'2_factor_auth_code' => '', '2_factor_auth_info' => '', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -564,6 +565,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1303,6 +1306,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: видалено процес з версії документа «[name]»', 'removeFolderFromDropFolder' => '', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => 'Видалити обрані файли', 'remove_review_log' => '', @@ -1500,6 +1504,7 @@ URL: [url]', 'select_category' => 'Оберіть категорію', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => '', 'select_groups' => 'Оберіть групи', 'select_grp_approvers' => 'Оберіть групу затверджувачів', @@ -1547,7 +1552,9 @@ URL: [url]', 'service_name' => '', 'sessions' => '', 'setDateFromFile' => '', +'setDateFromFile_desc' => '', 'setDateFromFolder' => '', +'setDateFromFolder_desc' => '', 'settings' => 'Налаштування', 'settings_activate_module' => 'Активувати модуль', 'settings_activate_php_extension' => 'Активувати розширення PHP', @@ -1645,6 +1652,8 @@ URL: [url]', 'settings_delete_install_folder' => 'Видаліть ENABLE_INSTALL_TOOL в каталозі конфігурації для того, щоби почати використовувати систему', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => 'Відключити власне редагування', 'settings_disableSelfEdit_desc' => 'Якщо ввімкнено, користувачі не зможуть змінювати інформацію про себе.', 'settings_disable_install' => 'Видалити ENABLE_INSTALL_TOOL, якщо можливо', @@ -1769,6 +1778,8 @@ URL: [url]', 'settings_encryptionKey' => 'Ключ шифрування', 'settings_encryptionKey_desc' => 'Рядок використовується для створення унікального ідентифікатора, який додається як приховане поле до формулярів, для запобігання CSRF-атак.', 'settings_error' => 'Помилка', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => 'Розгортати дерево каталогів', 'settings_expandFolderTree_desc' => 'Розгортати дерево каталогів.', 'settings_expandFolderTree_val0' => 'Починати із згорнутого дерева', diff --git a/languages/zh_CN/lang.inc b/languages/zh_CN/lang.inc index ce7664fd5..1fec1f315 100644 --- a/languages/zh_CN/lang.inc +++ b/languages/zh_CN/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => '双重认证', +'2_factor_auth_code' => '', '2_factor_auth_info' => '该系统启用双重认证。您需要在手机上进行 Google 认证。下面你会看到两个 QR 码。正确的是你目前的密码。在左边你可以设置一个新的密码。如果您设置了新的密码,请重新扫描并通过 Google 认证。', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -559,6 +560,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1309,6 +1312,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: [name] - 已从文档版本中移除工作流', 'removeFolderFromDropFolder' => '导入后删除文件夹', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => '删除选中的文件', 'remove_review_log' => '', @@ -1483,6 +1487,7 @@ URL: [url]', 'select_category' => '选中分类', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => '选择用户组', 'select_groups' => '点击选择组', 'select_grp_approvers' => '点击选择组审批组', @@ -1535,7 +1540,9 @@ URL: [url]', 'service_name' => '', 'sessions' => '在线用户', 'setDateFromFile' => '导入文件接收日期', +'setDateFromFile_desc' => '', 'setDateFromFolder' => '导入文件夹接收日期', +'setDateFromFolder_desc' => '', 'settings' => '设置', 'settings_activate_module' => '启用模块', 'settings_activate_php_extension' => '启用 PHP 扩展', @@ -1633,6 +1640,8 @@ URL: [url]', 'settings_delete_install_folder' => '在使用 DMS 前,您必须先删除配置目录(config)下的 ENABLE_INSTALL_TOOL 文件', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => '禁用自编辑', 'settings_disableSelfEdit_desc' => '若勾选,则用户不能编辑自己的档案信息', 'settings_disable_install' => '如有可能,则删除 ENABLE_INSTALL_TOOL 文件', @@ -1757,6 +1766,8 @@ URL: [url]', 'settings_encryptionKey' => '加密密钥', 'settings_encryptionKey_desc' => '这个字符串用于创建一个唯一的标识符,并作为一个隐藏字段添加到表单中以防止CSRF攻击。', 'settings_error' => '错误', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => '展开文件夹树', 'settings_expandFolderTree_desc' => '展开文件夹树', 'settings_expandFolderTree_val0' => '启动时隐藏树形结构', diff --git a/languages/zh_TW/lang.inc b/languages/zh_TW/lang.inc index f8cc6faf9..bec9620f4 100644 --- a/languages/zh_TW/lang.inc +++ b/languages/zh_TW/lang.inc @@ -23,6 +23,7 @@ $text = array( '2_factor_auth' => '2階段認證', +'2_factor_auth_code' => '', '2_factor_auth_info' => '此系統強制執行2階段身份驗證。您將需要在手機上使用Google Authenticator。在下面,您可以看到兩個QR碼。正確的是您當前的秘密。在左側,您可以設置一個新的秘密。如果您設置了新的機密,請確保使用Google Authenticator重新掃描它。', '2_fact_auth_current_secret' => '', '2_fact_auth_new_secret' => '', @@ -577,6 +578,8 @@ URL: [url]', 'download_header_document_name' => '', 'download_header_document_no' => '', 'download_header_filename' => '', +'download_header_folder_name' => '', +'download_header_folder_no' => '', 'download_header_internal_version' => '', 'download_header_reviewer' => '', 'download_header_review_comment' => '', @@ -1330,6 +1333,7 @@ URL: [url]', 'removed_workflow_email_body_html' => '', 'removed_workflow_email_subject' => '[sitename]: [name] - 從文檔版本中刪除了工作流程', 'removeFolderFromDropFolder' => '導入後刪除文件夾', +'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', 'remove_marked_files' => '刪除勾選的檔案', 'remove_review_log' => '', @@ -1534,6 +1538,7 @@ URL: [url]', 'select_category' => '選中分類', 'select_created' => '', 'select_documents_for_process' => '', +'select_folder' => '', 'select_group' => '選擇群', 'select_groups' => '點擊選擇組', 'select_grp_approvers' => '請點選審核人員群組', @@ -1586,7 +1591,9 @@ URL: [url]', 'service_name' => '', 'sessions' => '在線用戶', 'setDateFromFile' => '從導入的文件接管日期', +'setDateFromFile_desc' => '', 'setDateFromFolder' => '從導入的文件夾接管日期', +'setDateFromFolder_desc' => '', 'settings' => '設置', 'settings_activate_module' => '激活模塊', 'settings_activate_php_extension' => '激活PHP擴展', @@ -1684,6 +1691,8 @@ URL: [url]', 'settings_delete_install_folder' => '為了使用SeedDMS,必須在配置目錄中刪除文件ENABLE_INSTALL_TOOL', 'settings_disableChangePassword' => '', 'settings_disableChangePassword_desc' => '', +'settings_disableReceiptComment' => '', +'settings_disableReceiptComment_desc' => '', 'settings_disableSelfEdit' => '禁用自我編輯', 'settings_disableSelfEdit_desc' => '如果選中,則用戶無法編輯自己的個人資料', 'settings_disable_install' => '如果可能,刪除文件ENABLE_INSTALL_TOOL', @@ -1808,6 +1817,8 @@ URL: [url]', 'settings_encryptionKey' => '加密金鑰', 'settings_encryptionKey_desc' => '該字符串用於創建唯一的標識符,該標識符作為隱藏字段添加到表單中,以防止CSRF攻擊。', 'settings_error' => '錯誤', +'settings_excludeFoldersDashboard' => '', +'settings_excludeFoldersDashboard_desc' => '', 'settings_expandFolderTree' => '展開文件樹', 'settings_expandFolderTree_desc' => '展開文件樹', 'settings_expandFolderTree_val0' => '從隱藏的樹開始', From 435c94f585cad0c7073139f6eeceaf82ec408edb Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 15:20:41 +0100 Subject: [PATCH 073/208] add export of folder list --- inc/inc.ClassDownloadMgr.php | 72 +++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/inc/inc.ClassDownloadMgr.php b/inc/inc.ClassDownloadMgr.php index 97b5020c3..3ca87c849 100644 --- a/inc/inc.ClassDownloadMgr.php +++ b/inc/inc.ClassDownloadMgr.php @@ -39,24 +39,48 @@ class SeedDMS_Download_Mgr { */ protected $items; + /** + * @var array $folder_items list of folder content items + * @access protected + */ + protected $folder_items; + /** * @var array $extracols list of arrays with extra columns per item * @access protected */ protected $extracols; + /** + * @var array $folder_extracols list of arrays with extra columns per folder item + * @access protected + */ + protected $folder_extracols; + /** * @var array $header list of entries in header (first line) * @access protected */ protected $header; + /** + * @var array $folder_header list of entries in header (first line) + * @access protected + */ + protected $folder_header; + /** * @var array $extraheader list of extra entries in header * @access protected */ protected $extraheader; + /** + * @var array $folder_extraheader list of extra entries in header + * @access protected + */ + protected $folder_extraheader; + /** * @var array $rawcontents list of content used instead of document content * @access protected @@ -72,10 +96,14 @@ class SeedDMS_Download_Mgr { function __construct($tmpdir = '') { $this->tmpdir = $tmpdir; $this->items = array(); + $this->folder_items = array(); $this->header = array(getMLText('download_header_document_no'), getMLText('download_header_document_name'), getMLText('download_header_filename'), getMLText('download_header_state'), getMLText('download_header_internal_version'), getMLText('download_header_reviewer'), getMLText('download_header_review_date'), getMLText('download_header_review_comment'), getMLText('download_header_review_state'), getMLText('download_header_approver'), getMLText('download_header_approval_date'), getMLText('download_header_approval_comment'), getMLText('download_header_approval_state')); + $this->folder_header = array(getMLText('download_header_folder_no'), getMLText('download_header_folder_name')); $this->extracols = array(); + $this->folder_extracols = array(); $this->rawcontents = array(); $this->extraheader = array(); + $this->folder_extraheader = array(); $this->filenames = array(); } @@ -83,6 +111,10 @@ class SeedDMS_Download_Mgr { $this->extraheader = $extraheader; } /* }}} */ + public function addFolderHeader($extraheader) { /* {{{ */ + $this->folder_extraheader = $extraheader; + } /* }}} */ + public function addItem($item, $extracols=array(), $rawcontent='', $filename='') { /* {{{ */ $this->items[$item->getID()] = $item; $this->extracols[$item->getID()] = $extracols; @@ -90,10 +122,15 @@ class SeedDMS_Download_Mgr { $this->filenames[$item->getID()] = $filename; } /* }}} */ + public function addFolderItem($item, $extracols=array()) { /* {{{ */ + $this->folder_items[$item->getID()] = $item; + $this->folder_extracols[$item->getID()] = $extracols; + } /* }}} */ + public function createToc($file) { /* {{{ */ - $items = $this->items; $objPHPExcel = new PhpOffice\PhpSpreadsheet\Spreadsheet(); $objPHPExcel->getProperties()->setCreator("SeedDMS")->setTitle("Metadata"); + if($items = $this->items) { $sheet = $objPHPExcel->setActiveSheetIndex(0); $sheet->setTitle(getMLText('documents')); @@ -190,6 +227,39 @@ class SeedDMS_Download_Mgr { $i++; } } + } + + if($items = $this->folder_items) { + if($this->items) + $sheet = $objPHPExcel->createSheet($i); + else + $sheet = $objPHPExcel->setActiveSheetIndex(0); + $sheet->setTitle(getMLText('folders')); + + $i = 1; + $col = 1; + foreach($this->folder_header as $h) + $sheet->setCellValueByColumnAndRow($col++, $i, $h); + foreach($this->folder_extraheader as $h) + $sheet->setCellValueByColumnAndRow($col++, $i, $h); + $i++; + $items = $this->folder_items; + foreach($items as $item) { + if($item->isType('folder')) { + $folder = $item; + $dms = $folder->_dms; + + $col = 1; + $sheet->setCellValueByColumnAndRow($col++, $i, $folder->getID()); + $sheet->setCellValueByColumnAndRow($col++, $i, $folder->getName()); + if(isset($this->folder_extracols[$item->getID()]) && $this->folder_extracols[$item->getID()]) { + foreach($this->folder_extracols[$item->getID()] as $column) + $sheet->setCellValueByColumnAndRow($col++, $i, is_array($column) ? implode("\n", $column) : $column ); + } + $i++; + } + } + } $objWriter = new PhpOffice\PhpSpreadsheet\Writer\Xlsx($objPHPExcel); $objWriter->save($file); From ca29a27187ae5d8d5bb818c7eaeab30a0ff17a02 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Feb 2025 15:21:14 +0100 Subject: [PATCH 074/208] support export of folders in excel file --- out/out.Search.php | 4 ++-- views/bootstrap/class.Search.php | 12 +++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/out/out.Search.php b/out/out.Search.php index 064675a19..1f14ac23f 100644 --- a/out/out.Search.php +++ b/out/out.Search.php @@ -678,7 +678,7 @@ if($fullsearch) { $entries = array(); $fcount = 0; - if(!isset($_GET['action']) || $_GET['action'] != 'export') { +// if(!isset($_GET['action']) || $_GET['action'] != 'export') { if($resArr['folders']) { foreach ($resArr['folders'] as $entry) { if ($entry->getAccessMode($user) >= M_READ) { @@ -687,7 +687,7 @@ if($fullsearch) { } } } - } +// } $dcount = 0; if($resArr['docs']) { foreach ($resArr['docs'] as $entry) { diff --git a/views/bootstrap/class.Search.php b/views/bootstrap/class.Search.php index 12c64f56f..b37d9e897 100644 --- a/views/bootstrap/class.Search.php +++ b/views/bootstrap/class.Search.php @@ -243,6 +243,16 @@ $(document).ready(function() { } } } + if($extraheader = $this->callHook('extraDownloadFolderHeader')) + $downmgr->addFolderHeader($extraheader); + foreach($entries as $entry) { + if($entry->isType('folder')) { + if(empty($marks) || !empty($marks['F'.$entry->getId()])) { + $extracols = $this->callHook('extraDownloadFolderColumns', $entry); + $downmgr->addFolderItem($entry, $extracols); + } + } + } $filename = tempnam(sys_get_temp_dir(), ''); if($includecontent) { $downmgr->createArchive($filename); @@ -1463,7 +1473,7 @@ $(document).ready(function() { /* Batch operations {{{ */ if($settings->_batchOperations && $total) $this->contentHeading(getMLText('batch_operation')); - if($totaldocs) { + if($totaldocs || $totalfolders) { if(in_array('export', $settings->_batchOperations)) { ob_start(); $this->formField( From a3ea05177ac7486df310b1bdff880edbcb5b4fc7 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 4 Feb 2025 08:27:05 +0100 Subject: [PATCH 075/208] controll access on batch operations by advanced access rights --- views/bootstrap/class.Search.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/views/bootstrap/class.Search.php b/views/bootstrap/class.Search.php index b37d9e897..fe52a077b 100644 --- a/views/bootstrap/class.Search.php +++ b/views/bootstrap/class.Search.php @@ -1473,8 +1473,8 @@ $(document).ready(function() { /* Batch operations {{{ */ if($settings->_batchOperations && $total) $this->contentHeading(getMLText('batch_operation')); - if($totaldocs || $totalfolders) { - if(in_array('export', $settings->_batchOperations)) { + if(($totaldocs || $totalfolders) && in_array('export', $settings->_batchOperations)) { + if($accessobject->check_view_access($this, array('action'=>'export'))) { ob_start(); $this->formField( getMLText("include_content"), @@ -1496,6 +1496,7 @@ $(document).ready(function() { /* All other batch operations are only allowed for admins */ if($user->isAdmin()) { if($total && in_array('change_owner', $settings->_batchOperations)) { + if($accessobject->check_view_access($this, array('action'=>'change_owner'))) { ob_start(); $users = $dms->getAllUsers(); $options = array(); @@ -1521,8 +1522,10 @@ $(document).ready(function() { $content = ob_get_clean(); $this->printAccordion(getMLText('batch_change_owner'), $content); } + } if($totaldocs && in_array('add_reviewer', $settings->_batchOperations)) { + if($accessobject->check_view_access($this, array('action'=>'add_reviewer'))) { ob_start(); $users = $dms->getAllUsers(); $options = array(); @@ -1547,8 +1550,10 @@ $(document).ready(function() { $content = ob_get_clean(); $this->printAccordion(getMLText('batch_add_reviewer'), $content); } + } if($totaldocs && in_array('add_approver', $settings->_batchOperations)) { + if($accessobject->check_view_access($this, array('action'=>'add_approver'))) { ob_start(); $users = $dms->getAllUsers(); $options = array(); @@ -1573,8 +1578,10 @@ $(document).ready(function() { $content = ob_get_clean(); $this->printAccordion(getMLText('batch_add_approver'), $content); } + } if($totaldocs && in_array('change_category', $settings->_batchOperations)) { + if($accessobject->check_view_access($this, array('action'=>'change_category'))) { ob_start(); $cats = $dms->getDocumentCategories(); if($cats) { @@ -1611,6 +1618,7 @@ $(document).ready(function() { $this->printAccordion(getMLText('batch_change_category'), $content); } } + } } // }}} From c815b0069dd88b674d1b04b6ef13cb316a51ce9a Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 4 Feb 2025 11:04:58 +0100 Subject: [PATCH 076/208] get $accessobject from view --- views/bootstrap/class.Search.php | 1 + 1 file changed, 1 insertion(+) diff --git a/views/bootstrap/class.Search.php b/views/bootstrap/class.Search.php index fe52a077b..428bc3923 100644 --- a/views/bootstrap/class.Search.php +++ b/views/bootstrap/class.Search.php @@ -462,6 +462,7 @@ $(document).ready(function() { $dms = $this->params['dms']; $user = $this->params['user']; $settings = $this->params['settings']; + $accessobject = $this->params['accessobject']; $request = $this->params['request']; $fullsearch = $this->params['fullsearch']; $facetsearch = $this->params['facetsearch']; From 4d44774a7fdaa08ad0e318e065c0b815d83f1a7f Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 4 Feb 2025 13:39:02 +0100 Subject: [PATCH 077/208] select options in extension configuration can retain order (only attributedefinitions) --- views/bootstrap/class.Settings.php | 12 +++++++++++- views/bootstrap/styles/application.js | 11 +++++++++++ views/bootstrap4/styles/application.js | 11 +++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/views/bootstrap/class.Settings.php b/views/bootstrap/class.Settings.php index 007fdf035..4d4924ef7 100644 --- a/views/bootstrap/class.Settings.php +++ b/views/bootstrap/class.Settings.php @@ -762,12 +762,22 @@ if(($kkk = $this->callHook('getFullSearchEngine')) && is_array($kkk)) case "attributedefinitions": $objtype = empty($conf['objtype']) ? 0 : $conf['objtype']; $attrtype = empty($conf['attrtype']) ? 0 : $conf['attrtype']; + $order = empty($conf['order']) ? '' : $conf['order']; $recs = $dms->getAllAttributeDefinitions($objtype, $attrtype); if($recs) { - echo ""; if($allowempty) echo ""; + if($order == 'keep') { + foreach($selections as $selid) { + if($rec = $dms->getAttributeDefinition($selid)) { + echo ""; + } + } + } foreach($recs as $rec) { + if($order == 'keep' && in_array($rec->getID(), $selections)) + continue; echo ""; } echo ""; } elseif(!empty($conf['internal'])) { From d9a2ea5303e8c83e90c82a77ec216c2e45c7d965 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 18 Feb 2025 13:27:20 +0100 Subject: [PATCH 107/208] show quota on chart page when listing total document size per user --- CHANGELOG | 1 + out/out.Charts.php | 1 + views/bootstrap/class.Charts.php | 24 ++++++++++++++++++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 94e0df855..b001e24c4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- Changes in version 5.1.39 -------------------------------------------------------------------------------- +- show quota on chart page when listing total document size per user -------------------------------------------------------------------------------- Changes in version 5.1.38 diff --git a/out/out.Charts.php b/out/out.Charts.php index 6988c4fab..2aa0a7fe9 100644 --- a/out/out.Charts.php +++ b/out/out.Charts.php @@ -53,6 +53,7 @@ if ($view) { $view->setParam('type', $type); $view->setParam('data', $data); $view->setParam('accessobject', $accessop); + $view->setParam('quota', $settings->_quota); $view($_GET); exit; } diff --git a/views/bootstrap/class.Charts.php b/views/bootstrap/class.Charts.php index e9f7f6749..549c94c23 100644 --- a/views/bootstrap/class.Charts.php +++ b/views/bootstrap/class.Charts.php @@ -249,6 +249,7 @@ $(document).ready( function() { $user = $this->params['user']; $data = $this->params['data']; $type = $this->params['type']; + $quota = $this->params['quota']; $this->htmlAddHeader( ''."\n". @@ -285,8 +286,12 @@ $(document).ready( function() { $this->contentContainerEnd(); echo ""; echo ""; - echo ""; - if(in_array($type, array('docspermonth', 'docsaccumulated'))) + echo ""; + echo ""; + $types = array('docspermonth', 'docsaccumulated'); + if($quota) + $types[] = 'sizeperuser'; + if(in_array($type, $types)) echo ""; echo ""; $total = 0; @@ -323,6 +328,21 @@ $(document).ready( function() { } break; case 'sizeperuser': + foreach($data as $item) { + $currUser = $dms->getUser($item['res']); + echo ""; + echo ""; + if($quota) { + echo ""; + } + echo ""; + $total += $item['total']; + } + echo ""; + break; case 'sizepermonth': foreach($data as $item) { echo ""; From 0fe367820f94b7e526481f23aa40ee9e159ff3c7 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 18 Feb 2025 21:20:59 +0100 Subject: [PATCH 108/208] turn off legend for chart sizepermonth --- views/bootstrap/class.Charts.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/views/bootstrap/class.Charts.php b/views/bootstrap/class.Charts.php index 549c94c23..da627df17 100644 --- a/views/bootstrap/class.Charts.php +++ b/views/bootstrap/class.Charts.php @@ -273,7 +273,7 @@ $(document).ready( function() { $this->contentContainerEnd(); $this->columnEnd(); - if(in_array($type, array('docspermonth', 'docsaccumulated'))) { + if(in_array($type, array('sizepermonth', 'docspermonth', 'docsaccumulated'))) { $this->columnStart(9); } else { $this->columnStart(6); @@ -354,7 +354,7 @@ $(document).ready( function() { echo "
".getMLText('chart_'.$type.'_title')."".getMLText('total')."".getMLText('chart_'.$type.'_title')."".getMLText('total')."
".htmlspecialchars($item['key'])."".SeedDMS_Core_File::format_filesize((int) $item['total']).""; + $qt = $currUser->getQuota() ? $currUser->getQuota() : $quota; + echo $this->getProgressBar($currUser->getUsedDiskSpace(), $qt); + echo "
".SeedDMS_Core_File::format_filesize($total)."
".htmlspecialchars($item['key'])."".SeedDMS_Core_File::format_filesize((int) $item['total'])."
"; $this->columnEnd(); - if(!in_array($type, array('docspermonth', 'docsaccumulated'))) { + if(!in_array($type, array('sizepermonth', 'docspermonth', 'docsaccumulated'))) { $this->columnStart(3); $this->contentHeading(getMLText('legend')); $this->contentContainerStart('', 'legend'); From 4352f95818e89c69e71ccbca2575eeb6a42555d7 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 18 Feb 2025 21:22:01 +0100 Subject: [PATCH 109/208] new export flag to skip default columns --- out/out.Search.php | 5 +++++ views/bootstrap/class.Search.php | 14 +++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/out/out.Search.php b/out/out.Search.php index 1f14ac23f..09c079f50 100644 --- a/out/out.Search.php +++ b/out/out.Search.php @@ -52,6 +52,10 @@ $includecontent = false; if (isset($_GET["includecontent"]) && $_GET["includecontent"]) $includecontent = true; +$skipdefaultcols = false; +if (isset($_GET["skipdefaultcols"]) && $_GET["skipdefaultcols"]) + $skipdefaultcols = true; + $newowner = null; if (isset($_GET["newowner"]) && is_numeric($_GET["newowner"]) && $_GET['newowner'] > 0) { $newowner = $dms->getUser((int) $_GET['newowner']); @@ -735,6 +739,7 @@ if($settings->_showSingleSearchHit && count($entries) == 1) { $view->setParam('accessobject', $accessop); $view->setParam('query', $query); $view->setParam('includecontent', $includecontent); + $view->setParam('skipdefaultcols', $skipdefaultcols); $view->setParam('marks', isset($_GET['marks']) ? $_GET['marks'] : array()); $view->setParam('newowner', $newowner); $view->setParam('newreviewer', $newreviewer); diff --git a/views/bootstrap/class.Search.php b/views/bootstrap/class.Search.php index 428bc3923..bb7e754b3 100644 --- a/views/bootstrap/class.Search.php +++ b/views/bootstrap/class.Search.php @@ -57,7 +57,7 @@ $(document).ready( function() { $('#export').on('click', function(ev) { ev.preventDefault(); ev.stopPropagation(); - var url = $(this).attr('href')+'&includecontent='+($('#includecontent').prop('checked') ? '1' : '0'); + var url = $(this).attr('href')+'&includecontent='+($('#includecontent').prop('checked') ? '1' : '0')+'&skipdefaultcols='+($('#skipdefaultcols').prop('checked') ? '1' : '0'); var values = {}; $('input[name^=\"marks\"]').each(function() { if(this.checked) @@ -225,10 +225,12 @@ $(document).ready(function() { $user = $this->params['user']; $entries = $this->params['searchhits']; $includecontent = $this->params['includecontent']; + $skipdefaultcols = $this->params['skipdefaultcols']; $marks = $this->params['marks']; include("../inc/inc.ClassDownloadMgr.php"); $downmgr = new SeedDMS_Download_Mgr(); + $downmgr->skipDefaultCols($skipdefaultcols); if($extraheader = $this->callHook('extraDownloadHeader')) $downmgr->addHeader($extraheader); foreach($entries as $entry) { @@ -1487,6 +1489,16 @@ $(document).ready(function() { 'value'=>1, ) ); + $this->formField( + getMLText("skip_default_export_cols"), + array( + 'element'=>'input', + 'type'=>'checkbox', + 'name'=>'skipdefaultcols', + 'id'=>'skipdefaultcols', + 'value'=>1, + ) + ); //$this->formSubmit(" ".getMLText('export')); print $this->html_link('Search', array_merge($_GET, array('action'=>'export')), array('class'=>'btn btn-primary', 'id'=>'export'), " ".getMLText("batch_export"), false, true)."\n"; $content = ob_get_clean(); From 879855536fad1e1fd0b5e8a55e45947988e409eb Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 18 Feb 2025 21:22:27 +0100 Subject: [PATCH 110/208] new flag to skip exporting default columns --- inc/inc.ClassDownloadMgr.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/inc/inc.ClassDownloadMgr.php b/inc/inc.ClassDownloadMgr.php index d809e0526..4e4f6dad0 100644 --- a/inc/inc.ClassDownloadMgr.php +++ b/inc/inc.ClassDownloadMgr.php @@ -103,7 +103,15 @@ class SeedDMS_Download_Mgr { $this->tmpdir = $tmpdir; $this->items = array(); $this->folder_items = array(); - $this->header = array(getMLText('download_header_document_no'), getMLText('download_header_document_name'), getMLText('download_header_filename'), getMLText('download_header_state'), getMLText('download_header_internal_version'), getMLText('download_header_reviewer'), getMLText('download_header_review_date'), getMLText('download_header_review_comment'), getMLText('download_header_review_state'), getMLText('download_header_approver'), getMLText('download_header_approval_date'), getMLText('download_header_approval_comment'), getMLText('download_header_approval_state')); + $this->header = array(getMLText('download_header_document_no'), getMLText('download_header_document_name'), getMLText('download_header_filename'), getMLText('download_header_state'), getMLText('download_header_internal_version')); + $this->header[] = getMLText('download_header_reviewer'); + $this->header[] = getMLText('download_header_review_date'); + $this->header[] = getMLText('download_header_review_comment'); + $this->header[] = getMLText('download_header_review_state'); + $this->header[] = getMLText('download_header_approver'); + $this->header[] = getMLText('download_header_approval_date'); + $this->header[] = getMLText('download_header_approval_comment'); + $this->header[] = getMLText('download_header_approval_state'); $this->folder_header = array(getMLText('download_header_folder_no'), getMLText('download_header_folder_name')); $this->extracols = array(); $this->folder_extracols = array(); @@ -111,10 +119,11 @@ class SeedDMS_Download_Mgr { $this->extraheader = array(); $this->folder_extraheader = array(); $this->filenames = array(); - $this->skipdefaultcols = false; + $this->includereviewers = false; + $this->includeapprovers = false; } - public function setSkipDefaultCols($v) { /* {{{ */ + public function skipDefaultCols($v) { /* {{{ */ $this->skipdefaultcols = (bool) $v; } /* }}} */ From a44ddc0b941f7122cc3eb998fed3f424c9d319bc Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 21 Feb 2025 07:34:24 +0100 Subject: [PATCH 111/208] remove old code, add error middleware and catch all route --- index.php | 50 ++++++++------------------------------------------ 1 file changed, 8 insertions(+), 42 deletions(-) diff --git a/index.php b/index.php index bf780ef9a..5fe1d480c 100644 --- a/index.php +++ b/index.php @@ -44,32 +44,9 @@ if(true) { $containerBuilder = new \DI\ContainerBuilder(); $c = $containerBuilder->build(); - /* - $c['notFoundHandler'] = function ($c) use ($settings, $dms) { - return function ($request, $response) use ($c, $settings, $dms) { - $uri = $request->getUri(); - if($uri->getBasePath()) - $file = $uri->getPath(); - else - $file = substr($uri->getPath(), 1); - if(file_exists($file) && is_file($file)) { - $_SERVER['SCRIPT_FILENAME'] = basename($file); -// include($file); - exit; - } - if($request->isXhr()) { - exit; - } -// print_r($request->getUri()); -// exit; - return $c['response'] - ->withStatus(302) - ->withHeader('Location', isset($settings->_siteDefaultPage) && strlen($settings->_siteDefaultPage)>0 ? $settings->_httpRoot.$settings->_siteDefaultPage : $settings->_httpRoot."out/out.ViewFolder.php"); - }; - }; - */ AppFactory::setContainer($c); $app = AppFactory::create(); + /* put lots of data into the container, because if slim instanciates * a class by itself (with the help from the DI container), it will * pass the container to the constructor of the instanciated class. @@ -91,12 +68,8 @@ if(true) { } } - $app->get('/', function($request, $response) { - return $response - ->withHeader('Location', '/out/out.ViewFolder.php') - ->withStatus(302); + $app->addErrorMiddleware(false, true, true); - }); if(isset($GLOBALS['SEEDDMS_HOOKS']['initDMS'])) { foreach($GLOBALS['SEEDDMS_HOOKS']['initDMS'] as $hookObj) { if (method_exists($hookObj, 'addRoute')) { @@ -107,20 +80,13 @@ if(true) { } } - /* - $app->get('/out/[{path:.*}]', function($request, $response, $path = null) use ($app) { - $uri = $request->getUri(); - if($uri->getBasePath()) - $file = $uri->getPath(); - else - $file = substr($uri->getPath(), 1); - if(file_exists($file) && is_file($file)) { - $_SERVER['SCRIPT_FILENAME'] = basename($file); - include($file); - exit; - } + /* Catch all route */ + $app->get('/{path:.*}', function($request, $response) { + return $response + ->withHeader('Location', '/out/out.ViewFolder.php') + ->withStatus(302); + }); - */ $app->run(); } else { From 3538fd26168e1ecf274b6d9c4a75c1962a3576d8 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 21 Feb 2025 07:34:55 +0100 Subject: [PATCH 112/208] add slim error middleware and catch all route --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index b001e24c4..fe07e2f5d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ Changes in version 5.1.39 -------------------------------------------------------------------------------- - show quota on chart page when listing total document size per user +- turn off legend for chart sizepermonth -------------------------------------------------------------------------------- Changes in version 5.1.38 From 6731882ae0b2182474dcbe0a08d60c652b2c0dbe Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 27 Feb 2025 09:04:55 +0100 Subject: [PATCH 113/208] do not add group manager as mandatory reviewer/approver if logged in user is the manager itself --- inc/inc.Utils.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/inc/inc.Utils.php b/inc/inc.Utils.php index d42938604..f2392b35c 100644 --- a/inc/inc.Utils.php +++ b/inc/inc.Utils.php @@ -1075,7 +1075,9 @@ function getMandatoryReviewers($folder, $document, $user) { /* {{{ */ foreach($groups as $group) { $managers = $group->getManagers(); foreach($managers as $manager) { - $revi[] = $manager->getId(); + /* Do not add myself, if I'm the manager of the group */ + if($manager->getId() != $user->getId()) + $revi[] = $manager->getId(); } } } @@ -1170,7 +1172,9 @@ function getMandatoryApprovers($folder, $document, $user) { /* {{{ */ foreach($groups as $group) { $managers = $group->getManagers(); foreach($managers as $manager) { - $appi[] = $manager->getId(); + /* Do not add myself, if I'm the manager of the group */ + if($manager->getId() != $user->getId()) + $appi[] = $manager->getId(); } } } From f281376ac2b4642e7ac3844dbfefea7aa247cea0 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 27 Feb 2025 09:05:49 +0100 Subject: [PATCH 114/208] fix setting group approvers from previous version --- views/bootstrap/class.UpdateDocument.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/views/bootstrap/class.UpdateDocument.php b/views/bootstrap/class.UpdateDocument.php index ae9b7fc7a..68f9e8b28 100644 --- a/views/bootstrap/class.UpdateDocument.php +++ b/views/bootstrap/class.UpdateDocument.php @@ -559,10 +559,12 @@ console.log(element); $tmp = array(); foreach($approvalStatus as $r) { if($r['type'] == 1) { - if(!in_array($r['required'], $mapprovers['g'])) + if($mapprovers) { + if(!in_array($r['required'], $mapprovers['g'])) + $tmp[] = $r['required']; + } else { $tmp[] = $r['required']; - } else { - $tmp[] = $r['required']; + } } } $fieldwrap = array('', ''); From 9f5390e560f6884f2446c20d2d3ef983e77f443a Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 27 Feb 2025 09:06:19 +0100 Subject: [PATCH 115/208] add checkbox for enabling memcached --- op/op.Settings.php | 1 + views/bootstrap/class.Settings.php | 1 + 2 files changed, 2 insertions(+) diff --git a/op/op.Settings.php b/op/op.Settings.php index 704eb8da2..a682ec2b6 100644 --- a/op/op.Settings.php +++ b/op/op.Settings.php @@ -194,6 +194,7 @@ if ($action == "saveSettings") setStrValue("partitionSize"); // TODO: check if valid value, e.g. 1M or 5K setStrValue("maxUploadSize"); // TODO: check if valid value, e.g. 1M or 5K setBoolValue("enableXsendfile"); + setBoolValue("enableMemcached"); // SETTINGS - SYSTEM - AUTHENTICATION setBoolValue("enableGuestLogin"); diff --git a/views/bootstrap/class.Settings.php b/views/bootstrap/class.Settings.php index c3f4f9dab..7eec265b0 100644 --- a/views/bootstrap/class.Settings.php +++ b/views/bootstrap/class.Settings.php @@ -527,6 +527,7 @@ if(($kkk = $this->callHook('getFullSearchEngine')) && is_array($kkk)) showConfigText('settings_partitionSize', 'partitionSize'); ?> showConfigText('settings_maxUploadSize', 'maxUploadSize'); ?> showConfigCheckbox('settings_enableXsendfile', 'enableXsendfile'); ?> +showConfigCheckbox('settings_enableMemcached', 'enableMemcached'); ?> From e714e361a9846ececf01882144f358d6d822c95a Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 27 Feb 2025 09:07:06 +0100 Subject: [PATCH 116/208] add checkbox for enabling memcached --- inc/inc.ClassSettings.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/inc/inc.ClassSettings.php b/inc/inc.ClassSettings.php index e6439fb65..ac403bbef 100644 --- a/inc/inc.ClassSettings.php +++ b/inc/inc.ClassSettings.php @@ -144,6 +144,8 @@ class Settings { /* {{{ */ var $_batchOperations = array(); // or 'all', 'change_owner', etc. // jump straight to the document if it is the only hit of a search var $_showSingleSearchHit = true; + // enable/disable use of memcached + var $_enableMemcached = false; // contentOffsetDirTo var $_contentOffsetDir = "1048576"; // Maximum number of sub-directories per parent directory @@ -647,6 +649,7 @@ class Settings { /* {{{ */ $this->_partitionSize = strval($tab["partitionSize"]); $this->_maxUploadSize = strval($tab["maxUploadSize"]); $this->_enableXsendfile = Settings::boolVal($tab["enableXsendfile"]); + $this->_enableMemcached = Settings::boolVal($tab["enableMemcached"]); } // XML Path: /configuration/system/authentication @@ -1045,6 +1048,7 @@ class Settings { /* {{{ */ $this->setXMLAttributValue($node, "partitionSize", $this->_partitionSize); $this->setXMLAttributValue($node, "maxUploadSize", $this->_maxUploadSize); $this->setXMLAttributValue($node, "enableXsendfile", $this->_enableXsendfile); + $this->setXMLAttributValue($node, "enableMemcached", $this->_enableMemcached); // XML Path: /configuration/system/authentication $node = $this->getXMLNode($xml, '/configuration/system', 'authentication'); From 985aa5cc28db005d4045eca1f5b4fefccae804b3 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 27 Feb 2025 09:07:19 +0100 Subject: [PATCH 117/208] check im memcached is turned on in configuration --- inc/inc.DBInit.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/inc.DBInit.php b/inc/inc.DBInit.php index dafc2d1ea..5c5f41bba 100644 --- a/inc/inc.DBInit.php +++ b/inc/inc.DBInit.php @@ -56,7 +56,7 @@ if(isset($GLOBALS['SEEDDMS_HOOKS']['initStorage'])) { $dms = new SeedDMS_Core_DMS($db, $storage ? $storage : $settings->_contentDir.$settings->_contentOffsetDir); -if(extension_loaded('memcached')) { +if($settings->_enableMemcached && extension_loaded('memcached')) { $memcache = new Memcached('seeddms'); $memcache->addServers(array( array('localhost',11211), From 6c0b1691c3af6e1210b61cae7595b9a651e9ec69 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 27 Feb 2025 09:08:34 +0100 Subject: [PATCH 118/208] add changes of 5.1.39 --- CHANGELOG | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index fe07e2f5d..7c36c72a2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,11 @@ -------------------------------------------------------------------------------- - show quota on chart page when listing total document size per user - turn off legend for chart sizepermonth +- do not add group manager as mandatory approver/reviewer if logged in + user is the manager itself +- fixed setting group approvers from previous document version +- very experimental support of memcached for accelerating some database + operations (do not use in production) -------------------------------------------------------------------------------- Changes in version 5.1.38 From 0999808364b9f0f2b5c83c122281ff51455f1792 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 27 Feb 2025 09:26:44 +0100 Subject: [PATCH 119/208] add new phrases, updates --- languages/ar_EG/lang.inc | 2 ++ languages/bg_BG/lang.inc | 2 ++ languages/ca_ES/lang.inc | 2 ++ languages/cs_CZ/lang.inc | 2 ++ languages/de_DE/lang.inc | 4 +++- languages/el_GR/lang.inc | 2 ++ languages/en_GB/lang.inc | 4 +++- languages/es_ES/lang.inc | 2 ++ languages/fr_FR/lang.inc | 8 +++++--- languages/hr_HR/lang.inc | 2 ++ languages/hu_HU/lang.inc | 2 ++ languages/id_ID/lang.inc | 10 ++++++---- languages/it_IT/lang.inc | 2 ++ languages/ko_KR/lang.inc | 2 ++ languages/lo_LA/lang.inc | 2 ++ languages/nb_NO/lang.inc | 2 ++ languages/nl_NL/lang.inc | 2 ++ languages/pl_PL/lang.inc | 2 ++ languages/pt_BR/lang.inc | 2 ++ languages/ro_RO/lang.inc | 2 ++ languages/ru_RU/lang.inc | 2 ++ languages/sk_SK/lang.inc | 2 ++ languages/sv_SE/lang.inc | 2 ++ languages/tr_TR/lang.inc | 2 ++ languages/uk_UA/lang.inc | 2 ++ languages/zh_CN/lang.inc | 2 ++ languages/zh_TW/lang.inc | 2 ++ 27 files changed, 63 insertions(+), 9 deletions(-) diff --git a/languages/ar_EG/lang.inc b/languages/ar_EG/lang.inc index 0036e8ad6..d7b26d872 100644 --- a/languages/ar_EG/lang.inc +++ b/languages/ar_EG/lang.inc @@ -1683,6 +1683,8 @@ URL: [url]', 'settings_enableLargeFileUpload_desc' => 'تمكين تحميل الملفات الكبيرة', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'تمكين مهام القائمة', 'settings_enableMenuTasks_desc' => 'تمكين مهام القائمة', 'settings_enableMenuTransmittals' => '', diff --git a/languages/bg_BG/lang.inc b/languages/bg_BG/lang.inc index 2fec078d0..69dd99be8 100644 --- a/languages/bg_BG/lang.inc +++ b/languages/bg_BG/lang.inc @@ -1525,6 +1525,8 @@ $text = array( 'settings_enableLargeFileUpload_desc' => 'Ако е включено, качване на файлове е дустъпно и чрез джава-аплет, именован jumploader, без лимит за размер на файла. Това също ще позволи да се качват няколко файла наведнъж.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => '', 'settings_enableMenuTasks_desc' => '', 'settings_enableMenuTransmittals' => '', diff --git a/languages/ca_ES/lang.inc b/languages/ca_ES/lang.inc index 2c7a40dc3..ba7301b4c 100644 --- a/languages/ca_ES/lang.inc +++ b/languages/ca_ES/lang.inc @@ -1530,6 +1530,8 @@ URL: [url]', 'settings_enableLargeFileUpload_desc' => '', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => '', 'settings_enableMenuTasks_desc' => '', 'settings_enableMenuTransmittals' => '', diff --git a/languages/cs_CZ/lang.inc b/languages/cs_CZ/lang.inc index 7929d6c50..6a2a9920b 100644 --- a/languages/cs_CZ/lang.inc +++ b/languages/cs_CZ/lang.inc @@ -1755,6 +1755,8 @@ Jméno: [username] 'settings_enableLargeFileUpload_desc' => 'Je-li nastaveno, nahrávání souborů je také k dispozici prostřednictvím java appletu s názvem jumploader bez omezení velikosti souboru nastaveného prohlížečem. Umožňuje také nahrát několik souborů v jednom kroku.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'Povolit seznam úkolů v nabídce', 'settings_enableMenuTasks_desc' => 'Aktivovat / Zakázat položku nabídky, která obsahuje všechny úkoly pro uživatele. Obsahuje dokumenty, které musí být přezkoumány, schváleny atd.', 'settings_enableMenuTransmittals' => '', diff --git a/languages/de_DE/lang.inc b/languages/de_DE/lang.inc index 0ca34aff7..f12e0d09a 100644 --- a/languages/de_DE/lang.inc +++ b/languages/de_DE/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (3433), dgrutsch (22) +// Translators: Admin (3435), dgrutsch (22) $text = array( '2_factor_auth' => '2-Faktor Authentifizierung', @@ -2146,6 +2146,8 @@ Sollten Sie kein Passwort bekommen haben, dann nutzen Sie bitte die Passwort-Ver 'settings_enableLargeFileUpload_desc' => 'Wenn dies gesetzt ist, dann ist ebenfalls der Upload von Dokumenten durch ein java applet mit Namen \'jumploader\' ohne Begrenzung der maximalen Dateigröße möglich. Auch das Hochladen mehrerer Dokumente in einem Schritt wird dadurch ermöglicht. Das Einschalten bewirkt, dass keine http only Cookies mehr gesetzt werden.', 'settings_enableLoginByEmail' => 'Anmeldung mit E-Mail erlauben', 'settings_enableLoginByEmail_desc' => 'Wenn eingeschaltet, dann ist auch die Anmeldung mit der E-Mail-Adresse möglich. Die Anmeldung mit dem Benutzername bleibt weiterhin möglich. Diese Einstellung wird möglicherweise nicht von allen Authentifizierungsmethoden berücksichtigt. Da die E-Mail nicht eindeutig ist, kann die Identifikation fehlschagen, auch wenn das Password aus Sicht des anmeldenen Benutzers korrekt ist.', +'settings_enableMemcached' => 'Memcached verwenden', +'settings_enableMemcached_desc' => 'Verwendet intern memcached, um einige Datenbankoperationen zu beschleunigen und sollte nicht im Produktionsbetrieb eingeschaltet werden.', 'settings_enableMenuTasks' => 'Aufgabenliste im Menü', 'settings_enableMenuTasks_desc' => 'Ein-/Ausschalten des Menüeintrags, der anstehenden Aufgaben des Benutzers enthält. Diese Liste beinhaltet Dokumente die geprüft, freigegeben, usw. werden müssen.', 'settings_enableMenuTransmittals' => 'Dokumentenlisten im Menü', diff --git a/languages/el_GR/lang.inc b/languages/el_GR/lang.inc index 14fbed705..6f88ba684 100644 --- a/languages/el_GR/lang.inc +++ b/languages/el_GR/lang.inc @@ -1536,6 +1536,8 @@ URL: [url]', 'settings_enableLargeFileUpload_desc' => '', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => '', 'settings_enableMenuTasks_desc' => '', 'settings_enableMenuTransmittals' => '', diff --git a/languages/en_GB/lang.inc b/languages/en_GB/lang.inc index 51baa5b59..35724942d 100644 --- a/languages/en_GB/lang.inc +++ b/languages/en_GB/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (2531), archonwang (3), dgrutsch (9), netixw (14) +// Translators: Admin (2533), archonwang (3), dgrutsch (9), netixw (14) $text = array( '2_factor_auth' => '2-factor authentication', @@ -2148,6 +2148,8 @@ If you did not receive a password, please use the password forgotten function on 'settings_enableLargeFileUpload_desc' => 'If set, file upload is also available through a java applet called jumploader without a file size limit set by the browser. It also allows to upload several files in one step. Turning this on will turn off http only cookies.', 'settings_enableLoginByEmail' => 'Enable login by email', 'settings_enableLoginByEmail_desc' => 'If enabled, the user maya also use the email address for login. This will not disable login with the username. This setting may not be regarded by all authentication methods. Because the email is not unique, authentication may fail, even if the user enters a right password.', +'settings_enableMemcached' => 'Use memcached (experimental)', +'settings_enableMemcached_desc' => 'Use memcached for accelerating some database operations. This should not be be turned on in production.', 'settings_enableMenuTasks' => 'Enable task list in menu', 'settings_enableMenuTasks_desc' => 'Enable/Disable the menu item which contains all tasks for the user. This contains documents, that need to be reviewed, approved, etc.', 'settings_enableMenuTransmittals' => 'Enable transmittals in menu', diff --git a/languages/es_ES/lang.inc b/languages/es_ES/lang.inc index 10b6a45c8..bd0006183 100644 --- a/languages/es_ES/lang.inc +++ b/languages/es_ES/lang.inc @@ -1706,6 +1706,8 @@ URL: [url]', 'settings_enableLargeFileUpload_desc' => 'Si se habilita, la carga de ficheros también estará disponible a través de un applet java llamado jumploader, sin límite de tamaño de fichero fijado por el navegador. También permite la carga de múltiples ficheros de una sola vez.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'Activar en el menú la lista de tareas', 'settings_enableMenuTasks_desc' => 'Habilita/Deshabillita la parte del menú que contiene todas las tareas para el usuario. Contiene documentos que necesitan ser revisados, aprobados, etc.', 'settings_enableMenuTransmittals' => '', diff --git a/languages/fr_FR/lang.inc b/languages/fr_FR/lang.inc index a5132814b..48f7fcd92 100644 --- a/languages/fr_FR/lang.inc +++ b/languages/fr_FR/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (1173), jeromerobert (50), lonnnew (9), Oudiceval (1171) +// Translators: Admin (1175), jeromerobert (50), lonnnew (9), Oudiceval (1171) $text = array( '2_factor_auth' => 'Authentification forte', @@ -2093,6 +2093,8 @@ Nom : [username] 'settings_enableLargeFileUpload_desc' => 'Si défini, le téléchargement de fichier est également disponible via un applet java appelé jumploader sans limite de taille définie par le navigateur. Il permet également de télécharger plusieurs fichiers en une seule fois.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'Activer le menu des tâches', 'settings_enableMenuTasks_desc' => 'Affiche un menu avec la liste des tâches. Cette liste contient les documents en attente d’une action par l’utilisateur.', 'settings_enableMenuTransmittals' => '', @@ -2684,7 +2686,7 @@ URL : [url]

', 'type_to_filter' => 'Filtrer dans la liste', 'type_to_search' => 'Effectuer une recherche', 'uk_UA' => 'Ukrénien', -'undefined' => '', +'undefined' => 'indéfini', 'under_folder' => 'Dans le dossier', 'unknown_attrdef' => 'Définition d’attribut inconnue', 'unknown_command' => 'Commande non reconnue.', @@ -2703,7 +2705,7 @@ URL : [url]

', 'unlock_cause_locking_user' => 'Vous pouvez encore le mettre à jour, car vous êtes le seul à l\'avoir verrouillé. Le verrouillage sera automatiquement annulé.', 'unlock_document' => 'Déverrouiller', 'update' => 'Mettre à jour', -'updated' => '', +'updated' => 'mis à jour', 'updated_documents' => '', 'update_approvers' => 'Mettre à jour la liste des approbateurs', 'update_document' => 'Mettre à jour', diff --git a/languages/hr_HR/lang.inc b/languages/hr_HR/lang.inc index 4d918fdf6..726d24f6e 100644 --- a/languages/hr_HR/lang.inc +++ b/languages/hr_HR/lang.inc @@ -1719,6 +1719,8 @@ Internet poveznica: [url]', 'settings_enableLargeFileUpload_desc' => 'Ako je postavljeno, učitavanje datoteke je također dostupno kroz Java aplet naziva "jumploader" bez postavljenog ograničenja veličine datoteke od strane pretraživača. To također omogućuje učitavanje nekoliko datoteka u jednom koraku. Uključivanjem ovoga isključit će se samo http kolačići.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'Omogućavanje liste zadataka u izborniku', 'settings_enableMenuTasks_desc' => 'Omogućavanje/onemogućavanje stavke izbornika koja sadrži sve zadatke za korisnika. Ovo sadrži dokumente koji trebaju biti revidirani, odobreni itd.', 'settings_enableMenuTransmittals' => '', diff --git a/languages/hu_HU/lang.inc b/languages/hu_HU/lang.inc index f01240cdf..28e05914b 100644 --- a/languages/hu_HU/lang.inc +++ b/languages/hu_HU/lang.inc @@ -1696,6 +1696,8 @@ URL: [url]', 'settings_enableLargeFileUpload_desc' => 'Ha beállítja az állományok feltöltése elérhető lesz egy jumploadernek hívott java appleten keresztül a böngészőprogram állomány méret korlátja nélkül. Ez engedélyezi több állomány feltöltését egy lépésben.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'Feladatok menüpont engedélyezése', 'settings_enableMenuTasks_desc' => 'Engedélyezi / letiltja a menüelemet, amely a felhasználó összes feladatát tartalmazza. Ez olyan dokumentumokat tartalmaz, amelyeket felül kell vizsgálni, jóvá kell hagyni stb.', 'settings_enableMenuTransmittals' => '', diff --git a/languages/id_ID/lang.inc b/languages/id_ID/lang.inc index f57c3ff39..4ca2c9af1 100644 --- a/languages/id_ID/lang.inc +++ b/languages/id_ID/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (485), atoz-chevara (835) +// Translators: Admin (489), atoz-chevara (835) $text = array( '2_factor_auth' => '', @@ -382,7 +382,7 @@ URL: [url]

', 'dashboard' => '', 'databasesearch' => 'Pencarian Basis data', 'database_schema_version' => 'Versi skema basis data', -'data_loading' => '', +'data_loading' => 'Harap tunggu, data sedang disiapkan.', 'date' => 'Tanggal', 'days' => 'hari', 'debug' => 'Debug', @@ -689,7 +689,7 @@ URL: [url]

', 'empty_notify_list' => 'Tidak ada entri', 'enable_extension' => 'Aktifkan ekstensi', 'enddate' => '', -'en_GB' => '', +'en_GB' => 'Inggris (GB)', 'equal_transition_states' => 'Status awal dan akhir sama', 'error' => 'Galat', 'error_add_aro' => 'Kesalahan saat menambahkan objek permintaan akses', @@ -965,7 +965,7 @@ URL: [url]

', 'index_processing' => '', 'index_waiting' => 'Mengunggu', 'individuals' => 'Perorangan', -'individuals_in_groups' => '', +'individuals_in_groups' => 'Anggota di grup', 'ind_review_removed' => 'Perubahan status, karena ulasan pengguna [name] telah dihapus.', 'info_recipients_tab_not_released' => '', 'info_rm_user_from_processes_none' => '', @@ -1786,6 +1786,8 @@ Jika Anda tidak menerima kata sandi, silakan gunakan fitur lupa kata sandi di ha 'settings_enableLargeFileUpload_desc' => 'Jika disetel, unggah berkas juga tersedia melalui java applet yang disebut jumploader tanpa batas ukuran berkas yang ditetapkan oleh peramban. Ini juga memungkinkan untuk mengunggah beberapa berkas dalam satu langkah. Mengaktifkan ini akan mematikan cookie http saja.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'Aktifkan daftar task di menu', 'settings_enableMenuTasks_desc' => '', 'settings_enableMenuTransmittals' => '', diff --git a/languages/it_IT/lang.inc b/languages/it_IT/lang.inc index 7186a045d..a14a9b3f4 100644 --- a/languages/it_IT/lang.inc +++ b/languages/it_IT/lang.inc @@ -1742,6 +1742,8 @@ Name: [username] 'settings_enableLargeFileUpload_desc' => 'Se selezionato, il caricamento (upload) dei files può essere effettuato anche attraverso un\'applet Java chiamata Jumploader evitando il limite di dimensioni file imposto dal browser; Jumploader permette anche il caricamento di diversi files contemporaneamente.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'Abilita compito delle attività nel menù', 'settings_enableMenuTasks_desc' => 'Abilita/disabilita la voce di menu che contiene tutte le attività degli utenti. Questo conterrà i documenti che devono essere rivisti, approvati, etc.', 'settings_enableMenuTransmittals' => '', diff --git a/languages/ko_KR/lang.inc b/languages/ko_KR/lang.inc index b71a5cf17..d77801260 100644 --- a/languages/ko_KR/lang.inc +++ b/languages/ko_KR/lang.inc @@ -1713,6 +1713,8 @@ URL : [url]', 'settings_enableLargeFileUpload_desc' => '설정하면, 브라우저가 설정 한 파일 크기 제한없이 jumploader라는 파일 업로드 자바 애플릿을 통해 사용할 수 있습니다. 또한 한 번에 여러 파일을 업로드 할 수 있습니다.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => '메뉴의 작업 목록 허용', 'settings_enableMenuTasks_desc' => '사용자의 모든 작업이 포함되어있는 메뉴 항목을 활성/비활성 합니다. 이것은 검토, 승인등이 필요한 문서를 포함 합니다', 'settings_enableMenuTransmittals' => '', diff --git a/languages/lo_LA/lang.inc b/languages/lo_LA/lang.inc index ce3f7705a..32ffdf505 100644 --- a/languages/lo_LA/lang.inc +++ b/languages/lo_LA/lang.inc @@ -1739,6 +1739,8 @@ URL: [url]', 'settings_enableLargeFileUpload_desc' => 'ການຕັ້ງຄ່າອັບໂຫລດໄຟລຈະມີໃຫ້ບໍລິການຜ່ານທາງດ້ານຂວາຂອງເອັບເຟັກທີ່ເອີ້ນວ່າ jumploader ໂດຍບໍ່ມີຂິດຈຳກັດຂອງຂະໜາດໄຟລທີກຳນົດໂດຍບາວເຊີ ນອກຈາກນີຍັງຊ່ວຍໃນການອັບໂຫລດໄຟລຫຼາຍໄຟລໃນຂັນຕອນດຽວການເປີດຄຸນລັກສະນະນີ້ຈະປິດຄຸກກີ້ສະເພາະ Http ເທົ່ານັ້ນ', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'ເປີດການໄຊ້ງານ', 'settings_enableMenuTasks_desc' => 'ເປີດ/ປິດ ລາຍການເມນູທີ່ມີວຽກທັງໝົດສຳລັບຜູ້ໄຊ້ເອກະສານນີ້ມີເອກະສານທີຈ້ອງໄດ້ຮັບການກວດສອບ', 'settings_enableMenuTransmittals' => '', diff --git a/languages/nb_NO/lang.inc b/languages/nb_NO/lang.inc index 4c6da3e96..b85063e86 100644 --- a/languages/nb_NO/lang.inc +++ b/languages/nb_NO/lang.inc @@ -1752,6 +1752,8 @@ Bruker: [username] 'settings_enableLargeFileUpload_desc' => 'Hvis det er satt, er filopplasting også tilgjengelig via en java-applet som heter jumploader uten en filstørrelsesgrense som er angitt av nettleseren. Det gjør det også mulig å laste opp flere filer på ett trinn. Hvis du slår på dette, slås bare av cookies.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'Aktiver oppgaveliste i menyen', 'settings_enableMenuTasks_desc' => 'Aktiver/deaktiver menypunktet som inneholder alle oppgaver for brukeren. Denne inneholder dokumenter som må gjennomgås, godkjennes osv.', 'settings_enableMenuTransmittals' => '', diff --git a/languages/nl_NL/lang.inc b/languages/nl_NL/lang.inc index f5c604927..06e7b1513 100644 --- a/languages/nl_NL/lang.inc +++ b/languages/nl_NL/lang.inc @@ -1751,6 +1751,8 @@ Name: [username] 'settings_enableLargeFileUpload_desc' => 'Indien ingeschakeld, is bestandsupload ook beschikbaar via een java applet jumploader genaamd zonder een bestandsgrootte limiet door de browser. Het staat ook toe om meerdere bestanden in een keer te versturen.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'Menu-taken aanzetten', 'settings_enableMenuTasks_desc' => 'Menu-taken aanzetten', 'settings_enableMenuTransmittals' => '', diff --git a/languages/pl_PL/lang.inc b/languages/pl_PL/lang.inc index 8bdd509bd..c30be33a3 100644 --- a/languages/pl_PL/lang.inc +++ b/languages/pl_PL/lang.inc @@ -1682,6 +1682,8 @@ Name: [username] 'settings_enableLargeFileUpload_desc' => 'Jeśli zaznaczone, wczytywanie plików będzie możliwe również przez aplet javy bez limitu rozmiaru plików. Aplet pozwala również na wczytywanie wielu plików jednocześnie.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'Włącz listę zadań w menu', 'settings_enableMenuTasks_desc' => 'Włącza/Wyłącza pozycję w menu w której znajdują się wszystkie zadania dla użytkownika. Zawiera dokumenty, które potrzebują być ocenione, zatwierdzone, itd.', 'settings_enableMenuTransmittals' => '', diff --git a/languages/pt_BR/lang.inc b/languages/pt_BR/lang.inc index 0aecf194a..e4ccc69b8 100644 --- a/languages/pt_BR/lang.inc +++ b/languages/pt_BR/lang.inc @@ -1758,6 +1758,8 @@ Nome: [username] 'settings_enableLargeFileUpload_desc' => 'Se selecionado, o upload de arquivo também estará disponível através de um applet java chamado jumploader sem limite de tamanho de arquivo definido pelo navegador. Ele também permite fazer o upload de vários arquivos de uma só vez.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'Ativar lista de tarefas no menu', 'settings_enableMenuTasks_desc' => 'Ativar / desativar o item de menu que contém todas as tarefas do usuário. Contém documentos que precisam ser revisados, aprovados etc.', 'settings_enableMenuTransmittals' => '', diff --git a/languages/ro_RO/lang.inc b/languages/ro_RO/lang.inc index 6d6df45f2..1c71319c6 100644 --- a/languages/ro_RO/lang.inc +++ b/languages/ro_RO/lang.inc @@ -1720,6 +1720,8 @@ URL: [url]', 'settings_enableLargeFileUpload_desc' => 'Dacă este setat, incărcarea este de asemenea disponibilă prin intermediul unui applet Java numit jumploader fără limită de dimensiune a fișierului stabilită de browser. De asemenea, permite încărcarea mai multor fișiere într-un singur pas. Activand aceasta optiune va dezactiva optiunea http only cookies.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => '', 'settings_enableMenuTasks_desc' => '', 'settings_enableMenuTransmittals' => '', diff --git a/languages/ru_RU/lang.inc b/languages/ru_RU/lang.inc index 3f6485a2d..ee185d1ed 100644 --- a/languages/ru_RU/lang.inc +++ b/languages/ru_RU/lang.inc @@ -1727,6 +1727,8 @@ URL: [url]', 'settings_enableLargeFileUpload_desc' => 'Если включено, загрузка файлов доступна так же через Java-апплет, называемый jumploader, без ограничения размера файла. Это также позволит загружать несколько файлов за раз.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'Включить список задач в меню', 'settings_enableMenuTasks_desc' => 'Включить/отключить пункт меню, который содержит все задачи пользователя. Там содержатся документы, которые нуждаются в рецензии, утверждении и т.д.', 'settings_enableMenuTransmittals' => '', diff --git a/languages/sk_SK/lang.inc b/languages/sk_SK/lang.inc index 2ad5de322..b813c91bc 100644 --- a/languages/sk_SK/lang.inc +++ b/languages/sk_SK/lang.inc @@ -1760,6 +1760,8 @@ Meno: [username] 'settings_enableLargeFileUpload_desc' => 'If set, file upload is also available through a java applet called jumploader without a file size limit set by the browser. It also allows to upload several files in one step. Turning this on will turn off http only cookies.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'Enable task list in menu', 'settings_enableMenuTasks_desc' => 'Enable/Disable the menu item which contains all tasks for the user. This contains documents, that need to be reviewed, approved, etc.', 'settings_enableMenuTransmittals' => '', diff --git a/languages/sv_SE/lang.inc b/languages/sv_SE/lang.inc index 855648274..6485b5f10 100644 --- a/languages/sv_SE/lang.inc +++ b/languages/sv_SE/lang.inc @@ -1733,6 +1733,8 @@ Kommentar: [comment]', 'settings_enableLargeFileUpload_desc' => 'Om aktiverad, kan filer laddas upp via javaapplet med namnet jumploader, utan begränsningar i filstorlek. Flera filer kan även laddas upp samtidigt i ett steg.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'Aktivera uppgiftslista i menyn', 'settings_enableMenuTasks_desc' => 'Aktiverar ett menyobjekt som visar användarens uppgifter, såsom dokument som behöver granskas eller godkännas.', 'settings_enableMenuTransmittals' => '', diff --git a/languages/tr_TR/lang.inc b/languages/tr_TR/lang.inc index 66856745c..8c104fe63 100644 --- a/languages/tr_TR/lang.inc +++ b/languages/tr_TR/lang.inc @@ -1697,6 +1697,8 @@ URL: [url]', 'settings_enableLargeFileUpload_desc' => 'Etkinleştirilirse, büyük dosyalar dosya limitine bakılmaksızın jumploader isimli java applet aracılığıyla yüklenebilir. Bu ayrıca bir seferde birden çok dosya yüklemeyi de sağlar. Bu açıldığında sadece http çerezleri kapanmış olur.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => '', 'settings_enableMenuTasks_desc' => '', 'settings_enableMenuTransmittals' => '', diff --git a/languages/uk_UA/lang.inc b/languages/uk_UA/lang.inc index 2c586a27f..f55436cc5 100644 --- a/languages/uk_UA/lang.inc +++ b/languages/uk_UA/lang.inc @@ -1719,6 +1719,8 @@ URL: [url]', 'settings_enableLargeFileUpload_desc' => 'Якщо увімкнено, завантаження файлів доступне також через Java-аплет jumploader без обмеження розміру файлів. Це також дозволить завантажувати кілька файлів за раз.', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => 'Включити список завдань в меню', 'settings_enableMenuTasks_desc' => 'Включити/відключити пункт меню, який містить всі завдання користувача. Там містяться документи, які потребують рецензії, затвердження і т.ін.', 'settings_enableMenuTransmittals' => '', diff --git a/languages/zh_CN/lang.inc b/languages/zh_CN/lang.inc index 4505f5c79..e043538a4 100644 --- a/languages/zh_CN/lang.inc +++ b/languages/zh_CN/lang.inc @@ -1707,6 +1707,8 @@ URL: [url]', 'settings_enableLargeFileUpload_desc' => '如果设置了文件上传,也可以通过一个名为jumploader的浏览器java小程序来实现文件上传。它还允许一次上传多个文件。打开此选项将关闭网页cookie。', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => '在菜单中启用任务列表', 'settings_enableMenuTasks_desc' => '启用/禁用包含用户所有任务的菜单项。其中包含需要审核、批准的文件等。', 'settings_enableMenuTransmittals' => '', diff --git a/languages/zh_TW/lang.inc b/languages/zh_TW/lang.inc index 2f04097e8..f10508d96 100644 --- a/languages/zh_TW/lang.inc +++ b/languages/zh_TW/lang.inc @@ -1758,6 +1758,8 @@ URL: [url]', 'settings_enableLargeFileUpload_desc' => '如果設置了該選項,則還可以通過一個名為Jumploader的Java小程序來上傳文件,而瀏覽器沒有設置文件大小限制。它還允許一步上傳幾個文件。啟用此功能將關閉僅HTTP cookie。', 'settings_enableLoginByEmail' => '', 'settings_enableLoginByEmail_desc' => '', +'settings_enableMemcached' => '', +'settings_enableMemcached_desc' => '', 'settings_enableMenuTasks' => '在菜單中啟用任務列表', 'settings_enableMenuTasks_desc' => '啟用/禁用包含用戶所有任務的菜單項。其中包含需要審查,批准等的文件。', 'settings_enableMenuTransmittals' => '', From 86362c5284d921558e9136bf80da1de34739a5ab Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 28 Feb 2025 08:40:06 +0100 Subject: [PATCH 120/208] fix output of attributes --- views/bootstrap/class.DocumentVersionDetail.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/bootstrap/class.DocumentVersionDetail.php b/views/bootstrap/class.DocumentVersionDetail.php index 91c2404c0..f77bd267b 100644 --- a/views/bootstrap/class.DocumentVersionDetail.php +++ b/views/bootstrap/class.DocumentVersionDetail.php @@ -352,7 +352,7 @@ class SeedDMS_View_DocumentVersionDetail extends SeedDMS_Theme_Style { print "
  • ".$arr[0].": ".$arr[1]."
  • \n"; } else { $attrdef = $attribute->getAttributeDefinition(); - print "
  • ".htmlspecialchars($attrdef->getName()).": ".htmlspecialchars(implode(', ', $attribute->getValueAsArray()))."
  • \n"; + print "
  • ".htmlspecialchars($attrdef->getName()).": ".htmlspecialchars($attribute->getValueAsString())."
  • \n"; } } } From 4ba50995699f5f5611a532b372771b456591d3c5 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 28 Feb 2025 17:53:54 +0100 Subject: [PATCH 121/208] getAttributeEditField() handels arrays of attr values propperly --- views/bootstrap/class.Bootstrap.php | 39 ++++++++++++++++++++---- views/bootstrap4/class.Bootstrap4.php | 43 ++++++++++++++++++++++----- 2 files changed, 68 insertions(+), 14 deletions(-) diff --git a/views/bootstrap/class.Bootstrap.php b/views/bootstrap/class.Bootstrap.php index 7d7f4408d..017e213a1 100644 --- a/views/bootstrap/class.Bootstrap.php +++ b/views/bootstrap/class.Bootstrap.php @@ -1966,6 +1966,15 @@ $(document).ready(function() { echo self::getAttributeEditField($attrdef, $attribute, $fieldname, $norequire, $namepostfix, $alwaysmultiple); } /* }}} */ + /** + * Return html code for an input/select field of an attribute + * + * The passed attribute ($attribute) can either be an object of type + * SeedDMS_Core_Attribute, scalar or an array. A scalar or array is + * passed when the method is called to create the search form. In that + * case $attribute has the value from the post data after submitting the + * search form. + */ function getAttributeEditField($attrdef, $attribute, $fieldname='attributes', $norequire=false, $namepostfix='', $alwaysmultiple=false) { /* {{{ */ $dms = $this->params['dms']; $attr_id = $fieldname.'_'.$attrdef->getId().($namepostfix ? '_'.$namepostfix : ''); @@ -2002,10 +2011,19 @@ $(document).ready(function() { $content .= $this->getDocumentChooserHtml("attr".$attrdef->getId(), $target, $attr_name); break; case SeedDMS_Core_AttributeDefinition::type_user: - $target = $attribute ? $attribute->getValueAsArray() : []; $objvalue = []; - foreach($target as $t) - $objvalue[] = $t->getId(); + if($attribute) { + if(is_object($attribute)) { + $target = $attribute->getValueAsArray(); + foreach($target as $t) + $objvalue[] = $t->getId(); + } elseif(is_array($attribute)) { + foreach($attribute as $t) + $objvalue[] = $t; + } else { + $objvalue[] = $attribute; + } + } $users = $dms->getAllUsers(); if($users) { $allowempty = $attrdef->getMinValues() == 0; @@ -2025,10 +2043,19 @@ $(document).ready(function() { } break; case SeedDMS_Core_AttributeDefinition::type_group: - $target = $attribute ? $attribute->getValueAsArray() : []; $objvalue = []; - foreach($target as $t) - $objvalue[] = $t->getId(); + if($attribute) { + if(is_object($attribute)) { + $target = $attribute->getValueAsArray(); + foreach($target as $t) + $objvalue[] = $t->getId(); + } elseif(is_array($attribute)) { + foreach($attribute as $t) + $objvalue[] = $t; + } else { + $objvalue[] = $attribute; + } + } $groups = $dms->getAllGroups(); if($groups) { $allowempty = $attrdef->getMinValues() == 0; diff --git a/views/bootstrap4/class.Bootstrap4.php b/views/bootstrap4/class.Bootstrap4.php index 93ffc29f2..9e7c2fa64 100644 --- a/views/bootstrap4/class.Bootstrap4.php +++ b/views/bootstrap4/class.Bootstrap4.php @@ -1985,6 +1985,15 @@ $(document).ready(function() { echo self::getAttributeEditField($attrdef, $attribute, $fieldname, $norequire, $namepostfix, $alwaysmultiple); } /* }}} */ + /** + * Return html code for an input/select field of an attribute + * + * The passed attribute ($attribute) can either be an object of type + * SeedDMS_Core_Attribute, scalar or an array. A scalar or array is + * passed when the method is called to create the search form. In that + * case $attribute has the value from the post data after submitting the + * search form. + */ function getAttributeEditField($attrdef, $attribute, $fieldname='attributes', $norequire=false, $namepostfix='', $alwaysmultiple=false) { /* {{{ */ $dms = $this->params['dms']; $attr_id = $fieldname.'_'.$attrdef->getId().($namepostfix ? '_'.$namepostfix : ''); @@ -2018,18 +2027,27 @@ $(document).ready(function() { $content .= "getMinValues() > 0) ? ' required="required"' : '')." data-rule-number=\"true\"/>"; break; */ case SeedDMS_Core_AttributeDefinition::type_folder: - $target = $attribute ? $attribute->getValue() : null; + $target = $attribute ? (is_object($attribute) ? $attribute->getValue() : $attribute) : null; $content .= $this->getFolderChooserHtml("attr".$attrdef->getId(), M_READWRITE, -1, $target, $attr_name, false); break; case SeedDMS_Core_AttributeDefinition::type_document: - $target = $attribute ? $attribute->getValue() : null; + $target = $attribute ? (is_object($attribute) ? $attribute->getValue() : $attribute) : null; $content .= $this->getDocumentChooserHtml("attr".$attrdef->getId(), $target, $attr_name); break; case SeedDMS_Core_AttributeDefinition::type_user: - $target = $attribute ? $attribute->getValueAsArray() : []; $objvalue = []; - foreach($target as $t) - $objvalue[] = $t->getId(); + if($attribute) { + if(is_object($attribute)) { + $target = $attribute->getValueAsArray(); + foreach($target as $t) + $objvalue[] = $t->getId(); + } elseif(is_array($attribute)) { + foreach($attribute as $t) + $objvalue[] = $t; + } else { + $objvalue[] = $attribute; + } + } $users = $dms->getAllUsers(); if($users) { $allowempty = $attrdef->getMinValues() == 0; @@ -2049,10 +2067,19 @@ $(document).ready(function() { } break; case SeedDMS_Core_AttributeDefinition::type_group: - $target = $attribute ? $attribute->getValueAsArray() : []; $objvalue = []; - foreach($target as $t) - $objvalue[] = $t->getId(); + if($attribute) { + if(is_object($attribute)) { + $target = $attribute->getValueAsArray(); + foreach($target as $t) + $objvalue[] = $t->getId(); + } elseif(is_array($attribute)) { + foreach($attribute as $t) + $objvalue[] = $t; + } else { + $objvalue[] = $attribute; + } + } $groups = $dms->getAllGroups(); if($groups) { $allowempty = $attrdef->getMinValues() == 0; From d66f12ae213c8d21a909926228d131857db05bc9 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 28 Feb 2025 17:54:52 +0100 Subject: [PATCH 122/208] do not tread each field of search form as multivalued --- views/bootstrap/class.Search.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/views/bootstrap/class.Search.php b/views/bootstrap/class.Search.php index bb7e754b3..7df547f82 100644 --- a/views/bootstrap/class.Search.php +++ b/views/bootstrap/class.Search.php @@ -794,9 +794,9 @@ $(document).ready(function() { } elseif(in_array($attrdef->getType(), [SeedDMS_Core_AttributeDefinition::type_int, SeedDMS_Core_AttributeDefinition::type_float]) && !$attrdef->getValueSet()) { $this->formField(htmlspecialchars($attrdef->getName().' ('.getMLText('from').')'), $this->getAttributeEditField($attrdef, !empty($attributes[$attrdef->getID()]['from']) ? $attributes[$attrdef->getID()]['from'] : '', 'attributes', true, 'from')); $this->formField(htmlspecialchars($attrdef->getName().' ('.getMLText('to').')'), $this->getAttributeEditField($attrdef, !empty($attributes[$attrdef->getID()]['to']) ? $attributes[$attrdef->getID()]['to'] : '', 'attributes', true, 'to')); - - } else - $this->formField(htmlspecialchars($attrdef->getName()), $this->getAttributeEditField($attrdef, isset($attributes[$attrdef->getID()]) ? $attributes[$attrdef->getID()] : '', 'attributes', true, '', true)); + } else { + $this->formField(htmlspecialchars($attrdef->getName()), $this->getAttributeEditField($attrdef, isset($attributes[$attrdef->getID()]) ? $attributes[$attrdef->getID()] : '', 'attributes', true, '', false)); + } } } } From 329b54d00f117efd769311243d67b1e5942c4e30 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Mar 2025 21:42:54 +0100 Subject: [PATCH 123/208] encrypt referer to prevent malicious manipulation --- op/op.SetLanguage.php | 3 +-- views/bootstrap/class.Bootstrap.php | 2 +- views/bootstrap4/class.Bootstrap4.php | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/op/op.SetLanguage.php b/op/op.SetLanguage.php index 9cb0b2d02..f9a2da8b8 100644 --- a/op/op.SetLanguage.php +++ b/op/op.SetLanguage.php @@ -31,5 +31,4 @@ include("../inc/inc.Authentication.php"); $session->setLanguage($_GET['lang']); -header("Location: http".((isset($_SERVER['HTTPS']) && (strcmp($_SERVER['HTTPS'],'off')!=0)) ? "s" : "")."://".$_SERVER['HTTP_HOST'].$_GET['referer']); -?> +header("Location: http".((isset($_SERVER['HTTPS']) && (strcmp($_SERVER['HTTPS'],'off')!=0)) ? "s" : "")."://".$_SERVER['HTTP_HOST'].decryptData($settings->_encryptionKey, $_GET['referer'])); diff --git a/views/bootstrap/class.Bootstrap.php b/views/bootstrap/class.Bootstrap.php index 017e213a1..a9bdcc62f 100644 --- a/views/bootstrap/class.Bootstrap.php +++ b/views/bootstrap/class.Bootstrap.php @@ -390,7 +390,7 @@ background-image: linear-gradient(to bottom, #882222, #111111);; echo "
  • "; else echo "
  • "; - echo "params['settings']->_httpRoot."op/op.SetLanguage.php?lang=".$currLang."&referer=".$_SERVER["REQUEST_URI"]."\">"; + echo "params['settings']->_httpRoot."op/op.SetLanguage.php?lang=".$currLang."&referer=".urlencode(encryptData($this->params['settings']->_encryptionKey, $_SERVER["REQUEST_URI"]))."\">"; echo getMLText($currLang)."
  • \n"; } echo " \n"; diff --git a/views/bootstrap4/class.Bootstrap4.php b/views/bootstrap4/class.Bootstrap4.php index 9e7c2fa64..843f11277 100644 --- a/views/bootstrap4/class.Bootstrap4.php +++ b/views/bootstrap4/class.Bootstrap4.php @@ -460,7 +460,7 @@ background-image: linear-gradient(to bottom, #882222, #111111);; echo " params['settings']->_httpRoot."op/op.SetLanguage.php?lang=".$currLang."&referer=".$_SERVER["REQUEST_URI"]."\">"; + echo " href=\"".$this->params['settings']->_httpRoot."op/op.SetLanguage.php?lang=".$currLang."&referer=".urlencode(encryptData($this->params['settings']->_encryptionKey, $_SERVER["REQUEST_URI"]))."\">"; echo getMLText($currLang)."\n"; } echo " \n"; From 056736ecc5b5fe3e3d826a967e7bbe3d5025e70b Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 3 Mar 2025 21:44:33 +0100 Subject: [PATCH 124/208] add changes for 5.1.39 --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 7c36c72a2..edd5eef3c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -8,6 +8,7 @@ - fixed setting group approvers from previous document version - very experimental support of memcached for accelerating some database operations (do not use in production) +- prevent malicious manipulation of referer when setting language -------------------------------------------------------------------------------- Changes in version 5.1.38 From 3197f25ce8dd45e06e80b4458f31065c0dec6592 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 5 Mar 2025 07:29:56 +0100 Subject: [PATCH 125/208] log password forgotten request --- op/op.PasswordForgotten.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/op/op.PasswordForgotten.php b/op/op.PasswordForgotten.php index a77341174..ca9dc5e7d 100644 --- a/op/op.PasswordForgotten.php +++ b/op/op.PasswordForgotten.php @@ -55,7 +55,12 @@ if($user) { $params['url'] = getBaseUrl().$settings->_httpRoot."out/out.ChangePassword.php?hash=".$hash; $params['url_prefix'] = getBaseUrl().$settings->_httpRoot; $emailobj->toIndividual($settings->_smtpSendFrom, $user, $subject, $message, $params); + if($logger) + $logger->log("PasswordForgotten: Request for '".$login."' send to '".$email."'", PEAR_LOG_INFO); } +} else { + if($logger) + $logger->log("PasswordForgotten: no such user '".$login."' with email '".$email."'", PEAR_LOG_WARNING); } header('Location: ../out/out.PasswordSend.php'); From 444af0831bc19a8949f8fe6cc4dff15a9c010a94 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 5 Mar 2025 07:56:55 +0100 Subject: [PATCH 126/208] use add_log_line() --- op/op.PasswordForgotten.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/op/op.PasswordForgotten.php b/op/op.PasswordForgotten.php index ca9dc5e7d..c1e8e0fb9 100644 --- a/op/op.PasswordForgotten.php +++ b/op/op.PasswordForgotten.php @@ -55,12 +55,10 @@ if($user) { $params['url'] = getBaseUrl().$settings->_httpRoot."out/out.ChangePassword.php?hash=".$hash; $params['url_prefix'] = getBaseUrl().$settings->_httpRoot; $emailobj->toIndividual($settings->_smtpSendFrom, $user, $subject, $message, $params); - if($logger) - $logger->log("PasswordForgotten: Request for '".$login."' send to '".$email."'", PEAR_LOG_INFO); + add_log_line("Request for '".$login."' send to '".$email."'", PEAR_LOG_INFO); } } else { - if($logger) - $logger->log("PasswordForgotten: no such user '".$login."' with email '".$email."'", PEAR_LOG_WARNING); + add_log_line("No such user '".$login."' with email '".$email."'", PEAR_LOG_WARNING); } header('Location: ../out/out.PasswordSend.php'); From b5d32f3d53d664396179b3a111c72341eba83eb7 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 6 Mar 2025 07:15:46 +0100 Subject: [PATCH 127/208] do not add standard footer to mails send by scheduler --- inc/inc.Tasks.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/inc/inc.Tasks.php b/inc/inc.Tasks.php index 3443cbf2d..35fcbdc31 100644 --- a/inc/inc.Tasks.php +++ b/inc/inc.Tasks.php @@ -53,6 +53,7 @@ class SeedDMS_ExpiredDocumentsTask extends SeedDMS_SchedulerTaskBase { /* {{{ */ $params['count'] = count($docs); $params['__body__'] = $body; $params['__body_html__'] = $bodyhtml; + $params['__skip_footer__'] = true; $params['sitename'] = $settings->_siteName; $email->toIndividual('', $u, 'expired_docs_mail_subject', '', $params); $logger->log('Task \'expired_docs\': Sending reminder \'expired_docs_mail_subject\' to user \''.$u->getLogin().'\'', PEAR_LOG_INFO); @@ -79,6 +80,7 @@ class SeedDMS_ExpiredDocumentsTask extends SeedDMS_SchedulerTaskBase { /* {{{ */ $params['count'] = count($docs); $params['__body__'] = $body; $params['__body_html__'] = $bodyhtml; + $params['__skip_footer__'] = true; $params['sitename'] = $settings->_siteName; $email->toIndividual('', $taskparams['email'], 'expired_docs_mail_subject', '', $params); @@ -613,6 +615,7 @@ class SeedDMS_CalendarTask extends SeedDMS_SchedulerTaskBase { /* {{{ */ $params['count'] = count($events); $params['__body__'] = $body; $params['__body_html__'] = $bodyhtml; + $params['__skip_footer__'] = true; $params['sitename'] = $settings->_siteName; $email->toIndividual('', $auser, 'calendar_events_mail_subject', '', $params); @@ -714,6 +717,7 @@ class SeedDMS_StatisticTask extends SeedDMS_SchedulerTaskBase { /* {{{ */ $params = array(); $params['__body__'] = $body; $params['__body_html__'] = $bodyhtml; + $params['__skip_footer__'] = true; $params['sitename'] = $settings->_siteName; $email->toIndividual('', $auser, 'statistics_mail_subject', '', $params); From b30c4a7a6606b04f5e20826ff52cc6957bfd013f Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 6 Mar 2025 19:29:17 +0100 Subject: [PATCH 128/208] fix wrong position of text in progress bar --- views/bootstrap4/class.Bootstrap4.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/bootstrap4/class.Bootstrap4.php b/views/bootstrap4/class.Bootstrap4.php index 7c4f0ecf2..277210f87 100644 --- a/views/bootstrap4/class.Bootstrap4.php +++ b/views/bootstrap4/class.Bootstrap4.php @@ -3448,7 +3448,7 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) if($totalreceipts) { $content .= "
    -
    ".($rstat['1'] ? $rstat['1']."/".$totalreceipts : '').($allcomments['1'] ? " ".$this->printPopupBox('', implode('
    ', formatComment($allcomments['1'])), true) : "")."
    +
    ".($rstat['1'] ? $rstat['1']."/".$totalreceipts : '').($allcomments['1'] ? " ".$this->printPopupBox('', implode('
    ', formatComment($allcomments['1'])), true) : "")."
    ".($rstat['-1'] ? $rstat['-1']."/".$totalreceipts : '').($allcomments['-1'] ? " ".$this->printPopupBox('', implode('
    ', formatComment($allcomments['-1'])), true) : "")."
    "; } From 2eb19048abe2b2604f4ba64f1c00bb7adb3f9ae9 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 14 Mar 2025 16:51:15 +0100 Subject: [PATCH 129/208] add checking for revision date --- views/bootstrap/class.SetRevisors.php | 31 +++++++++++++++++++++------ 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/views/bootstrap/class.SetRevisors.php b/views/bootstrap/class.SetRevisors.php index 90bd3aa1e..9bef66cb0 100644 --- a/views/bootstrap/class.SetRevisors.php +++ b/views/bootstrap/class.SetRevisors.php @@ -13,11 +13,6 @@ * @version Release: @package_version@ */ -/** - * Include parent class - */ -//require_once("class.Bootstrap.php"); - /** * Class which outputs the html page for SetRevisors view * @@ -31,6 +26,26 @@ */ class SeedDMS_View_SetRevisors extends SeedDMS_Theme_Style { + function js() { /* {{{ */ + header('Content-Type: application/javascript; charset=UTF-8'); + parent::jsTranslations(array('js_form_error', 'js_form_errors')); +?> +function runValidation() { + $("#form1").validate({ + rules: { + startdate: { + required: true + }, + }, + messages: { + comment: "", + } + }); +} +runValidation(); +params['dms']; $user = $this->params['user']; @@ -44,6 +59,9 @@ class SeedDMS_View_SetRevisors extends SeedDMS_Theme_Style { $overallStatus = $content->getStatus(); + $this->htmlAddHeader(''."\n", 'js'); + $this->htmlAddHeader(''."\n", 'js'); + $this->htmlStartPage(getMLText("document_title", array("documentname" => htmlspecialchars($document->getName())))); $this->globalNavigation($folder); $this->contentStart(); @@ -69,7 +87,7 @@ class SeedDMS_View_SetRevisors extends SeedDMS_Theme_Style { } ?> - + @@ -184,4 +202,3 @@ class SeedDMS_View_SetRevisors extends SeedDMS_Theme_Style { $this->htmlEndPage(); } /* }}} */ } -?> From 789b5daaf8b5a5f35ee11dd66e1f92554d15a115 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 14 Mar 2025 16:51:34 +0100 Subject: [PATCH 130/208] add checking for revision date --- op/op.SetRevisors.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/op/op.SetRevisors.php b/op/op.SetRevisors.php index 672cd6677..3716b0183 100644 --- a/op/op.SetRevisors.php +++ b/op/op.SetRevisors.php @@ -55,10 +55,12 @@ if (!is_object($content)) { UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("invalid_version")); } -if (isset($_POST["startdate"])) { +$ts = null; +if (!empty($_POST["startdate"])) { $ts = makeTsFromDate($_POST["startdate"]); -} else { - $ts = time(); +} +if(!$ts) { + UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("invalid_revision_date")); } $startdate = date('Y-m-d', $ts); From 70c63afd10daf74fc941df029523f22bb7e90263 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 14 Mar 2025 17:16:06 +0100 Subject: [PATCH 131/208] fix setting attributes (user, group, folder, document) --- op/op.UpdateDocument.php | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/op/op.UpdateDocument.php b/op/op.UpdateDocument.php index dd4e05cd2..e633f44ff 100644 --- a/op/op.UpdateDocument.php +++ b/op/op.UpdateDocument.php @@ -283,10 +283,38 @@ default: $attributes = $_POST["attributes_version"]; foreach($attributes as $attrdefid=>$attribute) { $attrdef = $dms->getAttributeDefinition($attrdefid); + if(null === ($ret = $controller->callHook('validateAttribute', $attrdef, $attribute))) { if($attribute) { switch($attrdef->getType()) { case SeedDMS_Core_AttributeDefinition::type_date: - $attribute = date('Y-m-d', makeTsFromDate($attribute)); + if(is_array($attribute)) + $attribute = array_map(fn($value): string => date('Y-m-d', makeTsFromDate($value)), $attribute); + else + $attribute = date('Y-m-d', makeTsFromDate($attribute)); + break; + case SeedDMS_Core_AttributeDefinition::type_folder: + if(is_array($attribute)) + $attribute = array_map(fn($value): object => $dms->getFolder((int) $value), $attribute); + else + $attribute = $dms->getFolder((int) $attribute); + break; + case SeedDMS_Core_AttributeDefinition::type_document: + if(is_array($attribute)) + $attribute = array_map(fn($value): object => $dms->getDocument((int) $value), $attribute); + else + $attribute = $dms->getDocument((int) $attribute); + break; + case SeedDMS_Core_AttributeDefinition::type_user: + if(is_array($attribute)) + $attribute = array_map(fn($value): object => $dms->getUser((int) $value), $attribute); + else + $attribute = $dms->getUser((int) $attribute); + break; + case SeedDMS_Core_AttributeDefinition::type_group: + if(is_array($attribute)) + $attribute = array_map(fn($value): object => $dms->getGroup((int) $value), $attribute); + else + $attribute = $dms->getGroup((int) $attribute); break; } if(!$attrdef->validate($attribute, null, true)) { @@ -296,6 +324,10 @@ default: } elseif($attrdef->getMinValues() > 0) { UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("attr_min_values", array("attrname"=>$attrdef->getName()))); } + } else { + if($ret === false) + return false; + } } } else { $attributes = array(); From 128a57a9c5014f04839f9c512f36690ec05142b6 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 14 Mar 2025 17:20:05 +0100 Subject: [PATCH 132/208] fix setting attributes (user, group, document, folder) --- op/op.CheckInDocument.php | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/op/op.CheckInDocument.php b/op/op.CheckInDocument.php index e540e73ab..b5a250ed5 100644 --- a/op/op.CheckInDocument.php +++ b/op/op.CheckInDocument.php @@ -249,11 +249,39 @@ default: if(isset($_POST["attributes_version"]) && $_POST["attributes_version"]) { $attributes = $_POST["attributes_version"]; foreach($attributes as $attrdefid=>$attribute) { + if(null === ($ret = $controller->callHook('validateAttribute', $attrdef, $attribute))) { $attrdef = $dms->getAttributeDefinition($attrdefid); if($attribute) { switch($attrdef->getType()) { case SeedDMS_Core_AttributeDefinition::type_date: - $attribute = date('Y-m-d', makeTsFromDate($attribute)); + if(is_array($attribute)) + $attribute = array_map(fn($value): string => date('Y-m-d', makeTsFromDate($value)), $attribute); + else + $attribute = date('Y-m-d', makeTsFromDate($attribute)); + break; + case SeedDMS_Core_AttributeDefinition::type_folder: + if(is_array($attribute)) + $attribute = array_map(fn($value): object => $dms->getFolder((int) $value), $attribute); + else + $attribute = $dms->getFolder((int) $attribute); + break; + case SeedDMS_Core_AttributeDefinition::type_document: + if(is_array($attribute)) + $attribute = array_map(fn($value): object => $dms->getDocument((int) $value), $attribute); + else + $attribute = $dms->getDocument((int) $attribute); + break; + case SeedDMS_Core_AttributeDefinition::type_user: + if(is_array($attribute)) + $attribute = array_map(fn($value): object => $dms->getUser((int) $value), $attribute); + else + $attribute = $dms->getUser((int) $attribute); + break; + case SeedDMS_Core_AttributeDefinition::type_group: + if(is_array($attribute)) + $attribute = array_map(fn($value): object => $dms->getGroup((int) $value), $attribute); + else + $attribute = $dms->getGroup((int) $attribute); break; } if(!$attrdef->validate($attribute, null, true)) { @@ -263,6 +291,10 @@ default: } elseif($attrdef->getMinValues() > 0) { UI::exitError(getMLText("document_title", array("documentname" => $document->getName())),getMLText("attr_min_values", array("attrname"=>$attrdef->getName()))); } + } else { + if($ret === false) + return false; + } } } else { $attributes = array(); From dee29cb64fcb71e33795f64ff8c9c812d85ec830 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 14 Mar 2025 17:21:09 +0100 Subject: [PATCH 133/208] add changes for 5.1.39 --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index edd5eef3c..b01d8b807 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -9,6 +9,8 @@ - very experimental support of memcached for accelerating some database operations (do not use in production) - prevent malicious manipulation of referer when setting language +- fix setting attributes of type user, group, document, folder when updating + a document -------------------------------------------------------------------------------- Changes in version 5.1.38 From 1d62de521393412bca1d83bcd3f2735b55eb0122 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 14 Mar 2025 17:22:28 +0100 Subject: [PATCH 134/208] add changes for 6.0.32 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index ddd4b1d73..816efe650 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,9 @@ Changes in version 6.0.32 -------------------------------------------------------------------------------- - merge changes up to 5.1.39 +- fix setting attributes (user, group, document, folder) when checking in + a new document version +- validate setting revision date -------------------------------------------------------------------------------- Changes in version 6.0.31 From d7f1e899ba13a678a5d6f0c21924bada0fa88008 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 14 Mar 2025 17:32:36 +0100 Subject: [PATCH 135/208] fix nasty error when validating attribute in a hook --- op/op.CheckInDocument.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op/op.CheckInDocument.php b/op/op.CheckInDocument.php index b5a250ed5..4ae63cbce 100644 --- a/op/op.CheckInDocument.php +++ b/op/op.CheckInDocument.php @@ -249,8 +249,8 @@ default: if(isset($_POST["attributes_version"]) && $_POST["attributes_version"]) { $attributes = $_POST["attributes_version"]; foreach($attributes as $attrdefid=>$attribute) { - if(null === ($ret = $controller->callHook('validateAttribute', $attrdef, $attribute))) { $attrdef = $dms->getAttributeDefinition($attrdefid); + if(null === ($ret = $controller->callHook('validateAttribute', $attrdef, $attribute))) { if($attribute) { switch($attrdef->getType()) { case SeedDMS_Core_AttributeDefinition::type_date: From 9a3f217e45725ef949f950867a10bcfc692e0a2d Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 17 Mar 2025 12:50:01 +0100 Subject: [PATCH 136/208] add method isOnClipboard() --- inc/inc.ClassSession.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/inc/inc.ClassSession.php b/inc/inc.ClassSession.php index a9940d938..e1f1c1b8e 100644 --- a/inc/inc.ClassSession.php +++ b/inc/inc.ClassSession.php @@ -286,6 +286,24 @@ class SeedDMS_Session { return (array) $this->data['clipboard']; } /* }}} */ + /** + * Check if object is on clipboard + * + * @param object $object Document or folder + */ + function isOnClipboard($object) { /* {{{ */ + /* id is only set if load() was called before */ + if($this->id) { + $dms = $object->getDMS(); + if($object->isType('document')) { + return in_array($object->getID(), $this->data['clipboard']['docs']); + } elseif($object->isType('folder')) { + return in_array($object->getID(), $this->data['clipboard']['folders']); + } + } + return false; + } /* }}} */ + /** * Add to clipboard of session * From 9abbf6a1e5655833d797df484ba54a1d55341c7f Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 17 Mar 2025 15:57:51 +0100 Subject: [PATCH 137/208] objects can be removed from clipboard --- views/bootstrap/class.Bootstrap.php | 24 ++++++++++++++++++++---- views/bootstrap/styles/application.js | 6 ++++++ views/bootstrap4/class.Bootstrap4.php | 24 ++++++++++++++++++++---- views/bootstrap4/styles/application.js | 6 ++++++ 4 files changed, 52 insertions(+), 8 deletions(-) diff --git a/views/bootstrap/class.Bootstrap.php b/views/bootstrap/class.Bootstrap.php index a9bdcc62f..91ab0bc20 100644 --- a/views/bootstrap/class.Bootstrap.php +++ b/views/bootstrap/class.Bootstrap.php @@ -678,6 +678,7 @@ background-image: linear-gradient(to bottom, #882222, #111111);; private function folderNavigationBar($folder) { /* {{{ */ $dms = $this->params['dms']; + $session = $this->params['session']; $enableClipboard = $this->params['enableclipboard']; $accessobject = $this->params['accessobject']; if (!is_object($folder) || !$folder->isType('folder')) { @@ -718,7 +719,10 @@ background-image: linear-gradient(to bottom, #882222, #111111);; $menuitems['edit_folder_notify'] = array('link'=>$this->params['settings']->_httpRoot."out/out.FolderNotify.php?folderid=". $folderID ."&showtree=". showtree(), 'label'=>getMLText('edit_folder_notify')); } if($enableClipboard) { - $menuitems['add_to_clipboard'] = array('class'=>'addtoclipboard', 'attributes'=>array(['rel', 'F'.$folder->getId()], ['msg', getMLText('splash_added_to_clipboard')], ['title', getMLText("add_to_clipboard")]), 'label'=>getMLText("add_to_clipboard")); + if($session->isOnClipboard($folder)) + $menuitems['remove_from_clipboard'] = array('class'=>'removefromclipboard', 'attributes'=>array(['rel', 'F'.$folder->getId()], ['msg', getMLText('splash_removed_from_clipboard')], ['title', getMLText("remove_from_clipboard")]), 'label'=>getMLText("remove_from_clipboard")); + else + $menuitems['add_to_clipboard'] = array('class'=>'addtoclipboard', 'attributes'=>array(['rel', 'F'.$folder->getId()], ['msg', getMLText('splash_added_to_clipboard')], ['title', getMLText("add_to_clipboard")]), 'label'=>getMLText("add_to_clipboard")); } if ($accessobject->check_view_access('Indexer') && $this->params['enablefullsearch']) { $menuitems['index_folder'] = array('link'=>$this->params['settings']->_httpRoot."out/out.Indexer.php?folderid=". $folderID."&showtree=".showtree(), 'label'=>getMLText('index_folder')); @@ -741,6 +745,7 @@ background-image: linear-gradient(to bottom, #882222, #111111);; } /* }}} */ private function documentNavigationBar($document) { /* {{{ */ + $session = $this->params['session']; $accessobject = $this->params['accessobject']; $enableClipboard = $this->params['enableclipboard']; $accessMode = $document->getAccessMode($this->params['user']); @@ -789,7 +794,10 @@ background-image: linear-gradient(to bottom, #882222, #111111);; $menuitems['edit_document_notify'] = array('link'=>$this->params['settings']->_httpRoot."out/out.DocumentNotify". $docid, 'label'=>getMLText('edit_document_notify')); } if($enableClipboard) { - $menuitems['add_to_clipboard'] = array('class'=>'addtoclipboard', 'attributes'=>array(['rel', 'D'.$document->getId()], ['msg', getMLText('splash_added_to_clipboard')], ['title', getMLText("add_to_clipboard")]), 'label'=>getMLText("add_to_clipboard")); + if($session->isOnClipboard($document)) + $menuitems['remove_from_clipboard'] = array('class'=>'removefromclipboard', 'attributes'=>array(['rel', 'D'.$document->getId()], ['msg', getMLText('splash_removed_from_clipboard')], ['title', getMLText("remove_from_clipboard")]), 'label'=>getMLText("remove_from_clipboard")); + else + $menuitems['add_to_clipboard'] = array('class'=>'addtoclipboard', 'attributes'=>array(['rel', 'D'.$document->getId()], ['msg', getMLText('splash_added_to_clipboard')], ['title', getMLText("add_to_clipboard")]), 'label'=>getMLText("add_to_clipboard")); } if ($accessobject->check_view_access('TransferDocument')) { $menuitems['transfer_document'] = array('link'=>$this->params['settings']->_httpRoot."out/out.TransferDocument". $docid, 'label'=>getMLText('transfer_document')); @@ -3165,6 +3173,7 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) function documentListRowAction($document, $previewer, $skipcont=false, $version=0, $extracontent=array()) { /* {{{ */ $user = $this->params['user']; + $session = $this->params['session']; $enableClipboard = $this->params['enableclipboard']; $accessop = $this->params['accessobject']; $onepage = $this->params['onepage']; @@ -3194,7 +3203,10 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) $actions['document_access'] = $this->printAccessButton($document, true); } if($enableClipboard) { - $actions['add_to_clipboard'] = ''; + if($session->isOnClipboard($document)) + $actions['remove_from_clipboard'] = ''; + else + $actions['add_to_clipboard'] = ''; } if($onepage) $actions['view_document'] = ''; @@ -3376,6 +3388,7 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) function folderListRowAction($subFolder, $skipcont=false, $extracontent=array()) { /* {{{ */ $dms = $this->params['dms']; $user = $this->params['user']; + $session = $this->params['session']; // $folder = $this->params['folder']; $showtree = $this->params['showtree']; $enableRecursiveCount = $this->params['enableRecursiveCount']; @@ -3406,7 +3419,10 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) $actions['folder_access'] = $this->printAccessButton($subFolder, true); } if($enableClipboard) { - $actions['add_to_clipboard'] = ''; + if($session->isOnClipboard($subFolder)) + $actions['add_to_clipboard'] = ''; + else + $actions['add_to_clipboard'] = ''; } if($onepage) $actions['view_folder'] = ''; diff --git a/views/bootstrap/styles/application.js b/views/bootstrap/styles/application.js index a4911a4d8..1494912f2 100644 --- a/views/bootstrap/styles/application.js +++ b/views/bootstrap/styles/application.js @@ -407,6 +407,8 @@ $(document).ready( function() { if(data.success) { $("#main-clipboard").html('Loading').load(seeddms_webroot+'out/out.Clipboard.php?action=mainclipboard') $("#menu-clipboard div").html('Loading').load(seeddms_webroot+'out/out.Clipboard.php?action=menuclipboard') + $("div.ajax[data-action='navigation']").trigger('update', {}); + $("div.ajax[data-action='folderList']").trigger('update', {}); noty({ text: attr_msg, type: 'success', @@ -442,6 +444,8 @@ $(document).ready( function() { if(data.success) { $("#main-clipboard").html('Loading').load(seeddms_webroot+'out/out.Clipboard.php?action=mainclipboard') $("#menu-clipboard div").html('Loading').load(seeddms_webroot+'out/out.Clipboard.php?action=menuclipboard') + $("div.ajax[data-action='navigation']").trigger('update', {}); + $("div.ajax[data-action='folderList']").trigger('update', {}); noty({ text: attr_msg, type: 'success', @@ -753,6 +757,8 @@ function onAddClipboard(ev) { /* {{{ */ if(data.success) { $("#main-clipboard").html('Loading').load(seeddms_webroot+'out/out.Clipboard.php?action=mainclipboard') $("#menu-clipboard div").html('Loading').load(seeddms_webroot+'out/out.Clipboard.php?action=menuclipboard') + $("div.ajax[data-action='navigation']").trigger('update', {}); + $("div.ajax[data-action='folderList']").trigger('update', {}); noty({ text: data.message, type: 'success', diff --git a/views/bootstrap4/class.Bootstrap4.php b/views/bootstrap4/class.Bootstrap4.php index 843f11277..5ffa75298 100644 --- a/views/bootstrap4/class.Bootstrap4.php +++ b/views/bootstrap4/class.Bootstrap4.php @@ -683,6 +683,7 @@ background-image: linear-gradient(to bottom, #882222, #111111);; private function folderNavigationBar($folder) { /* {{{ */ $dms = $this->params['dms']; + $session = $this->params['session']; $enableClipboard = $this->params['enableclipboard']; $accessobject = $this->params['accessobject']; if (!is_object($folder) || !$folder->isType('folder')) { @@ -721,7 +722,10 @@ background-image: linear-gradient(to bottom, #882222, #111111);; $menuitems['edit_folder_notify'] = array('link'=>$this->params['settings']->_httpRoot."out/out.FolderNotify.php?folderid=". $folderID ."&showtree=". showtree(), 'label'=>getMLText('edit_folder_notify')); } if($enableClipboard) { - $menuitems['add_to_clipboard'] = array('class'=>'addtoclipboard', 'attributes'=>array(['rel', 'F'.$folder->getId()], ['msg', getMLText('splash_added_to_clipboard')], ['title', getMLText("add_to_clipboard")]), 'label'=>getMLText("add_to_clipboard")); + if($session->isOnClipboard($folder)) + $menuitems['remove_from_clipboard'] = array('class'=>'removefromclipboard', 'attributes'=>array(['rel', 'F'.$folder->getId()], ['msg', getMLText('splash_removed_from_clipboard')], ['title', getMLText("remove_from_clipboard")]), 'label'=>getMLText("remove_from_clipboard")); + else + $menuitems['add_to_clipboard'] = array('class'=>'addtoclipboard', 'attributes'=>array(['rel', 'F'.$folder->getId()], ['msg', getMLText('splash_added_to_clipboard')], ['title', getMLText("add_to_clipboard")]), 'label'=>getMLText("add_to_clipboard")); } if ($this->params['user']->isAdmin() && $this->params['enablefullsearch']) { $menuitems['index_folder'] = array('link'=>$this->params['settings']->_httpRoot."out/out.Indexer.php?folderid=". $folderID."&showtree=".showtree(), 'label'=>getMLText('index_folder')); @@ -742,6 +746,7 @@ background-image: linear-gradient(to bottom, #882222, #111111);; } /* }}} */ private function documentNavigationBar($document) { /* {{{ */ + $session = $this->params['session']; $accessobject = $this->params['accessobject']; $enableClipboard = $this->params['enableclipboard']; $accessMode = $document->getAccessMode($this->params['user']); @@ -788,7 +793,10 @@ background-image: linear-gradient(to bottom, #882222, #111111);; $menuitems['edit_document_notify'] = array('link'=>$this->params['settings']->_httpRoot."out/out.DocumentNotify". $docid, 'label'=>getMLText('edit_document_notify')); } if($enableClipboard) { - $menuitems['add_to_clipboard'] = array('class'=>'addtoclipboard', 'attributes'=>array(['rel', 'D'.$document->getId()], ['msg', getMLText('splash_added_to_clipboard')], ['title', getMLText("add_to_clipboard")]), 'label'=>getMLText("add_to_clipboard")); + if($session->isOnClipboard($document)) + $menuitems['remove_from_clipboard'] = array('class'=>'removefromclipboard', 'attributes'=>array(['rel', 'D'.$document->getId()], ['msg', getMLText('splash_removed_from_clipboard')], ['title', getMLText("remove_from_clipboard")]), 'label'=>getMLText("remove_from_clipboard")); + else + $menuitems['add_to_clipboard'] = array('class'=>'addtoclipboard', 'attributes'=>array(['rel', 'D'.$document->getId()], ['msg', getMLText('splash_added_to_clipboard')], ['title', getMLText("add_to_clipboard")]), 'label'=>getMLText("add_to_clipboard")); } if ($accessobject->check_view_access('TransferDocument')) { $menuitems['transfer_document'] = array('link'=>$this->params['settings']->_httpRoot."out/out.TransferDocument". $docid, 'label'=>getMLText('transfer_document')); @@ -3215,6 +3223,7 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) function documentListRowAction($document, $previewer, $skipcont=false, $version=0, $extracontent=array()) { /* {{{ */ $user = $this->params['user']; + $session = $this->params['session']; $enableClipboard = $this->params['enableclipboard']; $accessop = $this->params['accessobject']; $onepage = $this->params['onepage']; @@ -3244,7 +3253,10 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) $actions['document_access'] = $this->printAccessButton($document, true); } if($enableClipboard) { - $actions['add_to_clipboard'] = ''; + if($session->isOnClipboard($document)) + $actions['remove_from_clipboard'] = ''; + else + $actions['add_to_clipboard'] = ''; } if($onepage) $actions['view_document'] = ''; @@ -3478,6 +3490,7 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) function folderListRowAction($subFolder, $skipcont=false, $extracontent=array()) { /* {{{ */ $dms = $this->params['dms']; $user = $this->params['user']; + $session = $this->params['session']; // $folder = $this->params['folder']; $showtree = $this->params['showtree']; $enableRecursiveCount = $this->params['enableRecursiveCount']; @@ -3508,7 +3521,10 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) $actions['folder_access'] = $this->printAccessButton($subFolder, true); } if($enableClipboard) { - $actions['add_to_clipboard'] = ''; + if($session->isOnClipboard($subFolder)) + $actions['add_to_clipboard'] = ''; + else + $actions['add_to_clipboard'] = ''; } if($onepage) $actions['view_folder'] = ''; diff --git a/views/bootstrap4/styles/application.js b/views/bootstrap4/styles/application.js index bbd87464a..a36caa04b 100644 --- a/views/bootstrap4/styles/application.js +++ b/views/bootstrap4/styles/application.js @@ -455,6 +455,8 @@ $(document).ready( function() { if(data.success) { $("#main-clipboard").html('Loading').load(seeddms_webroot+'out/out.Clipboard.php?action=mainclipboard') $("#menu-clipboard div").html('Loading').load(seeddms_webroot+'out/out.Clipboard.php?action=menuclipboard') + $("div.ajax[data-action='navigation']").trigger('update', {}); + $("div.ajax[data-action='folderList']").trigger('update', {}); noty({ text: attr_msg, type: 'success', @@ -490,6 +492,8 @@ $(document).ready( function() { if(data.success) { $("#main-clipboard").html('Loading').load(seeddms_webroot+'out/out.Clipboard.php?action=mainclipboard') $("#menu-clipboard div").html('Loading').load(seeddms_webroot+'out/out.Clipboard.php?action=menuclipboard') + $("div.ajax[data-action='navigation']").trigger('update', {}); + $("div.ajax[data-action='folderList']").trigger('update', {}); noty({ text: attr_msg, type: 'success', @@ -801,6 +805,8 @@ function onAddClipboard(ev) { /* {{{ */ if(data.success) { $("#main-clipboard").html('Loading').load(seeddms_webroot+'out/out.Clipboard.php?action=mainclipboard') $("#menu-clipboard div").html('Loading').load(seeddms_webroot+'out/out.Clipboard.php?action=menuclipboard') + $("div.ajax[data-action='navigation']").trigger('update', {}); + $("div.ajax[data-action='folderList']").trigger('update', {}); noty({ text: data.message, type: 'success', From 2ecef66355158807b7d8dd7111ab74154042642c Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 17 Mar 2025 15:58:19 +0100 Subject: [PATCH 138/208] add changes for 5.1.39 --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index b01d8b807..ed0c07157 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -11,6 +11,7 @@ - prevent malicious manipulation of referer when setting language - fix setting attributes of type user, group, document, folder when updating a document +- objects can be removed from clipboard -------------------------------------------------------------------------------- Changes in version 5.1.38 From 38b3abc50ed5446fecff7c0a6b988125725d08ae Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 17 Mar 2025 16:16:03 +0100 Subject: [PATCH 139/208] add new phrases --- languages/ar_EG/lang.inc | 2 ++ languages/bg_BG/lang.inc | 2 ++ languages/ca_ES/lang.inc | 2 ++ languages/cs_CZ/lang.inc | 2 ++ languages/de_DE/lang.inc | 4 +++- languages/el_GR/lang.inc | 2 ++ languages/en_GB/lang.inc | 10 ++++++---- languages/es_ES/lang.inc | 2 ++ languages/fr_FR/lang.inc | 2 ++ languages/hr_HR/lang.inc | 2 ++ languages/hu_HU/lang.inc | 2 ++ languages/id_ID/lang.inc | 2 ++ languages/it_IT/lang.inc | 2 ++ languages/ko_KR/lang.inc | 2 ++ languages/lo_LA/lang.inc | 2 ++ languages/nb_NO/lang.inc | 2 ++ languages/nl_NL/lang.inc | 2 ++ languages/pl_PL/lang.inc | 2 ++ languages/pt_BR/lang.inc | 2 ++ languages/ro_RO/lang.inc | 2 ++ languages/ru_RU/lang.inc | 2 ++ languages/sk_SK/lang.inc | 2 ++ languages/sv_SE/lang.inc | 2 ++ languages/tr_TR/lang.inc | 2 ++ languages/uk_UA/lang.inc | 2 ++ languages/zh_CN/lang.inc | 2 ++ languages/zh_TW/lang.inc | 2 ++ 27 files changed, 59 insertions(+), 5 deletions(-) diff --git a/languages/ar_EG/lang.inc b/languages/ar_EG/lang.inc index d7b26d872..c212434ed 100644 --- a/languages/ar_EG/lang.inc +++ b/languages/ar_EG/lang.inc @@ -1287,6 +1287,7 @@ URL: [url]', 'removeFolderFromDropFolder' => 'إزالة مجلد من إسقاط لائحة', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'ازالة الملفات المختارة', 'remove_review_log' => '', 'remove_task' => '', @@ -2003,6 +2004,7 @@ URL: [url]', 'sign_out' => 'تسجيل الخروج', 'sign_out_user' => 'تسجيل خروج مستخدم', 'site_brand' => 'مجلس النواب اللبناني', +'skip_default_export_cols' => '', 'sk_SK' => 'السلوفاكية', 'sort_by_date' => 'رتب حسب التاريخ', 'sort_by_expiration_date' => '', diff --git a/languages/bg_BG/lang.inc b/languages/bg_BG/lang.inc index 69dd99be8..10de75365 100644 --- a/languages/bg_BG/lang.inc +++ b/languages/bg_BG/lang.inc @@ -1156,6 +1156,7 @@ $text = array( 'removeFolderFromDropFolder' => '', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => '', 'remove_review_log' => '', 'remove_task' => '', @@ -1845,6 +1846,7 @@ $text = array( 'sign_out' => 'изход', 'sign_out_user' => '', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Словашки', 'sort_by_date' => 'Сортирай по дата"', 'sort_by_expiration_date' => '', diff --git a/languages/ca_ES/lang.inc b/languages/ca_ES/lang.inc index ba7301b4c..b810e2964 100644 --- a/languages/ca_ES/lang.inc +++ b/languages/ca_ES/lang.inc @@ -1161,6 +1161,7 @@ URL: [url]', 'removeFolderFromDropFolder' => 'Esborrar carpeta després de la importació', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => '', 'remove_review_log' => '', 'remove_task' => '', @@ -1850,6 +1851,7 @@ URL: [url]', 'sign_out' => 'desconnectar', 'sign_out_user' => '', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Eslovac', 'sort_by_date' => '', 'sort_by_expiration_date' => '', diff --git a/languages/cs_CZ/lang.inc b/languages/cs_CZ/lang.inc index 6a2a9920b..4e10f11f3 100644 --- a/languages/cs_CZ/lang.inc +++ b/languages/cs_CZ/lang.inc @@ -1333,6 +1333,7 @@ URL: [url]', 'removeFolderFromDropFolder' => 'Odstranit složku po nahrání', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'Odstranit označené soubory', 'remove_review_log' => '', 'remove_task' => '', @@ -2075,6 +2076,7 @@ Jméno: [username] 'sign_out' => 'Odhlásit', 'sign_out_user' => 'Odhlášení uživatele', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Slovenština', 'sort_by_date' => '', 'sort_by_expiration_date' => '', diff --git a/languages/de_DE/lang.inc b/languages/de_DE/lang.inc index f12e0d09a..08aa062e4 100644 --- a/languages/de_DE/lang.inc +++ b/languages/de_DE/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (3435), dgrutsch (22) +// Translators: Admin (3437), dgrutsch (22) $text = array( '2_factor_auth' => '2-Faktor Authentifizierung', @@ -1622,6 +1622,7 @@ URL: [url]

    ', 'removeFolderFromDropFolder' => 'Ordner nach Import entfernen', 'removeFolderFromDropFolder_desc' => 'Schalten Sie dies ein, um den importierten Ordner im Ablageordner auf der Festplatte zu löschen.', 'remove_approval_log' => 'Einzelne Freigabe entfernen', +'remove_from_clipboard' => 'Aus Zwischenablage entfernen', 'remove_marked_files' => 'Markierte Dateien löschen', 'remove_review_log' => 'Einzelne Prüfung entfernen', 'remove_task' => 'Task entfernen', @@ -2466,6 +2467,7 @@ Sollten Sie kein Passwort bekommen haben, dann nutzen Sie bitte die Passwort-Ver 'sign_out' => 'Abmelden', 'sign_out_user' => 'Benutzer abmelden', 'site_brand' => '', +'skip_default_export_cols' => 'Keine voreingestellten Spalten', 'sk_SK' => 'Slovakisch', 'sort_by_date' => 'Nach Datum sortieren', 'sort_by_expiration_date' => 'Nach Ablaufdatum sortieren', diff --git a/languages/el_GR/lang.inc b/languages/el_GR/lang.inc index 6f88ba684..ff4ac51ba 100644 --- a/languages/el_GR/lang.inc +++ b/languages/el_GR/lang.inc @@ -1167,6 +1167,7 @@ URL: [url]', 'removeFolderFromDropFolder' => '', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => '', 'remove_review_log' => '', 'remove_task' => '', @@ -1856,6 +1857,7 @@ URL: [url]', 'sign_out' => 'Αποσύνδεση', 'sign_out_user' => 'Αποσύνδεση χρήστη', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Σλοβάκικα', 'sort_by_date' => '', 'sort_by_expiration_date' => '', diff --git a/languages/en_GB/lang.inc b/languages/en_GB/lang.inc index 35724942d..61ccbd479 100644 --- a/languages/en_GB/lang.inc +++ b/languages/en_GB/lang.inc @@ -19,7 +19,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -// Translators: Admin (2533), archonwang (3), dgrutsch (9), netixw (14) +// Translators: Admin (2538), archonwang (3), dgrutsch (9), netixw (14) $text = array( '2_factor_auth' => '2-factor authentication', @@ -1198,9 +1198,9 @@ URL: [url]

    ', 'language' => 'Language', 'lastaccess' => 'Last access', 'last_update' => 'Last Update', -'latest_newdocuments' => 'Latest added documents', -'latest_statuschange' => 'Latest status change', -'latest_updateddocuments' => 'Latest updated documents', +'latest_newdocuments' => 'Recently added documents', +'latest_statuschange' => 'Documents with recent status change', +'latest_updateddocuments' => 'Recently updated documents', 'legend' => 'Legend', 'librarydoc' => 'Document from library', 'linked_document' => 'Linked document', @@ -1624,6 +1624,7 @@ URL: [url]

    ', 'removeFolderFromDropFolder' => 'Remove folder after import', 'removeFolderFromDropFolder_desc' => 'Enable this if you want the folder which was imported to be removed from the drop folder.', 'remove_approval_log' => 'Remove approval', +'remove_from_clipboard' => 'Remove from clipboard', 'remove_marked_files' => 'Remove marked files', 'remove_review_log' => 'Remove review', 'remove_task' => 'Remove task', @@ -2468,6 +2469,7 @@ If you did not receive a password, please use the password forgotten function on 'sign_out' => 'Sign out', 'sign_out_user' => 'Sign out user', 'site_brand' => '', +'skip_default_export_cols' => 'Skip default columns', 'sk_SK' => 'Slovak', 'sort_by_date' => 'Sort by date', 'sort_by_expiration_date' => 'Sort by date of expiration', diff --git a/languages/es_ES/lang.inc b/languages/es_ES/lang.inc index bd0006183..1642898f1 100644 --- a/languages/es_ES/lang.inc +++ b/languages/es_ES/lang.inc @@ -1310,6 +1310,7 @@ nURL: [url]', 'removeFolderFromDropFolder' => 'Eliminar carpeta después de importar', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'Eliminar ficheros marcados', 'remove_review_log' => '', 'remove_task' => '', @@ -2026,6 +2027,7 @@ URL: [url]', 'sign_out' => 'Salir', 'sign_out_user' => 'Desconectar usuario', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Slovaco', 'sort_by_date' => 'Ordenar por Fecha', 'sort_by_expiration_date' => 'Ordenar por fecha de vencimiento', diff --git a/languages/fr_FR/lang.inc b/languages/fr_FR/lang.inc index 48f7fcd92..b48b04038 100644 --- a/languages/fr_FR/lang.inc +++ b/languages/fr_FR/lang.inc @@ -1577,6 +1577,7 @@ URL : [url]

    ', 'removeFolderFromDropFolder' => 'Suppression du dossier après importation', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => 'Approbation retirée', +'remove_from_clipboard' => '', 'remove_marked_files' => 'Supprimer les fichiers sélectionnés', 'remove_review_log' => 'Vérification retirée', 'remove_task' => '', @@ -2413,6 +2414,7 @@ Nom : [username] 'sign_out' => 'Déconnexion', 'sign_out_user' => 'Déconnecter l\'utilisateur', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Slovaque', 'sort_by_date' => 'Trier par date', 'sort_by_expiration_date' => 'Trier par date d’expiration', diff --git a/languages/hr_HR/lang.inc b/languages/hr_HR/lang.inc index 726d24f6e..b864e3dc2 100644 --- a/languages/hr_HR/lang.inc +++ b/languages/hr_HR/lang.inc @@ -1306,6 +1306,7 @@ Internet poveznica: [url]', 'removeFolderFromDropFolder' => '', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'Ukloni označene datoteke', 'remove_review_log' => '', 'remove_task' => '', @@ -2039,6 +2040,7 @@ Internet poveznica: [url]', 'sign_out' => 'Odjava', 'sign_out_user' => 'Odjavi korisnika', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Slovački', 'sort_by_date' => '', 'sort_by_expiration_date' => '', diff --git a/languages/hu_HU/lang.inc b/languages/hu_HU/lang.inc index 28e05914b..d51870348 100644 --- a/languages/hu_HU/lang.inc +++ b/languages/hu_HU/lang.inc @@ -1301,6 +1301,7 @@ URL: [url]', 'removeFolderFromDropFolder' => '', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'Megjelölt állományok eltávolítása', 'remove_review_log' => '', 'remove_task' => '', @@ -2016,6 +2017,7 @@ URL: [url]', 'sign_out' => 'Kijelentkezés', 'sign_out_user' => 'Kijelentkezés', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Szlovák', 'sort_by_date' => '', 'sort_by_expiration_date' => '', diff --git a/languages/id_ID/lang.inc b/languages/id_ID/lang.inc index 4ca2c9af1..7b321d005 100644 --- a/languages/id_ID/lang.inc +++ b/languages/id_ID/lang.inc @@ -1410,6 +1410,7 @@ URL: [url]', 'removeFolderFromDropFolder' => 'Hapus folder setelah diimpor', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => 'Hapus persetujuan', +'remove_from_clipboard' => '', 'remove_marked_files' => 'Hapus file yang ditandai', 'remove_review_log' => 'Hapus ulasan', 'remove_task' => '', @@ -2106,6 +2107,7 @@ Jika Anda tidak menerima kata sandi, silakan gunakan fitur lupa kata sandi di ha 'sign_out' => 'Keluar', 'sign_out_user' => '', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Slovakia', 'sort_by_date' => 'Urutkan berdasarkan tanggal', 'sort_by_expiration_date' => 'Urutkan berdasarkan tanggal kadaluwarsa', diff --git a/languages/it_IT/lang.inc b/languages/it_IT/lang.inc index a14a9b3f4..bd14bd388 100644 --- a/languages/it_IT/lang.inc +++ b/languages/it_IT/lang.inc @@ -1319,6 +1319,7 @@ URL: [url]', 'removeFolderFromDropFolder' => 'Rimuovi la cartella di pubblicazione dopo l\'importazione', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'Rimuovi i files contrassegnati', 'remove_review_log' => '', 'remove_task' => '', @@ -2062,6 +2063,7 @@ Name: [username] 'sign_out' => 'Disconnettiti', 'sign_out_user' => 'Disconnetti l\'utente', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Slovacco', 'sort_by_date' => 'Ordina per data', 'sort_by_expiration_date' => '', diff --git a/languages/ko_KR/lang.inc b/languages/ko_KR/lang.inc index d77801260..aca1dbdd2 100644 --- a/languages/ko_KR/lang.inc +++ b/languages/ko_KR/lang.inc @@ -1300,6 +1300,7 @@ URL: [url]', 'removeFolderFromDropFolder' => '', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => '마크 파일을 제거', 'remove_review_log' => '', 'remove_task' => '', @@ -2033,6 +2034,7 @@ URL : [url]', 'sign_out' => '로그 아웃', 'sign_out_user' => '사용자가 로그 아웃', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => '슬로바키아어', 'sort_by_date' => '', 'sort_by_expiration_date' => '', diff --git a/languages/lo_LA/lang.inc b/languages/lo_LA/lang.inc index 32ffdf505..93cf4b57a 100644 --- a/languages/lo_LA/lang.inc +++ b/languages/lo_LA/lang.inc @@ -1316,6 +1316,7 @@ URL: [url]', 'removeFolderFromDropFolder' => 'ຍ້າຍໂຟລເດີຫຼັງຈາກນຳຂໍ້ມູນເຂົ້າ', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'ລົບໄຟລທີມີເຄື່ອງໝາຍໄວ້', 'remove_review_log' => '', 'remove_task' => '', @@ -2059,6 +2060,7 @@ URL: [url]', 'sign_out' => 'ອອກຈາກລະບົບ', 'sign_out_user' => 'ອອກຈາກລະບົບຜູ້ໄຊ້', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'ສະໂລວາເກຍ', 'sort_by_date' => '', 'sort_by_expiration_date' => '', diff --git a/languages/nb_NO/lang.inc b/languages/nb_NO/lang.inc index b85063e86..e2daee1cd 100644 --- a/languages/nb_NO/lang.inc +++ b/languages/nb_NO/lang.inc @@ -1331,6 +1331,7 @@ URL: [url]', 'removeFolderFromDropFolder' => 'Fjern mappe etter import', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'Fjern markerte filer', 'remove_review_log' => '', 'remove_task' => '', @@ -2072,6 +2073,7 @@ Bruker: [username] 'sign_out' => 'Logg ut', 'sign_out_user' => 'Logg ut bruker', 'site_brand' => 'Nettsted merke/logo', +'skip_default_export_cols' => '', 'sk_SK' => 'Slovakisk', 'sort_by_date' => 'Sorter etter dato', 'sort_by_expiration_date' => '', diff --git a/languages/nl_NL/lang.inc b/languages/nl_NL/lang.inc index 06e7b1513..a67ecc6ec 100644 --- a/languages/nl_NL/lang.inc +++ b/languages/nl_NL/lang.inc @@ -1329,6 +1329,7 @@ URL: [url]', 'removeFolderFromDropFolder' => 'Map verwijderen uit Dropfilder', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'Geselecteerde bestanden worden verwijderd', 'remove_review_log' => '', 'remove_task' => '', @@ -2071,6 +2072,7 @@ Name: [username] 'sign_out' => 'Log uit', 'sign_out_user' => 'Log gebruiker uit', 'site_brand' => 'Merk van de site', +'skip_default_export_cols' => '', 'sk_SK' => 'Slowaaks', 'sort_by_date' => 'Sorteren op datum', 'sort_by_expiration_date' => 'Sorteren op vervaldatum', diff --git a/languages/pl_PL/lang.inc b/languages/pl_PL/lang.inc index c30be33a3..c7c5f2031 100644 --- a/languages/pl_PL/lang.inc +++ b/languages/pl_PL/lang.inc @@ -1295,6 +1295,7 @@ URL: [url]', 'removeFolderFromDropFolder' => 'Usuń folder po imporcie', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'Usuń zaznaczone pliki', 'remove_review_log' => '', 'remove_task' => '', @@ -2002,6 +2003,7 @@ Name: [username] 'sign_out' => 'Wyloguj', 'sign_out_user' => 'Wyloguj użytkownika', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'słowacki', 'sort_by_date' => 'Sortuj według daty', 'sort_by_expiration_date' => 'Sortuj według daty ważności', diff --git a/languages/pt_BR/lang.inc b/languages/pt_BR/lang.inc index e4ccc69b8..7c160cf46 100644 --- a/languages/pt_BR/lang.inc +++ b/languages/pt_BR/lang.inc @@ -1336,6 +1336,7 @@ URL: [url]', 'removeFolderFromDropFolder' => 'Remover pasta após a importação', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'Remover arquivos marcados', 'remove_review_log' => '', 'remove_task' => '', @@ -2078,6 +2079,7 @@ Nome: [username] 'sign_out' => 'Sair', 'sign_out_user' => 'Sair usuário', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Eslovaco', 'sort_by_date' => 'classificar por data', 'sort_by_expiration_date' => '', diff --git a/languages/ro_RO/lang.inc b/languages/ro_RO/lang.inc index 1c71319c6..ee71eb4f5 100644 --- a/languages/ro_RO/lang.inc +++ b/languages/ro_RO/lang.inc @@ -1307,6 +1307,7 @@ URL: [url]', 'removeFolderFromDropFolder' => '', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'Eliminați fișierele marcate', 'remove_review_log' => '', 'remove_task' => '', @@ -2040,6 +2041,7 @@ URL: [url]', 'sign_out' => 'Sign out', 'sign_out_user' => 'Sign out utilizator', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Slovacă', 'sort_by_date' => 'Sortare dupa data', 'sort_by_expiration_date' => '', diff --git a/languages/ru_RU/lang.inc b/languages/ru_RU/lang.inc index ee185d1ed..44773426b 100644 --- a/languages/ru_RU/lang.inc +++ b/languages/ru_RU/lang.inc @@ -1309,6 +1309,7 @@ URL: [url]', 'removeFolderFromDropFolder' => '', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'Удалить выбранные файлы', 'remove_review_log' => '', 'remove_task' => '', @@ -2047,6 +2048,7 @@ URL: [url]', 'sign_out' => 'Выйти', 'sign_out_user' => 'Пользовательский выход', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Slovak', 'sort_by_date' => 'Сортировка по дате', 'sort_by_expiration_date' => '', diff --git a/languages/sk_SK/lang.inc b/languages/sk_SK/lang.inc index b813c91bc..325e5dfb2 100644 --- a/languages/sk_SK/lang.inc +++ b/languages/sk_SK/lang.inc @@ -1337,6 +1337,7 @@ URL: [url]', 'removeFolderFromDropFolder' => 'Po importe odstrániť zložku', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'Odstrániť označené súbory', 'remove_review_log' => '', 'remove_task' => '', @@ -2080,6 +2081,7 @@ Meno: [username] 'sign_out' => 'odhlásiť', 'sign_out_user' => 'Odhlásiť používateľa', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Slovenčina', 'sort_by_date' => '', 'sort_by_expiration_date' => '', diff --git a/languages/sv_SE/lang.inc b/languages/sv_SE/lang.inc index 6485b5f10..cff8d554f 100644 --- a/languages/sv_SE/lang.inc +++ b/languages/sv_SE/lang.inc @@ -1310,6 +1310,7 @@ URL: [url]', 'removeFolderFromDropFolder' => 'Radera katalog efter import', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'Ta bort markerade filer', 'remove_review_log' => '', 'remove_task' => '', @@ -2053,6 +2054,7 @@ Kommentar: [comment]', 'sign_out' => 'Logga ut', 'sign_out_user' => 'Logga ut användare', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Slovakiska', 'sort_by_date' => '', 'sort_by_expiration_date' => '', diff --git a/languages/tr_TR/lang.inc b/languages/tr_TR/lang.inc index 8c104fe63..5aaa3d30f 100644 --- a/languages/tr_TR/lang.inc +++ b/languages/tr_TR/lang.inc @@ -1301,6 +1301,7 @@ URL: [url]', 'removeFolderFromDropFolder' => '', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'İşaretli dosyaları sil', 'remove_review_log' => '', 'remove_task' => '', @@ -2017,6 +2018,7 @@ URL: [url]', 'sign_out' => 'Çıkış', 'sign_out_user' => 'Kullanıcı hesabından çıkış', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Slovakça', 'sort_by_date' => 'Tarihe göre sırala', 'sort_by_expiration_date' => '', diff --git a/languages/uk_UA/lang.inc b/languages/uk_UA/lang.inc index f55436cc5..bb81cc2d6 100644 --- a/languages/uk_UA/lang.inc +++ b/languages/uk_UA/lang.inc @@ -1308,6 +1308,7 @@ URL: [url]', 'removeFolderFromDropFolder' => '', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => 'Видалити обрані файли', 'remove_review_log' => '', 'remove_task' => '', @@ -2039,6 +2040,7 @@ URL: [url]', 'sign_out' => 'Вийти', 'sign_out_user' => 'Вихід користувача', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => 'Slovak', 'sort_by_date' => '', 'sort_by_expiration_date' => '', diff --git a/languages/zh_CN/lang.inc b/languages/zh_CN/lang.inc index e043538a4..a74001c9e 100644 --- a/languages/zh_CN/lang.inc +++ b/languages/zh_CN/lang.inc @@ -1314,6 +1314,7 @@ URL: [url]', 'removeFolderFromDropFolder' => '导入后删除文件夹', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => '删除选中的文件', 'remove_review_log' => '', 'remove_task' => '', @@ -2027,6 +2028,7 @@ URL: [url]', 'sign_out' => '登出', 'sign_out_user' => '退出登录', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => '斯洛伐克语', 'sort_by_date' => '日期排序', 'sort_by_expiration_date' => '', diff --git a/languages/zh_TW/lang.inc b/languages/zh_TW/lang.inc index f10508d96..3ac4ed82f 100644 --- a/languages/zh_TW/lang.inc +++ b/languages/zh_TW/lang.inc @@ -1335,6 +1335,7 @@ URL: [url]', 'removeFolderFromDropFolder' => '導入後刪除文件夾', 'removeFolderFromDropFolder_desc' => '', 'remove_approval_log' => '', +'remove_from_clipboard' => '', 'remove_marked_files' => '刪除勾選的檔案', 'remove_review_log' => '', 'remove_task' => '', @@ -2078,6 +2079,7 @@ URL: [url]', 'sign_out' => '登出', 'sign_out_user' => '登出使用者', 'site_brand' => '', +'skip_default_export_cols' => '', 'sk_SK' => '斯洛伐克語', 'sort_by_date' => '依日期排序', 'sort_by_expiration_date' => '', From 757e95ab86901bdda095b9019a4bcc9c82814b2a Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 18 Mar 2025 09:57:28 +0100 Subject: [PATCH 140/208] set previewConverters and convertToPdf --- out/out.AttributeMgr.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/out/out.AttributeMgr.php b/out/out.AttributeMgr.php index fba8266df..845a426d3 100644 --- a/out/out.AttributeMgr.php +++ b/out/out.AttributeMgr.php @@ -57,6 +57,8 @@ if($view) { $view->setParam('enableRecursiveCount', $settings->_enableRecursiveCount); $view->setParam('maxRecursiveCount', $settings->_maxRecursiveCount); $view->setParam('previewWidthList', $settings->_previewWidthList); + $view->setParam('previewConverters', isset($settings->_converters['preview']) ? $settings->_converters['preview'] : array()); + $view->setParam('convertToPdf', $settings->_convertToPdf); $view->setParam('timeout', $settings->_cmdTimeout); $view->setParam('accessobject', $accessop); $view->setParam('xsendfile', $settings->_enableXsendfile); From 9b2c120b5f13e7b10f61f7cb5311187afb675807 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 18 Mar 2025 09:57:45 +0100 Subject: [PATCH 141/208] call hooks for show document and folder row --- views/bootstrap/class.AttributeMgr.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/views/bootstrap/class.AttributeMgr.php b/views/bootstrap/class.AttributeMgr.php index 5e16006ab..a026a9d96 100644 --- a/views/bootstrap/class.AttributeMgr.php +++ b/views/bootstrap/class.AttributeMgr.php @@ -161,7 +161,11 @@ $(document).ready( function() { foreach($res['docs'] as $document) { $extracontent = array(); $extracontent['below_title'] = $this->getListRowPath($document); - echo $this->documentListRow($document, $previewer, false, 0, $extracontent); + $txt = $this->callHook('documentListItem', $document, $previewer, false, 'attributemgr', $extracontent); + if(is_string($txt)) + echo $txt; + else + echo $this->documentListRow($document, $previewer, false, 0, $extracontent); } echo "\n\n"; @@ -176,10 +180,14 @@ $(document).ready( function() { print "".getMLText("action")."\n"; print "\n\n\n"; foreach($res['contents'] as $content) { - $doc = $content->getDocument(); + $document = $content->getDocument(); $extracontent = array(); $extracontent['below_title'] = $this->getListRowPath($doc); - echo $this->documentListRow($doc, $previewer, false, 0, $extracontent); + $txt = $this->callHook('documentListItem', $document, $previewer, false, 'attributemgr', $extracontent); + if(is_string($txt)) + echo $txt; + else + echo $this->documentListRow($document, $previewer, false, 0, $extracontent); } print ""; } From df8d6edcffd5ec5fbfa29332fa121496de520f96 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 18 Mar 2025 09:58:49 +0100 Subject: [PATCH 142/208] add changes for 5.1.39 --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index ed0c07157..e2ee1f921 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,7 @@ - fix setting attributes of type user, group, document, folder when updating a document - objects can be removed from clipboard +- call hooks for document/folder list in attribute manager -------------------------------------------------------------------------------- Changes in version 5.1.38 From 597e9c89b3a002bfb7c5c092331c29b5bf2cc818 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 18 Mar 2025 11:00:52 +0100 Subject: [PATCH 143/208] start new version 5.1.40 --- CHANGELOG | 4 ++++ inc/inc.Version.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index e2ee1f921..6e3c827d2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +-------------------------------------------------------------------------------- + Changes in version 5.1.40 +-------------------------------------------------------------------------------- + -------------------------------------------------------------------------------- Changes in version 5.1.39 -------------------------------------------------------------------------------- diff --git a/inc/inc.Version.php b/inc/inc.Version.php index 4510a7760..b2a6c068b 100644 --- a/inc/inc.Version.php +++ b/inc/inc.Version.php @@ -20,7 +20,7 @@ class SeedDMS_Version { /* {{{ */ - const _number = "5.1.39"; + const _number = "5.1.40"; const _string = "SeedDMS"; function __construct() { From 54832e372750fb80814c6bd5a529854f4fb15a0d Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 18 Mar 2025 14:19:37 +0100 Subject: [PATCH 144/208] fix saving user data when language selection is turned of (Closes: #568) --- CHANGELOG | 1 + op/op.EditUserData.php | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 6e3c827d2..4ac10f57c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ -------------------------------------------------------------------------------- Changes in version 5.1.40 -------------------------------------------------------------------------------- +- fix saving user data when language selection is turned of (Closes: #568) -------------------------------------------------------------------------------- Changes in version 5.1.39 diff --git a/op/op.EditUserData.php b/op/op.EditUserData.php index 66b1b5327..fbea088de 100644 --- a/op/op.EditUserData.php +++ b/op/op.EditUserData.php @@ -46,7 +46,8 @@ if(!checkFormKey('edituserdata')) { $fullname = $_POST["fullname"]; $email = $_POST["email"]; $comment = $_POST["comment"]; -$language = $_POST["language"]; +if(isset($_POST["language"])) + $language = $_POST["language"]; /* 'theme' won't be set, if themeselector is turned off */ if(isset($_POST["theme"])) $mytheme = $_POST["theme"]; @@ -103,7 +104,7 @@ if ($user->getEmail() != $email) if ($user->getComment() != $comment) $user->setComment($comment); -if ($user->getLanguage() != $language) +if (isset($language) && $user->getLanguage() != $language) $user->setLanguage($language); if (isset($mytheme) && $user->getTheme() != $mytheme) From 9d400a808e4698484ef5ca1f9e92ffe005f12591 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 19 Mar 2025 15:40:41 +0100 Subject: [PATCH 145/208] use httpRoot when redirecting to out.ViewFolder.php --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index 5fe1d480c..7d53674b1 100644 --- a/index.php +++ b/index.php @@ -83,7 +83,7 @@ if(true) { /* Catch all route */ $app->get('/{path:.*}', function($request, $response) { return $response - ->withHeader('Location', '/out/out.ViewFolder.php') + ->withHeader('Location', $settings->_httpRoot.'out/out.ViewFolder.php') ->withStatus(302); }); From 0e6f14dbaf6563713b7c7090e8f89bd21cfe6aa5 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 21 Mar 2025 13:19:26 +0100 Subject: [PATCH 146/208] add odt2txt for converting libreoffice documents to txt --- doc/README.Converters | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/README.Converters b/doc/README.Converters index 8f83c1307..32a73f72f 100644 --- a/doc/README.Converters +++ b/doc/README.Converters @@ -49,6 +49,9 @@ application/vnd.openxmlformats-officedocument.wordprocessingml.document application/msword catdoc %s +application/vnd.oasis.opendocument.text + odt2txt %s + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx2csv -d tab %s From a4899a52ade9b19e235015e003da76c3b77bc9e7 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 21 Mar 2025 13:20:04 +0100 Subject: [PATCH 147/208] $settings must be passed into route function --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index 7d53674b1..9c0106cbe 100644 --- a/index.php +++ b/index.php @@ -81,7 +81,7 @@ if(true) { } /* Catch all route */ - $app->get('/{path:.*}', function($request, $response) { + $app->get('/{path:.*}', function($request, $response) use ($settings) { return $response ->withHeader('Location', $settings->_httpRoot.'out/out.ViewFolder.php') ->withStatus(302); From 54c3ec54fcca8151693114ff654e4ed246c2f4dc Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 21 Mar 2025 13:20:52 +0100 Subject: [PATCH 148/208] seperate seeddms info from extension list, output storage driver --- views/bootstrap/class.Info.php | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/views/bootstrap/class.Info.php b/views/bootstrap/class.Info.php index 119f85f10..88c118c5f 100644 --- a/views/bootstrap/class.Info.php +++ b/views/bootstrap/class.Info.php @@ -13,11 +13,6 @@ * @version Release: @package_version@ */ -/** - * Include parent class - */ -//require_once("class.Bootstrap.php"); - /** * Class which outputs the html page for Info view * @@ -60,17 +55,30 @@ class SeedDMS_View_Info extends SeedDMS_Theme_Style { $this->rowStart(); $this->columnStart(6); $this->contentHeading(getMLText("seeddms_info")); - $seedextensions = $extmgr->getExtensionConfiguration(); echo "\n"; echo "\n\n"; - echo ""; - echo "\n"; + echo "\n"; echo "\n\n\n"; $dbversion = $dms->getDBVersion(); - echo "\n"; + echo "\n"; if($user->isAdmin()) { - echo "\n"; + $storage = $dms->getStorage(); + echo "\n"; + echo "\n"; + } + echo "\n
    ".getMLText("name"); - echo "".getMLText("name")."
    ".getMLText('seeddms_version')."".$version->version()."
    ".getMLText('seeddms_version')."".$version->version()."
    ".getMLText('database_schema_version')."".$dbversion['major'].".".$dbversion['minor'].".".$dbversion['subminor']."
    ".getMLText('database_schema_version')."".$dbversion['major'].".".$dbversion['minor'].".".$dbversion['subminor']."
    ".getMLText('storage')."".($storage ? $storage->info() : "legacy")."
    \n"; + + if($user->isAdmin()) { + $this->contentHeading(getMLText("extension_info")); + echo "\n"; + echo "\n\n"; + echo ""; + echo ""; + echo "\n"; + echo "\n"; + echo "\n\n\n"; + $seedextensions = $extmgr->getExtensionConfiguration(); foreach($seedextensions as $extname=>$extconf) { echo ""; echo "\n"; } + echo "\n
    ".getMLText("name"); + echo "".getMLText("version")."
    "; if(!$settings->extensionIsDisabled($extname)) @@ -85,8 +93,8 @@ class SeedDMS_View_Info extends SeedDMS_Theme_Style { echo "".$extname."
    ".$extconf['title']."
    ".$extconf['version']."
    \n"; } - echo "\n\n"; $this->columnEnd(); $this->columnStart(6); if($user->isAdmin()) { From 37fd1ac969bbda46ca2aab530ced9fd1b8a39d7a Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 21 Mar 2025 13:23:07 +0100 Subject: [PATCH 149/208] replace functions directly accessing file system if documents or attachments are involved --- views/bootstrap/class.ViewDocument.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/views/bootstrap/class.ViewDocument.php b/views/bootstrap/class.ViewDocument.php index 698923c57..e40237207 100644 --- a/views/bootstrap/class.ViewDocument.php +++ b/views/bootstrap/class.ViewDocument.php @@ -308,7 +308,7 @@ $(document).ready( function() { foreach($files as $file) { - $file_exists=file_exists($dms->contentDir . $file->getPath()); + $file_exists = $file->exists();//file_exists($dms->contentDir . $file->getPath()); $responsibleUser = $file->getUser(); @@ -344,7 +344,7 @@ $(document).ready( function() { print "
  • ".htmlspecialchars($file->getOriginalFileName())."
  • \n"; if ($file_exists) { $realmimetype = $file->getRealMimeType(); - print "
  • ".SeedDMS_Core_File::format_filesize(filesize($dms->contentDir . $file->getPath())) ." bytes, ".htmlspecialchars($file->getMimeType())."
  • "; + print "
  • ".SeedDMS_Core_File::format_filesize($file->size()) ." bytes, ".htmlspecialchars($file->getMimeType())."
  • "; } else print "
  • ".htmlspecialchars($file->getMimeType())." - ".getMLText("document_deleted")."
  • "; print "
  • ".getMLText("uploaded_by")." getEmail())."\">".htmlspecialchars($responsibleUser->getFullName())."
  • "; @@ -703,7 +703,7 @@ $(document).ready( function() { $previewwidthdetail = $this->params['previewWidthDetail']; // verify if file exists - $file_exists=file_exists($dms->contentDir . $latestContent->getPath()); + $file_exists = $latestContent->exists(); //file_exists($dms->contentDir . $latestContent->getPath()); $status = $latestContent->getStatus(); @@ -1717,4 +1717,3 @@ $(document).ready( function() { $this->htmlEndPage(); } /* }}} */ } -?> From f3fa653eee5f17191a20bb92dedccb2960d0f364 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Fri, 21 Mar 2025 13:25:13 +0100 Subject: [PATCH 150/208] replace file_exists() with exists() function of object --- views/bootstrap/class.Bootstrap.php | 2 +- views/bootstrap4/class.Bootstrap4.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/views/bootstrap/class.Bootstrap.php b/views/bootstrap/class.Bootstrap.php index 91ab0bc20..8ac2e2922 100644 --- a/views/bootstrap/class.Bootstrap.php +++ b/views/bootstrap/class.Bootstrap.php @@ -3278,7 +3278,7 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) $extracontent = array_merge($extracontent, $ec); $content .= ""; - if (file_exists($dms->contentDir . $latestContent->getPath())) { + if ($latestContent->exists()) { $previewhtml = $this->callHook('documentListPreview', $previewer, $document, $latestContent); if(is_string($previewhtml)) $content .= $previewhtml; diff --git a/views/bootstrap4/class.Bootstrap4.php b/views/bootstrap4/class.Bootstrap4.php index 5ffa75298..fc8f61bf4 100644 --- a/views/bootstrap4/class.Bootstrap4.php +++ b/views/bootstrap4/class.Bootstrap4.php @@ -3327,7 +3327,7 @@ $('body').on('click', '[id^=\"table-row-folder\"] td:nth-child(2)', function(ev) $extracontent = array_merge($extracontent, $ec); $content .= ""; - if (file_exists($dms->contentDir . $latestContent->getPath())) { + if ($latestContent->exists()) { $previewhtml = $this->callHook('documentListPreview', $previewer, $document, $latestContent); if(is_string($previewhtml)) $content .= $previewhtml; From 5ce55216ad24f6f7ae58ab04515a983eea5d8c02 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Mon, 24 Mar 2025 15:55:57 +0100 Subject: [PATCH 151/208] add changes for 5.1.40 --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 4ac10f57c..87cd0e523 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ Changes in version 5.1.40 -------------------------------------------------------------------------------- - fix saving user data when language selection is turned of (Closes: #568) +- add much better support for new storage drivers -------------------------------------------------------------------------------- Changes in version 5.1.39 From edb91d329975cbd66842b010a0e3d72499432ffe Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 25 Mar 2025 18:09:41 +0100 Subject: [PATCH 152/208] fix possible xss attack --- views/bootstrap/class.Clipboard.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/views/bootstrap/class.Clipboard.php b/views/bootstrap/class.Clipboard.php index cce60ab47..7899bb055 100644 --- a/views/bootstrap/class.Clipboard.php +++ b/views/bootstrap/class.Clipboard.php @@ -52,12 +52,12 @@ class SeedDMS_View_Clipboard extends SeedDMS_Theme_Style { $subitems = []; foreach($clipboard['folders'] as $folderid) { if($folder = $this->params['dms']->getFolder($folderid)) { - $subitems[] = array('label'=>' '.$folder->getName(), 'link'=>$this->params['settings']->_httpRoot."out/out.ViewFolder.php?folderid=".$folder->getID(), 'class'=>"table-row-folder droptarget", 'attributes'=>array(array('data-droptarget', "folder_".$folder->getID()), array('rel', "folder_".$folder->getID()), array('data-name', htmlspecialchars($folder->getName(), ENT_QUOTES)))); + $subitems[] = array('label'=>' '.htmlspecialchars($folder->getName()), 'link'=>$this->params['settings']->_httpRoot."out/out.ViewFolder.php?folderid=".$folder->getID(), 'class'=>"table-row-folder droptarget", 'attributes'=>array(array('data-droptarget', "folder_".$folder->getID()), array('rel', "folder_".$folder->getID()), array('data-name', htmlspecialchars($folder->getName(), ENT_QUOTES)))); } } foreach($clipboard['docs'] as $docid) { if($document = $this->params['dms']->getDocument($docid)) - $subitems[] = array('label'=>' '.$document->getName(), 'link'=>$this->params['settings']->_httpRoot."out/out.ViewDocument.php?documentid=".$document->getID(), 'class'=>"table-row-document droptarget", 'attributes'=>array(array('data-droptarget', "document_".$document->getID()), array('rel', "document_".$document->getID()), array('formtoken', createFormKey('')), array('data-name', htmlspecialchars($document->getName(), ENT_QUOTES)))); + $subitems[] = array('label'=>' '.htmlspecialchars($document->getName()), 'link'=>$this->params['settings']->_httpRoot."out/out.ViewDocument.php?documentid=".$document->getID(), 'class'=>"table-row-document droptarget", 'attributes'=>array(array('data-droptarget', "document_".$document->getID()), array('rel', "document_".$document->getID()), array('formtoken', createFormKey('')), array('data-name', htmlspecialchars($document->getName(), ENT_QUOTES)))); } if((count($clipboard['docs']) + count($clipboard['folders'])) > 0) { $subitems[] = array('divider'=>true); From 7529c68c80b7b49aea6f7e5eb6bf44ef6969ce17 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 26 Mar 2025 07:54:33 +0100 Subject: [PATCH 153/208] include all conf.php files and var_export() them instead of concating them --- inc/inc.ClassExtensionMgr.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/inc/inc.ClassExtensionMgr.php b/inc/inc.ClassExtensionMgr.php index 3b1033364..519014339 100644 --- a/inc/inc.ClassExtensionMgr.php +++ b/inc/inc.ClassExtensionMgr.php @@ -206,13 +206,19 @@ class SeedDMS_Extension_Mgr { $fp = @fopen(self::getExtensionsConfFile(), "w"); if($fp) { if($extensions) { + $EXT_CONF = []; foreach($extensions as $_ext) { if(file_exists($this->extdir . "/" . $_ext . "/conf.php")) { - $content = file_get_contents($this->extdir . "/" . $_ext . "/conf.php"); - fwrite($fp, $content); + include $this->extdir . "/" . $_ext . "/conf.php"; +// $content = file_get_contents($this->extdir . "/" . $_ext . "/conf.php"); +// fwrite($fp, $content); } } } +// fclose($fp); +// $fp = @fopen(self::getExtensionsConfFile(), "w"); + fwrite($fp, ' Date: Wed, 26 Mar 2025 07:55:50 +0100 Subject: [PATCH 154/208] add changes for 5.1.40 --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 87cd0e523..ac498445b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,8 @@ -------------------------------------------------------------------------------- - fix saving user data when language selection is turned of (Closes: #568) - add much better support for new storage drivers +- fix possible xss attack +- saver way to collect plugin configuration -------------------------------------------------------------------------------- Changes in version 5.1.39 From 5a4042383634da834f167c066f0ae2c6b312fa30 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 26 Mar 2025 08:39:30 +0100 Subject: [PATCH 155/208] set id of some select fields for extension config --- views/bootstrap/class.Settings.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/views/bootstrap/class.Settings.php b/views/bootstrap/class.Settings.php index 7eec265b0..1a8d15b6c 100644 --- a/views/bootstrap/class.Settings.php +++ b/views/bootstrap/class.Settings.php @@ -688,7 +688,7 @@ if(($kkk = $this->callHook('getFullSearchEngine')) && is_array($kkk)) switch($conf['type']) { case 'checkbox': ?> - " value="">" value="1" _extensions[$extname][$confkey]) && $settings->_extensions[$extname][$confkey]) echo 'checked'; ?> /> + " value="">" value="1" _extensions[$extname][$confkey]) && $settings->_extensions[$extname][$confkey]) echo 'checked'; ?> /> callHook('getFullSearchEngine')) && is_array($kkk)) $order = empty($conf['order']) ? '' : $conf['order']; if(!empty($conf['options'])) { $selections = empty($settings->_extensions[$extname][$confkey]) ? array() : explode(",", $settings->_extensions[$extname][$confkey]); - echo ""; if(is_array($conf['options'])) { $options = $conf['options']; } elseif(is_string($conf['options']) && $conf['options'] == 'hook') { From d1dfc924b56c6d556c74bcd5e2b08828b30d508c Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 26 Mar 2025 08:39:58 +0100 Subject: [PATCH 156/208] fix possible xss attack when document name contains malicious code --- views/bootstrap/class.Tasks.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/views/bootstrap/class.Tasks.php b/views/bootstrap/class.Tasks.php index cfcb6c1be..dfb29f9fc 100644 --- a/views/bootstrap/class.Tasks.php +++ b/views/bootstrap/class.Tasks.php @@ -203,7 +203,7 @@ class SeedDMS_View_Tasks extends SeedDMS_Theme_Style { $subitems = []; foreach($tasks['review'] as $t) { $doc = $dms->getDocument($t['id']); - $subitems[] = array('label'=>$doc->getName(), 'link'=>$this->params['settings']->_httpRoot."out/out.ViewDocument.php?documentid=".$doc->getID()."¤ttab=revapp", 'class'=>"table-row-document", 'rel'=>"document_".$doc->getID()); + $subitems[] = array('label'=>htmlspecialchars($doc->getName()), 'link'=>$this->params['settings']->_httpRoot."out/out.ViewDocument.php?documentid=".$doc->getID()."¤ttab=revapp", 'class'=>"table-row-document", 'rel'=>"document_".$doc->getID()); } $menuitems['tasks']['children']['review'] = array('label'=>getMLText('documents_to_review'), 'children'=>$subitems); @@ -212,7 +212,7 @@ class SeedDMS_View_Tasks extends SeedDMS_Theme_Style { $subitems = []; foreach($tasks['approval'] as $t) { $doc = $dms->getDocument($t['id']); - $subitems[] = array('label'=>$doc->getName(), 'link'=>$this->params['settings']->_httpRoot."out/out.ViewDocument.php?documentid=".$doc->getID()."¤ttab=revapp", 'class'=>"table-row-document", 'rel'=>"document_".$doc->getID()); + $subitems[] = array('label'=>htmlspecialchars($doc->getName()), 'link'=>$this->params['settings']->_httpRoot."out/out.ViewDocument.php?documentid=".$doc->getID()."¤ttab=revapp", 'class'=>"table-row-document", 'rel'=>"document_".$doc->getID()); } $menuitems['tasks']['children']['approval'] = array('label'=>getMLText('documents_to_approve'), 'children'=>$subitems); } @@ -220,7 +220,7 @@ class SeedDMS_View_Tasks extends SeedDMS_Theme_Style { $subitems = []; foreach($tasks['workflow'] as $t) { $doc = $dms->getDocument($t['id']); - $subitems[] = array('label'=>$doc->getName(), 'link'=>$this->params['settings']->_httpRoot."out/out.ViewDocument.php?documentid=".$doc->getID()."¤ttab=workflow", 'class'=>"table-row-document", 'rel'=>"document_".$doc->getID()); + $subitems[] = array('label'=>htmlspecialchars($doc->getName()), 'link'=>$this->params['settings']->_httpRoot."out/out.ViewDocument.php?documentid=".$doc->getID()."¤ttab=workflow", 'class'=>"table-row-document", 'rel'=>"document_".$doc->getID()); } $menuitems['tasks']['children']['workflow'] = array('label'=>getMLText('documents_to_trigger_workflow'), 'children'=>$subitems); } @@ -228,7 +228,7 @@ class SeedDMS_View_Tasks extends SeedDMS_Theme_Style { $subitems = []; foreach($tasks['rejected'] as $t) { $doc = $dms->getDocument($t['id']); - $subitems[] = array('label'=>$doc->getName(), 'link'=>$this->params['settings']->_httpRoot."out/out.ViewDocument.php?documentid=".$doc->getID()."¤ttab=docinfo", 'class'=>"table-row-document", 'rel'=>"document_".$doc->getID()); + $subitems[] = array('label'=>htmlspecialchars($doc->getName()), 'link'=>$this->params['settings']->_httpRoot."out/out.ViewDocument.php?documentid=".$doc->getID()."¤ttab=docinfo", 'class'=>"table-row-document", 'rel'=>"document_".$doc->getID()); } $menuitems['tasks']['children']['rejected'] = array('label'=>getMLText('documents_rejected'), 'children'=>$subitems); } From 0ad6416d651defb1286e8f27a2b1e397c337a1a8 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 26 Mar 2025 09:30:33 +0100 Subject: [PATCH 157/208] fix typo --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index ac498445b..fce17f2ea 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,7 +3,7 @@ -------------------------------------------------------------------------------- - fix saving user data when language selection is turned of (Closes: #568) - add much better support for new storage drivers -- fix possible xss attack +- fix possible xss attacks - saver way to collect plugin configuration -------------------------------------------------------------------------------- From 28ba7b59b9825d8c27d37b88c94fbd3a62951982 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 26 Mar 2025 09:36:38 +0100 Subject: [PATCH 158/208] fix possible xss attack --- views/bootstrap/class.Tasks.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/views/bootstrap/class.Tasks.php b/views/bootstrap/class.Tasks.php index 419ebbc5c..8b92a6653 100644 --- a/views/bootstrap/class.Tasks.php +++ b/views/bootstrap/class.Tasks.php @@ -323,7 +323,7 @@ class SeedDMS_View_Tasks extends SeedDMS_Theme_Style { $subitems = []; foreach($tasks['receipt'] as $t) { $doc = $dms->getDocument($t['id']); - $subitems[] = array('label'=>$doc->getName(), 'link'=>"../out/out.ViewDocument.php?documentid=".$doc->getID()."¤ttab=recipients", 'class'=>"table-row-document", 'rel'=>"document_".$doc->getID()); + $subitems[] = array('label'=>htmlspecialchars($doc->getName()), 'link'=>"../out/out.ViewDocument.php?documentid=".$doc->getID()."¤ttab=recipients", 'class'=>"table-row-document", 'rel'=>"document_".$doc->getID()); } $menuitems['tasks']['children']['receipt'] = array('label'=>getMLText('documents_to_receipt'), 'children'=>$subitems); } @@ -331,7 +331,7 @@ class SeedDMS_View_Tasks extends SeedDMS_Theme_Style { $subitems = []; foreach($tasks['revision'] as $t) { $doc = $dms->getDocument($t['id']); - $subitems[] = array('label'=>$doc->getName(), 'link'=>"../out/out.ViewDocument.php?documentid=".$doc->getID()."¤ttab=revision", 'class'=>"table-row-document", 'rel'=>"document_".$doc->getID()); + $subitems[] = array('label'=>htmlspecialchars($doc->getName()), 'link'=>"../out/out.ViewDocument.php?documentid=".$doc->getID()."¤ttab=revision", 'class'=>"table-row-document", 'rel'=>"document_".$doc->getID()); } $menuitems['tasks']['children']['revision'] = array('label'=>getMLText('documents_to_revise'), 'children'=>$subitems); } @@ -339,7 +339,7 @@ class SeedDMS_View_Tasks extends SeedDMS_Theme_Style { $subitems = []; foreach($tasks['needscorrection'] as $t) { $doc = $dms->getDocument($t['id']); - $subitems[] = array('label'=>$doc->getName(), 'link'=>"../out/out.ViewDocument.php?documentid=".$doc->getID()."¤ttab=docinfo", 'class'=>"table-row-document", 'rel'=>"document_".$doc->getID()); + $subitems[] = array('label'=>htmlspecialchars($doc->getName()), 'link'=>"../out/out.ViewDocument.php?documentid=".$doc->getID()."¤ttab=docinfo", 'class'=>"table-row-document", 'rel'=>"document_".$doc->getID()); } $menuitems['tasks']['children']['needscorrection'] = array('label'=>getMLText('documents_to_correct'), 'children'=>$subitems); } @@ -355,7 +355,7 @@ class SeedDMS_View_Tasks extends SeedDMS_Theme_Style { $subitems = []; foreach($tasks['checkedout'] as $t) { $doc = $dms->getDocument($t['id']); - $subitems[] = array('label'=>$doc->getName(), 'link'=>"../out/out.ViewDocument.php?documentid=".$doc->getID()."¤ttab=docinfo", 'class'=>"table-row-document", 'rel'=>"document_".$doc->getID()); + $subitems[] = array('label'=>htmlspecialchars($doc->getName()), 'link'=>"../out/out.ViewDocument.php?documentid=".$doc->getID()."¤ttab=docinfo", 'class'=>"table-row-document", 'rel'=>"document_".$doc->getID()); } $menuitems['tasks']['children']['checkedout'] = array('label'=>getMLText('documents_checked_out_by_you'), 'children'=>$subitems); } From fc555555d27997b72f40247fa3079e65b9d452a0 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Thu, 27 Mar 2025 14:14:18 +0100 Subject: [PATCH 159/208] allow CheckOut for users --- inc/inc.ClassAccessOperation.php | 1 + 1 file changed, 1 insertion(+) diff --git a/inc/inc.ClassAccessOperation.php b/inc/inc.ClassAccessOperation.php index 4061f7533..06bd4e3a1 100644 --- a/inc/inc.ClassAccessOperation.php +++ b/inc/inc.ClassAccessOperation.php @@ -81,6 +81,7 @@ class SeedDMS_AccessOperation { 'CategoryChooser', 'ChangePassword', 'CheckInDocument', + 'CheckOutDocument', 'Clipboard', 'Dashboard', 'DocumentAccess', From 7f2d12e299e1a0922d92a2ea557ed4ce7f6edddf Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 1 Apr 2025 10:39:48 +0200 Subject: [PATCH 160/208] output timezone and current date/time on server --- views/bootstrap/class.Info.php | 1 + 1 file changed, 1 insertion(+) diff --git a/views/bootstrap/class.Info.php b/views/bootstrap/class.Info.php index 88c118c5f..7a4b4991d 100644 --- a/views/bootstrap/class.Info.php +++ b/views/bootstrap/class.Info.php @@ -106,6 +106,7 @@ class SeedDMS_View_Info extends SeedDMS_Theme_Style { echo "\n\n\n"; echo "PHP".phpversion()."\n"; echo "Path to php.ini".php_ini_loaded_file()."\n"; + echo "Timezone".date_default_timezone_get()." (Current date/time on server is ".getLongReadableDate(time()).")\n"; echo "\n\n"; $this->contentHeading(getMLText("installed_php_extensions")); From 8f2f15bb80a61c9f4b65308361756dc45ce6061b Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 1 Apr 2025 12:50:01 +0200 Subject: [PATCH 161/208] add new method extension() for showing config of extension --- views/bootstrap/class.Settings.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/views/bootstrap/class.Settings.php b/views/bootstrap/class.Settings.php index 1a8d15b6c..480d685d6 100644 --- a/views/bootstrap/class.Settings.php +++ b/views/bootstrap/class.Settings.php @@ -318,7 +318,7 @@ class SeedDMS_View_Settings extends SeedDMS_Theme_Style { params['extmgr']; header('Content-Type: application/javascript; charset=UTF-8'); @@ -369,7 +369,15 @@ console.log($(event.currentTarget).data('target').substring(1)); params['dms']; + $user = $this->params['user']; + $settings = $this->params['settings']; + $extmgr = $this->params['extmgr']; + + } /* }}} */ + + public function show() { /* {{{ */ $dms = $this->params['dms']; $user = $this->params['user']; $settings = $this->params['settings']; From 42a38984f782f2e444d07571be2b898b7fb4d8f7 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Tue, 1 Apr 2025 12:55:35 +0200 Subject: [PATCH 162/208] add method showConfigFolder() (currently not used) --- views/bootstrap/class.Settings.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/views/bootstrap/class.Settings.php b/views/bootstrap/class.Settings.php index 480d685d6..c57c6454b 100644 --- a/views/bootstrap/class.Settings.php +++ b/views/bootstrap/class.Settings.php @@ -318,6 +318,19 @@ class SeedDMS_View_Settings extends SeedDMS_Theme_Style { params['settings']; + $dms = $this->params['dms']; +?> + "> + : + +printFolderChooserHtml($name, M_READWRITE, -1, $dms->getFolder($settings->{"_".$name}), $name);?> + + +params['extmgr']; From 22f23c71f039bd86de78df08a01e337dec6d7e34 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 2 Apr 2025 08:02:09 +0200 Subject: [PATCH 163/208] fix indenting --- inc/inc.ClassSettings.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/inc/inc.ClassSettings.php b/inc/inc.ClassSettings.php index ac403bbef..f6c59003d 100644 --- a/inc/inc.ClassSettings.php +++ b/inc/inc.ClassSettings.php @@ -940,6 +940,8 @@ class Settings { /* {{{ */ if (is_null($configFilePath)) $configFilePath = $this->_configFilePath; + // copy($configFilePath, $configFilePath.'.'.time()); + // Load $xml = simplexml_load_string(file_get_contents($configFilePath)); $this->getXMLNode($xml, '/', 'configuration'); @@ -1260,9 +1262,9 @@ class Settings { /* {{{ */ */ foreach($extension as $fieldname=>$confvalue) { if($fieldname != '___disable__' && $confvalue) { - $parameter = $extnode->addChild('parameter'); - $parameter[0] = isset($extension[$fieldname]) ? (is_array($extension[$fieldname]) ? implode(',', $extension[$fieldname]) : $extension[$fieldname]) : ''; - $this->setXMLAttributValue($parameter, 'name', $fieldname); + $parameter = $extnode->addChild('parameter'); + $parameter[0] = isset($extension[$fieldname]) ? (is_array($extension[$fieldname]) ? implode(',', $extension[$fieldname]) : $extension[$fieldname]) : ''; + $this->setXMLAttributValue($parameter, 'name', $fieldname); } } /* Old code saves those parameters listed in the configuration From e578e2a206d9697bfcb9b3173cefe70c5ece1626 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 2 Apr 2025 08:02:53 +0200 Subject: [PATCH 164/208] remove old function getBoolValue() --- op/op.Settings.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/op/op.Settings.php b/op/op.Settings.php index a682ec2b6..da5a32f9f 100644 --- a/op/op.Settings.php +++ b/op/op.Settings.php @@ -29,17 +29,6 @@ include("../inc/inc.DBInit.php"); include("../inc/inc.ClassUI.php"); include("../inc/inc.Authentication.php"); - -function getBoolValue($post_name) -{ - $out = false; - if (isset($_POST[$post_name])) - if ($_POST[$post_name]=="on") - $out = true; - - return $out; -} - if (!$user->isAdmin()) { UI::exitError(getMLText("admin_tools"),getMLText("access_denied")); } From f8ceb0d56a11d610bd1b9e008016f7cc38449ac4 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 2 Apr 2025 08:03:52 +0200 Subject: [PATCH 165/208] do not set bool/array value if not exist in post data --- op/op.Settings.php | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/op/op.Settings.php b/op/op.Settings.php index da5a32f9f..db2432ad6 100644 --- a/op/op.Settings.php +++ b/op/op.Settings.php @@ -57,10 +57,12 @@ if ($action == "saveSettings") function setBoolValue($name) { global $_POST, $settings; if(!in_array($name, $settings->_hiddenConfFields)) { - if (isset($_POST[$name]) && $_POST[$name]=="on") - $settings->{"_".$name} = true; - else - $settings->{"_".$name} = false; + if (isset($_POST[$name])) { + if ($_POST[$name]=="on") + $settings->{"_".$name} = true; + else + $settings->{"_".$name} = false; + } } } function setIntValue($name) { @@ -70,11 +72,13 @@ if ($action == "saveSettings") } function setArrayValue($name) { global $_POST, $settings; - if(!in_array($name, $settings->_hiddenConfFields)) { - if(isset($_POST[$name]) && $_POST[$name]) - $settings->{"_".$name} = $_POST[$name]; - else - $settings->{"_".$name} = array(); + if (!in_array($name, $settings->_hiddenConfFields)) { + if (isset($_POST[$name])) { + if ($_POST[$name]) + $settings->{"_".$name} = $_POST[$name]; + else + $settings->{"_".$name} = array(); + } } } function setDirValue($name) { From c2d8b383c3c215f79c54bfaaaf90be46864fce7a Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 2 Apr 2025 08:04:56 +0200 Subject: [PATCH 166/208] support saving via ajax --- op/op.Settings.php | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/op/op.Settings.php b/op/op.Settings.php index db2432ad6..c72aaa84b 100644 --- a/op/op.Settings.php +++ b/op/op.Settings.php @@ -321,15 +321,21 @@ if ($action == "saveSettings") // ------------------------------------------------------------------------- // save // ------------------------------------------------------------------------- - if (!$settings->save()) - UI::exitError(getMLText("admin_tools"),getMLText("settings_SaveError")); + if (!$settings->save()) { + if(isAjax()) { + echo json_encode(array('success'=>false, 'msg'=>getMLText('settings_SaveError'))); + exit; + } else { + UI::exitError(getMLText("admin_tools"),getMLText("settings_SaveError")); + } + } add_log_line(".php&action=savesettings"); } -$session->setSplashMsg(array('type'=>'success', 'msg'=>getMLText('splash_settings_saved'))); - - -header("Location:../out/out.Settings.php?currenttab=".$_POST['currenttab']); - -?> +if(isAjax()) { + echo json_encode(array('success'=>true, 'msg'=>getMLText('splash_settings_saved'))); +} else { + $session->setSplashMsg(array('type'=>'success', 'msg'=>getMLText('splash_settings_saved'))); + header("Location:../out/out.Settings.php?currenttab=".$_POST['currenttab']); +} From 692318dcc1e566d634a0214b87164d98177a4fca Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 2 Apr 2025 08:05:37 +0200 Subject: [PATCH 167/208] pass extension name to view --- out/out.Settings.php | 1 + 1 file changed, 1 insertion(+) diff --git a/out/out.Settings.php b/out/out.Settings.php index 6f5422620..9e20ea4de 100644 --- a/out/out.Settings.php +++ b/out/out.Settings.php @@ -42,6 +42,7 @@ if($view) { $view->setParam('settings', $settings); $view->setParam('extmgr', $extMgr); $view->setParam('currenttab', (isset($_REQUEST['currenttab']) ? $_REQUEST['currenttab'] : '')); + $view->setParam('extname', (isset($_REQUEST['extensionname']) ? $_REQUEST['extensionname'] : '')); $view->setParam('allusers', $users); $view->setParam('allgroups', $groups); $view->setParam('accessobject', $accessop); From 4f3e6cadf51e647ad29e0c089c267f3acc230149 Mon Sep 17 00:00:00 2001 From: Uwe Steinmann Date: Wed, 2 Apr 2025 08:06:38 +0200 Subject: [PATCH 168/208] remove aria-hidden from some buttons --- views/bootstrap/class.Bootstrap.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/views/bootstrap/class.Bootstrap.php b/views/bootstrap/class.Bootstrap.php index 8ac2e2922..129ad00f0 100644 --- a/views/bootstrap/class.Bootstrap.php +++ b/views/bootstrap/class.Bootstrap.php @@ -1503,9 +1503,9 @@ function getOverallStatusIcon($status) { /* {{{ */ */ function getModalBox($config) { /* {{{ */ $content = ' -