--- civimember_roles.module	2008-02-03 17:38:51.000000000 -0600
+++ civimember_roles.module.2	2008-02-05 12:14:45.000000000 -0600
@@ -1,5 +1,5 @@
 <?php
-// $Id: civimember_roles.module,v 1.1.2.3 2008/02/03 23:38:51 posco Exp $
+// $Id: civimember_roles.module,v 1.1.2.7 2008/02/05 18:14:08 posco Exp $
 
 /**
  * @file
@@ -58,7 +58,7 @@ function civimember_roles_menu($may_cach
   if (variable_get('civimember_roles_sync_method', 0) == 1) {
     global $user;
     if (in_array('authenticated user', $user->roles)) {
-      _civimember_roles_sync($user->mail);
+      _civimember_roles_sync($user->uid);
     }
   }
   
@@ -78,7 +78,7 @@ function civimember_roles_perm() {
 function civimember_roles_user($op, &$edit, &$account) {
   if (variable_get('civimember_roles_sync_method', 0) == 0) {
     if ($op == 'login' || $op == 'logout') {
-      _civimember_roles_sync($account->mail);
+      _civimember_roles_sync($account->uid);
     }
   }
 }
@@ -88,7 +88,7 @@ function civimember_roles_user($op, &$ed
  */
 function civimember_roles_cron() {
   if (variable_get('civimember_roles_sync_method', 0) == 2) {
-    civicrm_initialize(true);
+    civicrm_initialize(TRUE);
     _civimember_roles_sync();
   }
 }
@@ -101,7 +101,7 @@ function civimember_roles_show_rules($ac
   //Delete rule
   if ($action == 'delete') {
     if (is_numeric($id)) {
-      $delete = db_query('DELETE FROM {civimember_roles_rules} WHERE rule_id = \'%d\'', $id);
+      $delete = db_query('DELETE FROM {civimember_roles_rules} WHERE rule_id = %d', $id);
       
       if ($delete) {
         drupal_set_message(t('Rule ID %id was successfully deleted.', array('%id' => $id)));
@@ -179,7 +179,8 @@ function civimember_roles_manual_sync() 
 function civimember_roles_manual_sync_submit($form_id, $form_values) {
   if (_civimember_roles_sync()) {
     drupal_set_message(t('CiviMember Memberships and Drupal Roles have been synchronized using available rules. Note: if no association rules exist then synchronization has not been completed.'));
-  } else {
+  } 
+  else {
     drupal_set_message(t('There was an error. CiviMember Memberships and Drupal Roles could not be synchronized.'), $type = 'error');
   }
 }
@@ -374,10 +375,15 @@ function civimember_roles_add_rule_form_
 }
 
 /**
- * Finds members and applies roles based on the rules defined in the settings page. If the email param is defined then
+ * Finds members and applies roles based on the rules defined in the settings page. If the ext_uid param is defined then
  * this function will only sync one user.
  */
-function _civimember_roles_sync($email = NULL) {    
+function _civimember_roles_sync($ext_uid = NULL) {    
+  
+  //Bring in CRM_Core_BAO_UFMatch class so we can find Drupal UIDs
+  global $civicrm_root;
+  require_once $civicrm_root . '/CRM/Core/BAO/UFMatch.php';
+  
   $rules = db_query('SELECT * FROM {civimember_roles_rules}');
   
   //Error check
@@ -389,7 +395,7 @@ function _civimember_roles_sync($email =
     $codes = unserialize($result->status_codes);
         
     //CiviCRM query
-    $memberships = 'SELECT status_id, email FROM civicrm_membership cm
+    $memberships = 'SELECT cc.id, status_id FROM civicrm_membership cm
                     LEFT JOIN civicrm_contact cc ON cm.contact_id = cc.id 
                     LEFT JOIN civicrm_location cl ON cc.id = cl.entity_id 
                     LEFT JOIN civicrm_email ce ON cl.id = ce.location_id 
@@ -404,24 +410,41 @@ function _civimember_roles_sync($email =
       2 => array(CIVICRM_DOMAIN_ID, 'Integer')
     );
         
-    if (!empty($email)) {
-      $memberships .= ' AND email = %3';
-      $params[3] = array($email, 'String');
+    if (!empty($ext_uid)) {
+      //Let's get the UID's Contact ID so we only grab one record from the CiviCRM DB.
+      $cid = CRM_Core_BAO_UFMatch::getContactId($ext_uid);
+
+      if(!empty($cid)) {
+        $memberships .= ' AND cc.id = %3';
+        $params[3] = array((int) $cid, 'Integer');
+      }
+      else {
+        watchdog('civimember_roles', t('The uid: %uid did not have a CiviCRM Contact ID.', array('%uid' => (int) $ext_uid)), WATCHDOG_ERROR);
+        return FALSE;
+      }
     }
 
     $dao =& CRM_Core_DAO::executeQuery($memberships, $params);
-        
-    //If the record has the correct status, set up the Drupal user to either have a role added or removed
+
     $add_accounts = array();
     $remove_accounts = array();
     while ($dao->fetch()) {
-      $uid = db_result(db_query('SELECT uid FROM {users} WHERE mail = \'%s\'', $dao->email));
       
-      if (in_array($dao->status_id, $codes['current'])) {
-        $add_accounts[] = $uid;
-      }
-      elseif (in_array($dao->status_id, $codes['expired'])) {
-        $remove_accounts[] = $uid;
+      //Lets get the Drupal UID based on CiviCRM Contact ID
+      $uid = CRM_Core_BAO_UFMatch::getUFId($dao->id);
+      
+      /* We silently don't add the UID if it doesn't exist so we don't force that a Drupal user exists
+       * for each CiviCRM contact.
+       */
+      if (!empty($uid)) {
+        
+        //If the record has the correct status, set up the Drupal user to either have a role added or removed
+        if (in_array($dao->status_id, $codes['current'])) {
+          $add_accounts[] = (int) $uid;
+        }
+        elseif (in_array($dao->status_id, $codes['expired'])) {
+          $remove_accounts[] = (int) $uid;
+        }
       }
     }
     
@@ -430,9 +453,22 @@ function _civimember_roles_sync($email =
     //Error check.
     if(is_numeric($result->rid)) {
       
+      /* Now we are going to give the current user temp user 1 status (superuser) so they can edit roles.
+       * We turn session saving off to prevent permission escalation in case there is a problem loading
+       * the page.
+       */
+      global $user;
+      $current_user = $user->uid;
+      session_save_session(FALSE);
+      $user = user_load(array('uid' => 1));
+      
       //Apply roles.
       user_multiple_role_edit($add_accounts, 'add_role', $result->rid);
       user_multiple_role_edit($remove_accounts, 'remove_role', $result->rid);
+      
+      //Now we restore the current user and renable session saving.
+      $user = user_load(array('uid' => $current_user));
+      session_save_session(TRUE);
     } 
     else {
       return FALSE;
