diff -urp --strip salesforce_api/salesforce_api.admin.inc new_salesforce_api/salesforce_api.admin.inc
--- salesforce_api/salesforce_api.admin.inc	2009-07-31 09:04:05.000000000 +0100
+++ new_salesforce_api/salesforce_api.admin.inc	2009-08-11 15:27:40.000000000 +0100
@@ -71,6 +71,30 @@ function salesforce_api_settings_form() 
     '#default_value' => variable_get('salesforce_api_error_log', SALESFORCE_LOG_ALL),
   );
 
+  $form['objects'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Object settings'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+    '#weight' => -9,
+  );
+  $form['objects']['clear_cache'] = array(
+    '#type'  => 'item',
+    '#value' => t('Caching data improves performance, however your Drupal site will be unaware of any alterations made to your Salesforce installation unless the cached data is refreshed. Select the lifetime the object data after which the cache will be automatically refreshed.  To refresh all cached object data on your site, click the button below.'),
+  );  
+  $period = drupal_map_assoc(array(32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval');  
+  $period[CACHE_PERMANENT] = t('<none>');
+  $form['objects']['salesforce_api_object_expire'] = array(
+    '#type' => 'select',
+    '#title' => t('Cache lifetime'),
+    '#options' => $period,
+    '#default_value' => variable_get('salesforce_api_object_expire', CACHE_PERMANENT),
+  );
+  $form['objects']['clear_cache_clear'] = array(
+    '#type' => 'submit',
+    '#value' => t('Clear cached object data'),
+    '#submit' => array('salesforce_api_cache_build'),
+  );
   // Validate handler makes sure that the salesforce_api_password doesn't get set to null on accident
   $form['#validate'][] = 'salesforce_api_settings_form_validate';
   $form['#submit'][] = 'salesforce_api_settings_form_submit';
@@ -189,6 +213,7 @@ function salesforce_api_fieldmap_add_for
   $form_state['redirect'] = SALESFORCE_PATH_FIELDMAPS .'/'. $index .'/edit';
 }
 
+
 /**
  * Creates a new fieldmap in the database and returns its index.
  *
@@ -423,6 +448,89 @@ function theme_salesforce_api_fieldmap_e
 }
 
 /**
+ * Ask salesforce for a list of objects and display a checklist for the user.
+ * Based on user selection, set up or tear down cached/synched Salesforce data.
+ * @TODO make this more user friendly. At the moment it's possible for an admin user to blow away 
+ * their entire local SalesForce cache with a few clicks. This is not necessarily desirable.
+ *
+ * @param string $form_state 
+ * @return void
+ * @author aaron
+**/
+function salesforce_api_admin_object(&$form_state) {
+  $objects = salesforce_api_describeGlobal();
+  $cache = cache_get('salesforce_api_sf_objects');
+  $defaults = array_keys($cache->data);
+
+  if (empty($objects->types)) {
+    drupal_set_message(t('There was an error retrieving the list of SalesForce objects. Please verify that your SalesForce instance is properly configured.'), 'error');
+    return;
+  }
+
+  $options = array_combine($objects->types, $objects->types);
+  $fields = array('objects' => array(
+      '#type' => 'checkboxes',
+      '#title' => 'SalesForce Objects',
+      '#description' => 'Check the SalesForce objects you would like to synchronize locally.',
+      '#options' => $options,
+      '#default_value' => $defaults,
+    ),
+    '#theme' => 'salesforce_api_object_options',
+    'submit' => array(
+      '#type' => 'submit', 
+      '#value' => 'Save'
+     ),
+  );
+  return $fields;
+}
+
+/**
+ * FAPI submit handler 
+ */
+function salesforce_api_admin_object_submit($form, &$form_state) {
+	$values = $form_state['values']['objects'];
+  foreach ($values as $i => $t) {
+    if (empty($t)) continue;
+    $real_types[] = $t;
+  }
+  $sf_objects = variable_set('salesforce_api_enabled_objects', $real_types);
+  $objects = salesforce_api_cache_build();
+  return;
+}
+
+function salesforce_api_admin_object_settings($form_state, $type) {
+  return array('settings' => array(
+    '#type' => 'markup', 
+    '#value' => 'Placeholder for per-object configuration settings.'
+    )
+  );
+}
+
+/**
+ * Theming function for @see salesforce_api_admin_setup
+ * For locally-cached SF Objects, add a "configure" or "re-map" link next to the checkbox
+ */
+function theme_salesforce_api_object_options($element = null) {
+  if(empty($element['objects']['#options'])) { return drupal_render($element); }
+  $objects = $element['objects'];
+  $options = $objects['#options'];
+  foreach($options as $i) {
+    if(empty($objects[$i]['#value'])) { continue; }
+    $link = l('configure', SALESFORCE_PATH_OBJECT.'/'.$i);
+    if($_SESSION['objects_error'][$i]) {
+      $element['objects'][$i]['#prefix'] = '<div class="error">';
+      $element['objects'][$i]['#suffix'] = '</div>';
+      unset($_SESSION['objects_error'][$i]);
+      $link = l('re-map fields', SALESFORCE_PATH_OBJECT.'/'.$i);
+    }
+    $element['objects'][$i]['#title'] .= ' | ' . $link;
+  }
+  unset($_SESSION['objects_error']);
+  return drupal_render($element);
+}
+
+//End CMT
+/**
  * Demonstrates some of the API functionality through the Salesforce class and
  * fieldmap functionality.
  *
@@ -518,3 +626,4 @@ function salesforce_api_demo($demo = NUL
 
   return $output;
 }
+
diff -urp --strip salesforce_api/salesforce_api.install new_salesforce_api/salesforce_api.install
--- salesforce_api/salesforce_api.install	2009-07-31 09:54:20.000000000 +0100
+++ new_salesforce_api/salesforce_api.install	2009-08-11 16:25:47.000000000 +0100
@@ -20,6 +20,7 @@ function salesforce_api_install() {
 function salesforce_api_uninstall() {
   drupal_uninstall_schema('salesforce_api');
   db_query("DELETE FROM {variable} WHERE {name} LIKE 'salesforce%'");
+  db_query("DELETE FROM {cache} WHERE {cid} = 'salesforce_api_sf_objects'");  
 }
 
 /**
@@ -27,6 +28,8 @@ function salesforce_api_uninstall() {
  */
 function salesforce_api_enable() {
   drupal_set_message(t('Salesforce API: Before making any Salesforce connections, please <a href="!url">enter your Salesforce API credentials</a>', array('!url' => url(SALESFORCE_PATH_ADMIN))), 'warning');
+  drupal_set_message(t('Salesforce API: The default Salesforce object have been enabled, to export/import any other objects see the <a href="!url">Object setup</a> page.', array('!url' => url(SALESFORCE_PATH_OBJECT))), 'warning');  
+
 }
 
 /**
diff -urp --strip salesforce_api/salesforce_api.module new_salesforce_api/salesforce_api.module
--- salesforce_api/salesforce_api.module	2009-07-31 09:04:05.000000000 +0100
+++ new_salesforce_api/salesforce_api.module	2009-08-11 16:09:12.000000000 +0100
@@ -19,8 +19,9 @@ define('SALESFORCE_DIR_WSDL', SALESFORCE
 
 // Define Drupal paths for various parts of the Salesforce UI.
 define('SALESFORCE_PATH_ADMIN', 'admin/settings/salesforce');
-define('SALESFORCE_PATH_FIELDMAPS', 'admin/settings/salesforce/fieldmap');
-define('SALESFORCE_PATH_DEMO', 'admin/settings/salesforce/demo');
+define('SALESFORCE_PATH_FIELDMAPS', SALESFORCE_PATH_ADMIN.'/fieldmap');
+define('SALESFORCE_PATH_DEMO', SALESFORCE_PATH_ADMIN.'/demo');
+define('SALESFORCE_PATH_OBJECT', SALESFORCE_PATH_ADMIN.'/object');
 
 // Define field importing requirements.
 // TODO: I believe we need to use bitwise operators instead.
@@ -111,6 +112,25 @@ function salesforce_api_menu() {
     'type' => MENU_CALLBACK,
     'file' => 'salesforce_api.admin.inc',
   );
+  $items[SALESFORCE_PATH_OBJECT] = array(
+    'title' => 'Object setup',
+    'description' => 'Define which SalesForce objects you would like to be available in your Drupal site.',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('salesforce_api_admin_object'),
+    'access arguments' => array('administer salesforce'),
+    'type' => MENU_LOCAL_TASK,
+    'file' => 'salesforce_api.admin.inc',
+    );
+  
+  $items[SALESFORCE_PATH_OBJECT.'/%'] = array(
+    'title' => 'Object setup',
+    'page callbacck' => 'drupal_get_form',
+    'page arguments' => array('salesforce_api_admin_object_settings', 
+                              count(explode('/', SALESFORCE_PATH_OBJECT))),
+    'access arguments' => array('administer salesforce'),
+    'type' => MENU_CALLBACK,
+    'file' => 'salesforce_api.admin.inc',
+    );
 
   return $items;
 }
@@ -191,33 +211,45 @@ function salesforce_api_fieldmap_objects
   if ($type == 'salesforce') {
     $cache = cache_get('salesforce_api_sf_objects');
     if ($cache->data == '') {
-      $sf_objects = variable_get('salesforce_api_enabled_objects', array('Campaign', 'Contact', 'Lead'));
-      $sf = salesforce_api_connect();
-      $result = $sf->client->describeSObjects($sf_objects);
-      foreach ($result as $key => $object) {
-        $objects[$sf_objects[$key]] = array(
-          'label' => t($sf_objects[$key]),
-          'fields' => array(),
-        );
-        foreach ($object->fields as $field) {
-          $objects[$sf_objects[$key]]['fields'][$field->name] = array(
-            'label' => t($field->label),
-          );
-          if ($field->createable != 1) {
-            $objects[$sf_objects[$key]]['fields'][$field->name]['type'] = SALESFORCE_FIELD_SOURCE_ONLY;
-          }
-          elseif ($field->nillable != 1 && $field->defaultedOnCreate != 1) {
-            $objects[$sf_objects[$key]]['fields'][$field->name]['type'] = SALESFORCE_FIELD_REQUIRED;
-          }
-        }
-      }
-      cache_set('salesforce_api_sf_objects', $objects);
+      $objects = salesforce_api_cache_build();
     }
     else {
       $objects = $cache->data;
     }
   }
+  return $objects;
+}
 
+/**
+ * Recreate the salesforce object cache
+ */
+function salesforce_api_cache_build(){
+  $sf_objects = variable_get('salesforce_api_enabled_objects', array('Campaign', 'Contact', 'Lead'));
+  $sf = salesforce_api_connect();
+  $result = $sf->client->describeSObjects($sf_objects);
+  foreach ($result as $key => $object) {
+    $objects[$sf_objects[$key]] = array(
+      'label' => t($sf_objects[$key]),
+      'fields' => array(),
+    );
+    foreach ($object->fields as $field) {
+      $objects[$sf_objects[$key]]['fields'][$field->name] = array(
+        'label' => t($field->label),
+      );
+      if ($field->createable != 1) {
+        $objects[$sf_objects[$key]]['fields'][$field->name]['type'] = SALESFORCE_FIELD_SOURCE_ONLY;
+      }
+      elseif ($field->nillable != 1 && $field->defaultedOnCreate != 1) {
+        $objects[$sf_objects[$key]]['fields'][$field->name]['type'] = SALESFORCE_FIELD_REQUIRED;
+      }
+    }
+  }
+  
+  // find the expiry time
+  $lifetime = variable_get('salesforce_api_object_expire', CACHE_PERMANENT);
+  $expire = ($lifetime == CACHE_PERMANENT) ? CACHE_PERMANENT : time() + $lifetime;
+  cache_set('salesforce_api_sf_objects', $objects, $table = 'cache', $expire, $headers = NULL);
+  drupal_set_message(t('Salesforce object cache has been refreshed.'));
   return $objects;
 }
 
@@ -590,3 +622,62 @@ function salesforce_api_theme($existing,
     ),
   );
 }
