From b19097058c02f203321599bf04a5d7da7c2dafe8 Mon Sep 17 00:00:00 2001
From: thomascube <thomas@roundcube.net>
Date: Fri, 01 Dec 2006 13:06:16 -0500
Subject: [PATCH] Introducing preview pane and conditional skin tags

---
 program/localization/de_DE/messages.inc     |    2 
 program/include/main.inc                    |   62 ++++++
 program/localization/de_CH/messages.inc     |    5 
 skins/default/mail.css                      |   44 +++
 program/steps/mail/show.inc                 |   38 +--
 program/localization/de_CH/labels.inc       |    3 
 config/main.inc.php.dist                    |    9 
 skins/default/templates/messagepreview.html |   19 +
 program/steps/settings/save_prefs.inc       |   28 +-
 program/steps/mail/move_del.inc             |    5 
 index.php                                   |    6 
 program/include/rcube_shared.inc            |    3 
 skins/default/templates/mail.html           |   13 +
 skins/default/settings.css                  |    4 
 program/localization/en_US/messages.inc     |    4 
 program/steps/mail/func.inc                 |   21 ++
 program/steps/settings/func.inc             |  208 +++++++++++---------
 program/localization/en_US/labels.inc       |    1 
 program/js/app.js                           |   81 ++++++-
 19 files changed, 392 insertions(+), 164 deletions(-)

diff --git a/config/main.inc.php.dist b/config/main.inc.php.dist
index c047199..fb227c4 100644
--- a/config/main.inc.php.dist
+++ b/config/main.inc.php.dist
@@ -195,6 +195,9 @@
  *                                                    'fuzzy_search'  => 0);
  */
 
+// don't allow these settings to be overriden by the user
+$rcmail_config['dont_override'] = array();
+
 // list of configuration option names that need to be available in Javascript.
 $rcmail_config['javascript_config'] = array('read_when_deleted', 'flag_for_deletion');
 
@@ -216,6 +219,9 @@
 // prefer displaying HTML messages
 $rcmail_config['prefer_html'] = TRUE;
 
+// compose html formatted messages by default
+$rcmail_config['htmleditor'] = TRUE;
+
 // show pretty dates as standard
 $rcmail_config['prettydate'] = TRUE;
 
@@ -228,5 +234,8 @@
 // save compose message every 300 seconds (5min)
 $rcmail_config['draft_autosave'] = 300;
 
+// default setting if preview pane is enabled
+$rcmail_config['preview_pane'] = FALSE;
+
 // end of config file
 ?>
diff --git a/index.php b/index.php
index da92874..5d42e6d 100644
--- a/index.php
+++ b/index.php
@@ -2,7 +2,7 @@
 /*
  +-----------------------------------------------------------------------+
  | RoundCube Webmail IMAP Client                                         |
- | Version 0.1-20061122                                                  |
+ | Version 0.1-20061201                                                  |
  |                                                                       |
  | Copyright (C) 2005-2006, RoundCube Dev. - Switzerland                 |
  | Licensed under the GNU GPL                                            |
@@ -40,7 +40,7 @@
 
 */
 
-define('RCMAIL_VERSION', '0.1-20061122');
+define('RCMAIL_VERSION', '0.1-20061201');
 
 // define global vars
 $CHARSET = 'UTF-8';
@@ -264,7 +264,7 @@
   {
   include_once('program/steps/mail/func.inc');
   
-  if ($_action=='show' || $_action=='print')
+  if ($_action=='show' || $_action=='preview' || $_action=='print')
     include('program/steps/mail/show.inc');
 
   if ($_action=='get')
diff --git a/program/include/main.inc b/program/include/main.inc
index 9cf1f67..a7e50e4 100644
--- a/program/include/main.inc
+++ b/program/include/main.inc
@@ -1142,8 +1142,12 @@
 
 
   // parse for specialtags
-  $output = parse_rcube_xml($templ);
+  $output = parse_rcube_xml(parse_rcube_conditions($templ));
   
+  // add debug console
+  if ($CONFIG['debug_level'] & 8)
+    $OUTPUT->footer = '<div style="position:absolute;top:5px;left:5px;width:400px;opacity:0.8;z-index:9000;"><form name="debugform"><textarea name="console" rows="15" cols="40" style="width:400px;border:none;font-size:x-small"></textarea></form>';
+
   $OUTPUT->write(trim(parse_with_globals($output)), $skin_path);
 
   if ($exit)
@@ -1161,6 +1165,55 @@
   }
 
 
