cvs diff: Diffing modules/update
Index: modules/update/update.compare.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/update/update.compare.inc,v
retrieving revision 1.1
diff -u -p -r1.1 update.compare.inc
--- modules/update/update.compare.inc	11 Jul 2007 15:15:40 -0000	1.1
+++ modules/update/update.compare.inc	9 Jan 2008 01:07:53 -0000
@@ -156,10 +156,20 @@ function update_process_project_info(&$p
  * remote servers, calculate the current status.
  *
  * This function is the heart of the update status feature. It iterates over
- * every currently installed project, and for each one, decides what major
- * release series to consider (the larger of the major version currently
- * installed and the default major version specified by the maintainer of that
- * project).
+ * every currently installed project. For each one, it first checks if the
+ * project has been flagged with a special status like "unsupported" or
+ * "insecure", or if the project node itself has been unpublished. In any of
+ * those cases, the project is marked with an error and the next project is
+ * considered.
+ *
+ * If the project itself is valid, the function decides what major release
+ * series to consider. The project defines what the currently supported major
+ * versions are for each version of core, so the first step is to make sure
+ * the current version is still supported. If so, that's the target version.
+ * If the current version is unsupported, the project maintainer's recommended
+ * major version is used. There's also a check to make sure that this function
+ * never recommends an earlier release than the currently installed major
+ * version. 
  *
  * Given a target major version, it scans the available releases looking for
  * the specific release to recommend (avoiding beta releases and development
@@ -213,28 +223,105 @@ function update_calculate_project_data($
   update_process_project_info($projects);
   foreach ($projects as $project => $project_info) {
     if (isset($available[$project])) {
+
+      // If the project status for this version of core specially marked as
+      // something bad, there's nothing else to consider.
+      if (isset($available[$project]['project_status'])) {
+        switch ($available[$project]['project_status']) {
+          case 'insecure':
+            $projects[$project]['status'] = UPDATE_NOT_SECURE;
+            break;
+          case 'unpublished':
+          case 'revoked':
+            $projects[$project]['status'] = UPDATE_REVOKED;
+            break;
+          case 'unsupported':
+            $projects[$project]['status'] = UPDATE_NOT_SUPPORTED;
+            break;
+          default:
+            // Assume anything else (e.g. 'published') is valid and we should
+            // perform the rest of the logic in this function.
+            break;
+        }
+      }
+
+      if (!empty($projects[$project]['status'])) {
+        // We already know the status for this project, so there's nothing
+        // else to compute. Just record everything else we fetched from the
+        // XML file into our projects array and move to the next project.
+        $projects[$project] += $available[$project];
+        continue;
+      }
+
       // Figure out the target major version.
       $existing_major = $project_info['existing_major'];
-      if (isset($available[$project]['default_major'])) {
-        $default_major = $available[$project]['default_major'];
-        $target_major = max($existing_major, $default_major);
+      $supported_majors = array();
+      if (isset($available[$project]['supported_majors'])) {
+        $supported_majors = explode(',', $available[$project]['supported_majors']);
+      }
+      elseif (isset($available[$project]['default_major'])) {
+        // Older release history XML file without supported or recommended.
+        $supported_majors[] = $available[$project]['default_major'];
+      }
+
+      if (in_array($existing_major, $supported_majors)) {
+        // Still supported, stay at the current major version.
+        $target_major = $existing_major;
+      }
+      elseif (isset($available[$project]['recommended_major'])) {
+        // Since 'recommended_major' is defined, we know this is the new XML
+        // format. Therefore, we know the current release is unsupported since
+        // its major version was not in the 'supported_majors' list. We should 
+        // find the best release from the recommended major version.
+        $target_major = $available[$project]['recommended_major'];
+        $projects[$project]['status'] = UPDATE_NOT_SUPPORTED;
+      }
+      elseif (isset($available[$project]['default_major'])) {
+        // Older release history XML file without recommended, so recommend
+        // the currently defined "default_major" version.
+        $target_major = $available[$project]['default_major'];
       }
       else {
+        // Malformed XML file? Stick with the current version.
         $target_major = $existing_major;
       }
+      // Make sure we never tell the admin to downgrade.
+      $target_major = max($existing_major, $target_major);
 
       $version_patch_changed = '';
       $patch = '';
 
+      // Defend ourselves from XML history files that contain no releases.
+      if (empty($available[$project]['releases'])) {
+        $projects[$project]['status'] = UPDATE_UNKNOWN;
+        $projects[$project]['reason'] = t('No available releases found');
+        continue;
+      }
       foreach ($available[$project]['releases'] as $version => $release) {
-        // Ignore unpublished releases.
+        // First, if this is the existing release, check a few conditions.
+        if ($projects[$project]['existing_version'] == $version) {
+          if (isset($release['terms']['Release type']) &&
+              in_array('Insecure', $release['terms']['Release type'])) {
+            $projects[$project]['status'] = UPDATE_NOT_SECURE;
+          }
+          elseif ($release['status'] != 'published') {
+            $projects[$project]['status'] = UPDATE_REVOKED;
+          }
+          elseif (isset($release['terms']['Release type']) &&
+                  in_array('Unsupported', $release['terms']['Release type'])) {
+            $projects[$project]['status'] = UPDATE_NOT_SUPPORTED;
+          }
+        }
+
+        // Otherwise, ignore unpublished releases.
         if ($release['status'] != 'published') {
           continue;
         }
 
-        // See if this is a higher major version than our target, and if so,
-        // record it as an "Also available" release.
-        if ($release['version_major'] > $target_major) {
+        // See if this is a higher major version than our target and yet still
+        // supported. If so, record it as an "Also available" release.
+        if ($release['version_major'] > $target_major && 
+            in_array($release['version_major'], $supported_majors)) {
           if (!isset($available[$project]['also'])) {
             $available[$project]['also'] = array();
           }
@@ -303,8 +390,7 @@ function update_calculate_project_data($
         }
 
         // See if this release is a security update.
-        if (isset($release['terms'])
-            && isset($release['terms']['Release type'])
+        if (isset($release['terms']['Release type'])
             && in_array('Security update', $release['terms']['Release type'])) {
           $projects[$project]['security updates'][] = $release;
         }
@@ -344,45 +430,40 @@ function update_calculate_project_data($
         continue;
       }
 
-      // Check based upon install type and the site-wide threshold setting.
-      $error_level = variable_get('update_notification_threshold', 'all');
-
-      switch ($projects[$project]['install_type']) {
-        case 'official':
-          if ($projects[$project]['existing_version'] == $projects[$project]['recommended'] || $projects[$project]['existing_version'] == $projects[$project]['latest_version']) {
-            $projects[$project]['status'] = UPDATE_CURRENT;
-          }
-          else {
-            if (!empty($projects[$project]['security updates'])) {
-              $projects[$project]['status'] = UPDATE_NOT_SECURE;
+      // Figure out the status, based on what we've seen and the install type.
+      if (!empty($projects[$project]['security updates'])) {
+        // If we found security updates, that always trumps any other status.
+        $projects[$project]['status'] = UPDATE_NOT_SECURE;
+      }
+      elseif (!isset($projects[$project]['status'])) {
+        switch ($projects[$project]['install_type']) {
+          case 'official':
+            if ($projects[$project]['existing_version'] == $projects[$project]['recommended'] || $projects[$project]['existing_version'] == $projects[$project]['latest_version']) {
+              $projects[$project]['status'] = UPDATE_CURRENT;
             }
             else {
               $projects[$project]['status'] = UPDATE_NOT_CURRENT;
             }
-          }
-          break;
-        case 'dev':
-          if (!empty($projects[$project]['security updates'])) {
-            $projects[$project]['status'] = UPDATE_NOT_SECURE;
             break;
-          }
 
-          $latest = $available[$project]['releases'][$projects[$project]['latest_dev']];
-          if (empty($projects[$project]['datestamp'])) {
-            $projects[$project]['status'] = UPDATE_NOT_CHECKED;
-            $projects[$project]['reason'] = t('Unknown release date');
-          }
-          elseif (($projects[$project]['datestamp'] + 100 > $latest['date'])) {
-            $projects[$project]['status'] = UPDATE_CURRENT;
-          }
-          else {
-            $projects[$project]['status'] = UPDATE_NOT_CURRENT;
-          }
-          break;
+          case 'dev':
+            $latest = $available[$project]['releases'][$projects[$project]['latest_dev']];
+            if (empty($projects[$project]['datestamp'])) {
+              $projects[$project]['status'] = UPDATE_NOT_CHECKED;
+              $projects[$project]['reason'] = t('Unknown release date');
+            }
+            elseif (($projects[$project]['datestamp'] + 100 > $latest['date'])) {
+              $projects[$project]['status'] = UPDATE_CURRENT;
+            }
+            else {
+              $projects[$project]['status'] = UPDATE_NOT_CURRENT;
+            }
+            break;
 
-        default:
-          $projects[$project]['status'] = UPDATE_UNKNOWN;
-          $projects[$project]['reason'] = t('Invalid info');
+          default:
+            $projects[$project]['status'] = UPDATE_UNKNOWN;
+            $projects[$project]['reason'] = t('Invalid info');
+        }
       }
     }
     else {
Index: modules/update/update.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/update/update.module,v
retrieving revision 1.8
diff -u -p -r1.8 update.module
--- modules/update/update.module	8 Jan 2008 10:35:43 -0000	1.8
+++ modules/update/update.module	9 Jan 2008 01:07:53 -0000
@@ -17,29 +17,40 @@ define('UPDATE_DEFAULT_URL', 'http://upd
 // These are internally used constants for this code, do not modify.
 
 /**
- * Project is up to date.
+ * Project is missing security update(s).
  */
-define('UPDATE_CURRENT', 1);
+define('UPDATE_NOT_SECURE', 1);
 
 /**
- * Project is missing security update(s).
+ * Current release has been unpublished and is no longer available.
+ */
+define('UPDATE_REVOKED', 2);
+
+/**
+ * Current release is no longer supported by the project maintainer.
  */
-define('UPDATE_NOT_SECURE', 2);
+define('UPDATE_NOT_SUPPORTED', 3);
 
 /**
  * Project has a new release available, but it is not a security release.
  */
-define('UPDATE_NOT_CURRENT', 3);
+define('UPDATE_NOT_CURRENT', 4);
+
+/**
+ * Project is up to date.
+ */
+define('UPDATE_CURRENT', 5);
 
 /**
  * Project's status cannot be checked.
  */
-define('UPDATE_NOT_CHECKED', 4);
+define('UPDATE_NOT_CHECKED', -1);
 
 /**
  * No available update data was found for project.
  */
-define('UPDATE_UNKNOWN', 5);
+define('UPDATE_UNKNOWN', -2);
+
 
 /**
  * Implementation of hook_help().
@@ -185,13 +196,6 @@ function update_requirements($phase) {
       include_once './modules/update/update.compare.inc';
       $data = update_calculate_project_data($available);
       switch ($data['drupal']['status']) {
-        case UPDATE_NOT_CURRENT:
-          $requirements['update_core']['value'] = t('Out of date (version @version available)', array('@version' => $data['drupal']['recommended']));
-          $requirements['update_core']['severity'] = $notification_level == 'all' ? REQUIREMENT_ERROR : REQUIREMENT_WARNING;
-          $requirements['update_core']['reason'] = UPDATE_NOT_CURRENT;
-          $requirements['update_core']['description'] = _update_message_text('core', UPDATE_NOT_CURRENT, TRUE);
-          break;
-
         case UPDATE_NOT_SECURE:
           $requirements['update_core']['value'] = t('Not secure! (version @version available)', array('@version' => $data['drupal']['recommended']));
           $requirements['update_core']['severity'] = REQUIREMENT_ERROR;
@@ -199,12 +203,35 @@ function update_requirements($phase) {
           $requirements['update_core']['description'] = _update_message_text('core', UPDATE_NOT_SECURE, TRUE);
           break;
 
+        case UPDATE_REVOKED:
+          $requirements['update_core']['value'] = t('Revoked! No longer supported or available.');
+          $requirements['update_core']['severity'] = REQUIREMENT_ERROR;
+          $requirements['update_core']['reason'] = UPDATE_REVOKED;
+          $requirements['update_core']['description'] = _update_message_text('core', UPDATE_REVOKED, TRUE);
+          break;
+
+        case UPDATE_NOT_SUPPORTED:
+          $requirements['update_core']['value'] = t('Not supported!');
+          $requirements['update_core']['severity'] = REQUIREMENT_ERROR;
+          $requirements['update_core']['reason'] = UPDATE_NOT_SUPPORTED;
+          $requirements['update_core']['description'] = _update_message_text('core', UPDATE_NOT_SUPPORTED, TRUE);
+          break;
+
+        case UPDATE_NOT_CURRENT:
+          $requirements['update_core']['value'] = t('Out of date (version @version available)', array('@version' => $data['drupal']['recommended']));
+          $requirements['update_core']['severity'] = $notification_level == 'all' ? REQUIREMENT_ERROR : REQUIREMENT_WARNING;
+          $requirements['update_core']['reason'] = UPDATE_NOT_CURRENT;
+          $requirements['update_core']['description'] = _update_message_text('core', UPDATE_NOT_CURRENT, TRUE);
+          break;
+
         default:
           $requirements['update_core']['value'] = t('Up to date');
           break;
       }
       // We don't want to check drupal a second time.
       unset($data['drupal']);
+      $revoked = FALSE;
+      $not_supported = FALSE;
       $not_current = FALSE;
       if (!empty($data)) {
         $requirements['update_contrib']['title'] = t('Module and theme update status');
@@ -212,19 +239,43 @@ function update_requirements($phase) {
         $requirements['update_contrib']['value'] = t('Up to date');
         foreach (array_keys($data) as $project) {
           if (isset($available[$project])) {
-            if ($data[$project]['status'] == UPDATE_NOT_SECURE) {
-              $requirements['update_contrib']['value'] = t('Not secure!');
-              $requirements['update_contrib']['severity'] = REQUIREMENT_ERROR;
-              $requirements['update_contrib']['reason'] = UPDATE_NOT_SECURE;
-              $requirements['update_contrib']['description'] = _update_message_text('contrib', UPDATE_NOT_SECURE, TRUE);
-              break;
-            }
-            elseif ($data[$project]['status'] == UPDATE_NOT_CURRENT) {
-              $not_current = TRUE;
+            switch ($data[$project]['status']) {
+              case UPDATE_NOT_SECURE:
+                $requirements['update_contrib']['value'] = t('Not secure!');
+                $requirements['update_contrib']['severity'] = REQUIREMENT_ERROR;
+                $requirements['update_contrib']['reason'] = UPDATE_NOT_SECURE;
+                $requirements['update_contrib']['description'] = _update_message_text('contrib', UPDATE_NOT_SECURE, TRUE);
+                // This is what we'll print, no need to continue the foreach.
+                break 2;
+              case UPDATE_REVOKED:
+                $revoked = TRUE;
+                break;
+              case UPDATE_NOT_SUPPORTED:
+                $not_supported = TRUE;
+                break;
+              case UPDATE_NOT_CURRENT:
+                $not_current = TRUE;
+                break;
             }
           }
         }
-        if (!isset($requirements['update_contrib']['severity']) && $not_current) {
+        // Depending on what we saw, print out the right message.
+        if (isset($requirements['update_contrib']['severity'])) {
+          // We already found an insecure project, nothing more to say.
+        }
+        elseif ($revoked) {
+          $requirements['update_contrib']['severity'] = REQUIREMENT_ERROR;
+          $requirements['update_contrib']['value'] = t('Release revoked');
+          $requirements['update_contrib']['reason'] = UPDATE_REVOKED;
+          $requirements['update_contrib']['description'] = _update_message_text('contrib', UPDATE_REVOKED, TRUE);
+        }
+        elseif ($not_supported) {
+          $requirements['update_contrib']['severity'] = REQUIREMENT_ERROR;
+          $requirements['update_contrib']['value'] = t('Unsupported release');
+          $requirements['update_contrib']['reason'] = UPDATE_NOT_SUPPORTED;
+          $requirements['update_contrib']['description'] = _update_message_text('contrib', UPDATE_NOT_SUPPORTED, TRUE);
+        }
+        elseif ($not_current) {
           $requirements['update_contrib']['severity'] = $notification_level == 'all' ? REQUIREMENT_ERROR : REQUIREMENT_WARNING;
           $requirements['update_contrib']['value'] = t('Out of date');
           $requirements['update_contrib']['reason'] = UPDATE_NOT_CURRENT;
@@ -368,21 +419,39 @@ function _update_message_text($msg_type,
   $langcode = isset($language) ? $language->language : NULL;
   $text = '';
   switch ($msg_reason) {
-    case UPDATE_NOT_CURRENT:
+    case UPDATE_NOT_SECURE:
       if ($msg_type == 'core') {
-        $text = t('There are updates available for your version of Drupal. To ensure the proper functioning of your site, you should update as soon as possible.', array(), $langcode);
+        $text = t('There is a security update available for your version of Drupal. To ensure the security of your server, you should update immediately!', array(), $langcode);
       }
       else {
-        $text = t('There are updates available for one or more of your modules or themes. To ensure the proper functioning of your site, you should update as soon as possible.', array(), $langcode);
+        $text = t('There are security updates available for one or more of your modules or themes. To ensure the security of your server, you should update immediately!', array(), $langcode);
       }
       break;
 
-    case UPDATE_NOT_SECURE:
+    case UPDATE_REVOKED:
       if ($msg_type == 'core') {
-        $text = t('There is a security update available for your version of Drupal. To ensure the security of your server, you should update immediately!', array(), $langcode);
+        $text = t('Your version of Drupal has been revoked and is no longer available for download. Upgrading is highly advised!', array(), $langcode);
       }
       else {
-        $text = t('There are security updates available for one or more of your modules or themes. To ensure the security of your server, you should update immediately!', array(), $langcode);
+        $text = t('The installed version of at least one of your modules or themes has been revoked and is no longer available for download. Upgrading is highly advised!', array(), $langcode);
+      }
+      break;
+
+    case UPDATE_NOT_SUPPORTED:
+      if ($msg_type == 'core') {
+        $text = t('Your version of Drupal is no longer supported. Upgrading is highly advised!', array(), $langcode);
+      }
+      else {
+        $text = t('The installed version of at least one of your modules or themes is no longer supported. Upgrading is highly advised! Please see the project homepage for more details.', array(), $langcode);
+      }
+      break;
+
+    case UPDATE_NOT_CURRENT:
+      if ($msg_type == 'core') {
+        $text = t('There are updates available for your version of Drupal. To ensure the proper functioning of your site, you should update as soon as possible.', array(), $langcode);
+      }
+      else {
+        $text = t('There are updates available for one or more of your modules or themes. To ensure the proper functioning of your site, you should update as soon as possible.', array(), $langcode);
       }
       break;
   }
Index: modules/update/update.report.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/update/update.report.inc,v
retrieving revision 1.7
diff -u -p -r1.7 update.report.inc
--- modules/update/update.report.inc	1 Jan 2008 18:03:12 -0000	1.7
+++ modules/update/update.report.inc	9 Jan 2008 01:07:53 -0000
@@ -48,9 +48,11 @@ function theme_update_report($data) {
         $icon = theme('image', 'misc/watchdog-ok.png');
         break;
       case UPDATE_NOT_SECURE:
+      case UPDATE_REVOKED:
+      case UPDATE_NOT_SUPPORTED:
       case UPDATE_NOT_CURRENT:
         if ($notification_level == 'all'
-            || $project['status'] == UPDATE_NOT_SECURE) {
+            || $project['status'] != UPDATE_NOT_CURRENT) {
           $class = 'error';
           $icon = theme('image', 'misc/watchdog-error.png');
           break;
@@ -64,16 +66,30 @@ function theme_update_report($data) {
 
     $row = '<div class="version-status">';
     switch ($project['status']) {
-      case UPDATE_CURRENT:
-        $row .= t('Up to date');
-        break;
       case UPDATE_NOT_SECURE:
         $row .= '<span class="security-error">';
         $row .= t('Security update required!');
         $row .= '</span>';
         break;
+      case UPDATE_REVOKED:
+        $row .= '<span class="revoked">';
+        $row .= t('Revoked!');
+        $row .= '</span>';
+        break;
+      case UPDATE_NOT_SUPPORTED:
+        $row .= '<span class="not-supported">';
+        $row .= t('Not supported!');
+        $row .= '</span>';
+        break;
       case UPDATE_NOT_CURRENT:
+        $row .= '<span class="not-current">';
         $row .= t('Update available');
+        $row .= '</span>';
+        break;
+      case UPDATE_CURRENT:
+        $row .= '<span class="current">';
+        $row .= t('Up to date');
+        $row .= '</span>';
         break;
       default:
         $row .= check_plain($project['reason']);
