Index: profiles/default/default.profile =================================================================== RCS file: /cvs/drupal/drupal/profiles/default/default.profile,v retrieving revision 1.12 diff -u -p -r1.12 default.profile --- profiles/default/default.profile 16 May 2007 13:45:17 -0000 1.12 +++ profiles/default/default.profile 29 Jun 2007 07:08:57 -0000 @@ -8,7 +8,7 @@ * An array of modules to be enabled. */ function default_profile_modules() { - return array('color', 'comment', 'help', 'taxonomy', 'dblog'); + return array('color', 'comment', 'help', 'taxonomy', 'dblog', 'update'); } /** Index: modules/update/update-rtl.css =================================================================== RCS file: modules/update/update-rtl.css diff -N modules/update/update-rtl.css --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/update/update-rtl.css 29 Jun 2007 07:08:57 -0000 @@ -0,0 +1,31 @@ +/* $Id: update-rtl.css,v 1.1 2007/06/28 20:38:26 dww Exp $ */ + +.update .project { + padding-right: .25em; +} + +.update .version-status { + float: left; + padding-left: 10px; +} + +.update .version-status .icon { + padding-right: .5em; +} + +.update table.version .version-title { + padding-left: 1em; +} + +.update table.version .version-details { + padding-left: .5em; +} + +.update table.version .version-links { + text-align: left; + padding-left: 1em; +} + +.update-settings tr.update-settings-label td.update-settings-label { + padding: 0 2em 0 0; +} Index: modules/update/update.css =================================================================== RCS file: modules/update/update.css diff -N modules/update/update.css --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/update/update.css 29 Jun 2007 07:08:57 -0000 @@ -0,0 +1,110 @@ +/* $Id: update.css,v 1.5 2007/06/28 20:38:26 dww Exp $ */ +.update .project { + font-weight: bold; + font-size: 110%; + padding-left: .25em; /* LTR */ + height: 22px; +} + +.update .version-status { + float: right; /* LTR */ + padding-right: 10px; /* LTR */ + font-size: 110%; + height: 20px; +} + +.update .version-status .icon { + padding-left: .5em; /* LTR */ +} + +.update .info { + margin: 0; + padding: 1em 1em .25em 1em; +} + +.update tr td { + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; +} + +.update tr.error { + background: #fcc; +} + +.update tr.error .version-recommended { + background: #fdd; +} + +.update tr.ok { + background: #dfd; +} + +.update tr.warning { + background: #ffd; +} + +.update tr.warning .version-recommended { + background: #ffe; +} + +.current-version, .new-version { + direction: ltr; /* Note: version numbers should always be LTR. */ +} + + +table.update, +.update table.version { + width: 100%; + margin-top: .5em; +} + +.update table.version tbody { + border: none; +} + +.update table.version tr, +.update table.version td { + line-height: .9em; + padding: 0; + margin: 0; + border: none; +} + +.update table.version .version-title { + padding-left: 1em; /* LTR */ + width: 14em; +} + +.update table.version .version-details { + padding-right: .5em; /* LTR */ +} + +.update table.version .version-links { + text-align: right; /* LTR */ + padding-right: 1em; /* LTR */ +} + +.update table.version-security .version-title { + color: #970F00; +} + +.update table.version-recommended-strong .version-title { + font-weight: bold; +} + +.update .security-error { + font-weight: bold; + color: #970F00; +} + +.update-settings .form-select { + width: 12em; +} + +.update-settings tr.update-settings-label td.update-settings-label { + font-size: 70%; + font-weight: bold; + background: #ddd; + color: #666; + padding: 0 0 0 2em; /* LTR */ +} Index: modules/update/update.info =================================================================== RCS file: modules/update/update.info diff -N modules/update/update.info --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/update/update.info 29 Jun 2007 07:08:57 -0000 @@ -0,0 +1,6 @@ +; $Id: update.info,v 1.3 2007/06/28 02:20:47 dww Exp $ +name = Update status +description = Checks the status of available updates for Drupal and your installed modules and themes. +version = VERSION +package = Core - optional +core = 6.x Index: modules/update/update.module =================================================================== RCS file: modules/update/update.module diff -N modules/update/update.module --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/update/update.module 29 Jun 2007 07:08:57 -0000 @@ -0,0 +1,642 @@ +'. t('Here you can find information about available updates for your installed modules and themes. Note that each module or theme is part of a "project", which may or may not have the same name, and might include multiple modules or themes within it.') .'
'; + + case 'admin/logs/updates/settings': + return ''. t('Here you can configure what kinds of available updates for your installed modules and themes should be marked as an error on the !status_report, the !modules_page, and the !themes_page, along with other related settings.', array('!status_report' => l(t('status report'), 'admin/logs/status'), '!modules_page' => l(t('modules page'), 'admin/build/modules'), '!themes_page' => l(t('themes page'), 'admin/build/themes'))) .'
'; + + case 'admin/build/themes': + case 'admin/build/modules': + include_once './includes/install.inc'; + $status = update_requirements('runtime'); + foreach (array('core', 'contrib') as $report_type) { + $type = 'update_'. $report_type; + if (isset($status[$type]['severity'])) { + if ($status[$type]['severity'] == REQUIREMENT_ERROR) { + drupal_set_message($status[$type]['description'], 'error'); + } + elseif ($status[$type]['severity'] == REQUIREMENT_WARNING) { + drupal_set_message($status[$type]['description']); + } + } + } + return ''. t('See the !available_updates page for information on installed modules and themes with new versions released.', array('!available_updates' => l(t('available updates'), 'admin/logs/updates'))) .'
'; + } +} + +/** + * Implementation of hook_menu(). + */ +function update_menu() { + $items = array(); + + $items['admin/logs/updates'] = array( + 'title' => 'Available updates', + 'description' => 'Get a status report about available updates for your installed modules and themes.', + 'page callback' => 'update_status', + 'access arguments' => array('administer site configuration'), + 'file' => 'update.report.inc', + 'weight' => 10, + ); + $items['admin/logs/updates/list'] = array( + 'title' => 'List', + 'page callback' => 'update_status', + 'access arguments' => array('administer site configuration'), + 'file' => 'update.report.inc', + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $items['admin/logs/updates/settings'] = array( + 'title' => 'Settings', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('update_settings'), + 'access arguments' => array('administer site configuration'), + 'file' => 'update.settings.inc', + 'type' => MENU_LOCAL_TASK, + ); + $items['admin/logs/updates/force-check'] = array( + 'title' => 'Manual update check', + 'page callback' => 'update_force_status', + 'access arguments' => array('administer site configuration'), + 'file' => 'update.fetch.inc', + 'type' => MENU_CALLBACK, + ); + + return $items; +} + +/** + * Implementation of the hook_theme() registry. + */ +function update_theme() { + return array( + 'update_settings' => array( + 'arguments' => array('form' => NULL), + ), + 'update_report' => array( + 'arguments' => array('data' => NULL), + ), + 'update_version' => array( + 'arguments' => array('version' => NULL, 'tag' => NULL, 'class' => NULL), + ), + ); +} + +/** + * Implementation of hook_requirements + */ +function update_requirements($phase, $plaintext = FALSE) { + if ($phase == 'runtime') { + $requirements['update_core']['title'] = t('Drupal core update status'); + $error_level = variable_get('update_error_threshold', 'all'); + $see_more = $plaintext ? '' : ' '. t('See the !available_updates page for more information.', array('!available_updates' => l(t('available updates'), 'admin/logs/updates'))); + if ($avail = update_get_available(FALSE)) { + $data = update_calculate_project_data($avail); + 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'] = $error_level == 'all' ? REQUIREMENT_ERROR : REQUIREMENT_WARNING; + $requirements['update_drupal']['description'] = 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.') . $see_more; + 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; + $requirements['update_core']['description'] = t('There is a security update available for your version of Drupal. To ensure the security of your server, you should update immediately.') . $see_more; + break; + + default: + $requirements['update_core']['value'] = t('Up to date'); + break; + } + // We don't want to check drupal a second time. + unset($data['drupal']); + $not_current = FALSE; + if (!empty($data)) { + $requirements['update_contrib']['title'] = t('Module and theme update status'); + // Default to being current until we see otherwise. + $requirements['update_contrib']['value'] = t('Up to date'); + foreach (array_keys($data) as $project) { + if (isset($avail[$project])) { + if ($data[$project]['status'] == UPDATE_NOT_SECURE) { + $requirements['update_contrib']['value'] = t('Not secure!'); + $requirements['update_contrib']['severity'] = REQUIREMENT_ERROR; + $requirements['update_contrib']['description'] = 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.') . $see_more; + break; + } + elseif ($data[$project]['status'] == UPDATE_NOT_CURRENT) { + $not_current = TRUE; + } + } + } + if (!isset($requirements['update_contrib']['severity']) && $not_current) { + $requirements['update_contrib']['severity'] = $error_level == 'all' ? REQUIREMENT_ERROR : REQUIREMENT_WARNING; + $requirements['update_contrib']['value'] = t('Out of date'); + $requirements['update_contrib']['description'] = 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.') . $see_more; + } + } + } + else { + $requirements['update_core']['value'] = t('No update data available'); + $requirements['update_core']['severity'] = REQUIREMENT_WARNING; + $requirements['update_core']['description'] = _update_no_data(); + } + return $requirements; + } +} + +/** + * Implementation of hook_cron(). + */ +function update_cron() { + $frequency = variable_get('update_check_frequency', 'daily'); + $interval = 60 * 60 * 24 * ($frequency == 'weekly' ? 7 : 1); + if (time() - variable_get('update_last_check', 0) > $interval) { + update_refresh(); + _update_cron_notify(); + } +} + +/** + * Implementation of hook_form_alter(). + * + * Adds a submit handler to the system modules and themes forms, so that if a + * site admin saves either form, we invalidate the cache of available updates. + * + * @see update_invalidate_cache() + */ +function update_form_alter(&$form, $form_state, $form_id) { + if ($form_id == 'system_modules' || $form_id == 'system_themes' ) { + $form['#submit'][] = 'update_invalidate_cache'; + } +} + +/** + * Prints a warning message when there is no data about available updates. + */ +function _update_no_data() { + $destination = drupal_get_destination(); + return t('No information is available about potential new releases for currently installed modules and themes. To check for updates, you may need to !run_cron or you can !check_manually. Please note that checking for available updates can take a long time, so please be patient.', array( + '!run_cron' => l(t('run cron'), 'admin/logs/status/run-cron', array('query' => $destination)), + '!check_manually' => l(t('check manually'), 'admin/logs/updates/force-check', array('query' => $destination)), + )); +} + +/** + * Fetch an array of installed and enabled projects. + * + * This is only responsible for generating an array of projects (taking into + * account projects that include more than one module or theme). Other + * information like the specific version and install type (official release, + * dev snapshot, etc) is handled later in update_process_project_info() since + * that logic is only required when preparing the status report, not for + * fetching the available release data. + * + * @see update_process_project_info() + * @see update_calculate_project_data() + * + */ +function update_get_projects() { + static $projects = array(); + if (empty($projects)) { + _update_process_info_list($projects, module_rebuild_cache(), 'module'); + _update_process_info_list($projects, system_theme_data(), 'theme'); + } + return $projects; +} + +function _update_process_info_list(&$projects, &$list, $project_type) { + foreach ($list as $file) { + if (empty($file->status)) { + // Skip disabled modules or themes. + continue; + } + + // Skip if the .info file is broken. + if (empty($file->info)) { + continue; + } + + // If the .info doesn't define the 'project', try to figure it out. + if (!isset($file->info['project'])) { + $file->info['project'] = update_get_project($file); + } + + if (!isset($projects[$file->info['project']])) { + // Only process this if we haven't done this project, since a single + // project can have multiple modules or themes. + $projects[$file->info['project']] = array( + 'name' => $file->info['project'], + 'info' => $file->info, + 'datestamp' => isset($file->info['datestamp']) ? $file->info['datestamp'] : 0, + 'includes' => array($file->name => $file->info['name']), + 'project_type' => $file->info['project'] == 'drupal' ? 'core' : $project_type, + ); + } + else { + $projects[$file->info['project']]['includes'][$file->name] = $file->info['name']; + } + } +} + +/** + * Given a $file object (as returned by system_get_files_database()), figure + * out what project it belongs to. + * + * @see system_get_files_database() + */ +function update_get_project($file) { + $project = ''; + if (isset($file->info['project'])) { + $project = $file->info['project']; + } + elseif (isset($file->info['package']) + && (strpos($file->info['package'], 'Core -') !== FALSE)) { + $project = 'drupal'; + } + elseif (in_array($file->name, array('bluemarine', 'chameleon', 'garland', 'marvin', 'minnelli', 'pushbutton'))) { + // Unfortunately, there's no way to tell if a theme is part of core, + // so we must hard-code a list here. + $project = 'drupal'; + } + else { + // This isn't part of core, so guess the project from the directory. + $last = ''; + foreach (array_reverse(explode('/', $file->filename)) as $dir) { + if ($dir == 'modules' || $dir == 'themes') { + break; + } + $last = $dir; + } + if ($last) { + $project = $last; + } + else { + continue; + } + } + return $project; +} + +/** + * Process the list of projects on the system to figure out the currently + * installed versions, and other information that is required before we can + * compare against the available releases to produce the status report. + * + * @param $projects + * Array of project information from update_get_projects(). + */ +function update_process_project_info(&$projects) { + foreach ($projects as $key => $project) { + // Assume an official release until we see otherwise. + $install_type = 'official'; + + $info = $project['info']; + + if (isset($info['version'])) { + // Check for development snapshots + if (preg_match('@(dev|HEAD)@', $info['version'])) { + $install_type = 'dev'; + } + + // Figure out what the currently installed major version is. We need + // to handle both contribution (e.g. "5.x-1.3", major = 1) and core + // (e.g. "5.1", major = 5) version strings. + $matches = array(); + if (preg_match('/^(\d+\.x-)?(\d+)\..*$/', $info['version'], $matches)) { + $info['major'] = $matches[2]; + } + elseif (!isset($info['major'])) { + // This would only happen for version strings that don't follow the + // drupal.org convention. We let contribs define "major" in their + // .info in this case, and only if that's missing would we hit this. + $info['major'] = -1; + } + } + else { + // No version info available at all. + $install_type = 'unknown'; + $info['version'] = t('Unknown'); + $info['major'] = -1; + } + + // Finally, save the results we care about into the $projects array. + $projects[$key]['existing_version'] = $info['version']; + $projects[$key]['existing_major'] = $info['major']; + $projects[$key]['install_type'] = $install_type; + unset($projects[$key]['info']); + } +} + +/** + * Given the installed projects and the available release data retrieved from + * 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). + * + * Given a target major version, it scans the available releases looking for + * the specific release to recommend (avoiding beta releases and development + * snapshots if possible). This is complicated to describe, but an example + * will help clarify. For the target major version, find the highest patch + * level. If there is a release at that patch level with no extra ("beta", + * etc), then we recommend the release at that patch level with the most + * recent release date. If every release at that patch level has extra (only + * betas), then recommend the latest release from the previous patch + * level. For example: + * + * 1.6-bugfix <-- recommended version because 1.6 already exists. + * 1.6 + * + * or + * + * 1.6-beta + * 1.5 <-- recommended version because no 1.6 exists. + * 1.4 + * + * It also looks for the latest release from the same major version, even a + * beta release, to display to the user as the "Latest version" option. + * Additionally, it finds the latest official release from any higher major + * versions that have been released to provide a set of "Also available" + * options. + * + * Finally, and most importantly, it keeps scanning the release history until + * it gets to the currently installed release, searching for anything marked + * as a security update. If any security updates have been found between the + * recommended release and the installed version, all of the releases that + * included a security fix are recorded so that the site administrator can be + * warned their site is insecure, and links pointing to the release notes for + * each security update can be included (which, in turn, will link to the + * official security announcements for each vulnerability). + * + * This function relies on the fact that the .xml release history data comes + * sorted based on major version and patch level, then finally by release date + * if there are multiple releases such as betas from the same major.patch + * version (e.g. 5.x-1.5-beta1, 5.x-1.5-beta2, and 5.x-1.5). Development + * snapshots for a given major version are always listed last. + * + * @param $avail + * Array of data about available project releases. + * + * @see update_get_available() + * @see update_get_projects() + * @see update_process_project_info() + */ +function update_calculate_project_data($avail) { + $projects = update_get_projects(); + update_process_project_info($projects); + $settings = variable_get('update_project_settings', array()); + foreach ($projects as $project => $project_info) { + if (isset($avail[$project])) { + // Figure out the target major version. + $existing_major = $project_info['existing_major']; + if (isset($avail[$project]['default_major'])) { + $default_major = $avail[$project]['default_major']; + $target_major = max($existing_major, $default_major); + } + else { + $target_major = $existing_major; + } + + // Initialize variables needed to find the recommended version. + $version_patch_changed = ''; + $patch = ''; + + foreach ($avail[$project]['releases'] as $version => $release) { + // 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) { + if (!isset($avail[$project]['also'])) { + $avail[$project]['also'] = array(); + } + if (!isset($avail[$project]['also'][$release['version_major']])) { + $avail[$project]['also'][$release['version_major']] = $version; + } + // Otherwise, this release can't matter to us, since it's neither + // from the release series we're currently using nor the recommended + // release. We don't even care about security updates for this + // branch, since if a project maintainer puts out a security release + // at a higher major version and not at the lower major version, + // they must change the default major release at the same time, in + // which case we won't hit this code. + continue; + } + + // Look for the 'latest version' if we haven't found it yet. Latest is + // defined as the most recent version for the target major version. + if (!isset($avail[$project]['latest_version']) + && $release['version_major'] == $target_major) { + $avail[$project]['latest_version'] = $version; + } + + // Look for the development snapshot release for this branch. + if (!isset($avail[$project]['dev_version']) + && isset($release['version_extra']) + && $release['version_extra'] == 'dev') { + $avail[$project]['dev_version'] = $version; + } + + // Look for the 'recommended' version if we haven't found it yet (see + // phpdoc at the top of this function for the definition). + if (!isset($avail[$project]['recommended']) + && $release['version_major'] == $target_major + && isset($release['version_patch'])) { + if ($patch != $release['version_patch']) { + $patch = $release['version_patch']; + $version_patch_changed = $release['version']; + } + if (empty($release['version_extra']) && $patch == $release['version_patch']) { + $avail[$project]['recommended'] = $version_patch_changed; + } + } + + // Stop searching once we hit the currently installed version. + if ($projects[$project]['existing_version'] == $version) { + break; + } + + // If we're running a dev snapshot and have a timestamp, stop + // searching for security updates once we hit an official release + // older than what we've got. Allow 100 seconds of leeway to handle + // differences between the datestamp in the .info file and the + // timestamp of the tarball itself (which are usually off by 1 or 2 + // seconds) so that we don't flag that as a new release. + if ($projects[$project]['install_type'] == 'dev') { + if (empty($projects[$project]['datestamp'])) { + // We don't have current timestamp info, so we can't know. + continue; + } + elseif (isset($release['date']) && ($projects[$project]['datestamp'] + 100 > $release['date'])) { + // We're newer than this, so we can skip it. + continue; + } + } + + // See if this release is a security update. + if (isset($release['terms']) + && isset($release['terms']['Release type']) + && in_array('Security update', $release['terms']['Release type'])) { + $projects[$project]['security updates'][] = $release; + } + } + + // If we were unable to find a recommended version, then make the latest + // version the recommended version if possible. + if (!isset($avail[$project]['recommended']) && isset($avail[$project]['latest_version'])) { + $avail[$project]['recommended'] = $avail[$project]['latest_version']; + } + + // If we're running a dev snapshot, compare the date of the dev snapshot + // with the latest official version, and record the absolute latest in + // 'latest_dev' so we can correctly decide if there's a newer release + // than our current snapshot. + if ($projects[$project]['install_type'] == 'dev') { + if (isset($avail[$project]['dev_version']) && $avail[$project]['releases'][$avail[$project]['dev_version']]['date'] > $avail[$project]['releases'][$avail[$project]['latest_version']]['date']) { + $projects[$project]['latest_dev'] = $avail[$project]['dev_version']; + } + else { + $projects[$project]['latest_dev'] = $avail[$project]['latest_version']; + } + } + + // Stash the info about available releases into our $projects array. + $projects[$project] += $avail[$project]; + + // + // Check to see if we need an update or not. + // + + // If we don't know what to recommend, there's nothing much we can + // report, so bail out early. + if (!isset($projects[$project]['recommended'])) { + $projects[$project]['status'] = UPDATE_UNKNOWN; + $projects[$project]['reason'] = t('No available releases found'); + continue; + } + + // First, see if we're not supposed to check due to settings. + if (isset($settings[$project]) && isset($settings[$project]['check']) && + ($settings[$project]['check'] == 'never' || + $settings[$project]['check'] == $avail[$project]['recommended'])) { + $projects[$project]['check'] = FALSE; + $projects[$project]['status'] = UPDATE_NOT_CHECKED; + $projects[$project]['reason'] = t('Settings'); + $projects[$project]['notes'] = $settings[$project]['notes']; + continue; + } + + // Check based upon install type and site-wide error threshold setting. + $error_level = variable_get('update_error_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; + } + else { + $projects[$project]['status'] = UPDATE_NOT_CURRENT; + } + } + break; + case 'dev': + if (!empty($projects[$project]['security updates'])) { + $projects[$project]['status'] = UPDATE_NOT_SECURE; + break; + } + + $latest = $avail[$project]['releases'][$projects[$project]['latest_dev']]; + if (empty($projects[$project]['datestamp'])) { + $projects[$project]['status'] = UPDATE_NOT_CHECKED; + $projects[$project]['reason'] = t('No filedate available'); + } + 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'); + } + } + else { + $projects[$project]['status'] = UPDATE_UNKNOWN; + $projects[$project]['reason'] = t('No available releases found'); + } + } + return $projects; +} + +/** + * Internal helper to try to get the update information from the cache + * if possible, and to refresh the cache when necessary. + * + * @param $refresh + * Boolean to indicate if this method should refresh the cache automatically + * if there's no data. + */ +function update_get_available($refresh = FALSE) { + $avail = array(); + if (($cache = cache_get('update_info', 'cache')) + && $cache->expire > time()) { + $avail = $cache->data; + } + elseif ($refresh) { + $avail = update_refresh(); + } + return $avail; +} + +/** + * Invalidates any cached data relating to update status. + */ +function update_invalidate_cache() { + cache_clear_all('update_info', 'cache'); +} + +/** + * Wrapper to load the include file and then refresh the release data. + */ +function update_refresh() { + include_once './modules/update/update.fetch.inc'; + _update_refresh(); +} Index: modules/update/update.report.inc =================================================================== RCS file: modules/update/update.report.inc diff -N modules/update/update.report.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/update/update.report.inc 29 Jun 2007 07:08:57 -0000 @@ -0,0 +1,222 @@ +'. t('Last checked: ') . ($last ? format_date($last) : t('Never')); + $output .= ' '. l(t('Check manually'), 'admin/logs/updates/force-check') .''; + + if (!is_array($data)) { + $output .= ''. $data .'
'; + return $output; + } + + $header = array(); + $rows = array(); + + $error_level = variable_get('update_error_threshold', 'all'); + + foreach ($data as $project) { + switch ($project['status']) { + case UPDATE_CURRENT: + $class = 'ok'; + $icon = theme('image', 'misc/watchdog-ok.png'); + break; + case UPDATE_NOT_SECURE: + case UPDATE_NOT_CURRENT: + if ($error_level == 'all' + || $project['status'] == UPDATE_NOT_SECURE) { + $class = 'error'; + $icon = theme('image', 'misc/watchdog-error.png'); + break; + } + // Otherwise, deliberate no break and use the warning class/icon. + default: + $class = 'warning'; + $icon = theme('image', 'misc/watchdog-warning.png'); + break; + } + + $row = ''. $tag ." | \n"; + $output .= ''; + $output .= l($version['version'], $version['release_link']); + $output .= ' ('. format_date($version['date'], 'custom', 'Y-M-d') .') '; + $output .= " | \n"; + $output .= ''; + $links = array(); + $links['update-download'] = array( + 'title' => t('Download'), + 'href' => $version['download_link'], + ); + $links['update-release-notes'] = array( + 'title' => t('Release notes'), + 'href' => $version['release_link'], + ); + $output .= theme('links', $links); + $output .= ' | '; + $output .= '