+// parse conditional code
+function parse_rcube_conditions($input)
+  {
+  if (($matches = preg_split('/<roundcube:(if|elseif|else|endif)\s+([^>]+)>/is', $input, 2, PREG_SPLIT_DELIM_CAPTURE)) && count($matches)==4)
+    {
+    if (preg_match('/^(else|endif)$/i', $matches[1]))
+      return $matches[0] . parse_rcube_conditions($matches[3]);
+    else
+      {
+      $attrib = parse_attrib_string($matches[2]);
+      if (isset($attrib['condition']))
+        {
+        $condmet = rcube_xml_condition($attrib['condition']);
+        $submatches = preg_split('/<roundcube:(elseif|else|endif)\s+([^>]+)>/is', $matches[3], 2, PREG_SPLIT_DELIM_CAPTURE);
+
+		    if ($condmet)
+			    $result = $submatches[0] . preg_replace('/.*<roundcube:endif\s+[^>]+>/is', '', $submatches[3]);
+        else
+          $result = "<roundcube:$submatches[1] $submatches[2]>" . $submatches[3];
+          
+        return $matches[0] . parse_rcube_conditions($result);
+        }
+      else
+        {
+        raise_error(array('code' => 500, 'type' => 'php', 'line' => __LINE__, 'file' => __FILE__,
+                          'message' => "Unable to parse conditional tag " . $matches[2]), TRUE, FALSE);
+        }
+      }
+    }
+
+  return $input;
+  }
+
+ 
+/**
+ * Determines if a given condition is met
+ *
+ * @return True if condition is valid, False is not
+ */
+function rcube_xml_condition($condition)
+  {
+  $condition = preg_replace(
+      array('/session:([a-z0-9_]+)/i', '/config:([a-z0-9_]+)/i', '/request:([a-z0-9_]+)/ie'),
+      array("\$_SESSION['\\1']", "\$GLOBALS['CONFIG']['\\1']", "get_input_value('\\1', RCUBE_INPUT_GPC)"),
+      $condition);
+
+  return @eval("return (".$condition.");");
+  }
+
 
 function parse_rcube_xml($input)
   {
@@ -1169,12 +1222,19 @@
   }
 
 
+/**
+ * Convert a xml command tag into real content
+ */
 function rcube_xml_command($command, $str_attrib, $add_attrib=array())
   {
   global $IMAP, $CONFIG, $OUTPUT;
   
   $command = strtolower($command);
   $attrib = parse_attrib_string($str_attrib) + $add_attrib;
+  
+  // empty output if required condition is not met
+  if (!empty($attrib['condition']) && !rcube_xml_condition($attrib['condition']))
+    return '';
 
   // execute command
   switch ($command)
diff --git a/program/include/rcube_shared.inc b/program/include/rcube_shared.inc
index a5e5e85..7a0fd05 100644
--- a/program/include/rcube_shared.inc
+++ b/program/include/rcube_shared.inc
@@ -169,6 +169,9 @@
 
     if (strlen($this->scripts['foot']))
       $__page_footer .= sprintf($this->script_tag, $this->scripts['foot']);
+      
+    if ($this->footer)
+      $__page_footer .= "\n" . $this->footer;
 
     $__page_header .= $this->css->show();
   
diff --git a/program/js/app.js b/program/js/app.js
index bc6563e..3d4d848 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -32,7 +32,7 @@
   this.ref = 'rcube_webmail_client';
  
   // webmail client settings
-  this.dblclick_time = 600;
+  this.dblclick_time = 500;
   this.message_time = 5000;
   
   this.mbox_expression = new RegExp('[^0-9a-z\-_]', 'gi');
@@ -137,7 +137,7 @@
         // enable mail commands
         this.enable_command('list', 'checkmail', 'compose', 'add-contact', 'search', 'reset-search', true);
         
-        if (this.env.action=='show')
+        if (this.env.action=='show' || this.env.action=='preview')
           {
           this.enable_command('show', 'reply', 'reply-all', 'forward', 'moveto', 'delete', 'viewsource', 'print', 'load-attachment', true);
           if (this.env.next_uid)
@@ -151,8 +151,15 @@
             this.enable_command('firstmessage', true);
             }
           }
+        
+        // make preview/message frame visible
+        if (this.env.action == 'preview' && this.env.framed && parent.rcmail)
+          {
+          this.enable_command('compose', 'add-contact', false);
+          parent.rcmail.show_messageframe(true);
+          }
 
