summaryrefslogtreecommitdiff
path: root/program/steps
diff options
context:
space:
mode:
Diffstat (limited to 'program/steps')
-rw-r--r--program/steps/addressbook/delete.inc40
-rw-r--r--program/steps/addressbook/edit.inc6
-rw-r--r--program/steps/addressbook/export.inc4
-rw-r--r--program/steps/addressbook/func.inc68
-rw-r--r--program/steps/addressbook/move.inc24
-rw-r--r--program/steps/addressbook/photo.inc8
-rw-r--r--program/steps/addressbook/save.inc39
-rw-r--r--program/steps/addressbook/show.inc7
-rw-r--r--program/steps/addressbook/undo.inc3
-rw-r--r--program/steps/mail/attachments.inc25
-rw-r--r--program/steps/mail/autocomplete.inc18
-rw-r--r--program/steps/mail/check_recent.inc9
-rw-r--r--program/steps/mail/compose.inc59
-rw-r--r--program/steps/mail/copy.inc16
-rw-r--r--program/steps/mail/folders.inc4
-rw-r--r--program/steps/mail/func.inc238
-rw-r--r--program/steps/mail/get.inc2
-rw-r--r--program/steps/mail/list.inc106
-rw-r--r--program/steps/mail/list_contacts.inc2
-rw-r--r--program/steps/mail/move_del.inc17
-rw-r--r--program/steps/mail/search.inc26
-rw-r--r--program/steps/mail/search_contacts.inc2
-rw-r--r--program/steps/mail/sendmail.inc62
-rw-r--r--program/steps/mail/show.inc22
-rw-r--r--program/steps/settings/about.inc6
-rw-r--r--program/steps/settings/delete_identity.inc55
-rw-r--r--program/steps/settings/edit_folder.inc49
-rw-r--r--program/steps/settings/edit_identity.inc16
-rw-r--r--program/steps/settings/edit_response.inc2
-rw-r--r--program/steps/settings/folders.inc198
-rw-r--r--program/steps/settings/func.inc35
-rw-r--r--program/steps/settings/identities.inc22
-rw-r--r--program/steps/settings/responses.inc10
-rw-r--r--program/steps/settings/save_folder.inc25
-rw-r--r--program/steps/settings/save_identity.inc34
-rw-r--r--program/steps/settings/save_prefs.inc1
-rw-r--r--program/steps/settings/upload.inc144
-rw-r--r--program/steps/utils/html2text.inc5
-rw-r--r--program/steps/utils/spell_html.inc36
-rw-r--r--program/steps/utils/text2html.inc33
40 files changed, 924 insertions, 554 deletions
diff --git a/program/steps/addressbook/delete.inc b/program/steps/addressbook/delete.inc
index 3d57d7074..f5b8e4eb5 100644
--- a/program/steps/addressbook/delete.inc
+++ b/program/steps/addressbook/delete.inc
@@ -77,6 +77,17 @@ foreach ($cids as $source => $cid) {
}
}
+if (!empty($_SESSION['contact_undo'])) {
+ $_SESSION['contact_undo']['ts'] = time();
+ $msg = html::span(null, $RCMAIL->gettext('contactdeleted'))
+ . ' ' . html::a(array('onclick' => rcmail_output::JS_OBJECT_NAME.".command('undo', '', this)"), $RCMAIL->gettext('undo'));
+
+ $OUTPUT->show_message($msg, 'confirmation', null, true, $undo_time);
+}
+else {
+ $OUTPUT->show_message('contactdeleted', 'confirmation');
+}
+
$page = isset($_SESSION['page']) ? $_SESSION['page'] : 1;
// update saved search after data changed
@@ -87,8 +98,13 @@ if (($records = rcmail_search_update(true)) !== false) {
$result = new rcube_result_set($count, $first);
$pages = ceil((count($records) + $delcnt) / $PAGE_SIZE);
+ // last page and it's empty, display previous one
+ if ($result->count && $result->count <= ($PAGE_SIZE * ($page - 1))) {
+ $OUTPUT->command('list_page', 'prev');
+ $rowcount = $RCMAIL->gettext('loading');
+ }
// get records from the next page to add to the list
- if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) {
+ else if ($pages > 1 && $page < $pages) {
// sort the records
ksort($records, SORT_LOCALE_STRING);
@@ -110,10 +126,15 @@ if (($records = rcmail_search_update(true)) !== false) {
else {
// count contacts for this user
$result = $CONTACTS->count();
+ $pages = ceil(($result->count + $delcnt) / $PAGE_SIZE);
+ // last page and it's empty, display previous one
+ if ($result->count && $result->count <= ($PAGE_SIZE * ($page - 1))) {
+ $OUTPUT->command('list_page', 'prev');
+ $rowcount = $RCMAIL->gettext('loading');
+ }
// get records from the next page to add to the list
- $pages = ceil(($result->count + $delcnt) / $PAGE_SIZE);
- if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) {
+ else if ($pages > 1 && $page < $pages) {
$CONTACTS->set_page($page);
$records = $CONTACTS->list_records(null, -$delcnt);
}
@@ -121,18 +142,7 @@ else {
// update message count display
$OUTPUT->set_env('pagecount', ceil($result->count / $PAGE_SIZE));
-$OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result));
-
-if (!empty($_SESSION['contact_undo'])) {
- $_SESSION['contact_undo']['ts'] = time();
- $msg = html::span(null, $RCMAIL->gettext('contactdeleted'))
- . ' ' . html::a(array('onclick' => rcmail_output::JS_OBJECT_NAME.".command('undo', '', this)"), $RCMAIL->gettext('undo'));
-
- $OUTPUT->show_message($msg, 'confirmation', null, true, $undo_time);
-}
-else {
- $OUTPUT->show_message('contactdeleted', 'confirmation');
-}
+$OUTPUT->command('set_rowcount', $rowcount ? $rowcount : rcmail_get_rowcount_text($result));
// add new rows from next page (if any)
if (!empty($records)) {
diff --git a/program/steps/addressbook/edit.inc b/program/steps/addressbook/edit.inc
index 3bbbfccdf..a7def586d 100644
--- a/program/steps/addressbook/edit.inc
+++ b/program/steps/addressbook/edit.inc
@@ -69,6 +69,8 @@ $OUTPUT->add_handlers(array(
'filedroparea' => 'rcmail_photo_drop_area',
));
+$OUTPUT->set_pagetitle($RCMAIL->gettext(($RCMAIL->action == 'add' ? 'addcontact' : 'editcontact')));
+
if ($RCMAIL->action == 'add' && $OUTPUT->template_exists('contactadd')) {
$OUTPUT->send('contactadd');
}
@@ -98,12 +100,15 @@ function rcmail_get_edit_record()
function rcmail_contact_edithead($attrib)
{
+ global $RCMAIL;
+
// check if we have a valid result
$record = rcmail_get_edit_record();
$i_size = !empty($attrib['size']) ? $attrib['size'] : 20;
$form = array(
'head' => array(
+ 'name' => $RCMAIL->gettext('contactnameandorg'),
'content' => array(
'prefix' => array('size' => $i_size),
'firstname' => array('size' => $i_size, 'visible' => true),
@@ -253,6 +258,7 @@ function get_form_tags($attrib)
if ($RCMAIL->action == 'edit')
$hiddenfields->add(array('name' => '_source', 'value' => $SOURCE_ID));
$hiddenfields->add(array('name' => '_gid', 'value' => $CONTACTS->group_id));
+ $hiddenfields->add(array('name' => '_search', 'value' => rcube_utils::get_input_value('_search', rcube_utils::INPUT_GPC)));
if (($result = $CONTACTS->get_result()) && ($record = $result->first()))
$hiddenfields->add(array('name' => '_cid', 'value' => $record['ID']));
diff --git a/program/steps/addressbook/export.inc b/program/steps/addressbook/export.inc
index 2b45e5cd1..a6d3af978 100644
--- a/program/steps/addressbook/export.inc
+++ b/program/steps/addressbook/export.inc
@@ -103,7 +103,9 @@ header('Content-Type: text/x-vcard; charset='.RCUBE_CHARSET);
header('Content-Disposition: attachment; filename="contacts.vcf"');
while ($result && ($row = $result->next())) {
- prepare_for_export($row, $CONTACTS);
+ if ($CONTACTS) {
+ prepare_for_export($row, $CONTACTS);
+ }
// fix folding and end-of-line chars
$row['vcard'] = preg_replace('/\r|\n\s+/', '', $row['vcard']);
diff --git a/program/steps/addressbook/func.inc b/program/steps/addressbook/func.inc
index be0dd2a33..2c22d5a47 100644
--- a/program/steps/addressbook/func.inc
+++ b/program/steps/addressbook/func.inc
@@ -81,7 +81,6 @@ if (!$RCMAIL->action && !$OUTPUT->ajax_call) {
$OUTPUT->set_env('search_mods', $search_mods);
$OUTPUT->set_env('address_sources', $js_list);
$OUTPUT->set_env('writable_source', $writeable);
- $OUTPUT->set_env('compose_extwin', $RCMAIL->config->get('compose_extwin',false));
$OUTPUT->set_pagetitle($RCMAIL->gettext('addressbook'));
$_SESSION['addressbooks_count'] = $count;
@@ -112,7 +111,7 @@ if ($undo = $_SESSION['contact_undo']) {
// register UI objects
$OUTPUT->add_handlers(array(
'directorylist' => 'rcmail_directory_list',
-// 'groupslist' => 'rcmail_contact_groups',
+ 'savedsearchlist' => 'rcmail_savedsearch_list',
'addresslist' => 'rcmail_contacts_list',
'addresslisttitle' => 'rcmail_contacts_list_title',
'addressframe' => 'rcmail_contact_frame',
@@ -251,6 +250,28 @@ function rcmail_directory_list($attrib)
$out .= '</li>';
}
+ $OUTPUT->set_env('contactgroups', $jsdata);
+ $OUTPUT->set_env('collapsed_abooks', (string)$RCMAIL->config->get('collapsed_abooks',''));
+ $OUTPUT->add_gui_object('folderlist', $attrib['id']);
+ $OUTPUT->include_script('treelist.js');
+
+ // add some labels to client
+ $OUTPUT->add_label('deletegroupconfirm', 'groupdeleting', 'addingmember', 'removingmember',
+ 'newgroup', 'grouprename', 'searchsave', 'namex', 'save'
+ );
+
+ return html::tag('ul', $attrib, $out, html::$common_attrib);
+}
+
+
+function rcmail_savedsearch_list($attrib)
+{
+ global $RCMAIL, $OUTPUT;
+
+ if (!$attrib['id'])
+ $attrib['id'] = 'rcmsavedsearchlist';
+
+ $out = '';
$line_templ = html::tag('li', array(
'id' => 'rcmli%s', 'class' => '%s'),
html::a(array('href' => '#', 'rel' => 'S%s',
@@ -263,26 +284,19 @@ function rcmail_directory_list($attrib)
$js_id = rcube::JQ($id);
// set class name(s)
- $class_name = 'contactsearch';
- if ($current === $id)
- $class_name .= ' selected';
- if ($source['class_name'])
- $class_name .= ' ' . $source['class_name'];
+ $classes = array('contactsearch');
+ if (!empty($source['class_name']))
+ $classes[] = $source['class_name'];
$out .= sprintf($line_templ,
rcube_utils::html_identifier('S'.$id, true),
- $class_name,
+ join(' ', $classes),
$id,
- $js_id, (!empty($source['name']) ? rcube::Q($source['name']) : rcube::Q($id)));
+ $js_id, (!empty($source['name']) ? rcube::Q($source['name']) : rcube::Q($id))
+ );
}
- $OUTPUT->set_env('contactgroups', $jsdata);
- $OUTPUT->set_env('collapsed_abooks', (string)$RCMAIL->config->get('collapsed_abooks',''));
- $OUTPUT->add_gui_object('folderlist', $attrib['id']);
- $OUTPUT->include_script('treelist.js');
-
- // add some labels to client
- $OUTPUT->add_label('deletegroupconfirm', 'groupdeleting', 'addingmember', 'removingmember');
+ $OUTPUT->add_gui_object('savedsearchlist', $attrib['id']);
return html::tag('ul', $attrib, $out, html::$common_attrib);
}
@@ -395,7 +409,7 @@ function rcmail_js_contacts_list($result, $prefix='')
), '&raquo;');
}
else
- $val = '&nbsp;';
+ $val = '';
break;
default:
@@ -422,7 +436,7 @@ function rcmail_contacts_list_title($attrib)
unset($attrib['name']);
$OUTPUT->add_gui_object('addresslist_title', $attrib['id']);
- $OUTPUT->add_label('contacts');
+ $OUTPUT->add_label('contacts','uponelevel');
return html::tag($attrib['tag'], $attrib, $RCMAIL->gettext($attrib['label']), html::$common_attrib);
}
@@ -518,7 +532,7 @@ function rcmail_contact_form($form, $record, $attrib = null)
foreach ($coltypes as $col => $prop) {
if ($prop['subtypes']) {
$subtype_names = array_map('rcmail_get_type_label', $prop['subtypes']);
- $select_subtype = new html_select(array('name' => '_subtype_'.$col.'[]', 'class' => 'contactselectsubtype'));
+ $select_subtype = new html_select(array('name' => '_subtype_'.$col.'[]', 'class' => 'contactselectsubtype', 'title' => $prop['label'] . ' ' . $RCMAIL->gettext('type')));
$select_subtype->add($subtype_names, $prop['subtypes']);
$coltypes[$col]['subtypes_select'] = $select_subtype->show();
}
@@ -607,7 +621,7 @@ function rcmail_contact_form($form, $record, $attrib = null)
// prepare subtype selector in edit mode
if ($edit_mode && is_array($colprop['subtypes'])) {
$subtype_names = array_map('rcmail_get_type_label', $colprop['subtypes']);
- $select_subtype = new html_select(array('name' => '_subtype_'.$col.'[]', 'class' => 'contactselectsubtype'));
+ $select_subtype = new html_select(array('name' => '_subtype_'.$col.'[]', 'class' => 'contactselectsubtype', 'title' => $colprop['label'] . ' ' . $RCMAIL->gettext('type')));
$select_subtype->add($subtype_names, $colprop['subtypes']);
}
else
@@ -649,6 +663,8 @@ function rcmail_contact_form($form, $record, $attrib = null)
if ($subtypes[$i])
$subtype = $subtypes[$i];
+ $colprop['id'] = 'ff_' . $col . intval($coltypes[$field]['count']);
+
// render composite field
if ($colprop['type'] == 'composite') {
$composite = array(); $j = 0;
@@ -714,7 +730,7 @@ function rcmail_contact_form($form, $record, $attrib = null)
// display row with label
if ($label) {
$rows .= html::div('row',
- html::div('contactfieldlabel label', $select_subtype ? $select_subtype->show($subtype) : rcube::Q($label)) .
+ html::div('contactfieldlabel label', $select_subtype ? $select_subtype->show($subtype) : html::label($colprop['id'], rcube::Q($label))) .
html::div('contactfieldcontent '.$colprop['type'], $val));
}
else // row without label
@@ -800,11 +816,15 @@ function rcmail_contact_photo($attrib)
}
$photo_img = $RCMAIL->url($url);
}
- else
+ else {
$ff_value = '-del-'; // will disable delete-photo action
+ }
- $img = html::img(array('src' => $photo_img, 'border' => 1, 'alt' => ''));
- $content = html::div($attrib, $img);
+ $content = html::div($attrib, html::img(array(
+ 'src' => $photo_img,
+ 'alt' => $RCMAIL->gettext('contactphoto'),
+ 'onerror' => 'this.src = rcmail.env.photo_placeholder',
+ )));
if ($CONTACT_COLTYPES['photo'] && ($RCMAIL->action == 'edit' || $RCMAIL->action == 'add')) {
$RCMAIL->output->add_gui_object('contactphoto', $attrib['id']);
diff --git a/program/steps/addressbook/move.inc b/program/steps/addressbook/move.inc
index 7a730af77..e83276523 100644
--- a/program/steps/addressbook/move.inc
+++ b/program/steps/addressbook/move.inc
@@ -142,10 +142,6 @@ foreach ($cids as $source => $source_cids) {
}
if (!$deleted || $deleted != $all) {
- // update saved search after data changed
- if ($deleted) {
- rcmail_search_update();
- }
$OUTPUT->command('list_contacts');
}
else {
@@ -157,8 +153,13 @@ else {
$result = new rcube_result_set($count, $first);
$pages = ceil((count($records) + $delcnt) / $PAGE_SIZE);
+ // last page and it's empty, display previous one
+ if ($result->count && $result->count <= ($PAGE_SIZE * ($page - 1))) {
+ $OUTPUT->command('list_page', 'prev');
+ $rowcount = $RCMAIL->gettext('loading');
+ }
// get records from the next page to add to the list
- if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) {
+ else if ($pages > 1 && $page < $pages) {
// sort the records
ksort($records, SORT_LOCALE_STRING);
@@ -180,10 +181,15 @@ else {
else {
// count contacts for this user
$result = $CONTACTS->count();
- // get records from the next page to add to the list
- $pages = ceil(($result->count + $deleted) / $PAGE_SIZE);
+ $pages = ceil(($result->count + $deleted) / $PAGE_SIZE);
- if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) {
+ // last page and it's empty, display previous one
+ if ($result->count && $result->count <= ($PAGE_SIZE * ($page - 1))) {
+ $OUTPUT->command('list_page', 'prev');
+ $rowcount = $RCMAIL->gettext('loading');
+ }
+ // get records from the next page to add to the list
+ else if ($pages > 1 && $page < $pages) {
$CONTACTS->set_page($page);
$records = $CONTACTS->list_records(null, -$deleted);
}
@@ -191,7 +197,7 @@ else {
// update message count display
$OUTPUT->set_env('pagecount', ceil($result->count / $PAGE_SIZE));
- $OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result));
+ $OUTPUT->command('set_rowcount', $rowcount ? $rowcount : rcmail_get_rowcount_text($result));
// add new rows from next page (if any)
if (!empty($records)) {
diff --git a/program/steps/addressbook/photo.inc b/program/steps/addressbook/photo.inc
index 482185735..30d09ffcc 100644
--- a/program/steps/addressbook/photo.inc
+++ b/program/steps/addressbook/photo.inc
@@ -72,8 +72,12 @@ $plugin = $RCMAIL->plugins->exec_hook('contact_photo',
if ($plugin['url']) {
$RCMAIL->output->redirect($plugin['url']);
}
-else {
- $data = $plugin['data'];
+
+$data = $plugin['data'];
+
+// detect if photo data is an URL
+if (strlen($data) < 1024 && filter_var($data, FILTER_VALIDATE_URL)) {
+ $RCMAIL->output->redirect($data);
}
// deliver alt image
diff --git a/program/steps/addressbook/save.inc b/program/steps/addressbook/save.inc
index 94556f96b..4f30fd4b7 100644
--- a/program/steps/addressbook/save.inc
+++ b/program/steps/addressbook/save.inc
@@ -148,6 +148,15 @@ if (!empty($cid)) {
$result = $plugin['result'];
if ($result) {
+ // show confirmation
+ $OUTPUT->show_message('successfullysaved', 'confirmation', null, false);
+
+ // in search mode, just reload the list (#1490015)
+ if ($_REQUEST['_search']) {
+ $OUTPUT->command('parent.command', 'list');
+ $OUTPUT->send('iframe');
+ }
+
// LDAP DN change
if (is_string($result) && strlen($result)>1) {
$newcid = $result;
@@ -165,11 +174,13 @@ if (!empty($cid)) {
$a_js_cols[] = rcube::Q((string)$record[$col]);
}
+ // performance: unset some big data items we don't need here
+ $record = array_intersect_key($record, array('ID' => 1,'email' => 1,'name' => 1));
+ $record['_type'] = 'person';
+
// update the changed col in list
$OUTPUT->command('parent.update_contact_row', $cid, $a_js_cols, $newcid, $source, $record);
- // show confirmation
- $OUTPUT->show_message('successfullysaved', 'confirmation', null, false);
$RCMAIL->overwrite_action('show');
}
else {
@@ -224,29 +235,13 @@ else {
$CONTACTS->add_to_group($plugin['group_id'], $plugin['ids']);
}
}
- else {
- $counts = $CONTACTS->count();
- }
-
- if ((string)$source === (string)$orig_source) {
- // add contact row or jump to the page where it should appear
- $CONTACTS->reset();
- $result = $CONTACTS->search($CONTACTS->primary_key, $insert_id);
-
- rcmail_js_contacts_list($result, 'parent.');
- $OUTPUT->command('parent.contact_list.select', rcube_utils::html_identifier($insert_id));
-
- // update record count display
- $CONTACTS->reset();
- $OUTPUT->command('parent.set_rowcount', rcmail_get_rowcount_text($counts));
- }
- else {
- // re-set iframe
- $OUTPUT->command('parent.show_contentframe');
- }
// show confirmation
$OUTPUT->show_message('successfullysaved', 'confirmation', null, false);
+
+ $OUTPUT->command('parent.set_rowcount', $RCMAIL->gettext('loading'));
+ $OUTPUT->command('parent.list_contacts');
+
$OUTPUT->send('iframe');
}
else {
diff --git a/program/steps/addressbook/show.inc b/program/steps/addressbook/show.inc
index f4224a3e2..5835ce7e5 100644
--- a/program/steps/addressbook/show.inc
+++ b/program/steps/addressbook/show.inc
@@ -32,7 +32,11 @@ $SOURCE_ID = $source;
if ($cid && ($record = $CONTACTS->get_record($cid, true))) {
$OUTPUT->set_env('readonly', $CONTACTS->readonly || $record['readonly']);
$OUTPUT->set_env('cid', $record['ID']);
- $OUTPUT->set_env('compose_extwin', $RCMAIL->config->get('compose_extwin',false));
+
+ // remember current search request ID (if in search mode)
+ if ($search = rcube_utils::get_input_value('_search', rcube_utils::INPUT_GET)) {
+ $OUTPUT->set_env('search_request', $search);
+ }
}
// get address book name (for display)
@@ -60,6 +64,7 @@ function rcmail_contact_head($attrib)
$form = array(
'head' => array( // section 'head' is magic!
+ 'name' => $RCMAIL->gettext('contactnameandorg'),
'content' => array(
'prefix' => array('type' => 'text'),
'firstname' => array('type' => 'text'),
diff --git a/program/steps/addressbook/undo.inc b/program/steps/addressbook/undo.inc
index ec3feb9c0..91547b765 100644
--- a/program/steps/addressbook/undo.inc
+++ b/program/steps/addressbook/undo.inc
@@ -45,9 +45,6 @@ foreach ((array)$undo['data'] as $source => $cid) {
}
}
-// update saved search after data changed
-rcmail_search_update();
-
$RCMAIL->session->remove('contact_undo');
$OUTPUT->show_message('contactrestored', 'confirmation');
diff --git a/program/steps/mail/attachments.inc b/program/steps/mail/attachments.inc
index 85bc36cac..5eaa655e3 100644
--- a/program/steps/mail/attachments.inc
+++ b/program/steps/mail/attachments.inc
@@ -38,7 +38,7 @@ if (!$COMPOSE) {
// remove an attachment
-if ($RCMAIL->action=='remove-attachment') {
+if ($RCMAIL->action == 'remove-attachment') {
$id = 'undefined';
if (preg_match('/^rcmfile(\w+)$/', $_POST['_file'], $regs)) {
@@ -60,32 +60,14 @@ if ($RCMAIL->action=='remove-attachment') {
exit;
}
-if ($RCMAIL->action=='display-attachment') {
+if ($RCMAIL->action == 'display-attachment') {
$id = 'undefined';
if (preg_match('/^rcmfile(\w+)$/', $_GET['_file'], $regs)) {
$id = $regs[1];
}
- if ($attachment = $COMPOSE['attachments'][$id]) {
- $attachment = $RCMAIL->plugins->exec_hook('attachment_display', $attachment);
- }
-
- if ($attachment['status']) {
- if (empty($attachment['size'])) {
- $attachment['size'] = $attachment['data'] ? strlen($attachment['data']) : @filesize($attachment['path']);
- }
-
- header('Content-Type: ' . $attachment['mimetype']);
- header('Content-Length: ' . $attachment['size']);
-
- if ($attachment['data']) {
- echo $attachment['data'];
- }
- else if ($attachment['path']) {
- readfile($attachment['path']);
- }
- }
+ $RCMAIL->display_uploaded_file($COMPOSE['attachments'][$id]);
exit;
}
@@ -139,6 +121,7 @@ if (is_array($_FILES['_attachments']['tmp_name'])) {
'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", rcmail_output::JS_OBJECT_NAME, $id),
'title' => $RCMAIL->gettext('delete'),
'class' => 'delete',
+ 'aria-label' => $RCMAIL->gettext('delete') . ' ' . $attachment['name'],
), $button);
$content .= rcube::Q($attachment['name']);
diff --git a/program/steps/mail/autocomplete.inc b/program/steps/mail/autocomplete.inc
index 71b337a53..30b8f2299 100644
--- a/program/steps/mail/autocomplete.inc
+++ b/program/steps/mail/autocomplete.inc
@@ -90,8 +90,14 @@ if (!empty($book_types) && strlen($search)) {
// skip duplicates
if (!in_array($contact, $contacts)) {
- $contacts[] = array('name' => $contact, 'type' => $sql_arr['_type']);
- $sort_keys[] = sprintf('%s %03d', $sql_arr['name'] , $idx++);
+ $contact = array('name' => $contact, 'type' => $sql_arr['_type']);
+
+ if (($display = rcube_addressbook::compose_search_name($sql_arr, $email, $name)) && $display != $contact['name']) {
+ $contact['display'] = $display;
+ }
+
+ $contacts[] = $contact;
+ $sort_keys[] = sprintf('%s %03d', $contact['display'] ?: $name, $idx++);
if (count($contacts) >= $MAXNUM) {
break 2;
@@ -118,7 +124,13 @@ if (!empty($book_types) && strlen($search)) {
if ($group_prop['email']) {
$idx = 0;
foreach ((array)$group_prop['email'] as $email) {
- $contacts[] = array('name' => format_email_recipient($email, $group['name']), 'type' => 'group');
+ $contacts[] = array(
+ 'name' => format_email_recipient($email, $group['name']),
+ 'email' => $email,
+ 'type' => 'group',
+ 'id' => $group['ID'],
+ 'source' => $id,
+ );
$sort_keys[] = sprintf('%s %03d', $group['name'] , $idx++);
if (count($contacts) >= $MAXNUM) {
diff --git a/program/steps/mail/check_recent.inc b/program/steps/mail/check_recent.inc
index cfdcda605..b95819415 100644
--- a/program/steps/mail/check_recent.inc
+++ b/program/steps/mail/check_recent.inc
@@ -77,15 +77,16 @@ foreach ($a_mailboxes as $mbox_name) {
if ($search_request && isset($_SESSION['search'])) {
unset($search_request); // only do this once
$_SESSION['search'] = $RCMAIL->storage->refresh_search();
- if ($_SESSION['search'][1]->multi)
+ if ($_SESSION['search'][1]->multi) {
$mbox_name = '';
+ }
}
if (!empty($_POST['_quota'])) {
- $OUTPUT->command('set_quota', $RCMAIL->quota_content());
+ $OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $mbox_name));
}
- $OUTPUT->set_env('exists', $RCMAIL->storage->count($mbox_name, 'EXISTS'));
+ $OUTPUT->set_env('exists', $RCMAIL->storage->count($mbox_name, 'EXISTS', true));
// "No-list" mode, don't get messages
if (empty($_POST['_list'])) {
@@ -146,7 +147,7 @@ foreach ($a_mailboxes as $mbox_name) {
// set trash folder state
if ($mbox_name === $trash) {
- $OUTPUT->command('set_trash_count', $RCMAIL->storage->count($mbox_name, 'EXISTS'));
+ $OUTPUT->command('set_trash_count', $RCMAIL->storage->count($mbox_name, 'EXISTS', true));
}
}
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index 2b717d673..1770a1bcb 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -80,7 +80,7 @@ if (!is_array($COMPOSE)) {
$OUTPUT->add_label('nosubject', 'nosenderwarning', 'norecipientwarning', 'nosubjectwarning', 'cancel',
'nobodywarning', 'notsentwarning', 'notuploadedwarning', 'savingmessage', 'sendingmessage',
'messagesaved', 'converting', 'editorwarning', 'searching', 'uploading', 'uploadingmany',
- 'fileuploaderror', 'sendmessage', 'savenewresponse', 'responsename', 'responsetext', 'save',
+ 'fileuploaderror', 'sendmessage', 'newresponse', 'responsename', 'responsetext', 'save',
'savingresponse', 'restoresavedcomposedata', 'restoremessage', 'delete', 'restore', 'ignore',
'selectimportfile');
@@ -91,6 +91,7 @@ $OUTPUT->set_env('session_id', session_id());
$OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder());
$OUTPUT->set_env('top_posting', intval($RCMAIL->config->get('reply_mode')) > 0);
$OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ',')));
+$OUTPUT->set_env('save_localstorage', (bool)$RCMAIL->config->get('compose_save_localstorage'));
$drafts_mbox = $RCMAIL->config->get('drafts_mbox');
$config_show_sig = $RCMAIL->config->get('show_sig', 1);
@@ -280,6 +281,7 @@ $from_email = @mb_strtolower($MESSAGE->compose['from_email']);
foreach ($parts as $header) {
$fvalue = '';
$decode_header = true;
+ $charset = $MESSAGE->headers->charset;
// we have a set of recipients stored is session
if ($header == 'to' && ($mailto_id = $COMPOSE['param']['mailto'])
@@ -287,16 +289,19 @@ foreach ($parts as $header) {
) {
$fvalue = urldecode($_SESSION['mailto'][$mailto_id]);
$decode_header = false;
+ $charset = $RCMAIL->output->charset;
// make session to not grow up too much
unset($_SESSION['mailto'][$mailto_id]);
$COMPOSE['param']['to'] = $fvalue;
}
else if (!empty($_POST['_'.$header])) {
- $fvalue = rcube_utils::get_input_value('_'.$header, rcube_utils::INPUT_POST, TRUE);
+ $fvalue = rcube_utils::get_input_value('_'.$header, rcube_utils::INPUT_POST, TRUE);
+ $charset = $RCMAIL->output->charset;
}
else if (!empty($COMPOSE['param'][$header])) {
- $fvalue = $COMPOSE['param'][$header];
+ $fvalue = $COMPOSE['param'][$header];
+ $charset = $RCMAIL->output->charset;
}
else if ($compose_mode == RCUBE_COMPOSE_REPLY) {
// get recipent address(es) out of the message headers
@@ -337,9 +342,9 @@ foreach ($parts as $header) {
// When To: and Reply-To: are the same we add From: address to the list (#1489037)
if ($v = $MESSAGE->headers->from) {
- $from = rcube_mime::decode_address_list($v, null, false, $MESSAGE->headers->charset, true);
- $to = rcube_mime::decode_address_list($MESSAGE->headers->to, null, false, $MESSAGE->headers->charset, true);
- $replyto = rcube_mime::decode_address_list($MESSAGE->headers->replyto, null, false, $MESSAGE->headers->charset, true);
+ $from = rcube_mime::decode_address_list($v, null, false, $charset, true);
+ $to = rcube_mime::decode_address_list($MESSAGE->headers->to, null, false, $charset, true);
+ $replyto = rcube_mime::decode_address_list($MESSAGE->headers->replyto, null, false, $charset, true);
if (count($replyto) && !count(array_diff($to, $replyto)) && count(array_diff($from, $to))) {
$fvalue .= (!empty($fvalue) ? $separator : '') . $v;
@@ -365,7 +370,7 @@ foreach ($parts as $header) {
// split recipients and put them back together in a unique way
if (!empty($fvalue) && in_array($header, array('to', 'cc', 'bcc'))) {
- $to_addresses = rcube_mime::decode_address_list($fvalue, null, $decode_header, $MESSAGE->headers->charset);
+ $to_addresses = rcube_mime::decode_address_list($fvalue, null, $decode_header, $charset);
$fvalue = array();
foreach ($to_addresses as $addr_part) {
@@ -611,7 +616,7 @@ function rcmail_compose_header_from($attrib)
$text = $html = $sql_arr['signature'];
if ($sql_arr['html_signature']) {
- $h2t = new rcube_html2text($sql_arr['signature'], false, false);
+ $h2t = new rcube_html2text($sql_arr['signature'], false, true);
$text = trim($h2t->get_text());
}
else {
@@ -624,7 +629,8 @@ function rcmail_compose_header_from($attrib)
}
if (!$sql_arr['html_signature']) {
- $html = "<pre>" . $html . "</pre>";
+ $t2h = new rcube_text2html($sql_arr['signature'], false);
+ $html = $t2h->get_html();
}
$a_signatures[$identity_id]['text'] = $text;
@@ -826,15 +832,8 @@ function rcmail_compose_part_body($part, $isHtml = false)
}
}
- if ($part->ctype_parameters['format'] == 'flowed') {
- $body = rcube_mime::unfold_flowed($body);
- }
-
// add HTML formatting
- $body = rcmail_plain_body($body);
- if ($body) {
- $body = '<pre>' . $body . '</pre>';
- }
+ $body = rcmail_plain_body($body, $part->ctype_parameters['format'] == 'flowed');
}
}
else {
@@ -957,8 +956,7 @@ function rcmail_compose_body($attrib)
"googie.setLanguages(%s);\n".
"googie.setCurrentLanguage('%s');\n".
"googie.setDecoration(false);\n".
- "googie.decorateTextarea('%s');\n".
- "%s.set_env('spellcheck', googie);",
+ "googie.decorateTextarea('%s');\n",
$RCMAIL->output->get_skin_path(),
$RCMAIL->url(array('_task' => 'utils', '_action' => 'spell', '_remote' => 1)),
!empty($dictionary) ? 'true' : 'false',
@@ -970,14 +968,13 @@ function rcmail_compose_body($attrib)
rcube::JQ(rcube::Q($RCMAIL->gettext('addtodict'))),
rcube_output::json_serialize($spellcheck_langs),
$lang,
- $attrib['id'],
- rcmail_output::JS_OBJECT_NAME), 'foot');
+ $attrib['id']), 'foot');
$OUTPUT->add_label('checking');
$OUTPUT->set_env('spellcheck_langs', join(',', $editor_lang_set));
}
- $out .= "\n".'<iframe name="savetarget" src="program/resources/blank.gif" style="width:0;height:0;border:none;visibility:hidden;"></iframe>';
+ $out .= "\n".'<iframe name="savetarget" src="program/resources/blank.gif" style="width:0;height:0;border:none;visibility:hidden;" aria-hidden="true"></iframe>';
return $out;
}
@@ -1463,6 +1460,9 @@ function rcmail_compose_subject($attrib)
$subject = $MESSAGE->subject;
else
$subject = 'Re: '.$MESSAGE->subject;
+
+ // replace (was: ...) (#1489375)
+ $subject = preg_replace('/\s*\([wW]as:[^\)]+\)\s*$/', '', $subject);
}
// create a forward-subject
else if ($compose_mode == RCUBE_COMPOSE_FORWARD) {
@@ -1525,7 +1525,9 @@ function rcmail_compose_attachment_list($attrib)
'href' => "#delete",
'title' => $RCMAIL->gettext('delete'),
'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", rcmail_output::JS_OBJECT_NAME, $id),
- 'class' => 'delete'
+ 'class' => 'delete',
+ 'tabindex' => $attrib['tabindex'] ?: '0',
+ 'aria-label' => $RCMAIL->gettext('delete') . ' ' . $a_prop['name'],
),
$button
) . rcube::Q($a_prop['name'])
@@ -1551,6 +1553,12 @@ function rcmail_compose_attachment_list($attrib)
$OUTPUT->set_env('attachments', $jslist);
$OUTPUT->add_gui_object('attachmentlist', $attrib['id']);
+ // put tabindex value into data-tabindex attribute
+ if (isset($attrib['tabindex'])) {
+ $attrib['data-tabindex'] = $attrib['tabindex'];
+ unset($attrib['tabindex']);
+ }
+
return html::tag('ul', $attrib, $out, html::$common_attrib);
}
@@ -1707,7 +1715,7 @@ function rcmail_editor_selector($attrib)
if (empty($attrib['name']))
$attrib['name'] = 'editorSelect';
- $attrib['onchange'] = "return rcmail_toggle_editor(this, '".$attrib['editorid']."', '_is_html')";
+ $attrib['onchange'] = "return rcmail.command('toggle-editor', {id: '".$attrib['editorid']."', html: this.value == 'html'}, '', event)";
$select = new html_select($attrib);
@@ -1864,9 +1872,10 @@ function rcmail_compose_responses_list($attrib)
foreach ($RCMAIL->get_compose_responses(true) as $response) {
$key = $response['key'];
$item = html::a(array(
- 'href '=> '#'.urlencode($response['name']),
+ 'href' => '#'.urlencode($response['name']),
'class' => rtrim('insertresponse ' . $attrib['itemclass']),
'unselectable' => 'on',
+ 'tabindex' => '0',
'rel' => $key,
), rcube::Q($response['name']));
diff --git a/program/steps/mail/copy.inc b/program/steps/mail/copy.inc
index 86586d34d..585310d47 100644
--- a/program/steps/mail/copy.inc
+++ b/program/steps/mail/copy.inc
@@ -24,15 +24,19 @@ if (!$OUTPUT->ajax_call) {
return;
}
-// move messages
+// copy messages
if (!empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) {
- $target = rcube_utils::get_input_value('_target_mbox', rcube_utils::INPUT_POST, true);
+ $target = rcube_utils::get_input_value('_target_mbox', rcube_utils::INPUT_POST, true);
+ $sources = array();
- foreach (rcmail::get_uids() as $mbox => $uids) {
- if ($mbox === $target)
+ foreach (rcmail::get_uids(null, null, $multifolder) as $mbox => $uids) {
+ if ($mbox === $target) {
$copied++;
- else
+ }
+ else {
$copied += (int)$RCMAIL->storage->copy_message($uids, $target, $mbox);
+ $sources[] = $mbox;
+ }
}
if (!$copied) {
@@ -47,7 +51,7 @@ if (!empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) {
rcmail_send_unread_count($target, true);
- $OUTPUT->command('set_quota', $RCMAIL->quota_content());
+ $OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $multifolder ? $sources[0] : 'INBOX'));
}
// unknown action or missing query param
else {
diff --git a/program/steps/mail/folders.inc b/program/steps/mail/folders.inc
index 519a41fdd..49bf25377 100644
--- a/program/steps/mail/folders.inc
+++ b/program/steps/mail/folders.inc
@@ -35,7 +35,7 @@ if ($RCMAIL->action == 'expunge') {
$OUTPUT->show_message('folderexpunged', 'confirmation');
if (!empty($_REQUEST['_reload'])) {
- $OUTPUT->command('set_quota', $RCMAIL->quota_content());
+ $OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $mbox));
$OUTPUT->command('message_list.clear');
$RCMAIL->action = 'list';
return;
@@ -69,7 +69,7 @@ else if ($RCMAIL->action == 'purge') {
$OUTPUT->command('message_list.clear');
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text(), $mbox);
$OUTPUT->command('set_unread_count', $mbox, 0);
- $OUTPUT->command('set_quota', $RCMAIL->quota_content());
+ $OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $mbox));
rcmail_set_unseen_count($mbox, 0);
// set trash folder state
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 7270cf95a..a7c483bba 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -23,39 +23,8 @@
// always instantiate storage object (but not connect to server yet)
$RCMAIL->storage_init();
-// set imap properties and session vars
-if (!strlen($mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true))) {
- $mbox = strlen($_SESSION['mbox']) ? $_SESSION['mbox'] : 'INBOX';
-}
-if (!($page = intval($_GET['_page']))) {
- $page = $_SESSION['page'] ? $_SESSION['page'] : 1;
-}
-
-$RCMAIL->storage->set_folder($_SESSION['mbox'] = $mbox);
-$RCMAIL->storage->set_page($_SESSION['page'] = $page);
-
-$a_threading = $RCMAIL->config->get('message_threading', array());
-$message_sort_col = $RCMAIL->config->get('message_sort_col');
-$message_sort_order = $RCMAIL->config->get('message_sort_order');
-
-// set default sort col/order to session
-if (!isset($_SESSION['sort_col'])) {
- $_SESSION['sort_col'] = $message_sort_col ? $message_sort_col : '';
-}
-if (!isset($_SESSION['sort_order'])) {
- $_SESSION['sort_order'] = strtoupper($message_sort_order) == 'ASC' ? 'ASC' : 'DESC';
-}
-
-// set threads mode
-if (isset($_GET['_threads'])) {
- if ($_GET['_threads'])
- $a_threading[$_SESSION['mbox']] = true;
- else
- unset($a_threading[$_SESSION['mbox']]);
-
- $RCMAIL->user->save_prefs(array('message_threading' => $a_threading));
-}
-$RCMAIL->storage->set_threading($a_threading[$_SESSION['mbox']]);
+// init environment - set current folder, page, list mode
+rcmail_init_env();
// set message set for search result
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'])
@@ -135,14 +104,20 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') {
}
}
+ if (!empty($_GET['_uid'])) {
+ $OUTPUT->set_env('list_uid', $_GET['_uid']);
+ }
+
// set configuration
$RCMAIL->set_env_config(array('delete_junk', 'flag_for_deletion', 'read_when_deleted',
- 'skip_deleted', 'display_next', 'message_extwin', 'compose_extwin', 'forward_attachment'));
+ 'skip_deleted', 'display_next', 'message_extwin', 'forward_attachment'));
if (!$OUTPUT->ajax_call) {
$OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash',
'movingmessage', 'copyingmessage', 'deletingmessage', 'markingmessage',
- 'copy', 'move', 'quota', 'replyall', 'replylist', 'stillsearching');
+ 'copy', 'move', 'quota', 'replyall', 'replylist', 'stillsearching',
+ 'flagged', 'unflagged', 'unread', 'deleted', 'replied', 'forwarded',
+ 'priority', 'withattachment', 'fileuploaderror');
}
$pagetitle = $RCMAIL->localize_foldername($mbox_name, true);
@@ -185,6 +160,64 @@ $RCMAIL->register_action_map(array(
/**
+ * Sets storage properties and session
+ */
+function rcmail_init_env()
+{
+ global $RCMAIL;
+
+ $default_threading = $RCMAIL->config->get('default_list_mode', 'list') == 'threads';
+ $a_threading = $RCMAIL->config->get('message_threading', array());
+ $message_sort_col = $RCMAIL->config->get('message_sort_col');
+ $message_sort_order = $RCMAIL->config->get('message_sort_order');
+
+ // set imap properties and session vars
+ if (!strlen($mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true))) {
+ $mbox = strlen($_SESSION['mbox']) ? $_SESSION['mbox'] : 'INBOX';
+ }
+ if (!($page = intval($_GET['_page']))) {
+ $page = $_SESSION['page'] ? $_SESSION['page'] : 1;
+ }
+
+ $RCMAIL->storage->set_folder($_SESSION['mbox'] = $mbox);
+ $RCMAIL->storage->set_page($_SESSION['page'] = $page);
+
+ // set default sort col/order to session
+ if (!isset($_SESSION['sort_col'])) {
+ $_SESSION['sort_col'] = $message_sort_col ? $message_sort_col : '';
+ }
+ if (!isset($_SESSION['sort_order'])) {
+ $_SESSION['sort_order'] = strtoupper($message_sort_order) == 'ASC' ? 'ASC' : 'DESC';
+ }
+
+ // set threads mode
+ if (isset($_GET['_threads'])) {
+ if ($_GET['_threads']) {
+ // re-set current page number when listing mode changes
+ if (!$a_threading[$_SESSION['mbox']]) {
+ $RCMAIL->storage->set_page($_SESSION['page'] = 1);
+ }
+
+ $a_threading[$_SESSION['mbox']] = true;
+ }
+ else {
+ // re-set current page number when listing mode changes
+ if ($a_threading[$_SESSION['mbox']]) {
+ $RCMAIL->storage->set_page($_SESSION['page'] = 1);
+ }
+
+ $a_threading[$_SESSION['mbox']] = false;
+ }
+
+ $RCMAIL->user->save_prefs(array('message_threading' => $a_threading));
+ }
+
+ $threading = isset($a_threading[$_SESSION['mbox']]) ? $a_threading[$_SESSION['mbox']] : $default_threading;
+
+ $RCMAIL->storage->set_threading($threading);
+}
+
+/**
* Returns default search mods
*/
function rcmail_search_mods()
@@ -351,13 +384,18 @@ function rcmail_js_message_list($a_headers, $insert_top=false, $a_show_cols=null
$head_replace = true;
}
- // add 'folder' column to list on multi-folder searches
- $search_set = $RCMAIL->storage->get_search_set();
+ $search_set = $RCMAIL->storage->get_search_set();
$multifolder = $search_set && $search_set[1]->multi;
+
+ // add/remove 'folder' column to the list on multi-folder searches
if ($multifolder && !in_array('folder', $a_show_cols)) {
$a_show_cols[] = 'folder';
$head_replace = true;
}
+ else if (!$multifolder && ($found = array_search('folder', $a_show_cols)) !== false) {
+ unset($a_show_cols[$found]);
+ $head_replace = true;
+ }
$mbox = $RCMAIL->storage->get_folder();
@@ -369,6 +407,7 @@ function rcmail_js_message_list($a_headers, $insert_top=false, $a_show_cols=null
// Make sure there are no duplicated columns (#1486999)
$a_show_cols = array_unique($a_show_cols);
+ $_SESSION['list_attrib']['columns'] = $a_show_cols;
// Plugins may set header's list_cols/list_flags and other rcube_message_header variables
// and list columns
@@ -507,14 +546,19 @@ function rcmail_message_list_head($attrib, $a_show_cols)
$a_sort_cols = array('subject', 'date', 'from', 'to', 'fromto', 'size', 'cc');
if (!empty($attrib['optionsmenuicon'])) {
- $onclick = 'return ' . rcmail_output::JS_OBJECT_NAME . ".command('menu-open', 'messagelistmenu')";
- if ($attrib['optionsmenuicon'] === true || $attrib['optionsmenuicon'] == 'true')
- $list_menu = html::div(array('onclick' => $onclick, 'class' => 'listmenu',
- 'id' => 'listmenulink', 'title' => $RCMAIL->gettext('listoptions')));
- else
- $list_menu = html::a(array('href' => '#', 'onclick' => $onclick),
- html::img(array('src' => $skin_path . $attrib['optionsmenuicon'],
- 'id' => 'listmenulink', 'title' => $RCMAIL->gettext('listoptions'))));
+ $onclick = 'return ' . rcmail_output::JS_OBJECT_NAME . ".command('menu-open', 'messagelistmenu', this, event)";
+ $inner = $RCMAIL->gettext('listoptions');
+ if (is_string($attrib['optionsmenuicon']) && $attrib['optionsmenuicon'] != 'true') {
+ $inner = html::img(array('src' => $skin_path . $attrib['optionsmenuicon'], 'alt' => $RCMAIL->gettext('listoptions')));
+ }
+ $list_menu = html::a(array(
+ 'href' => '#list-options',
+ 'onclick' => $onclick,
+ 'class' => 'listmenu',
+ 'id' => 'listmenulink',
+ 'title' => $RCMAIL->gettext('listoptions'),
+ 'tabindex' => '0',
+ ), $inner);
}
else {
$list_menu = '';
@@ -534,12 +578,14 @@ function rcmail_message_list_head($attrib, $a_show_cols)
// get column name
switch ($col) {
case 'flag':
- $col_name = html::span('flagged', '&nbsp;');
+ $col_name = html::span('flagged', $RCMAIL->gettext('flagged'));
break;
case 'attachment':
case 'priority':
+ $col_name = html::span($col, $RCMAIL->gettext($col));
+ break;
case 'status':
- $col_name = html::span($col, '&nbsp;');
+ $col_name = html::span($col, $RCMAIL->gettext('readstatus'));
break;
case 'threads':
$col_name = $list_menu;
@@ -854,95 +900,29 @@ function rcmail_print_body($part, $p = array())
// plaintext postprocessing
if ($part->ctype_secondary == 'plain') {
- if ($part->ctype_secondary == 'plain' && $part->ctype_parameters['format'] == 'flowed') {
- $body = rcube_mime::unfold_flowed($body);
- }
-
- $body = rcmail_plain_body($body);
+ $body = rcmail_plain_body($body, $part->ctype_parameters['format'] == 'flowed');
}
// allow post-processing of the message body
$data = $RCMAIL->plugins->exec_hook('message_part_after',
array('type' => $part->ctype_secondary, 'body' => $body, 'id' => $part->mime_id) + $data);
- return $data['type'] == 'html' ? $data['body'] : html::tag('pre', array(), $data['body']);
+ return $data['body'];
}
/**
* Handle links and citation marks in plain text message
*
* @param string Plain text string
+ * @param boolean Set to True if the source text is in format=flowed
*
* @return string Formatted HTML string
*/
-function rcmail_plain_body($body)
+function rcmail_plain_body($body, $flowed = false)
{
- global $RCMAIL;
-
- // make links and email-addresses clickable
- $attribs = array('link_attribs' => array('rel' => 'noreferrer', 'target' => '_blank'));
- $replacer = new rcmail_string_replacer($attribs);
-
- // search for patterns like links and e-mail addresses and replace with tokens
- $body = $replacer->replace($body);
-
- // split body into single lines
- $body = preg_split('/\r?\n/', $body);
- $quote_level = 0;
- $last = -1;
-
- // find/mark quoted lines...
- for ($n=0, $cnt=count($body); $n < $cnt; $n++) {
- if ($body[$n][0] == '>' && preg_match('/^(>+ {0,1})+/', $body[$n], $regs)) {
- $q = substr_count($regs[0], '>');
- $body[$n] = substr($body[$n], strlen($regs[0]));
-
- if ($q > $quote_level) {
- $body[$n] = $replacer->get_replacement($replacer->add(
- str_repeat('<blockquote>', $q - $quote_level))) . $body[$n];
- $last = $n;
- }
- else if ($q < $quote_level) {
- $body[$n] = $replacer->get_replacement($replacer->add(
- str_repeat('</blockquote>', $quote_level - $q))) . $body[$n];
- $last = $n;
- }
- }
- else {
- $q = 0;
- if ($quote_level > 0)
- $body[$n] = $replacer->get_replacement($replacer->add(
- str_repeat('</blockquote>', $quote_level))) . $body[$n];
- }
-
- $quote_level = $q;
- }
-
- $body = join("\n", $body);
-
- // quote plain text (don't use rcube::Q() here, to display entities "as is")
- $table = get_html_translation_table(HTML_SPECIALCHARS);
- unset($table['?']);
- $body = strtr($body, $table);
-
- // colorize signature (up to <sig_max_lines> lines)
- $len = strlen($body);
- $sig_max_lines = $RCMAIL->config->get('sig_max_lines', 15);
-
- while (($sp = strrpos($body, "-- \n", $sp ? -$len+$sp-1 : 0)) !== false) {
- if ($sp == 0 || $body[$sp-1] == "\n") {
- // do not touch blocks with more that X lines
- if (substr_count($body, "\n", $sp) < $sig_max_lines) {
- $body = substr($body, 0, max(0, $sp))
- . '<span class="sig">'.substr($body, $sp).'</span>';
- }
-
- break;
- }
- }
-
- // insert url/mailto links and citation tags
- $body = $replacer->resolve($body);
+ $options = array('flowed' => $flowed, 'wrap' => !$flowed, 'replacer' => 'rcmail_string_replacer');
+ $text2html = new rcube_text2html($body, false, $options);
+ $body = $text2html->get_html();
return $body;
}
@@ -1097,7 +1077,9 @@ function rcmail_message_headers($attrib, $headers=null)
$plugin = $RCMAIL->plugins->exec_hook('message_headers_output', array(
'output' => $output_headers,
'headers' => $headers_obj,
- 'exclude' => $exclude_headers
+ 'exclude' => $exclude_headers, // readonly
+ 'folder' => $MESSAGE->folder, // readonly
+ 'uid' => $MESSAGE->uid, // readonly
));
// single header value is requested
@@ -1272,8 +1254,8 @@ function rcmail_message_body($attrib)
$plugin = $RCMAIL->plugins->exec_hook('message_body_prefix',
array('part' => $MESSAGE, 'prefix' => ''));
- $out .= html::div('message-part', $plugin['prefix'] . html::tag('pre', array(),
- rcmail_plain_body(rcube::Q($MESSAGE->body, 'strict', false))));
+ $out .= html::div('message-part',
+ $plugin['prefix'] . rcmail_plain_body($MESSAGE->body));
}
}
@@ -1840,7 +1822,7 @@ function rcmail_send_mdn($message, &$smtp_error)
$body = $RCMAIL->gettext("yourmessage") . "\r\n\r\n" .
"\t" . $RCMAIL->gettext("to") . ': ' . rcube_mime::decode_mime_string($message->headers->to, $message->headers->charset) . "\r\n" .
"\t" . $RCMAIL->gettext("subject") . ': ' . $message->subject . "\r\n" .
- "\t" . $RCMAIL->gettext("sent") . ': ' . $RCMAIL->format_date($message->headers->date, $RCMAIL->config->get('date_long')) . "\r\n" .
+ "\t" . $RCMAIL->gettext("date") . ': ' . $RCMAIL->format_date($message->headers->date, $RCMAIL->config->get('date_long')) . "\r\n" .
"\r\n" . $RCMAIL->gettext("receiptnote");
$compose->headers($headers);
@@ -2099,6 +2081,7 @@ function rcmail_message_import_form($attrib = array())
));
$content = html::tag('input', array('type' => 'hidden', 'name' => '_unlock', 'value' => ''))
+ . html::tag('input', array('type' => 'hidden', 'name' => '_framed', 'value' => '1'))
. html::div(null, $fileinput->show())
. html::div('hint', $RCMAIL->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize))));
@@ -2136,11 +2119,10 @@ function rcmail_compose_contact_groups($abook, $source_id, $search = null, $sear
foreach ($abook->list_groups($search, $search_mode) as $group) {
$abook->reset();
$abook->set_group($group['ID']);
- $group_prop = $abook->get_group($group['ID']);
// group (distribution list) with email address(es)
- if ($group_prop['email']) {
- foreach ((array)$group_prop['email'] as $email) {
+ if ($group['email']) {
+ foreach ((array)$group['email'] as $email) {
$row_id = 'G'.$group['ID'];
$jsresult[$row_id] = format_email_recipient($email, $group['name']);
$OUTPUT->command('add_contact_row', $row_id, array(
@@ -2148,7 +2130,7 @@ function rcmail_compose_contact_groups($abook, $source_id, $search = null, $sear
}
}
// make virtual groups clickable to list their members
- else if ($group_prop['virtual']) {
+ else if ($group['virtual']) {
$row_id = 'G'.$group['ID'];
$OUTPUT->command('add_contact_row', $row_id, array(
'contactgroup' => html::a(array(
diff --git a/program/steps/mail/get.inc b/program/steps/mail/get.inc
index 02d57c7dc..b260d2c85 100644
--- a/program/steps/mail/get.inc
+++ b/program/steps/mail/get.inc
@@ -354,7 +354,7 @@ else if (strlen($part_id)) {
}
// send part as-it-is
else {
- if ($part->body) {
+ if ($part->body && empty($plugin['download'])) {
header("Content-Length: " . strlen($part->body));
echo $part->body;
$sent = true;
diff --git a/program/steps/mail/list.inc b/program/steps/mail/list.inc
index c4a6df57b..2dcc40d17 100644
--- a/program/steps/mail/list.inc
+++ b/program/steps/mail/list.inc
@@ -20,7 +20,7 @@
*/
if (!$OUTPUT->ajax_call) {
- return;
+ return;
}
$save_arr = array();
@@ -28,28 +28,28 @@ $dont_override = (array) $RCMAIL->config->get('dont_override');
// is there a sort type for this request?
if ($sort = rcube_utils::get_input_value('_sort', rcube_utils::INPUT_GET)) {
- // yes, so set the sort vars
- list($sort_col, $sort_order) = explode('_', $sort);
-
- // set session vars for sort (so next page and task switch know how to sort)
- if (!in_array('message_sort_col', $dont_override)) {
- $_SESSION['sort_col'] = $save_arr['message_sort_col'] = $sort_col;
- }
- if (!in_array('message_sort_order', $dont_override)) {
- $_SESSION['sort_order'] = $save_arr['message_sort_order'] = $sort_order;
- }
+ // yes, so set the sort vars
+ list($sort_col, $sort_order) = explode('_', $sort);
+
+ // set session vars for sort (so next page and task switch know how to sort)
+ if (!in_array('message_sort_col', $dont_override)) {
+ $_SESSION['sort_col'] = $save_arr['message_sort_col'] = $sort_col;
+ }
+ if (!in_array('message_sort_order', $dont_override)) {
+ $_SESSION['sort_order'] = $save_arr['message_sort_order'] = $sort_order;
+ }
}
// is there a set of columns for this request?
if ($cols = rcube_utils::get_input_value('_cols', rcube_utils::INPUT_GET)) {
- $_SESSION['list_attrib']['columns'] = explode(',', $cols);
- if (!in_array('list_cols', $dont_override)) {
- $save_arr['list_cols'] = explode(',', $cols);
- }
+ $_SESSION['list_attrib']['columns'] = explode(',', $cols);
+ if (!in_array('list_cols', $dont_override)) {
+ $save_arr['list_cols'] = explode(',', $cols);
+ }
}
if (!empty($save_arr)) {
- $RCMAIL->user->save_prefs($save_arr);
+ $RCMAIL->user->save_prefs($save_arr);
}
$mbox_name = $RCMAIL->storage->get_folder();
@@ -60,27 +60,32 @@ $RCMAIL->storage->folder_sync($mbox_name);
// initialize searching result if search_filter is used
if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL') {
- $search_request = md5($mbox_name.$_SESSION['search_scope'].$_SESSION['search_filter']);
- $RCMAIL->storage->search($mbox_name, $_SESSION['search_filter'], RCUBE_CHARSET, rcmail_sort_column());
- $_SESSION['search'] = $RCMAIL->storage->get_search_set();
- $_SESSION['search_request'] = $search_request;
- $OUTPUT->set_env('search_request', $search_request);
- $OUTPUT->set_env('search_filter', $_SESSION['search_filter']);
+ $search_request = md5($mbox_name.$_SESSION['search_scope'].$_SESSION['search_filter']);
+ $RCMAIL->storage->search($mbox_name, $_SESSION['search_filter'], RCUBE_CHARSET, rcmail_sort_column());
+
+ $_SESSION['search'] = $RCMAIL->storage->get_search_set();
+ $_SESSION['search_request'] = $search_request;
+
+ $OUTPUT->set_env('search_request', $search_request);
+ $OUTPUT->set_env('search_filter', $_SESSION['search_filter']);
+
+ $multifolder = is_a($_SESSION['search'][1], 'rcube_result_multifolder');
}
// fetch message headers
-if ($count = $RCMAIL->storage->count($mbox_name, $threading ? 'THREADS' : 'ALL', !empty($_REQUEST['_refresh'])))
- $a_headers = $RCMAIL->storage->list_messages($mbox_name, NULL, rcmail_sort_column(), rcmail_sort_order());
+if ($count = $RCMAIL->storage->count($mbox_name, $threading ? 'THREADS' : 'ALL', !empty($_REQUEST['_refresh']))) {
+ $a_headers = $RCMAIL->storage->list_messages($mbox_name, NULL, rcmail_sort_column(), rcmail_sort_order());
+}
// update search set (possible change of threading mode)
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'])
&& $_SESSION['search_request'] == $_REQUEST['_search']
) {
- $_SESSION['search'] = $RCMAIL->storage->get_search_set();
+ $_SESSION['search'] = $RCMAIL->storage->get_search_set();
}
// remove old search data
else if (empty($_REQUEST['_search']) && isset($_SESSION['search'])) {
- $RCMAIL->session->remove('search');
+ $RCMAIL->session->remove('search');
}
// empty result? we'll skip UNSEEN counting in rcmail_send_unread_count()
@@ -93,44 +98,47 @@ rcmail_send_unread_count($mbox_name, !empty($_REQUEST['_refresh']), $unseen);
// update message count display
$pages = ceil($count/$RCMAIL->storage->get_pagesize());
-$exists = $RCMAIL->storage->count($mbox_name, 'EXISTS');
+$page = $count ? $RCMAIL->storage->get_page() : 1;
+$exists = $RCMAIL->storage->count($mbox_name, 'EXISTS', true);
$OUTPUT->set_env('messagecount', $count);
$OUTPUT->set_env('pagecount', $pages);
$OUTPUT->set_env('threading', $threading);
-$OUTPUT->set_env('current_page', $count ? $RCMAIL->storage->get_page() : 1);
+$OUTPUT->set_env('current_page', $page);
$OUTPUT->set_env('exists', $exists);
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count), $mbox_name);
// remove old message rows if commanded by the client
if (!empty($_REQUEST['_clear'])) {
- $OUTPUT->command('clear_message_list');
+ $OUTPUT->command('clear_message_list');
}
// add message rows
rcmail_js_message_list($a_headers, false, $cols);
if (isset($a_headers) && count($a_headers)) {
- if ($search_request) {
- $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $count));
- }
-
- // remember last HIGHESTMODSEQ value (if supported)
- // we need it for flag updates in check-recent
- $data = $RCMAIL->storage->folder_data($mbox_name);
- if (!empty($data['HIGHESTMODSEQ'])) {
- $_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ'];
- }
+ if ($search_request) {
+ $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $count));
+ }
+
+ // remember last HIGHESTMODSEQ value (if supported)
+ // we need it for flag updates in check-recent
+ $data = $RCMAIL->storage->folder_data($mbox_name);
+ if (!empty($data['HIGHESTMODSEQ'])) {
+ $_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ'];
+ }
}
else {
- // handle IMAP errors (e.g. #1486905)
- if ($err_code = $RCMAIL->storage->get_error_code()) {
- $RCMAIL->display_server_error();
- }
- else if ($search_request)
- $OUTPUT->show_message('searchnomatch', 'notice');
- else
- $OUTPUT->show_message('nomessagesfound', 'notice');
+ // handle IMAP errors (e.g. #1486905)
+ if ($err_code = $RCMAIL->storage->get_error_code()) {
+ $RCMAIL->display_server_error();
+ }
+ else if ($search_request) {
+ $OUTPUT->show_message('searchnomatch', 'notice');
+ }
+ else {
+ $OUTPUT->show_message('nomessagesfound', 'notice');
+ }
}
// set trash folder state
@@ -138,5 +146,9 @@ if ($mbox_name === $RCMAIL->config->get('trash_mbox')) {
$OUTPUT->command('set_trash_count', $exists);
}
+if ($page == 1) {
+ $OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $multifolder ? 'INBOX' : $mbox_name));
+}
+
// send response
$OUTPUT->send();
diff --git a/program/steps/mail/list_contacts.inc b/program/steps/mail/list_contacts.inc
index 0ee81135b..4f17beffd 100644
--- a/program/steps/mail/list_contacts.inc
+++ b/program/steps/mail/list_contacts.inc
@@ -110,7 +110,7 @@ else if (!empty($result) && $result->count > 0) {
$keyname = $row['_type'] == 'group' ? 'contactgroup' : 'contact';
$OUTPUT->command('add_contact_row', $row_id, array(
- $keyname => html::span(array('title' => $email), rcube::Q($name ? $name : $email) .
+ $keyname => html::a(array('title' => $email), rcube::Q($name ? $name : $email) .
($name && count($emails) > 1 ? '&nbsp;' . html::span('email', rcube::Q($email)) : '')
)), $classname);
}
diff --git a/program/steps/mail/move_del.inc b/program/steps/mail/move_del.inc
index c29985875..4c57d6fa9 100644
--- a/program/steps/mail/move_del.inc
+++ b/program/steps/mail/move_del.inc
@@ -27,6 +27,7 @@ if (!$OUTPUT->ajax_call)
$threading = (bool) $RCMAIL->storage->get_threading();
$old_count = $RCMAIL->storage->count(NULL, $threading ? 'THREADS' : 'ALL');
$old_pages = ceil($old_count / $RCMAIL->storage->get_pagesize());
+$sources = array();
$trash = $RCMAIL->config->get('trash_mbox');
@@ -36,12 +37,13 @@ if ($RCMAIL->action == 'move' && !empty($_POST['_uid']) && strlen($_POST['_targe
$trash = $RCMAIL->config->get('trash_mbox');
$success = true;
- foreach (rcmail::get_uids() as $mbox => $uids) {
+ foreach (rcmail::get_uids(null, null, $multifolder) as $mbox => $uids) {
if ($mbox === $target) {
$count += count($uids);
}
else if ($RCMAIL->storage->move_message($uids, $target, $mbox)) {
$count += count($uids);
+ $sources[] = $mbox;
}
else {
$success = false;
@@ -69,10 +71,11 @@ if ($RCMAIL->action == 'move' && !empty($_POST['_uid']) && strlen($_POST['_targe
}
}
// delete messages
-else if ($RCMAIL->action=='delete' && !empty($_POST['_uid'])) {
- foreach (rcmail::get_uids() as $mbox => $uids) {
- $del += (int)$RCMAIL->storage->delete_message($uids, $mbox);
- $count += count($uids);
+else if ($RCMAIL->action == 'delete' && !empty($_POST['_uid'])) {
+ foreach (rcmail::get_uids(null, null, $multifolder) as $mbox => $uids) {
+ $del += (int)$RCMAIL->storage->delete_message($uids, $mbox);
+ $count += count($uids);
+ $sources[] = $mbox;
}
if (!$del) {
@@ -146,7 +149,7 @@ else {
rcmail_send_unread_count($target, true);
}
- $OUTPUT->command('set_quota', $RCMAIL->quota_content());
+ $OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $multifolder ? $sources[0] : 'INBOX'));
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count), $mbox);
if ($threading) {
@@ -166,7 +169,7 @@ else {
$OUTPUT->command('set_trash_count', $exists);
}
else if ($target !== null && $target === $trash) {
- $OUTPUT->command('set_trash_count', $RCMAIL->storage->count($trash, 'EXISTS'));
+ $OUTPUT->command('set_trash_count', $RCMAIL->storage->count($trash, 'EXISTS', true));
}
}
diff --git a/program/steps/mail/search.inc b/program/steps/mail/search.inc
index e610e9137..b50593480 100644
--- a/program/steps/mail/search.inc
+++ b/program/steps/mail/search.inc
@@ -127,8 +127,9 @@ if ($search_str) {
}
else if ($scope == 'sub') {
$mboxes = $RCMAIL->storage->list_folders_subscribed($mbox, '*', 'mail');
- if ($mbox != 'INBOX' && $mboxes[0] == 'INBOX')
+ if ($mbox != 'INBOX' && $mboxes[0] == 'INBOX') {
array_shift($mboxes);
+ }
}
$result = $RCMAIL->storage->search($mboxes, $search_str, $imap_charset, $sort_column);
@@ -144,7 +145,7 @@ if ($search_str) {
$_SESSION['last_text_search'] = $str;
}
$_SESSION['search_request'] = $search_request;
-$_SESSION['search_scope'] = $scope;
+$_SESSION['search_scope'] = $scope;
// Get the headers
@@ -162,9 +163,11 @@ if (!empty($result_h)) {
// remember last HIGHESTMODSEQ value (if supported)
// we need it for flag updates in check-recent
- $data = $RCMAIL->storage->folder_data($mbox_name);
- if (!empty($data['HIGHESTMODSEQ'])) {
- $_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ'];
+ if ($mbox !== null) {
+ $data = $RCMAIL->storage->folder_data($mbox);
+ if (!empty($data['HIGHESTMODSEQ'])) {
+ $_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ'];
+ }
}
}
// handle IMAP errors (e.g. #1486905)
@@ -179,17 +182,24 @@ else if ($result->incomplete) {
else {
$OUTPUT->show_message('searchnomatch', 'notice');
$OUTPUT->set_env('multifolder_listing', (bool)$result->multi);
- if ($result->multi && $scope == 'all')
+ if ($result->multi && $scope == 'all') {
$OUTPUT->command('select_folder', '');
+ }
}
+$OUTPUT->set_pagetitle($RCMAIL->gettext(array('name' => 'searchfor', 'vars' => array('q' => $str))));
+
// update message count display
$OUTPUT->set_env('search_request', $search_str ? $search_request : '');
$OUTPUT->set_env('search_filter', $_SESSION['search_filter']);
$OUTPUT->set_env('threading', $RCMAIL->storage->get_threading());
$OUTPUT->set_env('messagecount', $count);
$OUTPUT->set_env('pagecount', ceil($count/$RCMAIL->storage->get_pagesize()));
-$OUTPUT->set_env('exists', $RCMAIL->storage->count($mbox_name, 'EXISTS'));
+$OUTPUT->set_env('exists', $mbox === null ? 0 : $RCMAIL->storage->count($mbox, 'EXISTS'));
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count, 1), $mbox);
-$OUTPUT->set_pagetitle($RCMAIL->gettext(array('name' => 'searchfor', 'vars' => array('q' => $str))));
+
+if (!$result->incomplete) {
+ $OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $result->multi ? 'INBOX' : $mbox));
+}
+
$OUTPUT->send();
diff --git a/program/steps/mail/search_contacts.inc b/program/steps/mail/search_contacts.inc
index d56581695..ccef32dd2 100644
--- a/program/steps/mail/search_contacts.inc
+++ b/program/steps/mail/search_contacts.inc
@@ -87,7 +87,7 @@ if (!empty($result) && $result->count > 0) {
$row_id = $row['ID'].'-'.$i;
$jsresult[$row_id] = format_email_recipient($email, $name);
$OUTPUT->command('add_contact_row', $row_id, array(
- 'contact' => html::span(array('title' => $email), rcube::Q($name ? $name : $email) .
+ 'contact' => html::a(array('title' => $email), rcube::Q($name ? $name : $email) .
($name && count($emails) > 1 ? '&nbsp;' . html::span('email', rcube::Q($email)) : '')
)), 'person');
}
diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc
index 04ba94f5e..bac751298 100644
--- a/program/steps/mail/sendmail.inc
+++ b/program/steps/mail/sendmail.inc
@@ -77,7 +77,7 @@ $mailto = rcmail_email_input_format(rcube_utils::get_input_value('_to', rcube_u
$mailcc = rcmail_email_input_format(rcube_utils::get_input_value('_cc', rcube_utils::INPUT_POST, TRUE, $message_charset), true);
$mailbcc = rcmail_email_input_format(rcube_utils::get_input_value('_bcc', rcube_utils::INPUT_POST, TRUE, $message_charset), true);
-if ($EMAIL_FORMAT_ERROR) {
+if ($EMAIL_FORMAT_ERROR && !$savedraft) {
$OUTPUT->show_message('emailformaterror', 'error', array('email' => $EMAIL_FORMAT_ERROR));
$OUTPUT->send('iframe');
}
@@ -273,20 +273,31 @@ if ($isHtml) {
}
// append doctype and html/body wrappers
- $message_body = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">'
- . "\r\n<html><body" . (!empty($bstyle) ? " style='" . implode($bstyle, '; ') . "'" : '') . ">\r\n"
- . $message_body;
+ $bstyle = !empty($bstyle) ? (" style='" . implode($bstyle, '; ') . "'") : '';
+ $message_body = '<html><head>'
+ . '<meta http-equiv="Content-Type" content="text/html; charset=' . $message_charset . '" /></head>'
+ . "<body" . $bstyle . ">\r\n" . $message_body;
}
if (!$savedraft) {
if ($isHtml) {
- // remove signature's div ID
- $message_body = preg_replace('/\s*id="_rc_sig"/', '', $message_body);
-
- // add inline css for blockquotes
- $bstyle = 'padding-left:5px; border-left:#1010ff 2px solid; margin-left:5px';
- $message_body = preg_replace('/<blockquote>/',
- '<blockquote type="cite" style="'.$bstyle.'">', $message_body);
+ $b_style = 'padding: 0 0.4em; border-left: #1010ff 2px solid; margin: 0';
+ $pre_style = 'margin: 0; padding: 0; font-family: monospace';
+
+ $message_body = preg_replace(
+ array(
+ // remove signature's div ID
+ '/\s*id="_rc_sig"/',
+ // add inline css for blockquotes and container
+ '/<blockquote>/',
+ '/<div class="pre">/'
+ ),
+ array(
+ '',
+ '<blockquote type="cite" style="'.$b_style.'">',
+ '<div class="pre" style="'.$pre_style.'">'
+ ),
+ $message_body);
}
// Check spelling before send
@@ -300,10 +311,16 @@ if (!$savedraft) {
$COMPOSE['spell_checked'] = true;
if (!$spell_result) {
- $result = $isHtml ? $spellchecker->get_words() : $spellchecker->get_xml();
+ if ($isHtml) {
+ $result['words'] = $spellchecker->get();
+ $result['dictionary'] = (bool) $RCMAIL->config->get('spellcheck_dictionary');
+ }
+ else {
+ $result = $spellchecker->get_xml();
+ }
$OUTPUT->show_message('mispellingsfound', 'error');
- $OUTPUT->command('spellcheck_resume', $isHtml, $result);
+ $OUTPUT->command('spellcheck_resume', $result);
$OUTPUT->send('iframe');
}
}
@@ -411,7 +428,7 @@ if (is_array($COMPOSE['attachments'])) {
$attachment = $RCMAIL->plugins->exec_hook('attachment_get', $attachment);
if ($isHtml) {
- $dispurl = '/\ssrc\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile'
+ $dispurl = '/\s(poster|src)\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile'
. preg_quote($attachment['id']) . '[\s\'"]*/';
$message_body = $MAIL_MIME->getHTMLBody();
$is_inline = preg_match($dispurl, $message_body);
@@ -432,7 +449,7 @@ if (is_array($COMPOSE['attachments'])) {
$cid .= '@localhost';
}
- $message_body = preg_replace($dispurl, ' src="cid:' . $cid . '" ', $message_body);
+ $message_body = preg_replace($dispurl, ' \\1="cid:' . $cid . '" ', $message_body);
$MAIL_MIME->setHTMLBody($message_body);
@@ -467,15 +484,11 @@ if (preg_match('/[^\x00-\x7F]/', $MAIL_MIME->getTXTBody())) {
$transfer_encoding = $RCMAIL->config->get('force_7bit') ? 'quoted-printable' : '8bit';
}
else {
- $text_charset = '';
+ $text_charset = 'US-ASCII';
$transfer_encoding = '7bit';
}
if ($flowed) {
- if (!$text_charset) {
- $text_charset = 'US-ASCII';
- }
-
$text_charset .= ";\r\n format=flowed";
}
@@ -728,11 +741,11 @@ function rcmail_get_identity($id)
/**
* go from this:
- * <img src="http[s]://.../tiny_mce/plugins/emotions/images/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
+ * <img src="http[s]://.../tinymce/plugins/emoticons/img/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
*
* to this:
*
- * <img src="/path/on/server/.../tiny_mce/plugins/emotions/images/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
+ * <img src="/path/on/server/.../tinymce/plugins/emoticons/img/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
*/
function rcmail_fix_emoticon_paths($mime_message)
{
@@ -743,7 +756,7 @@ function rcmail_fix_emoticon_paths($mime_message)
// remove any null-byte characters before parsing
$body = preg_replace('/\x00/', '', $body);
- $searchstr = 'program/js/tiny_mce/plugins/emotions/img/';
+ $searchstr = 'program/js/tinymce/plugins/emoticons/img/';
$offset = 0;
// keep track of added images, so they're only added once
@@ -912,7 +925,8 @@ function rcmail_generic_message_footer($isHtml)
if (!preg_match('/\.(php|ini|conf)$/', $file) && strpos($file, '/etc/') === false) {
$footer = file_get_contents($file);
if ($isHtml && !$html_footer) {
- $footer = '<pre>' . $footer . '</pre>';
+ $t2h = new rcube_text2html($footer, false);
+ $footer = $t2h->get_html();
}
return $footer;
}
diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc
index beb2cc6e9..d4121fdd8 100644
--- a/program/steps/mail/show.inc
+++ b/program/steps/mail/show.inc
@@ -80,7 +80,7 @@ if ($uid) {
// set configuration
$RCMAIL->set_env_config(array('delete_junk', 'flag_for_deletion', 'read_when_deleted',
- 'skip_deleted', 'display_next', 'compose_extwin', 'forward_attachment'));
+ 'skip_deleted', 'display_next', 'forward_attachment'));
// set special folders
foreach (array('drafts', 'trash', 'junk') as $mbox) {
@@ -148,11 +148,14 @@ if ($uid) {
if (empty($MESSAGE->headers->flags['SEEN'])
&& ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($RCMAIL->config->get('preview_pane_mark_read')) == 0))
) {
+ $RCMAIL->output->command('set_unread_message', $MESSAGE->uid, $mbox_name);
$RCMAIL->plugins->exec_hook('message_read', array(
'uid' => $MESSAGE->uid,
'mailbox' => $mbox_name,
'message' => $MESSAGE,
));
+
+ $set_seen_flag = true;
}
}
@@ -174,9 +177,7 @@ else
// mark message as read
-if ($MESSAGE && $MESSAGE->headers && empty($MESSAGE->headers->flags['SEEN']) &&
- ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($RCMAIL->config->get('preview_pane_mark_read')) == 0))
-) {
+if (!empty($set_seen_flag)) {
if ($RCMAIL->storage->set_flag($MESSAGE->uid, 'SEEN')) {
if ($count = rcmail_get_unseen_count($mbox_name)) {
rcmail_set_unseen_count($mbox_name, $count - 1);
@@ -198,6 +199,7 @@ function rcmail_message_attachments($attrib)
if (sizeof($MESSAGE->attachments)) {
foreach ($MESSAGE->attachments as $attach_prop) {
$filename = rcmail_attachment_name($attach_prop, true);
+ $size = '';
if ($PRINT_MODE) {
$size = $RCMAIL->message_part_size($attach_prop);
@@ -212,6 +214,10 @@ function rcmail_message_attachments($attrib)
$title = '';
}
+ if ($attach_prop->size) {
+ $size = ' ' . html::span('attachment-size', '(' . $RCMAIL->show_bytes($attach_prop->size) . ')');
+ }
+
$mimetype = rcmail_fix_mimetype($attach_prop->mimetype);
$class = rcube_utils::file2class($mimetype, $filename);
$id = 'attach' . $attach_prop->mime_id;
@@ -221,7 +227,7 @@ function rcmail_message_attachments($attrib)
rcmail_output::JS_OBJECT_NAME, $attach_prop->mime_id),
'onmouseover' => $title ? '' : 'rcube_webmail.long_subject_title_ex(this, 0)',
'title' => rcube::Q($title),
- ), rcube::Q($filename));
+ ), rcube::Q($filename) . $size);
$ol .= html::tag('li', array('class' => $class, 'id' => $id), $link);
@@ -343,12 +349,14 @@ function rcmail_message_contactphoto($attrib)
'_task' => 'addressbook',
'_action' => 'photo',
'_email' => $MESSAGE->sender['mailto'],
- '_alt' => $placeholder
+ '_alt' => $placeholder,
));
+
+ $attrib['onerror'] = "this.src = '" . ($placeholder ? $placeholder : 'program/resources/blank.gif') . "'";
}
else {
$photo_img = $placeholder ? $placeholder : 'program/resources/blank.gif';
}
- return html::img(array('src' => $photo_img) + $attrib);
+ return html::img(array('src' => $photo_img, 'alt' => $RCMAIL->gettext('contactphoto')) + $attrib);
}
diff --git a/program/steps/settings/about.inc b/program/steps/settings/about.inc
index 026bfc1a2..73d0b0f0d 100644
--- a/program/steps/settings/about.inc
+++ b/program/steps/settings/about.inc
@@ -50,7 +50,7 @@ function rcmail_plugins_list($attrib)
$attrib['id'] = 'rcmpluginlist';
}
- $plugins = array_filter((array) $RCMAIL->config->get('plugins'));
+ $plugins = array_filter($RCMAIL->plugins->active_plugins);
$plugin_info = array();
foreach ($plugins as $name) {
@@ -61,8 +61,8 @@ function rcmail_plugins_list($attrib)
// load info from required plugins, too
foreach ($plugin_info as $name => $info) {
- if (is_array($info['required']) && !empty($info['required'])) {
- foreach ($info['required'] as $req_name) {
+ if (is_array($info['require']) && !empty($info['require'])) {
+ foreach ($info['require'] as $req_name) {
if (!isset($plugin_info[$req_name]) && ($req_info = $RCMAIL->plugins->get_info($req_name))) {
$plugin_info[$req_name] = $req_info;
}
diff --git a/program/steps/settings/delete_identity.inc b/program/steps/settings/delete_identity.inc
deleted file mode 100644
index f77620438..000000000
--- a/program/steps/settings/delete_identity.inc
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-
-/*
- +-----------------------------------------------------------------------+
- | program/steps/settings/delete_identity.inc |
- | |
- | This file is part of the Roundcube Webmail client |
- | Copyright (C) 2005-2013, The Roundcube Dev Team |
- | |
- | Licensed under the GNU General Public License version 3 or |
- | any later version with exceptions for skins & plugins. |
- | See the README file for a full license statement. |
- | |
- | PURPOSE: |
- | Delete the submitted identities (IIDs) from the database |
- | |
- +-----------------------------------------------------------------------+
- | Author: Thomas Bruederli <roundcube@gmail.com> |
- +-----------------------------------------------------------------------+
-*/
-
-$iid = rcube_utils::get_input_value('_iid', rcube_utils::INPUT_GPC);
-
-// check request token
-if (!$OUTPUT->ajax_call && !$RCMAIL->check_request(rcube_utils::INPUT_GPC)) {
- $OUTPUT->show_message('invalidrequest', 'error');
- $RCMAIL->overwrite_action('identities');
- return;
-}
-
-if ($iid && preg_match('/^[0-9]+(,[0-9]+)*$/', $iid)) {
- $plugin = $RCMAIL->plugins->exec_hook('identity_delete', array('id' => $iid));
-
- $deleted = !$plugin['abort'] ? $RCMAIL->user->delete_identity($iid) : $plugin['result'];
-
- if ($deleted > 0 && $deleted !== false) {
- $OUTPUT->show_message('deletedsuccessfully', 'confirmation', null, false);
- }
- else {
- $msg = $plugin['message'] ? $plugin['message'] : ($deleted < 0 ? 'nodeletelastidentity' : 'errorsaving');
- $OUTPUT->show_message($msg, 'error', null, false);
- }
-
- // send response
- if ($OUTPUT->ajax_call) {
- $OUTPUT->send();
- }
-}
-
-if ($OUTPUT->ajax_call) {
- exit;
-}
-
-// go to identities page
-$RCMAIL->overwrite_action('identities');
diff --git a/program/steps/settings/edit_folder.inc b/program/steps/settings/edit_folder.inc
index 6b7bd08d2..202578676 100644
--- a/program/steps/settings/edit_folder.inc
+++ b/program/steps/settings/edit_folder.inc
@@ -38,22 +38,20 @@ function rcmail_folder_form($attrib)
$storage = $RCMAIL->get_storage();
// edited folder name (empty in create-folder mode)
- $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true);
- $mbox_imap = rcube_charset::convert($mbox, RCUBE_CHARSET, 'UTF7-IMAP');
+ $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true);
// predefined path for new folder
- $parent = rcube_utils::get_input_value('_path', rcube_utils::INPUT_GPC, true);
- $parent_imap = rcube_charset::convert($parent, RCUBE_CHARSET, 'UTF7-IMAP');
+ $parent = rcube_utils::get_input_value('_path', rcube_utils::INPUT_GPC, true);
$threading_supported = $storage->get_capability('THREAD');
$delimiter = $storage->get_hierarchy_delimiter();
// Get mailbox parameters
if (strlen($mbox)) {
- $options = rcmail_folder_options($mbox_imap);
+ $options = rcmail_folder_options($mbox);
$namespace = $storage->get_namespace();
- $path = explode($delimiter, $mbox_imap);
+ $path = explode($delimiter, $mbox);
$folder = array_pop($path);
$path = implode($delimiter, $path);
$folder = rcube_charset::convert($folder, 'UTF7-IMAP');
@@ -62,7 +60,7 @@ function rcmail_folder_form($attrib)
}
else {
$options = array();
- $path = $parent_imap;
+ $path = $parent;
// allow creating subfolders of INBOX folder
if ($path == 'INBOX') {
@@ -88,7 +86,7 @@ function rcmail_folder_form($attrib)
// Location (name)
if ($options['protected']) {
- $foldername = str_replace($delimiter, ' &raquo; ', rcube::Q($RCMAIL->localize_folderpath($mbox_imap)));
+ $foldername = str_replace($delimiter, ' &raquo; ', rcube::Q($RCMAIL->localize_folderpath($mbox)));
}
else if ($options['norename']) {
$foldername = rcube::Q($folder);
@@ -101,7 +99,7 @@ function rcmail_folder_form($attrib)
$foldername = $foldername->show($folder);
if ($options['special']) {
- $foldername .= '&nbsp;(' . rcube::Q($RCMAIL->localize_foldername($mbox_imap)) .')';
+ $foldername .= '&nbsp;(' . rcube::Q($RCMAIL->localize_foldername($mbox)) .')';
}
}
@@ -122,7 +120,7 @@ function rcmail_folder_form($attrib)
}
else {
$selected = isset($_POST['_parent']) ? $_POST['_parent'] : $path_id;
- $exceptions = array($mbox_imap);
+ $exceptions = array($mbox);
// Exclude 'prefix' namespace from parent folders list (#1488349)
// If INBOX. namespace exists, folders created as INBOX subfolders
@@ -132,9 +130,9 @@ function rcmail_folder_form($attrib)
}
$select = $RCMAIL->folder_selector(array(
+ 'id' => '_parent',
'name' => '_parent',
'noselection' => '---',
- 'realnames' => false,
'maxlength' => 150,
'unsubscribed' => true,
'skip_noinferiors' => true,
@@ -154,17 +152,19 @@ function rcmail_folder_form($attrib)
);
// Settings: threading
- if ($threading_supported && ($mbox_imap == 'INBOX' || (!$options['noselect'] && !$options['is_root']))) {
- $select = new html_select(array('name' => '_viewmode', 'id' => '_listmode'));
+ if ($threading_supported && ($mbox == 'INBOX' || (!$options['noselect'] && !$options['is_root']))) {
+ $select = new html_select(array('name' => '_viewmode', 'id' => '_viewmode'));
$select->add($RCMAIL->gettext('list'), 0);
$select->add($RCMAIL->gettext('threads'), 1);
if (isset($_POST['_viewmode'])) {
$value = (int) $_POST['_viewmode'];
}
- else if (strlen($mbox_imap)) {
- $a_threaded = $RCMAIL->config->get('message_threading', array());
- $value = (int) isset($a_threaded[$mbox_imap]);
+ else if (strlen($mbox)) {
+ $a_threaded = $RCMAIL->config->get('message_threading', array());
+ $default_mode = $RCMAIL->config->get('default_list_mode', 'list');
+
+ $value = (int) (isset($a_threaded[$mbox]) ? $a_threaded[$mbox] : $default_mode == 'threads');
}
$form['props']['fieldsets']['settings']['content']['viewmode'] = array(
@@ -211,14 +211,14 @@ function rcmail_folder_form($attrib)
'content' => array()
);
- if ((!$options['noselect'] && !$options['is_root']) || $mbox_imap == 'INBOX') {
- $msgcount = $storage->count($mbox_imap, 'ALL', true, false);
+ if ((!$options['noselect'] && !$options['is_root']) || $mbox == 'INBOX') {
+ $msgcount = $storage->count($mbox, 'ALL', true, false);
// Size
if ($msgcount) {
// create link with folder-size command
$onclick = sprintf("return %s.command('folder-size', '%s', this)",
- rcmail_output::JS_OBJECT_NAME, rcube::JQ($mbox_imap));
+ rcmail_output::JS_OBJECT_NAME, rcube::JQ($mbox));
$size = html::a(array('href' => '#', 'onclick' => $onclick,
'id' => 'folder-size'), $RCMAIL->gettext('getfoldersize'));
}
@@ -248,7 +248,7 @@ function rcmail_folder_form($attrib)
// Allow plugins to modify folder form content
$plugin = $RCMAIL->plugins->exec_hook('folder_form',
array('form' => $form, 'options' => $options,
- 'name' => $mbox_imap, 'parent_name' => $parent_imap));
+ 'name' => $mbox, 'parent_name' => $parent));
$form = $plugin['form'];
@@ -261,7 +261,7 @@ function rcmail_folder_form($attrib)
$out = "$form_start\n";
// Create form output
- foreach ($form as $tab) {
+ foreach ($form as $idx => $tab) {
if (!empty($tab['fieldsets']) && is_array($tab['fieldsets'])) {
$content = '';
foreach ($tab['fieldsets'] as $fieldset) {
@@ -276,7 +276,7 @@ function rcmail_folder_form($attrib)
$content = rcmail_get_form_part($tab, $attrib);
}
- if ($content && sizeof($form) > 1) {
+ if ($idx != 'props') {
$out .= html::tag('fieldset', null, html::tag('legend', null, rcube::Q($tab['name'])) . $content) ."\n";
}
else {
@@ -287,6 +287,11 @@ function rcmail_folder_form($attrib)
$out .= "\n$form_end";
$RCMAIL->output->set_env('messagecount', (int) $msgcount);
+ $RCMAIL->output->set_env('folder', $mbox);
+
+ if ($mbox !== null && empty($_POST)) {
+ $RCMAIL->output->command('parent.set_quota', $RCMAIL->quota_content(null, $mbox));
+ }
return $out;
}
diff --git a/program/steps/settings/edit_identity.inc b/program/steps/settings/edit_identity.inc
index 3f7b6a58a..cd7ba5fa6 100644
--- a/program/steps/settings/edit_identity.inc
+++ b/program/steps/settings/edit_identity.inc
@@ -52,9 +52,9 @@ else {
$OUTPUT->include_script('list.js');
$OUTPUT->add_handler('identityform', 'rcube_identity_form');
$OUTPUT->set_env('identities_level', IDENTITIES_LEVEL);
-$OUTPUT->add_label('deleteidentityconfirm');
+$OUTPUT->add_label('deleteidentityconfirm', 'uploading');
-$OUTPUT->set_pagetitle($RCMAIL->gettext(($RCMAIL->action == 'add-identity' ? 'newidentity' : 'edititem')));
+$OUTPUT->set_pagetitle($RCMAIL->gettext(($RCMAIL->action == 'add-identity' ? 'addidentity' : 'editidentity')));
if ($RCMAIL->action == 'add-identity' && $OUTPUT->template_exists('identityadd')) {
$OUTPUT->send('identityadd');
@@ -96,7 +96,7 @@ function rcube_identity_form($attrib)
'spellcheck' => true),
'html_signature' => array('type' => 'checkbox',
'label' => $RCMAIL->gettext('htmlsignature'),
- 'onclick' => 'return rcmail_toggle_editor(this, \'rcmfd_signature\');'),
+ 'onclick' => 'return rcmail.command(\'toggle-editor\', {id: \'rcmfd_signature\', html: this.checked}, \'\', event)'),
))
);
@@ -176,5 +176,15 @@ function rcube_identity_form($attrib)
$out .= $form_end;
+ // add image upload form
+ $max_filesize = $RCMAIL->upload_init($RCMAIL->config->get('identity_image_size', 64) * 1024);
+ $upload_form_id = 'identityImageUpload';
+
+ $out .= '<form id="' . $upload_form_id . '" style="display: none">'
+ . html::div('hint', $RCMAIL->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize))))
+ . '</form>';
+
+ $RCMAIL->output->add_gui_object('uploadform', $upload_form_id);
+
return $out;
}
diff --git a/program/steps/settings/edit_response.inc b/program/steps/settings/edit_response.inc
index 6d3c3dc41..10dec1096 100644
--- a/program/steps/settings/edit_response.inc
+++ b/program/steps/settings/edit_response.inc
@@ -72,7 +72,7 @@ if ($RCMAIL->action == 'save-response' && isset($_POST['_name']) && !$RESPONSE_R
$OUTPUT->set_env('readonly', !empty($RESPONSE_RECORD['static']));
$OUTPUT->add_handler('responseform', 'rcube_response_form');
-$OUTPUT->set_pagetitle($RCMAIL->gettext($RCMAIL->action == 'add-response' ? 'savenewresponse' : 'editresponse'));
+$OUTPUT->set_pagetitle($RCMAIL->gettext($RCMAIL->action == 'add-response' ? 'addresponse' : 'editresponse'));
$OUTPUT->send('responseedit');
diff --git a/program/steps/settings/folders.inc b/program/steps/settings/folders.inc
index 1bcfb4cfc..14e41d607 100644
--- a/program/steps/settings/folders.inc
+++ b/program/steps/settings/folders.inc
@@ -20,14 +20,12 @@
+-----------------------------------------------------------------------+
*/
-// WARNING: folder names in UI are encoded with RCUBE_CHARSET
-
// init IMAP connection
$STORAGE = $RCMAIL->get_storage();
// subscribe mailbox
if ($RCMAIL->action == 'subscribe') {
- $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true, 'UTF7-IMAP');
+ $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
if (strlen($mbox)) {
$result = $STORAGE->subscribe(array($mbox));
@@ -58,7 +56,8 @@ if ($RCMAIL->action == 'subscribe') {
}
// unsubscribe mailbox
else if ($RCMAIL->action == 'unsubscribe') {
- $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true, 'UTF7-IMAP');
+ $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
+
if (strlen($mbox)) {
$result = $STORAGE->unsubscribe(array($mbox));
if ($result)
@@ -69,8 +68,7 @@ else if ($RCMAIL->action == 'unsubscribe') {
}
// delete an existing mailbox
else if ($RCMAIL->action == 'delete-folder') {
- $mbox_utf8 = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
- $mbox = rcube_charset::convert($mbox_utf8, RCUBE_CHARSET, 'UTF7-IMAP');
+ $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
if (strlen($mbox)) {
$plugin = $RCMAIL->plugins->exec_hook('folder_delete', array('name' => $mbox));
@@ -90,7 +88,7 @@ else if ($RCMAIL->action == 'delete-folder') {
if ($OUTPUT->ajax_call && $deleted) {
// Remove folder and subfolders rows
- $OUTPUT->command('remove_folder_row', $mbox_utf8, true);
+ $OUTPUT->command('remove_folder_row', $mbox);
$OUTPUT->show_message('folderdeleted', 'confirmation');
// Clear content frame
$OUTPUT->command('subscription_select');
@@ -102,13 +100,10 @@ else if ($RCMAIL->action == 'delete-folder') {
}
// rename an existing mailbox
else if ($RCMAIL->action == 'rename-folder') {
- $name_utf8 = trim(rcube_utils::get_input_value('_folder_newname', rcube_utils::INPUT_POST, true));
- $oldname_utf8 = rcube_utils::get_input_value('_folder_oldname', rcube_utils::INPUT_POST, true);
-
- if (strlen($name_utf8) && strlen($oldname_utf8)) {
- $name = rcube_charset::convert($name_utf8, RCUBE_CHARSET, 'UTF7-IMAP');
- $oldname = rcube_charset::convert($oldname_utf8, RCUBE_CHARSET, 'UTF7-IMAP');
+ $name = trim(rcube_utils::get_input_value('_folder_newname', rcube_utils::INPUT_POST, true));
+ $oldname = rcube_utils::get_input_value('_folder_oldname', rcube_utils::INPUT_POST, true);
+ if (strlen($name) && strlen($oldname)) {
$rename = rcmail_rename_folder($oldname, $name);
}
@@ -121,8 +116,7 @@ else if ($RCMAIL->action == 'rename-folder') {
}
// clear mailbox
else if ($RCMAIL->action == 'purge') {
- $mbox_utf8 = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
- $mbox = rcube_charset::convert($mbox_utf8, RCUBE_CHARSET, 'UTF7-IMAP');
+ $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
$delimiter = $STORAGE->get_hierarchy_delimiter();
$trash_mbox = $RCMAIL->config->get('trash_mbox');
$trash_regexp = '/^' . preg_quote($trash . $delimiter, '/') . '/';
@@ -134,7 +128,7 @@ else if ($RCMAIL->action == 'purge') {
$success = $STORAGE->delete_message('*', $mbox);
$delete = true;
}
- // copy to Trash
+ // move to Trash
else {
$success = $STORAGE->move_message('1:*', $trash_mbox, $mbox);
$delete = false;
@@ -144,13 +138,13 @@ else if ($RCMAIL->action == 'purge') {
$OUTPUT->set_env('messagecount', 0);
if ($delete) {
$OUTPUT->show_message('folderpurged', 'confirmation');
- $OUTPUT->command('set_quota', $RCMAIL->quota_content());
+ $OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $mbox));
}
else {
$OUTPUT->show_message('messagemoved', 'confirmation');
}
$_SESSION['unseen_count'][$mbox] = 0;
- $OUTPUT->command('show_folder', $mbox_utf8, null, true);
+ $OUTPUT->command('show_folder', $mbox, null, true);
}
else {
$RCMAIL->display_server_error('errorsaving');
@@ -177,11 +171,9 @@ if ($OUTPUT->ajax_call) {
}
$OUTPUT->set_pagetitle($RCMAIL->gettext('folders'));
-$OUTPUT->include_script('list.js');
$OUTPUT->set_env('prefix_ns', $STORAGE->get_namespace('prefix'));
-if ($STORAGE->get_capability('QUOTA')) {
- $OUTPUT->set_env('quota', true);
-}
+$OUTPUT->set_env('quota', (bool) $STORAGE->get_capability('QUOTA'));
+$OUTPUT->include_script('treelist.js');
// add some labels to client
$OUTPUT->add_label('deletefolderconfirm', 'purgefolderconfirm', 'folderdeleting',
@@ -189,8 +181,9 @@ $OUTPUT->add_label('deletefolderconfirm', 'purgefolderconfirm', 'folderdeleting'
// register UI objects
$OUTPUT->add_handlers(array(
- 'foldersubscription' => 'rcube_subscription_form',
+ 'foldersubscription' => 'rcmail_subscription_form',
'folderframe' => 'rcmail_folder_frame',
+ 'folderfilter' => 'rcmail_folder_filter',
'quotadisplay' => array($RCMAIL, 'quota_display'),
));
@@ -198,22 +191,15 @@ $OUTPUT->send('folders');
// build table with all folders listed by server
-function rcube_subscription_form($attrib)
+function rcmail_subscription_form($attrib)
{
global $RCMAIL, $OUTPUT;
list($form_start, $form_end) = get_form_tags($attrib, 'folders');
unset($attrib['form']);
- if (!$attrib['id'])
+ if (!$attrib['id']) {
$attrib['id'] = 'rcmSubscriptionlist';
-
- $table = new html_table();
-
- if ($attrib['noheader'] !== true && $attrib['noheader'] != "true") {
- // add table header
- $table->add_header('name', $RCMAIL->gettext('foldername'));
- $table->add_header('subscribed', '');
}
$STORAGE = $RCMAIL->get_storage();
@@ -227,7 +213,6 @@ function rcube_subscription_form($attrib)
$namespace = $STORAGE->get_namespace();
$special_folders = array_flip(array_merge(array('inbox' => 'INBOX'), $STORAGE->get_special_folders()));
$protect_default = $RCMAIL->config->get('protect_default_folders');
- $a_js_folders = array();
$seen = array();
$list_folders = array();
@@ -272,19 +257,16 @@ function rcube_subscription_form($attrib)
unset($seen);
- // add drop-target representing 'root'
- $table->add_row(array('id' => 'mailboxroot', 'class' => 'virtual root'));
- $table->add('name', '&nbsp;');
- $table->add(null, '&nbsp;');
-
- $a_js_folders['mailboxroot'] = array('', '', true);
-
$checkbox_subscribe = new html_checkbox(array(
'name' => '_subscribed[]',
'title' => $RCMAIL->gettext('changesubscription'),
'onclick' => rcmail_output::JS_OBJECT_NAME.".command(this.checked?'subscribe':'unsubscribe',this.value)",
));
+ $js_folders = array();
+ $folders = array();
+ $collapsed = $RCMAIL->config->get('collapsed_folders');
+
// create list of available folders
foreach ($list_folders as $i => $folder) {
$idx = $i + 1;
@@ -292,11 +274,10 @@ function rcube_subscription_form($attrib)
$subscribed = $sub_key !== false;
$protected = $protect_default && isset($special_folders[$folder['id']]);
$noselect = false;
- $classes = array($i%2 ? 'even' : 'odd');
+ $classes = array();
$folder_utf8 = rcube_charset::convert($folder['id'], 'UTF7-IMAP');
- $display_folder = str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;', $folder['level'])
- . rcube::Q($protected ? $RCMAIL->localize_foldername($folder['id']) : $folder['name']);
+ $display_folder = rcube::Q($protected ? $RCMAIL->localize_foldername($folder['id']) : $folder['name']);
if ($folder['virtual']) {
$classes[] = 'virtual';
@@ -352,25 +333,85 @@ function rcube_subscription_form($attrib)
}
}
- $table->add_row(array('id' => 'rcmrow'.$idx, 'class' => join(' ', $classes),
- 'foldername' => $folder['id']));
+ $is_collapsed = strpos($collapsed, '&'.rawurlencode($folder['id']).'&') !== false;
+ $folder_id = rcube_utils::html_identifier($folder['id'], true);
- $table->add('name', $display_folder);
- $table->add('subscribed', $checkbox_subscribe->show(($subscribed ? $folder_utf8 : ''),
- array('value' => $folder_utf8, 'disabled' => $disabled ? 'disabled' : '')));
+ if ($folder_class = $RCMAIL->folder_classname($folder['id'])) {
+ $classes[] = $folder_class;
+ }
- $a_js_folders['rcmrow'.$idx] = array($folder_utf8,
- $display_folder, $protected || $folder['virtual']);
+ $folders[$folder['id']] = array(
+ 'idx' => $folder_id,
+ 'folder_imap' => $folder['id'],
+ 'folder' => $folder_utf8,
+ 'display' => $display_folder,
+ 'protected' => $protected || $folder['virtual'],
+ 'class' => join(' ', $classes),
+ 'subscribed' => $subscribed,
+ 'level' => $folder['level'],
+ 'collapsed' => $is_collapsed,
+ 'content' => html::a(array('href' => '#'), $display_folder)
+ . $checkbox_subscribe->show(($subscribed ? $folder['id'] : ''),
+ array('value' => $folder['id'], 'disabled' => $disabled ? 'disabled' : ''))
+ );
}
- $RCMAIL->plugins->exec_hook('folders_list', array('table' => $table));
+ $plugin = $RCMAIL->plugins->exec_hook('folders_list', array('list' => $folders));
+
+ // add drop-target representing 'root'
+ $root = array(
+ 'idx' => rcube_utils::html_identifier('*', true),
+ 'folder_imap' => '*',
+ 'folder' => '',
+ 'display' => '',
+ 'protected' => true,
+ 'class' => 'root',
+ 'content' => '<span>&nbsp;</span>',
+ );
+
+ $folders = array();
+ $plugin['list'] = array_values($plugin['list']);
+
+ array_unshift($plugin['list'], $root);
+
+ for ($i = 0, $length = count($plugin['list']); $i<$length; $i++) {
+ $folders[] = rcmail_folder_tree_element($plugin['list'], $i, $js_folders);
+ }
$OUTPUT->add_gui_object('subscriptionlist', $attrib['id']);
- $OUTPUT->set_env('subscriptionrows', $a_js_folders);
+ $OUTPUT->set_env('subscriptionrows', $js_folders);
$OUTPUT->set_env('defaultfolders', array_keys($special_folders));
+ $OUTPUT->set_env('collapsed_folders', $collapsed);
$OUTPUT->set_env('delimiter', $delimiter);
- return $form_start . $table->show($attrib) . $form_end;
+ return $form_start . html::tag('ul', $attrib, implode('', $folders), html::$common_attrib) . $form_end;
+}
+
+function rcmail_folder_tree_element($folders, &$key, &$js_folders)
+{
+ $data = $folders[$key];
+ $idx = 'rcmli' . $data['idx'];
+
+ $js_folders[$data['folder_imap']] = array($data['folder'], $data['display'], $data['protected']);
+ $content = $data['content'];
+ $attribs = array(
+ 'id' => $idx,
+ 'class' => trim($data['class'] . ' mailbox')
+ );
+
+ $children = array();
+ while ($folders[$key+1] && $folders[$key+1]['level'] > $data['level']) {
+ $key++;
+ $children[] = rcmail_folder_tree_element($folders, $key, $js_folders);
+ }
+
+ if (!empty($children)) {
+ $content .= html::div('treetoggle ' . ($data['collapsed'] ? 'collapsed' : 'expanded'), '&nbsp;')
+ . html::tag('ul', array('style' => ($data['collapsed'] ? "display:none" : null)),
+ implode("\n", $children));
+ }
+
+ return html::tag('li', $attribs, $content);
}
function rcmail_folder_frame($attrib)
@@ -384,6 +425,50 @@ function rcmail_folder_frame($attrib)
return $OUTPUT->frame($attrib, true);
}
+function rcmail_folder_filter($attrib)
+{
+ global $RCMAIL;
+
+ $storage = $RCMAIL->get_storage();
+ $namespace = $storage->get_namespace();
+
+ if (empty($namespace['personal']) && empty($namespace['shared']) && empty($namespace['other'])) {
+ return '';
+ }
+
+ if (!$attrib['id']) {
+ $attrib['id'] = 'rcmfolderfilter';
+ }
+
+ $attrib['onchange'] = rcmail_output::JS_OBJECT_NAME . '.folder_filter(this.value)';
+
+ $roots = array();
+ $select = new html_select($attrib);
+ $select->add($RCMAIL->gettext('all'), '---');
+
+ foreach (array_keys($namespace) as $type) {
+ foreach ((array)$namespace[$type] as $ns) {
+ $root = rtrim($ns[0], $ns[1]);
+ $label = $RCMAIL->gettext('namespace.' . $type);
+
+ if (count($namespace[$type]) > 1) {
+ $label .= ' (' . rcube_charset::convert($root, 'UTF7-IMAP', RCUBE_CHARSET) . ')';
+ }
+
+ $select->add($label, $root);
+
+ if (strlen($root)) {
+ $roots[] = $root;
+ }
+ }
+ }
+
+ $RCMAIL->output->add_gui_object('foldersfilter', $attrib['id']);
+ $RCMAIL->output->set_env('ns_roots', $roots);
+
+ return $select->show();
+}
+
function rcmail_rename_folder($oldname, $newname)
{
global $RCMAIL;
@@ -406,16 +491,17 @@ function rcmail_rename_folder($oldname, $newname)
$a_threaded = (array) $RCMAIL->config->get('message_threading', array());
$oldprefix = '/^' . preg_quote($oldname . $delimiter, '/') . '/';
- foreach (array_keys($a_threaded) as $key) {
+ foreach ($a_threaded as $key => $val) {
if ($key == $oldname) {
unset($a_threaded[$key]);
- $a_threaded[$newname] = true;
+ $a_threaded[$newname] = $val;
}
else if (preg_match($oldprefix, $key)) {
unset($a_threaded[$key]);
- $a_threaded[preg_replace($oldprefix, $newname.$delimiter, $key)] = true;
+ $a_threaded[preg_replace($oldprefix, $newname.$delimiter, $key)] = $val;
}
}
+
$RCMAIL->user->save_prefs(array('message_threading' => $a_threaded));
// #1488692: update session
diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc
index 4b4575f10..0b2039a78 100644
--- a/program/steps/settings/func.inc
+++ b/program/steps/settings/func.inc
@@ -44,6 +44,8 @@ $RCMAIL->register_action_map(array(
'add-response' => 'edit_response.inc',
'save-response' => 'edit_response.inc',
'delete-response' => 'responses.inc',
+ 'delete-identity' => 'identities.inc',
+ 'upload-display' => 'upload.inc',
));
@@ -343,7 +345,7 @@ function rcmail_user_prefs($current = null)
if (is_array($meta) && $meta['name']) {
$skinname = $meta['name'];
$author_link = $meta['url'] ? html::a(array('href' => $meta['url'], 'target' => '_blank'), rcube::Q($meta['author'])) : rcube::Q($meta['author']);
- $license_link = $meta['license-url'] ? html::a(array('href' => $meta['license-url'], 'target' => '_blank'), rcube::Q($meta['license'])) : rcube::Q($meta['license']);
+ $license_link = $meta['license-url'] ? html::a(array('href' => $meta['license-url'], 'target' => '_blank', 'tabindex' => '-1'), rcube::Q($meta['license'])) : rcube::Q($meta['license']);
}
$skinnames[] = mb_strtolower($skinname);
@@ -916,6 +918,20 @@ function rcmail_user_prefs($current = null)
);
}
+ if (!isset($no_override['compose_save_localstorage'])) {
+ if (!$current) {
+ continue 2;
+ }
+
+ $field_id = 'rcmfd_compose_save_localstorage';
+ $input = new html_checkbox(array('name' => '_compose_save_localstorage', 'id' => $field_id, 'value' => 1));
+
+ $blocks['advanced']['options']['compose_save_localstorage'] = array(
+ 'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('savelocalstorage'))),
+ 'content' => $input->show($config['compose_save_localstorage']?1:0),
+ );
+ }
+
break;
// Addressbook config
@@ -1300,21 +1316,20 @@ function rcmail_update_folder_row($name, $oldname=null, $subscribe=false, $class
$protect_folders = $RCMAIL->config->get('protect_default_folders');
$storage = $RCMAIL->get_storage();
$delimiter = $storage->get_hierarchy_delimiter();
- $name_utf8 = rcube_charset::convert($name, 'UTF7-IMAP');
- $protected = $protect_folders && $storage->is_special_folder($name);
+ $name_utf8 = rcube_charset::convert($name, 'UTF7-IMAP');
+ $protected = $protect_folders && $storage->is_special_folder($name);
$foldersplit = explode($delimiter, $storage->mod_folder($name));
$level = count($foldersplit) - 1;
- $display_name = str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;', $level)
- . rcube::Q($protected ? $RCMAIL->localize_foldername($name) : rcube_charset::convert($foldersplit[$level], 'UTF7-IMAP'));
+ $display_name = $protected ? $RCMAIL->localize_foldername($name) : rcube_charset::convert($foldersplit[$level], 'UTF7-IMAP');
+ $class_name = trim($class_name . ' mailbox');
if ($oldname === null) {
- $OUTPUT->command('add_folder_row', $name_utf8, $display_name, $protected, $subscribe,
- false, $class_name);
+ $OUTPUT->command('add_folder_row', $name, $name_utf8, $display_name, $protected, $subscribe,
+ $class_name);
}
else {
- $OUTPUT->command('replace_folder_row', rcube_charset::convert($oldname, 'UTF7-IMAP'),
- $name_utf8, $display_name, $protected, $class_name);
+ $OUTPUT->command('replace_folder_row', $oldname, $name, $name_utf8, $display_name, $protected, $class_name);
}
}
@@ -1332,7 +1347,7 @@ function rcmail_settings_tabs($attrib)
array('command' => 'preferences', 'type' => 'link', 'label' => 'preferences', 'title' => 'editpreferences'),
array('command' => 'folders', 'type' => 'link', 'label' => 'folders', 'title' => 'managefolders'),
array('command' => 'identities', 'type' => 'link', 'label' => 'identities', 'title' => 'manageidentities'),
- array('command' => 'responses', 'type' => 'link', 'label' => 'responses', 'title' => 'editresponses'),
+ array('command' => 'responses', 'type' => 'link', 'label' => 'responses', 'title' => 'manageresponses'),
);
// get all identites from DB and define list of cols to be displayed
diff --git a/program/steps/settings/identities.inc b/program/steps/settings/identities.inc
index e19c16c79..f43edc1f7 100644
--- a/program/steps/settings/identities.inc
+++ b/program/steps/settings/identities.inc
@@ -19,6 +19,28 @@
+-----------------------------------------------------------------------+
*/
+if ($RCMAIL->action == 'delete-identity' && $OUTPUT->ajax_call) {
+ $iid = rcube_utils::get_input_value('_iid', rcube_utils::INPUT_POST);
+
+ if ($iid && preg_match('/^[0-9]+(,[0-9]+)*$/', $iid)) {
+ $plugin = $RCMAIL->plugins->exec_hook('identity_delete', array('id' => $iid));
+
+ $deleted = !$plugin['abort'] ? $RCMAIL->user->delete_identity($iid) : $plugin['result'];
+
+ if ($deleted > 0 && $deleted !== false) {
+ $OUTPUT->show_message('deletedsuccessfully', 'confirmation', null, false);
+ $OUTPUT->command('remove_identity', $iid);
+ }
+ else {
+ $msg = $plugin['message'] ? $plugin['message'] : ($deleted < 0 ? 'nodeletelastidentity' : 'errorsaving');
+ $OUTPUT->show_message($msg, 'error', null, false);
+ }
+ }
+
+ $OUTPUT->send();
+}
+
+
define('IDENTITIES_LEVEL', intval($RCMAIL->config->get('identities_level', 0)));
$OUTPUT->set_pagetitle($RCMAIL->gettext('identities'));
diff --git a/program/steps/settings/responses.inc b/program/steps/settings/responses.inc
index 06093b3b8..117e17f97 100644
--- a/program/steps/settings/responses.inc
+++ b/program/steps/settings/responses.inc
@@ -51,8 +51,8 @@ if (!empty($_POST['_insert'])) {
$RCMAIL->output->send();
}
-if ($RCMAIL->action == 'delete-response') {
- if ($key = rcube_utils::get_input_value('_key', rcube_utils::INPUT_GPC)) {
+if ($RCMAIL->action == 'delete-response' && $RCMAIL->output->ajax_call) {
+ if ($key = rcube_utils::get_input_value('_key', rcube_utils::INPUT_POST)) {
$responses = $RCMAIL->get_compose_responses(false, true);
foreach ($responses as $i => $response) {
if (empty($response['key']))
@@ -70,9 +70,7 @@ if ($RCMAIL->action == 'delete-response') {
$RCMAIL->output->command('remove_response', $key);
}
- if ($RCMAIL->output->ajax_call) {
- $RCMAIL->output->send();
- }
+ $RCMAIL->output->send();
}
@@ -95,7 +93,7 @@ function rcmail_responses_list($attrib)
{
global $RCMAIL, $OUTPUT;
- $attrib += array('id' => 'rcmresponseslist', 'tagname' => 'table', 'cols' => 1);
+ $attrib += array('id' => 'rcmresponseslist', 'tagname' => 'table');
$plugin = $RCMAIL->plugins->exec_hook('responses_list', array(
'list' => $RCMAIL->get_compose_responses(true),
diff --git a/program/steps/settings/save_folder.inc b/program/steps/settings/save_folder.inc
index d1449bb38..b8fc49060 100644
--- a/program/steps/settings/save_folder.inc
+++ b/program/steps/settings/save_folder.inc
@@ -24,12 +24,10 @@
// init IMAP connection
$STORAGE = $RCMAIL->get_storage();
-$name = trim(rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST, true));
-$old = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
-$path = rcube_utils::get_input_value('_parent', rcube_utils::INPUT_POST, true);
-
+$name = trim(rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST, true));
+$path = rcube_utils::get_input_value('_parent', rcube_utils::INPUT_POST, true);
+$old_imap = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
$name_imap = rcube_charset::convert($name, RCUBE_CHARSET, 'UTF7-IMAP');
-$old_imap = rcube_charset::convert($old, RCUBE_CHARSET, 'UTF7-IMAP');
// $path is in UTF7-IMAP already
$delimiter = $STORAGE->get_hierarchy_delimiter();
@@ -96,7 +94,7 @@ else {
}
// create a new mailbox
-if (!$error && !strlen($old)) {
+if (!$error && !strlen($old_imap)) {
$folder['subscribe'] = true;
$plugin = $RCMAIL->plugins->exec_hook('folder_create', array('record' => $folder));
@@ -115,15 +113,13 @@ if (!$error && !strlen($old)) {
if (isset($_POST['_viewmode'])) {
$a_threaded = (array) $RCMAIL->config->get('message_threading', array());
- if ($_POST['_viewmode'])
- $a_threaded[$folder['name']] = true;
- else
- unset($a_threaded[$folder['name']]);
+ $a_threaded[$folder['name']] = (bool) $_POST['_viewmode'];
$RCMAIL->user->save_prefs(array('message_threading' => $a_threaded));
}
rcmail_update_folder_row($folder['name'], null, $folder['subscribe'], $folder['class']);
+
$OUTPUT->show_message('foldercreated', 'confirmation');
// reset folder preview frame
$OUTPUT->command('subscription_select');
@@ -167,19 +163,18 @@ else if (!$error) {
}
else if (preg_match($oldprefix, $key)) {
unset($a_threaded[$key]);
- $a_threaded[preg_replace($oldprefix, $folder['name'].$delimiter, $key)] = true;
+ $a_threaded[preg_replace($oldprefix, $folder['name'].$delimiter, $key)] = $val;
}
}
}
- if ($_POST['_viewmode'])
- $a_threaded[$folder['name']] = true;
- else
- unset($a_threaded[$folder['name']]);
+
+ $a_threaded[$folder['name']] = (bool) $_POST['_viewmode'];
$RCMAIL->user->save_prefs(array('message_threading' => $a_threaded));
}
$OUTPUT->show_message('folderupdated', 'confirmation');
+ $OUTPUT->set_env('folder', $folder['name']);
if ($rename) {
// #1488692: update session
diff --git a/program/steps/settings/save_identity.inc b/program/steps/settings/save_identity.inc
index 77245b988..de0c84c91 100644
--- a/program/steps/settings/save_identity.inc
+++ b/program/steps/settings/save_identity.inc
@@ -79,8 +79,11 @@ foreach ($email_checks as $email) {
}
}
-// XSS protection in HTML signature (#1489251)
if (!empty($save_data['signature']) && !empty($save_data['html_signature'])) {
+ // replace uploaded images with data URIs
+ $save_data['signature'] = rcmail_attach_images($save_data['signature']);
+
+ // XSS protection in HTML signature (#1489251)
$save_data['signature'] = rcmail_wash_html($save_data['signature']);
// clear POST data of signature, we want to use safe content
@@ -191,6 +194,35 @@ else {
/**
+ * Attach uploaded images into signature as data URIs
+ */
+function rcmail_attach_images($html)
+{
+ global $RCMAIL;
+
+ $offset = 0;
+ $regexp = '/\s(poster|src)\s*=\s*[\'"]*\S+upload-display\S+file=rcmfile([0-9]+)[\s\'"]*/';
+
+ while (preg_match($regexp, $html, $matches, 0, $offset)) {
+ $file_id = $matches[2];
+ $data_uri = ' ';
+
+ if ($file_id && ($file = $_SESSION['identity']['files'][$file_id])) {
+ $file = $RCMAIL->plugins->exec_hook('attachment_get', $file);
+
+ $data_uri .= 'src="data:' . $file['mimetype'] . ';base64,';
+ $data_uri .= base64_encode($file['data'] ? $file['data'] : file_get_contents($file['path']));
+ $data_uri .= '" ';
+ }
+
+ $html = str_replace($matches[0], $data_uri, $html);
+ $offset += strlen($data_uri) - strlen($matches[0]) + 1;
+ }
+
+ return $html;
+}
+
+/**
* Sanity checks/cleanups on HTML body of signature
*/
function rcmail_wash_html($html)
diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc
index 7a17f21f4..f0ce9c9a3 100644
--- a/program/steps/settings/save_prefs.inc
+++ b/program/steps/settings/save_prefs.inc
@@ -90,6 +90,7 @@ case 'compose':
'default_font_size' => rcube_utils::get_input_value('_default_font_size', rcube_utils::INPUT_POST),
'reply_all_mode' => intval($_POST['_reply_all_mode']),
'forward_attachment' => !empty($_POST['_forward_attachment']),
+ 'compose_save_localstorage' => intval($_POST['_compose_save_localstorage']),
);
break;
diff --git a/program/steps/settings/upload.inc b/program/steps/settings/upload.inc
new file mode 100644
index 000000000..41e19f8fa
--- /dev/null
+++ b/program/steps/settings/upload.inc
@@ -0,0 +1,144 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | program/steps/settings/upload.inc |
+ | |
+ | This file is part of the Roundcube Webmail client |
+ | Copyright (C) 2005-2014, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ | PURPOSE: |
+ | Handles image uploads |
+ | |
+ +-----------------------------------------------------------------------+
+ | Author: Aleksander Machniak <alec@alec.pl> |
+ +-----------------------------------------------------------------------+
+*/
+
+// Upload progress update
+if (!empty($_GET['_progress'])) {
+ $RCMAIL->upload_progress();
+}
+
+$from = rcube_utils::get_input_value('_from', rcube_utils::INPUT_GET);
+$type = str_replace('edit-', '', $from);
+
+if ($RCMAIL->action == 'upload-display') {
+ $id = 'undefined';
+
+ if (preg_match('/^rcmfile(\w+)$/', $_GET['_file'], $regs)) {
+ $id = $regs[1];
+ }
+
+ $RCMAIL->display_uploaded_file($_SESSION[$type]['files'][$id]);
+
+ exit;
+}
+
+
+// Supported image format types
+$IMAGE_TYPES = explode(',', 'jpeg,jpg,jp2,tiff,tif,bmp,eps,gif,png,png8,png24,png32,svg,ico');
+
+// clear all stored output properties (like scripts and env vars)
+$OUTPUT->reset();
+
+$max_size = $RCMAIL->config->get($type . '_image_size', 64) * 1024;
+$post_size = $RCMAIL->show_bytes(parse_bytes(ini_get('upload_max_filesize')));
+$uploadid = rcube_utils::get_input_value('_uploadid', rcube_utils::INPUT_GET);
+
+
+if (is_array($_FILES['_file']['tmp_name'])) {
+ $multiple = count($_FILES['_file']['tmp_name']) > 1;
+
+ foreach ($_FILES['_file']['tmp_name'] as $i => $filepath) {
+ // Process uploaded attachment if there is no error
+ $err = $_FILES['_file']['error'][$i];
+
+ if (!$err) {
+ if ($max_size < $_FILES['_file']['size'][$i]) {
+ $err = 'size_error';
+ }
+ // check image file type
+ else {
+ $image = new rcube_image($filepath);
+ $imageprop = $image->props();
+
+ if (!in_array(strtolower($imageprop['type']), $IMAGE_TYPES)) {
+ $err = 'type_error';
+ }
+ }
+ }
+
+ // save uploaded image in storage backend
+ if (!$err) {
+ $attachment = $RCMAIL->plugins->exec_hook('attachment_upload', array(
+ 'path' => $filepath,
+ 'size' => $_FILES['_file']['size'][$i],
+ 'name' => $_FILES['_file']['name'][$i],
+ 'mimetype' => 'image/' . $imageprop['type'],
+ 'group' => $type,
+ ));
+ }
+
+ if (!$err && $attachment['status'] && !$attachment['abort']) {
+ $id = $attachment['id'];
+
+ // store new file in session
+ unset($attachment['status'], $attachment['abort']);
+ $RCMAIL->session->append($type . '.files', $id, $attachment);
+
+ $content = rcube::Q($attachment['name']);
+
+ $OUTPUT->command('add2attachment_list', "rcmfile$id", array(
+ 'html' => $content,
+ 'name' => $attachment['name'],
+ 'mimetype' => $attachment['mimetype'],
+ 'classname' => rcube_utils::file2class($attachment['mimetype'], $attachment['name']),
+ 'complete' => true
+ ),
+ $uploadid
+ );
+ }
+ else {
+ if ($err == 'type_error') {
+ $msg = $RCMAIL->gettext('invalidimageformat');
+ }
+ else if ($err == 'size_error') {
+ $msg = $RCMAIL->gettext(array('name' => 'filesizeerror', 'vars' => array('size' => $max_size)));
+ }
+ else if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
+ $msg = $RCMAIL->gettext(array('name' => 'filesizeerror', 'vars' => array('size' => $post_size)));
+ }
+ else if ($attachment['error']) {
+ $msg = $attachment['error'];
+ }
+ else {
+ $msg = $RCMAIL->gettext('fileuploaderror');
+ }
+
+ $OUTPUT->command('display_message', $msg, 'error');
+ }
+ }
+}
+else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+ // if filesize exceeds post_max_size then $_FILES array is empty,
+ // show filesizeerror instead of fileuploaderror
+ if ($maxsize = ini_get('post_max_size')) {
+ $msg = $RCMAIL->gettext(array(
+ 'name' => 'filesizeerror',
+ 'vars' => array('size' => $RCMAIL->show_bytes(parse_bytes($maxsize)))
+ ));
+ }
+ else {
+ $msg = $RCMAIL->gettext('fileuploaderror');
+ }
+
+ $OUTPUT->command('display_message', $msg, 'error');
+ $OUTPUT->command('remove_from_attachment_list', $uploadid);
+}
+
+$OUTPUT->send('iframe');
diff --git a/program/steps/utils/html2text.inc b/program/steps/utils/html2text.inc
index 58df34bd0..f6e2bec4d 100644
--- a/program/steps/utils/html2text.inc
+++ b/program/steps/utils/html2text.inc
@@ -21,6 +21,11 @@
$html = stream_get_contents(fopen('php://input', 'r'));
+// strip slashes if magic_quotes enabled
+if (get_magic_quotes_gpc() || get_magic_quotes_runtime()) {
+ $html = stripslashes($html);
+}
+
// Replace emoticon images with its text representation
$html = $RCMAIL->replace_emoticons($html);
diff --git a/program/steps/utils/spell_html.inc b/program/steps/utils/spell_html.inc
index 5935dc13f..6722f8787 100644
--- a/program/steps/utils/spell_html.inc
+++ b/program/steps/utils/spell_html.inc
@@ -19,31 +19,28 @@
+-----------------------------------------------------------------------+
*/
-// read input data
-$data = file_get_contents('php://input');
-// Decode JSON input
-$request = json_decode($data, true);
+$method = rcube_utils::get_input_value('method', rcube_utils::INPUT_POST);
+$lang = rcube_utils::get_input_value('lang', rcube_utils::INPUT_POST);
$result = array();
-$lang = $request['params'][0];
-$data = $request['params'][1];
-$data = implode("\n", (array) $data);
-
-$result['id'] = $request['id'];
-
$spellchecker = new rcube_spellchecker($lang);
-if ($request['method'] == 'checkWords') {
- $result['result'] = empty($data) ? array() : $spellchecker->get_words($data);
-}
-else if ($request['method'] == 'getSuggestions') {
- $result['result'] = $spellchecker->get_suggestions($data);
-}
-else if ($request['method'] == 'learnWord') {
+if ($method == 'addToDictionary') {
+ $data = rcube_utils::get_input_value('word', rcube_utils::INPUT_POST);
+
$spellchecker->add_word($data);
$result['result'] = true;
}
+else {
+ $data = rcube_utils::get_input_value('text', rcube_utils::INPUT_POST, true);
+ $data = html_entity_decode($data, ENT_QUOTES, RCUBE_CHARSET);
+
+ if ($data && !$spellchecker->check($data)) {
+ $result['words'] = $spellchecker->get();
+ $result['dictionary'] = (bool) $RCMAIL->config->get('spellcheck_dictionary');
+ }
+}
if ($error = $spellchecker->error()) {
rcube::raise_error(array('code' => 500, 'type' => 'php',
@@ -51,12 +48,11 @@ if ($error = $spellchecker->error()) {
'message' => sprintf("Spell check engine error: " . $error)),
true, false);
- echo '{"error":{"errstr":"' . addslashes($error) . '","errfile":"","errline":null,"errcontext":"","level":"FATAL"}}';
+ echo json_encode(array('error' => $error));
exit;
}
// send output
-header("Content-Type: text/xml; charset=".RCUBE_CHARSET);
+header("Content-Type: application/json; charset=".RCUBE_CHARSET);
echo json_encode($result);
exit;
-
diff --git a/program/steps/utils/text2html.inc b/program/steps/utils/text2html.inc
new file mode 100644
index 000000000..56d15fa19
--- /dev/null
+++ b/program/steps/utils/text2html.inc
@@ -0,0 +1,33 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | program/steps/utils/text2html.inc |
+ | |
+ | This file is part of the Roundcube Webmail client |
+ | Copyright (C) 2005-2014, The Roundcube Dev Team |
+ | |
+ | Licensed under the GNU General Public License version 3 or |
+ | any later version with exceptions for skins & plugins. |
+ | See the README file for a full license statement. |
+ | |
+ | PURPOSE: |
+ | Convert plain text to HTML |
+ | |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com> |
+ +-----------------------------------------------------------------------+
+*/
+
+$text = stream_get_contents(fopen('php://input', 'r'));
+
+// strip slashes if magic_quotes enabled
+if (get_magic_quotes_gpc() || get_magic_quotes_runtime()) {
+ $html = stripslashes($html);
+}
+
+$converter = new rcube_text2html($text, false, array('wrap' => true));
+
+header('Content-Type: text/html; charset=' . RCUBE_CHARSET);
+print $converter->get_html();
+exit;