Index: ldap_integration/ldapauth.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ldap_integration/ldapauth.module,v
retrieving revision 1.32.2.18
diff -u -p -r1.32.2.18 ldapauth.module
--- ldap_integration/ldapauth.module	5 Oct 2008 18:46:47 -0000	1.32.2.18
+++ ldap_integration/ldapauth.module	29 Oct 2008 19:27:41 -0000
@@ -26,6 +26,9 @@ define('LDAPAUTH_DISABLE_PASS_CHANGE', v
 define('LDAPAUTH_ALTER_EMAIL_FIELD',   variable_get('ldapauth_alter_email_field', LDAPAUTH_EMAIL_FIELD_NO));
 define('LDAPAUTH_DEFAULT_USER_ATTR',   variable_get('ldapauth_default_user_attr', 'uid'));
 define('LDAPAUTH_DEFAULT_MAIL_ATTR',   variable_get('ldapauth_default_mail_attr', 'mail'));
+define('LDAPAUTH_GROUPS_WO_LDAPAUTH',   variable_get('ldapgroups_groups_wo_ldapauth', FALSE));
+
+
 
 //////////////////////////////////////////////////////////////////////////////
 // Core API hooks
@@ -175,6 +178,9 @@ function ldapauth_perm() {
  * Implements hook_form_alter().
  */
 function ldapauth_form_alter(&$form, $form_state, $form_id) {
+
+ if (LDAPAUTH_GROUPS_WO_LDAPAUTH) return;
+
   global $user;
 
   // Replace the drupal authenticate function is it's used as validation.
@@ -285,6 +291,22 @@ function ldapauth_authenticate($form_val
   if (!isset($account->uid)) {
     // Register this new user.
     if ($ldap_user = _ldapauth_user_lookup($name)) {
+
+        // if ldapgroups module is enabled
+        // and allows for limiting which LDAP granted roles allow account creation
+        // test if user is elgible for account creation
+        if (module_exists("ldapgroups") && variable_get('ldapgroups_roles_granted_accts',FALSE) ) {
+          require_once(drupal_get_path('module', 'ldapgroups') .'/ldapgroupconf.class.php');
+          $account->name = $name;
+          $account->ldap_dn = $ldap_user['dn'];
+          $ldapgroupconf = new LDAPGroupConf($account,$_ldapauth_ldap);
+          if (! $ldapgroupconf->grant_drupal_account()) {
+            form_set_error('no ldap right to create account',t('Your username and password
+            are correct, but you do not have rights to create an account on this site.'));
+            return;
+          }
+        }
+
       // Generate a random drupal password. LDAP password will be used anyways.
       if (LDAPAUTH_LOGIN_PROCESS == LDAPAUTH_AUTH_EXCLUSIVED || !LDAPAUTH_SYNC_PASSWORDS)
         $pass = user_password(20);
Index: ldap_integration/ldapgroupconf.class.php
===================================================================
RCS file: ldap_integration/ldapgroupconf.class.php
diff -N ldap_integration/ldapgroupconf.class.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ldap_integration/ldapgroupconf.class.php	29 Oct 2008 19:27:42 -0000
@@ -0,0 +1,527 @@
+<?php
+// $Id: LDAPInterface.php,v 1.11.2.4 2008/09/16 15:58:58 miglius Exp $
+
+require_once(drupal_get_path('module', 'ldapauth') .'/ldap_integration/LDAPInterface.php');
+/**
+ * @file
+ * ldapgroups integrates ldap groups with drupal roles.
+ */
+
+//////////////////////////////////////////////////////////////////////////////
+define('LDAPGROUPS_DEFAULT_DN_ATTRIBUTE',      'ou');
+define('LDAPGROUPS_DEFAULT_ENTRIES_ATTRIBUTE', 'memberUid');
+define('LDAPGROUPS_GROUPS_WO_LDAPAUTH',   variable_get('ldapgroups_groups_wo_ldapauth', FALSE));
+define('LDAPGROUPS_GROUPS_WO_LDAPAUTH_SID',   variable_get('ldapgroups_groups_wo_ldapauth_sid', FALSE));
+define('LDAPAUTH_DEFAULT_USER_ATTR',   variable_get('ldapauth_default_user_attr', 'uid'));
+//////////////////////////////////////////////////////////////////////////////
+
+/**
+ * @file
+ * LDAPGroupConf class definition.
+ *
+ * LDAPGroupConf object encompasses:
+ *   - a drupal user account
+ *   - an instance of the ldap interface associated with the user
+ *   - the ldap groups parameters
+ */
+
+class LDAPGroupConf {
+
+  private $ldapauth_dbfield_to_property_map = array(
+    "ldapgroups_in_dn" =>  "ldapgroups_in_dn",
+    "ldapgroups_dn_attribute" =>  "ldapgroups_dn_attribute",
+    "ldapgroups_attr" =>  "ldapgroups_attr",
+    "ldapgroups_in_attr" =>  "ldapgroups_in_attr",
+    "ldapgroups_as_entries" =>  "ldapgroups_as_entries",
+    "ldapgroups_entries" =>  "ldapgroups_entries",
+    "ldapgroups_entries_attribute" =>  "ldapgroups_entries_attribute",
+    "ldapgroups_use_group_filter" =>  "ldapgroups_use_group_filter",
+    "ldapgroups_role_mappings" =>  "ldapgroups_role_mappings",
+    "ldapgroups_role_filtering_php" =>  "ldapgroups_role_filtering_php",
+    "ldapgroups_roles_granted_accts" => "ldapgroups_roles_granted_accts"
+  );
+
+  private $ldapgroups_in_dn;
+  private $ldapgroups_dn_attribute = LDAPGROUPS_DEFAULT_DN_ATTRIBUTE;
+  private $ldapgroups_attr;
+  private $ldapgroups_in_attr;
+  private $ldapgroups_as_entries;
+  private $ldapgroups_entries = '';
+  private $ldapgroups_entries_attribute;
+  public  $ldapgroups_use_group_filter;
+  private $ldapgroups_role_mappings;
+  private $ldapgroups_role_filtering_php;
+  private $all_drupal_roles = array();
+  private $user;
+  private $ldap_drupal_roles;
+  private $ldapgroups_roles_granted_accts;
+  private $ldap;
+
+  public function get_option($propname) {
+    return array_key_exists($propname, $this->ldapauth_dbfield_to_property_map) ? $this->$propname : NULL;
+  }
+
+/**
+ * Constructor may take LDAP object.  This is useful if class is being used
+ * by another LDAP module that already has an LDAP connection.
+ *
+ * @param $user
+ *   Drupal user object
+ *
+ * @param $ldap
+ *   LDAPInterface instance
+ *
+ */
+  public function __construct(&$user, &$ldap = NULL) {
+
+
+    /*
+    To make ldapgroups work without ldapauth authentication,
+       - add ldap groups admin switch which says:  "ignore ldapauth authentication"
+       - add ldap groups admin config which tells which ldap server(2) to use for groups
+       - in the class below, if  "ignore ldapauth authentication" is true
+           - if $this->user->ldap_config exists, $set sid to $this->user->ldap_config
+           - if $this->user->ldap_dn is empty,
+           - search ldap for user and get their dn and set $this->user->ldap_dn
+
+    */
+
+    $has_ldap = is_a($ldap, "LDAPInterface");
+    $has_user = is_object($user);
+
+    if (! ( $has_ldap || $has_user) ) {
+      return FALSE;
+    }
+
+    if ($has_user) {
+      $this->user = $user;
+      $this->ldap_drupal_roles = isset($this->user->ldap_drupal_roles) ? $this->user->ldap_drupal_roles : array();
+      if (LDAPGROUPS_GROUPS_WO_LDAPAUTH && ! $this->user->ldap_config) {
+        $this->user->ldap_config = LDAPGROUPS_GROUPS_WO_LDAPAUTH_SID;
+        user_save($this->user, array('ldap_config' => $this->user->ldap_config));
+      }
+    }
+
+    if ($has_ldap) {
+      $this->ldap = $ldap;
+    }
+
+    $sid = ($has_ldap) ? $ldap->getOption('sid') : $this->user->ldap_config;
+
+    if (!$sid) return FALSE;
+
+    if (! $ldapauth_row = db_fetch_object(db_query("SELECT * FROM {ldapauth} WHERE status = '1' AND sid = %d", $sid))) {
+      return FALSE;
+    }
+    elseif (! $has_ldap) {
+        $this->ldap = new LDAPInterface();
+        $this->ldap->setOption('sid', $ldapauth_row->sid);
+        $this->ldap->setOption('name', $ldapauth_row->name);
+        $this->ldap->setOption('server', $ldapauth_row->server);
+        $this->ldap->setOption('port', $ldapauth_row->port);
+        $this->ldap->setOption('tls', $ldapauth_row->tls);
+        $this->ldap->setOption('encrypted', $ldapauth_row->encrypted);
+        $this->ldap->setOption('basedn', $ldapauth_row->basedn);
+        $this->ldap->setOption('user_attr', $ldapauth_row->user_attr);
+    }
+
+    // db fields that map directly to properties without transformation
+    foreach ($this->ldapauth_dbfield_to_property_map as $_dbfieldname => $_propertyname) {
+      if ($ldapauth_row->$_dbfieldname) {
+        $this->$_propertyname = $ldapauth_row->$_dbfieldname;
+      }
+    }
+
+    // special cases of properties that need transformation
+    if ($this->ldapgroups_role_mappings) {
+      $this->ldapgroups_role_mappings =  unserialize($this->ldapgroups_role_mappings);
+    }
+
+    if (! $this->ldapgroups_role_filtering_php) {
+      $this->ldapgroups_role_filtering_php = LDAPGroupConf::get_default_group_filter();
+    }
+
+    if ($this->ldapgroups_roles_granted_accts) {
+      $this->ldapgroups_roles_granted_accts = unserialize($this->ldapgroups_roles_granted_accts);
+    }
+    else {
+      $this->ldapgroups_roles_granted_accts = FALSE;
+    }
+
+    // get all drupal roles that exist on site.  will speed up granting and removing roles.
+    $this->all_drupal_roles = array_flip(user_roles(FALSE, NULL));
+
+    if (LDAPGROUPS_GROUPS_WO_LDAPAUTH && ! $this->user->ldap_dn) {
+      if ($this->connectldap() === FALSE) {
+        return FALSE;
+      }
+      $_ldap_attributes = $this->ldapauth_user_lookup($this->user->name);
+      $this->user->ldap_dn = $_ldap_attributes['dn'];
+      $this->ldap->disconnect();
+    }
+  }
+
+/**
+ * Determine if user should be granted a drupal account.
+ *
+ *
+ * @return
+ *   true or false.
+ */
+  public function grant_drupal_account() {
+
+    if (! $this->ldapgroups_roles_granted_accts) {
+      return TRUE;
+    }
+
+    $ldap_granted_rolenames = $this->get_ldap_granted_rolenames();
+
+    // default to not granting role if ldap query fails or ldap groups not configured correctly
+    if ($ldap_granted_rolenames === FALSE || ! is_array($ldap_granted_rolenames)) {
+      return FALSE;
+    }
+
+    // if any rolenames in common, grant account
+    $ret = (count(array_intersect($ldap_granted_rolenames, $this->ldapgroups_roles_granted_accts)) > 0 );
+    return $ret;
+
+  }
+
+  /**
+ * Determine which Drupal roles should be granted based on LDAP groups
+ *
+ * @return
+ *   an array of Drupal role names
+ */
+  public function get_ldap_granted_rolenames() {
+     //figure out potential roles granted based on ldap group membership.
+
+    $full_dn_roles = $this->detect_groups();
+
+    if ($full_dn_roles === FALSE) {
+      return FALSE;
+    }
+    else {
+      // filter out granted roles ... if role filtering is enabled
+      if ($this->ldapgroups_use_group_filter) {
+        $this->filter_roles($full_dn_roles);
+
+      }
+      // convert to drupal friendly role names
+      $ldap_granted_rolenames = $this->full_dn_roles_to_rolenames($full_dn_roles);
+      return $ldap_granted_rolenames;
+    }
+  }
+
+  private function connectldap() {
+
+  // this function should probably be in ldapauth?
+  // First try to connect with the stored user's DN and password.
+  // If unsuccessful, connect with the BINDDN and BINDPW stored in the database for this config.
+
+  $dn = isset($_SESSION['ldap_login']['dn']) ? $_SESSION['ldap_login']['dn'] : '';
+  $pass = isset($_SESSION['ldap_login']['pass']) ? $_SESSION['ldap_login']['pass'] : '';
+
+  // If I try to connect using a blank dn and pass, I dont get an error until ldap_read,
+  // so I just check to see if they would be blank, based on ldap_forget_passwords, and
+  // make it read from the database.
+
+  if (LDAPAUTH_FORGET_PASSWORDS || !$this->ldap->connect($dn, $pass)) {
+    $row2 = db_fetch_object(db_query("SELECT binddn, bindpw FROM {ldapauth} WHERE sid = %d", $this->ldap->getOption('sid')));
+    $dn = $row2->binddn;
+    $pass = $row2->bindpw;
+    if (!$this->ldap->connect($dn, $pass)) {
+      watchdog('ldapgroups', "User login: user %name data could not be read in the LDAP directory", array('%name' => $this->user->name), WATCHDOG_WARNING);
+      return FALSE;
+    }
+  }
+}
+
+/**
+ * Detect user's LDAP groups.
+ *
+ * @return
+ *   An array of user groups that are in some ldap format,... not necessarily
+ *   a friendly Drupal role name.
+ */
+public function detect_groups() {
+
+  // Nothing to do if there are no groups configured.
+
+  if (!($this->ldapgroups_in_dn || $this->ldapgroups_in_attr || $this->ldapgroups_as_entries)) {
+    return FALSE;
+  }
+
+  if ($this->connectldap() === FALSE) {
+    die('failed to connect in detectgroups'); return FALSE;
+  }
+
+  // Strategy 1: group extracted from user's DN.
+  $dn_groups = array();
+
+  if ($this->ldapgroups_in_dn && $this->ldapgroups_dn_attribute) {
+
+    $pairs = explode(',',  drupal_strtolower($this->user->ldap_dn));
+    foreach ($pairs as $p) {
+      $pair = explode('=', $p);
+      if ( trim($pair[0]) == $this->ldapgroups_dn_attribute ) {
+        $dn_groups[] = trim($pair[1]);
+      }
+    }
+  }
+
+  // Strategy 2: groups in user attributes.
+  $attrib_groups = array();
+  if ($this->ldapgroups_in_attr && $attributes = $this->ldapgroups_attr) {
+    $attributes_array = explode("\r\n", $attributes);
+    foreach ($attributes_array as $attribute) {
+      $tmp = $this->ldap->retrieveMultiAttribute($this->user->ldap_dn, $attribute);
+      $attrib_groups = array_merge($attrib_groups, $tmp);
+    }
+  }
+
+  // Strategy 3: groups as entries.
+  $entries_groups = array();
+  if ($this->ldapgroups_as_entries && $branches = $this->ldapgroups_entries) {
+    $branches_array = explode("\r\n", $branches);
+    $group_attr = ($this->ldapgroups_entries_attribute ? $this->ldapgroups_entries_attribute : LDAPGROUPS_DEFAULT_ENTRIES_ATTRIBUTE);
+    foreach ($branches_array as $branch) {
+      $entries = $this->ldap->search($branch, "$group_attr=$this->user->ldap_dn", array($group_attr));
+      if ($entries['count'] == 0) {
+        $entries = $this->ldap->search($branch,  "$group_attr=$this->user->name", array($group_attr));
+      }
+      foreach ($entries as $entry) {
+        if (isset($entry['dn'])) {
+          $entries_groups[] = $entry['dn'];
+        }
+      }
+    }
+  }
+  $this->ldap->disconnect();
+  return array_merge($dn_groups, $attrib_groups, $entries_groups);
+}
+
+/**
+ * Return default group filter.  Needs to be static so it can be shown in documentation.
+ *
+ * @return
+ *   string of function to be executed when filtering groups.
+ */
+public static function get_default_group_filter() {
+
+$_filter = <<<EOT
+\$group_stripped = preg_replace('/\s+/', '', \$dn_role);
+\$approved_group_stripped = preg_replace('/\s+/', '', \$approved_group);
+if (strcasecmp(\$approved_group_stripped, \$group_stripped) == 0) {
+  \$filtered_full_dn_roles[] = \$approved_role;
+}
+EOT;
+
+return $_filter;
+}
+
+/**
+ * Filters in only drupal roles explicitly mapped from LDAP groups.
+ *
+ * @param $groups
+ *   An array of LDAP groups the user belongs to.
+ *
+ * @return
+ *   An array of drupal roles the user should be granted
+ */
+
+public function filter_roles(&$full_dn_roles) {
+
+ // print "<pre>"; print_r($full_dn_roles); die;
+  $filtered_full_dn_roles = array();
+  // This should take the roles array, pass it thru the filters and send a NEW set of roles back the filter.
+  foreach ($full_dn_roles as $dn_role) {
+    foreach ($this->ldapgroups_role_mappings as $approved_group => $approved_role) {
+      eval($this->ldapgroups_role_filtering_php);
+    }
+  }
+  $full_dn_roles = $filtered_full_dn_roles;
+}
+
+/**
+ * Convert DN format ldap group names to drupal rolenames.
+ *
+ * @param $full_dn_roles
+ *   An array of LDAP groups in DN format.
+ *
+ * @return
+ *   An array of drupal roles the user should be granted
+ */
+public function full_dn_roles_to_rolenames($full_dn_roles) {
+
+  // $full_dn_roles are in ldap role format
+  // $rolenames are in drupal friendly format e.g. "admin"
+
+  // convert $full_dn_roles to $rolenames
+  $rolenames = array();
+  if (!empty($full_dn_roles)) {
+    foreach ($full_dn_roles as $full_dn_role) {
+      if ($rolename = $this->ldapgroups_role_mappings[$full_dn_role]) {
+        // Just that.
+      }
+      else if (preg_match('/^[^=]*=([^,]*),.*$/', $full_dn_role, $matches)) {
+        $rolename = $matches[1];
+      }
+      else {
+        $rolename = $full_dn_role;
+      }
+      $rolenames[] = drupal_strtolower(trim($rolename));
+    }
+  }
+
+  return $rolenames;
+}
+
+/**
+ * Reconcile previously granted ldap roles with new ldap roles
+ *   - remove roles no longer granted
+ *   - create roles that don't exist.
+ *   - grant new roles to user.
+ *
+ * @param $rolenames
+ *   A name of the role.
+ *
+ * @return
+ */
+public function reconcile_ldap_roles(&$rolenames) {
+
+  // $rolenames are in drupal friendly format e.g. "admin"
+
+  // remove all previous ldap granted roles not in currently assigned roles
+    foreach ($this->ldap_drupal_roles as $rolename) {
+      if (! in_array($rolename, $rolenames)) {
+        $this->deny_role($rolename);
+      }
+    }
+
+   // create any new roles in $rolenames and grant them to user
+   // create_role and grant_role methods check if they already exist
+    foreach ($rolenames as $rolename) {
+      $this->create_role($rolename);
+      $this->grant_role($rolename);
+    }
+
+  // Store roles in the user object so we know which ones were granted here.
+
+  user_save($this->user, array('ldap_drupal_roles' => $rolenames));
+
+
+}
+
+/**
+ * Create a new role.
+ *
+ * @param $rolename
+ *   A name of the role.
+ *
+ * @return
+ */
+private function create_role($rolename) {
+  if (! $this->all_drupal_roles[$rolename]) {
+    db_query("INSERT INTO {role} (name) VALUES ('%s')", $rolename);
+    $this->all_drupal_roles[$rolename] = mysql_insert_id();  // rid
+  }
+}
+
+
+
+/**
+ * Grant a user with a role.
+ *
+ * @param $user
+ *   A user object.
+ * @param $rolename
+ *   A name of the role.
+ *
+ * @return
+ */
+private function grant_role($rolename) {
+  $rid = $this->all_drupal_roles[$rolename];
+  if (! array_key_exists($rolename, array_flip($this->user->roles))) {
+    db_query("INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)", $this->user->uid,  $rid);
+    $this->user->roles[$rid] = $rolename;
+  }
+}
+
+
+/**
+ * Deny a user with a role.
+ *
+ * @param $user
+ *   A user object.
+ * @param $rolename
+ *   A name of the role.
+ *
+ * @return
+ */
+private function deny_role($rolename) {
+  $rid = $this->all_drupal_roles[$rolename];
+  db_query("DELETE FROM {users_roles} WHERE uid = %d AND rid = %d", $this->user->uid, $rid);
+  unset($this->user->roles[$rid]);
+}
+
+
+/**
+ * Queries LDAP server for the user.
+ *
+ * @param $name
+ *   A login name.
+ *
+ * @return
+ *   An array with user's LDAP data or NULL if not found.
+ */
+private function ldapauth_user_lookup($name) {
+
+  if (! $this->ldap)
+    return;
+
+  foreach (explode("\r\n", $this->ldap->getOption('basedn')) as $base_dn) {
+    if (empty($base_dn))
+      continue;
+
+    $name_attr = $this->ldap->getOption('user_attr') ? $this->ldap->getOption('user_attr') : LDAPAUTH_DEFAULT_USER_ATTR;
+    $filter = "$name_attr=$name";
+    $result = $this->ldap->search($base_dn, $filter);
+    if (!$result)
+      continue;
+
+    $num_matches = $result['count'];
+    // Must find exactly one user for authentication to.
+    if ($num_matches != 1) {
+      watchdog('ldapauth', "Error: %num_matches users found with $%filter under %base_dn.", array('%num_matches' => $num_matches, '%filter' => $filter, '%base_dn' => $base_dn), WATCHDOG_ERROR);
+      continue;
+    }
+    $match = $result[0];
+
+    // These lines serve to fix the attribute name in case a
+    // naughty server (i.e.: MS Active Directory) is messing the
+    // characters' case.
+    // This was contributed by Dan "Gribnif" Wilga, and described
+    // here: http://drupal.org/node/87833
+    if (!isset($match[$name_attr][0])) {
+      $name_attr = drupal_strtolower($name_attr);
+      if (!isset($match[$name_attr][0]))
+        continue;
+    }
+    // Finally, we must filter out results with spaces added before
+    // or after, which are considered OK by LDAP but are no good for us
+    // We allow lettercase independence, as requested by Marc Galera
+    // on http://drupal.org/node/97728
+    //
+    // Some setups have multiple $name_attr per entry, as pointed out by
+    // Clarence "sparr" Risher on http://drupal.org/node/102008, so we
+    // loop through all possible options.
+    foreach ($match[$name_attr] as $value) {
+      if (drupal_strtolower(trim($value)) == drupal_strtolower($name))
+        return $match;
+    }
+  }
+}
+
+
+}
Index: ldap_integration/ldapgroups.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ldap_integration/Attic/ldapgroups.admin.inc,v
retrieving revision 1.1.2.8
diff -u -p -r1.1.2.8 ldapgroups.admin.inc
--- ldap_integration/ldapgroups.admin.inc	5 Oct 2008 18:46:47 -0000	1.1.2.8
+++ ldap_integration/ldapgroups.admin.inc	29 Oct 2008 19:27:42 -0000
@@ -1,6 +1,5 @@
 <?php
 // $Id: ldapgroups.admin.inc,v 1.1.2.8 2008/10/05 18:46:47 miglius Exp $
-
 /**
  * @file
  * Module admin page callbacks.
@@ -16,6 +15,7 @@
  *   The HTML table with the servers list.
  */
 function ldapgroups_admin_list() {
+
   $rows = array();
   $result = db_query("SELECT sid, name FROM {ldapauth} WHERE status = '1' ORDER BY name");
   while ($row = db_fetch_object($result)) {
@@ -31,10 +31,99 @@ function ldapgroups_admin_list() {
     array('data' => t('Operations'), 'colspan' => 2),
   );
 
-  return theme('table', $header, $rows);
+  $_intro = "<p>Configure LDAP Groups setting specific to a given LDAP Server or configuration below.</p>
+  <p>Sites not using the LDAPauth module for authentication, may want to configure ".
+  l(t('Use LDAP Groups without LDAP Auth'), "admin/settings/ldap/ldapgroups/woauth/edit") ."</p>";
+
+  return t($_intro) . theme('table', $header, $rows);
+}
+
+
+function ldapgroups_wo_ldapauth_edit(&$form_state, $op) {
+
+  if ($op == 'edit') {
+
+    $edit['ldapgroups_groups_wo_ldapauth'] = variable_get('ldapgroups_groups_wo_ldapauth', FALSE);
+    $edit['ldapgroups_groups_wo_ldapauth_sid'] = variable_get('ldapgroups_groups_wo_ldapauth_sid', FALSE);
+
+    $rows = array();
+    $result = db_query("SELECT sid, name FROM {ldapauth} WHERE status = '1' ORDER BY name");
+    $ldapconfs[-1] = 'None Selected';
+    while ($row = db_fetch_object($result)) {
+      $ldapconfs[$row->sid] = $row->name;
+    }
+
+    $form['groups_wo_ldapauth'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Use LDAP Groups functionality without Authenticating via LDAP'),
+      '#collapsible' => TRUE,
+      '#collapsed' => FALSE,
+      '#description' => '<p>In this scenario a particular LDAP config below must be used
+        to determine (1) how a drupal username will map to an LDAP user object and (2)
+        which LDAP config to query, and (3) how mapping is done.</p>'
+    );
+
+
+    $form['groups_wo_ldapauth']['ldapgroups_groups_wo_ldapauth'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Use LDAP Groups functionality without Authenticating via LDAP'),
+      '#default_value' => $edit['ldapgroups_groups_wo_ldapauth']
+    );
+
+    if (! $edit['ldapgroups_groups_wo_ldapauth_sid'] ) {
+      $edit['ldapgroups_groups_wo_ldapauth_sid'] = "-1";
+    }
+    $form['groups_wo_ldapauth']['ldapgroups_groups_wo_ldapauth_sid'] = array(
+      '#type' => 'radios',
+      '#title' => t('Which LDAP Config to use. One must be selected'),
+      '#default_value' =>  $edit['ldapgroups_groups_wo_ldapauth_sid'],
+      '#options' => $ldapconfs
+    );
+
+    $form['submit'] = array(
+      '#type' => 'submit',
+      '#value' => t('Update'),
+    );
+
+    $form['#validate'][] = '_ldapgroups_wo_ldapauth_validate';
+
+    return $form;
+  }
+  else {
+    $form_state['redirect'] = 'admin/settings/ldap/ldapgroups';
+    //drupal_goto('admin/settings/ldap/ldapgroups');
+  }
+
+}
+
+function _ldapgroups_wo_ldapauth_validate($form, $form_state) {
+
+  if ($form_state['values']['ldapgroups_groups_wo_ldapauth'] &&
+  ( ! $form_state['values']['ldapgroups_groups_wo_ldapauth_sid'] ||
+  $form_state['values']['ldapgroups_groups_wo_ldapauth_sid'] == "-1" )) {
+    form_set_error('ldapgroups_groups_wo_ldapauth_sid',
+    t('"<code>'. $form['groups_wo_ldapauth']['ldapgroups_groups_wo_ldapauth']['#title'] .'"</code> is checked,'.
+    ' but no LDAP Config was selected.'));
+  }
 }
 
 /**
+ * Submit hook for the settings form.
+ */
+function ldapgroups_wo_ldapauth_edit_submit($form, &$form_state) {
+  $values = $form_state['values'];
+
+  if ($values['ldapgroups_groups_wo_ldapauth_sid'] == -1) {
+    unset($values['ldapgroups_groups_wo_ldapauth_sid']);
+  }
+  variable_set('ldapgroups_groups_wo_ldapauth', $values['ldapgroups_groups_wo_ldapauth']);
+  variable_set('ldapgroups_groups_wo_ldapauth_sid', $values['ldapgroups_groups_wo_ldapauth_sid']);
+
+  drupal_set_message(t('The configuration options have been saved.'));
+}
+
+
+/**
  * Implements the LDAP server edit page.
  *
  * @param $form_state
@@ -49,6 +138,11 @@ function ldapgroups_admin_list() {
  */
 
 function ldapgroups_admin_edit(&$form_state, $op, $sid) {
+
+  // a static method and constant in ldapgroupconf.class is required for documentation in form
+
+  require_once(drupal_get_path('module', 'ldapgroups') .'/ldapgroupconf.class.php');
+
   if (($op == 'reset') && $sid) {
     $form['sid'] = array(
       '#type' => 'value',
@@ -64,13 +158,17 @@ function ldapgroups_admin_edit(&$form_st
     );
   }
   elseif ($op == 'edit' && $sid) {
-    $edit = db_fetch_array(db_query("SELECT ldapgroups_in_dn, ldapgroups_dn_attribute, ldapgroups_in_attr, ldapgroups_attr, ldapgroups_as_entries, ldapgroups_entries, ldapgroups_entries_attribute FROM {ldapauth} WHERE sid = %d", $sid));
+    $edit = db_fetch_array(db_query("SELECT ldapgroups_in_dn, ldapgroups_dn_attribute, ldapgroups_in_attr,
+      ldapgroups_attr, ldapgroups_as_entries, ldapgroups_entries, ldapgroups_entries_attribute,
+      ldapgroups_use_group_filter, ldapgroups_role_mappings,
+      ldapgroups_role_filtering_php, ldapgroups_roles_granted_accts
+      FROM {ldapauth} WHERE sid = %d", $sid));
 
     $form['group_dn'] = array(
       '#type' => 'fieldset',
       '#title' => t('Group by DN'),
       '#collapsible' => TRUE,
-      '#collapsed' => FALSE,
+      '#collapsed' => ! ($edit['ldapgroups_in_dn'] || $edit['ldapgroups_dn_attribute']),
     );
     $form['group_dn']['ldapgroups_in_dn'] = array(
       '#type' => 'checkbox',
@@ -91,7 +189,7 @@ function ldapgroups_admin_edit(&$form_st
       '#type' => 'fieldset',
       '#title' => t('Group by attribute'),
       '#collapsible' => TRUE,
-      '#collapsed' => FALSE,
+      '#collapsed' => ! ($edit['ldapgroups_in_attr'] || $edit['ldapgroups_attr']),
     );
     $form['group_attr']['ldapgroups_in_attr'] = array(
       '#type' => 'checkbox',
@@ -111,7 +209,7 @@ function ldapgroups_admin_edit(&$form_st
       '#type' => 'fieldset',
       '#title' => t('Group by entry'),
       '#collapsible' => TRUE,
-      '#collapsed' => FALSE,
+      '#collapsed' => ! ($edit['ldapgroups_as_entries'] || $edit['ldapgroups_entries'] || $edit['ldapgroups_entries_attribute']) ,
     );
     $form['group_entry']['ldapgroups_as_entries'] = array(
       '#type' => 'checkbox',
@@ -135,6 +233,73 @@ function ldapgroups_admin_edit(&$form_st
       '#description' => t('Name of the multivalued attribute which holds the CNs of group members, for example: !attr', array('!attr' => theme('placeholder', LDAPGROUPS_DEFAULT_ENTRIES_ATTRIBUTE))),
     );
 
+    $form['role_filtering'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('LDAP Group to Drupal Role Filtering'),
+      '#collapsible' => TRUE,
+      '#collapsed' => ! ($edit['ldapgroups_use_group_filter'] || $edit['ldapgroups_role_mappings'] || $edit['ldapgroups_role_filtering_php']),
+    );
+    $form['role_filtering']['ldapgroups_use_group_filter'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Use LDAP Group to Drupal Roles Filtering'),
+      '#default_value' => $edit['ldapgroups_use_group_filter'],
+      '#description' => t('The module automatically decides names for the Drupal roles based in the names of the LDAP groups. For example:
+      <ul><li>LDAP group: Admins => Drupal role: Admins</li><li>LDAP group: ou=Underlings,dc=myorg,dc=mytld => Drupal role: Underlings.</li></ul>However, if this is not enough, this name mapping can be refined
+      by using LDAP Group to Drupal Role filtering. If enabled, only groups with filters listed below will be mapped to Drupal roles.  If not enabled, a drupal role will be created for every group the user is associated with.')
+    );
+
+    if ($edit['ldapgroups_role_mappings']) {
+      $edit['ldapgroups_role_mappings'] = _ldapgroups_admin_group_mappings_serialized_to_text_input($edit['ldapgroups_role_mappings']);
+    }
+
+    $form['role_filtering']['ldapgroups_role_mappings'] = array(
+      '#type' => 'textarea',
+      '#title' => t('Mapping of LDAP Groups to Drupal Roles (one per line)'),
+      '#default_value' => $edit['ldapgroups_role_mappings'],
+      '#cols' => 50,
+      '#rows' => 5,
+      '#description' => t('If &quot;'. $form['role_filtering']['ldapgroups_use_group_filter']['#title'] .'&quot; checked above, enter a list of LDAP groups and their Drupal role mappings, one per line with a | delimiter.  Should be in the form [ldap group]|[drupal role] such as:<br/>cn=ED IT NAG Staff,DC=ad,DC=uiuc,DC=edu|admin<br/>cn=Ed Webs UIUC Webmasters,DC=ad,DC=uiuc,DC=edu|committee member'),
+    );
+    $form['#validate'][] = '_ldapgroups_role_mappings_validate';
+
+    $form['role_filtering']['ldapgroups_role_filtering_php'] = array(
+      '#type' => 'textarea',
+      '#title' => t('PHP to filter roles by'),
+      '#default_value' => $edit['ldapgroups_role_filtering_php'],
+      '#cols' => 25,
+      '#rows' => 5,
+      '#description' => t('If &quot;'. $form['role_filtering']['ldapgroups_use_group_filter']['#title'] .
+      '&quot; checked above, enter PHP to filter roles by.  Examine the function <code>filter_roles</code> in the file <code>'.
+      drupal_get_path('module', 'ldapgroups') .'/ldapgroupconf.class.php</code> to understand the context
+      this code is evaluated in. Careful, bad PHP code here will break your site.
+      If left empty, the following filter code will
+      be used:<br/><pre>'. LDAPGroupConf::get_default_group_filter() .'</pre>'),
+    );
+
+    $form['limit_account_creation_by_groups'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Limit which LDAP granted Drupal roles will have accounts created.'),
+      '#collapsible' => TRUE,
+      '#collapsed' => ! $edit['ldapgroups_roles_granted_accts'],
+    );
+
+    $_ldapgroups_roles_granted_accts = trim($edit['ldapgroups_roles_granted_accts']) ? join(", ", unserialize($edit['ldapgroups_roles_granted_accts'])) : '';
+    $form['limit_account_creation_by_groups']['ldapgroups_roles_granted_accts'] = array(
+      '#type' => 'textarea',
+      '#title' => t('Drupal roles which allow automatic account creation'),
+      '#default_value' => $_ldapgroups_roles_granted_accts,
+      '#cols' => 50,
+      '#rows' => 5,
+      '#description' => t('Leave blank to automatically create accounts for
+      all LDAP authenticated users.  Otherwise, enter a comma separated list
+      of <strong>Drupal</strong> roles such as <code>admin, author</code>.
+      If the user is not granted one of those Drupal roles based on LDAP,
+      the account will not be created.
+      Don\'t put the LDAP formatted group name such as <code>CN=blah,...</code>.
+      Spaces around commas will be ignored. Everything will be converted to lower case.'),
+    );
+
+
     $form['sid'] = array(
       '#type' => 'hidden',
       '#value' => $sid,
@@ -148,10 +313,15 @@ function ldapgroups_admin_edit(&$form_st
     return $form;
   }
   else {
-    drupal_goto('admin/settings/ldap/ldapgroups');
+    $form_state['redirect'] = 'admin/settings/ldap/ldapgroups/edit/'. $sid;
+    //drupal_goto('admin/settings/ldap/ldapgroups');
   }
 }
 
+function _ldapgroups_cleanrole($string) {
+  return trim(drupal_strtolower($string));
+};
+
 /**
  * Submit hook for the settings form.
  */
@@ -159,18 +329,145 @@ function ldapgroups_admin_edit_submit($f
   $values = $form_state['values'];
 
   if ($values['op'] == t('Reset') && $values['confirm'] == 1) {
-
-    // Settings reset.
-    db_query("UPDATE {ldapauth} SET ldapgroups_in_dn = 0, ldapgroups_dn_attribute = '', ldapgroups_in_attr = 0, ldapgroups_attr = '', ldapgroups_as_entries = 0, ldapgroups_entries = '', ldapgroups_entries_attribute = '' WHERE sid = %d", $values['sid']);
+    db_query("UPDATE {ldapauth} SET ldapgroups_in_dn = 0, ldapgroups_dn_attribute = '', ldapgroups_in_attr = 0, ldapgroups_attr = '', ldapgroups_as_entries = 0, ldapgroups_entries = '', ldapgroups_entries_attribute = '', ldapgroups_entries_attribute = '', ldapgroups_use_group_filter = '0', ldapgroups_role_mappings = '', ldapgroups_role_filtering_php = '', ldapgroups_roles_granted_accts = '' WHERE sid = %d", $values['sid']);
     drupal_set_message(t('The configuration options have been reset to their default values.'));
   }
   else {
+    $values['ldapgroups_dn_attribute'] = drupal_strtolower(trim($values['ldapgroups_dn_attribute']));
+  // parse, cleanse, and serialize array of ldapgroups_roles_granted_accts
+  if (trim($values['ldapgroups_roles_granted_accts'])) {
+    $rolenames = explode(",", $values['ldapgroups_roles_granted_accts']);
+    $rolenames = array_map("_ldapgroups_cleanrole", $rolenames);
+    $serialized_ldapgroups_roles_granted_accts = serialize($rolenames);
+    $ldapgroups_roles_granted_accts = TRUE;
+    }
+  else {
+    $serialized_ldapgroups_roles_granted_accts = '';
+    $ldapgroups_roles_granted_accts = FALSE;
+  }
+
 
-    // Update the ldapgroups configuration.
-    db_query("UPDATE {ldapauth} SET ldapgroups_in_dn = %d, ldapgroups_dn_attribute = '%s', ldapgroups_in_attr = %d, ldapgroups_attr = '%s', ldapgroups_as_entries = %d, ldapgroups_entries = '%s', ldapgroups_entries_attribute = '%s' WHERE sid = %d", $values['ldapgroups_in_dn'], $values['ldapgroups_dn_attribute'], $values['ldapgroups_in_attr'], $values['ldapgroups_attr'], $values['ldapgroups_as_entries'], $values['ldapgroups_entries'], $values['ldapgroups_entries_attribute'], $values['sid']);
+  // Convert | delimited text area to serialized array to stored in db.
+  $mappings = array();
+  $mapping_lines = explode("\n", $values['ldapgroups_role_mappings']);
+  foreach ($mapping_lines as $mapping_line) {
+    $pair = explode('|', $mapping_line);
+    if (trim($pair[1]) && $pair[0]) {
+      $mappings[$pair[0]] = _ldapgroups_cleanrole($pair[1]);
+    }
+  }
+  $serialized_ldapgroups_role_mappings = ($mappings) ? serialize($mappings) : '';
+
+  db_query("UPDATE {ldapauth} SET ldapgroups_in_dn = %d, ldapgroups_dn_attribute = '%s', ldapgroups_in_attr = %d,
+    ldapgroups_attr = '%s', ldapgroups_as_entries = %d, ldapgroups_entries = '%s',
+    ldapgroups_entries_attribute = '%s', ldapgroups_use_group_filter = %d,
+    ldapgroups_role_mappings = '%s', ldapgroups_role_filtering_php = '%s',
+    ldapgroups_roles_granted_accts = '%s'  WHERE sid = %d", $values['ldapgroups_in_dn'],
+    $values['ldapgroups_dn_attribute'], $values['ldapgroups_in_attr'], $values['ldapgroups_attr'],
+    $values['ldapgroups_as_entries'], $values['ldapgroups_entries'], $values['ldapgroups_entries_attribute'],
+    $values['ldapgroups_use_group_filter'], $serialized_ldapgroups_role_mappings,
+    $values['ldapgroups_role_filtering_php'], $serialized_ldapgroups_roles_granted_accts, $values['sid']);
+
+    variable_set('ldapgroups_roles_granted_accts', $ldapgroups_roles_granted_accts);
     drupal_set_message(t('The configuration options have been saved.'));
   }
 
-  $form_state['redirect'] = 'admin/settings/ldap/ldapgroups';
+  $form_state['redirect'] = 'admin/settings/ldap/ldapgroups/edit/'. $values['sid'];
+}
+
+
+
+// Convert LDAP group to Drupal role mappings from serialized array stored in db
+// to | delimited text area for user interface.
+function _ldapgroups_admin_group_mappings_serialized_to_text_input($_group_mappings) {
+  $_input_textarea = "";
+  $_group_mappings = unserialize($_group_mappings);
+  foreach ($_group_mappings as $_ldap_group => $_drupal_role) {
+    $_input_textarea =  $_input_textarea . $_ldap_group ."|". $_drupal_role ."\n";
+  }
+  return $_input_textarea;
+}
+
+function _ldapgroups_role_mappings_validate($form, $form_state) {
+
+  $values = $form_state['values'];
+
+  if ($values['ldapgroups_in_dn'] && ! $values['ldapgroups_dn_attribute'] ) {
+    form_set_error('ldapgroups_dn_attribute',
+    t('"<code>'. $form['group_dn']['ldapgroups_in_dn']['#title'] .'"</code> is checked,'.
+    ' but <code>"'. $form['group_dn']['ldapgroups_dn_attribute']['#title'] .'"</code> is empty.'));
+  }
+
+  if (! $values['ldapgroups_in_dn'] &&  $values['ldapgroups_dn_attribute'] ) {
+    drupal_set_message( t('<code>"'. $form['group_dn']['ldapgroups_in_dn']['#title']
+    .'"</code> is not checked,'.
+    ' but <code>"'. $form['group_dn']['ldapgroups_dn_attribute']['#title'] .'"</code> has data.
+    Groups will not be selected based on user\'s DN unless <code>"'.
+    $form['group_dn']['ldapgroups_in_dn']['#title'] .'"</code> is checked.'), "warning");
+  }
+
+  if ($values['ldapgroups_in_attr'] && ! $values['ldapgroups_attr'] ) {
+    form_set_error('ldapgroups_attr',
+    t('"<code>'. $form['group_attr']['ldapgroups_in_attr']['#title'] .'</code>" is checked,'.
+    ' but "<code>'. $form['group_attr']['ldapgroups_attr']['#title'] .'</code>" is empty.'));
+  }
+
+  if (! $values['ldapgroups_in_attr'] &&  $values['ldapgroups_attr'] ) {
+    drupal_set_message(
+    t('<code>"'. $form['group_attr']['ldapgroups_in_attr']['#title'] .'"</code> is not checked,'.
+    ' but <code>"'. $form['group_attr']['ldapgroups_attr']['#title'] .'"</code> has data.
+    Groups will not be selected based on user\'s LDAP Attributes unless "<code>'.
+    $form['group_attr']['ldapgroups_in_attr']['#title'] .'"</code> is checked.'), "warning");
+  }
+
+  if ($values['ldapgroups_as_entries'] && ! $values['ldapgroups_entries'] ) {
+    form_set_error('ldapgroups_entries',
+    t('<code>"'. $form['group_entry']['ldapgroups_as_entries']['#title'] .'"</code> is checked,'
+    .' but <code>"'. $form['group_entry']['ldapgroups_entries']['#title'] .'"</code> is empty.'));
+  }
+
+  if ($values['ldapgroups_as_entries'] && ! $values['ldapgroups_entries_attribute'] ) {
+    form_set_error('ldapgroups_entries',
+    t('<code>"'. $form['group_entry']['ldapgroups_as_entries']['#title'] .'"</code> is checked,'.
+    ' but <code>"'. $form['group_entry']['ldapgroups_entries_attribute']['#title'] .'"</code> is empty.'));
+  }
+
+  if (! $values['ldapgroups_as_entries'] &&  $values['ldapgroups_entries'] ) {
+    drupal_set_message(
+    t('<code>"'. $form['group_entry']['ldapgroups_as_entries']['#title'] .'"</code> is not checked,'.
+    ' but <code>"'. $form['group_entry']['ldapgroups_entries']['#title'] .'"</code> has data. Groups
+    will not be selected based "Group by entry" unless <code>"' .
+    $form['group_entry']['ldapgroups_as_entries']['#title'] .'"</code> is checked.'), "warning");
+  }
+
+  $bad_mapping_syntax = FALSE;
+  if ($values['ldapgroups_role_mappings']) {
+    $_mapping_lines = explode("\n", trim($values['ldapgroups_role_mappings']));
+    if (is_array($_mapping_lines) && count($_mapping_lines) > 0 ) {
+      foreach ($_mapping_lines as $_mapping_line) {
+        if (trim($_mapping_line) && count(explode('|', trim($_mapping_line))) != 2) {
+          $bad_mapping_syntax = TRUE;
+        }
+      }
+    }
+  }
+
+  if ($values['ldapgroups_use_group_filter'] && ! trim($values['ldapgroups_role_mappings'])) {
+    drupal_set_message(t("&quot;" . $form['role_filtering']['ldapgroups_use_group_filter']['#title'] .
+    "&quot; was checked, but no LDAP Groups to Drupal Role are listed.  This is ok, but no LDAP
+    groups will be mapped to Drupal roles."), "warning");
+  }
+
+  elseif (trim($values['ldapgroups_role_mappings']) && ! $values['ldapgroups_use_group_filter']) {
+    drupal_set_message(t("&quot;" . $form['role_filtering']['ldapgroups_use_group_filter']['#title'] .
+    "&quot; was not checked, but LDAP Groups to Drupal Role are listed.  This is ok, but no LDAP
+    groups will be mapped to Drupal roles."), "warning");
+  }
+
+  if ($bad_mapping_syntax) {
+    form_set_error('ldapgroups_role_mappings', t('Mapping of LDAP Groups to Drupal Roles should be
+    of the form:  [group]|[drupal role]'));
+  }
+
 }
 
Index: ldap_integration/ldapgroups.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ldap_integration/ldapgroups.install,v
retrieving revision 1.1.4.7
diff -u -p -r1.1.4.7 ldapgroups.install
--- ldap_integration/ldapgroups.install	5 Oct 2008 18:46:47 -0000	1.1.4.7
+++ ldap_integration/ldapgroups.install	29 Oct 2008 19:27:42 -0000
@@ -49,7 +49,29 @@ function ldapgroups_install() {
     'type' => 'varchar',
     'length' => 255,
   ));
+  db_add_field($ret, 'ldapauth', 'ldapgroups_use_group_filter', array(
+    'type' => 'int',
+    'size' => 'tiny',
+    'not null' => TRUE,
+    'default' => '0',
+  ));
+  db_add_field($ret, 'ldapauth', 'ldapgroups_role_mappings',  array(
+    'type' => 'text',
+    'not null' => FALSE,
+    'default' => '',
+  ));
+  db_add_field($ret, 'ldapauth', 'ldapgroups_role_filtering_php',  array(
+    'type' => 'text',
+    'not null' => FALSE,
+    'default' => '',
+  ));
+    db_add_field($ret, 'ldapauth', 'ldapgroups_roles_granted_accts',  array(
+    'type' => 'text',
+    'not null' => FALSE,
+    'default' => '',
+  ));
 
+  variable_set('ldapgroups_roles_granted_accts', FALSE);
   return $ret;
 }
 
@@ -57,7 +79,8 @@ function ldapgroups_install() {
  * Implementation of hook_uninstall().
  */
 function ldapgroups_uninstall() {
-  // We're removing fileds from an existing table, not deleting a whole one.
+  // We're removing fields from an existing table, not deleting a whole one.
+  // ...the table is used by other ldap modules
   $ret = array();
 
   db_drop_field($ret, 'ldapauth', 'ldapgroups_in_dn');
@@ -67,7 +90,120 @@ function ldapgroups_uninstall() {
   db_drop_field($ret, 'ldapauth', 'ldapgroups_as_entries');
   db_drop_field($ret, 'ldapauth', 'ldapgroups_entries');
   db_drop_field($ret, 'ldapauth', 'ldapgroups_entries_attribute');
+  db_drop_field($ret, 'ldapauth', 'ldapgroups_use_group_filter');
+  db_drop_field($ret, 'ldapauth', 'ldapgroups_role_mappings');
+  db_drop_field($ret, 'ldapauth', 'ldapgroups_role_filtering_php');
+  db_drop_field($ret, 'ldapauth', 'ldapgroups_roles_granted_accts');
 
+  variable_del('ldapgroups_roles_granted_accts');
+  variable_del('ldapgroups_groups_wo_ldapauth');
+  variable_del('ldapgroups_groups_wo_ldapauth_sid');
+
+  return $ret;
+}
+
+
+/**
+ * Implementation of hook_update().
+ */
+function ldapgroups_update_6100() {
+  // add db fields if they do not exist.
+
+  $message = '<p>With this LDAP Groups upgrade, LDAP group to Drupal role mappings are now
+  configured via the LDAP Groups web interface.</p>';
+
+
+  $ret = array();
+  $dbnewcolumns = FALSE;
+
+  if (! db_column_exists('ldapauth', 'ldapgroups_use_group_filter')) {
+    $dbnewcolumns = TRUE;
+    db_add_field($ret, 'ldapauth', 'ldapgroups_use_group_filter', array(
+      'type' => 'int',
+      'size' => 'tiny',
+      'not null' => TRUE,
+      'default' => '0',
+    ));
+  }
+
+  if (! db_column_exists('ldapauth', 'ldapgroups_role_mappings')) {
+    $dbnewcolumns = TRUE;
+    db_add_field($ret, 'ldapauth', 'ldapgroups_role_mappings',  array(
+      'type' => 'text',
+      'not null' => FALSE,
+      'default' => '',
+    ));
+  }
+
+  if (! db_column_exists('ldapauth', 'ldapgroups_role_filtering_php')) {
+    $dbnewcolumns = TRUE;
+    db_add_field($ret, 'ldapauth', 'ldapgroups_role_filtering_php',  array(
+      'type' => 'text',
+      'not null' => FALSE,
+      'default' => '',
+    ));
+  }
+
+  if (! db_column_exists('ldapauth', 'ldapgroups_roles_granted_accts')) {
+    $dbnewcolumns = TRUE;
+    db_add_field($ret, 'ldapauth', 'ldapgroups_roles_granted_accts',  array(
+      'type' => 'text',
+      'not null' => FALSE,
+      'default' => '',
+    ));
+  }
+
+
+
+
+
+
+  /* If the old  /ldap_integration/ldapgroups.conf.php files exists and ldapgroups_roles_filter
+   function is not commented out, import the mapping data into
+   the new db fields for it.  Previously whether or not the function ldapgroups_roles_filter
+   was commented out or not determined if mapping was used and mappings were applied to all sites
+   on a multisite install for all LDAP instances.  During update, role mappings are put into
+   all LDAP instances (The update SQL has no WHERE clause).
+  */
+  if ($dbnewcolumns) {
+    if (file_exists(drupal_get_path('module', 'ldapauth') .'/ldap_integration/ldapgroups.conf.php')) {
+      require_once(drupal_get_path('module', 'ldapauth') .'/ldap_integration/ldapgroups.conf.php');
+      if (function_exists('ldapgroups_role_mappings') && function_exists('ldapgroups_roles_filter')) {
+        $mappings = ldapgroups_role_mappings();
+        if (count($mappings) > 0) {
+          $result = db_query("UPDATE {ldapauth} SET  ldapgroups_use_group_filter = 1, ldapgroups_role_mappings = '%s'", serialize($mappings), TRUE);
+          $ret[] = array('success' => $result !== FALSE, 'query' => "UPDATE ldapauth SET  ldapgroups_use_group_filter = 1, ldapgroups_role_mappings = serialized mappings array" );
+          $message_groups = "<p>The following LDAP group to Drupal roles were read from the
+          <code>ldap_integration/ldapgroups.conf.php</code> file and configured for this site.
+          When you have updated all sites on this Drupal install that use LDAP groups mappings,
+          you may remove the <code>ldap_integration/ldapgroups.conf.php</code> file.</p>";
+
+          $message_groups .= "<ul>";
+          foreach ($mappings as $_ldap_group => $_drupal_role) {
+            $message_groups .= "<li>$_ldap_group : $_drupal_role  </li>";
+          }
+          $message_groups .= "<ul>";
+
+        }
+      }
+    }
+  }
+
+  if ($message_groups) {
+    $message .= $message_groups;
+  }
+  else { // if mappings were not imported from /ldap_integration/ldapgroups.conf.php, let admin know they need to add them
+    $message .= '<em>No LDAP group to Drupal role mappings were imported.</em>
+      If you did not use the <code>ldap_integration/ldapgroups.conf.php</code> file
+      for mappings this is the desired behavior.
+      If you used <code>ldap_integration/ldapgroups.conf.php</code>, those mappings will
+      need to be added via the LDAP Groups web interface.
+      <br/>You will need to edit your mappings for <strong>each LDAP configuration</strong>
+      on <strong>each site</strong>.';
+  }
+
+  drupal_set_message(t($message), 'warning');
   return $ret;
 }
 
+
Index: ldap_integration/ldapgroups.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/ldap_integration/ldapgroups.module,v
retrieving revision 1.24.2.10
diff -u -p -r1.24.2.10 ldapgroups.module
--- ldap_integration/ldapgroups.module	5 Oct 2008 18:46:47 -0000	1.24.2.10
+++ ldap_integration/ldapgroups.module	29 Oct 2008 19:27:42 -0000
@@ -6,21 +6,14 @@
  * ldapgroups integrates ldap groups with drupal roles.
  */
 
-//////////////////////////////////////////////////////////////////////////////
 
-define('LDAPGROUPS_DEFAULT_DN_ATTRIBUTE',      'ou');
-define('LDAPGROUPS_DEFAULT_ENTRIES_ATTRIBUTE', 'memberUid');
+/**
+ * TRUE signifies LDAP authentication is not being used.
+ */
+define('LDAPGROUPS_GROUPS_WO_LDAPAUTH',   variable_get('ldapgroups_groups_wo_ldapauth', FALSE));
 
-//////////////////////////////////////////////////////////////////////////////
 // Core API hooks
 
-/**
- * Implements hook_init().
- */
-function ldapgroups_init() {
-  include_once(drupal_get_path('module', 'ldapgroups') .'/ldap_integration/ldapgroups.conf.php');
-  require_once(drupal_get_path('module', 'ldapgroups') .'/ldap_integration/LDAPInterface.php');
-}
 
 /**
  * Implementation of hook_menu().
@@ -44,6 +37,16 @@ function ldapgroups_menu() {
     'access arguments' => array('administer ldap modules'),
     'file' => 'ldapgroups.admin.inc',
   );
+  $items['admin/settings/ldap/ldapgroups/woauth/edit'] = array(
+    'title' => 'Use LDAP Groups without LDAP Auth',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('ldapgroups_wo_ldapauth_edit', 5),
+    'type' => MENU_CALLBACK,
+    'weight' => 1,
+    'access arguments' => array('administer ldap modules'),
+    'file' => 'ldapgroups.admin.inc',
+  );
+
   $items['admin/settings/ldap/ldapgroups/reset'] = array(
     'title' => 'Groups',
     'page callback' => 'drupal_get_form',
@@ -60,6 +63,7 @@ function ldapgroups_menu() {
  * Implements hook_user().
  */
 function ldapgroups_user($op, &$edit, &$account, $category = NULL) {
+
   switch ($op) {
     case 'login':
       ldapgroups_user_login($account);
@@ -74,228 +78,29 @@ function ldapgroups_user($op, &$edit, &$
  * Implements hook_user() login operation.
  */
 function ldapgroups_user_login(&$account) {
-  $authmap = user_get_authmaps($account->name);
-  if (!isset($authmap['ldapauth'])) {
-    // This user is not authenticated via lapauth.
-    return TRUE;
-  }
-
-  // Setup the global $_ldapgroups_ldap object.
-  if (!_ldapgroups_ldap_init($account))
-    return;
-
-  // First, we take every mapped role from the user, later below
-  // we'll grant back those deserved.
-  $account->ldap_drupal_roles = isset($account->ldap_drupal_roles) ? $account->ldap_drupal_roles : array();
-  foreach ($account->ldap_drupal_roles as $role) {
-    _ldapgroups_deny_role($account, $role);
-  }
-
-  // Then, we figure out the appropriate groups.
-  $groups = _ldapgroups_detect_groups($account);
-  if ($groups === FALSE) {
-    // Oh, this means this user didn't even have to be here. Bye!
-    return TRUE;
-  }
-
-  // Next, we apply site-specific rules.
-  $roles = function_exists('ldapgroups_roles_filter') ? ldapgroups_roles_filter($groups) : $groups;
-
-  // At this point, the roles are in the full DN format.
-  // Turn them in into friendly names.
-
-  // Finally, we grant the roles.
-  // Need to check for empty roles.
-  if (!empty($roles)) {
-    $ldapgroups_role_mappings = ldapgroups_role_mappings();
-    foreach ($roles as $role) {
-      if (isset($ldapgroups_role_mappings[$role])) {
-        $friendly_role = $ldapgroups_role_mappings[$role];
-      }
-      else if (preg_match('/^[^=]*=([^,]*),.*$/', $role, $matches)) {
-        $friendly_role = $matches[1];
-      }
-      else {
-        $friendly_role = $role;
-      }
-      _ldapgroups_create_role($friendly_role);
-      _ldapgroups_grant_role($account, $friendly_role);
-    }
-  }
-
-  // Store roles in the user object so we know which ones
-  // were granted here.
-  user_save($account, array('ldap_drupal_roles' => $roles));
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Auxiliary functions
-
-/**
- * Detect user groups from the LDAP.
- *
- * @param $user
- *   A user object.
- *
- * @return
- *   An array of user groups.
- */
-function _ldapgroups_detect_groups($user) {
-  global $_ldapgroups_ldap;
-
-  // Nothing to do if the user is not LDAP authentified
-  // or there are no groups configured.
-
-  $row = db_fetch_object(db_query("SELECT ldapgroups_in_dn, ldapgroups_in_attr, ldapgroups_as_entries, ldapgroups_dn_attribute, ldapgroups_attr, ldapgroups_entries, ldapgroups_entries_attribute FROM {ldapauth} WHERE sid = %d", $_ldapgroups_ldap->getOption('sid')));
-  $groups_in_dn = $row->ldapgroups_in_dn;
-  $groups_in_attr = $row->ldapgroups_in_attr;
-  $groups_as_entries = $row->ldapgroups_as_entries;
-
-  $group_dn_attribute = $row->ldapgroups_dn_attribute ? $row->ldapgroups_dn_attribute : LDAPGROUPS_DEFAULT_DN_ATTRIBUTE;
-  $group_attr = $row->ldapgroups_attr;
-  $group_entries = $row->ldapgroups_entries ? $row->ldapgroups_entries : '';
-
-  if (!($groups_in_dn || $groups_in_attr || $groups_as_entries))
-    return FALSE;
-
-  // First try to connect with the stored user's DN and password.
-  // If unsuccessful, connect with the BINDDN and BINDPW stored in the database for this config.
-  $dn = isset($_SESSION['ldap_login']['dn']) ? $_SESSION['ldap_login']['dn'] : '';
-  $pass = isset($_SESSION['ldap_login']['pass']) ? $_SESSION['ldap_login']['pass'] : '';
-
-  // If I try to connect using a blank dn and pass, I dont get an error until ldap_read,
-  // so I just check to see if they would be blank, based on ldap_forget_passwords, and
-  // make it read from the database.
-  if (LDAPAUTH_FORGET_PASSWORDS || !$_ldapgroups_ldap->connect($dn, $pass)) {
-    $row2 = db_fetch_object(db_query("SELECT binddn, bindpw FROM {ldapauth} WHERE sid = %d", $_ldapgroups_ldap->getOption('sid')));
-    $dn = $row2->binddn;
-    $pass = $row2->bindpw;
-    if (!$_ldapgroups_ldap->connect($dn, $pass)) {
-      watchdog('ldapgroups', "User login: user %name data could not be read in the LDAP directory", array('%name' => $user->name), WATCHDOG_WARNING);
-      return FALSE;
-    }
-  }
 
-  // Strategy 1: group extracted from user's DN.
-  $dn_groups = array();
-  if ($groups_in_dn && $dn_group_attr = $group_dn_attribute) {
-    $pairs = explode(',', $user->ldap_dn);
-    foreach ($pairs as $p) {
-      $pair = explode('=', $p);
-      if (trim($pair[0]) == $dn_group_attr) {
-        $dn_groups[] = trim($pair[1]);
-      }
-    }
-  }
+  if (! LDAPGROUPS_GROUPS_WO_LDAPAUTH ) {
+    $authmap = user_get_authmaps($account->name);
 
-  // Strategy 2: groups in user attributes.
-  $attrib_groups = array();
-  if ($groups_in_attr && $attributes = $group_attr) {
-    $attributes_array = explode("\r\n", $attributes);
-    foreach ($attributes_array as $attribute) {
-      $tmp = $_ldapgroups_ldap->retrieveMultiAttribute($user->ldap_dn, $attribute);
-      $attrib_groups = array_merge($attrib_groups, $tmp);
+    if (!isset($authmap['ldapauth'])) {
+      // This user is not authenticated via lapauth.
+      return TRUE;
     }
+    if (! $account->ldap_config) return;
   }
 
-  // Strategy 3: groups as entries.
-  $entries_groups = array();
-  if ($groups_as_entries && $branches = $group_entries) {
-    $branches_array = explode("\r\n", $branches);
-    $group_attr = ($row->ldapgroups_entries_attribute ? $row->ldapgroups_entries_attribute : LDAPGROUPS_DEFAULT_ENTRIES_ATTRIBUTE);
-    foreach ($branches_array as $branch) {
-      $entries = $_ldapgroups_ldap->search($branch, "$group_attr=$user->ldap_dn", array($group_attr));
-      if ($entries['count'] == 0) {
-        $entries = $_ldapgroups_ldap->search($branch,  "$group_attr=$user->name", array($group_attr));
-      }
-      foreach ($entries as $entry) {
-        if (isset($entry['dn'])) {
-          $entries_groups[] = $entry['dn'];
-        }
-      }
-    }
-  }
+  require_once(drupal_get_path('module', 'ldapgroups') .'/ldapgroupconf.class.php');
 
-  $_ldapgroups_ldap->disconnect();
-  return array_merge($dn_groups, $attrib_groups, $entries_groups);
-}
+  $ldapgroupconf = new LDAPGroupConf($account);
 
-/**
- * Grant a user with a role.
- *
- * @param $user
- *   A user object.
- * @param $rolename
- *   A name of the role.
- *
- * @return
- */
-function _ldapgroups_grant_role($user, $rolename) {
-  $result = db_query("SELECT * FROM {role} WHERE name = '%s'", $rolename);
-  if ($row = db_fetch_object($result)) {
-    $result = db_query("SELECT * FROM {users_roles} WHERE uid = %d AND rid = %d", $user->uid, $row->rid);
-    if (!db_fetch_object($result)) {
-      db_query("INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)", $user->uid, $row->rid);
-    }
-  }
-}
+  $ldap_granted_rolenames = $ldapgroupconf->get_ldap_granted_rolenames();
 
-/**
- * Deny a user with a role.
- *
- * @param $user
- *   A user object.
- * @param $rolename
- *   A name of the role.
- *
- * @return
- */
-function _ldapgroups_deny_role($user, $rolename) {
-  $result = db_query("SELECT * FROM {role} WHERE name = '%s'", $rolename);
-  if ($row = db_fetch_object($result)) {
-    $result = db_query("SELECT * FROM {users_roles} WHERE uid = %d AND rid = %d", $user->uid, $row->rid);
-    if (db_fetch_object($result)) {
-      db_query("DELETE FROM {users_roles} WHERE uid = %d AND rid = %d", $user->uid, $row->rid);
-    }
+  if (!($ldap_granted_rolenames === FALSE)) {
+    // deny, grant, and create roles based on LDAP granted roles and past LDAP granted roles
+    $ldapgroupconf->reconcile_ldap_roles($ldap_granted_rolenames);
   }
 }
 
-/**
- * Create a new role.
- *
- * @param $rolename
- *   A name of the role.
- *
- * @return
- */
-function _ldapgroups_create_role($rolename) {
-  $result = db_query("SELECT * FROM {role} WHERE name = '%s'", $rolename);
-  if (!($row = db_fetch_object($result)))
-    db_query("INSERT INTO {role} (name) VALUES ('%s')", $rolename);
-}
 
-/**
- * Initiates the LDAPInterfase class.
- *
- * @param $sid
- *   An ID of the LDAP server configuration.
- *
- * @return
- */
-function _ldapgroups_ldap_init(&$user) {
-  global $_ldapgroups_ldap;
 
-  if ($row = db_fetch_object(db_query("SELECT * FROM {ldapauth} WHERE status = '1' AND sid = %d", $user->ldap_config))) {
-    $_ldapgroups_ldap = new LDAPInterface();
-    $_ldapgroups_ldap->setOption('sid', $row->sid);
-    $_ldapgroups_ldap->setOption('name', $row->name);
-    $_ldapgroups_ldap->setOption('server', $row->server);
-    $_ldapgroups_ldap->setOption('port', $row->port);
-    $_ldapgroups_ldap->setOption('tls', $row->tls);
-    $_ldapgroups_ldap->setOption('encrypted', $row->encrypted);
-    $_ldapgroups_ldap->setOption('basedn', $row->basedn);
-    $_ldapgroups_ldap->setOption('user_attr', $row->user_attr);
-    return $_ldapgroups_ldap;
-  }
-}
 
