diff --git acquia_agent/acquia_agent.css acquia_agent/acquia_agent.css
index 2fb86f1..fd812b9 100644
--- acquia_agent/acquia_agent.css
+++ acquia_agent/acquia_agent.css
@@ -1,9 +1,9 @@
-h3#an-info-header{
+h2#an-info-header{
   padding-top: 0.5em;
 }
 
 div#an-info-box{
-  display: table; 
+  display: table;
   width: 100%;
   table-layout: fixed;
   margin-top: 1.5em;
@@ -21,28 +21,32 @@ div#an-info-box{
 }
 
 #an-info-box div.cell.an-center{
-  padding-left: 2em; 
+  padding-left: 2em;
   border-left: 1px solid #D0D0D0;
   border-right: 1px solid #D0D0D0;
 }
 
 #an-info-box div.cell.an-right{
-  padding-left: 2em; 
+  padding-left: 2em;
 }
 
 div#an-pg-container{
-  display: table; 
+  display: table;
   width: 100%;
 }
 
 div#an-pg-form{
-  display: table-cell; 
+  display: table-cell;
   vertical-align: top;
   width: 100%;
 }
 
-div#an-pg-banner{
-  display: table-cell; 
+div.an-pg-banner{
+  display: table-cell;
   text-align: right;
   padding-left: 1em;
 }
+
+#acquia-agent-settings-form-banner{
+  padding-top:21px;
+}
diff --git acquia_agent/acquia_agent.install acquia_agent/acquia_agent.install
index b5e39c6..f61c59f 100644
--- acquia_agent/acquia_agent.install
+++ acquia_agent/acquia_agent.install
@@ -7,6 +7,7 @@
  *
  */
 
+
 /**
  * The minimum PHP memory recommended to install Acquia Drupal.
  */
@@ -106,7 +107,7 @@ function acquia_agent_requirements($phase) {
           'description' => t('Your subscription is expired or you are using an invalid identifier and key pair. You can check the subscription identifier and the subscription key at the <a href="@settings">Acquia settings</a> page. Check <a href="@acquia-network">your subscription on the Acquia Network</a> for further status information.', array('@settings' => url('admin/config/system/acquia-agent'), '@acquia-network' => $href)),
         );
       }
-      
+
       // During runtime, we can't override the PHP memory limit provided by
       // Drupal core, so we supplement it with our own warning instead (but
       // only when necessary to do so).
@@ -159,98 +160,3 @@ function acquia_agent_requirements($phase) {
   return $requirements;
 }
 