+
+/**
+* Wrapper for SOAP SforceBaseClient::describeGlobal
+* @return an SFQueryResult object (look at ->types for an array of SF object types)
+*/
+function salesforce_api_describeGlobal() {
+  static $objects;
+  if (!empty($objects)) {
+    return $objects;
+  }
+
+  $sf = salesforce_api_connect();
+  if ($sf === FALSE) {
+    $link = l('Please verify that you have completed your SalesForce credentials', SALESFORCE_PATH_ADMIN);
+    drupal_set_message(t('Unable to connect to SalesForce. !link', array('!link' => $link)), 'error');
+    return;
+  }
+  $objects = $sf->client->describeGlobal();
+  
+  return $objects;
+}
+
+/**
+ * Convert Salesforce object fields to fieldmap array for saving
+ */
+function salesforce_api_object_to_fieldmap_fields($object)	{
+
+  $fieldmap_object = array();
+  $fieldmap_object[$object->name] = array(
+    'label' => $object->label,
+    'fields' => array()
+  );
+
+  foreach($object->fields as $field) {
+    $fieldmap_object[$object->name]['fields'][$field->name]['label'] = $field->label;
+    if($field->createable != 1) {
+      $fieldmap_object[$object->name]['fields'][$field->name]['type'] = SALESFORCE_FIELD_SOURCE_ONLY;
+    }
+    elseif(!$field->nillable && !$field->defaultedOnCreate) {
+      $fieldmap_object[$object->name]['fields'][$field->name]['type'] = SALESFORCE_FIELD_REQUIRED;
+    }
+    else {
+      $fieldmap_object[$object->name]['fields'][$field->name]['type'] = SALESFORCE_FIELD_OPTIONAL;
+    }
+  }
+  return $fieldmap_object;
+}
+
+/**
+ * Implementation of hook_cron()
+ */
+function salesforce_api_cron() {
+
+  $cache = cache_get('salesforce_api_sf_objects');
+  // if the cache has already been delete or is expired then rebuild
+  if(!$cache || time() > $cache->expire) salesforce_api_cache_build();
+
+  return;
+}
\ No newline at end of file
