Page MenuHomePhorge

No OneTemporary

diff --git a/program/include/html.php b/program/include/html.php
index 8d3144d93..50689f2e7 100644
--- a/program/include/html.php
+++ b/program/include/html.php
@@ -1,647 +1,647 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/include/html.php |
| |
| This file is part of the RoundCube Webmail client |
| Copyright (C) 2005-2008, RoundCube Dev, - Switzerland |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Helper class to create valid XHTML code |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id: $
*/
/**
* Class for HTML code creation
*
* @package HTML
*/
class html
{
protected $tagname;
protected $attrib = array();
protected $allowed = array();
protected $content;
public static $common_attrib = array('id','class','style','title','align');
public static $containers = array('div','span','p','h1','h2','h3','form','textarea','table','tr','th','td','style');
public static $lc_tags = true;
/**
* Constructor
*
* @param array Hash array with tag attributes
*/
public function __construct($attrib = array())
{
if (is_array($attrib)) {
$this->attrib = $attrib;
}
}
/**
* Return the tag code
*
* @return string The finally composed HTML tag
*/
public function show()
{
return self::tag($this->tagname, $this->attrib, $this->content, array_merge(self::$common_attrib, $this->allowed));
}
/****** STATIC METHODS *******/
/**
* Generic method to create a HTML tag
*
* @param string Tag name
* @param array Tag attributes as key/value pairs
* @param string Optinal Tag content (creates a container tag)
* @param array List with allowed attributes, omit to allow all
* @return string The XHTML tag
*/
public static function tag($tagname, $attrib = array(), $content = null, $allowed_attrib = null)
{
$inline_tags = array('a','span','img');
$suffix = $attrib['nl'] || ($content && $attrib['nl'] !== false && !in_array($tagname, $inline_tags)) ? "\n" : '';
$tagname = self::$lc_tags ? strtolower($tagname) : $tagname;
if ($content || in_array($tagname, self::$containers)) {
$templ = $attrib['noclose'] ? "<%s%s>%s" : "<%s%s>%s</%s>%s";
unset($attrib['noclose']);
return sprintf($templ, $tagname, self::attrib_string($attrib, $allowed_attrib), $content, $tagname, $suffix);
}
else {
return sprintf("<%s%s />%s", $tagname, self::attrib_string($attrib, $allowed_attrib), $suffix);
}
}
/**
* Derrived method for <div> containers
*
* @param mixed Hash array with tag attributes or string with class name
* @param string Div content
* @return string HTML code
* @see html::tag()
*/
public static function div($attr = null, $cont = null)
{
if (is_string($attr)) {
$attr = array('class' => $attr);
}
return self::tag('div', $attr, $cont, array_merge(self::$common_attrib, array('onclick')));
}
/**
* Derrived method for <p> blocks
*
* @param mixed Hash array with tag attributes or string with class name
* @param string Paragraph content
* @return string HTML code
* @see html::tag()
*/
public static function p($attr = null, $cont = null)
{
if (is_string($attr)) {
$attr = array('class' => $attr);
}
return self::tag('p', $attr, $cont, self::$common_attrib);
}
/**
* Derrived method to create <img />
*
* @param mixed Hash array with tag attributes or string with image source (src)
* @return string HTML code
* @see html::tag()
*/
public static function img($attr = null)
{
if (is_string($attr)) {
$attr = array('src' => $attr);
}
return self::tag('img', $attr + array('alt' => ''), null, array_merge(self::$common_attrib, array('src','alt','width','height','border','usemap')));
}
/**
* Derrived method for link tags
*
* @param mixed Hash array with tag attributes or string with link location (href)
* @param string Link content
* @return string HTML code
* @see html::tag()
*/
public static function a($attr, $cont)
{
if (is_string($attr)) {
$attr = array('href' => $attr);
}
return self::tag('a', $attr, $cont, array_merge(self::$common_attrib, array('href','target','name','onclick','onmouseover','onmouseout','onmousedown','onmouseup')));
}
/**
* Derrived method for inline span tags
*
* @param mixed Hash array with tag attributes or string with class name
* @param string Tag content
* @return string HTML code
* @see html::tag()
*/
public static function span($attr, $cont)
{
if (is_string($attr)) {
$attr = array('class' => $attr);
}
return self::tag('span', $attr, $cont, self::$common_attrib);
}
/**
* Derrived method for form element labels
*
* @param mixed Hash array with tag attributes or string with 'for' attrib
* @param string Tag content
* @return string HTML code
* @see html::tag()
*/
public static function label($attr, $cont)
{
if (is_string($attr)) {
$attr = array('for' => $attr);
}
return self::tag('label', $attr, $cont, array_merge(self::$common_attrib, array('for')));
}
/**
* Derrived method for line breaks
*
* @return string HTML code
* @see html::tag()
*/
public static function br()
{
return self::tag('br');
}
/**
* Create string with attributes
*
* @param array Associative arry with tag attributes
* @param array List of allowed attributes
* @return string Valid attribute string
*/
public static function attrib_string($attrib = array(), $allowed = null)
{
if (empty($attrib)) {
return '';
}
$allowed_f = array_flip((array)$allowed);
$attrib_arr = array();
foreach ($attrib as $key => $value) {
// skip size if not numeric
if (($key=='size' && !is_numeric($value))) {
continue;
}
// ignore "internal" or not allowed attributes
if ($key == 'nl' || ($allowed && !isset($allowed_f[$key])) || $value === null) {
continue;
}
// skip empty eventhandlers
if (preg_match('/^on[a-z]+/', $key) && !$value) {
continue;
}
// attributes with no value
if (in_array($key, array('checked', 'multiple', 'disabled', 'selected'))) {
if ($value) {
$attrib_arr[] = sprintf('%s="%s"', $key, $key);
}
}
else if ($key=='value') {
$attrib_arr[] = sprintf('%s="%s"', $key, Q($value, 'strict', false));
}
else {
$attrib_arr[] = sprintf('%s="%s"', $key, Q($value));
}
}
return count($attrib_arr) ? ' '.implode(' ', $attrib_arr) : '';
}
}
/**
* Class to create an HTML input field
*
* @package HTML
*/
class html_inputfield extends html
{
protected $tagname = 'input';
protected $type = 'text';
- protected $allowed = array('type','name','value','size','tabindex','autocomplete','checked','onchange','onclick','disabled','readonly','spellcheck');
+ protected $allowed = array('type','name','value','size','tabindex','autocomplete','checked','onchange','onclick','disabled','readonly','spellcheck','results');
public function __construct($attrib = array())
{
if (is_array($attrib)) {
$this->attrib = $attrib;
}
if ($attrib['type']) {
$this->type = $attrib['type'];
}
if ($attrib['newline']) {
$this->newline = true;
}
}
/**
* Compose input tag
*
* @param string Field value
* @param array Additional attributes to override
* @return string HTML output
*/
public function show($value = null, $attrib = null)
{
// overwrite object attributes
if (is_array($attrib)) {
$this->attrib = array_merge($this->attrib, $attrib);
}
// set value attribute
if ($value !== null) {
$this->attrib['value'] = $value;
}
// set type
$this->attrib['type'] = $this->type;
return parent::show();
}
}
/**
* Class to create an HTML password field
*
* @package HTML
*/
class html_passwordfield extends html_inputfield
{
protected $type = 'password';
}
/**
* Class to create an hidden HTML input field
*
* @package HTML
*/
class html_hiddenfield extends html_inputfield
{
protected $type = 'hidden';
protected $fields_arr = array();
protected $newline = true;
/**
* Constructor
*
* @param array Named tag attributes
*/
public function __construct($attrib = null)
{
if (is_array($attrib)) {
$this->add($attrib);
}
}
/**
* Add a hidden field to this instance
*
* @param array Named tag attributes
*/
public function add($attrib)
{
$this->fields_arr[] = $attrib;
}
/**
* Create HTML code for the hidden fields
*
* @return string Final HTML code
*/
public function show()
{
$out = '';
foreach ($this->fields_arr as $attrib) {
$out .= self::tag($this->tagname, array('type' => $this->type) + $attrib);
}
return $out;
}
}
/**
* Class to create HTML radio buttons
*
* @package HTML
*/
class html_radiobutton extends html_inputfield
{
protected $type = 'radio';
/**
* Get HTML code for this object
*
* @param string Value of the checked field
* @param array Additional attributes to override
* @return string HTML output
*/
public function show($value = '', $attrib = null)
{
// overwrite object attributes
if (is_array($attrib)) {
$this->attrib = array_merge($this->attrib, $attrib);
}
// set value attribute
$this->attrib['checked'] = ((string)$value == (string)$this->attrib['value']);
return parent::show();
}
}
/**
* Class to create HTML checkboxes
*
* @package HTML
*/
class html_checkbox extends html_inputfield
{
protected $type = 'checkbox';
/**
* Get HTML code for this object
*
* @param string Value of the checked field
* @param array Additional attributes to override
* @return string HTML output
*/
public function show($value = '', $attrib = null)
{
// overwrite object attributes
if (is_array($attrib)) {
$this->attrib = array_merge($this->attrib, $attrib);
}
// set value attribute
$this->attrib['checked'] = ((string)$value == (string)$this->attrib['value']);
return parent::show();
}
}
/**
* Class to create an HTML textarea
*
* @package HTML
*/
class html_textarea extends html
{
protected $tagname = 'textarea';
protected $allowed = array('name','rows','cols','wrap','tabindex','onchange','disabled','readonly','spellcheck');
/**
* Get HTML code for this object
*
* @param string Textbox value
* @param array Additional attributes to override
* @return string HTML output
*/
public function show($value = '', $attrib = null)
{
// overwrite object attributes
if (is_array($attrib)) {
$this->attrib = array_merge($this->attrib, $attrib);
}
// take value attribute as content
if (empty($value) && !empty($this->attrib['value'])) {
$value = $this->attrib['value'];
}
// make shure we don't print the value attribute
if (isset($this->attrib['value'])) {
unset($this->attrib['value']);
}
if (!empty($value) && !ereg('mce_editor', $this->attrib['class'])) {
$value = Q($value, 'strict', false);
}
return self::tag($this->tagname, $this->attrib, $value, array_merge(self::$common_attrib, $this->allowed));
}
}
/**
* Builder for HTML drop-down menus
* Syntax:<pre>
* // create instance. arguments are used to set attributes of select-tag
* $select = new html_select(array('name' => 'fieldname'));
*
* // add one option
* $select->add('Switzerland', 'CH');
*
* // add multiple options
* $select->add(array('Switzerland','Germany'), array('CH','DE'));
*
* // generate pulldown with selection 'Switzerland' and return html-code
* // as second argument the same attributes available to instanciate can be used
* print $select->show('CH');
* </pre>
*
* @package HTML
*/
class html_select extends html
{
protected $tagname = 'select';
protected $options = array();
protected $allowed = array('name','size','tabindex','autocomplete','multiple','onchange','disabled');
/**
* Add a new option to this drop-down
*
* @param mixed Option name or array with option names
* @param mixed Option value or array with option values
*/
public function add($names, $values = null)
{
if (is_array($names)) {
foreach ($names as $i => $text) {
$this->options[] = array('text' => $text, 'value' => $values[$i]);
}
}
else {
$this->options[] = array('text' => $names, 'value' => $values);
}
}
/**
* Get HTML code for this object
*
* @param string Value of the selection option
* @param array Additional attributes to override
* @return string HTML output
*/
public function show($select = array(), $attrib = null)
{
// overwrite object attributes
if (is_array($attrib)) {
$this->attrib = array_merge($this->attrib, $attrib);
}
$this->content = "\n";
$select = (array)$select;
foreach ($this->options as $option) {
$attr = array(
'value' => $option['value'],
'selected' => (in_array($option['value'], $select, true) ||
in_array($option['text'], $select, true)) ? 1 : null);
$this->content .= self::tag('option', $attr, Q($option['text']));
}
return parent::show();
}
}
/**
* Class to build an HTML table
*
* @package HTML
*/
class html_table extends html
{
protected $tagname = 'table';
protected $allowed = array('id','class','style','width','summary','cellpadding','cellspacing','border');
private $header = array();
private $rows = array();
private $rowindex = 0;
private $colindex = 0;
public function __construct($attrib = array())
{
$this->attrib = array_merge($attrib, array('summary' => '', 'border' => 0));
}
/**
* Add a table cell
*
* @param array Cell attributes
* @param string Cell content
*/
public function add($attr, $cont)
{
if (is_string($attr)) {
$attr = array('class' => $attr);
}
$cell = new stdClass;
$cell->attrib = $attr;
$cell->content = $cont;
$this->rows[$this->rowindex]->cells[$this->colindex] = $cell;
$this->colindex++;
if ($this->attrib['cols'] && $this->colindex == $this->attrib['cols']) {
$this->add_row();
}
}
/**
* Add a table header cell
*
* @param array Cell attributes
* @param string Cell content
*/
public function add_header($attr, $cont)
{
if (is_string($attr))
$attr = array('class' => $attr);
$cell = new stdClass;
$cell->attrib = $attr;
$cell->content = $cont;
$this->header[] = $cell;
}
/**
* Jump to next row
*
* @param array Row attributes
*/
public function add_row($attr = array())
{
$this->rowindex++;
$this->colindex = 0;
$this->rows[$this->rowindex] = new stdClass;
$this->rows[$this->rowindex]->attrib = $attr;
$this->rows[$this->rowindex]->cells = array();
}
/**
* Build HTML output of the table data
*
* @param array Table attributes
* @return string The final table HTML code
*/
public function show($attrib = null)
{
if (is_array($attrib))
$this->attrib = array_merge($this->attrib, $attrib);
$thead = $tbody = "";
// include <thead>
if (!empty($this->header)) {
$rowcontent = '';
foreach ($this->header as $c => $col) {
$rowcontent .= self::tag('td', $col->attrib, $col->content);
}
$thead = self::tag('thead', null, self::tag('tr', null, $rowcontent));
}
foreach ($this->rows as $r => $row) {
$rowcontent = '';
foreach ($row->cells as $c => $col) {
$rowcontent .= self::tag('td', $col->attrib, $col->content);
}
if ($r < $this->rowindex || count($row->cells)) {
$tbody .= self::tag('tr', $row->attrib, $rowcontent);
}
}
if ($this->attrib['rowsonly']) {
return $tbody;
}
// add <tbody>
$this->content = $thead . self::tag('tbody', null, $tbody);
unset($this->attrib['cols'], $this->attrib['rowsonly']);
return parent::show();
}
}
?>
diff --git a/program/include/rcube_browser.php b/program/include/rcube_browser.php
index 0d4766417..162844f32 100644
--- a/program/include/rcube_browser.php
+++ b/program/include/rcube_browser.php
@@ -1,75 +1,76 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/include/rcube_browser.php |
| |
| This file is part of the RoundCube Webmail client |
| Copyright (C) 2007-2008, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Class representing the client browser's properties |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id: rcube_browser.php 328 2006-08-30 17:41:21Z thomasb $
*/
/**
* rcube_browser
*
* Provide details about the client's browser based on the User-Agent header
*
* @package Core
*/
class rcube_browser
{
function __construct()
{
$HTTP_USER_AGENT = $_SERVER['HTTP_USER_AGENT'];
$this->ver = 0;
$this->win = stristr($HTTP_USER_AGENT, 'win');
$this->mac = stristr($HTTP_USER_AGENT, 'mac');
$this->linux = stristr($HTTP_USER_AGENT, 'linux');
$this->unix = stristr($HTTP_USER_AGENT, 'unix');
$this->opera = stristr($HTTP_USER_AGENT, 'opera');
$this->ns4 = stristr($HTTP_USER_AGENT, 'mozilla/4') && !stristr($HTTP_USER_AGENT, 'msie');
$this->ns = ($this->ns4 || stristr($HTTP_USER_AGENT, 'netscape'));
$this->ie = stristr($HTTP_USER_AGENT, 'compatible; msie') && !$this->opera;
$this->mz = stristr($HTTP_USER_AGENT, 'mozilla/5');
- $this->safari = stristr($HTTP_USER_AGENT, 'safari');
+ $this->khtml = stristr($HTTP_USER_AGENT, 'khtml');
+ $this->safari = ($this->khtml || stristr($HTTP_USER_AGENT, 'safari'));
if ($this->ns) {
$test = eregi("mozilla\/([0-9\.]+)", $HTTP_USER_AGENT, $regs);
$this->ver = $test ? (float)$regs[1] : 0;
}
if ($this->mz) {
$test = ereg("rv:([0-9\.]+)", $HTTP_USER_AGENT, $regs);
$this->ver = $test ? (float)$regs[1] : 0;
}
if($this->ie) {
$test = eregi("msie ([0-9\.]+)", $HTTP_USER_AGENT, $regs);
$this->ver = $test ? (float)$regs[1] : 0;
}
if ($this->opera) {
$test = eregi("opera ([0-9\.]+)", $HTTP_USER_AGENT, $regs);
$this->ver = $test ? (float)$regs[1] : 0;
}
if (eregi(" ([a-z]{2})-([a-z]{2})", $HTTP_USER_AGENT, $regs))
$this->lang = $regs[1];
else
$this->lang = 'en';
$this->dom = ($this->mz || $this->safari || ($this->ie && $this->ver>=5) || ($this->opera && $this->ver>=7));
$this->pngalpha = $this->mz || $this->safari || ($this->ie && $this->ver>=5.5) ||
($this->ie && $this->ver>=5 && $this->mac) || ($this->opera && $this->ver>=7) ? true : false;
}
}
diff --git a/program/include/rcube_template.php b/program/include/rcube_template.php
index 61e4975eb..2108ed7ee 100755
--- a/program/include/rcube_template.php
+++ b/program/include/rcube_template.php
@@ -1,1099 +1,1102 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/include/rcube_template.php |
| |
| This file is part of the RoundCube Webmail client |
| Copyright (C) 2006-2008, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Class to handle HTML page output using a skin template. |
| Extends rcube_html_page class from rcube_shared.inc |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
/**
* Class to create HTML page output using a skin template
*
* @package View
* @todo Documentation
* @uses rcube_html_page
*/
class rcube_template extends rcube_html_page
{
var $app;
var $config;
var $framed = false;
var $pagetitle = '';
var $env = array();
var $js_env = array();
var $js_commands = array();
var $object_handlers = array();
public $type = 'html';
public $ajax_call = false;
/**
* Constructor
*
* @todo Use jQuery's $(document).ready() here.
* @todo Replace $this->config with the real rcube_config object
*/
public function __construct($task, $framed = false)
{
parent::__construct();
$this->app = rcmail::get_instance();
$this->config = $this->app->config->all();
+ $this->browser = new rcube_browser();
//$this->framed = $framed;
$this->set_env('task', $task);
// load the correct skin (in case user-defined)
$this->set_skin($this->config['skin']);
// add common javascripts
$javascript = 'var '.JS_OBJECT_NAME.' = new rcube_webmail();';
// don't wait for page onload. Call init at the bottom of the page (delayed)
$javascript_foot = "if (window.call_init)\n call_init('".JS_OBJECT_NAME."');";
$this->add_script($javascript, 'head_top');
$this->add_script($javascript_foot, 'foot');
$this->scripts_path = 'program/js/';
$this->include_script('common.js');
$this->include_script('app.js');
// register common UI objects
$this->add_handlers(array(
'loginform' => array($this, 'login_form'),
'username' => array($this, 'current_username'),
'message' => array($this, 'message_container'),
'charsetselector' => array($this, 'charset_selector'),
));
}
/**
* Set environment variable
*
* @param string Property name
* @param mixed Property value
* @param boolean True if this property should be added to client environment
*/
public function set_env($name, $value, $addtojs = true)
{
$this->env[$name] = $value;
if ($addtojs || isset($this->js_env[$name])) {
$this->js_env[$name] = $value;
}
}
/**
* Set page title variable
*/
public function set_pagetitle($title)
{
$this->pagetitle = $title;
}
/**
* Getter for the current page title
*
* @return string The page title
*/
public function get_pagetitle()
{
if (!empty($this->pagetitle)) {
$title = $this->pagetitle;
}
else if ($this->env['task'] == 'login') {
$title = rcube_label(array('name' => 'welcome', 'vars' => array('product' => $this->config['product_name'])));
}
else {
$title = ucfirst($this->env['task']);
}
return $title;
}
/**
* Set skin
*/
public function set_skin($skin)
{
if (!empty($skin) && is_dir('skins/'.$skin) && is_readable('skins/'.$skin))
$skin_path = 'skins/'.$skin;
else
$skin_path = $this->config['skin_path'] ? $this->config['skin_path'] : 'skins/default';
$this->app->config->set('skin_path', $skin_path);
$this->config['skin_path'] = $skin_path;
}
/**
* Check if a specific template exists
*
* @param string Template name
* @return boolean True if template exists
*/
public function template_exists($name)
{
$filename = $this->config['skin_path'] . '/templates/' . $name . '.html';
return (is_file($filename) && is_readable($filename));
}
/**
* Register a template object handler
*
* @param string Object name
* @param string Function name to call
* @return void
*/
public function add_handler($obj, $func)
{
$this->object_handlers[$obj] = $func;
}
/**
* Register a list of template object handlers
*
* @param array Hash array with object=>handler pairs
* @return void
*/
public function add_handlers($arr)
{
$this->object_handlers = array_merge($this->object_handlers, $arr);
}
/**
* Register a GUI object to the client script
*
* @param string Object name
* @param string Object ID
* @return void
*/
public function add_gui_object($obj, $id)
{
$this->add_script(JS_OBJECT_NAME.".gui_object('$obj', '$id');");
}
/**
* Call a client method
*
* @param string Method to call
* @param ... Additional arguments
*/
public function command()
{
$this->js_commands[] = func_get_args();
}
/**
* Add a localized label to the client environment
*/
public function add_label()
{
$arg_list = func_get_args();
foreach ($arg_list as $i => $name) {
$this->command('add_label', $name, rcube_label($name));
}
}
/**
* Invoke display_message command
*
* @param string Message to display
* @param string Message type [notice|confirm|error]
* @param array Key-value pairs to be replaced in localized text
* @uses self::command()
*/
public function show_message($message, $type='notice', $vars=NULL)
{
$this->command(
'display_message',
rcube_label(array('name' => $message, 'vars' => $vars)),
$type);
}
/**
* Delete all stored env variables and commands
*
* @return void
* @uses rcube_html::reset()
* @uses self::$env
* @uses self::$js_env
* @uses self::$js_commands
* @uses self::$object_handlers
*/
public function reset()
{
$this->env = array();
$this->js_env = array();
$this->js_commands = array();
$this->object_handlers = array();
parent::reset();
}
/**
* Redirect to a certain url
*
* @param mixed Either a string with the action or url parameters as key-value pairs
* @see rcmail::url()
*/
public function redirect($p = array())
{
$location = $this->app->url($p);
header('Location: ' . $location);
exit;
}
/**
* Send the request output to the client.
* This will either parse a skin tempalte or send an AJAX response
*
* @param string Template name
* @param boolean True if script should terminate (default)
*/
public function send($templ = null, $exit = true)
{
if ($templ != 'iframe') {
$this->parse($templ, false);
}
else {
$this->framed = $templ == 'iframe' ? true : $this->framed;
$this->write();
}
if ($exit) {
exit;
}
}
/**
* Process template and write to stdOut
*
* @param string HTML template
* @see rcube_html_page::write()
* @override
*/
public function write($template = '')
{
// unlock interface after iframe load
if ($this->framed) {
array_unshift($this->js_commands, array('set_busy', false));
}
// write all env variables to client
$js = $this->framed ? "if(window.parent) {\n" : '';
$js .= $this->get_js_commands() . ($this->framed ? ' }' : '');
$this->add_script($js, 'head_top');
// call super method
parent::write($template, $this->config['skin_path']);
}
/**
* Parse a specific skin template and deliver to stdout
*
* Either returns nothing, or exists hard (exit();)
*
* @param string Template name
* @param boolean Exit script
* @return void
* @link http://php.net/manual/en/function.exit.php
*/
private function parse($name = 'main', $exit = true)
{
$skin_path = $this->config['skin_path'];
$path = "$skin_path/templates/$name.html";
// read template file
if (($templ = @file_get_contents($path)) === false) {
raise_error(array(
'code' => 501,
'type' => 'php',
'line' => __LINE__,
'file' => __FILE__,
'message' => 'Error loading template for '.$name
), true, true);
return false;
}
// parse for specialtags
$output = $this->parse_conditions($templ);
$output = $this->parse_xml($output);
// add debug console
if ($this->config['debug_level'] & 8) {
$this->add_footer('<div style="position:absolute;top:5px;left:5px;width:405px;padding:2px;background:white;opacity:0.8;filter:alpha(opacity=80);z-index:9000">
<a href="#toggle" onclick="con=document.getElementById(\'dbgconsole\');con.style.display=(con.style.display==\'none\'?\'block\':\'none\');return false">console</a>
<form action="/" name="debugform" style="display:inline"><textarea name="console" id="dbgconsole" rows="20" cols="40" wrap="off" style="display:none;width:400px;border:none;font-size:x-small"></textarea></form></div>'
);
}
$output = $this->parse_with_globals($output);
$this->write(trim($output), $skin_path);
if ($exit) {
exit;
}
}
/**
* Return executable javascript code for all registered commands
*
* @return string $out
*/
private function get_js_commands()
{
$out = '';
if (!$this->framed && !empty($this->js_env)) {
$out .= JS_OBJECT_NAME . '.set_env('.json_serialize($this->js_env).");\n";
}
foreach ($this->js_commands as $i => $args) {
$method = array_shift($args);
foreach ($args as $i => $arg) {
$args[$i] = json_serialize($arg);
}
$parent = $this->framed || preg_match('/^parent\./', $method);
$out .= sprintf(
"%s.%s(%s);\n",
($parent ? 'parent.' : '') . JS_OBJECT_NAME,
preg_replace('/^parent\./', '', $method),
implode(',', $args)
);
}
return $out;
}
/**
* Make URLs starting with a slash point to skin directory
*
* @param string Input string
* @return string
*/
public function abs_url($str)
{
return preg_replace('/^\//', $this->config['skin_path'].'/', $str);
}
/***** Template parsing methods *****/
/**
* Replace all strings ($varname)
* with the content of the according global variable.
*/
private function parse_with_globals($input)
{
$GLOBALS['__comm_path'] = Q($this->app->comm_path);
return preg_replace('/\$(__[a-z0-9_\-]+)/e', '$GLOBALS["\\1"]', $input);
}
/**
* Public wrapper to dipp into template parsing.
*
* @param string $input
* @return string
* @uses rcube_template::parse_xml()
* @since 0.1-rc1
*/
public function just_parse($input)
{
return $this->parse_xml($input);
}
/**
* Parse for conditional tags
*
* @param string $input
* @return string
*/
private function parse_conditions($input)
{
$matches = preg_split('/<roundcube:(if|elseif|else|endif)\s+([^>]+)>/is', $input, 2, PREG_SPLIT_DELIM_CAPTURE);
if ($matches && count($matches) == 4) {
if (preg_match('/^(else|endif)$/i', $matches[1])) {
return $matches[0] . $this->parse_conditions($matches[3]);
}
$attrib = parse_attrib_string($matches[2]);
if (isset($attrib['condition'])) {
$condmet = $this->check_condition($attrib['condition']);
$submatches = preg_split('/<roundcube:(elseif|else|endif)\s+([^>]+)>/is', $matches[3], 2, PREG_SPLIT_DELIM_CAPTURE);
if ($condmet) {
$result = $submatches[0];
$result.= ($submatches[1] != 'endif' ? preg_replace('/.*<roundcube:endif\s+[^>]+>/Uis', '', $submatches[3], 1) : $submatches[3]);
}
else {
$result = "<roundcube:$submatches[1] $submatches[2]>" . $submatches[3];
}
return $matches[0] . $this->parse_conditions($result);
}
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
*
* @todo Get rid off eval() once I understand what this does.
* @todo Extend this to allow real conditions, not just "set"
* @param string Condition statement
* @return boolean True if condition is met, False if not
*/
private function check_condition($condition)
{
return eval("return (".$this->parse_expression($condition).");");
}
/**
* Parses expression and replaces variables
*
* @param string Expression statement
* @return string Expression statement
*/
private function parse_expression($expression)
{
return preg_replace(
array(
'/session:([a-z0-9_]+)/i',
'/config:([a-z0-9_]+)(:([a-z0-9_]+))?/i',
'/env:([a-z0-9_]+)/i',
'/request:([a-z0-9_]+)/i',
'/cookie:([a-z0-9_]+)/i'
),
array(
"\$_SESSION['\\1']",
"\$this->app->config->get('\\1',get_boolean('\\3'))",
"\$this->env['\\1']",
"get_input_value('\\1', RCUBE_INPUT_GPC)",
"\$_COOKIE['\\1']"
),
$expression);
}
/**
* Search for special tags in input and replace them
* with the appropriate content
*
* @param string Input string to parse
* @return string Altered input string
* @todo Use DOM-parser to traverse template HTML
* @todo Maybe a cache.
*/
private function parse_xml($input)
{
return preg_replace_callback('/<roundcube:([-_a-z]+)\s+([^>]+)>/Ui', array($this, 'xml_command_callback'), $input);
}
/**
* This is a callback function for preg_replace_callback (see #1485286)
* It's only purpose is to reconfigure parameters for xml_command, so that the signature isn't disturbed
*/
private function xml_command_callback($matches)
{
$str_attrib = isset($matches[2]) ? $matches[2] : '';
$add_attrib = isset($matches[3]) ? $matches[3] : array();
$command = $matches[1];
//matches[0] is the entire matched portion of the string
return $this->xml_command($command, $str_attrib, $add_attrib);
}
/**
* Convert a xml command tag into real content
*
* @param string Tag command: object,button,label, etc.
* @param string Attribute string
* @return string Tag/Object content
*/
private function xml_command($command, $str_attrib, $add_attrib = array())
{
$command = strtolower($command);
$attrib = parse_attrib_string($str_attrib) + $add_attrib;
// empty output if required condition is not met
if (!empty($attrib['condition']) && !$this->check_condition($attrib['condition'])) {
return '';
}
// execute command
switch ($command) {
// return a button
case 'button':
if ($attrib['name'] || $attrib['command']) {
return $this->button($attrib);
}
break;
// show a label
case 'label':
if ($attrib['name'] || $attrib['command']) {
return Q(rcube_label($attrib + array('vars' => array('product' => $this->config['product_name']))));
}
break;
// include a file
case 'include':
$path = realpath($this->config['skin_path'].$attrib['file']);
if (is_readable($path)) {
if ($this->config['skin_include_php']) {
$incl = $this->include_php($path);
}
else {
$incl = file_get_contents($path);
}
return $this->parse_xml($incl);
}
break;
case 'plugin.include':
//rcube::tfk_debug(var_export($this->config['skin_path'], true));
$path = realpath($this->config['skin_path'].$attrib['file']);
if (!$path) {
//rcube::tfk_debug("Does not exist:");
//rcube::tfk_debug($this->config['skin_path']);
//rcube::tfk_debug($attrib['file']);
//rcube::tfk_debug($path);
}
$incl = file_get_contents($path);
if ($incl) {
return $this->parse_xml($incl);
}
break;
// return code for a specific application object
case 'object':
$object = strtolower($attrib['name']);
// we are calling a class/method
if (($handler = $this->object_handlers[$object]) && is_array($handler)) {
if ((is_object($handler[0]) && method_exists($handler[0], $handler[1])) ||
(is_string($handler[0]) && class_exists($handler[0])))
return call_user_func($handler, $attrib);
}
else if (function_exists($handler)) {
// execute object handler function
return call_user_func($handler, $attrib);
}
if ($object=='productname') {
$name = !empty($this->config['product_name']) ? $this->config['product_name'] : 'RoundCube Webmail';
return Q($name);
}
if ($object=='version') {
$ver = (string)RCMAIL_VERSION;
if (is_file(INSTALL_PATH . '.svn/entries')) {
if (preg_match('/Revision:\s(\d+)/', @shell_exec('svn info'), $regs))
$ver .= ' [SVN r'.$regs[1].']';
}
return $ver;
}
if ($object=='steptitle') {
return Q($this->get_pagetitle());
}
if ($object=='pagetitle') {
$title = !empty($this->config['product_name']) ? $this->config['product_name'].' :: ' : '';
$title .= $this->get_pagetitle();
return Q($title);
}
break;
// return code for a specified eval expression
case 'exp':
$value = $this->parse_expression($attrib['expression']);
return eval("return Q($value);");
// return variable
case 'var':
$var = explode(':', $attrib['name']);
$name = $var[1];
$value = '';
switch ($var[0]) {
case 'env':
$value = $this->env[$name];
break;
case 'config':
$value = $this->config[$name];
if (is_array($value) && $value[$_SESSION['imap_host']]) {
$value = $value[$_SESSION['imap_host']];
}
break;
case 'request':
$value = get_input_value($name, RCUBE_INPUT_GPC);
break;
case 'session':
$value = $_SESSION[$name];
break;
case 'cookie':
$value = htmlspecialchars($_COOKIE[$name]);
break;
}
if (is_array($value)) {
$value = implode(', ', $value);
}
return Q($value);
break;
}
return '';
}
/**
* Include a specific file and return it's contents
*
* @param string File path
* @return string Contents of the processed file
*/
private function include_php($file)
{
ob_start();
include $file;
$out = ob_get_contents();
ob_end_clean();
return $out;
}
/**
* Create and register a button
*
* @param array Named button attributes
* @return string HTML button
* @todo Remove all inline JS calls and use jQuery instead.
* @todo Remove all sprintf()'s - they are pretty, but also slow.
*/
public function button($attrib)
{
static $sa_buttons = array();
static $s_button_count = 100;
// these commands can be called directly via url
$a_static_commands = array('compose', 'list');
if (!($attrib['command'] || $attrib['name'])) {
return '';
}
- $browser = new rcube_browser();
-
// try to find out the button type
if ($attrib['type']) {
$attrib['type'] = strtolower($attrib['type']);
}
else {
$attrib['type'] = ($attrib['image'] || $attrib['imagepas'] || $attrib['imageact']) ? 'image' : 'link';
}
$command = $attrib['command'];
// take the button from the stack
if ($attrib['name'] && $sa_buttons[$attrib['name']]) {
$attrib = $sa_buttons[$attrib['name']];
}
else if($attrib['image'] || $attrib['imageact'] || $attrib['imagepas'] || $attrib['class']) {
// add button to button stack
if (!$attrib['name']) {
$attrib['name'] = $command;
}
if (!$attrib['image']) {
$attrib['image'] = $attrib['imagepas'] ? $attrib['imagepas'] : $attrib['imageact'];
}
$sa_buttons[$attrib['name']] = $attrib;
}
else if ($command && $sa_buttons[$command]) {
// get saved button for this command/name
$attrib = $sa_buttons[$command];
}
// set border to 0 because of the link arround the button
if ($attrib['type']=='image' && !isset($attrib['border'])) {
$attrib['border'] = 0;
}
if (!$attrib['id']) {
$attrib['id'] = sprintf('rcmbtn%d', $s_button_count++);
}
// get localized text for labels and titles
if ($attrib['title']) {
$attrib['title'] = Q(rcube_label($attrib['title']));
}
if ($attrib['label']) {
$attrib['label'] = Q(rcube_label($attrib['label']));
}
if ($attrib['alt']) {
$attrib['alt'] = Q(rcube_label($attrib['alt']));
}
// set title to alt attribute for IE browsers
- if ($browser->ie && $attrib['title'] && !$attrib['alt']) {
+ if ($this->browser->ie && $attrib['title'] && !$attrib['alt']) {
$attrib['alt'] = $attrib['title'];
unset($attrib['title']);
}
// add empty alt attribute for XHTML compatibility
if (!isset($attrib['alt'])) {
$attrib['alt'] = '';
}
// register button in the system
if ($attrib['command']) {
$this->add_script(sprintf(
"%s.register_button('%s', '%s', '%s', '%s', '%s', '%s');",
JS_OBJECT_NAME,
$command,
$attrib['id'],
$attrib['type'],
$attrib['imageact'] ? $this->abs_url($attrib['imageact']) : $attrib['classact'],
$attrib['imagesel'] ? $this->abs_url($attrib['imagesel']) : $attrib['classsel'],
$attrib['imageover'] ? $this->abs_url($attrib['imageover']) : ''
));
// make valid href to specific buttons
if (in_array($attrib['command'], rcmail::$main_tasks)) {
$attrib['href'] = rcmail_url(null, null, $attrib['command']);
}
else if (in_array($attrib['command'], $a_static_commands)) {
$attrib['href'] = rcmail_url($attrib['command']);
}
else if ($attrib['command'] == 'permaurl' && !empty($this->env['permaurl'])) {
$attrib['href'] = $this->env['permaurl'];
}
}
// overwrite attributes
if (!$attrib['href']) {
$attrib['href'] = '#';
}
if ($command) {
$attrib['onclick'] = sprintf(
"return %s.command('%s','%s',this)",
JS_OBJECT_NAME,
$command,
$attrib['prop']
);
}
if ($command && $attrib['imageover']) {
$attrib['onmouseover'] = sprintf(
"return %s.button_over('%s','%s')",
JS_OBJECT_NAME,
$command,
$attrib['id']
);
$attrib['onmouseout'] = sprintf(
"return %s.button_out('%s','%s')",
JS_OBJECT_NAME,
$command,
$attrib['id']
);
}
if ($command && $attrib['imagesel']) {
$attrib['onmousedown'] = sprintf(
"return %s.button_sel('%s','%s')",
JS_OBJECT_NAME,
$command,
$attrib['id']
);
$attrib['onmouseup'] = sprintf(
"return %s.button_out('%s','%s')",
JS_OBJECT_NAME,
$command,
$attrib['id']
);
}
$out = '';
// generate image tag
if ($attrib['type']=='image') {
$attrib_str = html::attrib_string(
$attrib,
array(
'style', 'class', 'id', 'width',
'height', 'border', 'hspace',
'vspace', 'align', 'alt', 'tabindex'
)
);
$btn_content = sprintf('<img src="%s"%s />', $this->abs_url($attrib['image']), $attrib_str);
if ($attrib['label']) {
$btn_content .= ' '.$attrib['label'];
}
$link_attrib = array('href', 'onclick', 'onmouseover', 'onmouseout', 'onmousedown', 'onmouseup', 'title', 'target');
}
else if ($attrib['type']=='link') {
$btn_content = $attrib['label'] ? $attrib['label'] : $attrib['command'];
$link_attrib = array('href', 'onclick', 'title', 'id', 'class', 'style', 'tabindex', 'target');
}
else if ($attrib['type']=='input') {
$attrib['type'] = 'button';
if ($attrib['label']) {
$attrib['value'] = $attrib['label'];
}
$attrib_str = html::attrib_string(
$attrib,
array(
'type', 'value', 'onclick',
'id', 'class', 'style', 'tabindex'
)
);
$out = sprintf('<input%s disabled="disabled" />', $attrib_str);
}
// generate html code for button
if ($btn_content) {
$attrib_str = html::attrib_string($attrib, $link_attrib);
$out = sprintf('<a%s>%s</a>', $attrib_str, $btn_content);
}
return $out;
}
/* ************* common functions delivering gui objects ************** */
/**
* Create a form tag with the necessary hidden fields
*
* @param array Named tag parameters
* @return string HTML code for the form
*/
public function form_tag($attrib, $content = null)
{
if ($this->framed) {
$hiddenfield = new html_hiddenfield(array('name' => '_framed', 'value' => '1'));
$hidden = $hiddenfield->show();
}
if (!$content)
$attrib['noclose'] = true;
return html::tag('form',
$attrib + array('action' => "./", 'method' => "get"),
$hidden . $content);
}
/**
* GUI object 'username'
* Showing IMAP username of the current session
*
* @param array Named tag parameters (currently not used)
* @return string HTML code for the gui object
*/
public function current_username($attrib)
{
static $username;
// alread fetched
if (!empty($username)) {
return $username;
}
// get e-mail address form default identity
if ($sql_arr = $this->app->user->get_identity()) {
$username = $sql_arr['email'];
}
else {
$username = $this->app->user->get_username();
}
return $username;
}
/**
* GUI object 'loginform'
* Returns code for the webmail login form
*
* @param array Named parameters
* @return string HTML code for the gui object
*/
private function login_form($attrib)
{
$default_host = $this->config['default_host'];
$_SESSION['temp'] = true;
$input_user = new html_inputfield(array('name' => '_user', 'id' => 'rcmloginuser', 'size' => 30) + $attrib);
$input_pass = new html_passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd', 'size' => 30) + $attrib);
$input_action = new html_hiddenfield(array('name' => '_action', 'value' => 'login'));
$input_tzone = new html_hiddenfield(array('name' => '_timezone', 'id' => 'rcmlogintz', 'value' => '_default_'));
$input_host = null;
if (is_array($default_host)) {
$input_host = new html_select(array('name' => '_host', 'id' => 'rcmloginhost'));
foreach ($default_host as $key => $value) {
if (!is_array($value)) {
$input_host->add($value, (is_numeric($key) ? $value : $key));
}
else {
$input_host = null;
break;
}
}
}
else if (empty($default_host)) {
$input_host = new html_inputfield(array('name' => '_host', 'id' => 'rcmloginhost', 'size' => 30));
}
$form_name = !empty($attrib['form']) ? $attrib['form'] : 'form';
$this->add_gui_object('loginform', $form_name);
// create HTML table with two cols
$table = new html_table(array('cols' => 2));
$table->add('title', html::label('rcmloginuser', Q(rcube_label('username'))));
$table->add(null, $input_user->show(get_input_value('_user', RCUBE_INPUT_POST)));
$table->add('title', html::label('rcmloginpwd', Q(rcube_label('password'))));
$table->add(null, $input_pass->show());
// add host selection row
if (is_object($input_host)) {
$table->add('title', html::label('rcmloginhost', Q(rcube_label('server'))));
$table->add(null, $input_host->show(get_input_value('_host', RCUBE_INPUT_POST)));
}
$out = $input_action->show();
$out .= $input_tzone->show();
$out .= $table->show();
// surround html output with a form tag
if (empty($attrib['form'])) {
$out = $this->form_tag(array('name' => $form_name, 'method' => "post"), $out);
}
return $out;
}
/**
* GUI object 'searchform'
* Returns code for search function
*
* @param array Named parameters
* @return string HTML code for the gui object
*/
private function search_form($attrib)
{
// add some labels to client
$this->add_label('searching');
$attrib['name'] = '_q';
if (empty($attrib['id'])) {
$attrib['id'] = 'rcmqsearchbox';
}
+ if ($attrib['type'] == 'search' && !$this->browser->khtml) {
+ unset($attrib['type'], $attrib['results']);
+ }
+
$input_q = new html_inputfield($attrib);
$out = $input_q->show();
$this->add_gui_object('qsearchbox', $attrib['id']);
// add form tag around text field
if (empty($attrib['form'])) {
$out = $this->form_tag(array(
'name' => "rcmqsearchform",
'onsubmit' => JS_OBJECT_NAME . ".command('search');return false;",
'style' => "display:inline"),
$out);
}
return $out;
}
/**
* Builder for GUI object 'message'
*
* @param array Named tag parameters
* @return string HTML code for the gui object
*/
private function message_container($attrib)
{
if (isset($attrib['id']) === false) {
$attrib['id'] = 'rcmMessageContainer';
}
$this->add_gui_object('message', $attrib['id']);
return html::div($attrib, "");
}
/**
* GUI object 'charsetselector'
*
* @param array Named parameters for the select tag
* @return string HTML code for the gui object
*/
static function charset_selector($attrib)
{
// pass the following attributes to the form class
$field_attrib = array('name' => '_charset');
foreach ($attrib as $attr => $value) {
if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex'))) {
$field_attrib[$attr] = $value;
}
}
$charsets = array(
'US-ASCII' => 'ASCII (English)',
'EUC-JP' => 'EUC-JP (Japanese)',
'EUC-KR' => 'EUC-KR (Korean)',
'BIG5' => 'BIG5 (Chinese)',
'GB2312' => 'GB2312 (Chinese)',
'ISO-2022-JP' => 'ISO-2022-JP (Japanese)',
'ISO-8859-1' => 'ISO-8859-1 (Latin-1)',
'ISO-8859-2' => 'ISO-8895-2 (Central European)',
'ISO-8859-7' => 'ISO-8859-7 (Greek)',
'ISO-8859-9' => 'ISO-8859-9 (Turkish)',
'Windows-1251' => 'Windows-1251 (Cyrillic)',
'Windows-1252' => 'Windows-1252 (Western)',
'Windows-1255' => 'Windows-1255 (Hebrew)',
'Windows-1256' => 'Windows-1256 (Arabic)',
'Windows-1257' => 'Windows-1257 (Baltic)',
'UTF-8' => 'UTF-8'
);
$select = new html_select($field_attrib);
$select->add(array_values($charsets), array_keys($charsets));
$set = $_POST['_charset'] ? $_POST['_charset'] : $this->get_charset();
return $select->show($set);
}
} // end class rcube_template
diff --git a/skins/default/mail.css b/skins/default/mail.css
index 81e4cff35..ec78cd7a2 100644
--- a/skins/default/mail.css
+++ b/skins/default/mail.css
@@ -1,1066 +1,1065 @@
/***** RoundCube|Mail mail task styles *****/
#messagetoolbar
{
position: absolute;
top: 45px;
left: 200px;
right: 200px;
height: 35px;
white-space: nowrap;
/* border: 1px solid #cccccc; */
}
#messagetoolbar a
{
padding-right: 10px;
}
#messagetoolbar select
{
font-family: "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
font-size: 11px;
color: #333333;
}
#messagetoolbar select.mboxlist
{
position: absolute;
left: 375px;
top: 10px;
}
#messagetoolbar select.mboxlist option
{
padding-left: 15px;
}
#messagetoolbar select.mboxlist option[value="0"]
{
padding-left: 2px;
}
#markmessagemenu
{
position: absolute;
top: 32px;
left: 90px;
width: auto;
visibility: hidden;
background-color: #F9F9F9;
border: 1px solid #CCC;
padding: 1px;
opacity: 0.9;
filter:alpha(opacity=90);
z-index: 240;
}
ul.toolbarmenu
{
margin: 0;
padding: 0;
list-style: none;
}
ul.toolbarmenu li
{
font-size: 11px;
white-space: nowrap;
min-width: 130px;
width: auto !important;
width: 130px;
}
ul.toolbarmenu li a
{
display: block;
color: #a0a0a0;
padding: 2px 8px 3px 12px;
text-decoration: none;
}
ul.toolbarmenu li a.active:hover
{
background-color: #ddd;
}
#listcontrols
{
position: absolute;
left: 200px;
bottom: 20px;
height: 16px;
width: 500px;
font-size: 11px;
}
#listcontrols a,
#listcontrols a:active,
#listcontrols a:visited,
#mailboxcontrols a,
#mailboxcontrols a:active,
#mailboxcontrols a:visited,
td.formlinks a,
td.formlinks a:visited
{
color: #999999;
font-size: 11px;
text-decoration: none;
}
#listcontrols a.active,
#listcontrols a.active:active,
#listcontrols a.active:visited,
#mailboxcontrols a.active,
#mailboxcontrols a.active:active,
#mailboxcontrols a.active:visited,
ul.toolbarmenu li a.active,
ul.toolbarmenu li a.active:active,
ul.toolbarmenu li a.active:visited,
td.formlinks a,
td.formlinks a:visited
{
color: #CC0000;
}
#listcontrols a.active:hover,
#mailboxcontrols a.active:hover
{
text-decoration: underline;
}
#messagecountbar
{
position: absolute;
bottom: 16px;
right: 20px;
width: 300px;
height: 20px;
text-align: right;
white-space: nowrap;
}
#messagecountbar span
{
font-size: 11px;
color: #333333;
}
#mainscreen
{
position: absolute;
top: 85px;
right: 20px;
bottom: 40px;
left: 20px;
/* css hack for IE */
width: expression((parseInt(document.documentElement.clientWidth)-40)+'px');
height: expression((parseInt(document.documentElement.clientHeight)-125)+'px');
}
#mailrightcontainer
{
position: absolute;
top: 0px;
left: 170px;
bottom: 0px;
right: 0px;
/* css hack for IE */
width: expression((parseInt(this.parentNode.offsetWidth)-170)+'px');
height: expression(parseInt(this.parentNode.offsetHeight)+'px');
}
#messagepartcontainer
{
position: absolute;
top: 80px;
left: 20px;
right: 20px;
bottom: 20px;
/* css hack for IE */
width: expression((parseInt(document.documentElement.clientWidth)-40)+'px');
height: expression((parseInt(document.documentElement.clientHeight)-100)+'px');
}
#mailcontframe
{
position: absolute;
width: 100%;
top: 0px;
bottom: 0px;
border: 1px solid #999999;
background-color: #F9F9F9;
overflow: auto;
/* css hack for IE */
height: expression(parseInt(this.parentNode.offsetHeight)+'px');
}
#mailpreviewframe
{
position: absolute;
width: 100%;
top: 205px;
bottom: 0px;
border: 1px solid #999999;
background-color: #F9F9F9;
/* css hack for IE */
height: expression((parseInt(this.parentNode.offsetHeight)-205)+'px');
}
#messagecontframe
{
position: relative;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
width: 100%;
height: 100%;
}
#messagepartframe
{
width: 100%;
height: 100%;
border: 1px solid #999999;
background-color: #F9F9F9;
}
#partheader
{
position: absolute;
top: 10px;
left: 220px;
right: 20px;
height: 40px;
/* css hack for IE */
width: expression((parseInt(document.documentElement.clientWidth)-240)+'px');
}
#partheader table td
{
padding-left: 2px;
padding-right: 4px;
vertical-align: middle;
font-size: 11px;
}
#partheader table td.title
{
color: #666666;
font-weight: bold;
}
/** mailbox list styles */
#mailboxlist-header
{
display: block;
height: 12px;
margin: 0;
padding: 3px 10px 4px 10px;
background-color: #EBEBEB;
background-image: url(images/listheader_aqua.gif);
border-bottom: 1px solid #999;
color: #333333;
font-size: 11px;
font-weight: bold;
}
#mailboxlist-container
{
position: absolute;
top: 0px;
left: 0px;
width: 160px;
bottom: 0px;
border: 1px solid #999;
background-color: #F9F9F9;
overflow: auto;
/* css hack for IE */
height: expression(parseInt(this.parentNode.offsetHeight)+'px');
}
#mailboxlist
{
position:relative;
width: 100%;
height: auto;
margin: 0px;
padding: 0px;
list-style-image: none;
list-style-type: none;
overflow: hidden;
white-space: nowrap;
}
#mailboxlist li
{
display: block;
position: relative;
font-size: 11px;
background: url(images/icons/folder-closed.png) no-repeat;
background-position: 5px 1px;
border-bottom: 1px solid #EBEBEB;
}
#mailboxlist li div
{
position: absolute;
left: 8px !important;
left: -16px;
top: 2px;
width: 14px;
height: 16px;
}
#mailboxlist li div.collapsed,
#mailboxlist li div.expanded
{
cursor: pointer;
}
#mailboxlist li div.collapsed
{
background: url(images/icons/collapsed.png) bottom right no-repeat;
}
#mailboxlist li div.expanded
{
background: url(images/icons/expanded.png) bottom right no-repeat;
}
#mailboxlist li.inbox
{
background-image: url(images/icons/folder-inbox.png);
}
#mailboxlist li.drafts
{
background-image: url(images/icons/folder-drafts.png);
}
#mailboxlist li.sent
{
background-image: url(images/icons/folder-sent.png);
}
#mailboxlist li.junk
{
background-image: url(images/icons/folder-junk.png);
}
#mailboxlist li.trash
{
background-image: url(images/icons/folder-trash.png);
}
#mailboxlist li a
{
cursor: default;
display: block;
position: relative;
padding-left: 25px;
padding-top: 2px;
padding-bottom: 2px;
text-decoration: none;
}
#mailboxlist li.unread
{
font-weight: bold;
}
#mailboxlist li.virtual > a
{
color: #666;
}
#mailboxlist li.selected,
#mailboxlist li.droptarget li.selected
{
background-color: #929292;
}
#mailboxlist li.selected > a,
#mailboxlist li.droptarget li.selected a
{
color: #FFF;
font-weight: bold;
}
#mailboxlist li.droptarget
{
background-color: #FFFFA6;
}
/* styles for nested folders */
#mailboxlist ul {
list-style: none;
padding: 0;
margin:0;
border-top: 1px solid #EBEBEB;
padding-left: 15px;
background-position: 25px 1px;
background-color: #F9F9F9;
color: blue;
font-weight: normal;
}
#mailboxcontrols
{
position: absolute;
left: 20px;
width: 185px;
bottom: 20px;
height: 16px;
overflow: hidden;
font-size: 11px;
}
/** message list styles */
body.messagelist
{
margin: 0px;
background-color: #F9F9F9;
}
#messagelist
{
width: 100%;
display: table;
table-layout: fixed;
/* css hack for IE */
width: expression(parseInt(document.getElementById('mailcontframe').clientWidth)+'px');
}
/* safari hack \*/
html>body*#messagelist[id$="messagelist"]:not([class="none"]) { width: 99%; }
html>body*input[type$="file"]:not([class="none"]) { background-color: transparent; border:0; }
/**/
#messagelist thead tr td
{
height: 20px;
padding-top: 0px;
padding-bottom: 0px;
padding-left: 2px;
padding-right: 4px;
vertical-align: middle;
border-bottom: 1px solid #999999;
color: #333333;
background-color: #EBEBEB;
background-image: url(images/listheader_aqua.gif);
font-size: 11px;
font-weight: bold;
}
#messagelist thead tr td.sortedASC,
#messagelist thead tr td.sortedDESC
{
background-image: url(images/listheader_dark.gif);
}
#messagelist thead tr td.sortedASC a
{
background: url(images/sort_asc.gif) top right no-repeat;
}
#messagelist thead tr td.sortedDESC a
{
background: url(images/sort_desc.gif) top right no-repeat;
}
#messagelist thead tr td a
{
display: block;
width: auto !important;
width: 100%;
color: #333333;
text-decoration: none;
}
#messagelist tbody tr td
{
height: 16px;
padding: 2px;
padding-right: 4px;
font-size: 11px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
border-bottom: 1px solid #EBEBEB;
cursor: default;
}
#messagelist tbody tr td a
{
color: #000;
text-decoration: none;
white-space: nowrap;
cursor: inherit;
}
#messagelist tbody tr td.subject a
{
cursor: default;
}
#messagelist col
{
display: table-column;
text-align: left;
vertical-align: middle;
}
#messagelist tr td.icon,
#messagelist tr td.flag
{
width: 16px;
vertical-align: middle;
cursor: pointer;
}
#messagelist tr td.subject
{
overflow: hidden;
vertical-align: middle;
}
#messagelist tr td.size
{
width: 70px;
text-align: right;
vertical-align: middle;
}
#messagelist tr td.from,
#messagelist tr td.to
{
width: 180px;
vertical-align: middle;
}
#messagelist tr td.date
{
width: 118px;
vertical-align: middle;
}
#messagelist tr.message
{
background-color: #FFFFFF;
}
/*
#messagelist tr.odd
{
background-color: #F9F9F9;
}
*/
#messagelist tr.unread
{
font-weight: bold;
background-color: #FFFFFF;
}
#messagelist tr.selected td
{
color: #FFFFFF;
background-color: #CC3333;
}
#messagelist tr.unfocused td
{
color: #FFFFFF;
background-color: #929292;
}
#messagelist tr.selected td a
{
color: #FFFFFF;
}
#messagelist tr.unfocused td a
{
color: #FFFFFF;
}
#messagelist tr.deleted td a
{
color: #CCCCCC;
}
#messagelist tr.deleted td,
#messagelist tr.deleted td a
{
color: #CCCCCC;
}
#quotadisplay
{
color: #666666;
font-size: 11px;
}
#quotadisplay img
{
vertical-align: middle;
margin-left: 4px;
border: 1px solid #666666;
}
/** message view styles */
#messageframe
{
position: absolute;
top: 0px;
left: 170px;
right: 0px;
bottom: 0px;
border: 1px solid #999;
background-color: #FFF;
overflow: auto;
/* css hack for IE */
width: expression((parseInt(document.documentElement.clientWidth)-220)+'px');
height: expression((parseInt(document.documentElement.clientHeight)-125)+'px');
}
#printmessageframe
{
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
border: 1px solid #999;
background-color: #FFF;
overflow: auto;
/* css hack for IE */
width: expression((parseInt(document.documentElement.clientWidth)-220)+'px');
height: expression((parseInt(document.documentElement.clientHeight)-125)+'px');
}
div.messageheaderbox
{
position: relative;
margin: 6px 8px 0px 8px;
border: 1px solid #ccc;
}
table.headers-table
{
width: 100%;
background-color: #EBEBEB;
table-layout: fixed;
}
#messagebody table.headers-table
{
width: auto;
margin: 6px 8px;
background-color: #F4F4F4;
border: 1px solid #ccc;
}
#messageframe table.headers-table
{
border-bottom: 1px solid #ccc;
}
table.headers-table tr td
{
font-size: 11px;
border-bottom:1px solid #FFFFFF;
}
table.headers-table td.header-title
{
width: 80px;
color: #666666;
font-weight: bold;
text-align: right;
white-space: nowrap;
padding-right: 4px;
}
table.headers-table tr td.subject
{
width: 90%;
font-weight: bold;
}
table.headers-table tr td.all
{
width: 100%;
color: #666666;
text-align: left;
padding-right: 10px;
vertical-align: center;
text-align: center;
}
#attachment-list
{
margin: 0px;
padding: 0px 0px 0px 72px;
min-height: 16px;
list-style-image: none;
list-style-type: none;
background: url(images/icons/attachment.png) 60px 2px no-repeat #DFDFDF;
/* IE6 hack */
_height: expression(Math.min(16, parseInt(document.documentElement.clientHeight))+'px');
}
#attachment-list:after
{
content: ".";
display: block;
height: 0;
font-size: 0;
clear: both;
visibility: hidden;
}
#attachment-list li
{
float: left;
height: 18px;
font-size: 11px;
padding: 2px 0px 0px 15px;
white-space: nowrap;
}
#attachment-list li a
{
text-decoration: none;
}
#attachment-list li a:hover
{
text-decoration: underline;
}
#messagebody
{
position:relative;
- min-height: 300px;
padding-bottom: 10px;
background-color: #FFFFFF;
}
div.message-part
{
padding: 10px 8px;
border-top: 1px solid #ccc;
/* overflow: hidden; */
}
#messagebody div:first-child
{
border-top: 0;
}
div.message-part a,
div.message-htmlpart a
{
color: #0000CC;
}
div.message-part div.pre
{
margin: 0px;
padding: 0px;
font-family: monospace;
white-space: -moz-pre-wrap !important;
white-space: pre;
word-wrap: break-word; /* IE (and Safari) */
}
div.message-part blockquote
{
color: blue;
border-left: 2px solid blue;
border-right: 2px solid blue;
background-color: #F6F6F6;
margin: 2px 0px 2px 0px;
padding: 1px 8px 1px 10px;
}
div.message-part blockquote blockquote
{
color: green;
border-left: 2px solid green;
border-right: 2px solid green;
}
div.message-part blockquote blockquote blockquote
{
color: #990000;
border-left: 2px solid #bb0000;
border-right: 2px solid #bb0000;
}
body.iframe div.message-htmlpart
{
margin: 8px;
}
div.message-htmlpart div.rcmBody
{
margin: 8px;
}
#remote-objects-message
{
display: none;
margin: 8px;
min-height: 20px;
padding: 10px 10px 6px 46px;
}
#remote-objects-message a
{
color: #666666;
padding-left: 10px;
}
#remote-objects-message a:hover
{
color: #333333;
}
#messageviewlink
{
position: absolute;
top: 1px;
right: 1px;
width: 15px;
height: 15px;
border: 0;
}
/** message compose styles */
#compose-toolbar
{
white-space: nowrap;
}
#priority-selector,
#receipt-selector
{
padding-left: 30px;
white-space: nowrap;
}
#compose-container
{
position: absolute;
top: 90px;
left: 200px;
right: 25px;
bottom: 30px;
padding: 0px;
margin: 0px;
/* css hack for IE */
width: expression((parseInt(document.documentElement.clientWidth)-220)+'px');
height: expression((parseInt(document.documentElement.clientHeight)-130)+'px');
}
/*
#compose-headers
{
position: absolute;
top: 70px;
left: 200px;
height: 84px;
border-top: 1px solid #cccccc;
overflow: auto;
}
#compose-headers td
{
padding-top: 1px;
padding-bottom: 1px;
border-right: 1px solid #cccccc;
border-bottom: 1px solid #cccccc;
}
*/
#compose-headers
{
width: 100%;
}
/*
#compose-headers td
{
width: 100%;
}
*/
#compose-headers td.top
{
vertical-align: top;
}
#compose-headers td.title,
#compose-subject td.title
{
width: 80px !important;
color: #666666;
font-size: 11px;
font-weight: bold;
padding-right: 10px;
white-space: nowrap;
}
#compose-body,
#compose-headers td textarea,
#compose-headers td input
{
width: 100%;
width: expression('99%');
}
#compose-headers td textarea
{
height: 38px;
}
#compose-cc,
#compose-bcc,
#compose-replyto
{
display: none;
}
#compose-body
{
margin-top: 5px;
margin-bottom: 10px;
height: 90%;
min-height: 280px;
font-size: 9pt;
font-family: "Courier New", Courier, monospace;
}
#compose-attachments
{
position: absolute;
top: 100px;
left: 20px;
width: 160px;
}
#compose-attachments ul
{
margin: 0px;
padding: 0px;
border: 1px solid #CCCCCC;
background-color: #F9F9F9;
list-style-image: none;
list-style-type: none;
}
#compose-attachments ul li
{
height: 18px;
font-size: 11px;
padding-left: 2px;
padding-top: 2px;
padding-right: 4px;
border-bottom: 1px solid #EBEBEB;
white-space: nowrap;
overflow: hidden;
}
#attachment-title
{
background: url(images/icons/attachment.png) top left no-repeat;
padding: 0px 0px 3px 22px;
}
#attachment-form
{
position: absolute;
top: 150px;
left: 20px;
z-index: 200;
padding: 6px;
visibility: hidden;
border: 1px solid #CCCCCC;
background-color: #F9F9F9;
}
#attachment-form div
{
padding: 2px;
}
#attachment-form div.buttons
{
margin-top: 4px;
}
table.headers-table tr td.more-headers
{
cursor: pointer;
width: 100%;
height: 8px;
border-bottom: 0;
}
table.headers-table tr td.all
{
padding: 2px 6px 4px 6px;
border-bottom: 0;
}
td.show-headers
{
background: url(images/icons/down_small.gif) no-repeat center;
}
td.hide-headers
{
background: url(images/icons/up_small.gif) no-repeat center;
}
#all-headers
{
height: 150px;
display: none;
}
#headers-source
{
margin: 0 5px;
padding: 0.5em;
height: 145px;
background: white;
overflow: auto;
font-size: 11px;
white-space: nowrap;
border: 1px solid #999999;
display: none;
text-align: left;
color: #333;
}
font.bold
{
font-weight: bold;
}
diff --git a/skins/default/watermark.html b/skins/default/watermark.html
index 85e53652a..6202b8f83 100644
--- a/skins/default/watermark.html
+++ b/skins/default/watermark.html
@@ -1,12 +1,13 @@
<!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></title>
</head>
<body style="background-color:#F2F2F2;">
<div style="margin:10px auto; text-align:center">
<img src="images/rcube_watermark.png" width="245" height="245" alt="" />
</div>
</body>
</html>
\ No newline at end of file

File Metadata

Mime Type
text/x-diff
Expires
Sat, Mar 1, 10:22 AM (15 h, 52 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
166635
Default Alt Text
(76 KB)

Event Timeline