commit
						690ba0407d
					
				|  | @ -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 | ||||
|  |  | |||
|  | @ -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); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -193,16 +193,13 @@ jQuery(document).ready(function() { | |||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <div class="ui-tabs ui-corner-all ui-widget ui-widget-content"> | ||||
| <ul class="ui-tabs-nav ui-corner-all ui-helper-reset ui-helper-clearfix ui-widget-header"> | ||||
| 	<?php | ||||
| 		printTypeTabs($headerPrefix); | ||||
| 	?>
 | ||||
| </ul> | ||||
| 
 | ||||
| <?php | ||||
| printTypeTabs($headerPrefix); | ||||
| 
 | ||||
| function printTypeTabs($headerPrefix) { | ||||
| 	echo '<div class="ui-tabs ui-corner-all ui-widget ui-widget-content">'; | ||||
| 	echo '<ul class="ui-tabs-nav ui-corner-all ui-helper-reset ui-helper-clearfix ui-widget-header">'; | ||||
| 	$typeManager = new \LAM\TYPES\TypeManager(); | ||||
| 	$types = $typeManager->getConfiguredTypes(); | ||||
| 	foreach ($types as $type) { | ||||
|  | @ -217,5 +214,6 @@ function printTypeTabs($headerPrefix) { | |||
| 		echo $link; | ||||
| 		echo "</li>\n"; | ||||
| 	} | ||||
| 	echo '</ul>'; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
| 				} | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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 .= '<a href="mailto:' . htmlspecialchars($personalAttributes['mail'][0]) . '">' . htmlspecialchars($personalAttributes['mail'][0]) . '</a>' . $spacer; | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <?php | ||||
| /* | ||||
|  This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/) | ||||
|  Copyright (C) 2018  Roland Gruber | ||||
|  Copyright (C) 2018 - 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 | ||||
|  | @ -128,4 +128,20 @@ class AccountTest extends PHPUnit_Framework_TestCase { | |||
| 		$this->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')); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue