diff --git a/rpx_core.module b/rpx_core.module
index 4883728..5f20324 100644
--- a/rpx_core.module
+++ b/rpx_core.module
@@ -145,7 +145,7 @@ function rpx_core_form_alter(&$form, &$form_state, $form_id) {
   $field_map = variable_get('rpx_profile_fields_map', array());
   if (empty($field_map)) {
     return;
-  }
+  }  
 
   // Use Engage data to pre-fill profile fields.
   if(module_exists('profile')) {
@@ -550,32 +550,34 @@ function _rpx_import_user_data($account) {
   $map = variable_get('rpx_profile_fields_map', array());
   $provider = $_SESSION['rpx_last_provider_info']['name'];
   $rpx_data = rpx_core_get_rpx_session();
+  // array of field names => callbacks. 
+  // parameters for callback: node object &$node, field object $field, formatted new value $new_value, raw data from rpx $rpx_data
+  $custom_import_handlers = module_invoke_all('rpx_custom_data_import'); 
 
-  if (module_exists('profile')) {
-    // Collect fields list and load them together
-    $field_names = array();
-    foreach ($map as $mid => $mapping) {
-      // Filter-out at least non-updatable fields
-      if (!isset($mapping['update']) || $mapping['update'] == RPX_UPDATE_NONE) {
-        continue;
-      }
-      $field_names[] = $mapping['field'];
-    }
-    $profile_fields = _rpx_profile_get_fields($field_names, FALSE);
-  }
-
+  // Collect fields list and load them together
+  $profile_field_names = $content_profile_field_names = $profile_fields = array();
+  foreach ($map as $mid => $mapping) {
+    // Filter-out at least non-updatable fields
+    if (!isset($mapping['update']) || $mapping['update'] == RPX_UPDATE_NONE) continue;
+  
+    // test for field origin
+    if (module_exists('profile') && strpos($mapping['field'], 'profile_') === 0) $profile_field_names[] = $mapping['field'];
+    elseif (module_exists('content_profile') && strpos($mapping['field'], 'field_') === 0) $content_profile_field_names[] = $mapping['field'];
+  }
+  
+  $profile_fields += _rpx_profile_get_fields($profile_field_names, FALSE);
+  $profile_fields += _rpx_content_profile_get_fields($content_profile_field_names, $account);
+
+  $node = new stdClass; //used for content_profile fields
   foreach ($map as $mid => $mapping) {
+  	$field = $profile_fields[$mapping['field']];
+  	
     // Should we try to update the field at all?
-    if (!isset($mapping['update']) || $mapping['update'] == RPX_UPDATE_NONE) {
-      continue;
-    }
-
-    $new_data = _rpx_data_map($rpx_data, $mapping['fid']);
+    if (!isset($mapping['update']) || $mapping['update'] == RPX_UPDATE_NONE) continue;
 
     // Only update if provider returned data for the field.
-    if($new_data === '') {
-      continue;
-    }
+    $new_data = _rpx_data_map($rpx_data, $mapping['fid']);
+    if ($new_data === '') continue;
 
     // If data append is requested, make sure it's a multi-value field.
     if ($mapping['update'] == RPX_UPDATE_ADD) {
@@ -586,44 +588,34 @@ function _rpx_import_user_data($account) {
     // Check if whether we overwrite or not depends on the provider
     if ($mapping['update'] == RPX_UPDATE_MAYBE) {
       // Make sure this provider is in the mapping's provider list.
-      if(($provider_weight = array_search($provider, $mapping['providers'])) === FALSE) {
-        continue;
-      }
+      if(($provider_weight = array_search($provider, $mapping['providers'])) === FALSE) continue;
 
       // Make sure this provider is not lower in the weight table than the
       // previous one.
       $prev_provider = db_fetch_array(db_query("SELECT name FROM {rpx_mapping_provider} WHERE uid = %d AND mid = %d", $account->uid, $mid));
       $prev_provider = $prev_provider ? $prev_provider['name'] : '';
       $prev_provider_weight = array_search($prev_provider, $mapping['providers']);
-      if ($prev_provider_weight !== FALSE && $provider_weight > $prev_provider_weight) {
-        continue;
-      }
+      if ($prev_provider_weight !== FALSE && $provider_weight > $prev_provider_weight) continue;
+    }
+    
+    // Check that field still exists.
+    if (!isset($profile_fields[$mapping['field']])) {
+      _rpx_report_missing_field($field->origin, $mapping['field'], $account->name);
+      continue;
+    }
+    
+    // If we should only update empty field, make sure the field is empty.
+    $old_value = _rpx_profile_get_field_value($field, $account);
+    if ($mapping['update'] == RPX_UPDATE_EMPTY && $old_value && $old_value !== '') continue;
+
+    $new_value = _rpx_profile_format_value($field, $new_data);
+    if ($new_value === NULL) {
+      watchdog('rpx_core', 'Wrong data format for field %field_name.', array('%field_name' => $mapping['field']), WATCHDOG_WARNING);
+      continue;
     }
 
     // Import into the profile fields.
-    if(module_exists('profile')) {
-      // Check that field still exists.
-      if (!isset($profile_fields[$mapping['field']])) {
-        _rpx_report_missing_field('profile', $mapping['field'], $account->name);
-        continue;
-      }
-
-      $field = $profile_fields[$mapping['field']];
-      $old_value = db_result(db_query("SELECT value FROM {profile_values} WHERE fid = %d AND uid = %d", $field->fid, $account->uid));
-
-      // If we should only update empty field, make sure the field is empty.
-      if ($mapping['update'] == RPX_UPDATE_EMPTY) {
-        if ($old_value && $old_value !== '') {
-          continue;
-        }
-      }
-
-      $new_value = _rpx_profile_format_value($field, $new_data);
-      if ($new_value === NULL) {
-        watchdog('rpx_core', 'Wrong data format for field %field_name.', array('%field_name' => $mapping['field']), WATCHDOG_WARNING);
-        continue;
-      }
-
+    if ($field->origin == 'profile') {
       // Import the data.
       if ($old_value !== FALSE) {
         if (_profile_field_serialize($field->type)) {
@@ -640,6 +632,15 @@ function _rpx_import_user_data($account) {
       }
     }
 
+    // Import into the content profile fields (setup node values).
+    if ($field->origin == 'content_profile') {
+      // invoke hook_rpx_custom_data_import
+      if (isset($custom_import_handlers[$field->name]) && function_exists($custom_import_handlers[$field->name])) {
+      	call_user_func($custom_import_handlers[$field->name], &$node, $field, $new_value, $rpx_data);
+      }
+      else $node->{$field->name}[0][$field->column] = $new_value;
+    }
+
     // Record the provider's name as the last provider used in the mapping.
     if($mapping['update'] != RPX_UPDATE_ADD) {
       db_query("UPDATE {rpx_mapping_provider} SET name = '%s' WHERE uid = %d AND mid = %d", $provider, $account->uid, $mid);
@@ -648,6 +649,34 @@ function _rpx_import_user_data($account) {
       }
     }
   }
+  
+  // Import all the content profile data in 1 node_save action.
+  if (module_exists('content_profile')) {
+  	//merge objects
+    $node = (object) ((array) $node + (array) content_profile_load('profile', $account->uid));
+    node_save($node);
+  }
+  
+  drupal_set_message(t('user profile data import completed'));
+}
+
+
+/**
+ * Retrieve field value from profile
+ *
+ * @param object $field
+ *   Profile field object to get data from.
+ * @return
+ *   the field value
+ */
+function _rpx_profile_get_field_value($field, $account) {
+  if ($field->origin == 'profile') {
+	return db_result(db_query("SELECT value FROM {profile_values} WHERE fid = %d AND uid = %d", $field->fid, $account->uid));
+  }
+  if ($field->origin == 'content_profile') {
+	$node = content_profile_load('profile', $account->uid);
+	return $node->{$field->name}[0][$field->column];
+  }
 }
 
 /**
@@ -663,15 +692,10 @@ function _rpx_import_user_data($account) {
 function _rpx_profile_get_fields($names = array(), $reg_form = FALSE) {
   static $cache = array();
 
-  $result = array();
-  $load = array();
+  $result = $load = array();
   foreach ($names as $name) {
-    if (isset($cache[$name])) {
-      $result[$name] = $cache[$name];
-    }
-    else {
-      $load[] = $name;
-    }
+    if (isset($cache[$name])) $result[$name] = $cache[$name];
+    else $load[] = $name;
   }
 
   if (!empty($load)) {
@@ -687,6 +711,7 @@ function _rpx_profile_get_fields($names = array(), $reg_form = FALSE) {
     }
     $res = db_query($sql, $args);
     while ($field = db_fetch_object($res)) {
+      $field->origin = 'profile';
       $result[$field->name] = $cache[$field->name] = $field;
     }
   }
@@ -695,6 +720,62 @@ function _rpx_profile_get_fields($names = array(), $reg_form = FALSE) {
 }
 
 /**
+ * Retrieve content profile fields meta-information for selected fields.
+ *
+ * @param array $names
+ *   Profile fields to get information about.
+ * @return
+ *   An array of profile_fields data for each field.
+ */
+function _rpx_content_profile_get_fields($names = array(), $account, $reg_form = FALSE) {
+	static $cache = array();
+		
+	$result = $load = array();
+	foreach ($names as $name) {
+		if (isset($cache[$name])) $result[$name] = $cache[$name];
+		else $load[] = $name;
+	}
+		
+	if (!empty($load)) {
+		foreach ($names as $name) {
+			// basic data
+			$field = new stdClass;
+			$field->origin = 'content_profile';
+			$field->name = $name;
+			$field->registration_hide = false;
+			
+			// cck data
+			$field_info = content_fields($name);
+			$field->type = $field_info['type'];
+			$field->multiple = $field_info['multiple'];
+			foreach ($field_info['columns'] as $key => $values) {
+				$field->column = $key;
+				break; //try only the first column	  
+			}
+		
+			//content profile registration data
+			if (module_exists('content_profile_registration')) {
+				$node_types = content_profile_get_types('names');
+				foreach ($node_types as $type) {
+					if (in_array($name, content_profile_get_settings($type, 'registration_hide'))) {
+						$field->registration_hide = true;
+					}
+				}
+			}
+			
+			$result[$name] = $cache[$name] = $field;
+		}
+	}
+	
+	if ($reg_form) {
+		foreach ($result as $rfield) {
+			if ($rfield->registration_hide) unset($result[$rfield->name]);
+		}
+	}
+	return $result;
+}
+
+/**
  * Format value for profile field.
  *
  * @param object $field
@@ -705,36 +786,48 @@ function _rpx_profile_get_fields($names = array(), $reg_form = FALSE) {
  *   Mixed formatted value or NULL if formatting isn't possible.
  */
 function _rpx_profile_format_value($field, $value) {
-  switch ($field->type) {
-    case 'date':
-      if (!preg_match('/^(\d{4})\-(\d{2})\-(\d{2})$/', $value, $parsed_date)) {
-        return NULL;
-      }
-
-      // Profile stores days and months without leading zeroes
-      $result = array(
-        'year' => $parsed_date[1],
-        'month' => ltrim($parsed_date[2], '0'),
-        'day' => ltrim($parsed_date[3], '0'),
-      );
-      return $result;
-
-    case 'selection':
-      // Split just like Profile module does
-      $options = split("[\n\r]", $field->options);
-      foreach ($options as $option) {
-        if ($option = trim($option)) {
-          if (drupal_strtolower($value) == drupal_strtolower($option)) {
-            return $option;
+  if ($field->origin == 'profile') {
+    switch ($field->type) {
+      case 'date':
+        if (!preg_match('/^(\d{4})\-(\d{2})\-(\d{2})$/', $value, $parsed_date)) {
+          return NULL;
+        }
+  
+        // Profile stores days and months without leading zeroes
+        $result = array(
+          'year' => $parsed_date[1],
+          'month' => ltrim($parsed_date[2], '0'),
+          'day' => ltrim($parsed_date[3], '0'),
+        );
+        return $result;
+  
+      case 'selection':
+        // Split just like Profile module does
+        $options = split("[\n\r]", $field->options);
+        foreach ($options as $option) {
+          if ($option = trim($option)) {
+            if (drupal_strtolower($value) == drupal_strtolower($option)) {
+              return $option;
+            }
           }
         }
-      }
-      // No matches found, value can't be formatted
-      return NULL;
-
-    default:
-      // single, multi-line text and URL fields
-      return $value;
+        // No matches found, value can't be formatted
+        return NULL;
+  
+      default:
+        // single, multi-line text and URL fields
+        return $value;
+    }
+  }
+  
+  if ($field->origin == 'content_profile') {
+    switch ($field->type) {
+      case 'date':
+      case 'selection':
+      default:
+        // single, multi-line text and URL fields
+        return $value;
+    }
   }
 }
 
diff --git a/rpx_ui.module b/rpx_ui.module
index 4baafd1..b979624 100644
--- a/rpx_ui.module
+++ b/rpx_ui.module
@@ -324,14 +324,31 @@ function rpx_get_enabled_provider_array($force_lookup = FALSE) {
 function _rpx_drupal_field_catalog() {
   $fields = array();
 
+  // todo: Build an array containing the fields defined by the User core module.
+/*
+  $fields['name'] = 'User: Name';
+  $fields['mail'] = 'User: Email';
+  $fields['picture'] = 'User: Picture';
+*/
+
   // Build an array containing the fields defined by the Profile core module.
   if (module_exists('profile')) {
     $result = db_query("SELECT fid, title, name FROM {profile_fields} WHERE type IN ('textfield', 'textarea', 'url', 'date', 'selection') ORDER BY weight, title");
     while ($row = db_fetch_object($result)) {
-      $fields[$row->name] = $row->title;
+      $fields[$row->name] = 'Profile: '.$row->title;
     }
   }
 
+  // Build an array containing the fields defined by the Content Profile contributed module.
+  if (module_exists('content_profile')) {
+  	foreach (content_profile_get_types() as $type => $info) {
+	  	$typeinfo = content_types($type);
+	  	foreach ($typeinfo['fields'] as $fieldname => $fieldinfo) {
+	  		$fields[$fieldname] = 'Content Profile: '.($fieldinfo['label'] ? $fieldinfo['label'] : $fieldinfo['field_name']);
+	  	}
+  	}
+  }
+
   return $fields;
 }
 
