Index: subscribe.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/subscribe/subscribe.module,v
retrieving revision 1.21.2.5
diff -u -p -r1.21.2.5 subscribe.module
--- subscribe.module   1 Nov 2006 15:45:56 -0000   1.21.2.5
+++ subscribe.module   1 Dec 2006 06:16:02 -0000
@@ -37,13 +37,9 @@ function subscribe_menu($may_cache) {
       'type' => MENU_DEFAULT_LOCAL_TASK,
       'weight' => -10);
     $items[] = array('path' => 'admin/subscribe/sub/wizard', 'title' => t('subscribe to channel'),
-      'callback' => 'subscribe_url_form',
+      'callback' => 'subscribe_channel_form',
       'access' => $access,
       'type' => MENU_LOCAL_TASK);
-    $items[] = array('path' => 'admin/subscribe/sub/vocabmap', 'title' => t('Channel options'),
-      'callback' => 'subscribe_vocabmap_form',
-      'access' => $access,
-      'type' => MENU_CALLBACK);
     $items[] = array('path' => 'admin/subscribe/delete', 'title' => t('Delete subscription'),
       'callback' => 'subscribe_delete_form',
       'access' => $access,
@@ -93,7 +89,7 @@ function subscribe_nodeapi(&$node, $op, 
 
     case 'view':
       if (isset($node->remote_nid)) {
-        $node = theme_external_node($node, 0, 1);
+        $node = theme('external_node', $node, 0, 1);
       }
       break;
 
@@ -122,9 +118,9 @@ function subscribe_node_load($nid) {
 function theme_external_node($node, $teaser = 0, $page = 0) {
   $node->title = t('%node-title (from %remote-url)', array('%node-title' => $node->title, '%remote-url' => $node->remote_site_url));
 
-  $remote_url = $node->remote_site_url. '/';
-  $item[] = t('<a href="%remote-url">Visit this page</a>', array('%remote-url' => $remote_url. "node/$node->remote_nid"));
-  $item[] = t('Authored by: <a href="%remote-author-url">%remote-author</a>', array('%remote-author' => $node->remote_author, '%remote-author-url' => $remote_url. "user/$node->remote_uid"));
+  $remote_url = $node->remote_site_url .'/';
+  $item[] = l(t('Visit this page'), $remote_url .'node/'. $node->remote_nid);
+  $item[] = t('Authored by') .': '. l($node->remote_author, $remote_url .'user/'. $node->remote_uid);
 
   $referring_info = theme('item_list', $item);
 
@@ -144,7 +140,7 @@ function theme_external_node($node, $tea
  */
 function subscribe_overview() {
   $output = '<h3>'. t('Subscribed to:') .'</h3>';
-  $header = array(t('Name'),t('URI'), t('Last Received'), t('Operations'));
+  $header = array(t('Name'), t('URI'), t('Last received'), array('data' => t('Operations'), 'colspan' => 3));
   $result = db_query('SELECT * FROM {subscribe_subscriptions}');
   $row = array();
   while ($sub = db_fetch_object($result)) {
@@ -152,13 +148,12 @@ function subscribe_overview() {
       $sub->name,
       $sub->url,
       $sub->last_update ? format_date($sub->last_update) : t('never'),
-      '<table><tr><td>' .
-      // l(t('edit'), "admin/subscribe/sub/$sub->sid/edit") . '</td><td>' .
-      l(t('pull'), "admin/subscribe/pull/$sub->sid") . '</td><td>' .
-      l(t('delete'), "admin/subscribe/delete/$sub->sid") . '</td></tr></table>'
-      );
+      l(t('pull'), 'admin/subscribe/pull/'. $sub->sid),
+      l(t('edit subscription'), 'admin/subscribe/sub/wizard/'. $sub->sid),
+      l(t('delete'), 'admin/subscribe/delete/'. $sub->sid),
+    );
   }
-  $output .= ($row) ? theme('table', $header, $row) : '<p>' . t('You currently have no subscriptions.') . '</p><p>' . t('Would you like to') . ' ' . l(t('subscribe to a channel'),'admin/subscribe/sub/wizard') . '?</p>';
+  $output .= $row ? theme('table', $header, $row) : '<p>'. t('You currently have no subscriptions.') .'</p><p>'. t('Would you like to') .' '. l(t('subscribe to a channel'), 'admin/subscribe/sub/wizard') .'?</p>';
 
   return $output;
 }
@@ -207,13 +202,20 @@ function subscribe_delete($edit) {
   return $output;
 }
 
-function subscribe_url_form() {
-  // this form is a great opportunity for AJAXification
-  $edit = isset($_SESSION['edit']) ? $_SESSION['edit'] : array();
+function subscribe_channel_form($sid = NULL) {
+  if ($sid) {
+    $subscription = subscribe_subscription_load($sid);
+    $channel = subscribe_xmlc_get_channel($subscription->url, $subscription->channel_id, $subscription->username, $subscription->pass);
+  }
+  else {
+    $channel = array('vocabularies' => array());
+  }
+
+  // TODO: this form is a great opportunity for AJAXification
   $form = array();
   $form['channel'] = array(
     '#type' => 'fieldset',
-    '#title' => 'Subscribe to channel'
+    '#title' => 'Subscribe to channel',
   );
   $form['channel']['url'] = array(
     '#type' => 'textfield',
@@ -221,106 +223,173 @@ function subscribe_url_form() {
     '#size' => '70',
     '#maxlength' => '255',
     '#description' => t('E.g. http://example.com/xmlrpc.php'),
-    '#default_value' => isset($edit['url']) ? $edit['url'] : 'http://'
+    '#default_value' => isset($subscription) ? $subscription->url : 'http://',
   );
-  $form['channel']['channel']['channel_id'] = array(
+  $form['channel']['channel_id'] = array(
     '#type' => 'textfield',
     '#title' => 'Channel identifier',
     '#size' => '10',
     '#maxlength' => '255',
     '#description' => t('Typically an integer corresponding to the channel ID'),
-    '#default_value' => isset($edit['channel_id']) ? $edit['channel_id'] : ''
+    '#default_value' => isset($subscription) ? $subscription->channel_id : '',
   );
   $form['channel']['username'] = array(
     '#type' => 'textfield',
     '#title' => t('Username'),
     '#size' => '10',
     '#maxlength' => '60',
-    '#default_value' => isset($edit['username']) ? $edit['username'] : ''
+    '#default_value' => isset($subscription) ? $subscription->username : '',
   );
   $form['channel']['pass'] = array(
     '#type' => 'password',
     '#title' => t('Password'),
     '#size' => '10',
-    '#maxlength' => '32'
+    '#maxlength' => '32',
   );
+  
+  if (empty($_POST) && isset($subscription)) {
+    $form['channel']['pass']['#attributes'] = array('value' => $subscription->pass);
+  }
+  
+  // Generate the vocabulary mapping fieldset.
+  $vocabularies = taxonomy_get_vocabularies();
+
+  if (!$vocabularies && $channel['vocabularies']) {
+    drupal_set_message(t('In order to map remote vocabularies to local vocabularies, you must first create your local vocabularies using administer &gt; categories.'));
+  }
+  else {
+    $options = array();
+    foreach ($vocabularies as $v) {
+      $options[$v->vid] = $v->name;
+    }
+    $options['0'] = t('discard');
+  
+    // TODO: lots of error checking needs to go here to make sure
+    // the local vocabulary select box only includes vocabularies
+    // whose attributes match the remote vocabularies
+    $form['vocabmap'] = array('#type' => 'fieldset',
+      '#title' => t('Vocabulary mapping'),
+      '#tree' => TRUE,
+      '#theme' => 'subscribe_vocabmap_fieldset',
+    );
+    $vocabulary_map = subscribe_get_vocabmap($sid);    
+    foreach ($channel['vocabularies'] as $remote_vid => $remote_vocabulary) {
+      $form['vocabmap'][$remote_vid] = array(
+        '#type' => 'select',
+        '#options' => $options,
+        '#default_value' => isset($vocabulary_map[$remote_vid]) ? $vocabulary_map[$remote_vid] : NULL,
+        '#vname' => $remote_vocabulary['name'],
+      );
+    }
+  }
+
+  $form['receiving'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Receiving content'),
+  );
+  $form['receiving']['pushpull'] = array(
+    '#type' => 'radios',
+    '#title' => t('Method'),
+    '#default_value' => isset($subscription) ? $subscription->method : 0,
+    '#options' => array(t('Push: Receive content from channel automatically when the channel decides to send it.'), t('Pull: Receive content from channel only when you manually request it (your server must allow HTTP out).')),
+    '#description' => t('Choose how you would like this site to receive content.'),
+  );
+  
+  // TODO: $form['_channel'] = array('#type' => 'value', '#default_value' => NULL);
+  
+  $form['sid'] = array('#type' => 'value', '#value' => $sid);
+  
   $form['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Continue')
+    '#type' => form_get_errors() ? 'button' : 'submit',
+    '#value' => t('Submit'),
   );
-  unset($_SESSION['edit']);
-  return drupal_get_form('subscribe_url_form', $form);
+
+  return drupal_get_form('subscribe_channel_form', $form);
 }
 
 /**
- * Validator for initial subscription form.
+ * Validator for subscription form.
  */
-function subscribe_url_form_validate($form_id, $form_values) {
+function subscribe_channel_form_validate($form_id, $form_values) {
   if ($form_values['url'] == '') {
     form_set_error('url', t('You must specify the URL of the channel.'));
   }
   elseif (!valid_url($form_values['url'], TRUE)) {
     form_set_error('url', t('That is not a valid URL.'));
   }
-  if (form_get_errors()) {
-    $_SESSION['edit'] = $form_values;
+  elseif (!isset($form_values['sid']) && subscribe_subscribed_to_channel($form_values['url'], $form_values['channel_id'])) {
+    form_set_error('', t('You are already subscribed to this channel.'));
   }
-}
-
-function subscribe_url_form_submit($form_id, $form_values) {
-  $url = $form_values['url'];
-  $channel_id = check_plain($form_values['channel_id']);
-  $username = check_plain($form_values['username']);
-  $pass = check_plain($form_values['pass']);
-  $result = subscribe_xmlc_may_subscribe($url, $channel_id, $username, $pass);
-  if ($result[0]) { // if user may subscribe
-    $form_values = array();
-    $form_values['name']         = $result[1];
-    $form_values['node_types']   = $result[2];
-    $form_values['vocabularies'] = $result[3];
-    $form_values['base_url']     = $result[4];
-    $form_values['channel_id']   = $channel_id;
-    $form_values['username']     = $username;
-    $form_values['pass']         = $pass;
-    $form_values['url']          = $url;
-
-    // now that we have a response we can do preliminary validation
-
-    if (!$form_values['node_types']) {
-      drupal_set_message(t('The channel is not currently publishing any node types. This is probably a misconfiguration on the publishing site.'), 'error');
-      drupal_goto('admin/subscribe/sub/wizard');
-    }
-
-    $nodetypes = node_get_types();
-    $missing = array();
-    foreach (array_keys($form_values['node_types']) as $type) {
-      if (!key_exists($type, $nodetypes)) {
-        $missing[] = $type;
+  else {
+    // If it looks valid up until this point, get the channel information.
+    $channel = subscribe_xmlc_get_channel($form_values['url'], $form_values['channel_id'], $form_values['username'], $form_values['pass']);
+    if ($channel) { // if user may subscribe
+      // now that we have a response we can do preliminary validation
+      if (!$channel['node_types']) {
+        form_set_error('', t('The channel is not currently publishing any node types. This is probably a misconfiguration on the publishing site.'));
       }
-    }
-    if ($missing) {
-      if (count($missing) == 1) {
-        $type = $missing[0];
-        drupal_set_message(t('The remote site is publishing nodes of type %type but you do not support nodes of this type on your site. Please enable the appropriate module.', array('%type' => theme('placeholder', $type))), 'error');
+      
+      $nodetypes = node_get_types();
+      $missing = array();
+      foreach (array_keys($channel['node_types']) as $type) {
+        if (!key_exists($type, $nodetypes)) {
+          $missing[] = $type;
+        }
       }
-      else {
-        $phrase = '';
-        foreach ($missing as $type) {
-          $phrase .= ', ' . $type;
+      if ($missing) {
+        if (count($missing) == 1) {
+          $type = $missing[0];
+          form_set_error('', t('The remote site is publishing nodes of type %type but you do not support nodes of this type on your site. Please enable the appropriate module.', array('%type' => theme('placeholder', $type))));
         }
-        drupal_set_message(t('The remote site is publishing nodes of the following types: %types; but you do not support nodes of these types on your site. Please enable the appropriate modules.', array('%types' => theme('placeholder', ltrim($phrase, ',')), 'error')));
+        else {
+          $phrase = '';
+          foreach ($missing as $type) {
+            $phrase .= ', ' . $type;
+          }
+          form_set_error('', t('The remote site is publishing nodes of the following types: %types; but you do not support nodes of these types on your site. Please enable the appropriate modules.', array('%types' => theme('placeholder', ltrim($phrase, ',')))));
+        }
+      }
+
+      // Set channel so once we validate succesfully, the _submit can use this.
+      if (!form_get_errors()) {
+        form_set_value(array('#parents' => array('_channel')), $channel);
       }
-      drupal_goto('admin/subscribe/sub/wizard');
+    }
+    else {
+      form_set_error('', t('Unable to subscribe.'));
     }
   }
+}
+
+function subscribe_channel_form_submit($form_id, $form_values) {
+  $channel = subscribe_xmlc_get_channel($form_values['url'], $form_values['channel_id'], $form_values['username'], $form_values['pass']);
+  
+  $remote_vids = array();
+  $local_vids = array();
+  foreach ($form_values['vocabmap'] as $remote_vid => $local_vid) {
+    if ($local_vid != 0) {
+      $remote_vids[] = $remote_vid;
+      $local_vids[] = $local_vid;
+    }
+  }
+  
+  if ($form_values['sid']) {
+    $subscription = subscribe_subscription_load($form_values['sid']);
+    $cancel_result = subscribe_xmlc_cancel_subscription($subscription);
+  }
+  
+  $result = subscribe_xmlc_subscribe($form_values['url'], $form_values['channel_id'], $form_values['username'], $form_values['pass'], $form_values['pushpull'], $local_vids, $remote_vids, array());
+  if ($result['status'] = 'ok') {
+    $form_values['rsid'] = $result['sid'];
+    $form_values['method'] = $form_values['pushpull'];
+    $form_values['sid'] = subscribe_subscription_save($form_values);
+    subscribe_vocabmap_save($form_values['vocabmap'], $form_values['sid']);
+    drupal_set_message(t('Subscription to channel %name established.', array('%name' => theme('placeholder', $form_values['name']))));
+  }
   else {
-    $msg = t('Unable to subscribe.');
-    drupal_set_message($msg, 'error');
-    $_SESSION['edit'] = $form_values;
-    drupal_goto('admin/subscribe/sub/wizard');
+    drupal_set_message(t('Could not subscribe.'), 'error');
   }
-  $_SESSION['edit'] = $form_values;
-  return ('admin/subscribe/sub/vocabmap');
+  return 'admin/subscribe';
 }
 
 
@@ -328,158 +397,44 @@ function subscribe_url_form_submit($form
  * The form for mapping vocabularies from remote vocabularies to local vocabularies
  * if the publishing site is publishing vocabularies; also sets push/pull.
  */
-function subscribe_vocabmap_form() {
-  if (!isset($_SESSION['edit'])) {
-    drupal_set_message(t('Unable to retrieve session data.'), 'error');
-    drupal_goto('/subscribe/sub/wizard');
-  }
-  $edit = $_SESSION['edit'];
-  $remote_vocabularies = array();
 
-  foreach ($edit['vocabularies'] as $vid => $va) {
-    $remote_vocabularies[$vid] = (object)$va;
-  }
-
-  $vocabularies = taxonomy_get_vocabularies();
-  $voc_names = array();
-  $voc_options = array();
-  if (!$vocabularies && $remote_vocabularies) {
-    drupal_set_message(t('In order to map remote vocabularies to local vocabularies, you must first create your local vocabularies using administer &gt; categories.'), 'error');
-  }
-
-  foreach ($vocabularies as $v) {
-    $voc_names[$v->name] = $v->vid;
-    $voc_options[$v->vid] = $v->name;
-  }
-  $voc_options['0'] = t('discard');
-
-  // lots of error checking needs to go here to make sure
-  // the local vocabulary select box only includes vocabularies
-  // whose attributes match the remote vocabularies
-
-  $form = array();
-  $form['vocabmap'] = array();
-
-  foreach ($remote_vocabularies as $vid => $v) {
-    // autoselect
-    $selected_voc = '';
-    if (isset($voc_names[$v->name])) {
-      $selected_voc = $voc_names[$v->name];
-    }
-
-    $form['vocabmap']['localvoc' . $vid] = array(
-      '#type' => 'select',
-      '#options' => $voc_options,
-      '#default_value' => $selected_voc,
-      '#vname' => $v->name
-    );
-  }
-
-  $form['receiving'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Receiving Content')
-  );
-  $form['receiving']['pushpull'] = array(
-    '#type' => 'radios',
-    '#title' => t('Method'),
-    '#default_value' => isset($edit['pushpull']) ? $edit['pushpull'] : 0,
-    '#options' => array(t('Push: Receive content from channel automatically when the channel decides to send it.'), t('Pull: Receive content from channel only when you manually request it (your server must allow HTTP out).')),
-    '#description' => t('Choose how you would like this site to receive content.')
-  );
-  $form['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Subscribe to channel')
-  );
-
-  return drupal_get_form('subscribe_vocabmap_form', $form);
-}
-
-function theme_subscribe_vocabmap_form($form) {
-  $header = array(t('Remote Vocabulary'), '', t('Local Vocabulary'));
+function theme_subscribe_vocabmap_fieldset($form) {
+  $header = array(t('Remote vocabulary'), '', t('Local vocabulary'));
   $rows = array();
-  foreach (element_children($form['vocabmap']) as $key) {
+  foreach (element_children($form) as $key) {
     $rows[] = array(
-      array('data' => $form['vocabmap'][$key]['#vname']),
+      array('data' => $form[$key]['#vname']),
       array('data' => '&#8594;'),
-      array('data' => form_render($form['vocabmap'][$key]))
+      array('data' => form_render($form[$key]))
     );
   }
   if ($rows) {
-    $output = theme('fieldset', array('#title' => t('Vocabulary Mapping'), '#children' => theme_table($header, $rows)));
+    $output = theme('table', $header, $rows);
   }
   $output .= form_render($form);
   return $output;
 }
 
-function subscribe_vocabmap_form_validate($form, $form_values) {
-  if (!isset($_SESSION['edit'])) {
-    drupal_set_message(t('Unable to retrieve session data.'), 'error');
-    drupal_goto('/subscribe/sub/wizard');
-  }
-  $edit = $_SESSION['edit'];
-   if (!subscribe_subscription_validate($edit['url'], $edit['channel_id'])) {
-    drupal_set_message(t('You are already subscribed to this channel.'), 'error');
-    drupal_goto('admin/subscribe');
-   }
-}
-
-function subscribe_vocabmap_form_submit($form, $edit) {
-  if (!isset($_SESSION['edit'])) {
-    drupal_set_message(t('Unable to retrieve session data.'), 'error');
-    drupal_goto('/subscribe/sub/wizard');
-  }
-  $edit = array_merge($_SESSION['edit'], $edit);
-  unset($_SESSION['edit']);
-  $edit['channel_id'] = check_plain($edit['channel_id']);
-  $edit['username'] = check_plain($edit['username']);
-  $edit['pass'] = check_plain($edit['pass']);
-
-  $remote_vids = array();
-  $local_vids = array();
-  $vocab_map = _subscribe_extract_vocab_map($edit);
-  foreach ($vocab_map as $rvid => $local_vid) {
-    if ($local_vid != 0) {
-      $remote_vids[] = $rvid;
-      $local_vids[] = $local_vid;
-    }
-  }
-
-  $result = subscribe_xmlc_subscribe($edit['url'], $edit['channel_id'], $edit['username'], $edit['pass'], $edit['pushpull'], $local_vids, $remote_vids, array());
-  if ($result['status'] = 'ok') {
-    $edit['rsid'] = $result['sid'];
-    $edit['method'] = $edit['pushpull'];
-    $edit['sid'] = subscribe_subscription_save($edit);
-    subscribe_vocabmap_save($vocab_map, $edit['sid']);
-    drupal_set_message(t('Subscription to channel %name established.', array('%name' => theme('placeholder', $edit['name']))));
-    drupal_goto('admin/subscribe');
-  }
-  else {
-    drupal_set_message(t('Could not subscribe.'), 'error');
-    drupal_goto('admin/subscribe');
-  }
-}
-
 /**
  * Save local-remote vocabulary mapping.
  *
- * @param $local_vocabularies
- *   Array which must contain local/remote mappings
- *   encoded as e.g., $edit['localvoc2'] = 4.
- * @param $sid subscription id
- *
- * @return
- *
+ * @param $vocabulary_map
+ *   Array which must contain local/remote mappings encoded as e.g.,
+ *   array(12 => 4) where 12 is the remote vocabulary ID and 4 is local.
+ * @param $sid 
+ *   Subscription id
  */
-function subscribe_vocabmap_save($local_vocabularies, $sid) {
+function subscribe_vocabmap_save($vocabulary_map, $sid) {
   db_query("DELETE FROM {subscribe_vocab_map} WHERE sid = '%s'", $sid);
-  foreach ($local_vocabularies as $lvid => $rvid) {
-    db_query("INSERT INTO {subscribe_vocab_map} (sid, remote_vid, local_vid) VALUES (%d, %d, %d)", $sid, $rvid, $lvid);
+  // TODO: Remote/local were swapped here before, looks okay now.
+  foreach ($vocabulary_map as $remote_vid => $local_vid) {
+    db_query('INSERT INTO {subscribe_vocab_map} (sid, remote_vid, local_vid) VALUES (%d, %d, %d)', $sid, $remote_vid, $local_vid);
   }
 }
 
 /**
  * Generate a mapping of local vocabularies for a subscription
- * keyed by remote vocabulary ID: $vocabmap[3] = 4 means that
+ * keyed by remote vocabulary ID: $vocabmap[4] = 3 means that
  * vocabulary 4 on the remote site maps to vocabulary 3 on this site.
  *
  * @param $sid
@@ -487,9 +442,9 @@ function subscribe_vocabmap_save($local_
  */
 function subscribe_get_vocabmap($sid) {
   $vocabmap = array();
-  $result = db_query("SELECT * FROM {subscribe_vocab_map} WHERE sid = %d", $sid);
+  $result = db_query('SELECT * FROM {subscribe_vocab_map} WHERE sid = %d', $sid);
   while ($data = db_fetch_object($result)) {
-    $vocabmap[$data->remote_vid] = taxonomy_get_vocabulary($data->local_vid);
+    $vocabmap[$data->remote_vid] = $data->local_vid;
   }
 
   return $vocabmap;
@@ -505,10 +460,8 @@ function subscribe_get_vocabmap($sid) {
  * @param $channel_id
  *   the id of the channel
  */
-function subscribe_subscription_validate($url, $channel_id) {
-  $result = db_query("SELECT * FROM {subscribe_subscriptions} WHERE url = '%s' AND channel_id = %d", $url, $channel_id);
-  $data = db_fetch_object($result);
-  return !$data;
+function subscribe_subscribed_to_channel($url, $channel_id) {
+  return db_num_rows(db_query("SELECT * FROM {subscribe_subscriptions} WHERE url = '%s' AND channel_id = %d", $url, $channel_id));
 }
 
 /**
@@ -539,7 +492,7 @@ function subscribe_subscription_save($ed
   if ($edit['sid'] && db_result(db_query('SELECT COUNT(sid) FROM {subscribe_subscriptions} WHERE sid = %d', $edit['sid']))) { // existing subscription
     // Prepare the query:
     foreach ($edit as $key => $value) {
-      if (in_array($key, $fields)) {
+      if (in_array($key, $fields) && $key != 'sid') {
         $q[] = db_escape_string($key) ." = '%s'";
         $v[] = $value;
       }
@@ -637,15 +590,16 @@ function subscribe_pull($subscription, $
     $error = xmlrpc_error_msg();
     drupal_set_message($error, 'error');
   }
+
   if ($result['count']) {
     $site_metadata = array('site_url' => $result['site_url'], 'site_name' => $result['site_name'], 'sid' => $subscription->sid);
     list($n_counter, $u_counter, $t_counter) = subscribe_import($result['nodes'], $site_metadata);
-    drupal_set_message(t("New content from %name. Nodes imported: %ncount; nodes updated: %ucount; terms imported: %tcount.", array('%ncount' => $n_counter, '%ucount' => $u_counter, '%tcount' => $t_counter, '%name' => $subscription->name)));
-    db_query("UPDATE {subscribe_subscriptions} SET last_update = %d WHERE sid = %d", time(), $subscription->sid);
+    drupal_set_message(t('New content from %name. Nodes imported: %ncount; nodes updated: %ucount; terms imported: %tcount.', array('%ncount' => $n_counter, '%ucount' => $u_counter, '%tcount' => $t_counter, '%name' => check_plain($subscription->name))));
+    db_query('UPDATE {subscribe_subscriptions} SET last_update = %d WHERE sid = %d', time(), $subscription->sid);
     drupal_goto('admin/subscribe');
   }
   else {
-    drupal_set_message(t('Pull attempt failed for %url.', array('%url' => theme('placeholder', check_plain($subscription->url)))), 'error');
+    drupal_set_message(t('No new/updated content to pull from %url.', array('%url' => theme('placeholder', $subscription->url))));
   }
 }
 
@@ -665,7 +619,7 @@ function subscribe_pull($subscription, $
  * @return an array of count of nodes imported, count of taxonomy terms imported
  */
 function subscribe_import($nodes, $site_metadata) {
-
+  // TODO: Updated nodes not bringing terms or is it just not creating terms, freetagging?
   // required metadata
   $site_url  = $site_metadata['site_url'];
   $site_name = $site_metadata['site_name'];
@@ -678,7 +632,7 @@ function subscribe_import($nodes, $site_
 
   foreach ($nodes as $n) {
     $node = (object)$n;

     // get "external" information
     $remote_url    = $node->url;
     $remote_nid    = $node->nid;
@@ -694,7 +648,7 @@ function subscribe_import($nodes, $site_
     $node->uid = '1';
 
     // do we already have a copy of this node?
-    $local_nid = db_result(db_query("SELECT nid FROM {subscribe_node} WHERE remote_nid = %d AND sid = %d", $node->nid, $sid));
+    $local_nid = db_result(db_query('SELECT nid FROM {subscribe_node} WHERE remote_nid = %d AND sid = %d', $node->nid, $sid));
 
     if ($local_nid) {
       // substitute the local nid for the remote nid
@@ -707,7 +661,7 @@ function subscribe_import($nodes, $site_
       node_save($node);
       $u_counter = $u_counter + 1;
 
-      // will terms be orphaned now if remote terms have changed?
+      // TODO: will terms be orphaned now if remote terms have changed?
     }
     else {
       // force a new local nid
@@ -724,14 +678,14 @@ function subscribe_import($nodes, $site_
 
       // add vocabulary information
       foreach ($node->taxonomy_terms as $remote_term) {
-          // which vocabulary will we be adding it to?
-         $local_vid = $vocab_map[$remote_term['vid']]->vid;
-         if (!$local_vid) {
-            watchdog('subscribe', t('Discarding term %term because remote vocabulary id %vid is not mapped to a local vocabulary.', array('%term' => check_plain($remote_term->name), '%vid' => $remote_term->vid)));
-            continue;
-         }
-         
-         $db_result = db_query("SELECT * FROM {term_data} WHERE LOWER('%s') LIKE LOWER(name) AND vid = %d", trim($remote_term['name']), $local_vid);
+        // which vocabulary will we be adding it to?
+        $local_vid = $vocab_map[$remote_term['vid']];
+        if (!$local_vid) {
+          watchdog('subscribe', t('Discarding term %term because remote vocabulary id %vid is not mapped to a local vocabulary.', array('%term' => check_plain($remote_term->name), '%vid' => $remote_term->vid)));
+          continue;
+        }
+        
+        $db_result = db_query("SELECT * FROM {term_data} WHERE LOWER('%s') LIKE LOWER(name) AND vid = %d", trim($remote_term['name']), $local_vid);
         $local_term = db_fetch_object($db_result);
 
         if ($local_term) { // existing term
@@ -739,16 +693,16 @@ function subscribe_import($nodes, $site_
           $result = db_query("SELECT nid FROM {term_node} WHERE nid = %d AND tid = %d", $local_nid, $local_term->tid);
           $nid = db_result($result);
           if (!$nid) { // this nid-tid pair has not yet been mapped
-            db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $local_nid, $local_term->tid);  
+            db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $local_nid, $local_term->tid);
           }
         }
         else { // term does not exist locally; add new term
           unset($remote_term['tid']); // local Drupal will assign a new tid
           $remote_term['vid'] = $local_vid;
           $remote_term['weight'] = 0; // discard remote weights
-          taxonomy_save_term($remote_term); // sets $remote_term->tid
+          taxonomy_save_term($remote_term); // sets $remote_term['tid']
           $t_counter = $t_counter + 1;
-          db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $local_nid, $remote_term->tid);
+          db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $local_nid, $remote_term['tid']);
         }
       }
     }
@@ -789,6 +743,30 @@ function subscribe_xmlc_may_subscribe($u
 }
 
 /**
+ * Helper function that returns information about a specified channel in an
+ * associative array.
+ */
+function subscribe_xmlc_get_channel($url, $channel_id, $username, $pass) {
+  $result = subscribe_xmlc_may_subscribe($url, check_plain($channel_id), check_plain($username), check_plain($pass));
+
+  // May user even subscribe?
+  if (!$result[0]) {
+    return array();
+  }
+  
+  $channel = array();
+  $channel['name']         = $result[1];
+  $channel['node_types']   = $result[2];
+  $channel['vocabularies'] = $result[3];
+  $channel['base_url']     = $result[4];
+  $channel['channel_id']   = $channel_id;
+  $channel['username']     = $username;
+  $channel['pass']         = $pass;
+  $channel['url']          = $url;
+  return $channel;
+}
+
+/**
  * XMLRPC client to request that remote site which has the publish
  * module installed establish a publishing relationship with client
  * site (that is, this site).