-/**
- * Warn users who are upgrading from a pre-release version of CCK about any
- * broken Views on their site.
- */
-function acquia_agent_update_6000() {
-  $ret = array();
-  $broken_filters = array();
-  // To be safe, we require that CCK and Views both be enabled, and also
-  // perform many checks of their APIs during the course of this update.
-  if (module_exists('content') && module_exists('views') && function_exists('views_api_version') && views_api_version() == 2.0) {
-    // We also make sure only to print warnings in the case where the user
-    // has a pre-release CCK schema version, because otherwise they may have
-    // already made manual changes to their Views, and the warning messages
-    // here therefore would not be accurate.
-    $cck_schema_version = variable_get('content_schema_version', 0);
-    if ($cck_schema_version >= 6000 && $cck_schema_version <= 6008) {
-      // Search through all filters for all Views.
-      if (function_exists('views_get_all_views') && ($views = views_get_all_views()) && is_array($views)) {
-        foreach ($views as $view) {
-          if (method_exists($view, 'init_display')) {
-            $view->init_display();
-            if (is_array($view->display)) {
-              foreach ($view->display as $display_id => $display) {
-                if (method_exists($display->handler, 'is_defaulted') && !$display->handler->is_defaulted('filter') && method_exists($display->handler, 'get_handlers')) {
-                  $handlers = $display->handler->get_handlers('filter');
-                  if (is_array($handlers)) {
-                    foreach ($handlers as $handler_id => $handler) {
-                      // If the filter is on a CCK text or number field and
-                      // defines a list of allowed values, then it is broken.
-                      if (isset($handler->content_field)) {
-                        $field = $handler->content_field;
-                        if (isset($field['type']) && in_array($field['type'], array('text', 'number_integer', 'number_decimal', 'number_float'), TRUE)) {
-                          if (function_exists('content_allowed_values')) {
-                            $allowed_values = content_allowed_values($field);
-                            if (count($allowed_values) && isset($view->type)) {
-                              switch ($view->type) {
-                                case t('Normal'):
-                                  // The human-readable name is friendlier
-                                  // for Views accessible via the UI.
-                                  $broken_filters['database'][$view->name][] = t('Content: @label', array('@label' => $field['widget']['label']));
-                                  break;
-                                case t('Overriden'):
-                                case t('Default'):
-                                  // The machine-readable name is friendlier
-                                  // for Views stored in code.
-                                  $broken_filters['code'][$view->name][] = $field['field_name'];
-                                  break;
-                              }
-                            }
-                          }
-                        }
-                      }
-                    }
-                  }
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-  if (!empty($broken_filters)) {
-    // Convert the list of broken filters to a user-friendly format.
-    foreach ($broken_filters as $type => $views) {
-      foreach ($views as $view => $fields) {
-        $view_replacement = ($type == 'database') ? l($view, 'admin/build/views/edit/' . $view) : check_plain($view);
-        // Make sure we don't print the same field name twice.
-        $broken_filters[$type][$view] = t('!view (broken filters: %filters)', array('!view' => $view_replacement, '%filters' => implode(', ', array_unique($fields))));
-      }
-    }
-    $broken_database_filters = isset($broken_filters['database']) ? $broken_filters['database'] : array();
-    $broken_code_filters = isset($broken_filters['code']) ? $broken_filters['code'] : array();
-    $t_strings = array(
-      '!database_views' => '<li>' . implode('</li><li>', $broken_database_filters) . '</li>',
-      '!code_views' => '<li>' . implode('</li><li>', $broken_code_filters) . '</li>',
-      '@drupal_url' => 'http://drupal.org/node/330658',
-    );
-    if (!empty($broken_database_filters)) {
-      $text = 'The following Views on your site may not work correctly as a result of this upgrade:<ul>!database_views</ul>In particular, filters on CCK text or numeric fields that refer to a list of allowed values will need to be recreated. You may do this through the administrative interface by editing the "Filters" section of each View, removing the broken filters listed above, and replacing each with a new one of type "Content: ... Allowed values". Alternatively, you can edit an exported version of the View and then reimport it; <a href="@drupal_url">more information</a> on this option is available from the CCK issue queue on drupal.org.';
-      $message = t($text, $t_strings);
-      watchdog('acquia', $text, $t_strings, WATCHDOG_WARNING);
-      drupal_set_message($message, 'warning');
-      $ret[] = array('success' => TRUE, 'query' => $message);
-    }
-    if (!empty($broken_code_filters)) {
-      $text = 'The following Views on your site may not work correctly as a result of this upgrade:<ul>!code_views</ul>In particular, filters on CCK text or numeric fields that refer to a list of allowed values will need to be recreated. The Views listed above are defined in code and will need to be edited there. <a href="@drupal_url">More information</a> on how to do this is available from the CCK issue queue on drupal.org.';
-      $message = t($text, $t_strings);
-      watchdog('acquia', $text, $t_strings, WATCHDOG_WARNING);
-      drupal_set_message($message, 'warning');
-      $ret[] = array('success' => TRUE, 'query' => $message);
-    }
-  }
-  return $ret;
-}
diff --git acquia_agent/acquia_agent.module acquia_agent/acquia_agent.module
index 97773ba..1f9e931 100644
--- acquia_agent/acquia_agent.module
+++ acquia_agent/acquia_agent.module
@@ -18,6 +18,7 @@ define('SUBSCRIPTION_MESSAGE_FUTURE'  , 1500);
 define('SUBSCRIPTION_MESSAGE_EXPIRED' , 1600);
 define('SUBSCRIPTION_MESSAGE_INVALID' , 1700);
 define('SUBSCRIPTION_VALIDATION_ERROR', 1800);
+define('SUBSCRIPTION_PROVISION_ERROR' , 9000);
 
 /**
  * Subscription message lifetime defined by the Acquia Network.
@@ -29,7 +30,7 @@ define('SUBSCRIPTION_MESSAGE_LIFETIME', 15*60);
  */
 function acquia_agent_menu() {
   $items['admin/config/system/acquia-agent'] = array(
-    'title' => 'Acquia Network',
+    'title' => 'Acquia Network settings',
     'description' => 'Connect your site to the Acquia Network.',
     'page callback' => 'acquia_agent_settings_page',
     'file' => 'acquia_agent.pages.inc',
@@ -48,20 +49,32 @@ function acquia_agent_menu() {
  * Implementation of hook_init().
  */
 function acquia_agent_init() {
-  if (empty($_POST) && user_access('administer site configuration') && (!acquia_agent_has_credentials())) {
+  if ( !(arg(0) == 'overlay-ajax' && arg(1) == 'page_top') &&
+      arg(3) != 'acquia-agent' &&
+      empty($_POST) &&
+      user_access('administer site configuration') &&
+      (!acquia_agent_has_credentials())) {
+    $message = t('Get a <a href="@acquia-free">free 30 day trial</a> of Drupal support, enhanced content search, comment spam blocking and more. If you have an Acquia Network subscription, <a href="@settings">connect now</a>.', array('@acquia-free' => url('admin/config/system/acquia-agent'), '@settings' => url('admin/config/system/acquia-agent/connection')));
     if (arg(0) == 'admin') {
-      drupal_set_message(t('Subscribe to the <a href="@acquia-network">Acquia Network</a> to access Network Services and Technical Support for your Drupal site.<br /> 
-To learn how Acquia can help you manage your Drupal site, visit the <a href="@acquia-ps">Acquia Products &amp; Services page</a>.<br />
-Once subscribed, please enter your subscription key and identifier on the <a href="@settings">settings page</a>.<br />
-To turn this message off, disable the Acquia Network Connector modules.', array('@acquia-network' => 'http://acquia.com/network', '@acquia-ps' => 'http://acquia.com/products-services', '@settings' => url('admin/config/system/acquia-agent'))), 'warning', FALSE);
-    }
-    else {
-      drupal_set_message(t('If you have an <a href="@acquia-network">Acquia Network subscription</a>, please enter your subscription key and identifier on the <a href="@settings">settings page</a>.', array('@acquia-network' => 'http://acquia.com/network', '@settings' => url('admin/config/system/acquia-agent'))), 'warning', FALSE);
+      $message .= '<br />' . t('To turn this message off, disable the Acquia Network Connector <a href="@admin-modules">modules</a>.', array('@admin-modules' => url('admin/modules', array('fragment' => 'edit-modules-acquia-network-connector'))));
     }
+    drupal_set_message($message, 'warning', FALSE);
   }
 }
 
 /**
+ * Implementation of hook_theme().
+ */
+function acquia_agent_theme() {
+  return array(
+    'acquia_agent_banner_form' => array(
+      'render element' => 'form',
+      'file' => 'acquia_agent.pages.inc',
+    ),
+  );
+}
+
+/**
  * Get subscription status from the Acquia Network, and store the result.
  *
  * This check also sends a heartbeat to the Acquia Network unless
@@ -87,11 +100,14 @@ function acquia_agent_check_subscription($params = array()) {
     }
     // Include Acquia Search module version number.
     if (module_exists('acquia_search')) {
-      $info = db_query("SELECT info FROM {system} WHERE name = 'acquia_search'")->fetchField();
-      if ($info = unserialize($info)) {
-        $params['search_version'] = $info['version'];
+      $result = db_query("SELECT name, info FROM {system} WHERE name IN ('acquia_search', 'apachesolr')");
+      foreach ($result as $data) {
+        if ($info = unserialize($data->info)) {
+          $params['search_version'][$data->name] = $info['version'];
+        }
       }
     }
+    $old_status = acquia_agent_subscription_is_active();
     $data = acquia_agent_call('acquia.agent.subscription', $params);
     $subscription['timestamp'] = REQUEST_TIME;
     if ($errno = xmlrpc_errno()) {
@@ -99,6 +115,10 @@ function acquia_agent_check_subscription($params = array()) {
         case SUBSCRIPTION_NOT_FOUND:
         case SUBSCRIPTION_EXPIRED:
           variable_del('acquia_subscription_data');
+          //notify everybody that the subscription status has changed
+          if ($old_status) {
+            module_invoke_all('acquia_subscription_status', FALSE);
+          }
           break;
       }
     }
@@ -106,6 +126,11 @@ function acquia_agent_check_subscription($params = array()) {
       $subscription += $data['result']['body'];
       variable_set('acquia_subscription_data', $subscription);
       // use: acquia_agent_settings('acquia_subscription_data');
+
+      // notify everybody that the subscription status has changed
+      if (!$old_status) {
+        module_invoke_all('acquia_subscription_status', TRUE);
+      }
     }
     else {
       watchdog('acquia agent', 'HMAC validation error: <pre>@data</pre>', array('@data' => print_r($data, TRUE)), WATCHDOG_ERROR);
@@ -114,6 +139,9 @@ function acquia_agent_check_subscription($params = array()) {
   return $subscription;
 }
 
+function acquia_agent_report_xmlrpc_error() {
+  drupal_set_message(t('Error: @message (@errno)', array('@message' => xmlrpc_error_msg(), '@errno' => xmlrpc_errno())), 'error');
+}
 /**
  * Implementation of hook_update_status_alter().
  *
@@ -129,12 +157,12 @@ function acquia_agent_check_subscription($params = array()) {
  * @see update_calculate_project_data()
  */
 function acquia_agent_update_status_alter(&$projects) {
-  
+
   if (!$subscription = acquia_agent_has_update_service()) {
     // Get subscription data or return if the service is not enabled.
     return;
   }
-  
+
   foreach ($projects as $project => $project_info) {
     if ($project == 'drupal') {
       if (isset($subscription['update'])) {
@@ -195,7 +223,7 @@ function acquia_agent_has_update_service() {
     // that the web service willingly told us to not do update notifications.
     return FALSE;
   }
-  
+
   return $subscription;
 }
 
@@ -355,26 +383,7 @@ function acquia_agent_valid_credentials($identifier, $key, $acquia_network_addre
  *
  */
 function acquia_agent_call($method, $params, $identifier = NULL, $key = NULL, $acquia_network_address = NULL) {
-  $path = drupal_get_path('module', 'acquia_agent');
-  require_once $path . '/acquia_agent_streams.inc';
-
-  if (empty($acquia_network_address)) {
-    $acquia_network_address = acquia_agent_settings('acquia_network_address');
-  }
-  // Strip protocol (scheme) from Network address
-  $uri = parse_url($acquia_network_address);
-  $port = isset($uri['port']) ? ':' . $uri['port'] : '';
-  $path = isset($uri['path']) ? $uri['path'] : '';
-  $acquia_network_address = $uri['host'] . $port . $path;
-  // Add a scheme based on PHP's capacity.
-  if (in_array('ssl', stream_get_transports(), TRUE) && !defined('ACQUIA_DEVELOPMENT_NOSSL')) {
-    // OpenSSL is available in PHP
-    $acquia_network_address = 'https://' . $acquia_network_address;
-  }
-  else {
-    $acquia_network_address = 'http://' . $acquia_network_address;
-  }
-  $acquia_network_address .= '/xmlrpc.php';
+  $acquia_network_address = acquia_agent_network_address($acquia_network_address);
   $host = isset($_SERVER["SERVER_ADDR"]) ? $_SERVER["SERVER_ADDR"] : '';
   $data = array(
     'authenticator' => _acquia_agent_authenticator($params, $identifier, $key),
@@ -421,6 +430,30 @@ function acquia_agent_connection_error_message() {
 }
 
 /**
+ * Helper function to build the xmlrpc target address.
+ */
+function acquia_agent_network_address($acquia_network_address = NULL) {
+  if (empty($acquia_network_address)) {
+    $acquia_network_address = acquia_agent_settings('acquia_network_address');
+  }
+  // Strip protocol (scheme) from Network address
+  $uri = parse_url($acquia_network_address);
+  $port = isset($uri['port']) ? ':' . $uri['port'] : '';
+  $path = isset($uri['path']) ? $uri['path'] : '';
+  $acquia_network_address = $uri['host'] . $port . $path;
+  // Add a scheme based on PHP's capacity.
+  if (in_array('ssl', stream_get_transports(), TRUE) && !defined('ACQUIA_DEVELOPMENT_NOSSL')) {
+    // OpenSSL is available in PHP
+    $acquia_network_address = 'https://' . $acquia_network_address;
+  }
+  else {
+    $acquia_network_address = 'http://' . $acquia_network_address;
+  }
+  $acquia_network_address .= '/xmlrpc.php';
+  return $acquia_network_address;
+}
+
+/**
  * Helper function to check if an identifer and key exist.
  */
 function acquia_agent_has_credentials() {
@@ -459,7 +492,7 @@ function acquia_agent_settings($variable_name) {
 /**
  * API function used by others to ensure version information is loaded.
  *
- * Saves us some cycles to not load it each time, when it is actually 
+ * Saves us some cycles to not load it each time, when it is actually
  * not needed. We store this in a separate file, so that the Acquia
  * build process only needs to alter that file instead of the main
  * module file.
@@ -473,18 +506,104 @@ function acquia_agent_load_versions() {
  * Implementation of hook_form_[form_id]_alter()..
  */
 function acquia_agent_form_system_modules_alter(&$form, &$form_state) {
-  
-  if (isset($form['modules']['Acquia Network Connector']['acquia_search'])) {
+
+  if (isset($form['description']['acquia_search'])) {
     $subscription = acquia_agent_settings('acquia_subscription_data');
-    
+
     if (!module_exists('acquia_search') && empty($subscription['active'])) {
-      $row = &$form['modules']['Acquia Network Connector']['acquia_search'];
-      $row['enable']['#disabled'] = TRUE;
-      $text = t('Acquia Search requires an <a href="@network-url">Acquia Network subscription</a>', array('@network-url' => 'http://acquia.com/products-services/acquia-search'));
-      $message = '<div style="padding-left:5px; margin:8px 0px" class="messages warning" id="acquia-agent-no-search">' . $text . '</div>';  
-      $row['description']['#markup'] =  $message . $row['description']['#markup'];
+      $form['status']['#disabled_modules'][] = 'acquia_search';
+      $text = 'Acquia Search requires an <a href="@network-url">Acquia Network subscription</a>';
+      $message = t($text, array('@network-url' => 'http://acquia.com/products-services/acquia-search'));
+      $form['description']['acquia_search']['#value'] = '<div style="padding-left:5px; margin:8px 0px" class="messages warning" id="acquia-agent-no-search">' . $message . '</div>' . $form['description']['acquia_search']['#value'];
+    }
+  }
+}
+
+/**
+ * Builds a stream context based on a url and local .pem file if available.
+ */
+function acquia_agent_stream_context_create($url, $module = 'acquia_agent') {
+  $opts = array();
+  $uri = parse_url($url);
+  if (isset($uri['scheme']) && ($uri['scheme'] == 'https') && variable_get('acquia_agent_verify_peer', 0)) {
+    // Look for a local certificate to validate the server identity.
+    $pem_file = drupal_get_path('module', $module) . '/' . $uri['host'] . '.pem';
+    if (file_exists($pem_file)) {
+      $opts['ssl'] = array(
+        'verify_peer' => TRUE,
+        'cafile' => $pem_file,
+        'allow_self_signed' => FALSE, // doesn't mean anything in this case
+        'CN_match' => $uri['host']);
     }
   }
+  return stream_context_create($opts);
 }
 
 
+/**
+ * Determine if a response from the Acquia Network is valid.
+ *
+ * @param $data
+ *   The data array returned by acquia_agent_call().
+ * @return
+ *   TRUE or FALSE.
+ */
+function acquia_agent_valid_response($data) {
+  $authenticator = $data['authenticator'];
+  $result = $data['result'];
+  $result_auth = $result['authenticator'];
+  $valid = ($authenticator['nonce'] == $result_auth['nonce']);
+  $valid = $valid && ($authenticator['time'] < $result_auth['time']);
+  $key = acquia_agent_settings('acquia_key');
+  $hash = _acquia_agent_hmac($key, $result_auth['time'], $result_auth['nonce'], $result['body']);
+  return $valid && ($hash == $result_auth['hash']);
+}
+
+/**
+ * Send a XML-RPC request.
+ *
+ * This function should never be called directly - use acquia_agent_call().
+ */
+function _acquia_agent_request($url, $method, $data) {
+  $ctx = acquia_agent_stream_context_create($url);
+  if (!$ctx) {
+    // TODO: what's a meaningful fault code?
+    xmlrpc_error(-1, t('SSL is not supported or setup failed'));
+    $result = FALSE;
+  }
+  else {
+    $result = xmlrpc($url, array($method => array($data)), array('context' => $ctx));
+  }
+  if ($errno = xmlrpc_errno()) {
+    watchdog('acquia agent', '@message (@errno): %server - %method - <pre>@data</pre>', array('@message' => xmlrpc_error_msg(), '@errno' => xmlrpc_errno(), '%server' => $url, '%method' => $method, '@data' => print_r($data, TRUE)), WATCHDOG_ERROR);
+  }
+  return $result;
+}
+
+/**
+ * Creates an authenticator based on xmlrpc params and a HMAC-SHA1.
+ */
+function _acquia_agent_authenticator($params = array(), $identifier = NULL, $key = NULL) {
+  if (empty($identifier)) {
+    $identifier = acquia_agent_settings('acquia_identifier');
+  }
+  if (empty($key)) {
+    $key = acquia_agent_settings('acquia_key');
+  }
+  $time = REQUEST_TIME;
+  $nonce = base64_encode(hash('sha256', drupal_random_bytes(55), TRUE));
+  $authenticator['identifier'] = $identifier;
+  $authenticator['time'] = $time;
+  $authenticator['hash'] = _acquia_agent_hmac($key, $time, $nonce, $params);
+  $authenticator['nonce'] = $nonce;
+  return $authenticator;
+}
+
+/**
+ * Calculates a HMAC-SHA1 according to RFC2104 (http://www.ietf.org/rfc/rfc2104.txt).
+ * With addition of xmlrpc params.
+ */
+function _acquia_agent_hmac($key, $time, $nonce, $params) {
+  $data = $time . ':' . $nonce . ':' . $key . ':' . serialize($params);
+  return base64_encode(hash_hmac('sha1', $data, $key, TRUE));
+}
diff --git acquia_agent/acquia_agent.pages.inc acquia_agent/acquia_agent.pages.inc
index 9144a96..6dd6f7e 100644
--- acquia_agent/acquia_agent.pages.inc
+++ acquia_agent/acquia_agent.pages.inc
@@ -7,126 +7,576 @@
  */
 
 /**
- * Menu callback for settings page.
+ * Helper function. Creates an authenticator for xmlrpc calls
  */
-function acquia_agent_settings_page() {
-
-  $identifier = acquia_agent_settings('acquia_identifier');
-  $key = acquia_agent_settings('acquia_key');
-  $change = FALSE;
+function _acquia_agent_create_authenticator($body, $pass = NULL) {
+  $a = array();
+  $a['time'] = REQUEST_TIME;
+  $a['nonce'] = base64_encode(hash('sha256', drupal_random_bytes(55), TRUE));;
+  // We need an hmac to authenticate to an acquia.com account.
+  // This will fail if acquia.com moves to D7.
+  if (isset($pass)) {
+    $a['hash'] = _acquia_agent_hmac(md5($pass), $a['time'], $a['nonce'], $body);
+  }
+  else {
+    // rpc.acquia.com XML-RPC interface requires this parameter to be a string.
+    // Just pass a dummy value.
+    $a['hash'] = 'x';
+  }
+  return $a;
+}
 
-  // Check $_POST so we don't send extra XML-RPC requests during form submission.
-  if ($identifier && $key && empty($_POST)) {
-    // Check our connection to the Acquia Network and validity of the crenditials.
-    $acquia_network_address = acquia_agent_settings('acquia_network_address');
-    if (acquia_agent_valid_credentials($identifier, $key, $acquia_network_address)) {
-      drupal_set_message(t('You are successfully communicating with the Acquia Network. To change the subscription keys, click the %alter button.', array('%alter' => t('Alter settings'))), 'status', FALSE);
+/**
+ * Helper function that creates a new AN subscription via xmlrpc call. It stores id/key
+ * if success and sets page error otherwise
+ */
+function _acquia_agent_call_provision_freetrial($body, $authenticator, $pass) {
+  $md5_pass = md5($pass);
+  $values = array('body' => $body, 'authenticator' => $authenticator);
+  $result = xmlrpc(acquia_agent_network_address(), array('acquia.agent.provision.freetrial' => array($values)));
+  if ($errno = xmlrpc_errno()) {
+    drupal_set_message(t('Error getting free trial: @message (@errno)', array('@message' => xmlrpc_error_msg(), '@errno' => xmlrpc_errno())), 'error');
+    watchdog('acquia agent', '@message (@errno): %server - %method - <pre>@data</pre>', array('@message' => xmlrpc_error_msg(), '@errno' => xmlrpc_errno(), '%server' => acquia_agent_network_address(), '%method' => 'acquia.agent.provision.freetrial', '@data' => print_r($values, TRUE)), WATCHDOG_ERROR);
+    $result = FALSE;
+  }
+  elseif (!empty($result['body']['nid'])) {
+    if (!empty($result['body']['hashkey']) && !empty($md5_pass)) {
+      // We have a key XOR'd with a hash.
+      $hash = str_pad(_acquia_agent_hmac(
+        $md5_pass,
+        $authenticator['time'],
+        $authenticator['nonce'],
+        $result['body']['identifier']), 64, chr(0x00));
+      // Repeat the XOR and remove trailing NUL bytes.
+      $key = rtrim(base64_decode($result['body']['hashkey']) ^ $hash);
+      // Strip off the padding marker character.
+      $key = substr($key, 0, -1);
     }
     else {
-      $error_message = acquia_agent_connection_error_message();
-      drupal_set_message($error_message, 'error', FALSE);
-      $change = TRUE;
+      $key = $result['body']['key'];
     }
+    variable_set('acquia_key', $key);
+    variable_set('acquia_identifier', $result['body']['identifier']);
+    drupal_set_message(t('The Acquia configuration options have been saved.'));
+    // Check subscription and send a heartbeat to Acquia Network via XML-RPC.
+    // Our status gets updated locally via the return data.
+    acquia_agent_check_subscription();
+    cache_clear_all();
+  }
+  return $result;
+}
+
+/**
+ *  Main 30 day trial form function
+ */
+function acquia_agent_an_trial_form($form, &$form_state, $banner) {
+  $cur_step = NULL;
+  if (!empty($form_state['storage']['step'])) {
+    $function = '_acquia_agent_an_trial_' . $form_state['storage']['step'] . '_form';
+    return $function($form_state, $banner);
+  }
+  else {
+    return _acquia_agent_an_trial_start_form($form_state, $banner);
+  }
+}
+
+/**
+ * 30 day trial form submit dispatch function
+ */
+function acquia_agent_an_trial_form_submit($form, &$form_state) {
+  if (empty($form_state['storage'])) {
+    $form_state['storage'] = array();
+    $form_state['storage']['values'] = array();
+  }
+
+  // Store submitted form values. Overwrite old values with new.
+  $form_state['storage']['values'] = $form_state['values'] + $form_state['storage']['values'];
+
+  // Call the step-specific submit handler.
+  $submit_function = '_acquia_agent_an_trial_' . $form_state['values']['this_step'] . '_form_submit';
+  if (function_exists($submit_function)) {
+    $submit_function($form, $form_state);
+  }
+
+  // Set up next step.
+  if (!empty($form_state['values']['step_next'])) {
+    $form_state['storage']['step'] = $form_state['values']['step_next'];
+    $form_state['rebuild'] = TRUE;
+  }
+  elseif (acquia_agent_has_credentials()) {
+    // The proces is complete.
+    drupal_set_message(t('The site "!site" is now connected to the Acquia network. A welcome email has been sent to the email address you provided', array('!site' => $form_state['values']['subscription_name'])));
+    unset($form_state['storage']);
+    $form_state['redirect'] = 'admin/config/system/acquia-agent';
+  }
+}
+
+function _acquia_agent_provision_freetrial($form, &$form_state) {
+  $val = $form_state['values'] + $form_state['storage']['values'];
+  $body = array();
+
+  $body['accept_terms_checkbox'] = 1;
+
+  $new_user = empty($form_state['storage']['userdata']['uid']);
+  if ($new_user) {
+    // New user
+    $body['primary_email'] = $val['email'];
+
+    $pass = $val['pass'];
+    // Send password as hash.
+    $body['pass'] = md5($val['pass']);
+    $body['billing_first_name'] = $val['billing_first_name'];
+    $body['billing_last_name'] = $val['billing_last_name'];
   }
-  $page = array();
-  $subscription = acquia_agent_settings('acquia_subscription_data');
-  // Check $_POST so we don't tell people status about previously stored
-  // credentials during form submission.
-  if ($subscription['active'] && empty($_POST)) {
-    $title = t("Subscription active. Click here to go to the Acquia Network.");
-    $page['subscription_link'] = array( '#markup' => "<p>" . l($title, $subscription['href']) . "</p>\n" );
+  else {
+    // Existing user
+    $body['uid'] = $form_state['storage']['userdata']['uid'];
+    $pass = $val['pass'];
   }
 
-  $page['settings_form'] = drupal_get_form('acquia_agent_settings_form', $change);
-  $page['communication_form'] = drupal_get_form('acquia_agent_communication_form');  
-    
-  return $page;
+  $body['subscription_name'] = $val['subscription_name'];
+  $body['site_url'] = $val['site_url'];
+  $body['billing_company'] = $val['billing_company'];
+  $body['billing_phone'] = $val['billing_phone'];
+  $body['billing_country_acquia'] = $val['billing_country_acquia'];
+  $auth = _acquia_agent_create_authenticator($body, ($new_user ? NULL : $pass));
+  return _acquia_agent_call_provision_freetrial($body, $auth, $pass);
 }
 
 /**
- * Settings form builder function.
+ * Start form page
+ *
+ * Where user decides if they want to enter their email and get a new subscrition or go to the settings page
+ * and use existing AN subscription id/key
  */
-function acquia_agent_communication_form($form, $form_state) {
-  $ssl_available = (in_array('ssl', stream_get_transports(), TRUE) && !defined('ACQUIA_DEVELOPMENT_NOSSL'));
+function _acquia_agent_an_trial_start_form(&$form_state) {
+  $form = array(
+    '#prefix' =>  acquia_agent_an_info_header(),
+    'email' => array(
+      '#type' => 'textfield',
+      '#title' => t('E-mail address'),
+      '#size' => 32,
+      '#maxlength' => 64,
+      '#required' => TRUE,
+    ),
+    'continue' => array(
+      '#type' => 'submit',
+      '#value' => 'Next >'),
+    'settings_link' => array(
+      '#markup' => '<br/>' . l(t('I already have an active Acquia subscription, and now I want to connect this site to it'), 'admin/config/system/acquia-agent/connection')),
+    // Special value elements.
+    'this_step' => array(
+      '#type' => 'value',
+      '#value' => 'start',
+    ),
+    '#validate' => array('_acquia_agent_an_trial_start_form_validate'),
+  );
+  return $form;
+}
 
-  $form['acquia_agent_verify_peer'] = array(
-    '#type' => 'radios',
-    '#title' => t('Enhanced SSL security'),
-    '#default_value' => (int) (variable_get('acquia_agent_verify_peer', 0) && $ssl_available),
-    '#options' => array(0 => t('Disabled'), 1 => t('Enabled')),
-    '#description' => t('If enabled the Acquia Connector will attempty to verify Acquia server identities before sending data.  May cause communication to fail, however, depending on your local configuration.'),
-    '#disabled' => !$ssl_available,
+function _acquia_agent_an_trial_start_form_validate($form, &$form_state) {
+  if (!valid_email_address($form_state['values']['email'])) {
+    form_set_error('email', t('Email is invalid'));
+  }
+}
+
+function _acquia_agent_an_trial_start_form_submit($form, &$form_state) {
+  $result = xmlrpc(acquia_agent_network_address(), array('acquia.agent.mail.exists' => array($form_state['values']['email'])));
+
+  if ($errno = xmlrpc_errno()) {
+    acquia_agent_report_xmlrpc_error();
+    // Set form error to prevent switching to the next page.
+    form_set_error('email');
+  }
+  elseif ($result) {
+    // Existing user.
+    $form_state['values']['step_next'] = 'pass_old';
+  }
+  else {
+    // New user.
+    $form_state['values']['step_next'] = 'details_new';
+  }
+}
+
+/**
+ * New user form
+ */
+function _acquia_agent_an_trial_details_new_form(&$form_state, $banner = NULL) {
+  global $user;
+
+  $val = $form_state['storage']['values'];
+  $form = array(
+    '#prefix' =>  '<p>' . t('Start your subscription by providing the information below. We\'ll create a free trial subscription for you, and set up this site with the subscription keys.') . '</p>',
+    'email' => array(
+      '#type' => 'item',
+      '#title' => t('E-mail address'),
+      '#markup' => $val['email'],
+      '#required' => TRUE,
+    ),
+    'subscription_name' => array(
+      '#type' => 'textfield',
+      '#title' => t('Subscription name'),
+      '#size' => 32,
+      '#maxlength' => 64,
+      '#required' => TRUE,
+      '#default_value' => variable_get('site_name', 'Site for ' . $user->name),
+    ),
+    'site_url' => array(
+      '#type' => 'textfield',
+      '#title' => t('Your site\'s URL'),
+      '#size' => 32,
+      '#maxlength' => 128,
+      '#default_value' => url(NULL, array('absolute' => TRUE)),
+    ),
+    'billing_country_acquia' => array(
+      '#type' => 'select',
+      '#title' => t('Country'),
+      '#options' => _acquia_agent_countries(),
+      '#required' => TRUE
+    ),
+    'pass' => array(
+      '#type' => 'password_confirm',
+      '#title' => t('Create your Acquia.com password'),
+      '#size' => 32,
+      '#required' => TRUE,
+    ),
+    'billing_first_name' => array(
+      '#type' => 'textfield',
+      '#title' => t('First name'),
+      '#size' => 32,
+      '#maxlength' => 32,
+      '#required' => TRUE,
+    ),
+    'billing_last_name' => array(
+      '#type' => 'textfield',
+      '#title' => t('Last name'),
+      '#size' => 32,
+      '#maxlength' => 32,
+      '#required' => TRUE,
+    ),
+    'billing_company' => array(
+      '#type' => 'textfield',
+      '#title' => t('Organization name'),
+      '#size' => 32,
+      '#maxlength' => 64,
+      '#required' => TRUE,
+    ),
+    'billing_phone' => array(
+      '#type' => 'textfield',
+      '#title' => t('Phone'),
+      '#size' => 32,
+      '#maxlength' => 64,
+      '#required' => TRUE,
+    ),
+    'submit' => array(
+      '#type' => 'submit',
+      '#value' => t('Start my new 30-day free trial for this site'),
+    ),
+    // Special value elements.
+    'this_step' => array(
+      '#type' => 'value',
+      '#value' => 'details_new',
+    ),
 
+    'banner' => array('#markup' => $banner),
+    '#theme' => 'acquia_agent_banner_form',
+    '#validate' => array('_acquia_agent_an_trial_details_form_validate'),
   );
+  return $form;
+}
 
-  if ($ssl_available) {
-    $form['acquia_agent_verify_peer']['#description'] .= ' <div class="ok">' . t('PHP has SSL support and may support this feature.') . '</div>';
+function _acquia_agent_an_trial_details_form_validate($form, &$form_state) {
+  if (strlen($form_state['values']['site_url']) && !valid_url($form_state['values']['site_url'], TRUE)) {
+    form_set_error('site_url', 'Please enter a valid website URL or leave the field empty. A valid website URL should include http:// or https://.');
+  }
+  // We don't want to do the provisioning if there are any errors.
+  if (!form_get_errors()) {
+    // Do the provisioning at the validation stage so a form error doesn't lose form values.
+    $result = _acquia_agent_provision_freetrial($form, $form_state);
+    if (!$result) {
+      form_set_error('', '');
+    }
+    else {
+      $form_state['result'] = $result['body'];
+    }
+  }
+}
+
+/**
+ * Existing user form page
+ */
+function _acquia_agent_an_trial_details_old_form(&$form_state, $banner = NULL) {
+  $ud = $form_state['storage']['userdata'];
+
+  $form = array(
+    '#prefix' => '<p>' . t('Let\'s get started creating a new trial subscription for your account.') . '</p>',
+    'name' => array(
+      '#type' => 'item',
+      '#title' => t('My account username'),
+      '#markup' => $ud['name'],
+      '#required' => TRUE,
+    ),
+    'first_name' => array(
+      '#type' => 'item',
+      '#title' => t('First name'),
+      '#markup' => $ud['profile_firstname'],
+      '#required' => TRUE,
+    ),
+    'last_name' => array(
+      '#type' => 'item',
+      '#title' => t('Last name'),
+      '#markup' => $ud['profile_lastname'],
+      '#required' => TRUE,
+    ),
+    'subscription_name' => array(
+      '#type' => 'textfield',
+      '#title' => t('Subscription name'),
+      '#size' => 32,
+      '#maxlength' => 64,
+      '#required' => TRUE,
+      '#default_value' => variable_get('site_name', t('My new site')),
+    ),
+    'site_url' => array(
+      '#type' => 'textfield',
+      '#title' => t('Your site\'s URL'),
+      '#size' => 32,
+      '#maxlength' => 128,
+      '#default_value' => url(NULL, array('absolute' => TRUE)),
+    ),
+    'billing_country_acquia' => array(
+      '#type' => 'select',
+      '#title' => t('Country'),
+      '#options' => _acquia_agent_countries(),
+      '#required' => TRUE,
+      '#default_value' => $ud['profile_country'],
+    ),
+    'billing_company' => array(
+      '#type' => 'textfield',
+      '#title' => t('Company'),
+      '#size' => 32,
+      '#maxlength' => 64,
+      '#default_value' => $ud['profile_organization'],
+      '#required' => TRUE,
+    ),
+    'billing_phone' => array(
+      '#type' => 'textfield',
+      '#title' => t('Phone'),
+      '#size' => 32,
+      '#maxlength' => 64,
+      '#default_value' => $ud['profile_officephone'],
+      '#required' => TRUE,
+    ),
+    'submit' => array(
+      '#type' => 'submit',
+      '#value' => t('Start my new 30-day free trial for this site'),
+    ),
+    // Special value elements.
+    'this_step' => array(
+      '#type' => 'value',
+      '#value' => 'details_old',
+    ),
+
+    'banner' => array('#markups' => $banner),
+    '#theme' => 'acquia_agent_banner_form',
+    '#validate' => array('_acquia_agent_an_trial_details_form_validate'),
+  );
+
+  return $form;
+}
+
+/**
+ * Existing user password page
+ *
+ */
+function _acquia_agent_an_trial_pass_old_form(&$form_state, $banner = NULL) {
+  $values = $form_state['storage']['values'];
+  $form = array(
+    '#prefix' =>  acquia_agent_an_info_header(),
+    'form_header' => array(
+      '#markup' => acquia_agent_existing_account_msg(),
+    ),
+    'email' => array(
+      '#type' => 'item',
+      '#title' => t('E-mail address'),
+      '#markup' => $values['email'],
+      '#required' => TRUE,
+    ),
+    'pass' => array(
+      '#type' => 'password',
+      '#title' => t('Acquia.com password'),
+      '#description' => t('Please enter your Acquia.com password here'),
+      '#size' => 32,
+      '#required' => TRUE,
+    ),
+    'continue' => array(
+      '#type' => 'submit',
+      '#value' => 'Next >',
+    ),
+    'forgot_pass' => array(
+      '#value' => '<br/>' . l(t('I forgot my password'), 'http://acquia.com/user/password', array('attributes' => array('target' => '_blank'))),
+    ),
+    // Special value elements.
+    'this_step' => array(
+      '#type' => 'value',
+      '#value' => 'pass_old',
+    ),
+    'step_next' => array(
+      '#type' => 'value',
+      '#value' => 'details_old',
+    ),
+    '#validate' => array('_acquia_agent_an_trial_pass_old_form_validate'),
+  );
+  return $form;
+}
+
+function _acquia_agent_an_trial_pass_old_form_validate($form, &$form_state) {
+  $val = $form_state['storage']['values'];
+  if (!empty($val['email'])) {
+    $params = array('email' => $val['email']);
+    $args = array('body' => $params, 'authenticator' => _acquia_agent_create_authenticator($params, $form_state['values']['pass']));
+    $result = xmlrpc(acquia_agent_network_address(), array('acquia.agent.provision.get_user_details' => array($args)));
+    if ($errno = xmlrpc_errno()) {
+      acquia_agent_report_xmlrpc_error();
+      // Set form error to prevent switching to the next page.
+      form_set_error('email');
+    }
+    else {
+      $form_state['storage']['userdata'] = $result['body'];
+    }
   }
   else {
-    $form['acquia_agent_verify_peer']['#description'] .= ' <div class="error">' . t('PHP does not have SSL support.') . '</div>';
+    // Paranoid check. should not happen.
+    form_set_error('email', t('No email provided'));
   }
+}
+
+/**
+ * Main page function
+ */
+function acquia_agent_settings_page($arg = NULL) {
+  $identifier = acquia_agent_settings('acquia_identifier');
+  $key = acquia_agent_settings('acquia_key');
+  $path = drupal_get_path('module', 'acquia_agent');
+  $banner = theme('image', array('path' => $path . '/acquia_vertical_banner.png'));
+  drupal_add_css($path . '/acquia_agent.css', 'module', 'all', FALSE);
 
-  return system_settings_form($form);
+  if (($identifier && $key) || $arg == 'connection') {
+    return acquia_agent_settings_form_page($banner);
+  }
+  else {
+    drupal_set_title(t('Get a free 30 day trial of the Acquia Network'));
+    return drupal_get_form('acquia_agent_an_trial_form', $banner);
+  }
 }
 
 /**
- * Settings form builder function.
+ * Menu callback for settings page.
  */
-function acquia_agent_settings_form($form, $form_state, $change = FALSE) {
+function acquia_agent_settings_form_page($banner = NULL) {
   $identifier = acquia_agent_settings('acquia_identifier');
   $key = acquia_agent_settings('acquia_key');
 
-  // Alow changing settings if requested in the API, via a form button or
-  // there is at least one value missing.
-  $change = $change || isset($form_state['change_settings']) || (empty($identifier) || empty($key));
+  $output =  '';
+  // Check $_POST so we don't send extra XML-RPC requests during form submission.
+  if ($identifier && $key && empty($_POST)) {
+    // Check our connection to the Acquia Network and validity of the crenditials.
+    $acquia_network_address = acquia_agent_settings('acquia_network_address');
+    if (acquia_agent_valid_credentials($identifier, $key, $acquia_network_address)) {
+      $subscription = acquia_agent_settings('acquia_subscription_data');
+    }
+    else {
+      $error_message = acquia_agent_connection_error_message();
+      drupal_set_message($error_message, 'error', FALSE);
+    }
+  }
+  return drupal_get_form('acquia_agent_settings_form', $banner);
+}
+
+/**
+ * Settings form builder function.
+ */
+function acquia_agent_settings_form($form, &$form_state, $banner) {
+  $identifier = acquia_agent_settings('acquia_identifier');
+  $key = acquia_agent_settings('acquia_key');
 
   // Help for copying the identifier and key.
   $copy_help = t('Copy from <a href="@subscriptions-overview">your subscriptions overview on the Acquia Network</a>.', array('@subscriptions-overview' => 'http://acquia.com/network/dashboard/subscription'));
 
-  $form['acquia_identifier'] = array(
+  $form['cs'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Acquia Network keys'),
+    '#collapsible' => FALSE,
+    '#collapsed' => FALSE,
+  );
+
+  $form['cs']['acquia_identifier'] = array(
     '#type' => 'textfield',
-    '#title' => t('Acquia subscription identifier'),
+    '#title' => t('Identifier'),
     '#default_value' => $identifier,
-    // Disable field if not changing values, making this a display only field.
-    '#disabled' => !$change,
-    '#description' => t('Identifier of this website (a public key).') . ($change ? ' ' . $copy_help : ''),
-    '#required' => $change,
+    '#description' => $copy_help,
+    '#required' => TRUE,
   );
-  $form['acquia_key'] = array(
+  $form['cs']['acquia_key'] = array(
     '#type' => 'textfield',
-    '#title' => t('Acquia subscription key'),
+    '#title' => t('Key'),
     '#default_value' => $key,
-    // Disallow access if not changing values. Only the identifier is shown then.
-    '#access' => $change,
-    '#description' => t('Key of this website (a private key).') . ($change ? ' ' . $copy_help : ''),
-    '#required' => $change,
+    '#description' => $copy_help,
+    '#required' => TRUE,
   );
-  $form['buttons']['submit'] = array(
+
+  $form['cs']['buttons']['submit'] = array(
     '#type' => 'submit',
-    '#value' => t('Save configuration'),
+    '#value' => t('Save keys'),
     '#validate' => array('acquia_agent_set_validate'),
     '#submit' => array('acquia_agent_set_submit'),
-    // Only show this button if changing values.
-    '#access' => $change,
   );
-  $form['buttons']['delete'] = array(
+  $form['cs']['buttons']['delete'] = array(
     '#type' => 'submit',
-    '#value' => t('Delete subscription information'),
+    '#value' => t('Clear keys'),
+    '#access' => (!empty($identifier) || !empty($key)),
     '#submit' => array('acquia_agent_delete_submit'),
-    // Only show this button if changing values and we have existing settings to delete.
-    '#access' => ($change && (!empty($identifier) || !empty($key))),
   );
-  $form['buttons']['change'] = array(
-    '#type' => 'submit',
-    '#value' => t('Alter settings'),
-    '#submit' => array('acquia_agent_change_submit'),
-    // Only show this button if not already changing settings.
-    '#access' => !$change,
+  $ssl_available = (in_array('ssl', stream_get_transports(), TRUE) && !defined('ACQUIA_DEVELOPMENT_NOSSL'));
+
+  $form['ssl'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('SSL settings'),
+    '#collapsible' => FALSE,
   );
+  $form['ssl']['acquia_agent_verify_peer'] = array(
+    '#type' => 'radios',
+    '#title' => t('Enhanced SSL security'),
+    '#default_value' => (int) (variable_get('acquia_agent_verify_peer', 0) && $ssl_available),
+    '#options' => array(0 => t('Disabled'), 1 => t('Enabled')),
+    '#description' => t('If enabled the Acquia Connector will attempty to verify Acquia server identities before sending data.  May cause communication to fail, however, depending on your local configuration.'),
+    '#disabled' => !$ssl_available,
+  );
+
+  if ($ssl_available) {
+    $form['ssl']['acquia_agent_verify_peer']['#description'] .= ' <div class="messages status">' . t('PHP has SSL support and may support this feature.') . '</div>';
+    $form['ssl']['buttons']['submit'] = array(
+      '#type' => 'submit',
+      '#value' => t('Save configuration'),
+      '#submit' => array('acquia_agent_ssl_submit'),
+    );
+  }
+  else {
+    $form['ssl']['acquia_agent_verify_peer']['#description'] .= ' <div class="messages error">' . t('PHP does not have SSL support.') . '</div>';
+  }
+  $form['banner'] = array('#markup' => $banner);
+  $form['#theme'] = 'acquia_agent_banner_form';
   return $form;
 }
 
 /**
+ * Submit acquia_agent_settings ssl setting.
+ */
+function acquia_agent_ssl_submit($form, &$form_state) {
+  variable_set('acquia_agent_verify_peer', $form_state['values']['acquia_agent_verify_peer']);
+  drupal_set_message(t('The configuration options have been saved.'));
+}
+
+/**
  * Validate acquia_agent_settings form submissions.
  */
 function acquia_agent_set_validate($form, &$form_state) {
@@ -155,7 +605,9 @@ function acquia_agent_set_submit($form, &$form_state) {
   drupal_set_message(t('The Acquia configuration options have been saved.'));
   // Check subscription and send a heartbeat to Acquia Network via XML-RPC.
   // Our status gets updated locally via the return data.
-  acquia_agent_check_subscription();
+  $active = acquia_agent_check_subscription();
+  // Redirect to the path without the suffix.
+  $form_state['redirect'] = 'admin/config/system/acquia-agent';
   cache_clear_all();
 }
 
@@ -163,20 +615,297 @@ function acquia_agent_set_submit($form, &$form_state) {
  * Delete acquia_agent settings.
  */
 function acquia_agent_delete_submit($form, &$form_state) {
+  $old_status = acquia_agent_subscription_is_active();
+
   variable_del('acquia_key');
   variable_del('acquia_identifier');
   variable_del('acquia_network_address');
   variable_del('acquia_subscription_data');
   drupal_set_message(t('Your Acquia configuration has been deleted.'));
+  // Redirect to the path with the suffix.
+  $form_state['redirect'] = 'admin/config/system/acquia-agent/connection';
   cache_clear_all();
+
+  // notify everybody that the subscription status may have changed
+  if ($old_status) {
+    module_invoke_all('acquia_subscription_status', FALSE);
+  }
 }
 
-/**
- * Submit function for the "Change settings" button.
- */
-function acquia_agent_change_submit($form, &$form_state) {
-  // Go back to the form and let the user change settings there.
-  $form_state['change_settings'] = TRUE;
-  $form_state['rebuild'] = TRUE;
+function theme_acquia_agent_banner_form($variables) {
+  $form = $variables['form'];
+  if (empty($form['banner'])) {
+    return drupal_render_children($form);
+  }
+  $banner = drupal_render($form['banner']);
+  $output = '<div id="an-pg-container"><div id="an-pg-form">';
+  $output .= drupal_render_children($form);
+  $output .= "\n</div>\n";
+  $output .= '<div class="an-pg-banner" id="' . $form['#id'] . '-banner">';
+  $output .= '<a href="http://acquia.com/products-services/acquia-network" target="_blank">' . $banner . '</a>';
+  $output .= "\n</div>\n</div>\n";
+  return $output;
 }
 
+function acquia_agent_an_info_header() {
+  $l_opt = array('attributes' => array('target' => '_blank'));
+  $output = '<h2 id="an-info-header">' . t('With the <a href="@acquia-network" target="_blank">Acquia Network</a> you get:', array('@acquia-network' => 'http://acquia.com/products-services/acquia-network')) . '</h2>';
+  $output .= '<div id="an-info-box">';
+  $output .=   '<div class="cell an-left">';
+  $output .=     '<h2>' . t('Drupal support') . '</h2>';
+  $output .=     t('Get expert advice for tough Drupal questions.');
+  $output .=     '<br/>' . l(t('Learn more'), 'http://acquia.com/drupal-support', $l_opt);
+  $output .=   '</div>';
+  $output .=   '<div class="cell an-center">';
+  $output .=     '<h2>' . t('Acquia Search') . '</h2>';
+  $output .=     t('Add faceted search and content recommendations.');
+  $output .=     '<br/>' . l(t('Learn more'), 'http://acquia.com/products-services/acquia-search', $l_opt);
+  $output .=   '</div>';
+  $output .=   '<div class="cell an-right">';
+  $output .=     '<h2>' . t('Mollom') . '</h2>';
+  $output .=     t('Add automated spam blocking for all user generated content.');
+  $output .=     '<br/>' . l(t('Learn more'), 'http://acquia.com/documentation/getting-started/acquia-network-services/mollom', $l_opt);
+  $output .=   '</div>';
+  $output .= '</div>';
+  return $output;
+}
+
+function acquia_agent_existing_account_msg() {
+  $output = '<div class="messages warning" style="margin-top: 0px">';
+  $output .= t('An existing Acquia.com account is associated with that email address. Enter your password to associate this free trial with that account, or <a href="@an_trial">try another email address</a>', array('@an_trial' => url('admin/config/system/acquia-agent')));
+  $output .= '</div>';
+  return $output;
+}
+
+/**
+ * List of countries in the Acquia Network database.
+ */
+function _acquia_agent_countries() {
+  return array(
+    'United States' => 'United States',
+    'Afghanistan' => 'Afghanistan',
+    'Albania' => 'Albania',
+    'Algeria' => 'Algeria',
+    'American Samoa' => 'American Samoa',
+    'Andorra' => 'Andorra',
+    'Angola' => 'Angola',
+    'Anguilla' => 'Anguilla',
+    'Antigua and Barbuda' => 'Antigua and Barbuda',
+    'Argentina' => 'Argentina',
+    'Armenia' => 'Armenia',
+    'Ascension Island' => 'Ascension Island',
+    'Australia' => 'Australia',
+    'Austria' => 'Austria',
+    'Azerbaijan' => 'Azerbaijan',
+    'Bahamas' => 'Bahamas',
+    'Bahrain' => 'Bahrain',
+    'Bangladesh' => 'Bangladesh',
+    'Barbados' => 'Barbados',
+    'Belarus' => 'Belarus',
+    'Belgium' => 'Belgium',
+    'Belize' => 'Belize',
+    'Benin' => 'Benin',
+    'Bermuda' => 'Bermuda',
+    'Bhutan' => 'Bhutan',
+    'Bolivia' => 'Bolivia',
+    'Bosnia and Herzegovina' => 'Bosnia and Herzegovina',
+    'Botswana' => 'Botswana',
+    'Brazil' => 'Brazil',
+    'British Indian Ocean Territory' => 'British Indian Ocean Territory',
+    'Brunei Darussalam' => 'Brunei Darussalam',
+    'Bulgaria' => 'Bulgaria',
+    'Burkina Faso' => 'Burkina Faso',
+    'Burundi' => 'Burundi',
+    'Cambodia' => 'Cambodia',
+    'Cameroon' => 'Cameroon',
+    'Canada' => 'Canada',
+    'Cape Verde' => 'Cape Verde',
+    'Cayman Islands' => 'Cayman Islands',
+    'Central African Republic' => 'Central African Republic',
+    'Chad' => 'Chad',
+    'Chile' => 'Chile',
+    'China' => 'China',
+    'Colombia' => 'Colombia',
+    'Comoros' => 'Comoros',
+    'Congo' => 'Congo',
+    'Cook Islands' => 'Cook Islands',
+    'Costa Rica' => 'Costa Rica',
+    'Cote D Ivoire' => 'Cote D Ivoire',
+    'Croatia' => 'Croatia',
+    'Cuba' => 'Cuba',
+    'Cyprus' => 'Cyprus',
+    'Czech Republic' => 'Czech Republic',
+    'Denmark' => 'Denmark',
+    'Djibouti' => 'Djibouti',
+    'Dominica' => 'Dominica',
+    'Dominican Republic' => 'Dominican Republic',
+    'Ecuador' => 'Ecuador',
+    'Egypt' => 'Egypt',
+    'El Salvador' => 'El Salvador',
+    'Equatorial Guinea' => 'Equatorial Guinea',
+    'Eritrea' => 'Eritrea',
+    'Estonia' => 'Estonia',
+    'Ethiopia' => 'Ethiopia',
+    'Falkland Islands' => 'Falkland Islands',
+    'Faroe Islands' => 'Faroe Islands',
+    'Federated States of Micronesia' => 'Federated States of Micronesia',
+    'Fiji' => 'Fiji',
+    'Finland' => 'Finland',
+    'France' => 'France',
+    'French Guiana' => 'French Guiana',
+    'French Polynesia' => 'French Polynesia',
+    'Gabon' => 'Gabon',
+    'Georgia' => 'Georgia',
+    'Germany' => 'Germany',
+    'Ghana' => 'Ghana',
+    'Greece' => 'Greece',
+    'Greenland' => 'Greenland',
+    'Grenada' => 'Grenada',
+    'Guadeloupe' => 'Guadeloupe',
+    'Guatemala' => 'Guatemala',
+    'Guam' => 'Guam',
+    'Guinea' => 'Guinea',
+    'Guinea Bissau' => 'Guinea Bissau',
+    'Guyana' => 'Guyana',
+    'Haiti' => 'Haiti',
+    'Holy See (Vatican City)' => 'Holy See (Vatican City)',
+    'Honduras' => 'Honduras',
+    'Hong Kong' => 'Hong Kong',
+    'Hungary' => 'Hungary',
+    'Iceland' => 'Iceland',
+    'India' => 'India',
+    'Indonesia' => 'Indonesia',
+    'Iran' => 'Iran',
+    'Ireland' => 'Ireland',
+    'Isle of Man' => 'Isle of Man',
+    'Israel' => 'Israel',
+    'Italy' => 'Italy',
+    'Jamaica' => 'Jamaica',
+    'Japan' => 'Japan',
+    'Jordan' => 'Jordan',
+    'Kazakhstan' => 'Kazakhstan',
+    'Kenya' => 'Kenya',
+    'Kiribati' => 'Kiribati',
+    'Korea' => 'Korea',
+    'Kuwait' => 'Kuwait',
+    'Kyrgyzstan' => 'Kyrgyzstan',
+    'Laos' => 'Laos',
+    'Latvia' => 'Latvia',
+    'Lebanon' => 'Lebanon',
+    'Lesotho' => 'Lesotho',
+    'Liberia' => 'Liberia',
+    'Libya' => 'Libya',
+    'Liechtenstein' => 'Liechtenstein',
+    'Lithuania' => 'Lithuania',
+    'Luxembourg' => 'Luxembourg',
+    'Macau' => 'Macau',
+    'Macedonia' => 'Macedonia',
+    'Madagascar' => 'Madagascar',
+    'Malawi' => 'Malawi',
+    'Malaysia' => 'Malaysia',
+    'Maldives' => 'Maldives',
+    'Mali' => 'Mali',
+    'Malta' => 'Malta',
+    'Marshall Islands' => 'Marshall Islands',
+    'Martinique' => 'Martinique',
+    'Mauritius' => 'Mauritius',
+    'Mayotte' => 'Mayotte',
+    'Mexico' => 'Mexico',
+    'Moldova' => 'Moldova',
+    'Monaco' => 'Monaco',
+    'Mongolia' => 'Mongolia',
+    'Montenegro' => 'Montenegro',
+    'Montserrat' => 'Montserrat',
+    'Morocco' => 'Morocco',
+    'Mozambique' => 'Mozambique',
+    'Myanmar' => 'Myanmar',
+    'Namibia' => 'Namibia',
+    'Nauru' => 'Nauru',
+    'Nepal' => 'Nepal',
+    'Netherlands' => 'Netherlands',
+    'Netherlands Antilles' => 'Netherlands Antilles',
+    'New Caledonia' => 'New Caledonia',
+    'New Zealand' => 'New Zealand',
+    'Nicaragua' => 'Nicaragua',
+    'Niger' => 'Niger',
+    'Nigeria' => 'Nigeria',
+    'Niue' => 'Niue',
+    'Norfolk Island' => 'Norfolk Island',
+    'Northern Mariana Islands' => 'Northern Mariana Islands',
+    'Norway' => 'Norway',
+    'Oman' => 'Oman',
+    'Pakistan' => 'Pakistan',
+    'Palau' => 'Palau',
+    'Palestine' => 'Palestine',
+    'Panama' => 'Panama',
+    'Papua New Guinea' => 'Papua New Guinea',
+    'Paraguay' => 'Paraguay',
+    'Peru' => 'Peru',
+    'Philippines' => 'Philippines',
+    'Pitcairn' => 'Pitcairn',
+    'Poland' => 'Poland',
+    'Portugal' => 'Portugal',
+    'Puerto Rico' => 'Puerto Rico',
+    'Qatar' => 'Qatar',
+    'Reunion' => 'Reunion',
+    'Romania' => 'Romania',
+    'Russian Federation' => 'Russian Federation',
+    'Rwanda' => 'Rwanda',
+    'Saint Vincent and the Grenadines' => 'Saint Vincent and the Grenadines',
+    'San Marino' => 'San Marino',
+    'Sao Tome and Principe' => 'Sao Tome and Principe',
+    'Saudi Arabia' => 'Saudi Arabia',
+    'Senegal' => 'Senegal',
+    'Serbia' => 'Serbia',
+    'Seychelles' => 'Seychelles',
+    'Sierra Leone' => 'Sierra Leone',
+    'Singapore' => 'Singapore',
+    'Slovakia' => 'Slovakia',
+    'Slovenia' => 'Slovenia',
+    'Solomon Islands' => 'Solomon Islands',
+    'Somalia' => 'Somalia',
+    'South Africa' => 'South Africa',
+    'South Georgia' => 'South Georgia',
+    'Spain' => 'Spain',
+    'Sri Lanka' => 'Sri Lanka',
+    'St. Kitts and Nevis' => 'St. Kitts and Nevis',
+    'St. Lucia' => 'St. Lucia',
+    'St. Pierre and Miquelon' => 'St. Pierre and Miquelon',
+    'Sudan' => 'Sudan',
+    'Suriname' => 'Suriname',
+    'Swaziland' => 'Swaziland',
+    'Sweden' => 'Sweden',
+    'Switzerland' => 'Switzerland',
+    'Syrian Arab Republic' => 'Syrian Arab Republic',
+    'Taiwan' => 'Taiwan',
+    'Tajikistan' => 'Tajikistan',
+    'Tanzania' => 'Tanzania',
+    'Thailand' => 'Thailand',
+    'The Gambia' => 'The Gambia',
+    'Togo' => 'Togo',
+    'Tokelau' => 'Tokelau',
+    'Tonga' => 'Tonga',
+    'Trinidad and Tobago' => 'Trinidad and Tobago',
+    'Tunisia' => 'Tunisia',
+    'Turkey' => 'Turkey',
+    'Turkmenistan' => 'Turkmenistan',
+    'Turks and Caicos Islands' => 'Turks and Caicos Islands',
+    'Tuvalu' => 'Tuvalu',
+    'Uganda' => 'Uganda',
+    'Ukraine' => 'Ukraine',
+    'United Arab Emirates' => 'United Arab Emirates',
+    'United Kingdom' => 'United Kingdom',
+    'Uruguay' => 'Uruguay',
+    'Uzbekistan' => 'Uzbekistan',
+    'Vanuatu' => 'Vanuatu',
+    'Venezuela' => 'Venezuela',
+    'Viet Nam' => 'Viet Nam',
+    'Virgin Islands' => 'Virgin Islands',
+    'Western Samoa' => 'Western Samoa',
+    'Yemen' => 'Yemen',
+    'Yugoslavia' => 'Yugoslavia',
+    'Zaire' => 'Zaire',
+    'Zambia' => 'Zambia',
+    'Zimbabwe' => 'Zimbabwe',
+  );
+};
diff --git acquia_agent/acquia_agent_streams.inc acquia_agent/acquia_agent_streams.inc
deleted file mode 100644
index bbf59fb..0000000
--- acquia_agent/acquia_agent_streams.inc
+++ /dev/null
@@ -1,313 +0,0 @@
-<?php
-// $Id$
-
-/**
- * @file
- *   XML-RPC communication functions for Acquia communication.
- */
-
-/**
- * Performs one or more XML-RPC request(s), using a PHP stream context
- * when creating the socket.  This function is copied and modified
- * from Drupal 6's common.inc and xmlrpc.inc.
- *
- * This function should never be called directly - use acquia_agent_call().
- *
- * @param $context
- *   A PHP stream context created with stream_create_context().  This
- *   context will be used when a socket connection to the XML-RPC
- *   endpoint is created.
- * @param ...
- *   The rest of the parameters and return values are the same as xmlrpc().
- */
-function _acquia_agent_xmlrpc() {
-  require_once DRUPAL_ROOT . '/includes/xmlrpc.inc';
-
-  $args = func_get_args();
-  $context = array_shift($args);
-  $url = array_shift($args);
-  if (is_array($args[0])) {
-    $method = 'system.multicall';
-    $multicall_args = array();
-    foreach ($args[0] as $call) {
-      $multicall_args[] = array('methodName' => array_shift($call), 'params' => $call);
-    }
-    $args = array($multicall_args);
-  }
-  else {
-    $method = array_shift($args);
-  }
-  $xmlrpc_request = xmlrpc_request($method, $args);
-  $result = acquia_agent_http_request($context, $url, array("Content-Type" => "text/xml"), 'POST', $xmlrpc_request->xml);
-  if ($result->code != 200) {
-    xmlrpc_error($result->code, $result->error);
-    return FALSE;
-  }
-  $message = xmlrpc_message($result->data);
-  // Now parse what we've got back
-  if (!xmlrpc_message_parse($message)) {
-    // XML error
-    xmlrpc_error(-32700, t('Parse error. Not well formed'));
-    return FALSE;
-  }
-  // Is the message a fault?
-  if ($message->messagetype == 'fault') {
-    xmlrpc_error($message->fault_code, $message->fault_string);
-    return FALSE;
-  }
-  // Message must be OK
-  return $message->params[0];
-}
-
-/**
- * Builds a stream context based on a url and local .pem file if available.
- */
-function acquia_agent_stream_context_create($url, $module = 'acquia_agent') {
-  $opts = array();
-  $uri = parse_url($url);
-  if (isset($uri['scheme']) && ($uri['scheme'] == 'https') && variable_get('acquia_agent_verify_peer', 0)) {
-    // Look for a local certificate to validate the server identity.
-    $pem_file = drupal_get_path('module', $module) . '/' . $uri['host'] . '.pem';
-    if (file_exists($pem_file)) {
-      $opts['ssl'] = array(
-        'verify_peer' => TRUE,
-        'cafile' => $pem_file,
-        'allow_self_signed' => FALSE, // doesn't mean anything in this case
-        'CN_match' => $uri['host']);
-    }
-  }
-  return stream_context_create($opts);
-}
-
-/**
- * Perform an HTTP request.  This function is copied and modified
- * from Drupal 6's common.inc.
- *
- * @param $context
- *   A PHP stream context created with stream_create_context().  This
- *   context will be used when a socket connection is created.
- * @param ...
- *   The rest of the parameters and return values are the same as xmlrpc().
- */
-function acquia_agent_http_request($context, $url, $headers = array(), $method = 'GET', $data = NULL, $retry = 3) {
-  $result = new stdClass();
-
-  // Parse the URL and make sure we can handle the schema.
-  $uri = parse_url($url);
-
-  switch ($uri['scheme']) {
-    case 'http':
-      $port = isset($uri['port']) ? $uri['port'] : 80;
-      $host = $uri['host'] . ($port != 80 ? ':' . $port : '');
-      $fp = @fsockopen($uri['host'], $port, $errno, $errstr, 15);
-      break;
-    case 'https':
-      // Note: Only works for PHP 4.3 compiled with OpenSSL.
-      $port = isset($uri['port']) ? $uri['port'] : 443;
-      $host = $uri['host'] . ($port != 443 ? ':' . $port : '');
-      if (!isset($context)) {
-        $fp = @fsockopen('ssl://' . $uri['host'], $port, $errno, $errstr, 20);
-      }
-      else {
-        $fp = @stream_socket_client('ssl://' . $uri['host'] . ':' . $port, $errno, $errstr, 20, STREAM_CLIENT_CONNECT, $context);
-        if (!$fp && $errno == 0) {
-          // An SSL error occurred.  I do not know of any way to get
-          // an error code or message programmatically.  By not having
-          // an @ before stream_socket_client(), the actual SSL error
-          // will be logged via watchdog.
-          $errno = 999;
-          $errstr = t('SSL error creating socket');
-        }
-      }
-      break;
-    default:
-      $result->error = 'invalid schema ' . $uri['scheme'];
-      return $result;
-  }
-
-  // Make sure the socket opened properly.
-  if (!$fp) {
-    // When a network error occurs, we use a negative number so it does not
-    // clash with the HTTP status codes.
-    $result->code = -$errno;
-    $result->error = trim($errstr);
-    return $result;
-  }
-
-  // Construct the path to act on.
-  $path = isset($uri['path']) ? $uri['path'] : '/';
-  if (isset($uri['query'])) {
-    $path .= '?' . $uri['query'];
-  }
-
-  // Create HTTP request.
-  $defaults = array(
-    // RFC 2616: "non-standard ports MUST, default ports MAY be included".
-    // We don't add the port to prevent from breaking rewrite rules checking the
-    // host that do not take into account the port number.
-    'Host' => "Host: $host",
-    'User-Agent' => 'User-Agent: Drupal (+http://drupal.org/)',
-  );
-
-  // Only add Content-Length if we actually have any content or if it is a POST
-  // or PUT request. Some non-standard servers get confused by Content-Length in
-  // at least HEAD/GET requests, and Squid always requires Content-Length in
-  // POST/PUT requests.
-  if (!empty($data) || $method == 'POST' || $method == 'PUT') {
-    $defaults['Content-Length'] = 'Content-Length: ' . strlen($data);
-  }
-
-  // If the server url has a user then attempt to use basic authentication
-  if (isset($uri['user'])) {
-    $defaults['Authorization'] = 'Authorization: Basic ' . base64_encode($uri['user'] . (!empty($uri['pass']) ? ":" . $uri['pass'] : ''));
-  }
-
-  foreach ($headers as $header => $value) {
-    $defaults[$header] = $header . ': ' . $value;
-  }
-
-  $request = $method . ' ' . $path . " HTTP/1.0\r\n";
-  $request .= implode("\r\n", $defaults);
-  $request .= "\r\n\r\n";
-  if ($data) {
-    $request .= $data . "\r\n";
-  }
-  $result->request = $request;
-
-  fwrite($fp, $request);
-
-  // Fetch response.
-  $response = '';
-  while (!feof($fp) && $chunk = fread($fp, 1024)) {
-    $response .= $chunk;
-  }
-  fclose($fp);
-
-  // Parse response.
-  list($split, $result->data) = explode("\r\n\r\n", $response, 2);
-  $split = preg_split("/\r\n|\n|\r/", $split);
-
-  list($protocol, $code, $text) = explode(' ', trim(array_shift($split)), 3);
-  $result->headers = array();
-
-  // Parse headers.
-  while ($line = trim(array_shift($split))) {
-    list($header, $value) = explode(':', $line, 2);
-    if (isset($result->headers[$header]) && $header == 'Set-Cookie') {
-      // RFC 2109: the Set-Cookie response header comprises the token Set-
-      // Cookie:, followed by a comma-separated list of one or more cookies.
-      $result->headers[$header] .= ',' . trim($value);
-    }
-    else {
-      $result->headers[$header] = trim($value);
-    }
-  }
-
-  $responses = array(
-    100 => 'Continue', 101 => 'Switching Protocols',
-    200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content',
-    300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect',
-    400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed',
-    500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported'
-  );
-  // RFC 2616 states that all unknown HTTP codes must be treated the same as the
-  // base code in their class.
-  if (!isset($responses[$code])) {
-    $code = floor($code / 100) * 100;
-  }
-
-  switch ($code) {
-    case 200: // OK
-    case 304: // Not modified
-      break;
-    case 301: // Moved permanently
-    case 302: // Moved temporarily
-    case 307: // Moved temporarily
-      $location = $result->headers['Location'];
-
-      if ($retry) {
-        $result = acquia_agent_http_request($context, $result->headers['Location'], $headers, $method, $data, --$retry);
-        $result->redirect_code = $result->code;
-      }
-      $result->redirect_url = $location;
-
-      break;
-    default:
-      $result->error = $text;
-  }
-
-  $result->code = $code;
-  return $result;
-}
-
-/**
- * Determine if a response from the Acquia Network is valid.
- *
- * @param $data
- *   The data array returned by acquia_agent_call().
- * @return
- *   TRUE or FALSE.
- */
-function acquia_agent_valid_response($data) {
-  $authenticator = $data['authenticator'];
-  $result = $data['result'];
-  $result_auth = $result['authenticator'];
-  $valid = ($authenticator['nonce'] == $result_auth['nonce']);
-  $valid = $valid && ($authenticator['time'] < $result_auth['time']);
-  $key = acquia_agent_settings('acquia_key');
-  $hash = _acquia_agent_hmac($key, $result_auth['time'], $result_auth['nonce'], $result['body']);
-  return $valid && ($hash == $result_auth['hash']);
-}
-
-/**
- * Send a XML-RPC request.
- *
- * This function should never be called directly - use acquia_agent_call().
- */
-function _acquia_agent_request($url, $method, $data) {
-  $ctx = acquia_agent_stream_context_create($url);
-  if (!$ctx) {
-    // TODO: what's a meaningful fault code?
-    xmlrpc_error(-1, t('SSL is not supported or setup failed'));
-    $result = FALSE;
-  }
-  else {
-    $result = _acquia_agent_xmlrpc($ctx, $url, $method, $data);
-  }
-  if ($errno = xmlrpc_errno()) {
-    watchdog('acquia agent', '@message (@errno): %server - %method - <pre>@data</pre>', array('@message' => xmlrpc_error_msg(), '@errno' => xmlrpc_errno(), '%server' => $url, '%method' => $method, '@data' => print_r($data, TRUE)), WATCHDOG_ERROR);
-  }
-  return $result;
-}
-
-/**
- * Creates an authenticator based on xmlrpc params and a HMAC-SHA1.
- */
-function _acquia_agent_authenticator($params = array(), $identifier = NULL, $key = NULL) {
-  if (empty($identifier)) {
-    $identifier = acquia_agent_settings('acquia_identifier');
-  }
-  if (empty($key)) {
-    $key = acquia_agent_settings('acquia_key');
-  }
-  $time = REQUEST_TIME;
-  $nonce = md5(drupal_random_bytes(55));
-  $authenticator['identifier'] = $identifier;
-  $authenticator['time'] = $time;
-  $authenticator['hash'] = _acquia_agent_hmac($key, $time, $nonce, $params);
-  $authenticator['nonce'] = $nonce;
-  return $authenticator;
-}
-
-/**
- * Calculates a HMAC-SHA1 according to RFC2104 (http://www.ietf.org/rfc/rfc2104.txt).
- * With addition of xmlrpc params.
- */
-function _acquia_agent_hmac($key, $time, $nonce, $params) {
-  return base64_encode(
-    pack("H*", sha1((str_pad($key, 64, chr(0x00)) ^ (str_repeat(chr(0x5c), 64))) .
-    pack("H*", sha1((str_pad($key, 64, chr(0x00)) ^ (str_repeat(chr(0x36), 64))) .
-    $time . ':' . $nonce . ':' . $key . ':' . serialize($params)))))
-  );
-}
-
