From b6814340c5e711803b47ff1e77571eeb28d303c0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20=C4=8Ciha=C5=99?= <mcihar@novell.com>
Date: Wed, 2 Feb 2011 11:43:21 +0100
Subject: [PATCH] Display notification if newer version is available.

This is done using asynchronous javascript so it should not block any
actions.
---
 js/functions.js             |   64 ++++++++++++++++++++++++++++++++++++++++
 js/jquery/jquery.sprintf.js |   68 +++++++++++++++++++++++++++++++++++++++++++
 js/messages.php             |    9 ++++++
 main.php                    |    1 +
 4 files changed, 142 insertions(+), 0 deletions(-)
 create mode 100644 js/jquery/jquery.sprintf.js

diff --git a/js/functions.js b/js/functions.js
index bfbcca1..1c40132 100644
--- a/js/functions.js
+++ b/js/functions.js
@@ -45,6 +45,55 @@ function suggestPassword(passwd_form) {
 }
 
 /**
+ * Version string to integer conversion.
+ */
+function parseVersionString (str) {
+    if (typeof(str) != 'string') { return false; }
+    var add = 0;
+    // Parse possible alpha/beta/rc/
+    var state = str.split('-');
+    if (state.length >= 2) {
+        if (state[1].substr(0, 2) == 'rc') {
+            add = - 20 - parseInt(state[1].substr(2));
+        } else if (state[1].substr(0, 4) == 'beta') {
+            add =  - 40 - parseInt(state[1].substr(4));
+        } else if (state[1].substr(0, 5) == 'alpha') {
+            add =  - 60 - parseInt(state[1].substr(5));
+        } else if (state[1].substr(0, 3) == 'dev') {
+            /* We don't handle dev, it's git snapshot */
+            add = 0;
+        }
+    }
+    // Parse version
+    var x = str.split('.');
+    // Use 0 for non existing parts
+    var maj = parseInt(x[0]) || 0;
+    var min = parseInt(x[1]) || 0;
+    var pat = parseInt(x[2]) || 0;
+    var hotfix = parseInt(x[3]) || 0;
+    return  maj * 100000000 + min * 1000000 + pat * 10000 + hotfix * 100 + add;
+}
+
+/**
+ * Indicates current available version on main page.
+ */
+function PMA_current_version() {
+    var current = parseVersionString('3.4.0'/*pmaversion*/);
+    var latest = parseVersionString(PMA_latest_version);
+    $('#li_pma_version').append(PMA_messages['strLatestAvailable'] + ' ' + PMA_latest_version);
+    if (latest > current) {
+        var message = $.sprintf(PMA_messages['strNewerVersion'], PMA_latest_version, PMA_latest_date);
+        if (Math.floor(latest / 10000) == Math.floor(current / 10000)) {
+            /* Security update */
+            klass = 'warning';
+        } else {
+            klass = 'notice';
+        }
+        $('#maincontainer').after('<div class="' + klass + '">' + message + '</div>');
+    }
+}
+
+/**
  * for libraries/display_change_password.lib.php
  *     libraries/user_password.php
  *
@@ -2414,5 +2463,20 @@ $(document).ready(function() {
         $(this).closest("form").submit();
     });
 
+    /**
+     * Load version information asynchronously.
+     */
+    if ($('#li_pma_version').length > 0) {
+        (function() {
+            var s = document.createElement('script');
+            s.type = 'text/javascript';
+            s.async = true;
+            s.src = 'http://www.phpmyadmin.net/home_page/version.js';
+            s.onload = PMA_current_version;
+            var x = document.getElementsByTagName('script')[0];
+            x.parentNode.insertBefore(s, x);
+        })();
+    }
+
 }) // end of $(document).ready()
 
