Index: modules/aggregator/aggregator.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.api.php,v
retrieving revision 1.5
diff -u -r1.5 aggregator.api.php
--- modules/aggregator/aggregator.api.php	24 Aug 2009 17:11:41 -0000	1.5
+++ modules/aggregator/aggregator.api.php	3 Oct 2009 22:08:10 -0000
@@ -82,6 +82,14 @@
  *   $feed->source_string contains the raw feed data as a string. Parse data
  *   from $feed->source_string and expose it to other modules as an array of
  *   data items on $feed->items.
+ * 
+ *   Feed format:
+ *   - $feed->description (string) - description of the feed
+ *   - $feed->image (string) - image for the feed
+ *   - $feed->etag (string) - value of feed's entity tag header field
+ *   - $feed->modified (UNIX timestamp) - value of feed's last modified header 
+ *     field
+ *   - $feed->items (Array) - array of feed items.
  *
  *   By convention, the common format for a single feed item is:
  *   $item[key-name] = value;
@@ -93,6 +101,9 @@
  *   AUTHOR (string) - the feed item's author
  *   GUID (string) - RSS/Atom global unique identifier
  *   LINK (string) - the feed item's URL
+ * 
+ * @return 
+ *   TRUE if parsing was successful, FALSE otherwise.
  *
  * @see hook_aggregator_parse_info()
  * @see hook_aggregator_fetch()
@@ -101,7 +112,11 @@
  * @ingroup aggregator
  */
 function hook_aggregator_parse($feed) {
-  $feed->items = mymodule_parse($feed->source_string);
+  if ($items = mymodule_parse($feed->source_string)) {
+    $feed->items = $items;
+    return TRUE;
+  }
+  return FALSE;  
 }
 
 /**
Index: modules/aggregator/aggregator.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v
retrieving revision 1.424
diff -u -r1.424 aggregator.module
--- modules/aggregator/aggregator.module	25 Sep 2009 15:20:12 -0000	1.424
+++ modules/aggregator/aggregator.module	3 Oct 2009 22:08:11 -0000
@@ -585,20 +585,49 @@
  *   An object describing the feed to be refreshed.
  */
 function aggregator_refresh($feed) {
+  // Store feed URL to track changes.
+  $feed_url = $feed->url;
+
+  // Fetch the feed.
   list($fetcher, $parser, $processors) = _aggregator_get_variables();
   module_invoke($fetcher, 'aggregator_fetch', $feed);
 
   if ($feed->source_string !== FALSE) {
     // Parse the feed.
-    module_invoke($parser, 'aggregator_parse', $feed);
+    if (module_invoke($parser, 'aggregator_parse', $feed)) {
+      // Update feed with parsed data.
+      db_merge('aggregator_feed')
+        ->key(array('fid' => $feed->fid))
+        ->fields(array(
+          'url' => $feed->url,
+          'checked' => REQUEST_TIME,
+          'link' => empty($feed->link) ? $feed->url : $feed->link,
+          'description' => empty($feed->description) ? '' : $feed->description,
+          'image' => empty($feed->image) ? '' : $feed->image,
+          'hash' => md5($feed->source_string),
+          'etag' => empty($feed->etag) ? '' : $feed->etag,
+          'modified' => empty($feed->modified) ? '' : $feed->modified,
+        ))
+        ->execute();
+
+      // Log if feed URL has changed.
+      if ($feed->url != $feed_url) {
+        watchdog('aggregator', 'Updated URL for feed %title to %url.', array('%title' => $feed->title, '%url' => $feed->url));
+      }
 
-    // If there are items on the feed, let all enabled processors do their work on it.
-    if (@count($feed->items)) {
-      foreach ($processors as $processor) {
-        module_invoke($processor, 'aggregator_process', $feed);
+      watchdog('aggregator', 'There is new syndicated content from %site.', array('%site' => $feed->title));
+      drupal_set_message(t('There is new syndicated content from %site.', array('%site' => $feed->title)));
+
+      // If there are items on the feed, let all enabled processors do their work on it.
+      if (@count($feed->items)) {
+        $processors = variable_get('aggregator_processors', array('aggregator'));
+        foreach ($processors as $processor) {
+          module_invoke($processor, 'aggregator_process', $feed);
+        }
       }
     }
   }
+
   // Expire old feed items.
   if (function_exists('aggregator_expire')) {
     aggregator_expire($feed);
Index: modules/aggregator/aggregator.parser.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.parser.inc,v
retrieving revision 1.4
diff -u -r1.4 aggregator.parser.inc
--- modules/aggregator/aggregator.parser.inc	15 Jul 2009 21:32:43 -0000	1.4
+++ modules/aggregator/aggregator.parser.inc	3 Oct 2009 22:08:11 -0000
@@ -44,32 +44,21 @@
     }
 
     $etag = empty($feed->http_headers['ETag']) ? '' : $feed->http_headers['ETag'];
-    // Update the feed data.
-    db_merge('aggregator_feed')
-      ->key(array('fid' => $feed->fid))
-      ->fields(array(
-        'url' => $feed->url,
-        'checked' => REQUEST_TIME,
-        'link' => !empty($channel['link']) ? $channel['link'] : '',
-        'description' => !empty($channel['description']) ? $channel['description'] : '',
-        'image' => $image,
-        'hash' => md5($feed->source_string),
-        'etag' => $etag,
-        'modified' => $modified,
-      ))
-      ->execute();
+
+    // Add parsed data to the feed object.
+    $feed->link = !empty($channel['LINK']) ? $channel['LINK'] : '';
+    $feed->description = !empty($channel['DESCRIPTION']) ? $channel['DESCRIPTION'] : '';
+    $feed->image = $image;
+    $feed->etag = $etag;
+    $feed->modified = $modified;
 
     // Clear the cache.
     cache_clear_all();
 
-    if (isset($feed->redirected)) {
-      watchdog('aggregator', 'Updated URL for feed %title to %url.', array('%title' => $feed->title, '%url' => $feed->url));
-    }
-
-    watchdog('aggregator', 'There is new syndicated content from %site.', array('%site' => $feed->title));
-    drupal_set_message(t('There is new syndicated content from %site.', array('%site' => $feed->title)));
-
+    return TRUE;
   }
+
+  return FALSE;
 }
 
 /**
Index: modules/aggregator/aggregator.fetcher.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.fetcher.inc,v
retrieving revision 1.9
diff -u -r1.9 aggregator.fetcher.inc
--- modules/aggregator/aggregator.fetcher.inc	25 Sep 2009 23:53:26 -0000	1.9
+++ modules/aggregator/aggregator.fetcher.inc	3 Oct 2009 22:08:10 -0000
@@ -45,7 +45,6 @@
       break;
     case 301:
       $feed->url = $result->redirect_url;
-      $feed->redirected = TRUE;
       // Do not break here.
     case 200:
     case 302:
