diff --git a/admin/templates/default/config.tpl b/admin/templates/default/config.tpl index bd4f1b1bd5..8eae450db2 100644 --- a/admin/templates/default/config.tpl +++ b/admin/templates/default/config.tpl @@ -8,26 +8,6 @@ -
'.lang('EGroupware version').' '.$version.'
', + 'apiVersion' => ''.lang('EGroupware version').' '.egw_framework::api_version($changelog).'
', 'applications' => $apps, 'templates' => $templates, 'translations' => $translations, diff --git a/phpgwapi/inc/class.egw_framework.inc.php b/phpgwapi/inc/class.egw_framework.inc.php index 3cc08c9f3b..0b441209a8 100644 --- a/phpgwapi/inc/class.egw_framework.inc.php +++ b/phpgwapi/inc/class.egw_framework.inc.php @@ -873,6 +873,107 @@ abstract class egw_framework 'id="notificationbell" style="display: none"'); } + /** + * URL to check for security or maintenance updates + */ + const CURRENT_VERSION_URL = 'http://www.egroupware.org/currentversion'; + /** + * How long to cache (in secs) / often to check for updates + */ + const VERSIONS_CACHE_TIMEOUT = 7200; + /** + * After how many days of not applied security updates, start warning non-admins too + */ + const WARN_USERS_DAYS = 3; + + /** + * Check update status + * + * @return string + * @todo Check from client-side, if server-side check fails + */ + protected static function _get_update_notification() + { + $versions = egw_cache::getTree(__CLASS__, 'versions', function() + { + $versions = array(); + $security = null; + if (($remote = file_get_contents(egw_framework::CURRENT_VERSION_URL))) + { + list($current, $security) = explode("\n", $remote); + if (empty($security)) $security = $current; + $versions = array( + 'current' => $current, // last maintenance update + 'security' => $security, // last security update + ); + } + return $versions; + }, array(), self::VERSIONS_CACHE_TIMEOUT); + + $api = self::api_version(); + + if ($versions) + { + if (version_compare($api, $versions['security'], '<')) + { + if (!$GLOBALS['egw_info']['user']['apps']['admin'] && !self::update_older($versions['security'], self::WARN_USERS_DAYS)) + { + return null; + } + return html::a_href(html::image('phpgwapi', 'security-update', lang('EGroupware security update %1 needs to be installed!', $versions['security'])), + 'http://www.egroupware.org/changelog', null, ' target="_blank"'); + } + if ($GLOBALS['egw_info']['user']['apps']['admin'] && version_compare($api, $versions['current'], '<')) + { + return html::a_href(html::image('phpgwapi', 'update', lang('EGroupware maintenance update %1 available', $versions['current'])), + 'http://www.egroupware.org/changelog', null, ' target="_blank"'); + } + } + elseif ($GLOBALS['egw_info']['user']['apps']['admin']) + { + return html::a_href(html::image('phpgwapi', 'update', lang('Automatic update check failed, you need to check manually!')), + 'http://www.egroupware.org/changelog', null, ' target="_blank" data-api-version="'.$api.'"'); + } + return null; + } + + /** + * Check if version is older then $days days + * + * @param string $version eg. "14.1.20140715" last part is checked (only if > 20140000!) + * @param int $days + * @return boolean + */ + protected static function update_older($version, $days) + { + list(,,$date) = explode('.', $version); + if ($date < 20140000) return false; + $version_timestamp = mktime(0, 0, 0, (int)substr($date, 4, 2), (int)substr($date, -2), (int)substr($date, 0, 4)); + + return (time() - $version_timestamp) / 86400 > $days; + } + + /** + * Get API version from changelog or database, whichever is bigger + * + * @param string &$changelog on return path to changelog + * @return string + */ + public static function api_version(&$changelog=null) + { + $version = preg_replace('/[^0-9.]/', '', $GLOBALS['egw_info']['server']['versions']['phpgwapi']); + // parse version from changelog + $changelog = EGW_SERVER_ROOT.'/doc/rpm-build/debian.changes'; + $matches = null; + if (($f = fopen($changelog, 'r')) && preg_match('/egroupware-epl \(([0-9.]+)/', fread($f, 80), $matches) && + version_compare($version, $matches[1], '<')) + { + $version = $matches[1]; + fclose($f); + } + return $version; + } + /** * Get the link to an application's index page * @@ -1373,6 +1474,10 @@ if ($app == 'home') continue; $this->_add_topmenu_item($apps['logout']); + if (($update = self::_get_update_notification())) + { + $this->_add_topmenu_info_item($update, 'update'); + } if($GLOBALS['egw_info']['user']['apps']['notifications']) { $this->_add_topmenu_info_item(self::_get_notification_bell(), 'notifications'); diff --git a/phpgwapi/lang/egw_de.lang b/phpgwapi/lang/egw_de.lang index 5c20ff89bb..2ccc882ae6 100644 --- a/phpgwapi/lang/egw_de.lang +++ b/phpgwapi/lang/egw_de.lang @@ -91,6 +91,7 @@ austria common de ÖSTERREICH author common de Autor autohide sidebox menu's common de Linkes Navigationsmenü ausblenden autohide sidebox menus common de Linkes Navigationsmenü ausblenden +automatic update check failed, you need to check manually! admin de Automatischer Test fehlgeschlagen, Sie müssen selbst überprüfen ob neue Updates vorliegen! automatically hide the sidebox menu's? common de Automatisch linkes Navigationsmenü ausblenden? automatically hide the sidebox menus? common de Automatisch linkes Navigationsmenü ausblenden? autosave default category common de Standard-Kategorie automatisch speichern @@ -266,6 +267,8 @@ edit categories common de Kategorien editieren edit category common de Kategorie editieren egroupware common de EGroupware egroupware api version common de EGroupware API Version +egroupware maintenance update %1 available admin de EGroupware Fehlerbehebungsupdate %1 ist verfügbar +egroupware security update %1 needs to be installed! common de EGroupware Sicherheitsupdate %1 muss installiert werden! egroupware: login blocked for user '%1', ip %2 common de EGroupware: Anmelden gesperrt für Benutzer '%1', IP %2 egypt common de ÄGYPTEN el salvador common de EL SALVADOR diff --git a/phpgwapi/lang/egw_en.lang b/phpgwapi/lang/egw_en.lang index 5f7b91d2d7..748c167c30 100644 --- a/phpgwapi/lang/egw_en.lang +++ b/phpgwapi/lang/egw_en.lang @@ -91,6 +91,7 @@ austria common en AUSTRIA author common en Author autohide sidebox menu's common en Autohide side menu autohide sidebox menus common en Autohide side menu +automatic update check failed, you need to check manually! admin en Automatic update check failed, you need to check manually! automatically hide the sidebox menu's? common en Automatically hide the side menu? automatically hide the sidebox menus? common en Automatically hide the side menu? autosave default category common en Auto-save default category. @@ -266,6 +267,8 @@ edit categories common en Edit categories edit category common en Edit category egroupware common en EGroupware egroupware api version common en EGroupware API version +egroupware maintenance update %1 available admin en EGroupware maintenance update %1 available +egroupware security update %1 needs to be installed! common en EGroupware security update %1 needs to be installed! egroupware: login blocked for user '%1', ip %2 common en Login blocked for user '%1', IP %2 egypt common en EGYPT el salvador common en EL SALVADOR diff --git a/phpgwapi/templates/idots/class.idots_framework.inc.php b/phpgwapi/templates/idots/class.idots_framework.inc.php index d6d530477a..e581ca6a63 100644 --- a/phpgwapi/templates/idots/class.idots_framework.inc.php +++ b/phpgwapi/templates/idots/class.idots_framework.inc.php @@ -450,8 +450,7 @@ class idots_framework extends egw_framework */ function _add_topmenu_info_item($content, $id=null) { - unset($id); // unused, but required in function signature - $this->tplsav2->menuinfoitems[] = $content; + $this->tplsav2->menuinfoitems[$id] = $content; } /** diff --git a/phpgwapi/templates/idots/css/traditional.css b/phpgwapi/templates/idots/css/traditional.css index c3c122ea73..2e044d328f 100755 --- a/phpgwapi/templates/idots/css/traditional.css +++ b/phpgwapi/templates/idots/css/traditional.css @@ -324,6 +324,23 @@ body { #topmenu_info { float:right; + white-space: nowrap; +} + +.topmenu_info_item { + display: inline-block; + padding-left: 8px; + position: relative; +} +#topmenu_info_update { + position: relative; + padding-right: 16px; + display: inline; +} +#topmenu_info_update a img { + height: 32px; + position: absolute; + z-index: 10000; } #divUpperTabs diff --git a/phpgwapi/templates/idots/topmenu.tpl.php b/phpgwapi/templates/idots/topmenu.tpl.php index 1529c9cfc4..90087898d6 100644 --- a/phpgwapi/templates/idots/topmenu.tpl.php +++ b/phpgwapi/templates/idots/topmenu.tpl.php @@ -18,8 +18,8 @@ - menuinfoitems as $mitems):?> - + menuinfoitems as $id => $mitems):?> +