From 65082b3adbfaa04c4aff7c41147bb43e34941106 Mon Sep 17 00:00:00 2001
From: thomascube <thomas@roundcube.net>
Date: Wed, 28 Sep 2011 07:49:37 -0400
Subject: [PATCH] Distinguish standard timezone offset and DST of client

---
 program/js/common.js               |   17 +++++++++++++++++
 program/include/main.inc           |    2 +-
 program/include/rcmail.php         |    2 ++
 program/include/rcube_template.php |    2 ++
 program/include/rcube_config.php   |   25 +++++++++++++++++--------
 program/js/app.js                  |    5 ++++-
 6 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/program/include/main.inc b/program/include/main.inc
index 226fa8a..4aefb3f 100644
--- a/program/include/main.inc
+++ b/program/include/main.inc
@@ -1038,7 +1038,7 @@
   if (empty($ts))
     return '';
 
-  // get user's timezone
+  // get user's timezone offset
   $tz = $RCMAIL->config->get_timezone();
 
   // convert time to user's timezone
diff --git a/program/include/rcmail.php b/program/include/rcmail.php
index edda07c..6da5f21 100644
--- a/program/include/rcmail.php
+++ b/program/include/rcmail.php
@@ -897,6 +897,8 @@
       
       if (isset($_REQUEST['_timezone']) && $_REQUEST['_timezone'] != '_default_')
         $_SESSION['timezone'] = floatval($_REQUEST['_timezone']);
+      if (isset($_REQUEST['_dstactive']) && $_REQUEST['_dstactive'] != '_default_')
+        $_SESSION['dst_active'] = intval($_REQUEST['_dstactive']);
 
       // force reloading complete list of subscribed mailboxes
       $this->imap->clear_cache('mailboxes', true);
diff --git a/program/include/rcube_config.php b/program/include/rcube_config.php
index 31b7ed6..4e40235 100644
--- a/program/include/rcube_config.php
+++ b/program/include/rcube_config.php
@@ -90,6 +90,13 @@
 
         // enable display_errors in 'show' level, but not for ajax requests
         ini_set('display_errors', intval(empty($_REQUEST['_remote']) && ($this->prop['debug_level'] & 4)));
+        
+        // set timezone auto settings values
+        if ($this->prop['timezone'] == 'auto') {
+          $this->prop['_timezone_auto'] = true;
+          $this->prop['dst_active'] = intval(date('I'));
+          $this->prop['timezone']   = date('Z') / 3600 - $this->prop['dst_active'];
+        }
 
         // export config data
         $GLOBALS['CONFIG'] = &$this->prop;
@@ -207,6 +214,12 @@
 
         $this->userprefs = $prefs;
         $this->prop      = array_merge($this->prop, $prefs);
+
+        // override timezone settings with client values
+        if ($this->prop['_timezone_auto']) {
+            $this->prop['timezone']   = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : $this->prop['timezone'];
+            $this->prop['dst_active'] = isset($_SESSION['dst_active']) ? $_SESSION['dst_active'] : $this->prop['dst_active'];
+        }
     }
 
 
@@ -221,17 +234,13 @@
     }
 
     /**
-     * Special getter for user's timezone
+     * Special getter for user's timezone offset including DST
+     *
+     * @return float  Timezone offset (in hours)
      */
     public function get_timezone()
     {
-      $tz = $this->get('timezone');
-      if ($tz == 'auto')
-        $tz = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : date('Z') / 3600;
-      else
-        $tz = intval($tz) + intval($this->get('dst_active'));
-
-      return $tz;
+      return floatval($this->get('timezone')) + intval($this->get('dst_active'));
     }
 
     /**
diff --git a/program/include/rcube_template.php b/program/include/rcube_template.php
index 9a7bee7..043fcc6 100755
--- a/program/include/rcube_template.php
+++ b/program/include/rcube_template.php
@@ -1105,6 +1105,7 @@
         $input_task   = new html_hiddenfield(array('name' => '_task', 'value' => 'login'));
         $input_action = new html_hiddenfield(array('name' => '_action', 'value' => 'login'));
         $input_tzone  = new html_hiddenfield(array('name' => '_timezone', 'id' => 'rcmlogintz', 'value' => '_default_'));
+        $input_dst    = new html_hiddenfield(array('name' => '_dstactive', 'id' => 'rcmlogindst', 'value' => '_default_'));
         $input_url    = new html_hiddenfield(array('name' => '_url', 'id' => 'rcmloginurl', 'value' => $url));
         $input_user   = new html_inputfield(array('name' => '_user', 'id' => 'rcmloginuser')
             + $attrib + $user_attrib);
@@ -1156,6 +1157,7 @@
         $out  = $input_task->show();
         $out .= $input_action->show();
         $out .= $input_tzone->show();
+        $out .= $input_dst->show();
         $out .= $input_url->show();
         $out .= $table->show();
 
diff --git a/program/js/app.js b/program/js/app.js
index 22599eb..1a8d967 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -380,7 +380,10 @@
           $('#rcmloginpwd').focus();
 
         // detect client timezone
-        $('#rcmlogintz').val(new Date().getTimezoneOffset() / -60);
+        var tz = new Date().getTimezoneOffset() / -60;
+        var stdtz = new Date().getStdTimezoneOffset() / -60;
+        $('#rcmlogintz').val(stdtz);
+        $('#rcmlogindst').val(tz > stdtz ? 0 : 0);
 
         // display 'loading' message on form submit, lock submit button
         $('form').submit(function () {
diff --git a/program/js/common.js b/program/js/common.js
index f69125b..831e44a 100644
--- a/program/js/common.js
+++ b/program/js/common.js
@@ -671,6 +671,23 @@
   return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
 };
 
+// Extend Date prototype to detect Standard timezone without DST
+// from http://www.michaelapproved.com/articles/timezone-detect-and-ignore-daylight-saving-time-dst/
+Date.prototype.getStdTimezoneOffset = function()
+{
+  var m = 12,
+    d = new Date(null, m, 1),
+    tzo = d.getTimezoneOffset();
+
+    while (--m) {
+      d.setUTCMonth(m);
+      if (tzo != d.getTimezoneOffset()) {
+        return Math.max(tzo, d.getTimezoneOffset());
+    }
+  }
+
+  return tzo;
+}
 
 // Make getElementById() case-sensitive on IE
 if (bw.ie)

--
Gitblit v1.9.1