diff --git a/CHANGELOG b/CHANGELOG index 4326b33b0..f5a9c050f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +-------------------------------------------------------------------------------- + Changes in version 6.0.12 +-------------------------------------------------------------------------------- +- merge changes up to 5.1.19 + -------------------------------------------------------------------------------- Changes in version 6.0.11 -------------------------------------------------------------------------------- @@ -157,6 +162,12 @@ - add document list which can be exported as an archive - search results can be exported +-------------------------------------------------------------------------------- + Changes in version 5.1.19 +-------------------------------------------------------------------------------- +- add hooks showDocumentAttribute and showDocumentContentAttribute in Search view +- fix layout problems of select2 menu, add option for adding an icon to each option + -------------------------------------------------------------------------------- Changes in version 5.1.18 -------------------------------------------------------------------------------- diff --git a/SeedDMS_Core/Core/inc.ClassDMS.php b/SeedDMS_Core/Core/inc.ClassDMS.php index 85ffcab7b..0b54c5fdf 100644 --- a/SeedDMS_Core/Core/inc.ClassDMS.php +++ b/SeedDMS_Core/Core/inc.ClassDMS.php @@ -472,7 +472,7 @@ class SeedDMS_Core_DMS { $this->lasterror = ''; $this->version = '@package_version@'; if($this->version[0] == '@') - $this->version = '6.0.11'; + $this->version = '6.0.12'; } /* }}} */ /** @@ -824,7 +824,9 @@ class SeedDMS_Core_DMS { * Returns a document by its name * * This function searches a document by its name and restricts the search - * to given folder if passed as the second parameter. + * to the given folder if passed as the second parameter. + * If there are more than one document with that name, then only the first + * one will be returned. * * @param string $name * @param object $folder diff --git a/SeedDMS_Core/package.xml b/SeedDMS_Core/package.xml index b4317f562..6d1736908 100644 --- a/SeedDMS_Core/package.xml +++ b/SeedDMS_Core/package.xml @@ -15,8 +15,8 @@ 2020-06-05 - 6.0.11 - 6.0.11 + 6.0.12 + 6.0.12 stable @@ -24,7 +24,7 @@ GPL License -SeedDMS_Core_DMS::filterAccess() properly checks for documents +- ??? @@ -1802,6 +1802,21 @@ add method SeedDMS_Core_DatabaseAccess::setLogFp() - fix SeedDMS_Core_DMS::getDocumentByOriginalFilename() + + 2020-07-30 + + + 5.1.19 + 5.1.19 + + + stable + stable + + GPL License + + + 2017-02-28 @@ -2036,5 +2051,21 @@ remove a user from all its process can also be used to set a new user SeedDMS_Core_DocumentContent::delRevisor() returns -4 if user has already made a revision + + 2020-06-05 + + + 6.0.11 + 6.0.11 + + + stable + stable + + GPL License + +SeedDMS_Core_DMS::filterAccess() properly checks for documents + + diff --git a/controllers/class.UserListCsv.php b/controllers/class.UserListCsv.php index 5debafc6e..7d321849c 100644 --- a/controllers/class.UserListCsv.php +++ b/controllers/class.UserListCsv.php @@ -33,12 +33,12 @@ class SeedDMS_Controller_UserListCsv extends SeedDMS_Controller_Common { $m = max($m, count($u->getGroups())); } $fp = fopen("php://temp/maxmemory", 'r+'); - $header = array('login', 'name', 'email', 'comment', 'role', 'quota', 'homefolder'); + $header = array('login', 'passenc', 'name', 'email', 'comment', 'role', 'quota', 'homefolder'); for($i=1; $i<=$m; $i++) $header[] = 'group_'.$i; fputcsv($fp, $header, ';'); foreach($allUsers as $u) { - $data = array($u->getLogin(), $u->getFullName(), $u->getEmail(), $u->getComment(), $u->isAdmin() ? 'admin' : ($u->isGuest() ? 'guest' : 'user'), $u->getQuota(), $u->getHomeFolder() ? $u->getHomeFolder() : ''); + $data = array($u->getLogin(), $u->getPwd(), $u->getFullName(), $u->getEmail(), $u->getComment(), $u->isAdmin() ? 'admin' : ($u->isGuest() ? 'guest' : 'user'), $u->getQuota(), $u->getHomeFolder() ? $u->getHomeFolder() : ''); foreach($u->getGroups() as $g) $data[] = $g->getName(); fputcsv($fp, $data, ';'); diff --git a/inc/inc.ClassDbAuthentication.php b/inc/inc.ClassDbAuthentication.php index 18838ee3e..5d94b2c64 100644 --- a/inc/inc.ClassDbAuthentication.php +++ b/inc/inc.ClassDbAuthentication.php @@ -58,7 +58,7 @@ class SeedDMS_DbAuthentication extends SeedDMS_Authentication { // Check if password matches (if not a guest user) // Assume that the password has been sent via HTTP POST. It would be careless // (and dangerous) for passwords to be sent via GET. - if (md5($password) != $user->getPwd()) { + if (!seed_pass_verify($password, $user->getPwd())) { /* if counting of login failures is turned on, then increment its value */ if($settings->_loginFailure) { $failures = $user->addLoginFailure(); diff --git a/inc/inc.Utils.php b/inc/inc.Utils.php index e4b2582ab..0c2c43e4c 100644 --- a/inc/inc.Utils.php +++ b/inc/inc.Utils.php @@ -615,7 +615,7 @@ function getBaseUrl() { /* {{{ */ return "http".((isset($_SERVER['HTTPS']) && (strcmp($_SERVER['HTTPS'],'off')!=0)) ? "s" : "")."://".$_SERVER['HTTP_HOST']; } /* }}} */ -function getToken($length){ +function getToken($length){ /* {{{ */ $token = ""; $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; $codeAlphabet.= "abcdefghijklmnopqrstuvwxyz"; @@ -627,7 +627,27 @@ function getToken($length){ } return $token; -} +} /* }}} */ + +/** + * Hash a password + * + * @param string $password + * @return string hashed password + */ +function seed_pass_hash($password) { /* {{{ */ + return md5($password); +} /* }}} */ + +/** + * Verify a password + * + * @param string $password + * @return string hashed password + */ +function seed_pass_verify($password, $hash) { /* {{{ */ + return $hash == md5($password); +} /* }}} */ function resolveTask($task) { global $dms, $user, $settings, $logger; @@ -642,19 +662,19 @@ function resolveTask($task) { return $task; } -class SeedDMS_CSRF { +class SeedDMS_CSRF { /* {{{ */ protected $secret; - public function __construct($secret) { + public function __construct($secret) { /* {{{ */ $this->secret = $secret; - } + } /* }}} */ - public function create_api_key() { + public function create_api_key() { /* {{{ */ return base64_encode($this->encrypt(time().'|'.$_SERVER['REMOTE_ADDR'])); // !change if you dont want IP check - } + } /* }}} */ - public function check_api_key($key, $timeout = 5) { + public function check_api_key($key, $timeout = 5) { /* {{{ */ if (empty($key)) exit('Invalid Key'); $keys = explode('|', $this->decrypt(base64_decode($key))); @@ -664,9 +684,9 @@ class SeedDMS_CSRF { $keys[0] >= (time() - $timeout) && $keys[1] == $_SERVER['REMOTE_ADDR'] // !change if you dont want IP check ); - } + } /* }}} */ - public function encrypt($string, $key = 'PrivateKey', $method = 'AES-256-CBC') { + public function encrypt($string, $key = 'PrivateKey', $method = 'AES-256-CBC') { /* {{{ */ // hash $key = hash('sha256', $key); // create iv - encrypt method AES-256-CBC expects 16 bytes @@ -675,9 +695,9 @@ class SeedDMS_CSRF { $output = openssl_encrypt($string, $method, $key, 0, $iv); // encode return base64_encode($output); - } + } /* }}} */ - public function decrypt($string, $key = 'PrivateKey', $method = 'AES-256-CBC') { + public function decrypt($string, $key = 'PrivateKey', $method = 'AES-256-CBC') { /* {{{ */ // hash $key = hash('sha256', $key); // create iv - encrypt method AES-256-CBC expects 16 bytes @@ -686,8 +706,8 @@ class SeedDMS_CSRF { $string = base64_decode($string); // decrypt return openssl_decrypt($string, $method, $key, 0, $iv); - } -} + } /* }}} */ +} /* }}} */ //$CSRF = new SeedDMS_CSRF($settings->_encryptionKey); //$kkk = $CSRF->create_api_key(); diff --git a/inc/inc.Version.php b/inc/inc.Version.php index 9a49e5774..23545fbef 100644 --- a/inc/inc.Version.php +++ b/inc/inc.Version.php @@ -20,7 +20,7 @@ class SeedDMS_Version { /* {{{ */ - const _number = "6.0.11"; + const _number = "6.0.12"; const _string = "SeedDMS"; function __construct() { diff --git a/op/op.ChangePassword.php b/op/op.ChangePassword.php index c15da5a68..d481dd129 100644 --- a/op/op.ChangePassword.php +++ b/op/op.ChangePassword.php @@ -54,7 +54,7 @@ if (empty($newpassword) || empty($newpasswordrepeat) || $newpassword != $newpass $user = $dms->checkPasswordRequest($hash); if($user) { - $user->setPwd(md5($newpassword)); + $user->setPwd(seed_pass_hash($newpassword)); $dms->deletePasswordRequest($hash); header('Location: ../out/out.Login.php'); exit; diff --git a/op/op.EditUserData.php b/op/op.EditUserData.php index 749bbda20..08385c97b 100644 --- a/op/op.EditUserData.php +++ b/op/op.EditUserData.php @@ -46,7 +46,7 @@ if(isset($_POST["theme"])) $mytheme = $_POST["theme"]; $current_pwd = $_POST["currentpwd"]; -if($user->getPwd() != md5($current_pwd)) { +if(!seed_pass_verify($current_pwd, $user->getPwd())) { UI::exitError(getMLText("edit_user_details"),getMLText("password_wrong")); } @@ -61,14 +61,14 @@ if (isset($_POST["pwd"]) && ($_POST["pwd"] != "")) { if ($current_pwd == $_POST["pwd"]) // history doesn't have the initial pw stored yet UI::exitError(getMLText("set_password"),getMLText("password_already_used")); $phm = new SeedDMS_PasswordHistoryManager($db); - $oldpwd = $phm->search($user, md5($_POST["pwd"])); + $oldpwd = $phm->search($user, seed_pass_hash($_POST["pwd"])); if($oldpwd) { UI::exitError(getMLText("set_password"),getMLText("password_already_used")); } else { - $phm->add($user, md5($_POST["pwd"])); + $phm->add($user, seed_pass_hash($_POST["pwd"])); } } - $user->setPwd(md5($_POST["pwd"])); + $user->setPwd(seed_pass_hash($_POST["pwd"])); $user->setPwdExpiration(date('Y-m-d H:i:s', time()+$settings->_passwordExpiration*86400)); } else { UI::exitError(getMLText("set_password"),getMLText("password_strength_insuffient")); @@ -76,14 +76,14 @@ if (isset($_POST["pwd"]) && ($_POST["pwd"] != "")) { } else { if($settings->_passwordHistory > 0) { $phm = new SeedDMS_PasswordHistoryManager($db); - $oldpwd = $phm->search($user, md5($_POST["pwd"])); + $oldpwd = $phm->search($user, seed_pass_hash($_POST["pwd"])); if($oldpwd) { UI::exitError(getMLText("set_password"),getMLText("password_already_used")); } else { - $phm->add($user, md5($_POST["pwd"])); + $phm->add($user, seed_pass_hash($_POST["pwd"])); } } - $user->setPwd(md5($_POST["pwd"])); + $user->setPwd(seed_pass_hash($_POST["pwd"])); $user->setPwdExpiration(date('Y-m-d H:i:s', time()+$settings->_passwordExpiration*86400)); } } diff --git a/op/op.ImportUsers.php b/op/op.ImportUsers.php index 68c19d842..210055c7d 100644 --- a/op/op.ImportUsers.php +++ b/op/op.ImportUsers.php @@ -31,6 +31,11 @@ function getBaseData($colname, $coldata, $objdata) { /* {{{ */ return $objdata; } /* }}} */ +function getPasswordPlainData($colname, $coldata, $objdata) { /* {{{ */ + $objdata['passenc'] = seed_pass_hash($coldata); + return $objdata; +} /* }}} */ + function getQuotaData($colname, $coldata, $objdata) { /* {{{ */ $objdata[$colname] = SeedDMS_Core_File::parse_filesize($coldata); return $objdata; @@ -98,7 +103,9 @@ if (isset($_FILES['userdata']) && $_FILES['userdata']['error'] == 0) { $colmap[$i] = array("getFolderData", $colname); } elseif(in_array($colname, array('quota'))) { $colmap[$i] = array("getQuotaData", $colname); - } elseif(in_array($colname, array('login', 'name', 'email', 'comment', 'group'))) { + } elseif(in_array($colname, array('password'))) { + $colmap[$i] = array("getPasswordPlainData", $colname); + } elseif(in_array($colname, array('login', 'name', 'passenc', 'email', 'comment', 'group'))) { $colmap[$i] = array("getBaseData", $colname); } elseif(substr($colname, 0, 5) == 'attr:') { $kk = explode(':', $colname, 2); @@ -141,6 +148,11 @@ if (isset($_FILES['userdata']) && $_FILES['userdata']['error'] == 0) { if($makeupdate) $eu->setEmail($u['email']); } + if(isset($u['passenc']) && $u['passenc'] != $eu->getPwd()) { + $log[] = array('id'=>$eu->getLogin(), 'type'=>'success', 'msg'=> "Encrypted password of user updated. '".$u['passenc']."' != '".$eu->getPwd()."'"); + if($makeupdate) + $eu->setPwd($u['passenc']); + } if(isset($u['comment']) && $u['comment'] != $eu->getComment()) { $log[] = array('id'=>$eu->getLogin(), 'type'=>'success', 'msg'=> "Comment of user updated. '".$u['comment']."' != '".$eu->getComment()."'"); if($makeupdate) diff --git a/op/op.UsrMgr.php b/op/op.UsrMgr.php index f0aef6184..5147def49 100644 --- a/op/op.UsrMgr.php +++ b/op/op.UsrMgr.php @@ -68,7 +68,7 @@ if ($action == "adduser") { UI::exitError(getMLText("admin_tools"),getMLText("user_exists")); } - $newUser = $dms->addUser($login, md5($pwd), $name, $email, $settings->_language, $settings->_theme, $comment, $role, $isHidden, $isDisabled, $pwdexpiration, $quota, $homefolder); + $newUser = $dms->addUser($login, seed_pass_hash($pwd), $name, $email, $settings->_language, $settings->_theme, $comment, $role, $isHidden, $isDisabled, $pwdexpiration, $quota, $homefolder); if ($newUser) { /* Set user image if uploaded */ @@ -388,7 +388,7 @@ else if ($action == "edituser") { $editedUser->setPwd(''); } else { if (isset($pwd) && ($pwd != "")) { - $editedUser->setPwd(md5($pwd)); + $editedUser->setPwd(seed_pass_hash($pwd)); } } if ($editedUser->getFullName() != $name) diff --git a/styles/bootstrap/application.js b/styles/bootstrap/application.js index b6f0d1435..abca13f75 100644 --- a/styles/bootstrap/application.js +++ b/styles/bootstrap/application.js @@ -11,7 +11,10 @@ chzn_template_func = function (state) { var warning = ''; if($(state.element).data('warning')) warning = $(state.element).data('warning')+''; /* make sure it is a string */ - var html = ''+state.text.replace(/ '; + html += state.text.replace(/'; if(warning) @@ -58,8 +61,8 @@ $(document).ready( function() { $(".chzn-select").select2({ width: '100%', - templateResult: chzn_template_func, - templateSelection: chzn_template_func + templateResult: chzn_template_func//, + //templateSelection: chzn_template_func }); /* change the color and length of the bar graph showing the password @@ -377,8 +380,8 @@ $(document).ready( function() { element.html(data); $(".chzn-select").select2({ width: '100%', - templateResult: chzn_template_func, - templateSelection: chzn_template_func + templateResult: chzn_template_func//, + //templateSelection: chzn_template_func }); $(".pwd").passStrength({ /* {{{ */ url: "../op/op.Ajax.php", @@ -426,8 +429,8 @@ $(document).ready( function() { element.html(data); $(".chzn-select").select2({ width: '100%', - templateResult: chzn_template_func, - templateSelection: chzn_template_func + templateResult: chzn_template_func//, + //templateSelection: chzn_template_func }); $(".pwd").passStrength({ /* {{{ */ url: "../op/op.Ajax.php", diff --git a/views/bootstrap/class.Search.php b/views/bootstrap/class.Search.php index 768a51fa9..b251a0f70 100644 --- a/views/bootstrap/class.Search.php +++ b/views/bootstrap/class.Search.php @@ -626,18 +626,40 @@ $(document).ready( function() { $attrstr .= "\n"; $attrstr .= ""; foreach($lcattributes as $lcattribute) { - $attrdef = $lcattribute->getAttributeDefinition(); - $attrstr .= "\n"; + $arr = $this->callHook('showDocumentContentAttribute', $lc, $lcattribute); + if(is_array($arr)) { + $attrstr .= ""; + $attrstr .= ""; + $attrstr .= ""; + $attrstr .= ""; + } elseif(is_string($arr)) { + $attrstr .= $arr; + } else { + $attrdef = $lcattribute->getAttributeDefinition(); + $attrstr .= "\n"; + // TODO: better use printAttribute() + // $this->printAttribute($lcattribute); + } } $attrstr .= "
".getMLText('name')."".getMLText('attribute_value')."
".htmlspecialchars($attrdef->getName())."".htmlspecialchars(implode(', ', $lcattribute->getValueAsArray()))."
".$arr[0].":".$arr[1]."
".htmlspecialchars($attrdef->getName())."".htmlspecialchars(implode(', ', $lcattribute->getValueAsArray()))."
\n"; } - $docttributes = $document->getAttributes(); - if($docttributes) { + $docattributes = $document->getAttributes(); + if($docattributes) { $attrstr .= "\n"; $attrstr .= ""; - foreach($docttributes as $docttribute) { - $attrdef = $docttribute->getAttributeDefinition(); - $attrstr .= "\n"; + foreach($docattributes as $docattribute) { + $arr = $this->callHook('showDocumentAttribute', $document, $docattribute); + if(is_array($arr)) { + $attrstr .= ""; + $attrstr .= ""; + $attrstr .= ""; + $attrstr .= ""; + } elseif(is_string($arr)) { + $attrstr .= $arr; + } else { + $attrdef = $docattribute->getAttributeDefinition(); + $attrstr .= "\n"; + } } $attrstr .= "
".getMLText('name')."".getMLText('attribute_value')."
".htmlspecialchars($attrdef->getName())."".htmlspecialchars(implode(', ', $docttribute->getValueAsArray()))."
".$arr[0].":".$arr[1]."
".htmlspecialchars($attrdef->getName())."".htmlspecialchars(implode(', ', $docattribute->getValueAsArray()))."
\n"; } diff --git a/views/bootstrap/class.ViewFolder.php b/views/bootstrap/class.ViewFolder.php index 0a6ed225e..3f30e3890 100644 --- a/views/bootstrap/class.ViewFolder.php +++ b/views/bootstrap/class.ViewFolder.php @@ -613,10 +613,11 @@ $('body').on('click', '.order-btn', function(ev) { echo ""; } -// $this->folderList(); + echo $this->callHook('rightContentPre'); ?>
getID()."&orderby=".$orderby."\"" : "") ?>>
callHook('rightContentPost'); echo "\n"; // End of right column div echo "\n"; // End of div around left and right column