-        if (this.env.action=='show' && this.env.blockedobjects)
+        if ((this.env.action=='show' || this.env.action=='preview') && this.env.blockedobjects)
           {
           if (this.gui_objects.remoteobjectsmsg)
             this.gui_objects.remoteobjectsmsg.style.display = 'block';
@@ -637,7 +644,7 @@
         
       case 'load-images':
         if (this.env.uid)
-          this.show_message(this.env.uid, true);
+          this.show_message(this.env.uid, true, this.env.action=='preview');
         break;
 
       case 'load-attachment':
@@ -646,7 +653,7 @@
         // open attachment in frame if it's of a supported mimetype
         if (this.env.uid && props.mimetype && find_in_array(props.mimetype, this.mimetypes)>=0)
           {
-          this.attachment_win = window.open(this.env.comm_path+'&_action=get'+url+'&_frame=1', 'rcubemailattachment');
+          this.attachment_win = window.open(this.env.comm_path+'&_action=get&'+qstring+'&_frame=1', 'rcubemailattachment');
           if (this.attachment_win)
             {
             setTimeout(this.ref+'.attachment_win.focus()', 10);
@@ -667,7 +674,7 @@
 
       case 'nextmessage':
         if (this.env.next_uid)
-          this.show_message(this.env.next_uid);
+          this.show_message(this.env.next_uid, false, this.env.action=='preview');
         break;
 
 	  case 'lastmessage':
@@ -677,7 +684,7 @@
 
       case 'previousmessage':
         if (this.env.prev_uid)
-          this.show_message(this.env.prev_uid);
+          this.show_message(this.env.prev_uid, false, this.env.action=='preview');
         break;
 
       case 'firstmessage':
@@ -1052,6 +1059,9 @@
 
   this.msglist_select = function(list)
     {
+    if (this.preview_timer)
+      clearTimeout(this.preview_timer);
+
     var selected = list.selection.length==1;
     if (this.env.mailbox == this.env.drafts_mailbox)
       {
@@ -1062,17 +1072,26 @@
       {
       this.enable_command('show', 'reply', 'reply-all', 'forward', 'print', selected);
       this.enable_command('delete', 'moveto', list.selection.length>0 ? true : false);
+
+      // start timer for message preview (wait for double click)
+      if (selected && this.env.contentframe)
+        this.preview_timer = setTimeout(this.ref+'.msglist_get_preview()', this.dblclick_time + 10);
+      else if (this.env.contentframe)
+        this.show_messageframe(false);
       }
-   };
+    };
 
 
   this.msglist_dbl_click = function(list)
     {
+      if (this.preview_timer)
+        clearTimeout(this.preview_timer);
+
     var uid = list.get_single_selection();
     if (uid && this.env.mailbox == this.env.drafts_mailbox)
       this.goto_url('compose', '_draft_uid='+uid+'&_mbox='+urlencode(this.env.mailbox), true);
     else if (uid)
-      this.show_message(uid);
+      this.show_message(uid, false, false);
     };
 
 
@@ -1085,6 +1104,15 @@
     };
 
 
+  this.msglist_get_preview = function()
+  {
+    var uid = this.get_single_uid();
+    if (uid && this.env.contentframe)
+      this.show_message(uid, false, true);
+    else if (this.env.contentframe)
+      this.show_messageframe(false);
+  };
+
 
   /*********************************************************/
   /*********     (message) list functionality      *********/
@@ -1092,11 +1120,12 @@
 
 
   // when user doble-clicks on a row
-  this.show_message = function(id, safe)
+  this.show_message = function(id, safe, preview)
     {
     var add_url = '';
+    var action = preview ? 'preview': 'show';
     var target = window;
-    if (this.env.contentframe && window.frames && window.frames[this.env.contentframe])
+    if (preview && this.env.contentframe && window.frames && window.frames[this.env.contentframe])
       {
       target = window.frames[this.env.contentframe];
       add_url = '&_framed=1';
@@ -1107,11 +1136,31 @@
 
     if (id)
       {
-      this.set_busy(true, 'loading');
-      target.location.href = this.env.comm_path+'&_action=show&_uid='+id+'&_mbox='+urlencode(this.env.mailbox)+add_url;
+      var url = '&_action='+action+'&_uid='+id+'&_mbox='+urlencode(this.env.mailbox)+add_url;
+      if (action == 'preview' && String(target.location.href).indexOf(url) >= 0)
+        this.show_messageframe(true);
+      else
+        {
+        this.set_busy(true, 'loading');
+        target.location.href = this.env.comm_path+url;
+        }
       }
     };
 
+
+  this.show_messageframe = function(show)
+    {
+    var frm;
+    if (this.env.contentframe && (frm = rcube_find_object(this.env.contentframe)))
+      {
+      if (window.frames[this.env.contentframe] && !show)
+        window.frames[this.env.contentframe].location.href = 'program/blank.gif';
+      frm.style.display = show ? 'block' : 'none';
+      }
+      
+    if (!show && this.busy)
+      this.set_busy(false);
+    };
 
 
   // list a specific page
@@ -1373,7 +1422,7 @@
   this.mark_message = function(flag, uid)
     {
     var a_uids = new Array();
-    var selection = this.message_list.get_selection();
+    var selection = this.message_list ? this.message_list.get_selection() : new Array();
     
     if (uid)
       a_uids[0] = uid;
@@ -3102,7 +3151,7 @@
   this.http_request = function(action, querystring, lock)
     {
     var request_obj = this.get_request_obj();
-    querystring += '&_remote=1';
+    querystring += (querystring ? '&' : '') + '_remote=1';
     
     // add timestamp to request url to avoid cacheing problems in Safari
     if (bw.safari)
@@ -3151,6 +3200,8 @@
       case 'moveto':
         if (this.env.action=='show')
           this.command('list');
+        else if (this.message_list)
+          this.message_list.init();
         break;
 
       case 'list':
diff --git a/program/localization/de_CH/labels.inc b/program/localization/de_CH/labels.inc
index 8507094..361d9ea 100644
--- a/program/localization/de_CH/labels.inc
+++ b/program/localization/de_CH/labels.inc
@@ -199,6 +199,9 @@
 $labels['pagesize']  = 'Einträge pro Seite';
 $labels['signature'] = 'Signatur';
 $labels['dstactive']  = 'Sommerzeit';
+$labels['htmleditor'] = 'HTML-Nachrichten verfassen';
+$labels['htmlsignature'] = 'HTML-Signatur';
+$labels['previewpane'] = 'Nachrichtenvorschau anzeigen';
 
 $labels['autosavedraft']  = 'Entwurf autom. speichern';
 $labels['everynminutes']  = 'alle $n Minuten';
diff --git a/program/localization/de_CH/messages.inc b/program/localization/de_CH/messages.inc
index f1c7e5b..0e6466e 100644
--- a/program/localization/de_CH/messages.inc
+++ b/program/localization/de_CH/messages.inc
@@ -104,5 +104,10 @@
 
 $messages['folderdeleted'] = 'Ordner erfolgreich gelöscht';
 
+$messages['deletedsuccessfully'] = "Erfolgreich gelöscht";
+
+$messages['converting'] = 'Entferne Formatierungen...';
+
+$messages['messageopenerror'] = 'Die Nachricht konnte nicht vom Server geladen werden';
 
 ?>
\ No newline at end of file
diff --git a/program/localization/de_DE/messages.inc b/program/localization/de_DE/messages.inc
index 8a178ed..34c6ef7 100644
--- a/program/localization/de_DE/messages.inc
+++ b/program/localization/de_DE/messages.inc
@@ -106,4 +106,6 @@
 
 $messages['folderdeleted'] = 'Ordner erfolgreich gelöscht';
 
+$messages['messageopenerror'] = 'Die Nachricht konnte nicht vom Server geladen werden';
+
 ?>
\ No newline at end of file
diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc
index 8b18362..542cca9 100644
--- a/program/localization/en_US/labels.inc
+++ b/program/localization/en_US/labels.inc
@@ -211,6 +211,7 @@
 $labels['dstactive']  = 'Daylight savings';
 $labels['htmleditor'] = 'Compose HTML messages';
 $labels['htmlsignature'] = 'HTML signature';
+$labels['previewpane'] = 'Show preview pane';
 
 $labels['autosavedraft']  = 'Automatically save draft';
 $labels['everynminutes']  = 'every $n minutes';
diff --git a/program/localization/en_US/messages.inc b/program/localization/en_US/messages.inc
index 1a49a8e..f5e0e8b 100644
--- a/program/localization/en_US/messages.inc
+++ b/program/localization/en_US/messages.inc
@@ -108,6 +108,10 @@
 
 $messages['folderdeleted'] = 'Folder successfully deleted';
 
+$messages['deletedsuccessfully'] = "Successfully deleted";
+
 $messages['converting'] = 'Removing formatting from message...';
 
+$messages['messageopenerror'] = 'Could not load message from server';
+
 ?>
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 76bb9b7..d655a33 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -558,6 +558,27 @@
   }
 
 
+// return an HTML iframe for loading mail content
+function rcmail_messagecontent_frame($attrib)
+  {
+  global $OUTPUT, $JS_OBJECT_NAME;
+  
+  if (empty($attrib['id']))
+    $attrib['id'] = 'rcmailcontentwindow';
+
+  // allow the following attributes to be added to the <iframe> tag
+  $attrib_str = create_attrib_string($attrib, array('id', 'class', 'style', 'src', 'width', 'height', 'frameborder'));
+  $framename = $attrib['id'];
+
+  $out = sprintf('<iframe name="%s"%s></iframe>'."\n",
+         $framename,
+         $attrib_str);
+
+  $OUTPUT->add_script("$JS_OBJECT_NAME.set_env('contentframe', '$framename');");
+
+  return $out;
+  }
+
 // return code for search function
 function rcmail_search_form($attrib)
   {
diff --git a/program/steps/mail/move_del.inc b/program/steps/mail/move_del.inc
index 80b2ad8..a7aa5c7 100644
--- a/program/steps/mail/move_del.inc
+++ b/program/steps/mail/move_del.inc
@@ -24,7 +24,7 @@
 // move messages
 if ($_action=='moveto' && $_GET['_uid'] && $_GET['_target_mbox'])
   {
-  $count = sizeof(explode(',', $_GET['_uid']));  
+  $count = sizeof(explode(',', $_GET['_uid']));
   $moved = $IMAP->move_message($_GET['_uid'], $_GET['_target_mbox'], $_GET['_mbox']);
   
   if (!$moved)
@@ -62,8 +62,7 @@
 
 // update message count display
 $pages = ceil($IMAP->messagecount()/$IMAP->page_size);
-$commands = "if (this.message_list) this.message_list.init();\n";
-$commands .= sprintf("this.set_rowcount('%s');\n", rcmail_get_messagecount_text());
+$commands = sprintf("this.set_rowcount('%s');\n", rcmail_get_messagecount_text());
 $commands .= sprintf("this.set_env('pagecount', %d);\n", $pages);
 
 
diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc
index c8e4937..8e6c3cd 100644
--- a/program/steps/mail/show.inc
+++ b/program/steps/mail/show.inc
@@ -30,12 +30,18 @@
   $MESSAGE = array('UID' => get_input_value('_uid', RCUBE_INPUT_GET));
   $MESSAGE['headers'] = $IMAP->get_headers($MESSAGE['UID']);
   $MESSAGE['structure'] = $IMAP->get_structure($MESSAGE['UID']);
-    
+  
   // go back to list if message not found (wrong UID)
   if (!$MESSAGE['headers'] || !$MESSAGE['structure'])
     {
-    $_action = 'list';
-    return;
+    show_message('messageopenerror', 'error');
+    if ($_action=='preview' && template_exists('messagepreview'))
+        parse_template('messagepreview');
+    else
+      {
+      $_action = 'list';
+      return;
+      }
     }
 
   $MESSAGE['subject'] = $IMAP->decode_header($MESSAGE['headers']->subject);
@@ -131,28 +137,6 @@
 
 
 
-// return an HTML iframe for loading mail content
-function rcmail_messagecontent_frame($attrib)
-  {
-  global $COMM_PATH, $OUTPUT, $GET_URL, $JS_OBJECT_NAME;
-  
-  // allow the following attributes to be added to the <iframe> tag
-  $attrib_str = create_attrib_string($attrib);
-  $framename = 'rcmailcontentwindow';
-  
-  $out = sprintf('<iframe src="%s" name="%s"%s>%s</iframe>'."\n",
-         $GET_URL,
-         $framename,
-         $attrib_str,
-         rcube_label('loading'));
-
-
-  $OUTPUT->add_script("$JS_OBJECT_NAME.set_env('contentframe', '$framename');");
-
-  return $out;
-  }
-
-
 function rcmail_remote_objects_msg($attrib)
   {
   global $CONFIG, $OUTPUT, $JS_OBJECT_NAME;
@@ -177,8 +161,10 @@
   }
 
 
-if ($_action=='print')
+if ($_action=='print' && template_exists('printmessage'))
   parse_template('printmessage');
+else if ($_action=='preview' && template_exists('messagepreview'))
+    parse_template('messagepreview');
 else
   parse_template('message');
 ?>
\ No newline at end of file
diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc
index fd98572..70d29db 100644
--- a/program/steps/settings/func.inc
+++ b/program/steps/settings/func.inc
@@ -34,6 +34,8 @@
   {
   global $DB, $CONFIG, $sess_user_lang;
 
+  $no_override = is_array($CONFIG['dont_override']) ? array_flip($CONFIG['dont_override']) : array();
+
   // add some labels to client
   rcube_add_label('nopagesizewarning');
   
@@ -46,116 +48,138 @@
   // return the complete edit form as table
   $out = "$form_start<table" . $attrib_str . ">\n\n";
 
-  $a_show_cols = array(
-	  'language'   => array('type' => 'text'),
-    'pagesize'   => array('type' => 'text'),
-    'timezone'   => array('type' => 'text'),
-    'prettydate' => array('type' => 'text'),
-    'draft_autosave' => array('type' => 'text')
-  );
-                       
   // show language selection
-  $a_lang = rcube_list_languages();
-  asort($a_lang);
+  if (!isset($no_override['language']))
+    {
+    $a_lang = rcube_list_languages();
+    asort($a_lang);
   
-  $field_id = 'rcmfd_lang';
-  $select_lang = new select(array('name' => '_language', 'id' => $field_id));
-  $select_lang->add(array_values($a_lang), array_keys($a_lang));
+    $field_id = 'rcmfd_lang';
+    $select_lang = new select(array('name' => '_language', 'id' => $field_id));
+    $select_lang->add(array_values($a_lang), array_keys($a_lang));
   
-
-  $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
-                  $field_id,
-                  rep_specialchars_output(rcube_label('language')),
-                  $select_lang->show($sess_user_lang));
+    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
+                    $field_id,
+                    rep_specialchars_output(rcube_label('language')),
+                    $select_lang->show($sess_user_lang));
+    }
 
 
   // show page size selection
-  $field_id = 'rcmfd_timezone';
-  $select_timezone = new select(array('name' => '_timezone', 'id' => $field_id));
-  $select_timezone->add('(GMT -11:00) Midway Island, Samoa', '-11');
-  $select_timezone->add('(GMT -10:00) Hawaii', '-10');
-  $select_timezone->add('(GMT -9:00) Alaska', '-9');
-  $select_timezone->add('(GMT -8:00) Pacific Time (US/Canada)', '-8');
-  $select_timezone->add('(GMT -7:00) Mountain Time (US/Canada)', '-7');
-  $select_timezone->add('(GMT -6:00) Central Time (US/Canada), Mexico City', '-6');
-  $select_timezone->add('(GMT -5:00) Eastern Time (US/Canada), Bogota, Lima', '-5');
-  $select_timezone->add('(GMT -4:00) Atlantic Time (Canada), Caracas, La Paz', '-4');
-  $select_timezone->add('(GMT -3:00) Brazil, Buenos Aires, Georgetown', '-3');
-  $select_timezone->add('(GMT -3:30) Nfld Time (Canada), Nfld, S. Labador', '-3.5');
-  $select_timezone->add('(GMT -2:00) Mid-Atlantic', '-2');
-  $select_timezone->add('(GMT -1:00) Azores, Cape Verde Islands', '-1');
-  $select_timezone->add('(GMT) Western Europe, London, Lisbon, Casablanca', '0');
-  $select_timezone->add('(GMT +1:00) Central European Time', '1');
-  $select_timezone->add('(GMT +2:00) EET: Kaliningrad, South Africa', '2');
-  $select_timezone->add('(GMT +3:00) Baghdad, Kuwait, Riyadh, Moscow, Nairobi', '3');
-  $select_timezone->add('(GMT +3:30) Tehran', '3.5');
-  $select_timezone->add('(GMT +4:00) Abu Dhabi, Muscat, Baku, Tbilisi', '4');
-  $select_timezone->add('(GMT +4:30) Kabul', '4.5');
-  $select_timezone->add('(GMT +5:00) Ekaterinburg, Islamabad, Karachi', '5');
-  $select_timezone->add('(GMT +5:30) Chennai, Kolkata, Mumbai, New Delhi', '5.5');
-  $select_timezone->add('(GMT +5:45) Kathmandu', '5.75');
-  $select_timezone->add('(GMT +6:00) Almaty, Dhaka, Colombo', '6');
-  $select_timezone->add('(GMT +7:00) Bangkok, Hanoi, Jakarta', '7');
-  $select_timezone->add('(GMT +8:00) Beijing, Perth, Singapore, Taipei', '8');
-  $select_timezone->add('(GMT +9:00) Tokyo, Seoul, Yakutsk', '9');
-  $select_timezone->add('(GMT +9:30) Adelaide, Darwin', '9.5');
-  $select_timezone->add('(GMT +10:00) EAST/AEST: Guam, Vladivostok', '10');
-  $select_timezone->add('(GMT +11:00) Magadan, Solomon Islands', '11');
-  $select_timezone->add('(GMT +12:00) Auckland, Wellington, Kamchatka', '12');
-  $select_timezone->add('(GMT +13:00) Tonga, Pheonix Islands', '13');
-  $select_timezone->add('(GMT +14:00) Kiribati', '14');
+  if (!isset($no_override['timezone']))
+    {
+    $field_id = 'rcmfd_timezone';
+    $select_timezone = new select(array('name' => '_timezone', 'id' => $field_id));
+    $select_timezone->add('(GMT -11:00) Midway Island, Samoa', '-11');
+    $select_timezone->add('(GMT -10:00) Hawaii', '-10');
+    $select_timezone->add('(GMT -9:00) Alaska', '-9');
+    $select_timezone->add('(GMT -8:00) Pacific Time (US/Canada)', '-8');
+    $select_timezone->add('(GMT -7:00) Mountain Time (US/Canada)', '-7');
+    $select_timezone->add('(GMT -6:00) Central Time (US/Canada), Mexico City', '-6');
+    $select_timezone->add('(GMT -5:00) Eastern Time (US/Canada), Bogota, Lima', '-5');
+    $select_timezone->add('(GMT -4:00) Atlantic Time (Canada), Caracas, La Paz', '-4');
+    $select_timezone->add('(GMT -3:00) Brazil, Buenos Aires, Georgetown', '-3');
+    $select_timezone->add('(GMT -3:30) Nfld Time (Canada), Nfld, S. Labador', '-3.5');
+    $select_timezone->add('(GMT -2:00) Mid-Atlantic', '-2');
+    $select_timezone->add('(GMT -1:00) Azores, Cape Verde Islands', '-1');
+    $select_timezone->add('(GMT) Western Europe, London, Lisbon, Casablanca', '0');
+    $select_timezone->add('(GMT +1:00) Central European Time', '1');
+    $select_timezone->add('(GMT +2:00) EET: Kaliningrad, South Africa', '2');
+    $select_timezone->add('(GMT +3:00) Baghdad, Kuwait, Riyadh, Moscow, Nairobi', '3');
+    $select_timezone->add('(GMT +3:30) Tehran', '3.5');
+    $select_timezone->add('(GMT +4:00) Abu Dhabi, Muscat, Baku, Tbilisi', '4');
+    $select_timezone->add('(GMT +4:30) Kabul', '4.5');
+    $select_timezone->add('(GMT +5:00) Ekaterinburg, Islamabad, Karachi', '5');
+    $select_timezone->add('(GMT +5:30) Chennai, Kolkata, Mumbai, New Delhi', '5.5');
+    $select_timezone->add('(GMT +5:45) Kathmandu', '5.75');
+    $select_timezone->add('(GMT +6:00) Almaty, Dhaka, Colombo', '6');
+    $select_timezone->add('(GMT +7:00) Bangkok, Hanoi, Jakarta', '7');
+    $select_timezone->add('(GMT +8:00) Beijing, Perth, Singapore, Taipei', '8');
+    $select_timezone->add('(GMT +9:00) Tokyo, Seoul, Yakutsk', '9');
+    $select_timezone->add('(GMT +9:30) Adelaide, Darwin', '9.5');
+    $select_timezone->add('(GMT +10:00) EAST/AEST: Guam, Vladivostok', '10');
+    $select_timezone->add('(GMT +11:00) Magadan, Solomon Islands', '11');
+    $select_timezone->add('(GMT +12:00) Auckland, Wellington, Kamchatka', '12');
+    $select_timezone->add('(GMT +13:00) Tonga, Pheonix Islands', '13');
+    $select_timezone->add('(GMT +14:00) Kiribati', '14');
   
   
-  $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
-                  $field_id,
-                  rep_specialchars_output(rcube_label('timezone')),
-                  $select_timezone->show($CONFIG['timezone']));
+    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
+                    $field_id,
+                    rep_specialchars_output(rcube_label('timezone')),
+                    $select_timezone->show($CONFIG['timezone']));
+    }
 
-
-  $field_id = 'rcmfd_dst';
-  $input_dst = new checkbox(array('name' => '_dst_active', 'id' => $field_id, 'value' => 1));
-  $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
-                  $field_id,
-                  rep_specialchars_output(rcube_label('dstactive')),
-                  $input_dst->show($CONFIG['dst_active']));
-
+  // daylight savings
+  if (!isset($no_override['dst_active']))
+    {
+    $field_id = 'rcmfd_dst';
+    $input_dst = new checkbox(array('name' => '_dst_active', 'id' => $field_id, 'value' => 1));
+    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
+                    $field_id,
+                    rep_specialchars_output(rcube_label('dstactive')),
+                    $input_dst->show($CONFIG['dst_active']));
+    }
 
   // show page size selection
-  $field_id = 'rcmfd_pgsize';
-  $input_pagesize = new textfield(array('name' => '_pagesize', 'id' => $field_id, 'size' => 5));
+  if (!isset($no_override['pagesize']))
+    {
+    $field_id = 'rcmfd_pgsize';
+    $input_pagesize = new textfield(array('name' => '_pagesize', 'id' => $field_id, 'size' => 5));
 
-  $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
-                  $field_id,
-                  rep_specialchars_output(rcube_label('pagesize')),
-                  $input_pagesize->show($CONFIG['pagesize']));
-
-  // show checkbox for HTML/plaintext messages
-  $field_id = 'rcmfd_htmlmsg';
-  $input_pagesize = new checkbox(array('name' => '_prefer_html', 'id' => $field_id, 'value' => 1));
-
-  $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
-                  $field_id,
-                  rep_specialchars_output(rcube_label('preferhtml')),
-                  $input_pagesize->show($CONFIG['prefer_html']?1:0));
+    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
+                    $field_id,
+                    rep_specialchars_output(rcube_label('pagesize')),
+                    $input_pagesize->show($CONFIG['pagesize']));
+    }
 
   // MM: Show checkbox for toggling 'pretty dates' 
