diff --git a/lam/HISTORY b/lam/HISTORY index 10591170..ad6f591c 100644 --- a/lam/HISTORY +++ b/lam/HISTORY @@ -1,7 +1,9 @@ December 2019 7.0 - Lamdaemon can be configured with directory prefix for homedirs + - Account list filters match on substrings instead of whole value - Fixed bugs: -> Missing CSS for Duo + -> Editing of DNs with comma on Windows (210) 29.09.2019 6.9 - Group account types can show member+owner count in list view diff --git a/lam/lib/account.inc b/lam/lib/account.inc index a43076eb..25a04091 100644 --- a/lam/lib/account.inc +++ b/lam/lib/account.inc @@ -673,7 +673,6 @@ function get_preg($argument, $regexp) { * @return String escaped DN */ function escapeDN($dn) { - $dn = preg_replace('/[ ]*,[ ]*/', ',', $dn); return str_replace( array(')', '(', ' ', '*'), array('\\29', '\\28', '\\20', '\\2a'), @@ -693,6 +692,19 @@ function escapeRDN($rdn) { $rdn); } +/** + * Converts the comma escaping from Windows to OpenLDAP style. + * + * @param string $dn DN + * @return string DN + */ +function convertCommaEscaping($dn) { + return str_replace( + array('\\,'), + array('\\2C'), + $dn); +} + /** * Connects to an LDAP server using the given URL. * @@ -1041,6 +1053,7 @@ function getAbstractDN($dn) { if ($dn == '') { return ''; } + $dn = str_replace('\\,', '\\2C', $dn); $parts = explode(',', $dn); for ($i = 0; $i < sizeof($parts); $i++) { $subparts = explode('=', $parts[$i]); @@ -1048,7 +1061,8 @@ function getAbstractDN($dn) { $parts[$i] = $subparts[1]; } } - return implode(' > ', $parts); + $abstractDn = implode(' > ', $parts); + return str_replace(array('\\2C', '\\,'), array(',', ','), $abstractDn); } /** @@ -1214,6 +1228,7 @@ function extractDNSuffix($dn) { if ($dn == null) { return null; } + $dn = convertCommaEscaping($dn); return substr($dn, strpos($dn, ',')+1); } diff --git a/lam/lib/adminHeader.inc b/lam/lib/adminHeader.inc index 85d258e0..6a8ed1b7 100644 --- a/lam/lib/adminHeader.inc +++ b/lam/lib/adminHeader.inc @@ -193,16 +193,13 @@ jQuery(document).ready(function() { }); -
- '; + echo ''; } diff --git a/lam/lib/lists.inc b/lam/lib/lists.inc index eb27dd40..44528327 100644 --- a/lam/lib/lists.inc +++ b/lam/lib/lists.inc @@ -1080,7 +1080,14 @@ class lamList { if (!$this->isAttributeFilteredByServer($attr)) { continue; } - $text .= '(' . $attr . '=' . $filter . ')'; + $filterExpression = $filter; + if (strpos($filter, '*') !== 0) { + $filterExpression = '*' . $filterExpression; + } + if (strrpos($filter, '*') !== (strlen($filter) - 1)) { + $filterExpression = $filterExpression . '*'; + } + $text .= '(' . $attr . '=' . $filterExpression . ')'; } return $text; } @@ -1113,7 +1120,7 @@ class lamList { continue; } $regex = str_replace(array('*'), array('.*'), $filterValue); - $regex = '/^' . $regex . '$/i'; + $regex = '/' . $regex . '/i'; if (!$this->isFilterMatching($data, $filterAttribute, $regex)) { $toFilter[] = $index; } diff --git a/lam/lib/modules.inc b/lam/lib/modules.inc index 6aadc869..60ac11f9 100644 --- a/lam/lib/modules.inc +++ b/lam/lib/modules.inc @@ -1051,10 +1051,9 @@ class accountContainer { $titleBarContainer = new htmlResponsiveRow(); $titleBarContainer->setCSSClasses(array('maxrow')); $titleBarTitleText = new htmlOutputText($this->titleBarTitle, false); - $titleBarContainer->add(new htmlDiv(null, $titleBarTitleText, array('titleBarTitle', 'text-left')), 12); - $titleBarContainer->addVerticalSpacer('0.5rem'); + $titleBarContainer->add(new htmlDiv(null, $titleBarTitleText, array('titleBarTitle', 'text-left')), 12, 12, 4); $titleBarSubtitleText = new htmlOutputText($this->titleBarSubtitle, false); - $titleBarContainer->add(new htmlDiv(null, $titleBarSubtitleText, array('titleBarSubtitle', 'text-left')), 12); + $titleBarContainer->add(new htmlDiv(null, $titleBarSubtitleText, array('titleBarSubtitle', 'responsiveLabel')), 12, 12, 8); $titleBarSuffixRdn = new htmlResponsiveRow(); $titleBarSuffixRdn->add(new htmlHorizontalLine(), 12); // suffix @@ -1314,6 +1313,7 @@ class accountContainer { . getSecurityTokenName() . '\',\'' . getSecurityTokenValue() . '\');'); $leftButtonGroup->addElement($passwordButton); } + // delete button if (!$this->isNewAccount) { $leftButtonGroup->addElement(new htmlSpacer('15px', null)); $deleteButton = new htmlButton('accountContainerDelete', _('Delete')); @@ -1321,7 +1321,7 @@ class accountContainer { $deleteButton->setCSSClasses(array('fullwidth-mobile-only')); $leftButtonGroup->addElement($deleteButton); } - $row->add($leftButtonGroup, 12, 7); + $row->add($leftButtonGroup, 12, 9); $rightGroup = new htmlGroup(); // profile selection @@ -1340,7 +1340,7 @@ class accountContainer { $rightGroup->addElement(new htmlSpacer('1px', null)); $rightGroup->addElement(new htmlHelpLink('401')); } - $row->add($rightGroup, 12, 5, 5, 'text-right'); + $row->add($rightGroup, 12, 3, 3, 'text-right'); parseHtml(null, $row, array(), false, $tabindex, $this->type->getScope()); } @@ -1937,9 +1937,9 @@ class accountContainer { } // Set to true if an real error has happened $stopprocessing = false; - if (strtolower($this->finalDN) != strtolower($this->dn_orig)) { + if (strtolower($this->finalDN) != convertCommaEscaping(strtolower($this->dn_orig))) { // move existing DN - if ($this->dn_orig!='') { + if ($this->dn_orig != '') { $removeOldRDN = false; if (isset($attributes[$this->finalDN]['modify'])) { $attributes[$this->finalDN]['modify'] = array_change_key_case($attributes[$this->finalDN]['modify'], CASE_LOWER); diff --git a/lam/lib/types/user.inc b/lam/lib/types/user.inc index f7fabada..19957452 100644 --- a/lam/lib/types/user.inc +++ b/lam/lib/types/user.inc @@ -128,6 +128,7 @@ class user extends baseType { * @return String title text */ public function getTitleBarTitle($container) { + $title = $this->buildAccountStatusIcon($container); // get attributes $personalAttributes = null; if ($container->getAccountModule('inetOrgPerson') != null) { @@ -158,37 +159,37 @@ class user extends baseType { // check if first and last name can be shown if (($personalAttributes != null) && isset($personalAttributes['sn'][0]) && !empty($personalAttributes['sn'][0]) && isset($personalAttributes['givenName'][0]) && !empty($personalAttributes['givenName'][0])) { - return htmlspecialchars($personalAttributes['givenName'][0] . ' ' . $personalAttributes['sn'][0]); + return $title . htmlspecialchars($personalAttributes['givenName'][0] . ' ' . $personalAttributes['sn'][0]); } // check if a display name is set if (($sambaAttributes != null) && isset($sambaAttributes['displayName'][0]) && !empty($sambaAttributes['displayName'][0])) { - return htmlspecialchars($sambaAttributes['displayName'][0]); + return $title . htmlspecialchars($sambaAttributes['displayName'][0]); } // check if a common name is set if (($personalAttributes != null) && isset($personalAttributes['cn'][0]) && !empty($personalAttributes['cn'][0])) { - return htmlspecialchars($personalAttributes['cn'][0]); + return $title . htmlspecialchars($personalAttributes['cn'][0]); } if (($unixAttributes != null) && isset($unixAttributes['cn'][0]) && !empty($unixAttributes['cn'][0])) { - return htmlspecialchars($unixAttributes['cn'][0]); + return $title . htmlspecialchars($unixAttributes['cn'][0]); } // check if a user name is set if (($unixAttributes != null) && isset($unixAttributes['uid'][0]) && !empty($unixAttributes['uid'][0])) { - return htmlspecialchars($unixAttributes['uid'][0]); + return $title . htmlspecialchars($unixAttributes['uid'][0]); } if (($personalAttributes != null) && isset($personalAttributes['uid'][0]) && !empty($personalAttributes['uid'][0])) { - return htmlspecialchars($personalAttributes['uid'][0]); + return $title . htmlspecialchars($personalAttributes['uid'][0]); } if (($accountAttributes != null) && isset($accountAttributes['uid'][0]) && !empty($accountAttributes['uid'][0])) { - return htmlspecialchars($accountAttributes['uid'][0]); + return $title . htmlspecialchars($accountAttributes['uid'][0]); } if (($mitKerberosAttributes != null) && isset($mitKerberosAttributes['krbPrincipalName'][0]) && !empty($mitKerberosAttributes['krbPrincipalName'][0])) { - return htmlspecialchars($mitKerberosAttributes['krbPrincipalName'][0]); + return $title . htmlspecialchars($mitKerberosAttributes['krbPrincipalName'][0]); } if ($container->isNewAccount) { - return _("New user"); + return $title . _("New user"); } // fall back to default - return parent::getTitleBarTitle($container); + return $title . parent::getTitleBarTitle($container); } /** @@ -206,10 +207,10 @@ class user extends baseType { $personalAttributes = $container->getAccountModule('windowsUser')->getAttributes(); } if ($personalAttributes == null) { - return $this->buildAccountStatusIcon($container); + return ''; } - $subtitle = $this->buildAccountStatusIcon($container); - $spacer = '        '; + $subtitle = ''; + $spacer = '     '; // check if an email address can be shown if (isset($personalAttributes['mail'][0]) && !empty($personalAttributes['mail'][0])) { $subtitle .= '' . htmlspecialchars($personalAttributes['mail'][0]) . '' . $spacer; diff --git a/lam/style/500_layout.css b/lam/style/500_layout.css index 9ec2e82b..b92b8a94 100644 --- a/lam/style/500_layout.css +++ b/lam/style/500_layout.css @@ -226,8 +226,9 @@ textarea { table.lamHeader { background-image: url(lam-images/headerLine.png); - padding: 0px 0px 0.5rem 0px; + padding: 0px; height: 35px; + margin-bottom: 0.5rem; } table.lamTop { @@ -587,7 +588,7 @@ tr.account { } #lamVerticalTabs .ui-tabs-panel { - padding: 1em; + padding: 0em 1em 1em 1em; float: left; } diff --git a/lam/templates/tree/treeViewContainer.php b/lam/templates/tree/treeViewContainer.php index 5c6a95e9..69a12065 100644 --- a/lam/templates/tree/treeViewContainer.php +++ b/lam/templates/tree/treeViewContainer.php @@ -2,7 +2,7 @@ /* This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/) - Copyright (C) 2010 - 2018 Roland Gruber + Copyright (C) 2010 - 2019 Roland Gruber This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lam/tests/lib/accountTest.php b/lam/tests/lib/accountTest.php index 3bef321e..769e9a7d 100644 --- a/lam/tests/lib/accountTest.php +++ b/lam/tests/lib/accountTest.php @@ -1,7 +1,7 @@ assertEquals('http://base/test.php', getCallingURL('http://base')); } + /** + * Tests convertCommaEscaping(). + */ + function testConvertCommaEscaping() { + $this->assertEquals('cn=test\\2C user,ou=People,o=test,c=de', convertCommaEscaping('cn=test\\, user,ou=People,o=test,c=de')); + } + + /** + * Tests getAbstractDN(). + */ + function testGetAbstractDN() { + $this->assertEquals('test > test > de', getAbstractDN('cn=test,o=test,c=de')); + $this->assertEquals('test,user > test > de', getAbstractDN('cn=test\\,user,o=test,c=de')); + $this->assertEquals('test,user > test > de', getAbstractDN('cn=test\\2Cuser,o=test,c=de')); + } + }