Permalink
Browse files

MDL-36119: auth_{ldap,cas}: LDAP Sync - implement paged results

Thanks to Jerome Charaoui for the original patch.
  • Loading branch information...
iarenaza committed Oct 31, 2012
1 parent 6109f21 commit c090d7c90ef11e430a8b34df48dc0470bda03ca1
View
@@ -3,7 +3,7 @@
/**
* @author Martin Dougiamas
* @author Jerome GUTIERREZ
- * @author I�aki Arenaza
+ * @author Iñaki Arenaza
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package moodle multiauth
*
@@ -206,6 +206,10 @@ function config_form($config, $err, $user_fields) {
}
}
+ if (!ldap_paged_results_supported($this->config->ldap_version)) {
+ echo $OUTPUT->notification(get_string('pagedresultsnotsupp', 'auth_ldap'));
+ }
+
include($CFG->dirroot.'/auth/cas/config.html');
}
@@ -279,6 +283,9 @@ function process_config($config) {
if (empty($config->ldapencoding)) {
$config->ldapencoding = 'utf-8';
}
+ if (!isset($config->pagesize)) {
+ $config->pagesize = LDAP_DEFAULT_PAGESIZE;
+ }
if (!isset($config->contexts)) {
$config->contexts = '';
}
@@ -339,6 +346,7 @@ function process_config($config) {
// save LDAP settings
set_config('host_url', trim($config->host_url), $this->pluginconfig);
set_config('ldapencoding', trim($config->ldapencoding), $this->pluginconfig);
+ set_config('pagesize', (int)trim($config->pagesize), $this->pluginconfig);
set_config('contexts', trim($config->contexts), $this->pluginconfig);
set_config('user_type', textlib::strtolower(trim($config->user_type)), $this->pluginconfig);
set_config('user_attribute', textlib::strtolower(trim($config->user_attribute)), $this->pluginconfig);
View
@@ -44,6 +44,9 @@
if (empty($config->ldapencoding)) {
$config->ldapencoding = 'utf-8';
}
+if (!isset($config->pagesize)) {
+ $config->pagesize = LDAP_DEFAULT_PAGESIZE;
+}
if (!isset($config->contexts)) {
$config->contexts = '';
}
@@ -258,6 +261,25 @@ <h4><?php print_string('auth_ldap_server_settings', 'auth_ldap') ?></h4>
<?php print_string('auth_ldap_ldap_encoding', 'auth_ldap') ?>
</td>
</tr>
+<tr valign="top">
+ <td align="right">
+ <label for="pagesize"><?php print_string('pagesize_key', 'auth_ldap') ?></label>
+ </td>
+ <td>
+ <?php $disabled = (!ldap_paged_results_supported($config->ldap_version)) ? ' disabled="disabled"' : '' ; ?>
+ <input id="pagesize" name="pagesize" type="text" value="<?php echo $config->pagesize ?>" <?php echo $disabled ?>/>
+ <?php
+ if (isset($err['pagesize'])) { echo $OUTPUT->error_text($err['pagesize']); }
+ if ($disabled) {
+ // Don't loose the page size value (disabled fields are not submitted!)
+ ?>
+ <input id="pagesize" name="pagesize" type="hidden" value="<?php echo $config->pagesize ?>" />
+ <?php } ?>
+ </td>
+ <td>
+ <?php print_string('pagesize', 'auth_ldap') ?>
+ </td>
+</tr>
<tr>
<td colspan="2">
<h4><?php print_string('auth_ldap_bind_settings', 'auth_ldap') ?></h4>
View
@@ -27,6 +27,6 @@
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2012061700; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->version = 2012110700; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2012061700; // Requires this Moodle version
$plugin->component = 'auth_cas'; // Full name of the plugin (used for diagnostics)
View
@@ -2,7 +2,7 @@
/**
* @author Martin Dougiamas
- * @author I�aki Arenaza
+ * @author Iñaki Arenaza
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package moodle multiauth
*
@@ -214,6 +214,7 @@ function get_userinfo($username) {
$ldapconnection = $this->ldap_connect();
if(!($user_dn = $this->ldap_find_userdn($ldapconnection, $extusername))) {
+ $this->ldap_close();
return false;
}
@@ -231,11 +232,13 @@ function get_userinfo($username) {
}
if (!$user_info_result = ldap_read($ldapconnection, $user_dn, '(objectClass=*)', $search_attribs)) {
+ $this->ldap_close();
return false; // error!
}
$user_entry = ldap_get_entries_moodle($ldapconnection, $user_info_result);
if (empty($user_entry)) {
+ $this->ldap_close();
return false; // entry not found
}
@@ -647,39 +650,50 @@ function sync_users($do_updates=true) {
$contexts = explode(';', $this->config->contexts);
if (!empty($this->config->create_context)) {
- array_push($contexts, $this->config->create_context);
+ array_push($contexts, $this->config->create_context);
}
- $fresult = array();
+ $ldap_pagedresults = ldap_paged_results_supported($this->config->ldap_version);
+ $ldap_cookie = '';
foreach ($contexts as $context) {
$context = trim($context);
if (empty($context)) {
continue;
}
- if ($this->config->search_sub) {
- //use ldap_search to find first user from subtree
- $ldap_result = ldap_search($ldapconnection, $context,
- $filter,
- array($this->config->user_attribute));
- } else {
- //search only in this context
- $ldap_result = ldap_list($ldapconnection, $context,
- $filter,
- array($this->config->user_attribute));
- }
- if(!$ldap_result) {
- continue;
- }
+ do {
+ if ($ldap_pagedresults) {
+ ldap_control_paged_result($ldapconnection, $this->config->pagesize, true, $ldap_cookie);
+ }
+ if ($this->config->search_sub) {
+ // Use ldap_search to find first user from subtree.
+ $ldap_result = ldap_search($ldapconnection, $context, $filter, array($this->config->user_attribute));
+ } else {
+ // Search only in this context.
+ $ldap_result = ldap_list($ldapconnection, $context, $filter, array($this->config->user_attribute));
+ }
+ if(!$ldap_result) {
+ continue;
+ }
+ if ($ldap_pagedresults) {
+ ldap_control_paged_result_response($ldapconnection, $ldap_result, $ldap_cookie);
+ }
+ if ($entry = @ldap_first_entry($ldapconnection, $ldap_result)) {
+ do {
+ $value = ldap_get_values_len($ldapconnection, $entry, $this->config->user_attribute);
+ $value = textlib::convert($value[0], $this->config->ldapencoding, 'utf-8');
+ $this->ldap_bulk_insert($value);
+ } while ($entry = ldap_next_entry($ldapconnection, $entry));
+ }
+ unset($ldap_result); // Free mem.
+ } while ($ldap_pagedresults && !empty($ldap_cookie));
+ }
- if ($entry = @ldap_first_entry($ldapconnection, $ldap_result)) {
- do {
- $value = ldap_get_values_len($ldapconnection, $entry, $this->config->user_attribute);
- $value = textlib::convert($value[0], $this->config->ldapencoding, 'utf-8');
- $this->ldap_bulk_insert($value);
- } while ($entry = ldap_next_entry($ldapconnection, $entry));
- }
- unset($ldap_result); // free mem
+ // If LDAP paged results were used, the current connection must be completely
+ // closed and a new one created, to work without paged results from here on.
+ if ($ldap_pagedresults) {
+ $this->ldap_close(true);
+ $ldapconnection = $this->ldap_connect();
}
/// preserve our user database
@@ -1411,42 +1425,46 @@ function ldap_get_userlist($filter='*') {
$contexts = explode(';', $this->config->contexts);
if (!empty($this->config->create_context)) {
- array_push($contexts, $this->config->create_context);
+ array_push($contexts, $this->config->create_context);
}
+ $ldap_pagedresults = ldap_paged_results_supported($this->config->ldap_version);
foreach ($contexts as $context) {
$context = trim($context);
if (empty($context)) {
continue;
}
- if ($this->config->search_sub) {
- // Use ldap_search to find first user from subtree
- $ldap_result = ldap_search($ldapconnection, $context,
- $filter,
- array($this->config->user_attribute));
- } else {
- // Search only in this context
- $ldap_result = ldap_list($ldapconnection, $context,
- $filter,
- array($this->config->user_attribute));
- }
-
- if(!$ldap_result) {
- continue;
- }
-
- $users = ldap_get_entries_moodle($ldapconnection, $ldap_result);
-
- // Add found users to list
- for ($i = 0; $i < count($users); $i++) {
- $extuser = textlib::convert($users[$i][$this->config->user_attribute][0],
- $this->config->ldapencoding, 'utf-8');
- array_push($fresult, $extuser);
- }
+ do {
+ if ($ldap_pagedresults) {
+ ldap_control_paged_result($ldapconnection, $this->config->pagesize, true, $ldap_cookie);
+ }
+ if ($this->config->search_sub) {
+ // Use ldap_search to find first user from subtree.
+ $ldap_result = ldap_search($ldapconnection, $context, $filter, array($this->config->user_attribute));
+ } else {
+ // Search only in this context.
+ $ldap_result = ldap_list($ldapconnection, $context, $filter, array($this->config->user_attribute));
+ }
+ if(!$ldap_result) {
+ continue;
+ }
+ if ($ldap_pagedresults) {
+ ldap_control_paged_result_response($ldapconnection, $ldap_result, $ldap_cookie);
+ }
+ $users = ldap_get_entries_moodle($ldapconnection, $ldap_result);
+ // Add found users to list.
+ for ($i = 0; $i < count($users); $i++) {
+ $extuser = textlib::convert($users[$i][$this->config->user_attribute][0],
+ $this->config->ldapencoding, 'utf-8');
+ array_push($fresult, $extuser);
+ }
+ unset($ldap_result); // Free mem.
+ } while ($ldap_pagedresults && !empty($ldap_cookie));
}
- $this->ldap_close();
+ // If paged results were used, make sure the current connection is completely closed
+ $this->ldap_close($ldap_pagedresults);
return $fresult;
}
@@ -1693,6 +1711,10 @@ function config_form($config, $err, $user_fields) {
return;
}
+ if (!ldap_paged_results_supported($this->config->ldap_version)) {
+ echo $OUTPUT->notification(get_string('pagedresultsnotsupp', 'auth_ldap'));
+ }
+
include($CFG->dirroot.'/auth/ldap/config.html');
}
@@ -1707,6 +1729,9 @@ function process_config($config) {
if (empty($config->ldapencoding)) {
$config->ldapencoding = 'utf-8';
}
+ if (!isset($config->pagesize)) {
+ $config->pagesize = LDAP_DEFAULT_PAGESIZE;
+ }
if (!isset($config->contexts)) {
$config->contexts = '';
}
@@ -1807,6 +1832,7 @@ function process_config($config) {
// Save settings
set_config('host_url', trim($config->host_url), $this->pluginconfig);
set_config('ldapencoding', trim($config->ldapencoding), $this->pluginconfig);
+ set_config('pagesize', (int)trim($config->pagesize), $this->pluginconfig);
set_config('contexts', $config->contexts, $this->pluginconfig);
set_config('user_type', textlib::strtolower(trim($config->user_type)), $this->pluginconfig);
set_config('user_attribute', textlib::strtolower(trim($config->user_attribute)), $this->pluginconfig);
@@ -2009,10 +2035,14 @@ function ldap_connect() {
/**
* Disconnects from a LDAP server
*
+ * @param force boolean Forces closing the real connection to the LDAP server, ignoring any
+ * cached connections. This is needed when we've used paged results
+ * and want to use normal results again.
*/
- function ldap_close() {
+ function ldap_close($force=false) {
$this->ldapconns--;
- if($this->ldapconns == 0) {
+ if (($this->ldapconns == 0) || ($force)) {
+ $this->ldapconns = 0;
@ldap_close($this->ldapconnection);
unset($this->ldapconnection);
}
View
@@ -7,6 +7,9 @@
if (empty($config->ldapencoding)) {
$config->ldapencoding = 'utf-8';
}
+if (!isset($config->pagesize)) {
+ $config->pagesize = LDAP_DEFAULT_PAGESIZE;
+}
if (!isset($config->contexts)) {
$config->contexts = '';
}
@@ -148,6 +151,26 @@ <h4><?php print_string('auth_ldap_server_settings', 'auth_ldap') ?></h4>
<?php print_string('auth_ldap_ldap_encoding', 'auth_ldap') ?>
</td>
</tr>
+<tr valign="top">
+ <td align="right">
+ <label for="pagesize"><?php print_string('pagesize_key', 'auth_ldap') ?></label>
+ </td>
+ <td>
+ <?php $disabled = (!ldap_paged_results_supported($config->ldap_version)) ? ' disabled="disabled"' : '' ; ?>
+ <input id="pagesize" name="pagesize" type="text" value="<?php echo $config->pagesize ?>" <?php echo $disabled ?>/>
+ <?php
+ if (isset($err['pagesize'])) { echo $OUTPUT->error_text($err['pagesize']); }
+ if ($disabled) {
+ // Don't loose the page size value (disabled fields are not submitted!)
+ ?>
+ <input id="pagesize" name="pagesize" type="hidden" value="<?php echo $config->pagesize ?>" />
+ <?php } ?>
+
+ </td>
+ <td>
+ <?php print_string('pagesize', 'auth_ldap') ?>
+ </td>
+</tr>
<tr>
<td colspan="2">
<h4><?php print_string('auth_ldap_bind_settings', 'auth_ldap') ?></h4>
@@ -128,6 +128,9 @@
$string['ntlmsso_failed'] = 'Auto-login failed, try the normal login page...';
$string['ntlmsso_isdisabled'] = 'NTLM SSO is disabled.';
$string['ntlmsso_unknowntype'] = 'Unknown ntlmsso type!';
+$string['pagedresultsnotsupp'] = '<em>LDAP paged results not supported (either your PHP version lacks support or you have configured Moodle to use LDAP protocol version 2)</em>';
+$string['pagesize'] = 'Make sure this value is smaller than your LDAP server result set size limit (the maximum number of entries that can be returned in a single query)';
+$string['pagesize_key'] = 'Page Size';
$string['pluginname'] = 'LDAP server';
$string['pluginnotenabled'] = 'Plugin not enabled!';
$string['renamingnotallowed'] = 'User renaming not allowed in LDAP';
View
@@ -26,6 +26,6 @@
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2012061700; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->version = 2012110700; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2012061700; // Requires this Moodle version
$plugin->component = 'auth_ldap'; // Full name of the plugin (used for diagnostics)
Oops, something went wrong.

0 comments on commit c090d7c

Please sign in to comment.