-  $field_id = 'rcmfd_prettydate';
-  $input_prettydate = new checkbox(array('name' => '_pretty_date', 'id' => $field_id, 'value' => 1));
+  if (!isset($no_override['prettydate']))
+    {
+    $field_id = 'rcmfd_prettydate';
+    $input_prettydate = new checkbox(array('name' => '_pretty_date', 'id' => $field_id, 'value' => 1));
 
-  $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
-                  $field_id,
-                  rep_specialchars_output(rcube_label('prettydate')),
-                  $input_prettydate->show($CONFIG['prettydate']?1:0));
+    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
+                    $field_id,
+                    rep_specialchars_output(rcube_label('prettydate')),
+                    $input_prettydate->show($CONFIG['prettydate']?1:0));
+    }
+
+  // show checkbox for HTML/plaintext messages
+  if (!isset($no_override['prefer_html']))
+    {
+    $field_id = 'rcmfd_htmlmsg';
+    $input_pagesize = new checkbox(array('name' => '_prefer_html', 'id' => $field_id, 'value' => 1));
+
+    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
+                    $field_id,
+                    rep_specialchars_output(rcube_label('preferhtml')),
+                    $input_pagesize->show($CONFIG['prefer_html']?1:0));
+    }
 
   // Show checkbox for HTML Editor