diff --git a/js/jquery/jquery.sprintf.js b/js/jquery/jquery.sprintf.js
new file mode 100644
index 0000000..3d39b76
--- /dev/null
+++ b/js/jquery/jquery.sprintf.js
@@ -0,0 +1,68 @@
+/**
+ * sprintf and vsprintf for jQuery
+ * somewhat based on http://jan.moesen.nu/code/javascript/sprintf-and-printf-in-javascript/
+ *
+ * Copyright (c) 2008 Sabin Iacob (m0n5t3r) <iacobs@m0n5t3r.info>
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * @license http://www.gnu.org/licenses/gpl.html
+ * @project jquery.sprintf
+ */
+(function($){
+        var formats = {
+                'b': function(val) {return parseInt(val, 10).toString(2);},
+                'c': function(val) {return String.fromCharCode(parseInt(val, 10));},
+                'd': function(val) {return parseInt(val, 10);},
+                'u': function(val) {return Math.abs(val);},
+                'f': function(val, p) {
+                        p = parseInt(p, 10);
+                        val = parseFloat(val);
+                        if(isNaN(p && val)) {
+                                return NaN;
+                        }
+                        return p && val.toFixed(p) || val;
+                },
+                'o': function(val) {return parseInt(val, 10).toString(8);},
+                's': function(val) {return val;},
+                'x': function(val) {return ('' + parseInt(val, 10).toString(16)).toLowerCase();},
+                'X': function(val) {return ('' + parseInt(val, 10).toString(16)).toUpperCase();}
+        };
+
+        var re = /%(?:(\d+)?(?:\.(\d+))?|\(([^)]+)\))([%bcdufosxX])/g;
+
+        var dispatch = function(data){
+                if(data.length == 1 && typeof data[0] == 'object') { //python-style printf
+                        data = data[0];
+                        return function(match, w, p, lbl, fmt, off, str) {
+                                return formats[fmt](data[lbl]);
+                        };
+                } else { // regular, somewhat incomplete, printf
+                        var idx = 0;
+                        return function(match, w, p, lbl, fmt, off, str) {
+                                if(fmt == '%') {
+                                        return '%';
+                                }
+                                return formats[fmt](data[idx++], p);
+                        };
+                }
+        };
+
+        $.extend({
+                sprintf: function(format) {
+                        var argv = Array.apply(null, arguments).slice(1);
+                        return format.replace(re, dispatch(argv));
+                },
+                vsprintf: function(format, data) {
+                        return format.replace(re, dispatch(data));
+                }
+        });
+})(jQuery);
+
diff --git a/js/messages.php b/js/messages.php
index f9f764e..ded9546 100644
--- a/js/messages.php
+++ b/js/messages.php
@@ -109,6 +109,11 @@ $js_messages['strChangePassword'] = __('Change Password');
 /* navigation tabs */
 $js_messages['strMore'] = __('More');
 
+/* update */
+$js_messages['strNewerVersion'] = __('A newer version of phpMyAdmin is available and you should consider upgrading. The newest version is %s, released on %s.');
+/* l10n: Latest available phpMyAdmin version */
+$js_messages['strLatestAvailable'] = __(', latest available:');
+
 echo "var PMA_messages = new Array();\n";
 foreach ($js_messages as $name => $js_message) {
     PMA_printJsValue("PMA_messages['" . $name . "']", $js_message);
@@ -116,6 +121,10 @@ foreach ($js_messages as $name => $js_message) {
 
 /* Calendar */
 echo "var themeCalendarImage = '" . $GLOBALS['pmaThemeImage'] . 'b_calendar.png' . "';\n";
+
+/* Version */
+echo "var pmaversion = '" . PMA_VERSION . "';\n";
+
 echo "if ($.datepicker) {\n";
 /* l10n: Display text for calendar close link */
 PMA_printJsValue("$.datepicker.regional['']['closeText']", __('Done'));
diff --git a/main.php b/main.php
index 1361391..942d2bc 100644
--- a/main.php
+++ b/main.php
@@ -14,6 +14,7 @@ require_once './libraries/common.inc.php';
 $GLOBALS['js_include'][] = 'colorpicker/js/colorpicker.js';
 $GLOBALS['js_include'][] = 'main_custom_color.js';
 $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js';
+$GLOBALS['js_include'][] = 'jquery/jquery.sprintf.js';
 
 // Handles some variables that may have been sent by the calling script
 $GLOBALS['db'] = '';
-- 
1.7.2.3

