diff options
author | Arthur Schiwon <blizzz@owncloud.com> | 2013-10-04 16:33:37 +0200 |
---|---|---|
committer | Arthur Schiwon <blizzz@owncloud.com> | 2013-10-17 19:13:27 +0200 |
commit | 3b1822cf91407f243f18311b8abc273ad2eb1b11 (patch) | |
tree | dce41cedcf3916bd9ef4951b74fec029fb9636c7 /apps | |
parent | 8290929aa6fcb1e62e79d7acf8bf310c8d6f94d7 (diff) | |
download | nextcloud-server-3b1822cf91407f243f18311b8abc273ad2eb1b11.tar.gz nextcloud-server-3b1822cf91407f243f18311b8abc273ad2eb1b11.zip |
LDAP Wizard: add detection, load and save of LDAP objectClasses for filter purposes
Diffstat (limited to 'apps')
-rw-r--r-- | apps/user_ldap/ajax/wizard.php | 1 | ||||
-rw-r--r-- | apps/user_ldap/css/settings.css | 20 | ||||
-rw-r--r-- | apps/user_ldap/js/settings.js | 81 | ||||
-rw-r--r-- | apps/user_ldap/lib/configuration.php | 20 | ||||
-rw-r--r-- | apps/user_ldap/lib/ildapwrapper.php | 16 | ||||
-rw-r--r-- | apps/user_ldap/lib/ldap.php | 8 | ||||
-rw-r--r-- | apps/user_ldap/lib/wizard.php | 150 | ||||
-rw-r--r-- | apps/user_ldap/lib/wizardresult.php | 11 | ||||
-rw-r--r-- | apps/user_ldap/settings.php | 12 | ||||
-rw-r--r-- | apps/user_ldap/templates/part.wizard-server.php | 4 | ||||
-rw-r--r-- | apps/user_ldap/templates/part.wizard-userfilter.php | 51 | ||||
-rw-r--r-- | apps/user_ldap/templates/settings.php | 2 |
12 files changed, 343 insertions, 33 deletions
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("<option value='"+objc+"'>"+objc+"</option>"); + } + 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("<pre>"); -// 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 @@ -106,6 +106,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 * @param $result LDAP result resource @@ -114,6 +122,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 * @param $baseDN The DN of the entry to read from 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 @@ /> <span> <input type="number" id="ldap_port" name="ldap_port" - class="hidden lwautosave" + class="invisible lwautosave" data-default="<?php p($_['ldap_port_default']); ?>" placeholder="<?php p($l->t('Port'));?>" /> </span> @@ -68,7 +68,7 @@ </div> <div class="tablerow"> - <div class="tablecell ldapWizardInfo hidden"> + <div class="tablecell ldapWizardInfo invisible"> </div> </div> </div> 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 @@ +<fieldset id="ldapWizard2"> + + <div> + <p> + <?php p($l->t('Limit the access to ownCloud to users meetignthis criteria:'));?> + </p> + + <p> + <label for="ldap_userfilter_objectclass"> + <?php p($l->t('only those object classes:'));?> + </label> + + <select id="ldap_userfilter_objectclass" multiple="multiple" + name="ldap_userfilter_objectclass" + data-default="<?php p($_['ldap_userfilter_objectclass_default']); ?>"> +<!-- <option><?php p($l->t('Any'));?></option> --> + </select> + </p> + + <p> + <label for="ldap_userfilter_groups"> + <?php p($l->t('only from those groups:'));?> + </label> + + <select id="ldap_userfilter_groups" multiple="multiple" + name="ldap_userfilter_groups" class="lwautosave" + data-default="<?php p($_['ldap_userfilter_groups_default']); ?>"> +<!-- <option value="TODOfillIn">TODO: fill in object classes via Ajax</option> --> +<!-- <option value="TODOfillIn2">22222</option> --> + </select> + </p> + + <p> + <label><a>↓ <?php p($l->t('Edit raw filter instead'));?></a></label> + </p> + + <p class="invisible"> + <input type="text" id="ldap_userlistfilter_raw" name="ldap_userlistfilter_raw" + class="lwautosave" + data-default="<?php p($_['ldap_userlistfilter_raw_default']); ?>" + placeholder="<?php p($l->t('Raw LDAP filter'));?>" + title="<?php p($l->t('The filter specifies which LDAP users shall have access to the ownCloud instance.'));?>" + /> + </p> + + <p> + <div class="ldapWizardInfo invisible"> </div> + </p> + <?php print_unescaped($_['wizardControls']); ?> + </div> +</fieldset>
\ 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 @@ <div id="ldapSettings" class="personalblock"> <ul> <?php foreach($_['toc'] as $id => $title) { ?> - <li><a href="<?php p($id); ?>"><?php p($title); ?></a></li> + <li id="<?php p($id); ?>"><a href="<?php p($id); ?>"><?php p($title); ?></a></li> <?php } ?> <li class="ldapSettingsTabs"><a href="#ldapSettings-3">Expert</a></li> <li class="ldapSettingsTabs"><a href="#ldapSettings-2">Advanced</a></li> |