From 02f292d0fdb3bdc2501364bf0dff96e1e2fcf502 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Tue, 17 Sep 2013 19:25:15 +0200 Subject: [PATCH 01/33] Doc fix --- apps/user_ldap/lib/connection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index 93efdb4c9cb..468f4b004bd 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -1,7 +1,7 @@ Date: Thu, 26 Sep 2013 22:31:57 +0200 Subject: [PATCH 02/33] LDAP: move Configuration out of Connection into class of its own. The new wizard requires it. --- apps/user_ldap/lib/access.php | 2 +- apps/user_ldap/lib/configuration.php | 352 ++++++++++++++++ apps/user_ldap/lib/connection.php | 598 ++++++++++----------------- apps/user_ldap/settings.php | 3 +- 4 files changed, 562 insertions(+), 393 deletions(-) create mode 100644 apps/user_ldap/lib/configuration.php diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index f75a78bcb0b..6177693c489 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -831,7 +831,7 @@ class Access extends LDAPUtility { private function combineFilter($filters, $operator) { $combinedFilter = '('.$operator; foreach($filters as $filter) { - if($filter[0] !== '(') { + if(!empty($filter) && $filter[0] !== '(') { $filter = '('.$filter.')'; } $combinedFilter.=$filter; diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php new file mode 100644 index 00000000000..e9e494c2f63 --- /dev/null +++ b/apps/user_ldap/lib/configuration.php @@ -0,0 +1,352 @@ +. + * + */ + +namespace OCA\user_ldap\lib; + +class Configuration { + + protected $configPrefix = null; + protected $configRead = false; + + //settings + protected $config = array( + 'ldapHost' => null, + 'ldapPort' => null, + 'ldapBackupHost' => null, + 'ldapBackupPort' => null, + 'ldapBase' => null, + 'ldapBaseUsers' => null, + 'ldapBaseGroups' => null, + 'ldapAgentName' => null, + 'ldapAgentPassword' => null, + 'ldapTLS' => null, + 'ldapNoCase' => null, + 'turnOffCertCheck' => null, + 'ldapIgnoreNamingRules' => null, + 'ldapUserDisplayName' => null, + 'ldapUserFilter' => null, + 'ldapGroupFilter' => null, + 'ldapGroupDisplayName' => null, + 'ldapGroupMemberAssocAttr' => null, + 'ldapLoginFilter' => null, + 'ldapQuotaAttribute' => null, + 'ldapQuotaDefault' => null, + 'ldapEmailAttribute' => null, + 'ldapCacheTTL' => null, + 'ldapUuidAttribute' => 'auto', + 'ldapOverrideUuidAttribute' => null, + 'ldapOverrideMainServer' => false, + 'ldapConfigurationActive' => false, + 'ldapAttributesForUserSearch' => null, + 'ldapAttributesForGroupSearch' => null, + 'homeFolderNamingRule' => null, + 'hasPagedResultSupport' => false, + 'ldapExpertUsernameAttr' => null, + 'ldapExpertUUIDAttr' => null, + ); + + public function __construct($configPrefix, $autoread = true) { + $this->configPrefix = $configPrefix; + if($autoread) { + $this->readConfiguration(); + } + } + + public function __get($name) { + if(isset($this->config[$name])) { + return $this->config[$name]; + } + } + + public function __set($name, $value) { + $this->setConfiguration(array($name => $value)); + } + + public function getConfiguration() { + return $this->config; + } + + /** + * @brief set LDAP configuration with values delivered by an array, not read + * from configuration. It does not save the configuration! To do so, you + * must call saveConfiguration afterwards. + * @param $config array that holds the config parameters in an associated + * array + * @param &$applied optional; array where the set fields will be given to + * @return null + */ + public function setConfiguration($config, &$applied = null) { + if(!is_array($config)) { + return false; + } + + $cta = $this->getConfigTranslationArray(); + foreach($config as $inputkey => $val) { + if(strpos($inputkey, '_') !== false && isset($cta[$inputkey])) { + $key = $cta[$inputkey]; + } elseif(isset($this->config[$inputkey])) { + $key = $inputkey; + } else { + continue; + } + + $setMethod = 'setValue'; + switch($key) { + case 'homeFolderNamingRule': + if(!empty($val) && strpos($val, 'attr:') === false) { + $val = 'attr:'.$val; + } + case 'ldapBase': + case 'ldapBaseUsers': + case 'ldapBaseGroups': + case 'ldapAttributesForUserSearch': + case 'ldapAttributesForGroupSearch': + $setMethod = 'setMultiLine'; + default: + $this->$setMethod($key, $val); + if(is_array($applied)) { + $applied[] = $inputkey; + } + } + } + + } + + public function readConfiguration() { + if(!$this->configRead && !is_null($this->configPrefix)) { + $cta = array_flip($this->getConfigTranslationArray()); + foreach($this->config as $key => $val) { +// if($this->configPrefix == 's04') var_dump($key); + if(!isset($cta[$key])) { + //some are determined + continue; + } + $dbkey = $cta[$key]; +// if($this->configPrefix == 's04') var_dump($dbkey); + switch($key) { + case 'ldapBase': + case 'ldapBaseUsers': + case 'ldapBaseGroups': + case 'ldapAttributesForUserSearch': + case 'ldapAttributesForGroupSearch': + $readMethod = 'getMultiLine'; + break; + case 'ldapIgnoreNamingRules': + $readMethod = 'getSystemValue'; + $dbkey = $key; + break; + case 'ldapAgentPassword': + $readMethod = 'getPwd'; + break; + case 'ldapUserDisplayName': + case 'ldapGroupDisplayName': + $readMethod = 'getLcValue'; + break; + default: + $readMethod = 'getValue'; + break; + } +// if($this->configPrefix == 's04') var_dump($readMethod); + $this->config[$key] = $this->$readMethod($dbkey); + } + $this->configRead = true; + } + if($this->configPrefix == 's03') { +// var_dump($this->config); + +// die; + } + } + + /** + * @brief saves the current Configuration in the database + */ + public function saveConfiguration() { + $cta = array_flip($this->getConfigTranslationArray()); + foreach($this->config as $key => $value) { + switch ($key) { + case 'ldapAgentPassword': + $value = base64_encode($value); + break; + case 'ldapBase': + case 'ldapBaseUsers': + case 'ldapBaseGroups': + case 'ldapAttributesForUserSearch': + case 'ldapAttributesForGroupSearch': + if(is_array($value)) { + $value = implode("\n", $value); + } + break; + //following options are not stored but detected, skip them + case 'ldapIgnoreNamingRules': + case 'ldapOverrideUuidAttribute': + case 'hasPagedResultSupport': + continue 2; + } + if(is_null($value)) { + $value = ''; + } + $this->saveValue($cta[$key], $value); + } + } + + protected function getMultiLine($varname) { + $value = $this->getValue($varname); + if(empty($value)) { + $value = ''; + } else { + $value = preg_split('/\r\n|\r|\n/', $value); + } + + return $value; + } + + protected function setMultiLine($varname, $value) { + if(empty($value)) { + $value = ''; + } else { + $value = preg_split('/\r\n|\r|\n/', $value); + } + + $this->setValue($varname, $value); + } + + protected function getPwd($varname) { + return base64_decode($this->getValue($varname)); + } + + protected function getLcValue($varname) { + return mb_strtolower($this->getValue($varname), 'UTF-8'); + } + + protected function getSystemValue($varname) { + //FIXME: if another system value is added, softcode the default value + return \OCP\Config::getSystemValue($varname, false); + } + + protected function getValue($varname) { + static $defaults; + if(is_null($defaults)) { + $defaults = $this->getDefaults(); + } +// if($this->configPrefix == 's04') var_dump($this->configPrefix.$varname); +// if(0 == $this->configKeyToDBKey($varname)) { +// var_dump($varname); +// print("
");
+// 			debug_print_backtrace(); die;
+// 		}
+		return \OCP\Config::getAppValue('user_ldap',
+										$this->configPrefix.$varname,
+										$defaults[$varname]);
+	}
+
+	protected function setValue($varname, $value) {
+		$this->config[$varname] = $value;
+	}
+
+	protected function saveValue($varname, $value) {
+		return \OCP\Config::setAppValue('user_ldap',
+										$this->configPrefix.$varname,
+										$value);
+	}
+
+	/**
+	 * @returns an associative array with the default values. Keys are correspond
+	 * to config-value entries in the database table
+	 */
+	public function getDefaults() {
+		return array(
+			'ldap_host'							=> '',
+			'ldap_port'							=> '389',
+			'ldap_backup_host'					=> '',
+			'ldap_backup_port'					=> '',
+			'ldap_override_main_server'			=> '',
+			'ldap_dn'							=> '',
+			'ldap_agent_password'				=> '',
+			'ldap_base'							=> '',
+			'ldap_base_users'					=> '',
+			'ldap_base_groups'					=> '',
+			'ldap_userlist_filter'				=> 'objectClass=person',
+			'ldap_login_filter'					=> 'uid=%uid',
+			'ldap_group_filter'					=> 'objectClass=posixGroup',
+			'ldap_display_name'					=> 'cn',
+			'ldap_group_display_name'			=> 'cn',
+			'ldap_tls'							=> 1,
+			'ldap_nocase'						=> 0,
+			'ldap_quota_def'					=> '',
+			'ldap_quota_attr'					=> '',
+			'ldap_email_attr'					=> '',
+			'ldap_group_member_assoc_attribute'	=> 'uniqueMember',
+			'ldap_cache_ttl'					=> 600,
+			'ldap_uuid_attribute'				=> 'auto',
+			'ldap_override_uuid_attribute'		=> 0,
+			'home_folder_naming_rule'			=> '',
+			'ldap_turn_off_cert_check'			=> 0,
+			'ldap_configuration_active'			=> 1,
+			'ldap_attributes_for_user_search'	=> '',
+			'ldap_attributes_for_group_search'	=> '',
+			'ldap_expert_username_attr'			=> '',
+			'ldap_expert_uuid_attr'				=> '',
+		);
+	}
+
+	/**
+	 * @return returns an array that maps internal variable names to database fields
+	 */
+	public function getConfigTranslationArray() {
+		//TODO: merge them into one representation
+		static $array = array(
+			'ldap_host'							=> 'ldapHost',
+			'ldap_port'							=> 'ldapPort',
+			'ldap_backup_host'					=> 'ldapBackupHost',
+			'ldap_backup_port'					=> 'ldapBackupPort',
+			'ldap_override_main_server' 		=> 'ldapOverrideMainServer',
+			'ldap_dn'							=> 'ldapAgentName',
+			'ldap_agent_password'				=> 'ldapAgentPassword',
+			'ldap_base'							=> 'ldapBase',
+			'ldap_base_users'					=> 'ldapBaseUsers',
+			'ldap_base_groups'					=> 'ldapBaseGroups',
+			'ldap_userlist_filter'				=> 'ldapUserFilter',
+			'ldap_login_filter'					=> 'ldapLoginFilter',
+			'ldap_group_filter'					=> 'ldapGroupFilter',
+			'ldap_display_name'					=> 'ldapUserDisplayName',
+			'ldap_group_display_name'			=> 'ldapGroupDisplayName',
+			'ldap_tls'							=> 'ldapTLS',
+			'ldap_nocase'						=> 'ldapNoCase',
+			'ldap_quota_def'					=> 'ldapQuotaDefault',
+			'ldap_quota_attr'					=> 'ldapQuotaAttribute',
+			'ldap_email_attr'					=> 'ldapEmailAttribute',
+			'ldap_group_member_assoc_attribute'	=> 'ldapGroupMemberAssocAttr',
+			'ldap_cache_ttl'					=> 'ldapCacheTTL',
+			'home_folder_naming_rule' 			=> 'homeFolderNamingRule',
+			'ldap_turn_off_cert_check' 			=> 'turnOffCertCheck',
+			'ldap_configuration_active' 		=> 'ldapConfigurationActive',
+			'ldap_attributes_for_user_search' 	=> 'ldapAttributesForUserSearch',
+			'ldap_attributes_for_group_search'	=> 'ldapAttributesForGroupSearch',
+			'ldap_expert_username_attr' 		=> 'ldapExpertUsernameAttr',
+			'ldap_expert_uuid_attr' 			=> 'ldapExpertUUIDAttr',
+		);
+		return $array;
+	}
+
+}
\ No newline at end of file
diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php
index 468f4b004bd..981d792325f 100644
--- a/apps/user_ldap/lib/connection.php
+++ b/apps/user_ldap/lib/connection.php
@@ -31,48 +31,15 @@ class Connection extends LDAPUtility {
 
 	//whether connection should be kept on __destruct
 	private $dontDestruct = false;
+	private $hasPagedResultSupport = true;
 
 	//cache handler
 	protected $cache;
 
-	//settings
-	protected $config = array(
-		'ldapHost' => null,
-		'ldapPort' => null,
-		'ldapBackupHost' => null,
-		'ldapBackupPort' => null,
-		'ldapBase' => null,
-		'ldapBaseUsers' => null,
-		'ldapBaseGroups' => null,
-		'ldapAgentName' => null,
-		'ldapAgentPassword' => null,
-		'ldapTLS' => null,
-		'ldapNoCase' => null,
-		'turnOffCertCheck' => null,
-		'ldapIgnoreNamingRules' => null,
-		'ldapUserDisplayName' => null,
-		'ldapUserFilter' => null,
-		'ldapGroupFilter' => null,
-		'ldapGroupDisplayName' => null,
-		'ldapGroupMemberAssocAttr' => null,
-		'ldapLoginFilter' => null,
-		'ldapQuotaAttribute' => null,
-		'ldapQuotaDefault' => null,
-		'ldapEmailAttribute' => null,
-		'ldapCacheTTL' => null,
-		'ldapUuidUserAttribute' => 'auto',
+	//settings handler
+	protected $configuration;
 		'ldapUuidGroupAttribute' => 'auto',
-		'ldapOverrideUuidAttribute' => null,
-		'ldapOverrideMainServer' => false,
-		'ldapConfigurationActive' => false,
-		'ldapAttributesForUserSearch' => null,
-		'ldapAttributesForGroupSearch' => null,
-		'homeFolderNamingRule' => null,
-		'hasPagedResultSupport' => false,
-		'ldapExpertUsernameAttr' => null,
-		'ldapExpertUUIDUserAttr' => null,
 		'ldapExpertUUIDGroupAttr' => null,
-	);
 
 	/**
 	 * @brief Constructor
@@ -83,13 +50,14 @@ class Connection extends LDAPUtility {
 		parent::__construct($ldap);
 		$this->configPrefix = $configPrefix;
 		$this->configID = $configID;
+		$this->configuration = new Configuration($configPrefix);
 		$memcache = new \OC\Memcache\Factory();
 		if($memcache->isAvailable()) {
 			$this->cache = $memcache->create();
 		} else {
 			$this->cache = \OC_Cache::getGlobalCache();
 		}
-		$this->config['hasPagedResultSupport'] =
+		$this->hasPagedResultSupport =
 			$this->ldap->hasPagedResultSupport();
 	}
 
@@ -114,23 +82,21 @@ class Connection extends LDAPUtility {
 			$this->readConfiguration();
 		}
 
-		if(isset($this->config[$name])) {
-			return $this->config[$name];
+		if($name === 'hasPagedResultSupport') {
+			return $this->hasPagedResultSupport;
 		}
+
+		return $this->configuration->$name;
 	}
 
 	public function __set($name, $value) {
-		$changed = false;
-		//only few options are writable
-		if($name === 'ldapUuidUserAttribute' || $name === 'ldapUuidGroupAttribute') {
-			\OCP\Util::writeLog('user_ldap', 'Set config '.$name.' to  '.$value, \OCP\Util::DEBUG);
-			$this->config[$name] = $value;
+		$before = $this->configuration->$name;
+		$this->configuration->$name = $value;
+		$after = $this->configuration->$name;
+		if($before !== $after) {
 			if(!empty($this->configID)) {
-				\OCP\Config::setAppValue($this->configID, $this->configPrefix.$name, $value);
+				$this->configuration->saveConfiguration();
 			}
-			$changed = true;
-		}
-		if($changed) {
 			$this->validateConfiguration();
 		}
 	}
@@ -174,7 +140,7 @@ class Connection extends LDAPUtility {
 		if(!$this->configured) {
 			$this->readConfiguration();
 		}
-		if(!$this->config['ldapCacheTTL']) {
+		if(!$this->configuration->ldapCacheTTL) {
 			return null;
 		}
 		if(!$this->isCached($key)) {
@@ -190,7 +156,7 @@ class Connection extends LDAPUtility {
 		if(!$this->configured) {
 			$this->readConfiguration();
 		}
-		if(!$this->config['ldapCacheTTL']) {
+		if(!$this->configuration->ldapCacheTTL) {
 			return false;
 		}
 		$key = $this->getCacheKey($key);
@@ -201,110 +167,30 @@ class Connection extends LDAPUtility {
 		if(!$this->configured) {
 			$this->readConfiguration();
 		}
-		if(!$this->config['ldapCacheTTL']
-			|| !$this->config['ldapConfigurationActive']) {
+		if(!$this->configuration->ldapCacheTTL
+			|| !$this->configuration->ldapConfigurationActive) {
 			return null;
 		}
 		$key   = $this->getCacheKey($key);
 		$value = base64_encode(serialize($value));
-		$this->cache->set($key, $value, $this->config['ldapCacheTTL']);
+		$this->cache->set($key, $value, $this->configuration->ldapCacheTTL);
 	}
 
 	public function clearCache() {
 		$this->cache->clear($this->getCacheKey(null));
 	}
 
-	private function getValue($varname) {
-		static $defaults;
-		if(is_null($defaults)) {
-			$defaults = $this->getDefaults();
-		}
-		return \OCP\Config::getAppValue($this->configID,
-										$this->configPrefix.$varname,
-										$defaults[$varname]);
-	}
-
-	private function setValue($varname, $value) {
-		\OCP\Config::setAppValue($this->configID,
-									$this->configPrefix.$varname,
-									$value);
-	}
-
 	/**
-	 * Special handling for reading Base Configuration
-	 *
-	 * @param $base the internal name of the config key
-	 * @param $value the value stored for the base
-	 */
-	private function readBase($base, $value) {
-		if(empty($value)) {
-			$value = '';
-		} else {
-			$value = preg_split('/\r\n|\r|\n/', $value);
-		}
-
-		$this->config[$base] = $value;
-	}
-
-	/**
-	 * Caches the general LDAP configuration.
+	 * @brief Caches the general LDAP configuration.
+	 * @param $force optional. true, if the re-read should be forced. defaults
+	 * to false.
+	 * @return null
 	 */
 	private function readConfiguration($force = false) {
 		if((!$this->configured || $force) && !is_null($this->configID)) {
-			$v = 'getValue';
-			$this->config['ldapHost']       = $this->$v('ldap_host');
-			$this->config['ldapBackupHost'] = $this->$v('ldap_backup_host');
-			$this->config['ldapPort']       = $this->$v('ldap_port');
-			$this->config['ldapBackupPort'] = $this->$v('ldap_backup_port');
-			$this->config['ldapOverrideMainServer']
-				= $this->$v('ldap_override_main_server');
-			$this->config['ldapAgentName']  = $this->$v('ldap_dn');
-			$this->config['ldapAgentPassword']
-				= base64_decode($this->$v('ldap_agent_password'));
-			$this->readBase('ldapBase',       $this->$v('ldap_base'));
-			$this->readBase('ldapBaseUsers',  $this->$v('ldap_base_users'));
-			$this->readBase('ldapBaseGroups', $this->$v('ldap_base_groups'));
-			$this->config['ldapTLS']        = $this->$v('ldap_tls');
-			$this->config['ldapNoCase']     = $this->$v('ldap_nocase');
-			$this->config['turnOffCertCheck']
-				= $this->$v('ldap_turn_off_cert_check');
-			$this->config['ldapUserDisplayName']
-				= mb_strtolower($this->$v('ldap_display_name'), 'UTF-8');
-			$this->config['ldapUserFilter']
-				= $this->$v('ldap_userlist_filter');
-			$this->config['ldapGroupFilter'] = $this->$v('ldap_group_filter');
-			$this->config['ldapLoginFilter'] = $this->$v('ldap_login_filter');
-			$this->config['ldapGroupDisplayName']
-				= mb_strtolower($this->$v('ldap_group_display_name'), 'UTF-8');
-			$this->config['ldapQuotaAttribute']
-				= $this->$v('ldap_quota_attr');
-			$this->config['ldapQuotaDefault']
-				= $this->$v('ldap_quota_def');
-			$this->config['ldapEmailAttribute']
-				= $this->$v('ldap_email_attr');
-			$this->config['ldapGroupMemberAssocAttr']
-				= $this->$v('ldap_group_member_assoc_attribute');
-			$this->config['ldapIgnoreNamingRules']
-				= \OCP\Config::getSystemValue('ldapIgnoreNamingRules', false);
-			$this->config['ldapCacheTTL']    = $this->$v('ldap_cache_ttl');
-			$this->config['ldapUuidUserAttribute']
-				= $this->$v('ldap_uuid_user_attribute');
+			$this->configuration->readConfiguration();
 			$this->config['ldapUuidGroupAttribute']
 				= $this->$v('ldap_uuid_group_attribute');
-			$this->config['ldapOverrideUuidAttribute']
-				= $this->$v('ldap_override_uuid_attribute');
-			$this->config['homeFolderNamingRule']
-				= $this->$v('home_folder_naming_rule');
-			$this->config['ldapConfigurationActive']
-				= $this->$v('ldap_configuration_active');
-			$this->config['ldapAttributesForUserSearch']
-				= preg_split('/\r\n|\r|\n/', $this->$v('ldap_attributes_for_user_search'));
-			$this->config['ldapAttributesForGroupSearch']
-				= preg_split('/\r\n|\r|\n/', $this->$v('ldap_attributes_for_group_search'));
-			$this->config['ldapExpertUsernameAttr']
-				= $this->$v('ldap_expert_username_attr');
-			$this->config['ldapExpertUUIDUserAttr']
-				= $this->$v('ldap_expert_uuid_user_attr');
 			$this->config['ldapExpertUUIDGroupAttr']
 				= $this->$v('ldap_expert_uuid_group_attr');
 
@@ -313,124 +199,32 @@ class Connection extends LDAPUtility {
 	}
 
 	/**
-	 * @return returns an array that maps internal variable names to database fields
-	 */
-	private function getConfigTranslationArray() {
-		static $array = array(
-			'ldap_host'=>'ldapHost',
-			'ldap_port'=>'ldapPort',
-			'ldap_backup_host'=>'ldapBackupHost',
-			'ldap_backup_port'=>'ldapBackupPort',
-			'ldap_override_main_server' => 'ldapOverrideMainServer',
-			'ldap_dn'=>'ldapAgentName',
-			'ldap_agent_password'=>'ldapAgentPassword',
-			'ldap_base'=>'ldapBase',
-			'ldap_base_users'=>'ldapBaseUsers',
-			'ldap_base_groups'=>'ldapBaseGroups',
-			'ldap_userlist_filter'=>'ldapUserFilter',
-			'ldap_login_filter'=>'ldapLoginFilter',
-			'ldap_group_filter'=>'ldapGroupFilter',
-			'ldap_display_name'=>'ldapUserDisplayName',
-			'ldap_group_display_name'=>'ldapGroupDisplayName',
-			'ldap_tls'=>'ldapTLS',
-			'ldap_nocase'=>'ldapNoCase',
-			'ldap_quota_def'=>'ldapQuotaDefault',
-			'ldap_quota_attr'=>'ldapQuotaAttribute',
-			'ldap_email_attr'=>'ldapEmailAttribute',
-			'ldap_group_member_assoc_attribute'=>'ldapGroupMemberAssocAttr',
-			'ldap_cache_ttl'=>'ldapCacheTTL',
-			'home_folder_naming_rule' => 'homeFolderNamingRule',
-			'ldap_turn_off_cert_check' => 'turnOffCertCheck',
-			'ldap_configuration_active' => 'ldapConfigurationActive',
-			'ldap_attributes_for_user_search' => 'ldapAttributesForUserSearch',
-			'ldap_attributes_for_group_search' => 'ldapAttributesForGroupSearch',
-			'ldap_expert_username_attr' => 'ldapExpertUsernameAttr',
-			'ldap_expert_uuid_user_attr' => 'ldapExpertUUIDUserAttr',
 			'ldap_expert_uuid_group_attr' => 'ldapExpertUUIDGroupAttr',
-		);
-		return $array;
-	}
-
-	/**
 	 * @brief set LDAP configuration with values delivered by an array, not read from configuration
 	 * @param $config array that holds the config parameters in an associated array
 	 * @param &$setParameters optional; array where the set fields will be given to
 	 * @return true if config validates, false otherwise. Check with $setParameters for detailed success on single parameters
 	 */
 	public function setConfiguration($config, &$setParameters = null) {
-		if(!is_array($config)) {
-			return false;
+		if(is_null($setParameters)) {
+			$setParameters = array();
 		}
-
-		$params = $this->getConfigTranslationArray();
-
-		foreach($config as $parameter => $value) {
-			if(($parameter === 'homeFolderNamingRule'
-				|| (isset($params[$parameter])
-					&& $params[$parameter] === 'homeFolderNamingRule'))
-				&& !empty($value)) {
-				$value = 'attr:'.$value;
-			} else if (strpos($parameter, 'ldapBase') !== false
-				|| (isset($params[$parameter])
-					&& strpos($params[$parameter], 'ldapBase') !== false)) {
-				$this->readBase($params[$parameter], $value);
-				if(is_array($setParameters)) {
-					$setParameters[] = $parameter;
-				}
-				continue;
-			}
-		    if(isset($this->config[$parameter])) {
-				$this->config[$parameter] = $value;
-				if(is_array($setParameters)) {
-					$setParameters[] = $parameter;
-				}
-		    } else if(isset($params[$parameter])) {
-				$this->config[$params[$parameter]] = $value;
-				if(is_array($setParameters)) {
-					$setParameters[] = $params[$parameter];
-				}
-		    }
+		$this->configuration->setConfiguration($config, $setParameters);
+		if(count($setParameters) > 0) {
+			$this->configured = $this->validateConfiguration();
 		}
 
-		$this->configured = $this->validateConfiguration();
-
 		return $this->configured;
 	}
 
 	/**
-	 * @brief saves the current Configuration in the database
+	 * @brief saves the current Configuration in the database and empties the
+	 * cache
+	 * @return null
 	 */
 	public function saveConfiguration() {
-		$trans = array_flip($this->getConfigTranslationArray());
-		foreach($this->config as $key => $value) {
-			\OCP\Util::writeLog('user_ldap', 'LDAP: storing key '.$key.
-				' value '.print_r($value, true), \OCP\Util::DEBUG);
-			switch ($key) {
-				case 'ldapAgentPassword':
-					$value = base64_encode($value);
-					break;
-				case 'ldapBase':
-				case 'ldapBaseUsers':
-				case 'ldapBaseGroups':
-				case 'ldapAttributesForUserSearch':
-				case 'ldapAttributesForGroupSearch':
-					if(is_array($value)) {
-						$value = implode("\n", $value);
-					}
-					break;
-				case 'ldapIgnoreNamingRules':
-				case 'ldapOverrideUuidAttribute':
-				case 'ldapUuidUserAttribute':
+		$this->configuration->saveConfiguration();
 				case 'ldapUuidGroupAttribute':
-				case 'hasPagedResultSupport':
-					continue 2;
-			}
-			if(is_null($value)) {
-				$value = '';
-			}
-
-		    $this->setValue($trans[$key], $value);
-		}
 		$this->clearCache();
 	}
 
@@ -440,191 +234,205 @@ class Connection extends LDAPUtility {
 	 */
 	public function getConfiguration() {
 		$this->readConfiguration();
-		$trans = $this->getConfigTranslationArray();
-		$config = array();
-		foreach($trans as $dbKey => $classKey) {
-			if($classKey === 'homeFolderNamingRule') {
-				if(strpos($this->config[$classKey], 'attr:') === 0) {
-					$config[$dbKey] = substr($this->config[$classKey], 5);
-				} else {
-					$config[$dbKey] = '';
-				}
-				continue;
-			} else if((strpos($classKey, 'ldapBase') !== false
-						|| strpos($classKey, 'ldapAttributes') !== false)
-						&& is_array($this->config[$classKey])) {
-				$config[$dbKey] = implode("\n", $this->config[$classKey]);
-				continue;
+		$config = $this->configuration->getConfiguration();
+		$cta = $this->configuration->getConfigTranslationArray();
+		$result = array();
+		foreach($cta as $dbkey => $configkey) {
+			switch($configkey) {
+				case 'homeFolderNamingRule':
+					if(strpos($config[$configkey], 'attr:') === 0) {
+						$result[$dbkey] = substr($config[$configkey], 5);
+					} else {
+						$result[$dbkey] = '';
+					}
+					break;
+				case 'ldapBase':
+				case 'ldapBaseUsers':
+				case 'ldapBaseGroups':
+				case 'ldapAttributesForUserSearch':
+				case 'ldapAttributesForGroupSearch':
+					if(is_array($config[$configkey])) {
+						$result[$dbkey] = implode("\n", $config[$configkey]);
+						break;
+					} //else follows default
+				default:
+					$result[$dbkey] = $config[$configkey];
 			}
-			$config[$dbKey] = $this->config[$classKey];
 		}
-
-		return $config;
+		return $result;
 	}
 
-	/**
-	 * @brief Validates the user specified configuration
-	 * @returns true if configuration seems OK, false otherwise
-	 */
-	private function validateConfiguration() {
-		// first step: "soft" checks: settings that are not really
-		// necessary, but advisable. If left empty, give an info message
-		if(empty($this->config['ldapBaseUsers'])) {
-			\OCP\Util::writeLog('user_ldap', 'Base tree for Users is empty, using Base DN', \OCP\Util::INFO);
-			$this->config['ldapBaseUsers'] = $this->config['ldapBase'];
-		}
-		if(empty($this->config['ldapBaseGroups'])) {
-			\OCP\Util::writeLog('user_ldap', 'Base tree for Groups is empty, using Base DN', \OCP\Util::INFO);
-			$this->config['ldapBaseGroups'] = $this->config['ldapBase'];
+	//TODO remove if not necessary
+// 	public function getDefaults() {
+// 		return $this->configuration->getDefaults();
+// 	}
+
+	private function doSoftValidation() {
+		//if User or Group Base are not set, take over Base DN setting
+		foreach(array('ldapBaseUsers', 'ldapBaseGroups') as $keyBase) {
+		    $val = $this->configuration->$keyBase;
+			if(empty($val)) {
+				$obj = strpos('Users', $keyBase) !== false ? 'Users' : 'Groups';
+				\OCP\Util::writeLog('user_ldap',
+									'Base tree for '.$obj.
+									' is empty, using Base DN',
+									\OCP\Util::INFO);
+				$this->configuration->$keyBase = $this->configuration->ldapBase;
+			}
 		}
-		if(empty($this->config['ldapGroupFilter']) && empty($this->config['ldapGroupMemberAssocAttr'])) {
+
+		$groupFilter = $this->configuration->ldapGroupFilter;
+		if(empty($groupFilter)) {
 			\OCP\Util::writeLog('user_ldap',
-				'No group filter is specified, LDAP group feature will not be used.',
-				\OCP\Util::INFO);
-		}
-		$uuidAttributes = array(
-			'auto', 'entryuuid', 'nsuniqueid', 'objectguid', 'guid');
-		$uuidSettings = array(
-						'ldapUuidUserAttribute' => 'ldapExpertUUIDUserAttr',
-						'ldapUuidGroupAttribute' => 'ldapExpertUUIDGroupAttr');
-		$cta = array_flip($this->getConfigTranslationArray());
-		foreach($uuidSettings as $defaultKey => $overrideKey) {
-			if( !in_array($this->config[$defaultKey], $uuidAttributes)
-				&& is_null($this->config[$overrideKey])
-				&& !is_null($this->configID)) {
-				\OCP\Config::setAppValue($this->configID,
-										$this->configPrefix.$cta[$defaultKey],
+								'No group filter is specified, LDAP group '.
+								'feature will not be used.',
+								\OCP\Util::INFO);
+		}
+
+		$uuidOverride = $this->configuration->ldapExpertUUIDAttr;
+		if(!empty($uuidOverride)) {
+			$this->configuration->ldapUuidAttribute = $uuidOverride;
+		} else {
+			$uuidAttributes = array('auto', 'entryuuid', 'nsuniqueid',
+									'objectguid', 'guid');
+			if(!in_array($this->configuration->ldapUuidAttribute,
+						 $uuidAttributes)
+				&& (!is_null($this->configID))) {
+				$this->configuration->ldapUuidAttribute = 'auto';
+				$this->configuration->saveConfiguration();
 										'auto');
 				\OCP\Util::writeLog('user_ldap',
-					'Illegal value for'.$defaultKey.', reset to autodetect.',
-					\OCP\Util::DEBUG);
+									'Illegal value for the UUID Attribute, '.
+									'reset to autodetect.',
+									\OCP\Util::INFO);
 			}
+
 		}
 
-		if(empty($this->config['ldapBackupPort'])) {
-			//force default
-			$this->config['ldapBackupPort'] = $this->config['ldapPort'];
+
+		$backupPort = $this->configuration->ldapBackupPort;
+		if(empty($backupPort)) {
+			$this->configuration->backupPort = $this->configuration->ldapPort;
 		}
-		foreach(array('ldapAttributesForUserSearch', 'ldapAttributesForGroupSearch') as $key) {
-			if(is_array($this->config[$key])
-				&& count($this->config[$key]) === 1
-				&& empty($this->config[$key][0])) {
-				$this->config[$key] = array();
+
+		//make sure empty search attributes are saved as simple, empty array
+		$sakeys = array('ldapAttributesForUserSearch',
+						'ldapAttributesForGroupSearch');
+		foreach($sakeys as $key) {
+			$val = $this->configuration->$key;
+			if(is_array($val) && count($val) === 1 && empty($val[0])) {
+				$this->configuration->$key = array();
 			}
 		}
-		if((strpos($this->config['ldapHost'], 'ldaps') === 0)
-			&& $this->config['ldapTLS']) {
-			$this->config['ldapTLS'] = false;
+
+		if((stripos($this->configuration->ldapHost, 'ldaps://') === 0)
+			&& $this->configuration->ldapTLS) {
+			$this->configuration->ldapTLS = false;
 			\OCP\Util::writeLog('user_ldap',
-				'LDAPS (already using secure connection) and TLS do not work together. Switched off TLS.',
-				\OCP\Util::INFO);
+								'LDAPS (already using secure connection) and '.
+								'TLS do not work together. Switched off TLS.',
+								\OCP\Util::INFO);
 		}
+	}
 
-		//second step: critical checks. If left empty or filled wrong, set as unconfigured and give a warning.
+	private function doCriticalValidation() {
 		$configurationOK = true;
-		if(empty($this->config['ldapHost'])) {
-			\OCP\Util::writeLog('user_ldap', 'No LDAP host given, won`t connect.', \OCP\Util::WARN);
-			$configurationOK = false;
-		}
-		if(empty($this->config['ldapPort'])) {
-			\OCP\Util::writeLog('user_ldap', 'No LDAP Port given, won`t connect.', \OCP\Util::WARN);
-			$configurationOK = false;
-		}
-		if((empty($this->config['ldapAgentName']) && !empty($this->config['ldapAgentPassword']))
-			|| (!empty($this->config['ldapAgentName']) && empty($this->config['ldapAgentPassword']))) {
-			\OCP\Util::writeLog('user_ldap',
-				'Either no password given for the user agent or a password is given, but no LDAP agent; won`t connect.',
-				\OCP\Util::WARN);
-			$configurationOK = false;
-		}
-		//TODO: check if ldapAgentName is in DN form
-		if(empty($this->config['ldapBase'])
-			&& (empty($this->config['ldapBaseUsers'])
-			&& empty($this->config['ldapBaseGroups']))) {
-			\OCP\Util::writeLog('user_ldap', 'No Base DN given, won`t connect.', \OCP\Util::WARN);
-			$configurationOK = false;
+		$errorStr = 'Configuration Error (prefix '.
+					strval($this->configPrefix).'): ';
+
+		//options that shall not be empty
+		$options = array('ldapHost', 'ldapPort', 'ldapUserDisplayName',
+						 'ldapGroupDisplayName', 'ldapLoginFilter');
+		foreach($options as $key) {
+			$val = $this->configuration->$key;
+			if(empty($val)) {
+				switch($key) {
+					case 'ldapHost':
+						$subj = 'LDAP Host';
+						break;
+					case 'ldapPort':
+						$subj = 'LDAP Port';
+						break;
+					case 'ldapUserDisplayName':
+						$subj = 'LDAP User Display Name';
+						break;
+					case 'ldapGroupDisplayName':
+						$subj = 'LDAP Group Display Name';
+						break;
+					case 'ldapLoginFilter':
+						$subj = 'LDAP Login Filter';
+						break;
+					default:
+						$subj = $key;
+						break;
+				}
+				$configurationOK = false;
+				\OCP\Util::writeLog('user_ldap',
+									$errorStr.'No '.$subj.' given!',
+									\OCP\Util::WARN);
+			}
 		}
-		if(empty($this->config['ldapUserDisplayName'])) {
+
+		//combinations
+		$agent = $this->configuration->ldapAgentName;
+		$pwd = $this->configuration->ldapAgentPassword;
+		if((empty($agent) && !empty($pwd)) || (!empty($agent) && empty($pwd))) {
 			\OCP\Util::writeLog('user_ldap',
-				'No user display name attribute specified, won`t connect.',
+								$errorStr.'either no password is given for the'.
+								'user agent or a password is given, but not an'.
+								'LDAP agent.',
 				\OCP\Util::WARN);
 			$configurationOK = false;
 		}
-		if(empty($this->config['ldapGroupDisplayName'])) {
+
+		$base = $this->configuration->ldapBase;
+		$baseUsers = $this->configuration->ldapBaseUsers;
+		$baseGroups = $this->configuration->ldapBaseGroups;
+
+		if(empty($base) && empty($baseUsers) && empty($baseGroups)) {
 			\OCP\Util::writeLog('user_ldap',
-				'No group display name attribute specified, won`t connect.',
-				\OCP\Util::WARN);
+								$errorStr.'Not a single Base DN given.',
+								\OCP\Util::WARN);
 			$configurationOK = false;
 		}
-		if(empty($this->config['ldapLoginFilter'])) {
-			\OCP\Util::writeLog('user_ldap', 'No login filter specified, won`t connect.', \OCP\Util::WARN);
-			$configurationOK = false;
-		}
-		if(mb_strpos($this->config['ldapLoginFilter'], '%uid', 0, 'UTF-8') === false) {
+
+		if(mb_strpos($this->configuration->ldapLoginFilter, '%uid', 0, 'UTF-8')
+		   === false) {
 			\OCP\Util::writeLog('user_ldap',
-				'Login filter does not contain %uid place holder, won`t connect.',
-				\OCP\Util::WARN);
-			\OCP\Util::writeLog('user_ldap', 'Login filter was ' . $this->config['ldapLoginFilter'], \OCP\Util::DEBUG);
+								$errorStr.'login filter does not contain %uid '.
+								'place holder.',
+								\OCP\Util::WARN);
 			$configurationOK = false;
 		}
 
-		if(!empty($this->config['ldapExpertUUIDUserAttr'])) {
-			$this->config['ldapUuidUserAttribute'] = $this->config['ldapExpertUUIDUserAttr'];
 		}
 		if(!empty($this->config['ldapExpertUUIDGroupAttr'])) {
 			$this->config['ldapUuidGroupAttribute'] = $this->config['ldapExpertUUIDGroupAttr'];
-		}
-
 		return $configurationOK;
 	}
 
 	/**
-	 * @returns an associative array with the default values. Keys are correspond
-	 * to config-value entries in the database table
+	 * @brief Validates the user specified configuration
+	 * @returns true if configuration seems OK, false otherwise
 	 */
-	static public function getDefaults() {
-		return array(
-			'ldap_host'                         => '',
-			'ldap_port'                         => '389',
-			'ldap_backup_host'                  => '',
-			'ldap_backup_port'                  => '',
-			'ldap_override_main_server'         => '',
-			'ldap_dn'                           => '',
-			'ldap_agent_password'               => '',
-			'ldap_base'                         => '',
-			'ldap_base_users'                   => '',
-			'ldap_base_groups'                  => '',
-			'ldap_userlist_filter'              => 'objectClass=person',
-			'ldap_login_filter'                 => 'uid=%uid',
-			'ldap_group_filter'                 => 'objectClass=posixGroup',
-			'ldap_display_name'                 => 'cn',
-			'ldap_group_display_name'           => 'cn',
-			'ldap_tls'                          => 1,
-			'ldap_nocase'                       => 0,
-			'ldap_quota_def'                    => '',
-			'ldap_quota_attr'                   => '',
-			'ldap_email_attr'                   => '',
-			'ldap_group_member_assoc_attribute' => 'uniqueMember',
-			'ldap_cache_ttl'                    => 600,
-			'ldap_uuid_user_attribute'          => 'auto',
+	private function validateConfiguration() {
+		// first step: "soft" checks: settings that are not really
+		// necessary, but advisable. If left empty, give an info message
+		$this->doSoftValidation();
+
+		//second step: critical checks. If left empty or filled wrong, set as
+		//unconfigured and give a warning.
+		return $this->doCriticalValidation();
 			'ldap_uuid_group_attribute'         => 'auto',
-			'ldap_override_uuid_attribute'		=> 0,
-			'home_folder_naming_rule'           => '',
-			'ldap_turn_off_cert_check'			=> 0,
-			'ldap_configuration_active'			=> 1,
-			'ldap_attributes_for_user_search'	=> '',
-			'ldap_attributes_for_group_search'	=> '',
-			'ldap_expert_username_attr'         => '',
-			'ldap_expert_uuid_user_attr'        => '',
 			'ldap_expert_uuid_group_attr'       => '',
-		);
 	}
 
+
 	/**
 	 * Connects and Binds to LDAP
 	 */
 	private function establishConnection() {
-		if(!$this->config['ldapConfigurationActive']) {
+		if(!$this->configuration->ldapConfigurationActive) {
 			return null;
 		}
 		static $phpLDAPinstalled = true;
@@ -632,29 +440,36 @@ class Connection extends LDAPUtility {
 			return false;
 		}
 		if(!$this->configured) {
-			\OCP\Util::writeLog('user_ldap', 'Configuration is invalid, cannot connect', \OCP\Util::WARN);
+			\OCP\Util::writeLog('user_ldap',
+								'Configuration is invalid, cannot connect',
+								\OCP\Util::WARN);
 			return false;
 		}
 		if(!$this->ldapConnectionRes) {
 			if(!$this->ldap->areLDAPFunctionsAvailable()) {
 				$phpLDAPinstalled = false;
 				\OCP\Util::writeLog('user_ldap',
-					'function ldap_connect is not available. Make sure that the PHP ldap module is installed.',
-					\OCP\Util::ERROR);
+									'function ldap_connect is not available. Make '.
+									'sure that the PHP ldap module is installed.',
+									\OCP\Util::ERROR);
 
 				return false;
 			}
-			if($this->config['turnOffCertCheck']) {
+			if($this->configuration->turnOffCertCheck) {
 				if(putenv('LDAPTLS_REQCERT=never')) {
 					\OCP\Util::writeLog('user_ldap',
 						'Turned off SSL certificate validation successfully.',
 						\OCP\Util::WARN);
 				} else {
-					\OCP\Util::writeLog('user_ldap', 'Could not turn off SSL certificate validation.', \OCP\Util::WARN);
+					\OCP\Util::writeLog('user_ldap',
+										'Could not turn off SSL certificate validation.',
+										\OCP\Util::WARN);
 				}
 			}
-			if(!$this->config['ldapOverrideMainServer'] && !$this->getFromCache('overrideMainServer')) {
-				$this->doConnect($this->config['ldapHost'], $this->config['ldapPort']);
+			if(!$this->configuration->ldapOverrideMainServer
+			   && !$this->getFromCache('overrideMainServer')) {
+				$this->doConnect($this->configuration->ldapHost,
+								 $this->configuration->ldapPort);
 				$bindStatus = $this->bind();
 				$error = $this->ldap->isResource($this->ldapConnectionRes) ?
 							$this->ldap->errno($this->ldapConnectionRes) : -1;
@@ -665,9 +480,10 @@ class Connection extends LDAPUtility {
 
 			//if LDAP server is not reachable, try the Backup (Replica!) Server
 			if((!$bindStatus && ($error !== 0))
-				|| $this->config['ldapOverrideMainServer']
+				|| $this->configuration->ldapOverrideMainServer
 				|| $this->getFromCache('overrideMainServer')) {
-					$this->doConnect($this->config['ldapBackupHost'], $this->config['ldapBackupPort']);
+					$this->doConnect($this->configuration->ldapBackupHost,
+									 $this->configuration->ldapBackupPort);
 					$bindStatus = $this->bind();
 					if(!$bindStatus && $error === -1) {
 						//when bind to backup server succeeded and failed to main server,
@@ -690,7 +506,7 @@ class Connection extends LDAPUtility {
 		$this->ldapConnectionRes = $this->ldap->connect($host, $port);
 		if($this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) {
 			if($this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) {
-				if($this->config['ldapTLS']) {
+				if($this->configuration->ldapTLS) {
 					$this->ldap->startTls($this->ldapConnectionRes);
 				}
 			}
@@ -702,7 +518,7 @@ class Connection extends LDAPUtility {
 	 */
 	public function bind() {
 		static $getConnectionResourceAttempt = false;
-		if(!$this->config['ldapConfigurationActive']) {
+		if(!$this->configuration->ldapConfigurationActive) {
 			return false;
 		}
 		if($getConnectionResourceAttempt) {
@@ -716,8 +532,8 @@ class Connection extends LDAPUtility {
 			return false;
 		}
 		$ldapLogin = @$this->ldap->bind($cr,
-										$this->config['ldapAgentName'],
-										$this->config['ldapAgentPassword']);
+										$this->configuration->ldapAgentName,
+										$this->configuration->ldapAgentPassword);
 		if(!$ldapLogin) {
 			\OCP\Util::writeLog('user_ldap',
 				'Bind failed: ' . $this->ldap->errno($cr) . ': ' . $this->ldap->error($cr),
diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php
index f20bc191183..45d874eff00 100644
--- a/apps/user_ldap/settings.php
+++ b/apps/user_ldap/settings.php
@@ -37,7 +37,8 @@ $tmpl->assign('serverConfigurationPrefixes', $prefixes);
 $tmpl->assign('serverConfigurationHosts', $hosts);
 
 // assign default values
-$defaults = \OCA\user_ldap\lib\Connection::getDefaults();
+$config = new \OCA\user_ldap\lib\Configuration('', false);
+$defaults = $config->getDefaults();
 foreach($defaults as $key => $default) {
     $tmpl->assign($key.'_default', $default);
 }

From 53db1fe5ac24f569918fa7cfb3dcd67054099836 Mon Sep 17 00:00:00 2001
From: Arthur Schiwon 
Date: Fri, 27 Sep 2013 18:30:59 +0200
Subject: [PATCH 03/33] First stage of new Wizard, neither feature complete nor
 ready

---
 apps/user_ldap/ajax/wizard.php                |  83 ++++++
 apps/user_ldap/css/settings.css               |  79 +++++-
 apps/user_ldap/js/settings.js                 |  88 ++++++
 apps/user_ldap/lib/wizard.php                 | 267 ++++++++++++++++++
 apps/user_ldap/lib/wizardresult.php           |  50 ++++
 apps/user_ldap/settings.php                   |  20 ++
 .../templates/part.settingcontrols.php        |  12 +
 .../templates/part.wizard-server.php          |  76 +++++
 .../templates/part.wizardcontrols.php         |  14 +
 apps/user_ldap/templates/settings.php         |  14 +-
 10 files changed, 688 insertions(+), 15 deletions(-)
 create mode 100644 apps/user_ldap/ajax/wizard.php
 create mode 100644 apps/user_ldap/lib/wizard.php
 create mode 100644 apps/user_ldap/lib/wizardresult.php
 create mode 100644 apps/user_ldap/templates/part.settingcontrols.php
 create mode 100644 apps/user_ldap/templates/part.wizard-server.php
 create mode 100644 apps/user_ldap/templates/part.wizardcontrols.php

diff --git a/apps/user_ldap/ajax/wizard.php b/apps/user_ldap/ajax/wizard.php
new file mode 100644
index 00000000000..53c66c34f8e
--- /dev/null
+++ b/apps/user_ldap/ajax/wizard.php
@@ -0,0 +1,83 @@
+.
+ *
+ */
+
+// Check user and app status
+OCP\JSON::checkAdminUser();
+OCP\JSON::checkAppEnabled('user_ldap');
+OCP\JSON::callCheck();
+
+$l=OC_L10N::get('user_ldap');
+
+if(!isset($_POST['action'])) {
+	\OCP\JSON::error(array('message' => $l->t('No action specified')));
+}
+$action = $_POST['action'];
+
+
+if(!isset($_POST['ldap_serverconfig_chooser'])) {
+	\OCP\JSON::error(array('message' => $l->t('No configuration specified')));
+}
+$prefix = $_POST['ldap_serverconfig_chooser'];
+
+$ldapWrapper = new OCA\user_ldap\lib\LDAP();
+$configuration = new \OCA\user_ldap\lib\Configuration($prefix);
+$wizard = new \OCA\user_ldap\lib\Wizard($configuration, $ldapWrapper);
+
+switch($action) {
+	case 'guessPortAndTLS':
+		try {
+			$result = $wizard->$action();
+			if($result !== false) {
+				OCP\JSON::success($result->getResultArray());
+				exit;
+			}
+		} catch (\Exception $e) {
+			\OCP\JSON::error(array('message' => $e->getMessage()));
+			exit;
+		}
+		\OCP\JSON::error();
+		exit;
+		break;
+
+	case 'save':
+		$key = isset($_POST['cfgkey']) ? $_POST['cfgkey'] : false;
+		$val = isset($_POST['cfgval']) ? $_POST['cfgval'] : null;
+		if($key === false || is_null($val)) {
+			\OCP\JSON::error(array('message' => $l->t('No data specified')));
+			exit;
+		}
+		$cfg = array($key => $val);
+		$setParameters = array();
+		$configuration->setConfiguration($cfg, $setParameters);
+		if(!in_array($key, $setParameters)) {
+			\OCP\JSON::error(array('message' => $l->t($key.' Could not set configuration '.$setParameters[0])));
+			exit;
+		}
+		$configuration->saveConfiguration();
+		OCP\JSON::success();
+		break;
+	default:
+		//TODO: return 4xx error
+		break;
+}
+
diff --git a/apps/user_ldap/css/settings.css b/apps/user_ldap/css/settings.css
index 6086c7b74e6..aa6c4687cf9 100644
--- a/apps/user_ldap/css/settings.css
+++ b/apps/user_ldap/css/settings.css
@@ -1,20 +1,58 @@
-#ldap fieldset p label {
-	width: 20%;
-	max-width: 200px;
-	display: inline-block;
-	vertical-align: top;
+.table {
+	display: table;
+}
+
+.tablecell {
+	display: table-cell !important;
+}
+
+.tablerow {
+	display: table-row;
+}
+
+.tablerow input, .tablerow textarea {
+	width: 100% !important;
+}
+
+.tablerow textarea {
+	height: 15px;
+}
+
+.hidden {
+	visibility: hidden;
+}
+
+.ldapSettingsTabs {
+	float: right !important;
+}
+
+.ldapWizardControls {
+	width: 60%;
 	text-align: right;
-	padding-top: 9px;
-	padding-right: 5px;
 }
 
-#ldap fieldset input, #ldap fieldset textarea {
+.ldapWizardInfo {
+	width: 100% !important;
+	height: 50px;
+	background-color: lightyellow;
+	border-radius: 0.5em;
+	padding: 0.6em 0.5em 0.4em !important;
+	margin-bottom: 0.3em;
+}
+
+#ldapWizard1 .hostPortCombinator {
 	width: 60%;
-	display: inline-block;
+	display: table;
 }
 
-#ldap fieldset p input[type=checkbox] {
-	vertical-align: bottom;
+#ldapWizard1 .hostPortCombinator div span {
+	width: 7%;
+	display: table-cell;
+	text-align: right;
+}
+
+#ldapWizard1 .host {
+	width: 96.5% !important;
 }
 
 .ldapIndent {
@@ -25,3 +63,22 @@
 	margin-left: 1.4em;
 	color: #FF3B3B;
 }
+
+#ldap fieldset p label {
+	width: 20%;
+	max-width: 200px;
+	display: inline-block;
+	vertical-align: top;
+	text-align: right;
+	padding-top: 9px;
+	padding-right: 5px;
+}
+
+#ldap fieldset input, #ldap fieldset textarea {
+ 	width: 60%;
+	display: inline-block;
+}
+
+#ldap fieldset p input[type=checkbox] {
+	vertical-align: bottom;
+}
\ No newline at end of file
diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js
index 20d6f76dcd6..97470b4da41 100644
--- a/apps/user_ldap/js/settings.js
+++ b/apps/user_ldap/js/settings.js
@@ -30,6 +30,7 @@ var LdapConfiguration = {
 						// assign the value
 						$('#'+configkey).val(configvalue);
 					});
+					LdapWizard.init();
 				}
 			}
 		);
@@ -91,6 +92,7 @@ var LdapConfiguration = {
 					$('#ldap_serverconfig_chooser option:selected').removeAttr('selected');
 					var html = '';
 					$('#ldap_serverconfig_chooser option:last').before(html);
+					LdapWizard.init();
 				} else {
 					OC.dialogs.alert(
 						result.message,
@@ -122,12 +124,98 @@ var LdapConfiguration = {
 	}
 };
 
+var LdapWizard = {
+	checkPortInfoShown: false,
+	changeIndicators: {},
+
+	ajax: function(param, fnOnSuccess, fnOnError) {
+		$.post(
+			OC.filePath('user_ldap','ajax','wizard.php'),
+			param,
+			function(result) {
+				if(result.status == 'success') {
+					fnOnSuccess(result);
+				} else {
+					fnOnError(result);
+				}
+			}
+		);
+	},
+
+	applyChanges: function (result) {
+		for (id in result.changes) {
+			$('#'+id).val(result.changes[id]);
+		}
+	},
+
+	checkPort: function() {
+		host = $('#ldap_host').val();
+		user = $('#ldap_dn').val();
+		pass = $('#ldap_agent_password').val();
+
+		if(host && user && pass) {
+			param = 'action=guessPortAndTLS'+
+					'&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val();
+
+			LdapWizard.ajax(param,
+				function(result) {
+					LdapWizard.applyChanges(result);
+					if($('#ldap_port').val()) {
+						$('#ldap_port').removeClass('hidden');
+						if(LdapWizard.checkPortInfoShown) {
+							$('#ldapWizard1 .ldapWizardInfo').addClass('hidden');
+							LdapWizard.checkPortInfoShown = false;
+						}
+					}
+				},
+				function (result) {
+					$('#ldap_port').removeClass('hidden');
+					$('#ldapWizard1 .ldapWizardInfo').text(t('user_ldap',
+						'Please specify a port'));
+					$('#ldapWizard1 .ldapWizardInfo').removeClass('hidden');
+					LdapWizard.checkPortInfoShown = true;
+				}
+			);
+		}
+	},
+
+	init: function() {
+		if($('#ldap_port').val()) {
+			$('#ldap_port').removeClass('hidden');
+		}
+	},
+
+	save: function(inputObj) {
+		param = 'cfgkey='+inputObj.id+
+				'&cfgval='+$(inputObj).val()+
+				'&action=save'+
+				'&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val();
+
+		$.post(
+			OC.filePath('user_ldap','ajax','wizard.php'),
+			param,
+			function(result) {
+				if(result.status == 'success') {
+					if(inputObj.id == 'ldap_host'
+					   || inputObj.id == 'ldap_dn'
+					   || inputObj.id == 'ldap_agent_password') {
+						LdapWizard.checkPort();
+					}
+				} else {
+// 					alert('Oooooooooooh :(');
+				}
+			}
+		);
+	}
+};
+
 $(document).ready(function() {
 	$('#ldapAdvancedAccordion').accordion({ heightStyle: 'content', animate: 'easeInOutCirc'});
 	$('#ldapSettings').tabs();
 	$('#ldap_submit').button();
 	$('#ldap_action_test_connection').button();
 	$('#ldap_action_delete_configuration').button();
+	$('.lwautosave').change(function() { LdapWizard.save(this); });
 	LdapConfiguration.refreshConfig();
 	$('#ldap_action_test_connection').click(function(event){
 		event.preventDefault();
diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php
new file mode 100644
index 00000000000..ff81df8bf03
--- /dev/null
+++ b/apps/user_ldap/lib/wizard.php
@@ -0,0 +1,267 @@
+.
+ *
+ */
+
+namespace OCA\user_ldap\lib;
+
+class Wizard extends LDAPUtility {
+	static protected $l;
+	protected $configuration;
+	protected $result;
+
+	/**
+	 * @brief Constructor
+	 * @param $configuration an instance of Configuration
+	 * @param $ldap	an instance of ILDAPWrapper
+	 */
+	public function __construct(Configuration $configuration, ILDAPWrapper $ldap) {
+		parent::__construct($ldap);
+		$this->configuration = $configuration;
+		if(is_null(Wizard::$l)) {
+			Wizard::$l = \OC_L10N::get('user_ldap');
+		}
+		$this->result = new WizardResult;
+	}
+
+	public function  __destruct() {
+		if($this->result->hasChanges()) {
+			$this->configuration->saveConfiguration();
+		}
+	}
+
+	/**
+	 * Tries to determine the port, requires given Host, User DN and Password
+	 * @returns mixed WizardResult on success, false otherwise
+	 */
+	public function guessPortAndTLS() {
+		if(!$this->checkRequirements(array('ldapHost',
+										   'ldapAgentName',
+										   'ldapAgentPassword'))) {
+			return false;
+		}
+		$this->checkHost();
+		$portSettings = $this->getPortSettingsToTry();
+		file_put_contents('/tmp/ps', print_r($portSettings, true).PHP_EOL, FILE_APPEND);
+
+		if(!is_array($portSettings)) {
+			throw new \Exception(print_r($portSettings, true));
+		}
+
+		//proceed from the best configuration and return on first success
+		foreach($portSettings as $setting) {
+			$p = $setting['port'];
+			$t = $setting['tls'];
+			\OCP\Util::writeLog('user_ldap', 'Wiz: trying port '. $p . ', TLS '. $t, \OCP\Util::DEBUG);
+			//connectAndBind may throw Exception, it needs to be catched by the
+			//callee of this method
+			if($this->connectAndBind($p, $t) === true) {
+				$config = array('ldapPort' => $p,
+								'ldapTLS'  => intval($t)
+							);
+				$this->configuration->setConfiguration($config);
+				\OCP\Util::writeLog('user_ldap', 'Wiz: detected Port '. $p, \OCP\Util::DEBUG);
+				$this->result->addChange('ldap_port', $p);
+				$this->result->addChange('ldap_tls', intval($t));
+// 				$this->result->addSpecific('port', $p);
+				return $this->result;
+			}
+		}
+
+		//custom port, undetected (we do not brute force)
+		return false;
+	}
+
+	public function guessBaseDN() {
+		if(!$this->checkRequirements(array('ldapHost',
+										   'ldapAgentName',
+										   'ldapAgentPassword',
+										   'ldapPort',
+										   ))) {
+			return false;
+		}
+		$cr = $this->getConnection();
+		if(!$cr) {
+			return false;
+		}
+	}
+
+	/**
+	 * @brief Checks, whether a port was entered in the Host configuration
+	 * field. In this case the port will be stripped off, but also stored as
+	 * setting.
+	 */
+	private function checkHost() {
+		$host = $this->configuration->ldapHost;
+		$hostInfo = parse_url($host);
+
+		//removes Port from Host
+		if(is_array($hostInfo) && isset($hostInfo['port'])) {
+			$port = $hostInfo['port'];
+			$host = str_replace(':'.$port, '', $host);
+			$config = array('ldapHost' => $host,
+							'ldapPort' => $port,
+							);
+			$this->result->addChange('ldap_host', $host);
+			$this->result->addChange('ldap_port', $port);
+			$this->configuration->setConfiguration($config);
+		}
+	}
+
+	/**
+	 * Connects and Binds to an LDAP Server
+	 * @param $port the port to connect with
+	 * @param $tls whether startTLS is to be used
+	 * @return
+	 */
+	private function connectAndBind($port = 389, $tls = false, $ncc = false) {
+		if($ncc) {
+			//No certificate check
+			//FIXME: undo afterwards
+			putenv('LDAPTLS_REQCERT=never');
+		}
+
+		//connect, does not really trigger any server communication
+		\OCP\Util::writeLog('user_ldap', 'Wiz: Checking Host Info ', \OCP\Util::DEBUG);
+		$host = $this->configuration->ldapHost;
+		$hostInfo = parse_url($host);
+		if(!$hostInfo) {
+			throw new \Exception($this->l->t('Invalid Host'));
+		}
+		if(isset($hostInfo['scheme'])) {
+			if(isset($hostInfo['port'])) {
+				//problem
+			} else {
+				$host .= ':' . $port;
+			}
+		}
+		\OCP\Util::writeLog('user_ldap', 'Wiz: Attempting to connect ', \OCP\Util::DEBUG);
+		$cr = $this->ldap->connect($host, $port);
+		if(!is_resource($cr)) {
+			throw new \Exception($this->l->t('Invalid Host'));
+		}
+
+		\OCP\Util::writeLog('user_ldap', 'Wiz: Setting LDAP Options ', \OCP\Util::DEBUG);
+		//set LDAP options
+		if($this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3)) {
+			if($tls) {
+				$this->ldap->startTls($cr);
+			}
+		}
+
+		\OCP\Util::writeLog('user_ldap', 'Wiz: Attemping to Bind ', \OCP\Util::DEBUG);
+		//interesting part: do the bind!
+		$login = $this->ldap->bind($cr,
+									$this->configuration->ldapAgentName,
+									$this->configuration->ldapAgentPassword);
+
+		if($login === true) {
+			$this->ldap->unbind($cr);
+			if($ncc) {
+				throw new \Exception('Certificate cannot be validated.');
+			}
+			\OCP\Util::writeLog('user_ldap', 'Wiz: Bind succesfull with Port '. $port, \OCP\Util::DEBUG);
+			return true;
+		}
+
+		$errno = $this->ldap->errno($cr);
+		$error = ldap_error($cr);
+		$this->ldap->unbind($cr);
+		if($errno === -1 || ($errno === 2 && $ncc)) {
+			//host, port or TLS wrong
+			return false;
+		} else if ($errno === 2) {
+			return $this->connectAndBind($port, $tls, true);
+		}
+		throw new \Exception($error);
+	}
+
+	private function checkRequirements($reqs) {
+		foreach($reqs as $option) {
+			$value = $this->configuration->$option;
+			if(empty($value)) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	private function getConnection() {
+		$cr = $this->ldap->connect(
+			$this->configuration->ldapHost.':'.$this->configuration->ldapPort,
+			$this->configuration->ldapPort);
+
+		if($this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3)) {
+			if($this->configuration->ldapTLS === 1) {
+				$this->ldap->startTls($cr);
+			}
+		}
+
+		$lo = @$this->ldap->bind($cr,
+								 $this->configuration->ldapAgentName,
+								 $this->configuration->ldapAgentPassword);
+		if($lo === true) {
+			return $cr;
+		}
+
+		return false;
+	}
+
+	private function getDefaultLdapPortSettings() {
+		static $settings = array(
+								array('port' => 7636, 'tls' => false),
+								array('port' =>  636, 'tls' => false),
+								array('port' => 7389, 'tls' => true),
+								array('port' =>  389, 'tls' => true),
+								array('port' => 7389, 'tls' => false),
+								array('port' =>  389, 'tls' => false),
+						  );
+		return $settings;
+	}
+
+	private function getPortSettingsToTry() {
+		//389 ← LDAP / Unencrypted or StartTLS
+		//636 ← LDAPS / SSL
+		//7xxx ← UCS. need to be checked first, because both ports may be open
+		$host = $this->configuration->ldapHost;
+		$port = intval($this->configuration->ldapPort);
+		$portSettings = array();
+
+		//In case the port is already provided, we will check this first
+		if($port > 0) {
+			$hostInfo = parse_url($host);
+			if(is_array($hostInfo)
+				&& isset($hostInfo['scheme'])
+				&& stripos($hostInfo['scheme'], 'ldaps') === false) {
+				$portSettings[] = array('port' => $port, 'tls' => true);
+			}
+			$portSettings[] =array('port' => $port, 'tls' => false);
+		}
+
+		//default ports
+		$portSettings = array_merge($portSettings,
+		                            $this->getDefaultLdapPortSettings());
+
+		return $portSettings;
+	}
+
+
+}
\ No newline at end of file
diff --git a/apps/user_ldap/lib/wizardresult.php b/apps/user_ldap/lib/wizardresult.php
new file mode 100644
index 00000000000..1d683fee976
--- /dev/null
+++ b/apps/user_ldap/lib/wizardresult.php
@@ -0,0 +1,50 @@
+.
+ *
+ */
+
+namespace OCA\user_ldap\lib;
+
+class WizardResult {
+	protected $changes = array();
+	protected $specifics = array();
+
+	public function addChange($key, $value) {
+		$this->changes[$key] = $value;
+	}
+
+	public function hasChanges() {
+		return count($this->changes) > 0;
+	}
+
+	public function addSpecific($key, $value) {
+		$this->specifics[$key] = $value;
+	}
+
+	public function getResultArray() {
+		$result = array();
+		$result['changes'] = $this->changes;
+		foreach($this->specifics as $key => $value) {
+			$result[$key] = $value;
+		}
+		return $result;
+	}
+}
\ No newline at end of file
diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php
index 45d874eff00..8a418a65005 100644
--- a/apps/user_ldap/settings.php
+++ b/apps/user_ldap/settings.php
@@ -33,8 +33,28 @@ $tmpl = new OCP\Template('user_ldap', 'settings');
 
 $prefixes = \OCA\user_ldap\lib\Helper::getServerConfigurationPrefixes();
 $hosts = \OCA\user_ldap\lib\Helper::getServerConfigurationHosts();
+
+$wizardHtml = '';
+$toc = array();
+
+$wControls = new OCP\Template('user_ldap', 'part.wizardcontrols');
+$wControls = $wControls->fetchPage();
+$sControls = new OCP\Template('user_ldap', 'part.settingcontrols');
+$sControls = $sControls->fetchPage();
+
+$wizard1 = new OCP\Template('user_ldap', 'part.wizard-server');
+$wizard1->assign('serverConfigurationPrefixes', $prefixes);
+$wizard1->assign('serverConfigurationHosts', $hosts);
+$wizard1->assign('wizardControls', $wControls);
+$wizardHtml .= $wizard1->fetchPage();
+$toc['#ldapWizard1'] = 'Server';
+
+$tmpl->assign('tabs', $wizardHtml);
+$tmpl->assign('toc', $toc);
+
 $tmpl->assign('serverConfigurationPrefixes', $prefixes);
 $tmpl->assign('serverConfigurationHosts', $hosts);
+$tmpl->assign('settingControls', $sControls);
 
 // assign default values
 $config = new \OCA\user_ldap\lib\Configuration('', false);
diff --git a/apps/user_ldap/templates/part.settingcontrols.php b/apps/user_ldap/templates/part.settingcontrols.php
new file mode 100644
index 00000000000..017f21c8b1c
--- /dev/null
+++ b/apps/user_ldap/templates/part.settingcontrols.php
@@ -0,0 +1,12 @@
+
+ + + + + t('Help'));?> + +
\ No newline at end of file diff --git a/apps/user_ldap/templates/part.wizard-server.php b/apps/user_ldap/templates/part.wizard-server.php new file mode 100644 index 00000000000..ae0a7e650c9 --- /dev/null +++ b/apps/user_ldap/templates/part.wizard-server.php @@ -0,0 +1,76 @@ +
+

+ + +

+ +
+
+
+
+ + + + +
+
+
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+ +
\ No newline at end of file diff --git a/apps/user_ldap/templates/part.wizardcontrols.php b/apps/user_ldap/templates/part.wizardcontrols.php new file mode 100644 index 00000000000..588c70916fa --- /dev/null +++ b/apps/user_ldap/templates/part.wizardcontrols.php @@ -0,0 +1,14 @@ +
+ + + + + t('Help'));?> + +
\ No newline at end of file diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index 319dc38a62d..9ca9673ada2 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -1,9 +1,12 @@
'.$l->t('Warning: Apps user_ldap and user_webdavauth are incompatible. You may experience unexpected behavior. Please ask your system administrator to disable one of them.').'

'); @@ -12,6 +15,7 @@ print_unescaped('

'.$l->t('Warning: The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it.').'

'); } ?> +

" />

+
@@ -93,6 +98,7 @@

+

t('Internal Username'));?>

@@ -105,8 +111,8 @@

t('Username-LDAP User Mapping'));?>

t('Usernames are used to store and assign (meta) data. In order to precisely identify and recognize users, each LDAP user will have a internal username. This requires a mapping from username to LDAP user. The created username is mapped to the UUID of the LDAP user. Additionally the DN is cached as well to reduce LDAP interaction, but it is not used for identification. If the DN changes, the changes will be found. The internal username is used all over. Clearing the mappings will have leftovers everywhere. Clearing the mappings is not configuration sensitive, it affects all LDAP configurations! Never clear the mappings in a production environment, only in a testing or experimental stage.'));?>


+
- t('Help'));?>
From 3fe400a3cabfe70c7fe48720d6b5283baedc3b2d Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Fri, 27 Sep 2013 18:41:25 +0200 Subject: [PATCH 04/33] Simplify WizardResult --- apps/user_ldap/lib/wizard.php | 1 - apps/user_ldap/lib/wizardresult.php | 8 -------- 2 files changed, 9 deletions(-) diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index ff81df8bf03..04802205cd4 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -81,7 +81,6 @@ class Wizard extends LDAPUtility { \OCP\Util::writeLog('user_ldap', 'Wiz: detected Port '. $p, \OCP\Util::DEBUG); $this->result->addChange('ldap_port', $p); $this->result->addChange('ldap_tls', intval($t)); -// $this->result->addSpecific('port', $p); return $this->result; } } diff --git a/apps/user_ldap/lib/wizardresult.php b/apps/user_ldap/lib/wizardresult.php index 1d683fee976..2140f654fd0 100644 --- a/apps/user_ldap/lib/wizardresult.php +++ b/apps/user_ldap/lib/wizardresult.php @@ -25,7 +25,6 @@ namespace OCA\user_ldap\lib; class WizardResult { protected $changes = array(); - protected $specifics = array(); public function addChange($key, $value) { $this->changes[$key] = $value; @@ -35,16 +34,9 @@ class WizardResult { return count($this->changes) > 0; } - public function addSpecific($key, $value) { - $this->specifics[$key] = $value; - } - public function getResultArray() { $result = array(); $result['changes'] = $this->changes; - foreach($this->specifics as $key => $value) { - $result[$key] = $value; - } return $result; } } \ No newline at end of file From 7c60384f20a1f5b9dea2288d8b39c5f556b4348f Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Sun, 29 Sep 2013 23:51:26 +0200 Subject: [PATCH 05/33] ignore autodetect-attribute on public save method --- apps/user_ldap/lib/configuration.php | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php index e9e494c2f63..ed6f384da88 100644 --- a/apps/user_ldap/lib/configuration.php +++ b/apps/user_ldap/lib/configuration.php @@ -201,6 +201,7 @@ class Configuration { case 'ldapIgnoreNamingRules': case 'ldapOverrideUuidAttribute': case 'hasPagedResultSupport': + case 'ldapUuidAttribute': continue 2; } if(is_null($value)) { From 8290929aa6fcb1e62e79d7acf8bf310c8d6f94d7 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Sun, 29 Sep 2013 23:53:14 +0200 Subject: [PATCH 06/33] LDAP Wizard: autodetect base DN --- apps/user_ldap/ajax/wizard.php | 1 + apps/user_ldap/js/settings.js | 71 +++++++++++++++++++++----- apps/user_ldap/lib/helper.php | 21 ++++++++ apps/user_ldap/lib/ildapwrapper.php | 8 +++ apps/user_ldap/lib/ldap.php | 4 ++ apps/user_ldap/lib/wizard.php | 79 ++++++++++++++++++++++++++--- 6 files changed, 162 insertions(+), 22 deletions(-) diff --git a/apps/user_ldap/ajax/wizard.php b/apps/user_ldap/ajax/wizard.php index 53c66c34f8e..7df922f17af 100644 --- a/apps/user_ldap/ajax/wizard.php +++ b/apps/user_ldap/ajax/wizard.php @@ -45,6 +45,7 @@ $wizard = new \OCA\user_ldap\lib\Wizard($configuration, $ldapWrapper); switch($action) { case 'guessPortAndTLS': + case 'guessBaseDN': try { $result = $wizard->$action(); if($result !== false) { diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js index 97470b4da41..45b1a9239f5 100644 --- a/apps/user_ldap/js/settings.js +++ b/apps/user_ldap/js/settings.js @@ -126,7 +126,7 @@ var LdapConfiguration = { var LdapWizard = { checkPortInfoShown: false, - changeIndicators: {}, + saveBlacklist: {}, ajax: function(param, fnOnSuccess, fnOnError) { $.post( @@ -144,10 +144,36 @@ var LdapWizard = { applyChanges: function (result) { for (id in result.changes) { + LdapWizard.saveBlacklist[id] = true; $('#'+id).val(result.changes[id]); } }, + checkBaseDN: function() { + host = $('#ldap_host').val(); + user = $('#ldap_dn').val(); + pass = $('#ldap_agent_password').val(); + + if(host && user && pass) { + param = 'action=guessBaseDN'+ + '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); + + LdapWizard.ajax(param, + function(result) { + LdapWizard.applyChanges(result); + if($('#ldap_base').val()) { + $('#ldap_base').removeClass('hidden'); + LdapWizard.hideInfoBox(); + } + }, + function (result) { + $('#ldap_base').removeClass('hidden'); + LdapWizard.showInfoBox('Please specify a port'); + } + ); + } + }, + checkPort: function() { host = $('#ldap_host').val(); user = $('#ldap_dn').val(); @@ -162,30 +188,45 @@ var LdapWizard = { LdapWizard.applyChanges(result); if($('#ldap_port').val()) { $('#ldap_port').removeClass('hidden'); - if(LdapWizard.checkPortInfoShown) { - $('#ldapWizard1 .ldapWizardInfo').addClass('hidden'); - LdapWizard.checkPortInfoShown = false; - } + LdapWizard.hideInfoBox(); } }, function (result) { $('#ldap_port').removeClass('hidden'); - $('#ldapWizard1 .ldapWizardInfo').text(t('user_ldap', - 'Please specify a port')); - $('#ldapWizard1 .ldapWizardInfo').removeClass('hidden'); - LdapWizard.checkPortInfoShown = true; + LdapWizard.showInfoBox('Please specify the BaseDN'); } ); } }, + hideInfoBox: function() { + if(LdapWizard.checkInfoShown) { + $('#ldapWizard1 .ldapWizardInfo').addClass('hidden'); + LdapWizard.checkInfoShown = false; + } + }, + init: function() { if($('#ldap_port').val()) { $('#ldap_port').removeClass('hidden'); } }, + processChanges: function(triggerObj) { + if(triggerObj.id == 'ldap_host' + || triggerObj.id == 'ldap_port' + || triggerObj.id == 'ldap_dn' + || triggerObj.id == 'ldap_agent_password') { + LdapWizard.checkPort(); + LdapWizard.checkBaseDN(); + } + }, + save: function(inputObj) { + if(LdapWizard.saveBlacklist.hasOwnProperty(inputObj.id)) { + delete LdapWizard.saveBlacklist[inputObj.id]; + return; + } param = 'cfgkey='+inputObj.id+ '&cfgval='+$(inputObj).val()+ '&action=save'+ @@ -196,16 +237,18 @@ var LdapWizard = { param, function(result) { if(result.status == 'success') { - if(inputObj.id == 'ldap_host' - || inputObj.id == 'ldap_dn' - || inputObj.id == 'ldap_agent_password') { - LdapWizard.checkPort(); - } + LdapWizard.processChanges(inputObj); } else { // alert('Oooooooooooh :('); } } ); + }, + + showInfoBox: function(text) { + $('#ldapWizard1 .ldapWizardInfo').text(t('user_ldap', text)); + $('#ldapWizard1 .ldapWizardInfo').removeClass('hidden'); + LdapWizard.checkInfoShown = true; } }; diff --git a/apps/user_ldap/lib/helper.php b/apps/user_ldap/lib/helper.php index 4c9dd07a12c..09f646921e3 100644 --- a/apps/user_ldap/lib/helper.php +++ b/apps/user_ldap/lib/helper.php @@ -161,4 +161,25 @@ class Helper { return true; } + + /** + * @brief extractsthe domain from a given URL + * @param $url the URL + * @return mixed, domain as string on success, false otherwise + */ + static public function getDomainFromURL($url) { + $uinfo = parse_url($url); + if(!is_array($uinfo)) { + return false; + } + + $domain = false; + if(isset($uinfo['host'])) { + $domain = $uinfo['host']; + } else if(isset($uinfo['path'])) { + $domain = $uinfo['path']; + } + + return $domain; + } } diff --git a/apps/user_ldap/lib/ildapwrapper.php b/apps/user_ldap/lib/ildapwrapper.php index 9e6bd56ef2a..5e12c7c63b9 100644 --- a/apps/user_ldap/lib/ildapwrapper.php +++ b/apps/user_ldap/lib/ildapwrapper.php @@ -67,6 +67,14 @@ interface ILDAPWrapper { */ public function controlPagedResultResponse($link, $result, &$cookie); + /** + * @brief Count the number of entries in a search + * @param $link LDAP link resource + * @param $result LDAP result resource + * @return mixed, number of results on success, false otherwise + */ + public function countEntries($link, $result); + /** * @brief Return the LDAP error number of the last LDAP command * @param $link LDAP link resource diff --git a/apps/user_ldap/lib/ldap.php b/apps/user_ldap/lib/ldap.php index b63e969912a..13314462b8c 100644 --- a/apps/user_ldap/lib/ldap.php +++ b/apps/user_ldap/lib/ldap.php @@ -49,6 +49,10 @@ class LDAP implements ILDAPWrapper { $isCritical, $cookie); } + public function countEntries($link, $result) { + return $this->invokeLDAPMethod('count_entries', $link, $result); + } + public function errno($link) { return $this->invokeLDAPMethod('errno', $link); } diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index 04802205cd4..ad71fd10f63 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -89,6 +89,10 @@ class Wizard extends LDAPUtility { return false; } + /** + * @brief tries to determine a base dn from User DN or LDAP Host + * @returns mixed WizardResult on success, false otherwise + */ public function guessBaseDN() { if(!$this->checkRequirements(array('ldapHost', 'ldapAgentName', @@ -97,10 +101,52 @@ class Wizard extends LDAPUtility { ))) { return false; } - $cr = $this->getConnection(); - if(!$cr) { + + //check whether a DN is given in the agent name (99.9% of all cases) + $base = null; + $i = stripos($this->configuration->ldapAgentName, 'dc='); + if($i !== false) { + $base = substr($this->configuration->ldapAgentName, $i); + + if($this->testBaseDN($base)) { + $this->applyFind('ldap_base', $base); + $this->applyFind('ldap_base_users', $base); + $this->applyFind('ldap_base_groups', $base); + return $this->result; + } + } + + //this did not help :( + //Let's see whether we can parse the Host URL and convert the domain to + //a base DN + $domain = Helper::getDomainFromURL($this->configuration->ldapHost); + if(!$domain) { return false; } + + $dparts = explode('.', $domain); + $base2 = implode('dc=', $dparts); + if($base !== $base2 && $this->testBaseDN($base2)) { + $this->applyFind('ldap_base', $base2); + $this->applyFind('ldap_base_users', $base2); + $this->applyFind('ldap_base_groups', $base2); + return $this->result; + } + + return false; + } + + /** + * @brief sets the found value for the configuration key in the WizardResult + * as well as in the Configuration instance + * @param $key the configuration key + * @param $value the (detected) value + * @return null + * + */ + private function applyFind($key, $value) { + $this->result->addChange($key, $value); + $this->configuration->setConfiguration(array($key => $value)); } /** @@ -116,13 +162,30 @@ class Wizard extends LDAPUtility { if(is_array($hostInfo) && isset($hostInfo['port'])) { $port = $hostInfo['port']; $host = str_replace(':'.$port, '', $host); - $config = array('ldapHost' => $host, - 'ldapPort' => $port, - ); - $this->result->addChange('ldap_host', $host); - $this->result->addChange('ldap_port', $port); - $this->configuration->setConfiguration($config); + $this->applyFind('ldap_host', $host); + $this->applyFind('ldap_port', $port); + } + } + + /** + * @brief Checks whether for a given BaseDN results will be returned + * @param $base the BaseDN to test + * @return bool true on success, false otherwise + */ + private function testBaseDN($base) { + $cr = $this->getConnection(); + if(!$cr) { + throw new \Excpetion('Could not connect to LDAP'); + } + + //base is there, let's validate it. If we search for anything, we should + //get a result set > 0 on a proper base + $rr = $this->ldap->search($cr, $base, 'objectClass=*', array('dn'), 0, 1); + if(!$this->ldap->isResource($rr)) { + return false; } + $entries = $this->ldap->countEntries($cr, $rr); + return ($entries !== false) && ($entries > 0); } /** From 3b1822cf91407f243f18311b8abc273ad2eb1b11 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Fri, 4 Oct 2013 16:33:37 +0200 Subject: [PATCH 07/33] LDAP Wizard: add detection, load and save of LDAP objectClasses for filter purposes --- apps/user_ldap/ajax/wizard.php | 1 + apps/user_ldap/css/settings.css | 20 ++- apps/user_ldap/js/settings.js | 81 ++++++++-- apps/user_ldap/lib/configuration.php | 20 +-- apps/user_ldap/lib/ildapwrapper.php | 16 ++ apps/user_ldap/lib/ldap.php | 8 + apps/user_ldap/lib/wizard.php | 150 +++++++++++++++++- apps/user_ldap/lib/wizardresult.php | 11 ++ apps/user_ldap/settings.php | 12 +- .../templates/part.wizard-server.php | 4 +- .../templates/part.wizard-userfilter.php | 51 ++++++ apps/user_ldap/templates/settings.php | 2 +- 12 files changed, 343 insertions(+), 33 deletions(-) create mode 100644 apps/user_ldap/templates/part.wizard-userfilter.php diff --git a/apps/user_ldap/ajax/wizard.php b/apps/user_ldap/ajax/wizard.php index 7df922f17af..807f04ca696 100644 --- a/apps/user_ldap/ajax/wizard.php +++ b/apps/user_ldap/ajax/wizard.php @@ -46,6 +46,7 @@ $wizard = new \OCA\user_ldap\lib\Wizard($configuration, $ldapWrapper); switch($action) { case 'guessPortAndTLS': case 'guessBaseDN': + case 'determineObjectClasses': try { $result = $wizard->$action(); if($result !== false) { diff --git a/apps/user_ldap/css/settings.css b/apps/user_ldap/css/settings.css index aa6c4687cf9..f6c9f756339 100644 --- a/apps/user_ldap/css/settings.css +++ b/apps/user_ldap/css/settings.css @@ -1,5 +1,6 @@ .table { display: table; + width: 60%; } .tablecell { @@ -18,7 +19,7 @@ height: 15px; } -.hidden { +.hidden, .invisible { visibility: hidden; } @@ -55,6 +56,16 @@ width: 96.5% !important; } +.tableCellInput { + margin-left: -40%; + width: 100%; +} + +.tableCellLabel { + text-align: right; + padding-right: 25%; +} + .ldapIndent { margin-left: 50px; } @@ -81,4 +92,11 @@ #ldap fieldset p input[type=checkbox] { vertical-align: bottom; +} + +select[multiple=multiple] + button { + height: 28px; + padding-top: 6px !important; + min-width: 40%; + max-width: 40%; } \ No newline at end of file diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js index 45b1a9239f5..88f63e25ca2 100644 --- a/apps/user_ldap/js/settings.js +++ b/apps/user_ldap/js/settings.js @@ -144,7 +144,10 @@ var LdapWizard = { applyChanges: function (result) { for (id in result.changes) { - LdapWizard.saveBlacklist[id] = true; + if(!$.isArray(result.changes[id])) { + //no need to blacklist multiselect + LdapWizard.saveBlacklist[id] = true; + } $('#'+id).val(result.changes[id]); } }, @@ -162,12 +165,12 @@ var LdapWizard = { function(result) { LdapWizard.applyChanges(result); if($('#ldap_base').val()) { - $('#ldap_base').removeClass('hidden'); + $('#ldap_base').removeClass('invisible'); LdapWizard.hideInfoBox(); } }, function (result) { - $('#ldap_base').removeClass('hidden'); + $('#ldap_base').removeClass('invisible'); LdapWizard.showInfoBox('Please specify a port'); } ); @@ -187,28 +190,59 @@ var LdapWizard = { function(result) { LdapWizard.applyChanges(result); if($('#ldap_port').val()) { - $('#ldap_port').removeClass('hidden'); + $('#ldap_port').removeClass('invisible'); LdapWizard.hideInfoBox(); } }, function (result) { - $('#ldap_port').removeClass('hidden'); + $('#ldap_port').removeClass('invisible'); LdapWizard.showInfoBox('Please specify the BaseDN'); } ); } }, + findObjectClasses: function() { + param = 'action=determineObjectClasses'+ + '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); + + LdapWizard.ajax(param, + function(result) { + $('#ldap_userfilter_objectclass').find('option').remove(); + for (i in result.options['ldap_userfilter_objectclass']) { + //FIXME: move HTML into template + objc = result.options['ldap_userfilter_objectclass'][i]; + $('#ldap_userfilter_objectclass').append(""); + } + LdapWizard.applyChanges(result); + $('#ldap_userfilter_objectclass').multiselect('refresh'); + }, + function (result) { + //TODO: error handling + } + ); + }, + hideInfoBox: function() { if(LdapWizard.checkInfoShown) { - $('#ldapWizard1 .ldapWizardInfo').addClass('hidden'); + $('#ldapWizard1 .ldapWizardInfo').addClass('invisible'); LdapWizard.checkInfoShown = false; } }, init: function() { if($('#ldap_port').val()) { - $('#ldap_port').removeClass('hidden'); + $('#ldap_port').removeClass('invisible'); + } + }, + + initUserFilter: function() { + LdapWizard.findObjectClasses(); + }, + + onTabChange: function(event, ui) { + if(ui.newTab[0].id === '#ldapWizard2') { + LdapWizard.initUserFilter(); } }, @@ -227,8 +261,20 @@ var LdapWizard = { delete LdapWizard.saveBlacklist[inputObj.id]; return; } - param = 'cfgkey='+inputObj.id+ - '&cfgval='+$(inputObj).val()+ + LdapWizard._save(inputObj, $(inputObj).val()); + }, + + saveMultiSelect: function(originalObj, resultObj) { + values = ''; + for(i = 0; i < resultObj.length; i++) { + values = values + "\n" + resultObj[i].value; + } + LdapWizard._save($('#'+originalObj)[0], $.trim(values)); + }, + + _save: function(object, value) { + param = 'cfgkey='+object.id+ + '&cfgval='+value+ '&action=save'+ '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); @@ -237,7 +283,7 @@ var LdapWizard = { param, function(result) { if(result.status == 'success') { - LdapWizard.processChanges(inputObj); + LdapWizard.processChanges(object); } else { // alert('Oooooooooooh :('); } @@ -247,17 +293,28 @@ var LdapWizard = { showInfoBox: function(text) { $('#ldapWizard1 .ldapWizardInfo').text(t('user_ldap', text)); - $('#ldapWizard1 .ldapWizardInfo').removeClass('hidden'); + $('#ldapWizard1 .ldapWizardInfo').removeClass('invisible'); LdapWizard.checkInfoShown = true; } }; $(document).ready(function() { $('#ldapAdvancedAccordion').accordion({ heightStyle: 'content', animate: 'easeInOutCirc'}); - $('#ldapSettings').tabs(); + $('#ldapSettings').tabs({ beforeActivate: LdapWizard.onTabChange }); $('#ldap_submit').button(); $('#ldap_action_test_connection').button(); $('#ldap_action_delete_configuration').button(); + $('#ldap_userfilter_groups').multiselect(); + $('#ldap_userfilter_objectclass').multiselect({ + header: false, + selectedList: 9, + noneSelectedText: t('user_ldap', 'Select object classes'), + click: function(event, ui) { + LdapWizard.saveMultiSelect('ldap_userfilter_objectclass', + $('#ldap_userfilter_objectclass').multiselect("getChecked") + ); + } + }); $('.lwautosave').change(function() { LdapWizard.save(this); }); LdapConfiguration.refreshConfig(); $('#ldap_action_test_connection').click(function(event){ diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php index ed6f384da88..e67e0d8d00b 100644 --- a/apps/user_ldap/lib/configuration.php +++ b/apps/user_ldap/lib/configuration.php @@ -44,6 +44,7 @@ class Configuration { 'turnOffCertCheck' => null, 'ldapIgnoreNamingRules' => null, 'ldapUserDisplayName' => null, + 'ldapUserFilterObjectclass' => null, 'ldapUserFilter' => null, 'ldapGroupFilter' => null, 'ldapGroupDisplayName' => null, @@ -121,6 +122,7 @@ class Configuration { case 'ldapBaseGroups': case 'ldapAttributesForUserSearch': case 'ldapAttributesForGroupSearch': + case 'ldapUserFilterObjectclass': $setMethod = 'setMultiLine'; default: $this->$setMethod($key, $val); @@ -136,19 +138,18 @@ class Configuration { if(!$this->configRead && !is_null($this->configPrefix)) { $cta = array_flip($this->getConfigTranslationArray()); foreach($this->config as $key => $val) { -// if($this->configPrefix == 's04') var_dump($key); if(!isset($cta[$key])) { //some are determined continue; } $dbkey = $cta[$key]; -// if($this->configPrefix == 's04') var_dump($dbkey); switch($key) { case 'ldapBase': case 'ldapBaseUsers': case 'ldapBaseGroups': case 'ldapAttributesForUserSearch': case 'ldapAttributesForGroupSearch': + case 'ldapUserFilterObjectclass': $readMethod = 'getMultiLine'; break; case 'ldapIgnoreNamingRules': @@ -166,16 +167,10 @@ class Configuration { $readMethod = 'getValue'; break; } -// if($this->configPrefix == 's04') var_dump($readMethod); $this->config[$key] = $this->$readMethod($dbkey); } $this->configRead = true; } - if($this->configPrefix == 's03') { -// var_dump($this->config); - -// die; - } } /** @@ -193,6 +188,7 @@ class Configuration { case 'ldapBaseGroups': case 'ldapAttributesForUserSearch': case 'ldapAttributesForGroupSearch': + case 'ldapUserFilterObjectclass': if(is_array($value)) { $value = implode("\n", $value); } @@ -250,12 +246,6 @@ class Configuration { if(is_null($defaults)) { $defaults = $this->getDefaults(); } -// if($this->configPrefix == 's04') var_dump($this->configPrefix.$varname); -// if(0 == $this->configKeyToDBKey($varname)) { -// var_dump($varname); -// print("
");
-// 			debug_print_backtrace(); die;
-// 		}
 		return \OCP\Config::getAppValue('user_ldap',
 										$this->configPrefix.$varname,
 										$defaults[$varname]);
@@ -288,6 +278,7 @@ class Configuration {
 			'ldap_base_users'					=> '',
 			'ldap_base_groups'					=> '',
 			'ldap_userlist_filter'				=> 'objectClass=person',
+			'ldap_userfilter_objectclass'		=> '',
 			'ldap_login_filter'					=> 'uid=%uid',
 			'ldap_group_filter'					=> 'objectClass=posixGroup',
 			'ldap_display_name'					=> 'cn',
@@ -327,6 +318,7 @@ class Configuration {
 			'ldap_base'							=> 'ldapBase',
 			'ldap_base_users'					=> 'ldapBaseUsers',
 			'ldap_base_groups'					=> 'ldapBaseGroups',
+			'ldap_userfilter_objectclass' 		=> 'ldapUserFilterObjectclass',
 			'ldap_userlist_filter'				=> 'ldapUserFilter',
 			'ldap_login_filter'					=> 'ldapLoginFilter',
 			'ldap_group_filter'					=> 'ldapGroupFilter',
diff --git a/apps/user_ldap/lib/ildapwrapper.php b/apps/user_ldap/lib/ildapwrapper.php
index 5e12c7c63b9..20587cba7db 100644
--- a/apps/user_ldap/lib/ildapwrapper.php
+++ b/apps/user_ldap/lib/ildapwrapper.php
@@ -105,6 +105,14 @@ interface ILDAPWrapper {
 	 * */
 	public function getAttributes($link, $result);
 
+	/**
+	 * @brief Get the DN of a result entry
+	 * @param $link LDAP link resource
+	 * @param $result LDAP result resource
+	 * @return string containing the DN, false on error
+	 */
+	public function getDN($link, $result);
+
 	/**
 	 * @brief Get all result entries
 	 * @param $link LDAP link resource
@@ -113,6 +121,14 @@ interface ILDAPWrapper {
 	 */
 	public function getEntries($link, $result);
 
+	/**
+	 * @brief Return next result id
+	 * @param $link LDAP link resource
+	 * @param $result LDAP entry result resource
+	 * @return an LDAP search result resource
+	 * */
+	public function nextEntry($link, $result);
+
 	/**
 	 * @brief Read an entry
 	 * @param $link LDAP link resource
diff --git a/apps/user_ldap/lib/ldap.php b/apps/user_ldap/lib/ldap.php
index 13314462b8c..bc963191722 100644
--- a/apps/user_ldap/lib/ldap.php
+++ b/apps/user_ldap/lib/ldap.php
@@ -69,10 +69,18 @@ class LDAP implements ILDAPWrapper {
 		return $this->invokeLDAPMethod('get_attributes', $link, $result);
 	}
 
+	public function getDN($link, $result) {
+		return $this->invokeLDAPMethod('get_dn', $link, $result);
+	}
+
 	public function getEntries($link, $result) {
 		return $this->invokeLDAPMethod('get_entries', $link, $result);
 	}
 
+	public function nextEntry($link, $result) {
+		return $this->invokeLDAPMethod('next_entry', $link, $result);
+	}
+
 	public function read($link, $baseDN, $filter, $attr) {
 		return $this->invokeLDAPMethod('read', $link, $baseDN, $filter, $attr);
 	}
diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php
index ad71fd10f63..170af44e118 100644
--- a/apps/user_ldap/lib/wizard.php
+++ b/apps/user_ldap/lib/wizard.php
@@ -28,6 +28,10 @@ class Wizard extends LDAPUtility {
 	protected $configuration;
 	protected $result;
 
+	const LRESULT_PROCESSED_OK = 0;
+	const LRESULT_PROCESSED_INVALID = 1;
+	const LRESULT_PROCESSED_SKIP = 2;
+
 	/**
 	 * @brief Constructor
 	 * @param $configuration an instance of Configuration
@@ -48,6 +52,51 @@ class Wizard extends LDAPUtility {
 		}
 	}
 
+	public function determineObjectClasses() {
+		if(!$this->checkRequirements(array('ldapHost',
+										   'ldapPort',
+										   'ldapAgentName',
+										   'ldapAgentPassword',
+										   'ldapBase',
+										   ))) {
+			return  false;
+		}
+		$cr = $this->getConnection();
+		if(!$cr) {
+			throw new \Excpetion('Could not connect to LDAP');
+		}
+
+		$p = 'objectclass=';
+		$obclasses = array($p.'inetOrgPerson',        $p.'person',
+						   $p.'organizationalPerson', $p.'user',
+						   $p.'posixAccount',         $p.'*');
+
+		$maxEntryObjC = '';
+		$availableObjectClasses =
+			$this->cumulativeSearchOnAttribute($obclasses, 'objectclass',
+												true, $maxEntryObjC);
+		if(is_array($availableObjectClasses)
+		   && count($availableObjectClasses) > 0) {
+			$this->result->addOptions('ldap_userfilter_objectclass',
+										$availableObjectClasses);
+		} else {
+			throw new \Exception(self::$l->t('Could not find any objectClass'));
+		}
+		$setOCs = $this->configuration->ldapUserFilterObjectclass;
+		file_put_contents('/tmp/set', print_r($setOCs, true));
+		if(is_array($setOCs) && !empty($setOCs)) {
+			//something is already configured? pre-select it.
+			$this->result->addChange('ldap_userfilter_objectclass', $setOCs);
+		} else if(!empty($maxEntryObjC)) {
+			//new? pre-select something hopefully sane
+			$maxEntryObjC = str_replace($p, '', $maxEntryObjC);
+			$this->result->addChange('ldap_userfilter_objectclass',
+									 $maxEntryObjC);
+		}
+
+		return $this->result;
+	}
+
 	/**
 	 * Tries to determine the port, requires given Host, User DN and Password
 	 * @returns mixed WizardResult on success, false otherwise
@@ -55,7 +104,8 @@ class Wizard extends LDAPUtility {
 	public function guessPortAndTLS() {
 		if(!$this->checkRequirements(array('ldapHost',
 										   'ldapAgentName',
-										   'ldapAgentPassword'))) {
+										   'ldapAgentPassword'
+										   ))) {
 			return false;
 		}
 		$this->checkHost();
@@ -266,6 +316,104 @@ class Wizard extends LDAPUtility {
 		return true;
 	}
 
+	/**
+	 * @brief does a cumulativeSearch on LDAP to get different values of a
+	 * specified attribute
+	 * @param $filters array, the filters that shall be used in the search
+	 * @param $attr the attribute of which a list of values shall be returned
+	 * @param $lfw bool, whether the last filter is a wildcard which shall not
+	 * be processed if there were already findings, defaults to true
+	 * @param $maxF string. if not null, this variable will have the filter that
+	 * yields most result entries
+	 * @return mixed, an array with the values on success, false otherwise
+	 *
+	 */
+	private function cumulativeSearchOnAttribute($filters, $attr, $lfw = true, &$maxF = null) {
+		$dnRead = array();
+		$foundItems = array();
+		$maxEntries = 0;
+		if(!is_array($this->configuration->ldapBase) || !isset($this->configuration->ldapBase[0])) {
+			return false;
+		}
+		$base = $this->configuration->ldapBase[0];
+		$cr = $this->getConnection();
+		if(!is_resource($cr)) {
+			return false;
+		}
+		foreach($filters as $filter) {
+			if($lfw && count($foundItems) > 0) {
+				continue;
+			}
+			$rr = $this->ldap->search($cr, $base, $filter, array($attr));
+			if(!$this->ldap->isResource($rr)) {
+				\OCP\Util::writeLog('user_ldap', 'Search failed, Base '.$base, \OCP\Util::DEBUG);
+				continue;
+			}
+			$entries = $this->ldap->countEntries($cr, $rr);
+			$getEntryFunc = 'firstEntry';
+			if(($entries !== false) && ($entries > 0)) {
+				if(!is_null($maxF) && $entries > $maxEntries) {
+					$maxEntries = $entries;
+					$maxF = $filter;
+				}
+				do {
+					$entry = $this->ldap->$getEntryFunc($cr, $rr);
+					if(!$this->ldap->isResource($entry)) {
+						continue 2;
+					}
+					$attributes = $this->ldap->getAttributes($cr, $entry);
+					$dn = $this->ldap->getDN($cr, $entry);
+					if($dn === false || in_array($dn, $dnRead)) {
+						continue;
+					}
+					$state = $this->getAttributeValuesFromEntry($attributes,
+																$attr,
+																$foundItems);
+					$dnRead[] = $dn;
+					$getEntryFunc = 'nextEntry';
+					$rr = $entry; //will be expected by nextEntry next round
+				} while($state === self::LRESULT_PROCESSED_SKIP
+						|| $this->ldap->isResource($entry));
+			}
+		}
+
+		return $foundItems;
+	}
+
+	/**
+	 * @brief appends a list of values fr
+	 * @param $result resource, the return value from ldap_get_attributes
+	 * @param $attribute string, the attribute values to look for
+	 * @param &$known array, new values will be appended here
+	 * @return int, state on of the class constants LRESULT_PROCESSED_OK,
+	 * LRESULT_PROCESSED_INVALID or LRESULT_PROCESSED_SKIP
+	 */
+	private function getAttributeValuesFromEntry($result, $attribute, &$known) {
+		if(!is_array($result)
+		   || !isset($result['count'])
+		   || !$result['count'] > 0) {
+			return self::LRESULT_PROCESSED_INVALID;
+		}
+
+		//strtolower on all keys for proper comparison
+		$result = \OCP\Util::mb_array_change_key_case($result);
+		$attribute = strtolower($attribute);
+		if(isset($result[$attribute])) {
+			foreach($result[$attribute] as $key => $val) {
+				if($key === 'count') {
+					continue;
+				}
+				if(!in_array($val, $known)) {
+					\OCP\Util::writeLog('user_ldap', 'Found objclass '.$val, \OCP\Util::DEBUG);
+					$known[] = $val;
+				}
+			}
+			return self::LRESULT_PROCESSED_OK;
+		} else {
+			return self::LRESULT_PROCESSED_SKIP;
+		}
+	}
+
 	private function getConnection() {
 		$cr = $this->ldap->connect(
 			$this->configuration->ldapHost.':'.$this->configuration->ldapPort,
diff --git a/apps/user_ldap/lib/wizardresult.php b/apps/user_ldap/lib/wizardresult.php
index 2140f654fd0..4c3b563c0c2 100644
--- a/apps/user_ldap/lib/wizardresult.php
+++ b/apps/user_ldap/lib/wizardresult.php
@@ -25,11 +25,19 @@ namespace OCA\user_ldap\lib;
 
 class WizardResult {
 	protected $changes = array();
+	protected $options = array();
 
 	public function addChange($key, $value) {
 		$this->changes[$key] = $value;
 	}
 
+	public function addOptions($key, $values) {
+		if(!is_array($values)) {
+			$values = array($values);
+		}
+		$this->options[$key] = $values;
+	}
+
 	public function hasChanges() {
 		return count($this->changes) > 0;
 	}
@@ -37,6 +45,9 @@ class WizardResult {
 	public function getResultArray() {
 		$result = array();
 		$result['changes'] = $this->changes;
+		if(count($this->options) > 0) {
+			$result['options'] = $this->options;
+		}
 		return $result;
 	}
 }
\ No newline at end of file
diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php
index 8a418a65005..ebba1dbd3a6 100644
--- a/apps/user_ldap/settings.php
+++ b/apps/user_ldap/settings.php
@@ -25,8 +25,11 @@
 
 OC_Util::checkAdminUser();
 
-OCP\Util::addscript('user_ldap', 'settings');
-OCP\Util::addstyle('user_ldap', 'settings');
+OCP\Util::addScript('user_ldap', 'settings');
+OCP\Util::addScript('core', 'jquery.multiselect');
+OCP\Util::addStyle('user_ldap', 'settings');
+OCP\Util::addStyle('core', 'jquery.multiselect');
+OCP\Util::addStyle('core', 'jquery-ui-1.10.0.custom');
 
 // fill template
 $tmpl = new OCP\Template('user_ldap', 'settings');
@@ -49,6 +52,11 @@ $wizard1->assign('wizardControls', $wControls);
 $wizardHtml .= $wizard1->fetchPage();
 $toc['#ldapWizard1'] = 'Server';
 
+$wizard2 = new OCP\Template('user_ldap', 'part.wizard-userfilter');
+$wizard2->assign('wizardControls', $wControls);
+$wizardHtml .= $wizard2->fetchPage();
+$toc['#ldapWizard2'] = 'User Filter';
+
 $tmpl->assign('tabs', $wizardHtml);
 $tmpl->assign('toc', $toc);
 
diff --git a/apps/user_ldap/templates/part.wizard-server.php b/apps/user_ldap/templates/part.wizard-server.php
index ae0a7e650c9..c6900fd24e8 100644
--- a/apps/user_ldap/templates/part.wizard-server.php
+++ b/apps/user_ldap/templates/part.wizard-server.php
@@ -33,7 +33,7 @@
 							/>
 						
 							
 						
@@ -68,7 +68,7 @@
 			
 
 			
-
diff --git a/apps/user_ldap/templates/part.wizard-userfilter.php b/apps/user_ldap/templates/part.wizard-userfilter.php new file mode 100644 index 00000000000..b58784b680f --- /dev/null +++ b/apps/user_ldap/templates/part.wizard-userfilter.php @@ -0,0 +1,51 @@ +
+ +
+

+ t('Limit the access to ownCloud to users meetignthis criteria:'));?> +

+ +

+ + + +

+ +

+ + + +

+ +

+ +

+ + + +

+

+

+ +
+
\ No newline at end of file diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index 9ca9673ada2..f63a4bdef1f 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -2,7 +2,7 @@
    $title) { ?> -
  • +
  • Expert
  • Advanced
  • From ee1b59734586cd4b539fe759f81ba1925e21f4f1 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Fri, 4 Oct 2013 16:44:26 +0200 Subject: [PATCH 08/33] css cleanup --- apps/user_ldap/css/settings.css | 2 +- apps/user_ldap/templates/part.wizard-server.php | 2 +- apps/user_ldap/templates/part.wizardcontrols.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/user_ldap/css/settings.css b/apps/user_ldap/css/settings.css index f6c9f756339..2f12108b090 100644 --- a/apps/user_ldap/css/settings.css +++ b/apps/user_ldap/css/settings.css @@ -19,7 +19,7 @@ height: 15px; } -.hidden, .invisible { +.invisible { visibility: hidden; } diff --git a/apps/user_ldap/templates/part.wizard-server.php b/apps/user_ldap/templates/part.wizard-server.php index c6900fd24e8..92c02177504 100644 --- a/apps/user_ldap/templates/part.wizard-server.php +++ b/apps/user_ldap/templates/part.wizard-server.php @@ -60,7 +60,7 @@

    -

    -

    -

    -

    -

    - " />

    -

    - " />

    -

    - " />

    - - -

    t('Connection Settings'));?>

    -

    +

    + " />

    -

    >


    @@ -100,7 +51,7 @@
    -
    +

    t('Internal Username'));?>

    t('By default the internal username will be created from the UUID attribute. It makes sure that the username is unique and characters do not need to be converted. The internal username has the restriction that only these characters are allowed: [ a-zA-Z0-9_.@- ]. Other characters are replaced with their ASCII correspondence or simply omitted. On collisions a number will be added/increased. The internal username is used to identify a user internally. It is also the default name for the user home folder. It is also a part of remote URLs, for instance for all *DAV services. With this setting, the default behavior can be overridden. To achieve a similar behavior as before ownCloud 5 enter the user display name attribute in the following field. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users.'));?>

    From f6b60c65866ff07f28ed06dd56aa784b62f1f0c8 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 9 Oct 2013 23:03:45 +0200 Subject: [PATCH 19/33] LDAP Wizard: add forgotten templates --- .../templates/part.wizard-groupfilter.php | 42 +++++++++++++++++++ .../templates/part.wizard-loginfilter.php | 37 ++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 apps/user_ldap/templates/part.wizard-groupfilter.php create mode 100644 apps/user_ldap/templates/part.wizard-loginfilter.php diff --git a/apps/user_ldap/templates/part.wizard-groupfilter.php b/apps/user_ldap/templates/part.wizard-groupfilter.php new file mode 100644 index 00000000000..d36c171b639 --- /dev/null +++ b/apps/user_ldap/templates/part.wizard-groupfilter.php @@ -0,0 +1,42 @@ +
    +
    +

    + t('Limit the access to ownCloud to groups meeting this criteria:'));?> +

    +

    + + + +

    +

    + + + +

    +

    + +

    + +

    +

    +

    +

    + 0 t('group(s) found'));?> +

    + +
    +
    \ No newline at end of file diff --git a/apps/user_ldap/templates/part.wizard-loginfilter.php b/apps/user_ldap/templates/part.wizard-loginfilter.php new file mode 100644 index 00000000000..4cad6595449 --- /dev/null +++ b/apps/user_ldap/templates/part.wizard-loginfilter.php @@ -0,0 +1,37 @@ +
    +
    +

    + t('What attribute shall be used as login name:'));?> +

    +

    + + + +

    +

    + + + +

    +

    + + + +

    +

    +

    +

    + + +
    +
    \ No newline at end of file From 3ae696f8438d4ecd0ec374ef73df7911b0d0a1db Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 9 Oct 2013 23:04:06 +0200 Subject: [PATCH 20/33] Wizard does not need data-defaults here --- apps/user_ldap/templates/part.wizard-server.php | 7 +------ .../user_ldap/templates/part.wizard-userfilter.php | 14 ++------------ 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/apps/user_ldap/templates/part.wizard-server.php b/apps/user_ldap/templates/part.wizard-server.php index 92c02177504..01dd8d0fcb2 100644 --- a/apps/user_ldap/templates/part.wizard-server.php +++ b/apps/user_ldap/templates/part.wizard-server.php @@ -27,14 +27,12 @@
    @@ -43,7 +41,6 @@
    @@ -52,7 +49,6 @@
    @@ -62,8 +58,7 @@
    diff --git a/apps/user_ldap/templates/part.wizard-userfilter.php b/apps/user_ldap/templates/part.wizard-userfilter.php index 879af95b2bc..85c870b5de3 100644 --- a/apps/user_ldap/templates/part.wizard-userfilter.php +++ b/apps/user_ldap/templates/part.wizard-userfilter.php @@ -1,49 +1,39 @@
    -

    t('Limit the access to ownCloud to users meeting this criteria:'));?>

    -

    -

    -

    - -

    -

    0 t('user(s) found'));?>

    From c975021a67d5f714490906bb6ee5cdd47b62e686 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 9 Oct 2013 23:16:26 +0200 Subject: [PATCH 21/33] clean up --- apps/user_ldap/settings.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php index 77bd26a52d9..5d3306246df 100644 --- a/apps/user_ldap/settings.php +++ b/apps/user_ldap/settings.php @@ -65,10 +65,6 @@ for($i = 0; $i < count($wizTabs); $i++) { $tmpl->assign('tabs', $wizardHtml); $tmpl->assign('toc', $toc); -$tmpl->assign('serverConfigurationPrefixes', $prefixes); -$tmpl->assign('serverConfigurationHosts', $hosts); -$tmpl->assign('settingControls', $sControls); - // assign default values $config = new \OCA\user_ldap\lib\Configuration('', false); $defaults = $config->getDefaults(); From 5606b60f36e0f6c34c18694a2a19f6446c6b2618 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 9 Oct 2013 23:27:20 +0200 Subject: [PATCH 22/33] LDAP: set displayname as default attribute for user display name --- apps/user_ldap/lib/configuration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php index 14a14890bd1..e1e5d2b65d6 100644 --- a/apps/user_ldap/lib/configuration.php +++ b/apps/user_ldap/lib/configuration.php @@ -306,7 +306,7 @@ class Configuration { 'ldap_group_filter' => 'objectClass=posixGroup', 'ldap_groupfilter_objectclass' => '', 'ldap_groupfilter_groups' => '', - 'ldap_display_name' => 'cn', + 'ldap_display_name' => 'displayName', 'ldap_group_display_name' => 'cn', 'ldap_tls' => 1, 'ldap_nocase' => 0, From 109ddde944ae17621c4680d9c7172eb585b1626d Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 10 Oct 2013 01:21:05 +0200 Subject: [PATCH 23/33] Wizard: autodetection of group-member-assoc attribute --- apps/user_ldap/ajax/wizard.php | 1 + apps/user_ldap/js/settings.js | 16 ++++++++ apps/user_ldap/lib/wizard.php | 61 +++++++++++++++++++++++++++++ apps/user_ldap/lib/wizardresult.php | 7 +++- 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/apps/user_ldap/ajax/wizard.php b/apps/user_ldap/ajax/wizard.php index ebeedaee959..c90efdf7e9e 100644 --- a/apps/user_ldap/ajax/wizard.php +++ b/apps/user_ldap/ajax/wizard.php @@ -46,6 +46,7 @@ $wizard = new \OCA\user_ldap\lib\Wizard($configuration, $ldapWrapper); switch($action) { case 'guessPortAndTLS': case 'guessBaseDN': + case 'determineGroupMemberAssoc': case 'determineUserObjectClasses': case 'determineGroupObjectClasses': case 'determineGroupsForUsers': diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js index 049df9b8b17..6b1f363bbaf 100644 --- a/apps/user_ldap/js/settings.js +++ b/apps/user_ldap/js/settings.js @@ -226,6 +226,7 @@ var LdapWizard = { LdapWizard.countUsers(); } else if(type == 'group') { LdapWizard.countGroups(); + LdapWizard.detectGroupMemberAssoc(); } }, function (result) { @@ -256,6 +257,20 @@ var LdapWizard = { LdapWizard._countThings('countUsers'); }, + detectGroupMemberAssoc: function() { + param = 'action=determineGroupMemberAssoc'+ + '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); + + LdapWizard.ajax(param, + function(result) { + //pure background story + }, + function (result) { + // error handling + } + ); + }, + findAttributes: function() { param = 'action=determineAttributes'+ '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); @@ -395,6 +410,7 @@ var LdapWizard = { LdapWizard.countUsers(); } else if(triggerObj.id == 'ldap_group_filter') { LdapWizard.countGroups(); + LdapWizard.detectGroupMemberAssoc(); } if(triggerObj.id == 'ldap_loginfilter_username' diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index 86cf8d75af6..2538fe4a2c5 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -230,6 +230,26 @@ class Wizard extends LDAPUtility { return $this->result; } + public function determineGroupMemberAssoc() { + if(!$this->checkRequirements(array('ldapHost', + 'ldapPort', + 'ldapAgentName', + 'ldapAgentPassword', + 'ldapGroupFilter', + ))) { + return false; + } + $attribute = $this->detectGroupMemberAssoc(); + if($attribute === false) { + return false; + } + $this->configuration->setConfiguration(array('ldapGroupMemberAssocAttr' => $attribute)); + //so it will be saved on destruct + $this->result->markChange(); + + return $this->result; + } + /** * @brief detects the available object classes * @returns the instance's WizardResult instance @@ -462,6 +482,47 @@ class Wizard extends LDAPUtility { } } + /** + * @brief tries to detect the group member association attribute which is + * one of 'uniqueMember', 'memberUid', 'member' + * @return mixed, string with the attribute name, false on error + */ + private function detectGroupMemberAssoc() { + $possibleAttrs = array('uniqueMember', 'memberUid', 'member', 'unfugasdfasdfdfa'); + $filter = $this->configuration->ldapGroupFilter; + if(empty($filter)) { + return false; + } + $cr = $this->getConnection(); + if(!$cr) { + throw new \Excpetion('Could not connect to LDAP'); + } + $base = $this->configuration->ldapBase[0]; + $rr = $this->ldap->search($cr, $base, $filter, $possibleAttrs); + if(!$this->ldap->isResource($rr)) { + return false; + } + $er = $this->ldap->firstEntry($cr, $rr); + while(is_resource($er)) { + $dn = $this->ldap->getDN($cr, $er); + $attrs = $this->ldap->getAttributes($cr, $er); + $result = array(); + for($i = 0; $i < count($possibleAttrs); $i++) { + if(isset($attrs[$possibleAttrs[$i]])) { + $result[$possibleAttrs[$i]] = $attrs[$possibleAttrs[$i]]['count']; + } + } + if(!empty($result)) { + natsort($result); + return key($result); + } + + $er = $this->ldap->nextEntry($cr, $er); + } + + return false; + } + /** * @brief Checks whether for a given BaseDN results will be returned * @param $base the BaseDN to test diff --git a/apps/user_ldap/lib/wizardresult.php b/apps/user_ldap/lib/wizardresult.php index 4c3b563c0c2..542f106cad8 100644 --- a/apps/user_ldap/lib/wizardresult.php +++ b/apps/user_ldap/lib/wizardresult.php @@ -26,11 +26,16 @@ namespace OCA\user_ldap\lib; class WizardResult { protected $changes = array(); protected $options = array(); + protected $markedChange = false; public function addChange($key, $value) { $this->changes[$key] = $value; } + public function markChange() { + $this->markedChange = true; + } + public function addOptions($key, $values) { if(!is_array($values)) { $values = array($values); @@ -39,7 +44,7 @@ class WizardResult { } public function hasChanges() { - return count($this->changes) > 0; + return (count($this->changes) > 0 || $this->markedChange); } public function getResultArray() { From 7ad8319488cc35c849dba9bae15c1784acbd68d1 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 10 Oct 2013 15:24:10 +0200 Subject: [PATCH 24/33] do not instantiate LDAP Proxy if there are no active configurations --- apps/user_ldap/appinfo/app.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/user_ldap/appinfo/app.php b/apps/user_ldap/appinfo/app.php index 9d6327181af..c2cd295523e 100644 --- a/apps/user_ldap/appinfo/app.php +++ b/apps/user_ldap/appinfo/app.php @@ -30,7 +30,7 @@ if(count($configPrefixes) === 1) { $ldapAccess = new OCA\user_ldap\lib\Access($connector, $ldapWrapper); $userBackend = new OCA\user_ldap\USER_LDAP($ldapAccess); $groupBackend = new OCA\user_ldap\GROUP_LDAP($ldapAccess); -} else { +} else if(count($configPrefixes) > 1) { $userBackend = new OCA\user_ldap\User_Proxy($configPrefixes, $ldapWrapper); $groupBackend = new OCA\user_ldap\Group_Proxy($configPrefixes, $ldapWrapper); } From f64ae7510708e50a416448b4eccb6b0535f2faa6 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 10 Oct 2013 19:37:12 +0200 Subject: [PATCH 25/33] LDAP Wizard: fix couple more or less nasty bugs aka polishing --- apps/user_ldap/js/settings.js | 39 ++++++++++++++++++++++++++-- apps/user_ldap/lib/configuration.php | 8 +++--- apps/user_ldap/lib/wizard.php | 22 +++++++++------- apps/user_ldap/settings.php | 1 + 4 files changed, 54 insertions(+), 16 deletions(-) diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js index 6b1f363bbaf..df5de874601 100644 --- a/apps/user_ldap/js/settings.js +++ b/apps/user_ldap/js/settings.js @@ -155,14 +155,16 @@ var LdapWizard = { $('#'+id).val(result.changes[id]); } } + LdapWizard.functionalityCheck(); }, checkBaseDN: function() { host = $('#ldap_host').val(); + port = $('#ldap_port').val(); user = $('#ldap_dn').val(); pass = $('#ldap_agent_password').val(); - if(host && user && pass) { + if(host && port && user && pass) { param = 'action=guessBaseDN'+ '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); @@ -195,6 +197,7 @@ var LdapWizard = { function(result) { LdapWizard.applyChanges(result); if($('#ldap_port').val()) { + LdapWizard.checkBaseDN(); $('#ldap_port').removeClass('invisible'); LdapWizard.hideInfoBox(); } @@ -346,6 +349,29 @@ var LdapWizard = { ); }, + functionalityCheck: function() { + //criterias to enable the connection: + // - host, port, user filter, login filter + host = $('#ldap_host').val(); + port = $('#ldap_port').val(); + userfilter = $('#ldap_dn').val(); + loginfilter = $('#ldap_agent_password').val(); + + //FIXME: activates a manually deactivated configuration. + if(host && port && userfilter && loginfilter) { + if($('#ldap_configuration_active').is(':checked')) { + return; + } + $('#ldap_configuration_active').prop('checked', true); + LdapWizard.save($('#ldap_configuration_active')[0]); + } else { + if($('#ldap_configuration_active').is(':checked')) { + $('#ldap_configuration_active').prop('checked', false); + LdapWizard.save($('#ldap_configuration_active')[0]); + } + } + }, + hideInfoBox: function() { if(LdapWizard.checkInfoShown) { $('#ldapWizard1 .ldapWizardInfo').addClass('invisible'); @@ -362,11 +388,13 @@ var LdapWizard = { initGroupFilter: function() { LdapWizard.findObjectClasses('ldap_groupfilter_objectclass', 'Group'); LdapWizard.findAvailableGroups('ldap_groupfilter_groups', 'Groups'); + LdapWizard.composeFilter('group'); LdapWizard.countGroups(); }, initLoginFilter: function() { LdapWizard.findAttributes(); + LdapWizard.composeFilter('login'); }, initMultiSelect: function(object, id, caption) { @@ -384,6 +412,7 @@ var LdapWizard = { initUserFilter: function() { LdapWizard.findObjectClasses('ldap_userfilter_objectclass', 'User'); LdapWizard.findAvailableGroups('ldap_userfilter_groups', 'Users'); + LdapWizard.composeFilter('user'); LdapWizard.countUsers(); }, @@ -403,7 +432,10 @@ var LdapWizard = { || triggerObj.id == 'ldap_dn' || triggerObj.id == 'ldap_agent_password') { LdapWizard.checkPort(); - LdapWizard.checkBaseDN(); + if($('#ldap_port').val()) { + //if Port is already set, check BaseDN + LdapWizard.checkBaseDN(); + } } if(triggerObj.id == 'ldap_userlist_filter') { @@ -442,6 +474,9 @@ var LdapWizard = { if(originalObj == 'ldap_userfilter_objectclass' || originalObj == 'ldap_userfilter_groups') { LdapWizard.composeFilter('user'); + //when user filter is changed afterwards, login filter needs to + //be adjusted, too + LdapWizard.composeFilter('login'); } else if(originalObj == 'ldap_loginfilter_attributes') { LdapWizard.composeFilter('login'); } else if(originalObj == 'ldap_groupfilter_objectclass' diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php index e1e5d2b65d6..2fb566aec6f 100644 --- a/apps/user_ldap/lib/configuration.php +++ b/apps/user_ldap/lib/configuration.php @@ -287,7 +287,7 @@ class Configuration { public function getDefaults() { return array( 'ldap_host' => '', - 'ldap_port' => '389', + 'ldap_port' => '', 'ldap_backup_host' => '', 'ldap_backup_port' => '', 'ldap_override_main_server' => '', @@ -296,14 +296,14 @@ class Configuration { 'ldap_base' => '', 'ldap_base_users' => '', 'ldap_base_groups' => '', - 'ldap_userlist_filter' => 'objectClass=person', + 'ldap_userlist_filter' => '', 'ldap_userfilter_objectclass' => '', 'ldap_userfilter_groups' => '', 'ldap_login_filter' => 'uid=%uid', 'ldap_loginfilter_email' => 0, 'ldap_loginfilter_username' => 1, 'ldap_loginfilter_attributes' => '', - 'ldap_group_filter' => 'objectClass=posixGroup', + 'ldap_group_filter' => '', 'ldap_groupfilter_objectclass' => '', 'ldap_groupfilter_groups' => '', 'ldap_display_name' => 'displayName', @@ -319,7 +319,7 @@ class Configuration { 'ldap_override_uuid_attribute' => 0, 'home_folder_naming_rule' => '', 'ldap_turn_off_cert_check' => 0, - 'ldap_configuration_active' => 1, + 'ldap_configuration_active' => 0, 'ldap_attributes_for_user_search' => '', 'ldap_attributes_for_group_search' => '', 'ldap_expert_username_attr' => '', diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index 2538fe4a2c5..a1d635faaea 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -38,6 +38,8 @@ class Wizard extends LDAPUtility { const LFILTER_USER_LIST = 3; const LFILTER_GROUP_LIST = 4; + const LDAP_NW_TIMEOUT = 4; + /** * @brief Constructor * @param $configuration an instance of Configuration @@ -222,6 +224,7 @@ class Wizard extends LDAPUtility { if($testMemberOf) { $this->configuration->hasMemberOfFilterSupport = $this->testMemberOf(); + $this->result->markChange(); if(!$this->configuration->hasMemberOfFilterSupport) { throw new \Exception('memberOf is not supported by the server'); } @@ -375,7 +378,6 @@ class Wizard extends LDAPUtility { } $this->checkHost(); $portSettings = $this->getPortSettingsToTry(); - file_put_contents('/tmp/ps', print_r($portSettings, true).PHP_EOL, FILE_APPEND); if(!is_array($portSettings)) { throw new \Exception(print_r($portSettings, true)); @@ -763,10 +765,10 @@ class Wizard extends LDAPUtility { \OCP\Util::writeLog('user_ldap', 'Wiz: Setting LDAP Options ', \OCP\Util::DEBUG); //set LDAP options - if($this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3)) { - if($tls) { - $this->ldap->startTls($cr); - } + $a = $this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3); + $c = $this->ldap->setOption($cr, LDAP_OPT_NETWORK_TIMEOUT, self::LDAP_NW_TIMEOUT); + if($tls) { + $this->ldap->startTls($cr); } \OCP\Util::writeLog('user_ldap', 'Wiz: Attemping to Bind ', \OCP\Util::DEBUG); @@ -915,7 +917,7 @@ class Wizard extends LDAPUtility { //pre-select objectclass with most result entries $maxEntryObjC = str_replace($p, '', $maxEntryObjC); $this->applyFind($dbkey, $maxEntryObjC); -// $this->result->addChange($dbkey, $maxEntryObjC); + $this->result->addChange($dbkey, $maxEntryObjC); } return $availableFeatures; @@ -962,10 +964,10 @@ class Wizard extends LDAPUtility { $this->configuration->ldapHost.':'.$this->configuration->ldapPort, $this->configuration->ldapPort); - if($this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3)) { - if($this->configuration->ldapTLS === 1) { - $this->ldap->startTls($cr); - } + $this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3); + $this->ldap->setOption($cr, LDAP_OPT_NETWORK_TIMEOUT, self::LDAP_NW_TIMEOUT); + if($this->configuration->ldapTLS === 1) { + $this->ldap->startTls($cr); } $lo = @$this->ldap->bind($cr, diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php index 5d3306246df..d077eafdde9 100644 --- a/apps/user_ldap/settings.php +++ b/apps/user_ldap/settings.php @@ -64,6 +64,7 @@ for($i = 0; $i < count($wizTabs); $i++) { $tmpl->assign('tabs', $wizardHtml); $tmpl->assign('toc', $toc); +$tmpl->assign('settingControls', $sControls); // assign default values $config = new \OCA\user_ldap\lib\Configuration('', false); From 63e9c56d48b257fd155de9fa6a978d2bfadffc1f Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 17 Oct 2013 13:05:14 +0200 Subject: [PATCH 26/33] LDAP Wizard: Use Ajax Spinner to indicate something is happening, especiall port detection --- apps/user_ldap/css/settings.css | 5 +++++ apps/user_ldap/js/settings.js | 26 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/apps/user_ldap/css/settings.css b/apps/user_ldap/css/settings.css index 2f12108b090..65bff3aadb7 100644 --- a/apps/user_ldap/css/settings.css +++ b/apps/user_ldap/css/settings.css @@ -5,6 +5,7 @@ .tablecell { display: table-cell !important; + white-space: nowrap; } .tablerow { @@ -75,6 +76,10 @@ color: #FF3B3B; } +.wizSpinner { + height: 15px; +} + #ldap fieldset p label { width: 20%; max-width: 200px; diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js index df5de874601..0ccf7ecf425 100644 --- a/apps/user_ldap/js/settings.js +++ b/apps/user_ldap/js/settings.js @@ -128,6 +128,7 @@ var LdapWizard = { checkPortInfoShown: false, saveBlacklist: {}, userFilterGroupSelectState: 'enable', + spinner: '', ajax: function(param, fnOnSuccess, fnOnError) { $.post( @@ -168,15 +169,18 @@ var LdapWizard = { param = 'action=guessBaseDN'+ '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); + LdapWizard.showSpinner('#ldap_base'); LdapWizard.ajax(param, function(result) { LdapWizard.applyChanges(result); + LdapWizard.hideSpinner('#ldap_base'); if($('#ldap_base').val()) { $('#ldap_base').removeClass('invisible'); LdapWizard.hideInfoBox(); } }, function (result) { + LdapWizard.hideSpinner('#ldap_base'); $('#ldap_base').removeClass('invisible'); LdapWizard.showInfoBox('Please specify a port'); } @@ -193,9 +197,11 @@ var LdapWizard = { param = 'action=guessPortAndTLS'+ '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); + LdapWizard.showSpinner('#ldap_port'); LdapWizard.ajax(param, function(result) { LdapWizard.applyChanges(result); + LdapWizard.hideSpinner('#ldap_port'); if($('#ldap_port').val()) { LdapWizard.checkBaseDN(); $('#ldap_port').removeClass('invisible'); @@ -203,6 +209,7 @@ var LdapWizard = { } }, function (result) { + LdapWizard.hideSpinner('#ldap_port'); $('#ldap_port').removeClass('invisible'); LdapWizard.showInfoBox('Please specify the BaseDN'); } @@ -278,6 +285,7 @@ var LdapWizard = { param = 'action=determineAttributes'+ '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); + LdapWizard.showSpinner('#ldap_loginfilter_attributes'); LdapWizard.ajax(param, function(result) { $('#ldap_loginfilter_attributes').find('option').remove(); @@ -287,6 +295,7 @@ var LdapWizard = { $('#ldap_loginfilter_attributes').append( ""); } + LdapWizard.hideSpinner('#ldap_loginfilter_attributes'); LdapWizard.applyChanges(result); $('#ldap_loginfilter_attributes').multiselect('refresh'); $('#ldap_loginfilter_attributes').multiselect('enable'); @@ -296,6 +305,7 @@ var LdapWizard = { $('#ldap_loginfilter_attributes').multiselect( {noneSelectedText : 'No attributes found'}); $('#ldap_loginfilter_attributes').multiselect('disable'); + LdapWizard.hideSpinner('#ldap_loginfilter_attributes'); } ); }, @@ -307,6 +317,7 @@ var LdapWizard = { param = 'action=determineGroupsFor'+type+ '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); + LdapWizard.showSpinner('#'+multisel); LdapWizard.ajax(param, function(result) { $('#'+multisel).find('option').remove(); @@ -315,11 +326,13 @@ var LdapWizard = { objc = result.options[multisel][i]; $('#'+multisel).append(""); } + LdapWizard.hideSpinner('#'+multisel); LdapWizard.applyChanges(result); $('#'+multisel).multiselect('refresh'); $('#'+multisel).multiselect('enable'); }, function (result) { + LdapWizard.hideSpinner('#'+multisel); $('#'+multisel).multiselect('disable'); } ); @@ -332,6 +345,7 @@ var LdapWizard = { param = 'action=determine'+type+'ObjectClasses'+ '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); + LdapWizard.showSpinner('#'+multisel); LdapWizard.ajax(param, function(result) { $('#'+multisel).find('option').remove(); @@ -340,10 +354,12 @@ var LdapWizard = { objc = result.options[multisel][i]; $('#'+multisel).append(""); } + LdapWizard.hideSpinner('#'+multisel); LdapWizard.applyChanges(result); $('#'+multisel).multiselect('refresh'); }, function (result) { + LdapWizard.hideSpinner('#'+multisel); //TODO: error handling } ); @@ -379,6 +395,11 @@ var LdapWizard = { } }, + hideSpinner: function(id) { + $(id+' + .wizSpinner').remove(); + $(id + " + button").css('display', 'inline'); + }, + init: function() { if($('#ldap_port').val()) { $('#ldap_port').removeClass('invisible'); @@ -510,6 +531,11 @@ var LdapWizard = { LdapWizard.checkInfoShown = true; }, + showSpinner: function(id) { + $(LdapWizard.spinner).insertAfter($(id)); + $(id + " + img + button").css('display', 'none'); + }, + toggleRawFilter: function(container, moc, mg, stateVar) { if($(container).hasClass('invisible')) { $(container).removeClass('invisible'); From 6b160d8507806f38eaeed2daea2f30621fb000b4 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 17 Oct 2013 18:33:58 +0200 Subject: [PATCH 27/33] LDAP Wizard: make Back and Continue work --- apps/user_ldap/js/settings.js | 58 +++++++++++++++++++ .../templates/part.wizardcontrols.php | 5 +- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js index 0ccf7ecf425..7ce1014a85d 100644 --- a/apps/user_ldap/js/settings.js +++ b/apps/user_ldap/js/settings.js @@ -159,6 +159,22 @@ var LdapWizard = { LdapWizard.functionalityCheck(); }, + basicStatusCheck: function() { + //criterias to continue from the first tab + // - host, port, user filter, agent dn, password, base dn + host = $('#ldap_host').val(); + port = $('#ldap_port').val(); + agent = $('#ldap_dn').val(); + pwd = $('#ldap_agent_password').val(); + base = $('#ldap_base').val(); + + if(host && port && agent && pwd && base) { + $('.ldap_action_continue').removeAttr('disabled'); + } else { + $('.ldap_action_continue').attr('disabled', 'disabled'); + } + }, + checkBaseDN: function() { host = $('#ldap_host').val(); port = $('#ldap_port').val(); @@ -245,6 +261,35 @@ var LdapWizard = { ); }, + controlBack: function() { + curTabIndex = $('#ldapSettings').tabs('option', 'active'); + if(curTabIndex == 0) { + return; + } + if(curTabIndex == 1) { + $('.ldap_action_back').addClass('invisible'); + } + $('#ldapSettings').tabs('option', 'active', curTabIndex - 1); + if(curTabIndex == 3) { + $('.ldap_action_continue').removeClass('invisible'); + } + }, + + controlContinue: function() { + curTabIndex = $('#ldapSettings').tabs('option', 'active'); + if(curTabIndex == 3) { + return; + } + $('#ldapSettings').tabs('option', 'active', 1 + curTabIndex); + if(curTabIndex == 2) { + //now last tab + $('.ldap_action_continue').addClass('invisible'); + } + if(curTabIndex == 0) { + $('.ldap_action_back').removeClass('invisible'); + } + }, + _countThings: function(method) { param = 'action='+method+ '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); @@ -404,6 +449,7 @@ var LdapWizard = { if($('#ldap_port').val()) { $('#ldap_port').removeClass('invisible'); } + LdapWizard.basicStatusCheck(); }, initGroupFilter: function() { @@ -470,6 +516,10 @@ var LdapWizard = { || triggerObj.id == 'ldap_loginfilter_email') { LdapWizard.composeFilter('login'); } + + if($('#ldapSettings').tabs('option', 'active') == 0) { + LdapWizard.basicStatusCheck(); + } }, save: function(inputObj) { @@ -595,6 +645,14 @@ $(document).ready(function() { $('#toggleRawUserFilter').click(LdapWizard.toggleRawUserFilter); $('#toggleRawGroupFilter').click(LdapWizard.toggleRawGroupFilter); LdapConfiguration.refreshConfig(); + $('.ldap_action_continue').click(function(event) { + event.preventDefault(); + LdapWizard.controlContinue(); + }); + $('.ldap_action_back').click(function(event) { + event.preventDefault(); + LdapWizard.controlBack(); + }); $('#ldap_action_test_connection').click(function(event){ event.preventDefault(); $.post( diff --git a/apps/user_ldap/templates/part.wizardcontrols.php b/apps/user_ldap/templates/part.wizardcontrols.php index 4d05586bdfb..db99145d514 100644 --- a/apps/user_ldap/templates/part.wizardcontrols.php +++ b/apps/user_ldap/templates/part.wizardcontrols.php @@ -1,8 +1,9 @@
    - - Date: Thu, 17 Oct 2013 18:55:02 +0200 Subject: [PATCH 28/33] Ldap Wizard: also disable tabs, if the first step is not complete --- apps/user_ldap/js/settings.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js index 7ce1014a85d..efd9bade1ab 100644 --- a/apps/user_ldap/js/settings.js +++ b/apps/user_ldap/js/settings.js @@ -170,8 +170,10 @@ var LdapWizard = { if(host && port && agent && pwd && base) { $('.ldap_action_continue').removeAttr('disabled'); + $('#ldapSettings').tabs('option', 'disabled', []); } else { $('.ldap_action_continue').attr('disabled', 'disabled'); + $('#ldapSettings').tabs('option', 'disabled', [1, 2, 3, 4, 5]); } }, From 6acd01d9f287def7cf4f35fbe71c069dd97eff8b Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 17 Oct 2013 19:40:59 +0200 Subject: [PATCH 29/33] resolve merge conflicts from rebase --- apps/user_ldap/lib/configuration.php | 21 +++++----- apps/user_ldap/lib/connection.php | 57 ++++++++++------------------ 2 files changed, 32 insertions(+), 46 deletions(-) diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php index 2fb566aec6f..460cd9e1dce 100644 --- a/apps/user_ldap/lib/configuration.php +++ b/apps/user_ldap/lib/configuration.php @@ -60,8 +60,8 @@ class Configuration { 'ldapQuotaDefault' => null, 'ldapEmailAttribute' => null, 'ldapCacheTTL' => null, - 'ldapUuidAttribute' => 'auto', - 'ldapOverrideUuidAttribute' => null, + 'ldapUuidUserAttribute' => 'auto', + 'ldapUuidGroupAttribute' => 'auto', 'ldapOverrideMainServer' => false, 'ldapConfigurationActive' => false, 'ldapAttributesForUserSearch' => null, @@ -70,7 +70,8 @@ class Configuration { 'hasPagedResultSupport' => false, 'hasMemberOfFilterSupport' => false, 'ldapExpertUsernameAttr' => null, - 'ldapExpertUUIDAttr' => null, + 'ldapExpertUUIDUserAttr' => null, + 'ldapExpertUUIDGroupAttr' => null, ); public function __construct($configPrefix, $autoread = true) { @@ -214,9 +215,9 @@ class Configuration { break; //following options are not stored but detected, skip them case 'ldapIgnoreNamingRules': - case 'ldapOverrideUuidAttribute': case 'hasPagedResultSupport': - case 'ldapUuidAttribute': + case 'ldapUuidUserAttribute': + case 'ldapUuidGroupAttribute': continue 2; } if(is_null($value)) { @@ -315,15 +316,16 @@ class Configuration { 'ldap_email_attr' => '', 'ldap_group_member_assoc_attribute' => 'uniqueMember', 'ldap_cache_ttl' => 600, - 'ldap_uuid_attribute' => 'auto', - 'ldap_override_uuid_attribute' => 0, + 'ldap_uuid_user_attribute' => 'auto', + 'ldap_uuid_group_attribute' => 'auto', 'home_folder_naming_rule' => '', 'ldap_turn_off_cert_check' => 0, 'ldap_configuration_active' => 0, 'ldap_attributes_for_user_search' => '', 'ldap_attributes_for_group_search' => '', 'ldap_expert_username_attr' => '', - 'ldap_expert_uuid_attr' => '', + 'ldap_expert_uuid_user_attr' => '', + 'ldap_expert_uuid_group_attr' => '', 'has_memberof_filter_support' => 0, ); } @@ -369,7 +371,8 @@ class Configuration { 'ldap_attributes_for_user_search' => 'ldapAttributesForUserSearch', 'ldap_attributes_for_group_search' => 'ldapAttributesForGroupSearch', 'ldap_expert_username_attr' => 'ldapExpertUsernameAttr', - 'ldap_expert_uuid_attr' => 'ldapExpertUUIDAttr', + 'ldap_expert_uuid_user_attr' => 'ldapExpertUUIUserDAttr', + 'ldap_expert_uuid_group_attr' => 'ldapExpertUUIDGroupAttr', 'has_memberof_filter_support' => 'hasMemberOfFilterSupport', ); return $array; diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index 981d792325f..8d34fb2f418 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -38,8 +38,6 @@ class Connection extends LDAPUtility { //settings handler protected $configuration; - 'ldapUuidGroupAttribute' => 'auto', - 'ldapExpertUUIDGroupAttr' => null, /** * @brief Constructor @@ -189,17 +187,11 @@ class Connection extends LDAPUtility { private function readConfiguration($force = false) { if((!$this->configured || $force) && !is_null($this->configID)) { $this->configuration->readConfiguration(); - $this->config['ldapUuidGroupAttribute'] - = $this->$v('ldap_uuid_group_attribute'); - $this->config['ldapExpertUUIDGroupAttr'] - = $this->$v('ldap_expert_uuid_group_attr'); - $this->configured = $this->validateConfiguration(); } } /** - 'ldap_expert_uuid_group_attr' => 'ldapExpertUUIDGroupAttr', * @brief set LDAP configuration with values delivered by an array, not read from configuration * @param $config array that holds the config parameters in an associated array * @param &$setParameters optional; array where the set fields will be given to @@ -224,7 +216,6 @@ class Connection extends LDAPUtility { */ public function saveConfiguration() { $this->configuration->saveConfiguration(); - case 'ldapUuidGroupAttribute': $this->clearCache(); } @@ -262,11 +253,6 @@ class Connection extends LDAPUtility { return $result; } - //TODO remove if not necessary -// public function getDefaults() { -// return $this->configuration->getDefaults(); -// } - private function doSoftValidation() { //if User or Group Base are not set, take over Base DN setting foreach(array('ldapBaseUsers', 'ldapBaseGroups') as $keyBase) { @@ -289,27 +275,29 @@ class Connection extends LDAPUtility { \OCP\Util::INFO); } - $uuidOverride = $this->configuration->ldapExpertUUIDAttr; - if(!empty($uuidOverride)) { - $this->configuration->ldapUuidAttribute = $uuidOverride; - } else { - $uuidAttributes = array('auto', 'entryuuid', 'nsuniqueid', - 'objectguid', 'guid'); - if(!in_array($this->configuration->ldapUuidAttribute, - $uuidAttributes) - && (!is_null($this->configID))) { - $this->configuration->ldapUuidAttribute = 'auto'; - $this->configuration->saveConfiguration(); - 'auto'); - \OCP\Util::writeLog('user_ldap', - 'Illegal value for the UUID Attribute, '. - 'reset to autodetect.', - \OCP\Util::INFO); - } + foreach(array('ldapExpertUUIDUserAttr' => 'ldapUuidUserAttribute', + 'ldapExpertUUIDGroupAttr' => 'ldapUuidGroupAttribute') + as $expertSetting => $effectiveSetting) { + $uuidOverride = $this->configuration->$expertSetting; + if(!empty($uuidOverride)) { + $this->configuration->$effectiveSetting = $uuidOverride; + } else { + $uuidAttributes = array('auto', 'entryuuid', 'nsuniqueid', + 'objectguid', 'guid'); + if(!in_array($this->configuration->$effectiveSetting, + $uuidAttributes) + && (!is_null($this->configID))) { + $this->configuration->$effectiveSetting = 'auto'; + $this->configuration->saveConfiguration(); + \OCP\Util::writeLog('user_ldap', + 'Illegal value for the '. + $effectiveSetting.', '.'reset to '. + 'autodetect.', \OCP\Util::INFO); + } + } } - $backupPort = $this->configuration->ldapBackupPort; if(empty($backupPort)) { $this->configuration->backupPort = $this->configuration->ldapPort; @@ -405,9 +393,6 @@ class Connection extends LDAPUtility { $configurationOK = false; } - } - if(!empty($this->config['ldapExpertUUIDGroupAttr'])) { - $this->config['ldapUuidGroupAttribute'] = $this->config['ldapExpertUUIDGroupAttr']; return $configurationOK; } @@ -423,8 +408,6 @@ class Connection extends LDAPUtility { //second step: critical checks. If left empty or filled wrong, set as //unconfigured and give a warning. return $this->doCriticalValidation(); - 'ldap_uuid_group_attribute' => 'auto', - 'ldap_expert_uuid_group_attr' => '', } From 183dd813d34f870c11bea3a97c9a6b34bc46808b Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 17 Oct 2013 20:57:19 +0200 Subject: [PATCH 30/33] Fix Spinner issues with Base DN field --- apps/user_ldap/js/settings.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js index efd9bade1ab..faef477420f 100644 --- a/apps/user_ldap/js/settings.js +++ b/apps/user_ldap/js/settings.js @@ -157,6 +157,10 @@ var LdapWizard = { } } LdapWizard.functionalityCheck(); + + if($('#ldapSettings').tabs('option', 'active') == 0) { + LdapWizard.basicStatusCheck(); + } }, basicStatusCheck: function() { @@ -451,6 +455,9 @@ var LdapWizard = { if($('#ldap_port').val()) { $('#ldap_port').removeClass('invisible'); } + if($('#ldap_base').val()) { + $('#ldap_base').removeClass('invisible'); + } LdapWizard.basicStatusCheck(); }, @@ -584,8 +591,10 @@ var LdapWizard = { }, showSpinner: function(id) { - $(LdapWizard.spinner).insertAfter($(id)); - $(id + " + img + button").css('display', 'none'); + if($(id + ' + .wizSpinner').length == 0) { + $(LdapWizard.spinner).insertAfter($(id)); + $(id + " + img + button").css('display', 'none'); + } }, toggleRawFilter: function(container, moc, mg, stateVar) { From 17010e8f587dc2e822660da342b3dc64475f8f41 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 17 Oct 2013 20:58:43 +0200 Subject: [PATCH 31/33] Don't set Base User and Base Group when Base DN was detected, would case problems but does not provide any benefit. also make sure that empty string is saved instead of false for multiline values --- apps/user_ldap/lib/configuration.php | 3 +++ apps/user_ldap/lib/wizard.php | 5 ----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php index 460cd9e1dce..c8bf1c09482 100644 --- a/apps/user_ldap/lib/configuration.php +++ b/apps/user_ldap/lib/configuration.php @@ -243,6 +243,9 @@ class Configuration { $value = ''; } else { $value = preg_split('/\r\n|\r|\n/', $value); + if($value === false) { + $value = ''; + } } $this->setValue($varname, $value); diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index a1d635faaea..7b7ef45af47 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -424,11 +424,8 @@ class Wizard extends LDAPUtility { $i = stripos($this->configuration->ldapAgentName, 'dc='); if($i !== false) { $base = substr($this->configuration->ldapAgentName, $i); - if($this->testBaseDN($base)) { $this->applyFind('ldap_base', $base); - $this->applyFind('ldap_base_users', $base); - $this->applyFind('ldap_base_groups', $base); return $this->result; } } @@ -445,8 +442,6 @@ class Wizard extends LDAPUtility { $base2 = implode('dc=', $dparts); if($base !== $base2 && $this->testBaseDN($base2)) { $this->applyFind('ldap_base', $base2); - $this->applyFind('ldap_base_users', $base2); - $this->applyFind('ldap_base_groups', $base2); return $this->result; } From 76a195a0be5d36c090c05ce60e02466e9783fea3 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Mon, 21 Oct 2013 23:15:21 +0200 Subject: [PATCH 32/33] LDAP Wizard: l10n improvements --- apps/user_ldap/ajax/wizard.php | 3 ++- apps/user_ldap/templates/part.wizard-groupfilter.php | 4 ++-- apps/user_ldap/templates/part.wizard-loginfilter.php | 2 +- apps/user_ldap/templates/part.wizard-userfilter.php | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/user_ldap/ajax/wizard.php b/apps/user_ldap/ajax/wizard.php index c90efdf7e9e..e580c097867 100644 --- a/apps/user_ldap/ajax/wizard.php +++ b/apps/user_ldap/ajax/wizard.php @@ -82,7 +82,8 @@ switch($action) { $setParameters = array(); $configuration->setConfiguration($cfg, $setParameters); if(!in_array($key, $setParameters)) { - \OCP\JSON::error(array('message' => $l->t($key.' Could not set configuration '.$setParameters[0]))); + \OCP\JSON::error(array('message' => $l->t($key. + ' Could not set configuration %s', $setParameters[0]))); exit; } $configuration->saveConfiguration(); diff --git a/apps/user_ldap/templates/part.wizard-groupfilter.php b/apps/user_ldap/templates/part.wizard-groupfilter.php index d36c171b639..17ce815589a 100644 --- a/apps/user_ldap/templates/part.wizard-groupfilter.php +++ b/apps/user_ldap/templates/part.wizard-groupfilter.php @@ -1,7 +1,7 @@

    - t('Limit the access to ownCloud to groups meeting this criteria:'));?> + t('Limit the access to %s to groups meeting this criteria:', $theme->getName()));?>

    diff --git a/apps/user_ldap/templates/part.wizard-loginfilter.php b/apps/user_ldap/templates/part.wizard-loginfilter.php index 4cad6595449..d4a36eb0cb7 100644 --- a/apps/user_ldap/templates/part.wizard-loginfilter.php +++ b/apps/user_ldap/templates/part.wizard-loginfilter.php @@ -13,7 +13,7 @@

    - t('Limit the access to ownCloud to users meeting this criteria:'));?> + t('Limit the access to %s to users meeting this criteria:', $theme->getName()));?>

    From 30c0f5dee602e8b09963f2be5234eeff04193eb5 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 23 Oct 2013 12:20:13 +0200 Subject: [PATCH 33/33] LDAP Wizard: proper strings and translations for user and group count text --- apps/user_ldap/lib/wizard.php | 12 +++++++++--- apps/user_ldap/templates/part.wizard-groupfilter.php | 2 +- apps/user_ldap/templates/part.wizard-userfilter.php | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index 7b7ef45af47..9b84c3d5a44 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -73,8 +73,10 @@ class Wizard extends LDAPUtility { $base = $this->configuration->ldapBase[0]; $filter = $this->configuration->ldapGroupFilter; \OCP\Util::writeLog('user_ldap', 'Wiz: g filter '. print_r($filter, true), \OCP\Util::DEBUG); + $l = \OC_L10N::get('user_ldap'); if(empty($filter)) { - $this->result->addChange('ldap_group_count', 0); + $output = $l->n('%s group found', '%s groups found', 0, array(0)); + $this->result->addChange('ldap_group_count', $output); return $this->result; } $cr = $this->getConnection(); @@ -87,7 +89,8 @@ class Wizard extends LDAPUtility { } $entries = $this->ldap->countEntries($cr, $rr); $entries = ($entries !== false) ? $entries : 0; - $this->result->addChange('ldap_group_count', $entries); + $output = $l->n('%s group found', '%s groups found', $entries, $entries); + $this->result->addChange('ldap_group_count', $output); return $this->result; } @@ -116,11 +119,14 @@ class Wizard extends LDAPUtility { } $entries = $this->ldap->countEntries($cr, $rr); $entries = ($entries !== false) ? $entries : 0; - $this->result->addChange('ldap_user_count', $entries); + $l = \OC_L10N::get('user_ldap'); + $output = $l->n('%s user found', '%s users found', $entries, $entries); + $this->result->addChange('ldap_user_count', $output); return $this->result; } + public function determineAttributes() { if(!$this->checkRequirements(array('ldapHost', 'ldapPort', diff --git a/apps/user_ldap/templates/part.wizard-groupfilter.php b/apps/user_ldap/templates/part.wizard-groupfilter.php index 17ce815589a..0cc4dfa572a 100644 --- a/apps/user_ldap/templates/part.wizard-groupfilter.php +++ b/apps/user_ldap/templates/part.wizard-groupfilter.php @@ -35,7 +35,7 @@

    - 0 t('group(s) found'));?> + 0 t('groups found'));?>

    diff --git a/apps/user_ldap/templates/part.wizard-userfilter.php b/apps/user_ldap/templates/part.wizard-userfilter.php index 146e6bb739a..c1d522ce2a6 100644 --- a/apps/user_ldap/templates/part.wizard-userfilter.php +++ b/apps/user_ldap/templates/part.wizard-userfilter.php @@ -35,7 +35,7 @@

    - 0 t('user(s) found'));?> + 0 t('users found'));?>