From 77de23fa939338546a3e049459ffd29edd9058c2 Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Sun, 11 Nov 2012 04:32:05 -0500
Subject: [PATCH] Added cross-task 'refresh' request for system state updates

---
 CHANGELOG                               |    2 +
 index.php                               |    4 +-
 program/steps/mail/check_recent.inc     |   10 +++-
 program/include/rcmail.php              |    5 ++
 program/localization/en_US/messages.inc |    1 
 program/steps/mail/func.inc             |    1 
 program/js/app.js                       |   83 ++++++++++++++++++++++++++++-------------
 7 files changed, 74 insertions(+), 32 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 02fe0e2..dea6c19 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,8 @@
 CHANGELOG Roundcube Webmail
 ===========================
 
+- Improved keep-alive action. Now the interval is based on session_lifetime
+- Added cross-task 'refresh' request for system state updates
 - Fix AREA links handling (#1488792)
 - Better client-side timezone detection using the jsTimezoneDetect library (#1488725)
 - Fix possible HTTP DoS on error in keep-alive requests (#1488782)
diff --git a/index.php b/index.php
index 0ad371a..05fc641 100644
--- a/index.php
+++ b/index.php
@@ -249,7 +249,6 @@
 $RCMAIL->set_task($plugin['task']);
 $RCMAIL->action = $plugin['action'];
 
-
 // handle special actions
 if ($RCMAIL->action == 'keep-alive') {
   $OUTPUT->reset();
@@ -282,7 +281,8 @@
   else if (($stepfile = $RCMAIL->get_action_file())
     && is_file($incfile = INSTALL_PATH . 'program/steps/'.$RCMAIL->task.'/'.$stepfile)
   ) {
-    include $incfile;
+    // include action file only once (in case it don't exit)
+    include_once $incfile;
     $redirects++;
   }
   else {
diff --git a/program/include/rcmail.php b/program/include/rcmail.php
index a755aa8..04b87e4 100644
--- a/program/include/rcmail.php
+++ b/program/include/rcmail.php
@@ -332,7 +332,7 @@
     $this->output->set_charset(RCMAIL_CHARSET);
 
     // add some basic labels to client
-    $this->output->add_label('loading', 'servererror', 'requesttimedout');
+    $this->output->add_label('loading', 'servererror', 'requesttimedout', 'refreshing');
 
     return $this->output;
   }
@@ -770,6 +770,7 @@
     }
   }
 
+
   /**
    * Registers action aliases for current task
    *
@@ -784,6 +785,7 @@
     }
   }
 
+
   /**
    * Returns current action filename
    *
@@ -798,6 +800,7 @@
     return strtr($this->action, '-', '_') . '.inc';
   }
 
+
   /**
    * Fixes some user preferences according to namespace handling change.
    * Old Roundcube versions were using folder names with removed namespace prefix.
diff --git a/program/js/app.js b/program/js/app.js
index f372c0f..25fddf1 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -482,7 +482,8 @@
         this.onloads[i]();
       }
 
-    // start keep-alive interval
+    // start keep-alive and refresh intervals
+    this.start_refresh();
     this.start_keepalive();
   };
 
@@ -878,10 +879,6 @@
       case 'firstmessage':
         if (this.env.first_uid)
           this.show_message(this.env.first_uid);
-        break;
-
-      case 'checkmail':
-        this.check_for_recent(true);
         break;
 
       case 'compose':
@@ -2059,6 +2056,15 @@
       else if (this.task == 'mail')
         this.list_mailbox(this.env.mailbox, page);
     }
+  };
+
+  // sends request to check for recent messages
+  this.checkmail = function()
+  {
+    var lock = this.set_busy(true, 'checkingmail'),
+      params = this.check_recent_params();
+
+    this.http_request('check-recent', params, lock);
   };
 
   // list messages of a specific mailbox using filter
@@ -6125,7 +6131,7 @@
     // trigger plugin hook
     var result = this.triggerEvent('request'+action, postdata);
     if (result !== undefined) {
-      // abort if one the handlers returned false
+      // abort if one of the handlers returned false
       if (result === false)
         return false;
       else
@@ -6237,6 +6243,7 @@
         }
         break;
 
+      case 'refresh':
       case 'check-recent':
       case 'getunread':
       case 'search':
@@ -6469,13 +6476,25 @@
   // starts interval for keep-alive signal
   this.start_keepalive = function()
   {
-    if (!this.env.session_lifetime || this.env.framed || this.task == 'login' || this.env.action == 'print')
+    if (!this.env.session_lifetime || this.env.framed || this.env.extwin || this.task == 'login' || this.env.action == 'print')
       return;
 
-    if (this._int)
-      clearInterval(this._int);
+    if (this._keepalive)
+      clearInterval(this._keepalive);
 
-    this._int = setInterval(function(){ ref.keep_alive(); }, this.env.session_lifetime * 0.5 * 1000);
+    this._keepalive = setInterval(function(){ ref.keep_alive(); }, this.env.session_lifetime * 0.5 * 1000);
+  };
+
+  // starts interval for refresh signal
+  this.start_refresh = function()
+  {
+    if (!this.env.keep_alive || this.env.framed || this.env.extwin || this.task == 'login' || this.env.action == 'print')
+      return;
+
+    if (this._refresh)
+      clearInterval(this._refresh);
+
+    this._refresh = setInterval(function(){ ref.refresh(); }, this.env.keep_alive * 1000);
   };
 
   // sends keep-alive signal
@@ -6485,27 +6504,39 @@
       this.http_request('keep-alive');
   };
 
-  // sends request to check for recent messages
-  this.check_for_recent = function(refresh)
+  // sends refresh signal
+  this.refresh = function()
   {
-    if (this.busy)
+    if (this.busy) {
+      // try again after 10 seconds
+      setTimeout(function(){ ref.refresh(); ref.start_refresh(); }, 10000);
       return;
-
-    var lock, url = {_mbox: this.env.mailbox};
-
-    if (refresh) {
-      lock = this.set_busy(true, 'checkingmail');
-      url._refresh = 1;
     }
 
-    if (this.gui_objects.messagelist)
-      url._list = 1;
-    if (this.gui_objects.quotadisplay)
-      url._quota = 1;
-    if (this.env.search_request)
-      url._search = this.env.search_request;
+    var params = {}, lock = this.set_busy(true, 'refreshing');
 
-    this.http_request('check-recent', url, lock);
+    if (this.task == 'mail' && this.gui_objects.mailboxlist)
+      params = this.check_recent_params();
+
+    // plugins should bind to 'requestrefresh' event to add own params
+    this.http_request('refresh', params, lock);
+  };
+
+  // returns check-recent request parameters
+  this.check_recent_params = function()
+  {
+    var params = {_mbox: this.env.mailbox};
+
+    if (this.gui_objects.mailboxlist)
+      params._folderlist = 1;
+    if (this.gui_objects.messagelist)
+      params._list = 1;
+    if (this.gui_objects.quotadisplay)
+      params._quota = 1;
+    if (this.env.search_request)
+      params._search = this.env.search_request;
+
+    return params;
   };
 
 
diff --git a/program/localization/en_US/messages.inc b/program/localization/en_US/messages.inc
index cabc999..a858d0a 100644
--- a/program/localization/en_US/messages.inc
+++ b/program/localization/en_US/messages.inc
@@ -37,6 +37,7 @@
 $messages['nomessagesfound'] = 'No messages found in this mailbox.';
 $messages['loggedout'] = 'You have successfully terminated the session. Good bye!';
 $messages['mailboxempty'] = 'Mailbox is empty.';
+$messages['refreshing'] = 'Refreshing...';
 $messages['loading'] = 'Loading...';
 $messages['uploading'] = 'Uploading file...';
 $messages['uploadingmany'] = 'Uploading files...';
diff --git a/program/steps/mail/check_recent.inc b/program/steps/mail/check_recent.inc
index 1a1b08c..90d17c1 100644
--- a/program/steps/mail/check_recent.inc
+++ b/program/steps/mail/check_recent.inc
@@ -19,8 +19,14 @@
  +-----------------------------------------------------------------------+
 */
 
+// If there's no folder or messages list, there's nothing to update
+// This can happen on 'refresh' request
+if (empty($_REQUEST['_folderlist']) && empty($_REQUEST['_list'])) {
+    return;
+}
+
 $current = $RCMAIL->storage->get_folder();
-$check_all = !empty($_GET['_refresh']) || (bool)$RCMAIL->config->get('check_all_folders');
+$check_all = $RCMAIL->action != 'refresh' || (bool)$RCMAIL->config->get('check_all_folders');
 
 // list of folders to check
 if ($check_all) {
@@ -101,7 +107,5 @@
         }
     }
 }
-
-$RCMAIL->plugins->exec_hook('keep_alive', array());
 
 $OUTPUT->send();
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index f128a38..374ab75 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -1810,6 +1810,7 @@
 
 // register action aliases
 $RCMAIL->register_action_map(array(
+    'refresh' => 'check_recent.inc',
     'preview' => 'show.inc',
     'print'   => 'show.inc',
     'moveto'  => 'move_del.inc',

--
Gitblit v1.9.1