-  $field_id = 'rcmfd_htmleditor';
-  $input_htmleditor = new checkbox(array('name' => '_htmleditor', 'id' => $field_id, 'value' => 1));
-  $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
-                  $field_id,
-                  rep_specialchars_output(rcube_label('htmleditor')),
-                  $input_htmleditor->show($CONFIG['htmleditor']?1:0));
+  if (!isset($no_override['htmleditor']))
+    {
+    $field_id = 'rcmfd_htmleditor';
+    $input_htmleditor = new checkbox(array('name' => '_htmleditor', 'id' => $field_id, 'value' => 1));
+    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
+                    $field_id,
+                    rep_specialchars_output(rcube_label('htmleditor')),
+                    $input_htmleditor->show($CONFIG['htmleditor']?1:0));
+    }
 
-  if (!empty($CONFIG['drafts_mbox']))
+  // show config parameter for preview pane
+  if (!isset($no_override['preview_pane']))
+    {
+    $field_id = 'rcmfd_preview';
+    $input_preview = new checkbox(array('name' => '_preview_pane', 'id' => $field_id, 'value' => 1));
+    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
+                    $field_id,
+                    rep_specialchars_output(rcube_label('previewpane')),
+                    $input_preview->show($CONFIG['preview_pane']?1:0));
+    }
+                  
+  if (!empty($CONFIG['drafts_mbox']) && !isset($no_override['preview_pane']))
     {
     $field_id = 'rcmfd_autosave';
     $select_autosave = new select(array('name' => '_draft_autosave', 'id' => $field_id));
diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc
index a438de0..fd254f9 100644
--- a/program/steps/settings/save_prefs.inc
+++ b/program/steps/settings/save_prefs.inc
@@ -19,21 +19,23 @@
 
 */
 
-$a_user_prefs = $_SESSION['user_prefs'];
-if (!is_array($a_user_prefs))
-  $a_user_prefs = array();
+$a_user_prefs = array(
+  'timezone'     => isset($_POST['_timezone']) ? floatval($_POST['_timezone']) : $CONFIG['timezone'],
+  'dst_active'   => isset($_POST['_dst_active']) ? TRUE : FALSE,
+  'pagesize'     => is_numeric($_POST['_pagesize']) ? intval($_POST['_pagesize']) : $CONFIG['pagesize'],
+  'prettydate'   => isset($_POST['_pretty_date']) ? TRUE : FALSE,
+  'prefer_html'  => isset($_POST['_prefer_html']) ? TRUE : FALSE,
+  'htmleditor'   => isset($_POST['_htmleditor']) ? TRUE : FALSE,
+  'preview_pane' => isset($_POST['_preview_pane']) ? TRUE : FALSE,
+  'draft_autosave' => isset($_POST['_draft_autosave']) ? intval($_POST['_draft_autosave']) : 0
+  );
+
+// don't override these parameters
+foreach ((array)$CONFIG['dont_override'] as $p)
+  $a_user_prefs[$p] = $CONFIG[$p];
 
 
-$a_user_prefs['timezone'] = isset($_POST['_timezone']) ? floatval($_POST['_timezone']) : $CONFIG['timezone'];
-$a_user_prefs['dst_active'] = isset($_POST['_dst_active']) ? TRUE : FALSE;
-$a_user_prefs['pagesize'] = is_numeric($_POST['_pagesize']) ? (int)$_POST['_pagesize'] : $CONFIG['pagesize'];
-$a_user_prefs['prefer_html'] = isset($_POST['_prefer_html']) ? TRUE : FALSE;
-$a_user_prefs['htmleditor'] = isset($_POST['_htmleditor']) ? TRUE : FALSE;
-$a_user_prefs['draft_autosave'] = isset($_POST['_draft_autosave']) ? intval($_POST['_draft_autosave']) : 0;
-
-// MM: Date format toggle (Pretty / Standard)
-$a_user_prefs['prettydate'] = isset($_POST['_pretty_date']) ? TRUE : FALSE;
-
+// switch UI language
 if (isset($_POST['_language']))
   {
   $sess_user_lang = $_SESSION['user_lang'] = get_input_value('_language', RCUBE_INPUT_POST);
diff --git a/skins/default/mail.css b/skins/default/mail.css
index d94d6a1..5bf05cb 100644
--- a/skins/default/mail.css
+++ b/skins/default/mail.css
@@ -120,6 +120,33 @@
   height: expression((parseInt(document.documentElement.clientHeight)-125)+'px');
 }
 
+#mailpreviewframe
+{
+  position: absolute;
+  top: 300px;
+  left: 200px;
+  right: 40px;
+  bottom: 40px;
+  border: 1px solid #999999;
+  background-color: #F9F9F9;
+  /* css hack for IE */
+  width: expression((parseInt(document.documentElement.clientWidth)-240)+'px');
+  height: expression((parseInt(document.documentElement.clientHeight)-340)+'px');
+}
+
+#messagecontframe
+{
+  width: 100%;
+  height: 100%;
+  border: 0;
+}
+
+/*\*/
+html>body*#messagecontframe
+{
+  height: 40%;
+}
+/**/
 
 #messagepartframe
 {
@@ -385,8 +412,7 @@
 
 #messagelist tbody tr td
 {
-  height: 16px !important;
-  height: 20px;
+  height: 16px;
   padding: 2px;
   padding-right: 4px;
   font-size: 11px;
@@ -459,12 +485,6 @@
   font-weight: bold;
   color: #FFFFFF;
   background-color: #CC3333;
-}
-
-#messagelist tr.focused td
-{
-  border-bottom: thin dotted;
-  border-top: thin dotted;
 }
 
 #messagelist tr.unfocused td
@@ -575,7 +595,7 @@
 #messageframe
 {
   position: absolute;
-  top: 85px;
+  top: 95px;
   left: 200px;
   right: 40px;
   bottom: 40px;
@@ -588,6 +608,12 @@
   height: expression((parseInt(document.documentElement.clientHeight)-125)+'px');
 }
 
+div.messageheaderbox
+{
+  margin: 6px 8px 0px 8px;
+  border: 1px solid #ccc;
+}
+
 table.headers-table
 {
   width: 100%;
diff --git a/skins/default/settings.css b/skins/default/settings.css
index c172576..ba5b65b 100644
--- a/skins/default/settings.css
+++ b/skins/default/settings.css
@@ -49,7 +49,7 @@
   position: absolute;
   top: 95px;
   left: 20px;
-  width: 550px;
+  width: 600px;
   border: 1px solid #999999;  
 }
 
@@ -78,7 +78,7 @@
 
 #identities-table
 {
-  width: 500px;
+  width: 600px;
   border: 1px solid #999999;
   background-color: #F9F9F9;
 }
diff --git a/skins/default/templates/mail.html b/skins/default/templates/mail.html
index 6d95d60..7e83057 100644
--- a/skins/default/templates/mail.html
+++ b/skins/default/templates/mail.html
@@ -54,6 +54,19 @@
   attachmentIcon="/images/icons/attachment.png" />
 </div>
 
+<roundcube:if condition="config:preview_pane == true" />
+<div id="mailpreviewframe">
+<roundcube:object name="messagecontentframe" id="messagecontframe" width="100%" height="100%" frameborder="0" src="/watermark.html" />
+</div>
+
+<style type="text/css">
+#mailcontframe {
+  bottom: auto;
+  height: 210px;
+}
+</style>
+<roundcube:endif />
+
 <div id="listcontrols">
 <roundcube:label name="select" />:&nbsp;
 <roundcube:button command="select-all" label="all" classAct="active" />&nbsp;
diff --git a/skins/default/templates/messagepreview.html b/skins/default/templates/messagepreview.html
new file mode 100644
index 0000000..e08f2c7
--- /dev/null
+++ b/skins/default/templates/messagepreview.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title><roundcube:object name="pagetitle" /></title>
+<link rel="stylesheet" type="text/css" href="/common.css" />
+<link rel="stylesheet" type="text/css" href="/mail.css" />
+</head>
+<body class="iframe">
+
+<div class="messageheaderbox">
+<roundcube:object name="messageHeaders" class="headers-table" cellspacing="0" cellpadding="2" addicon="/images/icons/plus.gif" summary="Message headers" />
+<roundcube:object name="messageAttachments" id="attachment-list" />
+</div>
+
+<roundcube:object name="blockedObjects" id="remote-objects-message" />
+<roundcube:object name="messageBody" id="messagebody" />
+
+</body>
+</html>

--
Gitblit v1.9.1