Merge branch 'master' of github.com:roundcube/roundcubemail

pull/129/head
Aleksander Machniak 11 years ago
commit b334a01791

@ -1,6 +1,9 @@
CHANGELOG Roundcube Webmail
===========================
- Make default font size for HTML messages configurable (request #118)
- Display full attachment name using title attribute when name is too long to display (#1489320)
- Fix XSS issue in addressbook group name field [CVE-2013-5646] (#1489333)
- Fix attachment icon issue when rare font/language is used (#1489326)
- After message is sent refresh messages list of replied message folder (#1489249)
- Add option force specified domain in user login - username_domain_forced (#1489264)
@ -96,8 +99,8 @@ RELEASE 0.9.3
- Fix base URL resolving on attribute values with no quotes (#1489275)
- Fix wrong handling of links with '|' character (#1489276)
- Fix colorspace issue on image conversion using ImageMagick (#1489270)
- Fix XSS vulnerability when editing a message "as new" or draft (#1489251)
- Fix XSS vulnerability when saving HTML signatures (#1489251)
- Fix XSS vulnerability when editing a message "as new" or draft [CVE-2013-5645] (#1489251)
- Fix XSS vulnerability when saving HTML signatures [CVE-2013-5645] (#1489251)
- Fix rewrite rule in .htaccess (#1489240)
- Fix detecting Turkish language in ISO-8859-9 encoding (#1489252)
- Fix identity-selection using Return-Path headers (#1489241)
@ -317,7 +320,7 @@ RELEASE 0.8.5
- Fix #countcontrols issue in IE<=8 when text is very long (#1488890)
- Fix unwanted horizontal scrollbar in message preview header (#1488866)
- Add workaround for IE<=8 bug where Content-Disposition:inline was ignored (#1488844)
- Fix XSS vulnerability in vbscript: and data:text links handling (#1488850)
- Fix XSS vulnerability in vbscript: and data:text links handling [CVE-2012-6121] (#1488850)
- Fix absolute positioning in HTML messages (#1488819)
- Fix cache (in)validation after setting \Deleted flag
- Fix keybord events on messages list in opera browser (#1488823)
@ -372,8 +375,8 @@ RELEASE 0.8.1
- Fix bug where domain name was converted to lower-case even with login_lc=false (#1488593)
- Fix lower-casing email address on replies (#1488598)
- Fix line separator in exported messages (#1488603)
- Fix XSS issue where plain signatures wasn't secured in HTML mode (#1488613)
- Fix XSS issue where href="javascript:" wasn't secured (#1488613)
- Fix XSS issue where plain signatures wasn't secured in HTML mode [CVE-2012-4668] (#1488613)
- Fix XSS issue where href="javascript:" wasn't secured [CVE-2012-3508] (#1488613)
- Fix impossible to create message with empty plain text part (#1488610)
- Fix stripped apostrophes when replying in plain text to HTML message (#1488606)
- Fix inactive Save search option after advanced search (#1488607)
@ -408,7 +411,7 @@ RELEASE 0.8.0
- Fix removing contact photo using LDAP addressbook (#1488420)
- Fix storing X-ANNIVERSARY date in vCard format (#1488527)
- Update to Mail_Mime-1.8.5 (#1488521)
- Fix XSS vulnerability in message subject handling using Larry skin (#1488519)
- Fix XSS vulnerability in message subject handling using Larry skin [CVE-2012-3507] (#1488519)
- Fix handling of links with various URI schemes e.g. "skype:" (#1488106)
- Fix handling of links inside PRE elements on html to text conversion
- Fix indexing of links on html to text conversion
@ -535,7 +538,7 @@ RELEASE 0.7
- Improved handling of some malformed values encoded with quoted-printable (#1488232)
- Add possibility to do LDAP bind before searching for bind DN
- Fix handling of empty <U> tags in HTML messages (#1488225)
- Add content filter for embedded attachments to protect from XSS on IE (#1487895)
- Add content filter for embedded attachments to protect from XSS on IE [CVE-2012-1253] (#1487895)
- Use strpos() instead of strstr() when possible (#1488211)
- Fix handling HTML entities when converting HTML to text (#1488212)
- Fix fit_string_to_size() renders browser and ui unresponsive (#1488207)
@ -703,7 +706,7 @@ RELEASE 0.6-beta
RELEASE 0.5.4
-------------
- Fix XSS vulnerability in UI messages (#1488030)
- Fix XSS vulnerability in UI messages [CVE-2011-2937] (#1488030)
RELEASE 0.5.3
-------------
@ -753,8 +756,8 @@ RELEASE 0.5.1
- Security: add optional referer check to prevent CSRF in GET requests
- Fix email_dns_check setting not used for identities/contacts (#1487740)
- Fix ICANN example addresses doesn't validate (#1487742)
- Security: protect login form submission from CSRF
- Security: prevent from relaying malicious requests through modcss.inc
- Security: protect login form submission from CSRF [CVE-2011-1491]
- Security: prevent from relaying malicious requests through modcss.inc [CVE-2011-1492]
- Fix handling of non-image attachments in multipart/related messages (#1487750)
- Fix IDNA support when IDN/INTL modules are in use (#1487742)
- Fix handling of invalid HTML comments in messages (#1487759)
@ -1197,7 +1200,7 @@ RELEASE 0.3-RC1
---------------
- Fix import of vCard entries with params (#1485453)
- Fix HTML messages output with empty block elements (#1485974)
- Use request tokens to protect POST requests from CSRF
- Use request tokens to protect POST requests from CSRF [CVE-2009-4076, CVE-2009-4077]
- Added hook when killing a session
- Added hook to write_log function (#1485971)
- Performance improvements by use UID commands (#1485690)
@ -1324,7 +1327,7 @@ RELEASE 0.2.1
- Fix large search results on server without SORT capability (#1485668)
- Get rid of preg_replace() with eval modifier and create_function usage (#1485686)
- Bring back <base> and <link> tags in HTML messages
- Fix XSS vulnerability through background attributes as reported by Julien Cayssol
- Fix XSS vulnerability through background attributes [CVE-2009-0413]
- Fix problems with backslash as IMAP hierarchy delimiter (#1484467)
- Secure vcard export by getting rid of preg's 'e' modifier use (#1485689)
- Fix authentication when submitting form with existing session (#1485679)

@ -245,6 +245,8 @@ $config['support_url'] = '';
// replace Roundcube logo with this image
// specify an URL relative to the document root of this Roundcube installation
// an array can be used to specify different logos for specific template files, '*' for default logo
// for example array("*" => "/images/roundcube_logo.png", "messageprint" => "/images/roundcube_logo_print.png")
$config['skin_logo'] = null;
// automatically create a new Roundcube user when log-in the first time.
@ -982,5 +984,9 @@ $config['autocomplete_single'] = false;
// Georgia, Helvetica, Impact, Tahoma, Terminal, Times New Roman, Trebuchet MS, Verdana
$config['default_font'] = 'Verdana';
// Default font size for composed HTML message.
// Supported sizes: 8pt, 10pt, 12pt, 14pt, 18pt, 24pt, 36pt
$config['default_font_size'] = '10pt';
// Enables display of email address with name instead of a name (and address in title)
$config['message_show_email'] = false;

@ -320,8 +320,7 @@ $config['hmailserver_server'] = array(
// 5: domain-username
// 6: username_domain
// 7: domain_username
// 8: username@domain; mbox.username
$config['password_virtualmin_format'] = 8;
$config['password_virtualmin_format'] = 0;
// pw_usermod Driver options

@ -48,10 +48,6 @@ class rcube_virtualmin_password
$pieces = explode("_", $username);
$domain = $pieces[0];
break;
case 8: // domain taken from alias, username left as it was
$email = $rcmail->user->data['alias'];
$domain = substr(strrchr($email, "@"), 1);
break;
default: // username@domain
$domain = substr(strrchr($username, "@"), 1);
}

@ -924,8 +924,21 @@ class rcmail_output_html extends rcmail_output
}
else if ($object == 'logo') {
$attrib += array('alt' => $this->xml_command(array('', 'object', 'name="productname"')));
if ($logo = $this->config->get('skin_logo'))
$attrib['src'] = $logo;
if ($logo = $this->config->get('skin_logo')) {
if (is_array($logo)) {
if ($template_logo = $logo[$this->template_name]) {
$attrib['src'] = $template_logo;
}
elseif ($template_logo = $logo['*']) {
$attrib['src'] = $template_logo;
}
}
else {
$attrib['src'] = $logo;
}
}
$content = html::img($attrib);
}
else if ($object == 'productname') {

@ -227,6 +227,13 @@ class rcmail_output_json extends rcmail_output
if (!empty($this->callbacks))
$response['callbacks'] = $this->callbacks;
// trigger generic hook where plugins can put additional content to the response
$hook = $this->app->plugins->exec_hook("render_response", array('response' => $response));
// save some memory
$response = $hook['response'];
unset($hook['response']);
echo self::json_serialize($response);
}

@ -1881,7 +1881,7 @@ function rcube_webmail()
html = expando;
else if (c == 'subject') {
if (bw.ie) {
col.onmouseover = function() { rcube_webmail.long_subject_title_ie(this, message.depth+1); };
col.onmouseover = function() { rcube_webmail.long_subject_title_ex(this, message.depth+1); };
if (bw.ie8)
tree = '<span></span>' + tree; // #1487821
}
@ -3427,7 +3427,8 @@ function rcube_webmail()
message = input_message.val(),
is_html = ($("input[name='_is_html']").val() == '1'),
sig = this.env.identity,
delim = this.env.recipients_delimiter,
delim = this.env.recipients_separator,
rx_delim = RegExp.escape(delim),
headers = ['replyto', 'bcc'];
// update reply-to/bcc fields with addresses defined in identities
@ -3444,16 +3445,18 @@ function rcube_webmail()
}
// cleanup
rx = new RegExp(RegExp.escape(delim) + '\\s*' + RegExp(delim), 'g');
input_val = input_val.replace(rx, delim)
rx = new RegExp('^\\s*' + RegExp.escape(delim) + '\\s*$');
input_val = input_val.replace(rx, '')
rx = new RegExp(rx_delim + '\\s*' + rx_delim, 'g');
input_val = input_val.replace(rx, delim);
rx = new RegExp('^[\\s' + rx_delim + ']+');
input_val = input_val.replace(rx, '');
// add new address(es)
if (new_val) {
rx = new RegExp(RegExp.escape(delim) + '\\s*$');
if (input_val && !rx.test(input_val))
input_val += delim + ' ';
if (new_val && input_val.indexOf(new_val) == -1 && input_val.indexOf(new_val.replace(/"/g, '')) == -1) {
if (input_val) {
rx = new RegExp('[' + rx_delim + '\\s]+$')
input_val = input_val.replace(rx, '') + delim + ' ';
}
input_val += new_val + delim + ' ';
}
@ -3639,7 +3642,12 @@ function rcube_webmail()
att.html = '<a title="'+this.get_label('cancel')+'" onclick="return rcmail.cancel_attachment_upload(\''+name+'\', \''+att.frame+'\');" href="#cancelupload" class="cancelupload">'
+ (this.env.cancelicon ? '<img src="'+this.env.cancelicon+'" alt="" />' : this.get_label('cancel')) + '</a>' + att.html;
var indicator, li = $('<li>').attr('id', name).addClass(att.classname).html(att.html);
var indicator, li = $('<li>');
li.attr('id', name)
.addClass(att.classname)
.html(att.html)
.on('mouseover', function() { rcube_webmail.long_subject_title_ex(this, 0); });
// replace indicator's li
if (upload_id && (indicator = document.getElementById(upload_id))) {
@ -4345,7 +4353,7 @@ function rcube_webmail()
boxtitle.append('&nbsp;&raquo;&nbsp;');
}
boxtitle.append($('<span>'+prop.name+'</span>'));
boxtitle.append($('<span>').text(prop.name));
}
this.triggerEvent('groupupdate', prop);
@ -6986,11 +6994,11 @@ rcube_webmail.long_subject_title = function(elem, indent)
if (!elem.title) {
var $elem = $(elem);
if ($elem.width() + indent * 15 > $elem.parent().width())
elem.title = $elem.html();
elem.title = $elem.text();
}
};
rcube_webmail.long_subject_title_ie = function(elem, indent)
rcube_webmail.long_subject_title_ex = function(elem, indent)
{
if (!elem.title) {
var $elem = $(elem),

@ -80,6 +80,9 @@ function rcmail_editor_callback()
if (rcmail.env.default_font)
$(tinyMCE.get(rcmail.env.composebody).getBody()).css('font-family', rcmail.env.default_font);
if (rcmail.env.default_font_size)
$(tinyMCE.get(rcmail.env.composebody).getBody()).css('font-size', rcmail.env.default_font_size);
if (elem && elem.type == 'select-one') {
rcmail.change_identity(elem);
// Focus previously focused element

@ -214,7 +214,7 @@ class rcube_config
$success = true;
}
// deprecated name of config variable
else if (is_array($rcmail_config)) {
if (is_array($rcmail_config)) {
$this->merge($rcmail_config);
$success = true;
}

@ -118,9 +118,12 @@ if (is_array($_FILES['_attachments']['tmp_name'])) {
'alt' => rcube_label('delete')
));
}
else {
else if ($COMPOSE['textbuttons']) {
$button = Q(rcube_label('delete'));
}
else {
$button = '';
}
$content = html::a(array(
'href' => "#delete",

@ -148,6 +148,9 @@ if ($font && !is_array($font)) {
$OUTPUT->set_env('default_font', $font);
}
// default font size for HTML editor
$OUTPUT->set_env('default_font_size', $RCMAIL->config->get('default_font_size'));
// get reference message and set compose mode
if ($msg_uid = $COMPOSE['param']['draft_uid']) {
$compose_mode = RCUBE_COMPOSE_DRAFT;
@ -1370,8 +1373,9 @@ function rcmail_compose_attachment_list($attrib)
if (!$attrib['id'])
$attrib['id'] = 'rcmAttachmentList';
$out = "\n";
$out = "\n";
$jslist = array();
$button = '';
if (is_array($COMPOSE['attachments'])) {
if ($attrib['deleteicon']) {
@ -1380,27 +1384,38 @@ function rcmail_compose_attachment_list($attrib)
'alt' => rcube_label('delete')
));
}
else
else if (rcube_utils::get_boolean($attrib['textbuttons'])) {
$button = Q(rcube_label('delete'));
}
foreach ($COMPOSE['attachments'] as $id => $a_prop) {
if (empty($a_prop))
continue;
$out .= html::tag('li', array('id' => 'rcmfile'.$id, 'class' => rcmail_filetype2classname($a_prop['mimetype'], $a_prop['name'])),
$out .= html::tag('li',
array(
'id' => 'rcmfile'.$id,
'class' => rcmail_filetype2classname($a_prop['mimetype'], $a_prop['name']),
'onmouseover' => "rcube_webmail.long_subject_title_ex(this, 0)",
),
html::a(array(
'href' => "#delete",
'title' => rcube_label('delete'),
'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", JS_OBJECT_NAME, $id),
'class' => 'delete'),
$button) . Q($a_prop['name']));
'class' => 'delete'
),
$button
) . Q($a_prop['name'])
);
$jslist['rcmfile'.$id] = array('name' => $a_prop['name'], 'complete' => true, 'mimetype' => $a_prop['mimetype']);
$jslist['rcmfile'.$id] = array('name' => $a_prop['name'], 'complete' => true, 'mimetype' => $a_prop['mimetype']);
}
}
if ($attrib['deleteicon'])
$COMPOSE['deleteicon'] = $CONFIG['skin_path'] . $attrib['deleteicon'];
else if (rcube_utils::get_boolean($attrib['textbuttons']))
$COMPOSE['textbuttons'] = true;
if ($attrib['cancelicon'])
$OUTPUT->set_env('cancelicon', $CONFIG['skin_path'] . $attrib['cancelicon']);
if ($attrib['loadingicon'])

@ -473,8 +473,9 @@ $isHtml = (bool) get_input_value('_is_html', RCUBE_INPUT_POST);
$message_body = get_input_value('_message', RCUBE_INPUT_POST, TRUE, $message_charset);
if ($isHtml) {
$font = rcube_fontdefs($RCMAIL->config->get('default_font'));
$bstyle = $font && is_string($font) ? " style='font-family: $font'" : '';
$font_family = rcube_fontdefs($RCMAIL->config->get('default_font', 'Arial'));
$font_size = $RCMAIL->config->get('default_font_size');
$bstyle = ' style="font:' . $font_size . ' ' . $font_family . ';"';
// append doctype and html/body wrappers
$message_body = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">' .

@ -175,9 +175,9 @@ function rcmail_message_attachments($attrib)
$ol .= html::tag('li', null, Q(sprintf("%s (%s)", $filename, $size)));
}
else {
if (mb_strlen($filename) > 50) {
if ($attrib['maxlength'] && mb_strlen($filename) > $attrib['maxlength']) {
$title = $filename;
$filename = abbreviate_string($filename, 50);
$filename = abbreviate_string($filename, $attrib['maxlength']);
}
else {
$title = '';
@ -190,6 +190,7 @@ function rcmail_message_attachments($attrib)
'href' => $MESSAGE->get_part_url($attach_prop->mime_id, false),
'onclick' => sprintf('return %s.command(\'load-attachment\',\'%s\',this)',
JS_OBJECT_NAME, $attach_prop->mime_id),
'onmouseover' => $title ? '' : 'rcube_webmail.long_subject_title_ex(this, 0)',
'title' => Q($title),
), Q($filename));
$ol .= html::tag('li', array('class' => $class, 'id' => $id), $link);

@ -40,24 +40,21 @@ function rcmail_user_prefs_form($attrib)
$out = $form_start;
foreach ($SECTIONS[$CURR_SECTION]['blocks'] as $block) {
foreach ($SECTIONS[$CURR_SECTION]['blocks'] as $class => $block) {
if (!empty($block['options'])) {
$table = new html_table(array('cols' => 2));
foreach ($block['options'] as $option) {
if ($option['advanced'])
$table->set_row_attribs('advanced');
if (isset($option['title'])) {
$table->add('title', $option['title']);
$table->add(null, $option['content']);
$table->add(null, $option['content']);
}
else {
$table->add(array('colspan' => 2), $option['content']);
}
}
$out .= html::tag('fieldset', null, html::tag('legend', null, $block['name']) . $table->show($attrib));
$out .= html::tag('fieldset', $class, html::tag('legend', null, $block['name']) . $table->show($attrib));
}
else if (!empty($block['content'])) {
$out .= html::tag('fieldset', null, html::tag('legend', null, $block['name']) . $block['content']);

@ -158,6 +158,7 @@ function rcmail_user_prefs($current = null)
'main' => array('name' => Q(rcube_label('mainoptions'))),
'skin' => array('name' => Q(rcube_label('skin'))),
'browser' => array('name' => Q(rcube_label('browseroptions'))),
'advanced'=> array('name' => Q(rcube_label('advancedoptions'))),
);
// language selection
@ -367,6 +368,7 @@ function rcmail_user_prefs($current = null)
$blocks = array(
'main' => array('name' => Q(rcube_label('mainoptions'))),
'new_message' => array('name' => Q(rcube_label('newmessage'))),
'advanced' => array('name' => Q(rcube_label('advancedoptions'))),
);
// show config parameter for preview pane
@ -488,6 +490,7 @@ function rcmail_user_prefs($current = null)
case 'mailview':
$blocks = array(
'main' => array('name' => Q(rcube_label('mainoptions'))),
'advanced' => array('name' => Q(rcube_label('advancedoptions'))),
);
// show checkbox to open message view in new window
@ -543,7 +546,7 @@ function rcmail_user_prefs($current = null)
$field_id = 'rcmfd_default_charset';
$blocks['main']['options']['default_charset'] = array(
$blocks['advanced']['options']['default_charset'] = array(
'title' => html::label($field_id, Q(rcube_label('defaultcharset'))),
'content' => $RCMAIL->output->charset_selector(array(
'id' => $field_id, 'name' => '_default_charset', 'selected' => $config['default_charset']
@ -605,6 +608,7 @@ function rcmail_user_prefs($current = null)
'main' => array('name' => Q(rcube_label('mainoptions'))),
'sig' => array('name' => Q(rcube_label('signatureoptions'))),
'spellcheck' => array('name' => Q(rcube_label('spellcheckoptions'))),
'advanced' => array('name' => Q(rcube_label('advancedoptions'))),
);
// show checkbox to compose messages in a new window
@ -673,8 +677,7 @@ function rcmail_user_prefs($current = null)
$select->add(rcube_label('miscfolding'), 1);
$select->add(rcube_label('2047folding'), 2);
$blocks['main']['options']['mime_param_folding'] = array(
'advanced' => true,
$blocks['advanced']['options']['mime_param_folding'] = array(
'title' => html::label($field_id, Q(rcube_label('mimeparamfolding'))),
'content' => $select->show($config['mime_param_folding']),
);
@ -688,8 +691,7 @@ function rcmail_user_prefs($current = null)
$field_id = 'rcmfd_force_7bit';
$input = new html_checkbox(array('name' => '_force_7bit', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['force_7bit'] = array(
'advanced' => true,
$blocks['advanced']['options']['force_7bit'] = array(
'title' => html::label($field_id, Q(rcube_label('force7bit'))),
'content' => $input->show($config['force_7bit']?1:0),
);
@ -842,23 +844,28 @@ function rcmail_user_prefs($current = null)
continue 2;
}
// Default font size
$field_id = 'rcmfd_default_font_size';
$select_default_font_size = new html_select(array('name' => '_default_font_size', 'id' => $field_id));
$fontsizes = array('8pt', '10pt', '12pt', '14pt', '18pt', '24pt', '36pt');
foreach ($fontsizes as $size) {
$select_default_font_size->add($size, $size);
}
// Default font
$field_id = 'rcmfd_default_font';
$fonts = rcube_fontdefs();
$selected = $config['default_font'];
$select_default_font = new html_select(array('name' => '_default_font', 'id' => $field_id));
$select = '<select name="_default_font" id="'.$field_id.'">';
$select .= '<option value=""' . (!$selected ? ' selected="selected"' : '') . '>---</option>';
$fonts = rcube_fontdefs();
foreach ($fonts as $fname => $font) {
$select .= '<option value="'.$fname.'"'
. ($fname == $selected ? ' selected="selected"' : '')
. ' style=\'font-family: ' . $font . '\'>'
. Q($fname) . '</option>';
$select_default_font->add($fname, $fname);
}
$select .= '</select>';
$blocks['main']['options']['default_font'] = array(
'title' => html::label($field_id, Q(rcube_label('defaultfont'))),
'content' => $select
'content' => $select_default_font->show($RCMAIL->config->get('default_font', 1)) .
$select_default_font_size->show($RCMAIL->config->get('default_font_size', 1))
);
}
break;
@ -866,7 +873,8 @@ function rcmail_user_prefs($current = null)
// Addressbook config
case 'addressbook':
$blocks = array(
'main' => array('name' => Q(rcube_label('mainoptions'))),
'main' => array('name' => Q(rcube_label('mainoptions'))),
'advanced' => array('name' => Q(rcube_label('advancedoptions'))),
);
if (!isset($no_override['default_addressbook'])
@ -962,7 +970,8 @@ function rcmail_user_prefs($current = null)
// Special IMAP folders
case 'folders':
$blocks = array(
'main' => array('name' => Q(rcube_label('mainoptions'))),
'main' => array('name' => Q(rcube_label('mainoptions'))),
'advanced' => array('name' => Q(rcube_label('advancedoptions'))),
);
if (!isset($no_override['show_real_foldernames'])) {
@ -1043,6 +1052,7 @@ function rcmail_user_prefs($current = null)
$blocks = array(
'main' => array('name' => Q(rcube_label('mainoptions'))),
'maintenance' => array('name' => Q(rcube_label('maintenance'))),
'advanced' => array('name' => Q(rcube_label('advancedoptions'))),
);
if (!isset($no_override['read_when_deleted'])) {

@ -89,6 +89,7 @@ switch ($CURR_SECTION)
'reply_mode' => isset($_POST['_reply_mode']) ? intval($_POST['_reply_mode']) : 0,
'strip_existing_sig' => isset($_POST['_strip_existing_sig']),
'default_font' => get_input_value('_default_font', RCUBE_INPUT_POST),
'default_font_size' => get_input_value('_default_font_size', RCUBE_INPUT_POST),
'forward_attachment' => !empty($_POST['_forward_attachment']),
);

@ -1594,9 +1594,7 @@ input.from_address
height: 18px;
line-height: 16px;
font-size: 11px;
padding-left: 2px;
padding-top: 2px;
padding-right: 4px;
padding: 2px 2px 1px 2px;
border-bottom: 1px solid #EBEBEB;
white-space: nowrap;
overflow: hidden;
@ -1609,8 +1607,10 @@ input.from_address
text-indent: -5000px;
width: 17px;
height: 16px;
padding-bottom: 2px;
display: inline-block;
text-decoration: none;
vertical-align: middle;
}
#compose-attachments li img

@ -49,7 +49,7 @@
</div>
<roundcube:object name="messageHeaders" class="headers-table" cellspacing="0" cellpadding="2" addicon="/images/icons/silhouette.png" summary="Message headers" />
<roundcube:object name="messageFullHeaders" id="full-headers" />
<roundcube:object name="messageAttachments" id="attachment-list" />
<roundcube:object name="messageAttachments" id="attachment-list" maxlength="50" />
<roundcube:object name="messageObjects" id="message-objects" />
<roundcube:object name="messageBody" id="messagebody" />
</div>

@ -20,7 +20,7 @@
</div>
<roundcube:object name="messageHeaders" class="headers-table" cellspacing="0" cellpadding="2" addicon="/images/icons/silhouette.png" summary="Message headers" />
<roundcube:object name="messageFullHeaders" id="full-headers" />
<roundcube:object name="messageAttachments" id="attachment-list" />
<roundcube:object name="messageAttachments" id="attachment-list" maxlength="50" />
</div>
<roundcube:object name="messageObjects" id="message-objects" />

@ -387,3 +387,8 @@ a.deletebutton {
overflow: auto;
padding: 10px;
}
#import-box p,
#import-box .propform {
max-width: 50em;
}

@ -48,6 +48,26 @@
border-radius: 4px 4px 0 0;
}
#preferences-details fieldset.advanced legend {
position: relative;
display: block;
width: 100%;
cursor: pointer;
}
#preferences-details fieldset.advanced .propform {
display: none;
}
#preferences-details fieldset.advanced .advanced-toggle {
position: absolute;
top: 2px;
right: 6px;
text-decoration: none;
color: #666;
font-size: 11px;
}
#sections-table tbody td.section,
#settings-sections span.listitem a,
#settings-sections span.tablink a {

@ -18,7 +18,7 @@
<h2 class="boxtitle"><roundcube:label name="importcontacts" /></h2>
<div id="import-box" class="boxcontent">
<roundcube:object name="importstep" />
<roundcube:object name="importstep" class="propform" />
<br/>
<p class="formbuttons">
<roundcube:object name="importnav" class="button" />

@ -195,6 +195,19 @@ function rcube_mail_ui()
new rcube_splitter({ id:'prefviewsplitter', p1:'#sectionslist', p2:'#preferences-box',
orientation:'v', relative:true, start:266, min:180, size:12 }).init();
}
else if (rcmail.env.action == 'edit-prefs') {
$('<a href="#toggle">&#9660;</a>')
.addClass('advanced-toggle')
.appendTo('#preferences-details fieldset.advanced legend');
$('#preferences-details fieldset.advanced legend').click(function(e){
var collapsed = $(this).hasClass('collapsed'),
toggle = $('.advanced-toggle', this).html(collapsed ? '&#9650;' : '&#9660;');
$(this)
.toggleClass('collapsed')
.closest('fieldset').children('.propform').toggle()
}).addClass('collapsed')
}
}
/*** addressbook task ***/
else if (rcmail.env.task == 'addressbook') {

@ -17,4 +17,207 @@ class Framework_Browser extends PHPUnit_Framework_TestCase
$this->assertInstanceOf('rcube_browser', $object, "Class constructor");
}
/**
* @dataProvider browsers
*/
function test_browser($useragent, $opera, $chrome, $ie, $ns, $ns4, $khtml, $safari, $mz)
{
$object = $this->getBrowser($useragent);
$this->assertEquals($opera, $object->opera, 'Check for Opera failed');
$this->assertEquals($chrome, $object->chrome, 'Check for Chrome failed');
$this->assertEquals($ie, $object->ie, 'Check for IE failed');
$this->assertEquals($ns, $object->ns, 'Check for NS failed');
$this->assertEquals($ns4, $object->ns4, 'Check for NS4 failed');
$this->assertEquals($khtml, $object->khtml, 'Check for khtml failed');
$this->assertEquals($safari, $object->safari, 'Check for Safari failed');
$this->assertEquals($mz, $object->mz, 'Check for MZ failed');
}
/**
* @dataProvider os
*/
function test_os($useragent, $windows, $linux, $unix, $mac)
{
$object = $this->getBrowser($useragent);
$this->assertEquals($windows, $object->win, 'Check Result of Windows');
$this->assertEquals($linux, $object->linux, 'Check Result of Linux');
$this->assertEquals($mac, $object->mac, 'Check Result of Mac');
$this->assertEquals($unix, $object->unix, 'Check Result of Unix');
}
/**
* @dataProvider versions
*/
function test_version($useragent, $version)
{
$object = $this->getBrowser($useragent);
$this->assertEquals($version, $object->ver);
}
/**
* @dataProvider dom
*/
function test_dom($useragent, $dom)
{
$object = $this->getBrowser($useragent);
$this->assertEquals($dom, $object->dom);
}
/**
* @dataProvider pngalpha
*/
function test_pngalpha($useragent, $pngalpha)
{
$object = $this->getBrowser($useragent);
$this->assertEquals($pngalpha, $object->pngalpha);
}
/**
* @dataProvider imgdata
*/
function test_imgdata($useragent, $imgdata)
{
$object = $this->getBrowser($useragent);
$this->assertEquals($imgdata, $object->imgdata);
}
function versions()
{
return $this->extractDataSet(array('version'));
}
function pngalpha()
{
return $this->extractDataSet(array('canPNGALPHA'));
}
function imgdata()
{
return $this->extractDataSet(array('canIMGDATA'));
}
private function extractDataSet($keys)
{
$keys = array_merge(array('useragent'), $keys);
$browser = $this->useragents();
$extracted = array();
foreach ($browser as $label => $data) {
foreach($keys as $key) {
$extracted[$data['useragent']][] = $data[$key];
}
}
return $extracted;
}
function lang()
{
return $this->extractDataSet(array('lang'));
}
function dom()
{
return $this->extractDataSet(array('hasDOM'));
}
function browsers()
{
return $this->extractDataSet(array('isOpera','isChrome','isIE','isNS','isNS4','isKHTML','isSafari','isMZ'));
}
function useragents()
{
return array(
'WIN: Mozilla Firefox ' => array(
'useragent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1',
'version' => '1.8', //Version
'isWin' => true, //isWindows
'isLinux' => false,
'isMac' => false, //isMac
'isUnix' => false, //isUnix
'isOpera' => false, //isOpera
'isChrome' => false, //isChrome
'isIE' => false, //isIE
'isNS' => false, //isNS
'isNS4' => false, //isNS4
'isKHTML' => false, //isKHTML
'isSafari' => false, //isSafari
'isMZ' => true, //isMZ
'lang' => 'en-US', //lang
'hasDOM' => true, //hasDOM
'canPNGALPHA' => true, //canPNGALPHA
'canIMGDATA' => true, //canIMGDATA
),
'LINUX: Bon Echo ' => array(
'useragent' => 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.1) Gecko/20070222 BonEcho/2.0.0.1',
'version' => '1.8', //Version
'isWin' => false, //isWindows
'isLinux' => true,
'isMac' => false, //isMac
'isUnix' => false, //isUnix
'isOpera' => false, //isOpera
'isChrome' => false, //isChrome
'isIE' => false, //isIE
'isNS' => false, //isNS
'isNS4' => false, //isNS4
'isKHTML' => false, //isKHTML
'isSafari' => false, //isSafari
'isMZ' => true, //isMZ
'lang' => 'en-US', //lang
'hasDOM' => true, //hasDOM
'canPNGALPHA' => true, //canPNGALPHA
'canIMGDATA' => true, //canIMGDATA
),
'Chrome Mac' => array(
'useragent' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.461.0 Safari/534.3',
'version' => '5', //Version
'isWin' => false, //isWindows
'isLinux' => false,
'isMac' => true, //isMac
'isUnix' => false, //isUnix
'isOpera' => false, //isOpera
'isChrome' => true, //isChrome
'isIE' => false, //isIE
'isNS' => false, //isNS
'isNS4' => false, //isNS4
'isKHTML' => true, //isKHTML
'isSafari' => false, //isSafari
'isMZ' => false, //isMZ
'lang' => 'en-US', //lang
'hasDOM' => false, //hasDOM
'canPNGALPHA' => false, //canPNGALPHA
'canIMGDATA' => true, //canIMGDATA
),
);
}
function os()
{
return $this->extractDataSet(array('isWin','isLinux','isUnix','isMac'));
}
/**
* @param string $useragent
* @return rcube_browser
*/
private function getBrowser($useragent)
{
/** @var $object rcube_browser */
$_SERVER['HTTP_USER_AGENT'] = $useragent;
$object = new rcube_browser();
return $object;
}
}

Loading…
Cancel
Save