diff -urp salesforce_orig/includes/salesforce.php salesforce/includes/salesforce.php
--- salesforce_orig/includes/salesforce.php	2007-05-04 04:09:05.000000000 -0500
+++ salesforce/includes/salesforce.php	2008-01-18 16:39:09.000000000 -0600
@@ -129,7 +129,8 @@ class salesforce {
      * @access public
      */
     function setURL($url){
-        $this->client->forceEndpoint = str_replace("https", "http", $url);
+        //$this->client->forceEndpoint = str_replace("https", "http", $url);
+				$this->client->forceEndpoint = $url;
     }
     
     /**
diff -urp salesforce_orig/includes/salesforce_api.inc salesforce/includes/salesforce_api.inc
--- salesforce_orig/includes/salesforce_api.inc	2007-11-09 17:47:16.000000000 -0600
+++ salesforce/includes/salesforce_api.inc	2008-01-17 14:36:20.000000000 -0600
@@ -12,7 +12,11 @@
  *  salesforce include + connecting via SOAP
  */
 function salesforce($login_return = false) {
-  static $included;
+  static $included, $salesforce;
+
+	if ($salesforce && !$login_return) {
+		return $salesforce;
+	}
 
   $admin = user_access('administer salesforce');
 
@@ -70,15 +74,22 @@ function salesforce_contact($op, $accoun
 
   switch ($op) {
     case 'insert': case 'update':
-      $contact = new sObject('Contact', null,
-      array(
-      'Company' => $account->company,
+
+			$fields = array(
       'FirstName' => $account->first_name,
       'LastName' => $account->last_name,
       'Phone' => $account->phone,
       'Fax' => $account->fax,
       'Email' => $account->mail,
-      ));
+      );
+
+			$fields = _sf_profile_fields_put($fields, $account);
+
+			if (!variable_get('salesforce_contact_sync', 0) && !variable_get('salesforce_lead_sync', 0)) {
+				$fields['Company'] = $account->company;
+			}
+			
+      $contact = new sObject('Contact', null, $fields);
 
       // add any additional params to the contact object
       foreach ($params as $param => $param_value) {
@@ -126,7 +137,7 @@ function salesforce_contact($op, $accoun
 
         if ($result['success'] == 'true') {
           if ($admin) {
-            drupal_set_message(t('updated contact in salesforce for the user <strong>@user</strong>', array('@user' => "$account->first_name $account->last_name")));
+            drupal_set_message(t('updated contact information in salesforce for the user <strong>@user</strong>', array('@user' => "$account->first_name $account->last_name")));
             return array('status' => 'updated');
           }
         } else {
@@ -147,6 +158,41 @@ function salesforce_contact($op, $accoun
         return array('error' => $error);
       }
       break;
+
+			case 'insert from remote':
+				// New user is being created from new contact on salesforce
+				db_query('DELETE FROM {salesforce_users} WHERE uid=%d', $account->uid);
+				db_query('INSERT INTO {salesforce_users} (uid,contact_id,account_id,created) VALUES (%d,"%s","%s", %d)', $account->uid, $account->contact_id, $account->account_id, time());
+				break;
+			
+			case 'update from remote':
+				// Information was updated in salesforce, we need to mirror it locally, called by cron.php
+				$profile_fields = _sf_get_profile_field_info();
+				
+				$contact = salesforce_contact_select($account, array_merge(array('FirstName','LastName','Phone','Fax','Email'), $profile_fields));
+				
+				if ($account->mail != $contact['Email'] ) {
+					user_save($account, array('mail' => $contact['Email'], 'status' => $status, 'update_from_salesforce' => TRUE));
+				}
+				
+				$fields = array(
+					'first_name' => $contact['FirstName'],
+					'last_name' => $contact['LastName'],
+					'phone' => $contact['Phone'],
+					'fax' => $contact['Fax'],
+					'update_from_salesforce' => TRUE
+				);
+				
+				$fields = _sf_profile_fields_get($fields, $profile_fields, $contact);
+				
+				if (!variable_get('salesforce_contact_sync', 0) && !variable_get('salesforce_lead_sync', 0)) {
+					$fields['company'] = $account->company;
+				}
+				
+				user_save($account, $fields, 'Personal Information');
+				break;
+
+
   }
 }
 
@@ -154,7 +200,7 @@ function salesforce_contact($op, $accoun
  *  handle leads in salesforce
  */
 function salesforce_lead($op, $account, $params = array()) {
-  // grab a salesforce api connection
+  // create a salesforce api client
   $salesforce = salesforce();
 
   // avoid fatal error on salesforce query with null element in query
@@ -168,15 +214,21 @@ function salesforce_lead($op, $account, 
   switch ($op) {
     case 'insert': case 'update': default:
       // create the main salesforce object
-      $lead = new sObject('Lead', null,
-      array(
-      'Company' => $account->company,
+			$fields = array(
       'FirstName' => $account->first_name,
       'LastName' => $account->last_name,
       'Phone' => $account->phone,
       'Fax' => $account->fax,
       'Email' => $account->mail,
-      ));
+      );
+
+			$fields = _sf_profile_fields_put($fields, $account);
+
+			if (!variable_get('salesforce_contact_sync', 0) && !variable_get('salesforce_lead_sync', 0)) {
+				$fields['Company'] = $account->company;
+			}
+
+      $lead = new sObject('Lead', null, $fields);
 
       // add any additional params to the lead object
       foreach ($params as $param => $param_value) {
@@ -255,6 +307,47 @@ function salesforce_lead($op, $account, 
         return array('error' => $error);
       }
       break;
+
+			// New user is being created from new lead on salesforce
+			case 'insert from remote':
+				db_query('DELETE FROM {salesforce_users} WHERE uid=%d', $account->uid);
+				db_query('INSERT INTO {salesforce_users} (uid,lead_id,account_id,created) VALUES (%d,"%s","%s",%d)', $account->uid, $account->lead_id, $account->account_id, time());
+				break;
+				
+			// Information was updated in salesforce, we need to mirror it locally, called by cron.php
+			case 'update from remote':
+				$profile_fields = _sf_get_profile_field_info();
+				
+				$lead = salesforce_lead_select($account,array_merge(array('FirstName','LastName','Phone','Fax','Email','IsConverted','ConvertedAccountId','ConvertedContactId'),$profile_fields));
+				// Otherwise we can update their profile, status, etc. as needed.
+				$status = variable_get('salesforce_lead_account_status', 0);
+				// Has this Lead been converted to a Contact?
+				if ($lead['IsConverted'] == 'true') {
+					$status = 1;
+					db_query('UPDATE {salesforce_users} SET lead_id="", contact_id="%s", account_id="%s" WHERE uid=%d', $lead['ConvertedContactId'], $lead['ConvertedAcountId'], $account->uid);
+				}
+			
+				if ($account->mail != $lead['Email'] ) {
+					user_save($account, array('mail' => $lead['Email'], 'status' => $status, 'update_from_salesforce' => TRUE));
+				}
+				
+				$fields = array(
+					'first_name' => $lead['FirstName'],
+					'last_name' => $lead['LastName'],
+					'phone' => $lead['Phone'],
+					'fax' => $lead['Fax'],
+					'update_from_salesforce' => TRUE
+				);
+				
+				$fields = _sf_profile_fields_get($fields, $profile_fields, $contact);
+				
+				if (!variable_get('salesforce_contact_sync', 0) && !variable_get('salesforce_lead_sync', 0)) {
+					$fields['company'] = $account->company;
+				}
+				
+				user_save($account, $fields, 'Personal Information');
+				break;
+
   }
 }
 
@@ -284,7 +377,7 @@ function salesforce_event($op, $subject,
       $event = new sObject('Event', NULL, array(
       'WhoId' => $id,
       $activityDate,
-      'Subject' => t('%subject - %date', array('%subject' => $subject, '%date' => format_date(time(), 'large'))),
+      'Subject' => t('@subject - @date', array('@subject' => $subject, '@date' => format_date(time(), 'large'))),
       'Description' => $message,
       'DurationInMinutes' => 1,
       ));
@@ -329,27 +422,60 @@ function salesforce_event($op, $subject,
 /**
  *  select from the salesforce contact table
  */
-function salesforce_account_select($account = NULL, $params = array(), $cache = true) {
+function salesforce_contact_select($account = NULL, $params = array(), $cache = true) {
   $salesforce = salesforce();
   $account = _salesforce_select_account($account);
 
   // make sure we're dealing with a contact
   if (!$account->salesforce['contact_id']) return array('error' => 'NO_CONTACT_ID');
 
-  $defaults = array('accountId');
+  $defaults = array('Id','AccountId');
   $params = array_merge($defaults, $params);
-  // query salesforce for the contact's account_id
-  $contact = $salesforce->query("SELECT ". implode(',', $params) ." FROM contact WHERE id = '". $account->salesforce['contact_id'] ."'");
-  $id = $contact['records']->values['AccountId'];
+
+  // is there any SOQL limiter for selecting contacts?
+	if ( $limiter = variable_get('salesforce_contact_soql_limiter', '') ) {
+		$limiter = ' AND ( '. trim($limiter) .')';
+	}
+
+	// query salesforce
+  $contact = $salesforce->query("SELECT ". implode(',', $params) ." FROM contact WHERE Id = '". $account->salesforce['contact_id'] ."'". $limiter);
+
+  $id = $contact['records']->id;
   if ($id) {
     if ($cache) {
-      _salesforce_insert('account_id', $id, $account);
+      _salesforce_insert('account_id', $contact['records']->values['AccountId'], $account);
     }
+		// add the Id to the returned value
+		$contact['records']->values['Id'] = $id;
     return $contact['records']->values;
   }
 }
 
 /**
+ * Select from the salesforce lead table
+ */
+function salesforce_lead_select($account = NULL, $params = array(), $cache = true) {
+	$salesforce = salesforce();
+	$account = _salesforce_select_account($account);
+	
+	// make sure we're dealing with a lead
+	if (!$account->salesforce['lead_id']) return array('error' => 'NO_LEAD_ID');
+	
+	$defaults = array('Id');
+	$params = array_merge($defaults,$params);
+
+	$lead = $salesforce->query("SELECT ". implode(',', $params) ." FROM lead WHERE id = '". $account->salesforce['lead_id'] ."'");
+	//$lead = $salesforce->query("SELECT id, FirstName, LastName, Email, Phone, Fax, IsConverted, ConvertedAccountId, ConvertedContactId FROM lead WHERE id = '". $account->salesforce['lead_id'] ."'");
+		
+	if (count($lead['records'])) {
+		// add the Id to the returned value
+		$lead['records']->values['Id'] = $lead['records']->id;
+		return $lead['records']->values;
+	}
+}
+
+
+/**
  *  retreive contract information from an account
  */
 function salesforce_contract_select($account = NULL, $params = array(), $defaults = true) {
@@ -359,7 +485,7 @@ function salesforce_contract_select($acc
 
   // first we need to make sure we have an account_id to work with
   if (!$account->salesforce['account_id']) {
-    $result = salesforce_account_select($account);
+    $result = salesforce_contact_select($account);
     $account->salesforce['account_id'] = $result['AccountId'];
     if (!$account->salesforce['account_id']) return array('error' => 'NO_ACCOUNT_ID_FOUND');
   }
@@ -382,3 +508,83 @@ function salesforce_contract_select($acc
 
   return $contracts;
 }
+
+/**
+ * get a list of all udpated objects of type within specified date range
+ */
+function salesforce_get_updated($type, $startDate, $endDate='') {
+	$salesforce = salesforce();
+	$endDate = ( !$endDate ) ? time() : $endDate;
+	$res = $salesforce->getUpdated($type, gmdate('c',$startDate), gmdate('c',$endDate));
+	
+	$updated = array();
+	if (count($res['ids']) > 1) {
+		foreach($res['ids'] as $id) {
+			$updated[$id] = salesforce_user_load($id);
+		}
+	} else if (count($res)) {
+		$updated[$res['ids']] = salesforce_user_load($res['ids']);
+	}
+	return (count($updated)) ? $updated : false;
+}
+
+/**
+ * Load a user object if their is a user that matches salesforce lead_id, or contact_id
+ *
+ * @param $id
+ *		Salesforce lead or contact id to look up.
+ * @return
+ *		$user object if present, else FALSE
+ */
+function salesforce_user_load($id) {
+	$uid = db_result(db_query('SELECT uid FROM {salesforce_users} WHERE lead_id="%s" OR contact_id="%s"', $id, $id));
+	if ($uid) {
+		return user_load(array('uid' => $uid));
+	} else {
+		return FALSE;
+	}
+}
+
+function _sf_get_profile_field_info() {
+	$res = db_query('SELECT name FROM {profile_fields} WHERE name LIKE "sf_%"');
+	$fields = array();
+	while($row = db_fetch_object($res)) {
+		$fields[$row->name] = substr($row->name,3);
+	}
+	return $fields;
+}
+
+/**
+ * Look up fields with speccial salesforce "sf_" prefix
+ */
+function _sf_profile_fields_put($fields, $account) {
+	$fields = ( count($fields) ) ? $fields : array();
+	// Look for fields with the special sf_ prefix
+	if ($account) {
+		foreach($account as $key => $value) {
+			if (substr($key,0,3) == 'sf_') {
+				// Check for profile date fields
+				if (is_array($value)) {
+					if ($value['year'] && $value['month'] && $value['day']) {
+						$value = new soapval(substr($key,3), 'date', gmdate('c',mktime(0,0,0,$value['day'],$value['month'],$value['year'])));
+					}
+				}
+				// Check for checkbox fields, hardcoded ...
+				if (in_array($key, array('sf_CORN__c'))) {
+					$value = ( $value == 1 ) ? true : false;
+				}
+		
+				$fields[substr($key,3)] = $value;
+			}
+		}
+	}
+	return $fields;
+}
+
+function _sf_profile_fields_get($fields, $profile_fields, $contact) {
+	$fields = ( count($fields) ) ? $fields : array();
+	foreach ($profile_fields as $key => $value) {
+		$fields[$key] = $contact[$value];
+	}
+	return $fields;
+}
\ No newline at end of file
diff -urp salesforce_orig/salesforce.install salesforce/salesforce.install
--- salesforce_orig/salesforce.install	2007-11-03 09:07:40.000000000 -0500
+++ salesforce/salesforce.install	2008-01-17 10:29:20.000000000 -0600
@@ -15,7 +15,7 @@ function salesforce_install() {
       contact_id tinytext NOT NULL,
       opp_id tinytext NOT NULL,
       account_id tinytext NOT NULL,
-      created timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
+      created INT(10),
       PRIMARY KEY  (uid)
       ) ENGINE=MyISAM DEFAULT CHARSET=utf8");      
 
@@ -44,6 +44,21 @@ function salesforce_install() {
         drupal_set_message(t('salesforce.module - logs table did not install'), 'error');
       }
 
+			db_query('CREATE TABLE IF NOT EXISTS {salesforce_sync_log} (
+				id INT NOT NULL AUTO_INCREMENT,
+				type VARCHAR(50),
+				sfid VARCHAR(50),
+				nid INT,
+				created_at INT(10),
+				PRIMARY KEY(id)
+				) ENGINE=MyISAM DEFAULT CHARSET=utf8');
+				
+			if (!db_error()) {
+				drupal_set_message(t('salesforce.module - sync_log table installed successfully'));
+			} else {
+				drupal_set_message(t('salesforce.module - sync_log table did not install'), 'error');
+			}
+
       break;
   }
 
diff -urp salesforce_orig/salesforce.module salesforce/salesforce.module
--- salesforce_orig/salesforce.module	2007-11-12 12:37:19.000000000 -0600
+++ salesforce/salesforce.module	2008-01-17 16:36:41.000000000 -0600
@@ -37,6 +37,22 @@ function salesforce_menu($may_cache) {
     'type' => MENU_NORMAL_ITEM, // optional
     );
 
+	$items[] = array(
+		'path' => 'admin/settings/salesforce/queue_contacts',
+		'title' => t('Import/Update Contacts'),
+		'callback' => 'salesforce_queue_contact_import_overview',
+		'access' => user_access('administer salesforce'),
+		'type' => MENU_NORMAL_ITEM
+		);
+		
+	$items[] = array(
+		'path' => 'admin/settings/salesforce/queue_contacts/do',
+		'title' => t('Import/Update Contacts'),
+		'callback' => 'salesforce_queue_contact_import',
+		'access' => user_access('administer salesforce'),
+		'type' => MENU_CALLBACK
+		);
+
   $items[] = array('path' => 'admin/content/salesforce',
   'title' => t('Salesforce'),
   'access' => user_access('administer salesforce'),
@@ -102,54 +118,109 @@ function salesforce_admin_settings() {
   _salesforce_settings();
 
   $form['salesforce_account'] = array(
-  '#type' => 'fieldset',
-  '#title' => t('SalesForce.com Account'),
-  '#collapsible' => true,
-  '#description' => t('this information is required for this module to work')
-  );
+	  '#type' => 'fieldset',
+	  '#title' => t('SalesForce.com Account'),
+	  '#collapsible' => true,
+	  '#description' => t('this information is required for this module to work'),
+	);
   $form['salesforce_account']['salesforce_user'] = array(
-  '#type' => 'textfield',
-  '#title' => t('Username'),
-  '#default_value' => variable_get('salesforce_user', NULL),
-  '#required' => true
-  );
+	  '#type' => 'textfield',
+	  '#title' => t('Username'),
+	  '#default_value' => variable_get('salesforce_user', NULL),
+	  '#required' => true,
+	 );
 
   // TODO: need to encrypt / decrypt this
   if (!variable_get('salesforce_password', NULL)) {
     $form['salesforce_account']['salesforce_password'] = array(
-    '#type' => 'password',
-    '#title' => t('Password'),
-    '#default_value' => variable_get('salesforce_password', NULL),
-    '#required' => true
-    );
-  } else {
-    $form['salesforce_account']['salesforce_password_delete'] = array(
-    '#prefix' => t('<strong>***** (TODO: setup like this until a better password saving feature can be implemented)</strong>'),
-    '#type' => 'checkbox',
-    '#title' => t('Delete Password'),
-    '#default_value' => variable_get('salesforce_password_delete', false)
-    );
+	    '#type' => 'password',
+	    '#title' => t('Password'),
+	    '#default_value' => variable_get('salesforce_password', NULL),
+	    '#required' => true,
+	   );
   }
+	else {
+    $form['salesforce_account']['salesforce_password_delete'] = array(
+	    '#prefix' => t('<strong>***** (TODO: setup like this until a better password saving feature can be implemented)</strong>'),
+	    '#type' => 'checkbox',
+	    '#title' => t('Delete Password'),
+	    '#default_value' => variable_get('salesforce_password_delete', false),
+	   );
+  }
+
+	$form['salesforce_contact_options'] = array(
+		'#type' => 'fieldset',
+		'#title' => t('Contact Options'),
+		'#collapsible' => true,	
+	);
+	$form['salesforce_contact_options']['salesforce_contact_sync'] = array(
+		'#type' => 'checkbox',
+		'#title' => t('Synchronize contacts in Salesforce'),
+		'#default_value' => variable_get('salesforce_contact_sync', 0),
+		'#description' => t('Allow Drupal to obtain information about Contacts from Salesforce and create Drupal user accounts for those Contacts. Once Drupal knows about a contact if it is updated in Salesforce it will be updated in Drupal.'),
+	);
+	$form['salesforce_contact_options']['salesforce_contact_account_status'] = array(
+		'#type' => 'radios',
+		'#title' => t('Contact default account status'),
+		'#default_value' => variable_get('salesforce_contact_account_status', 0),
+		'#options' => array( 0 => t('Blocked'), 1 => t('Active')),
+		'#description' => t('when creating a new user account from a Salesforce contact the account will be given this status.'),
+	);
+	// Stolen from user.module user_edit_form()
+	$roles = user_roles(1);
+  unset($roles[DRUPAL_AUTHENTICATED_RID]);
+  if ($roles) {
+		$form['salesforce_contact_options']['salesforce_contact_account_roles'] = array(
+			'#type' => 'checkboxes',
+			'#title' => t('Contact default account roles'),
+			'#default_value' => variable_get('salesforce_contact_account_roles',0),
+			'#options' => $roles,
+			'#description' => t('The new user receives the combined permissions of the %au role, and all roles selected here.', array('%au' => t('authenticated user')))
+		);
+	}
+	$form['salesforce_contact_options']['salesforce_contact_soql_limiter'] = array(
+		'#type' => 'textfield',
+		'#title' => t('Limit which contacts can be synced'),
+		'#description' => t('The WHERE portion of the SOQL statement used to select a contact from salesforce. Allows limiting to contacts that meet certian criteria. Enclose strings with single quotes.'),
+		'#default_value' => variable_get('salesforce_contact_soql_limiter', ''),
+	);
+
+  $form['salesforce_lead_options'] = array(
+	  '#type' => 'fieldset',
+	  '#title' => t('Lead Options'),
+	  '#collapsible' => true,
+	 );
+	$form['salesforce_lead_options']['salesforce_lead_sync'] = array(
+		'#type' => 'checkbox',
+		'#title' => t('Synchronize leads in Salesforce'),
+		'#default_value' => variable_get('salesforce_lead_sync', 0),
+		'#description' => t('Allow Drupal to obtain information about Leads from Salesforce and create Drupal user accounts for those Leads. Once Drupal knows about a lead if it is updated in Salesforce it will be updated in Drupal.'),
+	);
+	$form['salesforce_lead_options']['salesforce_lead_account_status'] = array(
+		'#type' => 'radios',
+		'#title' => t('Lead account status'),
+		'#default_value' => variable_get('salesforce_lead_account_status', 0),
+		'#options' => array( 0 => t('Blocked'), 1 => t('Active')),
+		'#description' => t('when creating a new user account from a Salesforce lead the account will be given this status.'),
+	);
 
   $form['salesforce_options'] = array(
-  '#type' => 'fieldset',
-  '#title' => t('Additional Options'),
-  '#collapsible' => true
-  );
-
+	  '#type' => 'fieldset',
+	  '#title' => t('Additional Options'),
+	  '#collapsible' => true,
+	 );
   $form['salesforce_options']['salesforce_leads_create_forms'] = array(
-  '#type' => 'textarea',
-  '#title' => t('Create Leads on form processes'),
-  '#description' => t('a new line for each form_id (drupal 5.0 will make this feature much easier as I will be able to generate a select box with the names of the forms)'),
-  '#default_value' => SALESFORCE_LEADS_CREATE_FORMS
-  );
-
+	  '#type' => 'textarea',
+	  '#title' => t('Create Leads on form processes'),
+	  '#description' => t('a new line for each form_id (drupal 5.0 will make this feature much easier as I will be able to generate a select box with the names of the forms)'),
+	  '#default_value' => SALESFORCE_LEADS_CREATE_FORMS,
+	 );
   $form['salesforce_options']['salesforce_events_create_forms'] = array(
-  '#type' => 'textarea',
-  '#title' => t('Create Events on form processes'),
-  '#description' => t('a new line for each form_id | message (drupal 5.0 will make this feature much easier as I will be able to generate a select box with the names of the forms)'),
-  '#default_value' => SALESFORCE_EVENTS_CREATE_FORMS
-  );
+	  '#type' => 'textarea',
+	  '#title' => t('Create Events on form processes'),
+	  '#description' => t('a new line for each form_id | message (drupal 5.0 will make this feature much easier as I will be able to generate a select box with the names of the forms)'),
+	  '#default_value' => SALESFORCE_EVENTS_CREATE_FORMS,
+	 );
 
 //  4.7 to 5.x conversion:
    //  return $form;
@@ -160,12 +231,114 @@ function salesforce_admin_settings() {
  * Implementation of hook_cron().
  */
 function salesforce_cron() {
+
   $result = db_query("SELECT sid, type, type_id, message, timestamp, status FROM {salesforce_log} WHERE status = 1 ORDER BY timestamp DESC");
   if (db_num_rows($result) > 0) {
     while ($row = db_fetch_object($result)) {
-      _salesforce_cron_run($row);
+    	_salesforce_cron_run($row);
     }
   }
+	
+	/**
+	 * TODO:
+	 * All of this should be put into the salesforce_sync_api.inc file once that becomes part of
+	 * the core module
+	 */
+	
+	$time = time();
+	$salesforce = salesforce();
+	
+	// Check for updated or deleted leads and log them in the sync_log for later processing
+	if (variable_get('salesforce_lead_sync', 0)) {
+		// updated
+		$res = $salesforce->getUpdated('Lead', gmdate('c', variable_get('salesforce_last', time())-600), gmdate('c', time()));
+		if ($res) {
+			foreach((array)$res['ids'] as $id) {
+				db_query('INSERT INTO {salesforce_sync_log} (type,sfid,created_at) VALUES ("%s","%s",%d)',
+					'lead_update', $id, time()
+				);
+			}
+		}
+		unset($res);
+		
+		// deleted
+		$res = $salesforce->getDeleted('Lead', gmdate('c', variable_get('salesforce_last', time())-600), gmdate('c', time()));
+		if ($res) {
+			// returns are in a different format if there is just one
+			if (count($res) == 1) {
+				$tmp = $res['deletedRecords'];
+				$res = array('deletedRecords' => array($tmp));
+			}
+			foreach((array)$res['deletedRecords'] as $record) {
+				echo 'adding delete log - ';
+				db_query('INSERT INTO {salesforce_sync_log} (type,sfid,created_at) VALUES ("%s","%s",%d)',
+					'lead_delete', $record['id'], time()
+				);
+			}
+		}
+		unset($res);
+	}
+	
+	// Check for updated or deleted contacts and log them in the sync_log for later processing
+	if (variable_get('salesforce_contact_sync', 0)) {
+		// updated
+		$res = $salesforce->getUpdated('Contact', gmdate('c', variable_get('salesforce_last', time())-600), gmdate('c', time()));
+		if ($res) {
+			foreach((array)$res['ids'] as $id) {
+				db_query('INSERT INTO {salesforce_sync_log} (type,sfid,created_at) VALUES ("%s","%s",%d)',
+					'contact_update', $id, time()
+				);
+			}
+		}
+		unset($res);
+		
+		// deleted
+		$res = $salesforce->getDeleted('Contact', gmdate('c', variable_get('salesforce_last', time())-600), gmdate('c', time()));
+		if ($res) {
+			// returns are in a different format if there is just one
+			if (count($res) == 1) {
+				$tmp = $res['deletedRecords'];
+				$res = array('deletedRecords' => array($tmp));
+			}
+			foreach((array)$res['deletedRecords'] as $record) {
+				db_query('INSERT INTO {salesforce_sync_log} (type,sfid,created_at) VALUES ("%s","%s",%d)',
+					'contact_delete', $record['id'], time()
+				);
+			}
+		}
+		unset($res);
+	}
+
+	// Then get 10 records from the log, and processes them during this cron run. This is to prevent timing out.
+	$res = db_query('SELECT * FROM {salesforce_sync_log} WHERE type="lead_update" OR type="lead_delete" OR type="contact_update" OR type="contact_delete" LIMIT 10');
+	while ($row = db_fetch_object($res)) {
+		switch($row->type) {
+			case 'lead_update':
+				_salesforce_cron_user_update(array($row->sfid => salesforce_user_load($row->sfid)), 'lead_id');
+				break;
+				
+			case 'lead_delete':
+				$user = salesforce_user_load($row->sfid);
+				user_delete(array(),$user->uid);
+				watchdog('salesforce', t('Deleted user %user because Lead was deleted in Salesforce', $user->name), WATCHDOG_NOTICE);
+				break;
+				
+			case 'contact_update':
+				_salesforce_cron_user_update(array($row->sfid => salesforce_user_load($row->sfid)), 'contact_id');
+				break;
+				
+			case 'contact_delete':
+				$user = salesforce_user_load($row->sfid);
+				db_query('UPDATE {users} SET status=0 WHERE uid=%d', $user->uid);
+				watchdog('salesforce', t('Blocked user because Contact was deleted in Salesforce'), WATCHDOG_NOTICE, url('user/'. $user->uid));
+				break;
+		}
+		db_query('DELETE FROM {salesforce_sync_log} WHERE type="%s" AND sfid="%s"', $row->type, $row->sfid);
+	}
+		
+	// Log current time for next run
+	variable_set('salesforce_last', $time);
+	
 }
 
 /**
@@ -188,26 +361,54 @@ function salesforce_user($op, &$edit, &$
       if ($edit['create_lead']) {
         // must reload the object with user_load() to grab the updated profile fields
         salesforce_lead('insert', user_load(array('uid' => $account->uid)), array('Description' => t('new site user: @date', array('@date' => format_date(time(), 'large')))));
+				
+			} else if ($edit['contact_id'] || $edit['lead_id']) {
+				// user is being created from salesforce contact/lead
+				$account->contact_id = $edit['contact_id'];
+				$account->lead_id = $edit['lead_id'];
+				$account->account_id = $edit['account_id'];
+								
+				if ($account->contact_id) {
+					salesforce_contact('insert from remote', $account);
+				} else if ($account->lead_id) {
+					salesforce_lead('insert from remote', $account);
+				}
       }
       break;
 
     case 'update':
-      if (_salesforce_is_form('leads', 'user_edit')) {
+      if (_salesforce_is_form('leads', 'user_edit') && !$edit['update_from_salesforce']) {
         // must reload the object with user_load() to grab the updated profile fields
         $updated_account = user_load(array('uid' => $account->uid));
-        if ($account->salesforce['contact_id']) {
-          salesforce_contact('update', $updated_account);
-        } else if ($account->salesforce['lead_id']) {
-          salesforce_lead('update', $updated_account, array('Description' => t('last updated account information: @date', array('@date' => format_date(time(), 'large')))));
-        } else {
-          // we check on a form value so we can display a checkbox instead of a hidden field if it's an admin viewing the page
-          if ($edit['create_lead']) {
-            // must reload the object with user_load() to grab the updated profile fields
-            salesforce_lead('insert', user_load(array('uid' => $account->uid)), array('Description' => t('admin adding lead: @date', array('@date' => format_date(time(), 'large')))));
-          }
+        // we check on a form value so we can display a checkbox instead of a hidden field if it's an admin viewing the page
+        if ($edit['create_lead']) {
+          // must reload the object with user_load() to grab the updated profile fields
+          salesforce_lead('insert', user_load(array('uid' => $account->uid)), array('Description' => t('admin adding lead: @date', array('@date' => format_date(time(), 'large')))));
         }
       }
+		
+			if ($account->salesforce['contact_id'] && variable_get('salesforce_contact_sync', 0)) {
+        salesforce_contact('update', user_load(array('uid' => $account->uid)));
+      } else if ($account->salesforce['lead_id'] && variable_get('salesforce_lead_sync', 0)) {
+        salesforce_lead('update', user_load(array('uid' => $account->uid)), array('Description' => t('last updated account information: @date', array('@date' => format_date(time(), 'large')))));
+      }
+
       break;
+
+		case 'delete':
+			// Remove their information from salesforce_users table
+			db_query('DELETE FROM {salesforce_users} WHERE uid=%d', $account->uid);
+			break;
+
+		case 'register':
+			// Add these fields to the registration form so we can make use of them later.
+			$form = array();
+			$form['account_id'] = array('#type' => 'hidden', '#value' => '');
+			$form['lead_id'] 		= array('#type' => 'hidden', '#value' => '');
+			$form['contact_id'] = array('#type' => 'hidden', '#value' => '');
+			return $form;
+			break;
+
     case 'view':
       break;
   }
@@ -293,20 +494,21 @@ function salesforce_contact_form($form_i
  *  all forms set to use lead / event actions receive these submit functions
  *  separated right now just because.. TODO: should probably be reduced 1 one function but we're waiting..
  */
-function salesforce_form_lead_submit() {
-  $message =_salesforce_is_form('leads', $_POST['edit']['form_id'], true);
+function salesforce_form_lead_submit($form_id, $form_values) {
+  $message =_salesforce_is_form('leads', $form_id, true);
   // TODO: ? (currently not needed but.. hmm...)
 }
-function salesforce_form_event_submit() {
+function salesforce_form_event_submit($form_id, $form_values) {
   global $user;
 
   // only track logged in users since we need an account to associated them with
   if ($user->uid == 0) return;
 
   // grab our message to display as the description of this event in salesforce
-  $message =_salesforce_is_form('events', $_POST['edit']['form_id'], true);
+  $message =_salesforce_is_form('events', $form_id, true);
+
   // insert our event and yet again i find myself having to reload the user object to get my stuff? wtf?
-  $result = salesforce_event('insert', $_POST['edit']['form_id'], $message, user_load(array('mail' => $_POST['edit']['mail'])));
+  $result = salesforce_event('insert', $form_id, $message, user_load(array('mail' => $form_values['mail'])));
 }
 
 /**
@@ -431,6 +633,69 @@ function salesforce_log_run_page() {
 }
 
 /**
+ * salesforce_queuue_contact_import
+ */
+function salesforce_queue_contact_import_overview() {
+	drupal_set_title(t('Salesforce - Contact update queue'));
+	$output = '<p>'. t('Queue your entire Salesforce Contact database for import/update in Drupal. If the Salesforce Contact is already associated with a Drupal user this will force a profile udpate. If the Salesforce Contact is not already linked to a Drupal user and matches a Drupal user based on e-mail address it will attempt to link the two, otherwise a new Drupal user will be created.') .'</p>';
+	$output .= '<p>'. l('Queue now', 'admin/settings/salesforce/queue_contacts/do') .'</p>';
+	
+	// Show all current log records
+	$res = db_query('SELECT * FROM {salesforce_sync_log} WHERE type="contact_update" ORDER BY created_at');
+	if (db_num_rows($res)) {
+		$rows = array();
+		while ($log_entry = db_fetch_object($res)) {
+			$rows[] = array(
+				$log_entry->sfid,
+				format_date($log_entry->created_at, 'short')
+				);
+		}
+		$output .= '<p>'. t('Current queue') .'</p>';
+		$output .= theme('table', array('Contact ID', 'Log Record Created'), $rows);
+		$output .= '<p>'. t('Total: <strong>@total</strong>', array('@total' => db_num_rows($res))). '</p>';
+	}
+	
+	return $output;
+}
+
+/**
+ * salesforce_queue_contact_import
+ *
+ * Queries Salesforce for the Id of all Contacts that match the optional SOQL limiter
+ * and then creates a record in the salesforce_sync_log for each one so that it will
+ * be updated next time cron.php is run
+ */
+function salesforce_queue_contact_import() {
+	$sf = salesforce();
+	$query = 'SELECT Id FROM Contact';
+	// is there any SOQL limiter for selecting accounts?
+	if ( $limiter = variable_get('salesforce_contact_soql_limiter', '') ) {
+		$query .= ' WHERE ('. trim($limiter) .')';
+	}
+		
+	$res = $sf->query($query);
+	
+	if ($res['size'] > 0) {
+		$contacts = (array)$res['records'];
+		while ($res['done'] != 'true') {
+			$res = $sf->queryMore($res['queryLocator']);
+			$contacts = array_merge($contacts, (array)$res['records']);
+		}
+	}
+	
+	$total = 0;
+	foreach ($contacts as $c) {
+		if ($c->id != '') {
+			db_query('INSERT INTO {salesforce_sync_log} (type,sfid,created_at) VALUES ("%s", "%s", %d)', 'contact_update', $c->id, time());
+			$total++;
+		}
+	}
+	
+	drupal_set_message(t('@total contacts queued for import/update from Salesforce', array('@total' => $total)));
+	drupal_goto('admin/settings/salesforce/queue_contacts');
+}
+
+/**
  *  helper functions
  */
 
@@ -438,7 +703,7 @@ function _salesforce_admin_list($op) {
   $sf = 'https://na1.salesforce.com/';
 
   if ($op == 'lead' || $op == 'contact') {
-    $result = db_query("SELECT s.uid FROM {salesforce_users} s WHERE %s != ''", 's.'. $op .'_id');
+    $result = db_query("SELECT * FROM {salesforce_users} s WHERE %s != ''", 's.'. $op .'_id');
     if (db_num_rows($result) > 0) {
       $cols = array(array('data' => t('User'), 'class' => 'user'), array('data' => t('Name')), array('data' => t('%i', array('%i' => ucfirst($op) .' ID')), 'class' => 'id'));
       if ($op == 'contact') {
@@ -446,9 +711,9 @@ function _salesforce_admin_list($op) {
       }
 
       while ($row = db_fetch_object($result)) {
-        if ($op == 'contact') {
+        if ($op == 'contact' && !$row->account_id) {
           // we do this incase we don't have a cached account id
-          salesforce_account_select(user_load(array('uid' => $row->uid)));
+          salesforce_contact_select(user_load(array('uid' => $row->uid)));
         }
         $account = user_load(array('uid' => $row->uid));
         // remove the extra 3 chars that are not used in this case
@@ -522,6 +787,113 @@ function _salesforce_cron_run($row) {
 }
 
 /**
+ * Apply updated salesforce information to a local user account
+ */
+function _salesforce_cron_user_update($updated, $type='contact_id') {
+	foreach($updated as $id => $user) {
+		// if they already have an account locally we just update it.
+		if ($user && $id) {
+			if ($type == 'contact_id') {
+				salesforce_contact('update from remote', $user);
+			} else if ($type == 'lead_id') {
+				salesforce_lead('update from remote', $user);
+			}
+			watchdog('salesforce', t('Updated @user from Salesforce', array('@user' => $user->name)));
+			
+		} else if ($id) {
+			// This is a record that exists on salesforce but not locally
+			$account->salesforce[$type] = $id;
+
+			$profile_fields = _sf_get_profile_field_info();
+
+			// TODO: Rather than select each one individually can we select all of them at once? This would be faster
+			// and require less calls to salesforce
+			$fields = array('FirstName', 'LastName', 'Phone', 'Fax', 'Email');
+			if ($type == 'contact_id') {
+				$contact = salesforce_contact_select($account, array_merge($fields, $profile_fields));
+			} else if ($type == 'lead_id') {
+				$contact = salesforce_lead_select($account, array_merge($fields, $profile_fields));
+			}
+			
+			
+			if ($contact) {
+			
+				// Lets see if we can find a local account with the same e-mail address first
+				if ($user = user_load(array('mail' => $contact['Email']))) {
+					// If we found one, we can actually just udpate that account.
+					$user->$type = $contact['Id'];
+					$user->salesforce[$type] = $contact['Id'];
+					$user->account_id = $contact['AccountId'];
+										
+					if ($type == 'contact_id') {
+						// saves the 'contact_id' field, creating a link between the drupal user and the salesforce contact
+						salesforce_contact('insert from remote', $user);
+					} else if ($type == 'lead_id') {
+						// saves the 'lead_id' field, creating a link between the drupal user and the salesforce lead
+						salesforce_lead('insert from remote', $user);
+					}
+					// We can then just re-call this function and save the changes
+					_salesforce_cron_user_update(array($contact['Id'] => $user), $type);
+					
+					_salesforce_cron_user_update(array($row->sfid => salesforce_user_load($row->sfid)), $type);
+				
+				} else {
+								
+					// If we can't find a local account with the same e-mail address we create a new one.
+					$values = array();
+					$values['name'] = $contact['FirstName'] . $contact['LastName'];
+					$values['mail'] = $contact['Email'];
+					$values['pass'] = user_password();
+					$values['notify'] = 1;
+					$values['create_lead'] = 0;
+					$values['first_name'] = $contact['FirstName'];
+					$values['last_name'] = $contact['LastName'];
+					$values['phone'] = $contact['Phone'];
+					$values['fax'] = $contact['Fax'];
+					$values[$type] = $id;
+					$values['account_id'] = $contact['AccountId'];
+			
+					$values = _sf_profile_fields_get($values, $profile_fields, $contact);
+			
+					// Make sure this is a unique username
+					$i = 1;
+					$name = $values['name'];
+					while (db_num_rows(db_query('SELECT uid FROM {users} WHERE name="%s"', $values['name'])) > 0) {
+						$values['name'] = $name .'_'. $i;
+						$i++;
+					}
+			
+					// Register the user account. Doing it this way allows Drupal to call all the necessary hooks
+					user_register_submit('user_register', $values);
+					
+					// get the new users uid
+					$uid = db_result(db_query('SELECT uid FROM {users} WHERE mail="%s" AND name="%s"', $values['mail'], $values['name']));
+					
+					// Set the new users status and roles manually since we can't do it via cron unless you run cron.php when
+					// logged in as an administrator
+					db_query('UPDATE {users} SET status=%d WHERE uid=%d', variable_get('salesforce_contact_account_status', 0), $uid);
+					$roles = variable_get('salesforce_contact_account_roles',0);
+					if ($roles) {
+						foreach ($roles as $key => $rid) {
+							if ($key == $rid) {
+								db_query('DELETE FROM {users_roles} WHERE uid=%d AND rid=%d', $uid, $rid);
+								db_query('INSERT INTO {users_roles} (uid,rid) VALUES (%d, %d)', $uid, $rid);
+							}
+						}
+					}
+					
+					watchdog('salesforce', t('Inserted user @user from Salesforce', array('@user' => $contact['FirstName'].$contact['LastName'])));
+				
+				}
+			
+			}
+			
+		}	
+	}
+	return true;
+}
+
+/**
  *  used for inserting a single column into the salesforce_users table
  */
 function _salesforce_insert($col, $value, $account = NULL) {
