diff options
Diffstat (limited to 'program/steps')
32 files changed, 2087 insertions, 1359 deletions
diff --git a/program/steps/addressbook/copy.inc b/program/steps/addressbook/copy.inc index 480a9b52e..d4387194a 100644 --- a/program/steps/addressbook/copy.inc +++ b/program/steps/addressbook/copy.inc @@ -57,10 +57,16 @@ foreach ($cids as $source => $cid) foreach ($cid as $cid) { $a_record = $CONTACTS->get_record($cid, true); + // avoid copying groups + if ($a_record['_type'] == 'group') + continue; + // Check if contact exists, if so, we'll need it's ID // Note: Some addressbooks allows empty email address field - if (!empty($a_record['email'])) - $result = $TARGET->search('email', $a_record['email'], 1, true, true); + // @TODO: should we check all email addresses? + $email = $CONTACTS->get_col_values('email', $a_record, true); + if (!empty($email)) + $result = $TARGET->search('email', $email[0], 1, true, true); else if (!empty($a_record['name'])) $result = $TARGET->search('name', $a_record['name'], 1, true, true); else @@ -114,7 +120,7 @@ foreach ($cids as $source => $cid) } } -if ($success == 0) +if (!$success) $OUTPUT->show_message($errormsg, 'error'); else $OUTPUT->show_message('copysuccess', 'notice', array('nr' => $success)); diff --git a/program/steps/addressbook/delete.inc b/program/steps/addressbook/delete.inc index 56118583c..3bb2ef500 100644 --- a/program/steps/addressbook/delete.inc +++ b/program/steps/addressbook/delete.inc @@ -68,48 +68,14 @@ foreach ($cids as $source => $cid) $page = isset($_SESSION['page']) ? $_SESSION['page'] : 1; // update saved search after data changed -if (($search_request = $_REQUEST['_search']) && isset($_SESSION['search'][$search_request])) { - $sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name'); - $afields = $RCMAIL->config->get('contactlist_fields'); - $search = (array)$_SESSION['search'][$search_request]; - $records = array(); - - // Get records from all sources (refresh search) - foreach ($search as $s => $set) { - $source = $RCMAIL->get_address_book($s); - - // reset page - $source->set_page(1); - $source->set_pagesize(9999); - $source->set_search_set($set); - - // get records - $result = $source->list_records($afields); - - if (!$result->count) { - unset($search[$s]); - continue; - } - - while ($row = $result->next()) { - $row['sourceid'] = $s; - $key = rcube_addressbook::compose_contact_key($row, $sort_col); - $records[$key] = $row; - } - unset($result); - - $search[$s] = $source->get_search_set(); - } - - $_SESSION['search'][$search_request] = $search; - +if (($records = rcmail_search_update(true)) !== false) { // create resultset object $count = count($records); $first = ($page-1) * $PAGE_SIZE; $result = new rcube_result_set($count, $first); + $pages = ceil((count($records) + $delcnt) / $PAGE_SIZE); // get records from the next page to add to the list - $pages = ceil((count($records) + $delcnt) / $PAGE_SIZE); if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) { // sort the records ksort($records, SORT_LOCALE_STRING); diff --git a/program/steps/addressbook/export.inc b/program/steps/addressbook/export.inc index 15bf8b0d4..761f26b75 100644 --- a/program/steps/addressbook/export.inc +++ b/program/steps/addressbook/export.inc @@ -138,7 +138,9 @@ header('Content-Disposition: attachment; filename="contacts.vcf"'); while ($result && ($row = $result->next())) { // we already have a vcard record if ($row['vcard'] && $row['name']) { - $row['vcard'] = preg_replace('/\r?\n/', rcube_vcard::$eol, $row['vcard']); + // fix folding and end-of-line chars + $row['vcard'] = preg_replace('/\r|\n\s+/', '', $row['vcard']); + $row['vcard'] = preg_replace('/\n/', rcube_vcard::$eol, $row['vcard']); echo rcube_vcard::rfc2425_fold($row['vcard']) . rcube_vcard::$eol; } // copy values into vcard object diff --git a/program/steps/addressbook/func.inc b/program/steps/addressbook/func.inc index ffc0b3b92..8ec581f9a 100644 --- a/program/steps/addressbook/func.inc +++ b/program/steps/addressbook/func.inc @@ -167,7 +167,7 @@ function rcmail_set_sourcename($abook) // get address book name (for display) if ($abook && $_SESSION['addressbooks_count'] > 1) { $name = $abook->get_name(); - if (!$name && $source == 0) { + if (!$name) { $name = rcube_label('personaladrbook'); } $OUTPUT->set_env('sourcename', html_entity_decode($name, ENT_COMPAT, 'UTF-8')); @@ -183,7 +183,6 @@ function rcmail_directory_list($attrib) $attrib['id'] = 'rcmdirectorylist'; $out = ''; - $local_id = '0'; $jsdata = array(); $line_templ = html::tag('li', array( @@ -270,7 +269,6 @@ function rcmail_contact_groups($args) $groups_html = ''; $groups = $RCMAIL->get_address_book($args['source'])->list_groups(); - $js_id = $RCMAIL->JQ($args['source']); if (!empty($groups)) { $line_templ = html::tag('li', array( @@ -283,7 +281,6 @@ function rcmail_contact_groups($args) $is_collapsed = strpos($RCMAIL->config->get('collapsed_abooks',''), '&'.rawurlencode($args['source']).'&') !== false; $args['out'] .= html::div('treetoggle ' . ($is_collapsed ? 'collapsed' : 'expanded'), ' '); - $jsdata = array(); foreach ($groups as $group) { $groups_html .= sprintf($line_templ, rcube_utils::html_identifier('G' . $args['source'] . $group['ID'], true), @@ -297,7 +294,7 @@ function rcmail_contact_groups($args) } $args['out'] .= html::tag('ul', - array('class' => 'groups', 'style' => ($is_collapsed ? "display:none;" : null)), + array('class' => 'groups', 'style' => ($is_collapsed || empty($groups) ? "display:none;" : null)), $groups_html); return $args; @@ -310,7 +307,7 @@ function rcmail_contacts_list($attrib) global $CONTACTS, $OUTPUT; // define list of cols to be displayed - $a_show_cols = array('name'); + $a_show_cols = array('name','action'); // add id to message list table if not specified if (!strlen($attrib['id'])) @@ -325,7 +322,7 @@ function rcmail_contacts_list($attrib) $OUTPUT->include_script('list.js'); // add some labels to client - $OUTPUT->add_label('deletecontactconfirm', 'copyingcontact', 'contactdeleting'); + $OUTPUT->add_label('deletecontactconfirm', 'copyingcontact', 'movingcontact', 'contactdeleting'); return $out; } @@ -339,31 +336,73 @@ function rcmail_js_contacts_list($result, $prefix='') return; // define list of cols to be displayed - $a_show_cols = array('name'); + $a_show_cols = array('name','action'); while ($row = $result->next()) { + $row['CID'] = $row['ID']; + $row['email'] = reset(rcube_addressbook::get_col_values('email', $row, true)); + + $source_id = $OUTPUT->get_env('source'); $a_row_cols = array(); - $classes = array('person'); // org records will follow some day + $classes = array($row['_type'] ? $row['_type'] : 'person'); // build contact ID with source ID if (isset($row['sourceid'])) { $row['ID'] = $row['ID'].'-'.$row['sourceid']; + $source_id = $row['sourceid']; } // format each col foreach ($a_show_cols as $col) { - $val = $col == 'name' ? rcube_addressbook::compose_list_name($row) : $row[$col]; - $a_row_cols[$col] = Q($val); + $val = ''; + switch ($col) { + case 'name': + $val = Q(rcube_addressbook::compose_list_name($row)); + break; + + case 'action': + if ($row['_type'] == 'group') { + $val = html::a(array( + 'href' => '#list', + 'rel' => $row['ID'], + 'title' => rcube_label('listgroup'), + 'onclick' => sprintf("return %s.command('pushgroup',{'source':'%s','id':'%s'},this,event)", JS_OBJECT_NAME, $source_id, $row['CID']), + ), '»'); + } + else + $val = ' '; + break; + + default: + $val = Q($row[$col]); + break; + } + + $a_row_cols[$col] = $val; } if ($row['readonly']) $classes[] = 'readonly'; - $OUTPUT->command($prefix.'add_contact_row', $row['ID'], $a_row_cols, join(' ', $classes)); + $OUTPUT->command($prefix.'add_contact_row', $row['ID'], $a_row_cols, join(' ', $classes), array_intersect_key($row, array('ID'=>1,'readonly'=>1,'_type'=>1,'email'=>1,'name'=>1))); } } +function rcmail_contacts_list_title($attrib) +{ + global $OUTPUT; + + $attrib += array('label' => 'contacts', 'id' => 'rcmabooklisttitle', 'tag' => 'span'); + unset($attrib['name']); + + $OUTPUT->add_gui_object('addresslist_title', $attrib['id']); + $OUTPUT->add_label('contacts'); + + return html::tag($attrib['tag'], $attrib, rcube_label($attrib['label']), html::$common_attrib); +} + + // similar function as /steps/settings/identities.inc::rcmail_identity_frame() function rcmail_contact_frame($attrib) { @@ -432,7 +471,7 @@ function rcmail_get_type_label($type) function rcmail_contact_form($form, $record, $attrib = null) { - global $RCMAIL, $CONFIG; + global $RCMAIL; // Allow plugins to modify contact form content $plugin = $RCMAIL->plugins->exec_hook('contact_form', array( @@ -441,7 +480,7 @@ function rcmail_contact_form($form, $record, $attrib = null) $form = $plugin['form']; $record = $plugin['record']; $edit_mode = $RCMAIL->action != 'show'; - $del_button = $attrib['deleteicon'] ? html::img(array('src' => $CONFIG['skin_path'] . $attrib['deleteicon'], 'alt' => rcube_label('delete'))) : rcube_label('delete'); + $del_button = $attrib['deleteicon'] ? html::img(array('src' => $RCMAIL->output->get_skin_file($attrib['deleteicon']), 'alt' => rcube_label('delete'))) : rcube_label('delete'); unset($attrib['deleteicon']); $out = ''; @@ -554,22 +593,13 @@ function rcmail_contact_form($form, $record, $attrib = null) // iterate over possible subtypes and collect values with their subtype if (is_array($colprop['subtypes'])) { $values = $subtypes = array(); - foreach ($colprop['subtypes'] as $i => $st) { - $newval = false; - if ($record[$field.':'.$st]) { - $subtypes[count($values)] = $st; - $newval = $record[$field.':'.$st]; - } - else if ($i == 0 && $record[$field]) { - $subtypes[count($values)] = $st; - $newval = $record[$field]; - } - if ($newval !== false) { - if (is_array($newval) && isset($newval[0])) - $values = array_merge($values, $newval); - else - $values[] = $newval; + foreach (rcube_addressbook::get_col_values($field, $record) as $st => $vals) { + foreach((array)$vals as $value) { + $i = count($values); + $subtypes[$i] = $st; + $values[$i] = $value; } + // TODO: add $st to $select_subtype if missing ? } } else { @@ -707,12 +737,15 @@ function rcmail_contact_form($form, $record, $attrib = null) function rcmail_contact_photo($attrib) { - global $SOURCE_ID, $CONTACTS, $CONTACT_COLTYPES, $RCMAIL, $CONFIG; + global $SOURCE_ID, $CONTACTS, $CONTACT_COLTYPES, $RCMAIL; if ($result = $CONTACTS->get_result()) $record = $result->first(); - $photo_img = $attrib['placeholder'] ? $CONFIG['skin_path'] . $attrib['placeholder'] : 'program/resources/blank.gif'; + $photo_img = $attrib['placeholder'] ? $RCMAIL->output->get_skin_file($attrib['placeholder']) : 'program/resources/blank.gif'; + if ($record['_type'] == 'group' && $attrib['placeholdergroup']) + $photo_img = $RCMAIL->output->get_skin_file($attrib['placeholdergroup']); + $RCMAIL->output->set_env('photo_placeholder', $photo_img); unset($attrib['placeholder']); @@ -746,6 +779,54 @@ function rcmail_format_date_col($val) return format_date($val, $RCMAIL->config->get('date_format', 'Y-m-d'), false); } +/** + * Updates saved search after data changed + */ +function rcmail_search_update($return = false) +{ + global $RCMAIL; + + if (($search_request = $_REQUEST['_search']) && isset($_SESSION['search'][$search_request])) { + $search = (array)$_SESSION['search'][$search_request]; + $sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name'); + $afields = $return ? $RCMAIL->config->get('contactlist_fields') : array('name', 'email'); + $records = array(); + + foreach ($search as $s => $set) { + $source = $RCMAIL->get_address_book($s); + + // reset page + $source->set_page(1); + $source->set_pagesize(9999); + $source->set_search_set($set); + + // get records + $result = $source->list_records($afields); + + if (!$result->count) { + unset($search[$s]); + continue; + } + + if ($return) { + while ($row = $result->next()) { + $row['sourceid'] = $s; + $key = rcube_addressbook::compose_contact_key($row, $sort_col); + $records[$key] = $row; + } + unset($result); + } + + $search[$s] = $source->get_search_set(); + } + + $_SESSION['search'][$search_request] = $search; + + return $records; + } + + return false; +} /** * Returns contact ID(s) and source(s) from GET/POST data @@ -787,7 +868,7 @@ function rcmail_get_cids($filter = null) } } else { - if (substr($id, -($got_source+1)) == "-$source") { + if (substr($id, -($got_source+1)) === "-$source") { $id = substr($id, 0, -($got_source+1)); } $result[$source][] = $id; @@ -803,6 +884,7 @@ $OUTPUT->add_handlers(array( 'directorylist' => 'rcmail_directory_list', // 'groupslist' => 'rcmail_contact_groups', 'addresslist' => 'rcmail_contacts_list', + 'addresslisttitle' => 'rcmail_contacts_list_title', 'addressframe' => 'rcmail_contact_frame', 'recordscountdisplay' => 'rcmail_rowcount_display', 'searchform' => array($OUTPUT, 'search_form') diff --git a/program/steps/addressbook/import.inc b/program/steps/addressbook/import.inc index df07d64bc..915aac884 100644 --- a/program/steps/addressbook/import.inc +++ b/program/steps/addressbook/import.inc @@ -88,7 +88,7 @@ function rcmail_import_confirm($attrib) $content = html::p(null, rcube_label(array( 'name' => 'importconfirm', - 'nr' => $IMORT_STATS->inserted, + 'nr' => $IMPORT_STATS->inserted, 'vars' => $vars, )) . ($IMPORT_STATS->names ? ':' : '.')); @@ -98,7 +98,7 @@ function rcmail_import_confirm($attrib) if ($IMPORT_STATS->skipped) { $content .= html::p(null, rcube_label(array( 'name' => 'importconfirmskipped', - 'nr' => $IMORT_STATS->skipped, + 'nr' => $IMPORT_STATS->skipped, 'vars' => $vars, )) . ':'); $content .= html::p('em', join(', ', array_map('Q', $IMPORT_STATS->skipped_names))); @@ -209,6 +209,15 @@ if (is_array($_FILES['_file'])) { foreach ($vcards as $vcard) { $a_record = $vcard->get_assoc(); + // Generate contact's display name (must be before validation), the same we do in save.inc + if (empty($a_record['name'])) { + $a_record['name'] = rcube_addressbook::compose_display_name($a_record, true); + // Reset it if equals to email address (from compose_display_name()) + if ($a_record['name'] == $a_record['email'][0]) { + $a_record['name'] = ''; + } + } + // skip invalid (incomplete) entries if (!$CONTACTS->validate($a_record, true)) { $IMPORT_STATS->invalid++; @@ -250,7 +259,7 @@ if (is_array($_FILES['_file'])) { if ($success) { $IMPORT_STATS->inserted++; - $IMPORT_STATS->names[] = $vcard->displayname ? $vcard->displayname : $email; + $IMPORT_STATS->names[] = $a_record['name'] ? $a_record['name'] : $email; } else { $IMPORT_STATS->errors++; diff --git a/program/steps/addressbook/list.inc b/program/steps/addressbook/list.inc index 1bb28658b..aca58d279 100644 --- a/program/steps/addressbook/list.inc +++ b/program/steps/addressbook/list.inc @@ -19,47 +19,20 @@ +-----------------------------------------------------------------------+ */ -$afields = $RCMAIL->config->get('contactlist_fields'); +if (!empty($_GET['_page'])) + $page = intval($_GET['_page']); +else + $page = !empty($_SESSION['page']) ? $_SESSION['page'] : 1; -// Use search result -if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']])) -{ - $search = (array)$_SESSION['search'][$_REQUEST['_search']]; - $records = array(); - - if (!empty($_GET['_page'])) - $page = intval($_GET['_page']); - else - $page = isset($_SESSION['page']) ? $_SESSION['page'] : 1; - - $_SESSION['page'] = $page; - $sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name'); - - // Get records from all sources - foreach ($search as $s => $set) { - $source = $RCMAIL->get_address_book($s); - - // reset page - $source->set_page(1); - $source->set_pagesize(9999); - $source->set_search_set($set); - - // get records - $result = $source->list_records($afields); - - while ($row = $result->next()) { - $row['sourceid'] = $s; - $key = rcube_addressbook::compose_contact_key($row, $sort_col); - $records[$key] = $row; - } - unset($result); - } +$_SESSION['page'] = $page; +// Use search result +if (($records = rcmail_search_update(true)) !== false) { // sort the records ksort($records, SORT_LOCALE_STRING); // create resultset object - $count = count($records); + $count = count($records); $first = ($page-1) * $PAGE_SIZE; $result = new rcube_result_set($count, $first); @@ -72,6 +45,7 @@ if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search } // List selected directory else { + $afields = $RCMAIL->config->get('contactlist_fields'); $CONTACTS = rcmail_contact_source(null, true); // get contacts for this user @@ -81,6 +55,11 @@ else { $OUTPUT->show_message('contactsearchonly', 'notice'); $OUTPUT->command('command', 'advanced-search'); } + + if ($CONTACTS->group_id) { + $OUTPUT->command('set_group_prop', array('ID' => $CONTACTS->group_id) + + array_intersect_key((array)$CONTACTS->get_group($CONTACTS->group_id), array('name'=>1,'email'=>1))); + } } // update message count display diff --git a/program/steps/addressbook/move.inc b/program/steps/addressbook/move.inc new file mode 100644 index 000000000..f8204e9ee --- /dev/null +++ b/program/steps/addressbook/move.inc @@ -0,0 +1,208 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/steps/addressbook/move.inc | + | | + | This file is part of the Roundcube Webmail client | + | Copyright (C) 2007-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: | + | Move a contact record from one direcotry to another | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + | Author: Aleksander Machniak <alec@alec.pl> | + +-----------------------------------------------------------------------+ +*/ + +// only process ajax requests +if (!$OUTPUT->ajax_call) { + return; +} + +$cids = rcmail_get_cids(); +$target = get_input_value('_to', RCUBE_INPUT_POST); +$target_group = get_input_value('_togid', RCUBE_INPUT_POST); + +$all = 0; +$deleted = 0; +$success = 0; +$errormsg = 'moveerror'; +$maxnum = $RCMAIL->config->get('max_group_members', 0); +$page = !empty($_SESSION['page']) ? $_SESSION['page'] : 1; + +foreach ($cids as $source => $source_cids) { + // Something wrong, target not specified + if (!strlen($target)) { + break; + } + + // It maight happen when moving records from search result + // Do nothing, go to next source + if ((string)$target === (string)$source) { + continue; + } + + $CONTACTS = $RCMAIL->get_address_book($source); + $TARGET = $RCMAIL->get_address_book($target); + + if (!$TARGET || !$TARGET->ready || $TARGET->readonly) { + break; + } + + if (!$CONTACTS || !$CONTACTS->ready || $CONTACTS->readonly) { + continue; + } + + $ids = array(); + + foreach ($source_cids as $idx => $cid) { + $a_record = $CONTACTS->get_record($cid, true); + + // avoid moving groups + if ($a_record['_type'] == 'group') { + unset($source_cids[$idx]); + continue; + } + + // Check if contact exists, if so, we'll need it's ID + // Note: Some addressbooks allows empty email address field + // @TODO: should we check all email addresses? + $email = $CONTACTS->get_col_values('email', $a_record, true); + if (!empty($email)) + $result = $TARGET->search('email', $email[0], 1, true, true); + else if (!empty($a_record['name'])) + $result = $TARGET->search('name', $a_record['name'], 1, true, true); + else + $result = new rcube_result_set(); + + // insert contact record + if (!$result->count) { + $plugin = $RCMAIL->plugins->exec_hook('contact_create', array( + 'record' => $a_record, 'source' => $target, 'group' => $target_group)); + + if (!$plugin['abort']) { + if ($insert_id = $TARGET->insert($plugin['record'], false)) { + $ids[] = $insert_id; + $success++; + } + } + else if ($plugin['result']) { + $ids = array_merge($ids, $plugin['result']); + $success++; + } + } + else { + $record = $result->first(); + $ids[] = $record['ID']; + $errormsg = empty($a_record['email']) ? 'contactnameexists' : 'contactexists'; + } + } + + // remove source contacts + if ($success && !empty($source_cids)) { + $all += count($source_cids); + $plugin = $RCMAIL->plugins->exec_hook('contact_delete', array( + 'id' => $source_cids, 'source' => $source)); + + $del_status = !$plugin['abort'] ? $CONTACTS->delete($source_cids) : $plugin['result']; + + if ($del_status) { + $deleted += $del_status; + } + } + + // assign to group + if ($target_group && $TARGET->groups && !empty($ids)) { + $plugin = $RCMAIL->plugins->exec_hook('group_addmembers', array( + 'group_id' => $target_group, 'ids' => $ids, 'source' => $target)); + + if (!$plugin['abort']) { + $TARGET->reset(); + $TARGET->set_group($target_group); + + if ($maxnum && ($TARGET->count()->count + count($plugin['ids']) > $maxnum)) { + $OUTPUT->show_message('maxgroupmembersreached', 'warning', array('max' => $maxnum)); + $OUTPUT->send(); + } + + if (($cnt = $TARGET->add_to_group($target_group, $plugin['ids'])) && $cnt > $success) + $success = $cnt; + } + else if ($plugin['result']) { + $success = $plugin['result']; + } + + $errormsg = $plugin['message'] ? $plugin['message'] : 'moveerror'; + } +} + +if (!$deleted || $deleted != $all) { + // update saved search after data changed + if ($deleted) { + rcmail_search_update(); + } + $OUTPUT->command('list_contacts'); +} +else { + // update saved search after data changed + if (($records = rcmail_search_update(true)) !== false) { + // create resultset object + $count = count($records); + $first = ($page-1) * $PAGE_SIZE; + $result = new rcube_result_set($count, $first); + $pages = ceil((count($records) + $delcnt) / $PAGE_SIZE); + + // get records from the next page to add to the list + if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) { + // sort the records + ksort($records, SORT_LOCALE_STRING); + + $first += $PAGE_SIZE; + // create resultset object + $res = new rcube_result_set($count, $first - $deleted); + + if ($PAGE_SIZE < $count) { + $records = array_slice($records, $first - $deleted, $deleted); + } + + $res->records = array_values($records); + $records = $res; + } + else { + unset($records); + } + } + 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); + + if ($_GET['_from'] != 'show' && $pages > 1 && $page < $pages) { + $CONTACTS->set_page($page); + $records = $CONTACTS->list_records(null, -$deleted); + } + } + + // update message count display + $OUTPUT->set_env('pagecount', ceil($result->count / $PAGE_SIZE)); + $OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result)); + + // add new rows from next page (if any) + if (!empty($records)) { + rcmail_js_contacts_list($records); + } +} + +if (!$success) + $OUTPUT->show_message($errormsg, 'error'); +else + $OUTPUT->show_message('movesuccess', 'notice', array('nr' => $success)); + +// send response +$OUTPUT->send(); diff --git a/program/steps/addressbook/save.inc b/program/steps/addressbook/save.inc index 8cab6e817..e7e5efc63 100644 --- a/program/steps/addressbook/save.inc +++ b/program/steps/addressbook/save.inc @@ -134,11 +134,11 @@ if (!empty($cid)) $record['email'] = reset($CONTACTS->get_col_values('email', $record, true)); $record['name'] = rcube_addressbook::compose_list_name($record); - foreach (array('name', 'email') as $col) + foreach (array('name') as $col) $a_js_cols[] = Q((string)$record[$col]); // update the changed col in list - $OUTPUT->command('parent.update_contact_row', $cid, $a_js_cols, $newcid, $source); + $OUTPUT->command('parent.update_contact_row', $cid, $a_js_cols, $newcid, $source, $record); // show confirmation $OUTPUT->show_message('successfullysaved', 'confirmation', null, false); @@ -192,7 +192,7 @@ else { if (($maxnum = $RCMAIL->config->get('max_group_members', 0)) && ($counts->count + 1 > $maxnum)) $OUTPUT->show_message('maxgroupmembersreached', 'warning', array('max' => $maxnum)); - $CONTACTS->add_to_group($gid, $plugin['ids']); + $CONTACTS->add_to_group($plugin['group_id'], $plugin['ids']); } } else diff --git a/program/steps/addressbook/show.inc b/program/steps/addressbook/show.inc index 16be89f94..950764bb1 100644 --- a/program/steps/addressbook/show.inc +++ b/program/steps/addressbook/show.inc @@ -101,8 +101,6 @@ function rcmail_contact_head($attrib) return false; } - $microformats = array('name' => 'fn', 'email' => 'email'); - $form = array( 'head' => array( // section 'head' is magic! 'content' => array( @@ -177,7 +175,7 @@ function rcmail_contact_details($attrib) } -function rcmail_render_email_value($email, $col) +function rcmail_render_email_value($email) { return html::a(array( 'href' => 'mailto:' . $email, @@ -188,7 +186,7 @@ function rcmail_render_email_value($email, $col) } -function rcmail_render_url_value($url, $col) +function rcmail_render_url_value($url) { $prefix = preg_match('!^(http|ftp)s?://!', $url) ? '' : 'http://'; return html::a(array( @@ -209,9 +207,8 @@ function rcmail_contact_record_groups($contact_id) return ''; } - $table = new html_table(array('cols' => 2, 'cellspacing' => 0, 'border' => 0)); - - $members = $CONTACTS->get_record_groups($contact_id); + $members = $CONTACTS->get_record_groups($contact_id); + $table = new html_table(array('cols' => 2, 'cellspacing' => 0, 'border' => 0)); $checkbox = new html_checkbox(array('name' => '_gid[]', 'class' => 'groupmember', 'disabled' => $CONTACTS->readonly)); @@ -223,7 +220,7 @@ function rcmail_contact_record_groups($contact_id) } $hiddenfields = new html_hiddenfield(array('name' => '_source', 'value' => get_input_value('_source', RCUBE_INPUT_GPC))); - $hiddenfields->add(array('name' => '_cid', 'value' => $record['ID'])); + $hiddenfields->add(array('name' => '_cid', 'value' => $contact_id)); $form_start = $RCMAIL->output->request_form(array( 'name' => "form", 'method' => "post", diff --git a/program/steps/addressbook/undo.inc b/program/steps/addressbook/undo.inc index 9c171143c..c23bd1cb6 100644 --- a/program/steps/addressbook/undo.inc +++ b/program/steps/addressbook/undo.inc @@ -46,30 +46,7 @@ foreach ((array)$undo['data'] as $source => $cid) } // update saved search after data changed -if ($delcnt && ($search_request = $_REQUEST['_search']) && isset($_SESSION['search'][$search_request])) { - $search = (array)$_SESSION['search'][$search_request]; - - foreach ($search as $s => $set) { - $source = $RCMAIL->get_address_book($s); - - // reset page - $source->set_page(1); - $source->set_pagesize(9999); - $source->set_search_set($set); - - // get records - $result = $source->list_records(array('name', 'email')); - - if (!$result->count) { - unset($search[$s]); - continue; - } - - $search[$s] = $source->get_search_set(); - } - - $_SESSION['search'][$search_request] = $search; -} +rcmail_search_update(); $RCMAIL->session->remove('contact_undo'); diff --git a/program/steps/mail/autocomplete.inc b/program/steps/mail/autocomplete.inc index 55579814c..f9e8d71a4 100644 --- a/program/steps/mail/autocomplete.inc +++ b/program/steps/mail/autocomplete.inc @@ -102,7 +102,7 @@ if (!empty($book_types) && strlen($search)) { // also list matching contact groups if ($abook->groups && count($contacts) < $MAXNUM) { - foreach ($abook->list_groups($search) as $group) { + foreach ($abook->list_groups($search, $mode) as $group) { $abook->reset(); $abook->set_group($group['ID']); $group_prop = $abook->get_group($group['ID']); diff --git a/program/steps/mail/check_recent.inc b/program/steps/mail/check_recent.inc index 3649d148c..8c0b1ffc0 100644 --- a/program/steps/mail/check_recent.inc +++ b/program/steps/mail/check_recent.inc @@ -81,9 +81,10 @@ foreach ($a_mailboxes as $mbox_name) { if (empty($_GET['_list'])) continue; - // get overall message count; allow caching because rcube_storage::folder_status() did a refresh + // get overall message count; allow caching because rcube_storage::folder_status() + // did a refresh but only in list mode $list_mode = $RCMAIL->storage->get_threading() ? 'THREADS' : 'ALL'; - $all_count = $RCMAIL->storage->count($mbox_name, $list_mode, false, false); + $all_count = $RCMAIL->storage->count($mbox_name, $list_mode, $list_mode == 'THREADS', false); $page = $RCMAIL->storage->get_page(); $page_size = $RCMAIL->storage->get_pagesize(); diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index c166eb74e..9ffde8a57 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -139,12 +139,11 @@ if (!empty($CONFIG['drafts_mbox'])) { } // set current mailbox in client environment $OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder()); -$OUTPUT->set_env('sig_above', $RCMAIL->config->get('sig_above', false)); $OUTPUT->set_env('top_posting', intval($RCMAIL->config->get('reply_mode')) > 0); $OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ','))); // default font for HTML editor -$font = rcube_fontdefs($RCMAIL->config->get('default_font', 'Verdana')); +$font = rcube_fontdefs($RCMAIL->config->get('default_font')); if ($font && !is_array($font)) { $OUTPUT->set_env('default_font', $font); } @@ -152,6 +151,7 @@ if ($font && !is_array($font)) { // get reference message and set compose mode if ($msg_uid = $COMPOSE['param']['draft_uid']) { $compose_mode = RCUBE_COMPOSE_DRAFT; + $OUTPUT->set_env('draft_id', $msg_uid); $RCMAIL->storage->set_folder($CONFIG['drafts_mbox']); } else if ($msg_uid = $COMPOSE['param']['reply_uid']) { @@ -170,6 +170,9 @@ $OUTPUT->set_env('compose_mode', $compose_mode); $config_show_sig = $RCMAIL->config->get('show_sig', 1); if ($compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT) { // don't add signature in draft/edit mode, we'll also not remove the old-one + // but only on page display, later we should be able to change identity/sig (#1489229) + if ($config_show_sig == 1 || $config_show_sig == 2) + $OUTPUT->set_env('show_sig_later', true); } else if ($config_show_sig == 1) $OUTPUT->set_env('show_sig', true); @@ -219,10 +222,10 @@ if (!empty($msg_uid) && empty($COMPOSE['as_attachment'])) $COMPOSE['param']['sent_mbox'] = $sent_folder; } } - else if ($compose_mode == RCUBE_COMPOSE_DRAFT) { - if ($MESSAGE->headers->others['x-draft-info']) { + else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) { + if ($compose_mode == RCUBE_COMPOSE_DRAFT && ($draft_info = $MESSAGE->headers->get('x-draft-info'))) { // get reply_uid/forward_uid to flag the original message when sending - $info = rcmail_draftinfo_decode($MESSAGE->headers->others['x-draft-info']); + $info = rcmail_draftinfo_decode($draft_info); if ($info['type'] == 'reply') $COMPOSE['reply_uid'] = $info['uid']; @@ -239,10 +242,10 @@ if (!empty($msg_uid) && empty($COMPOSE['as_attachment'])) } } - if ($MESSAGE->headers->in_reply_to) - $COMPOSE['reply_msgid'] = '<'.$MESSAGE->headers->in_reply_to.'>'; + if ($in_reply_to = $MESSAGE->headers->get('in-reply-to')) + $COMPOSE['reply_msgid'] = '<' . $in_reply_to . '>'; - $COMPOSE['references'] = $MESSAGE->headers->references; + $COMPOSE['references'] = $MESSAGE->headers->references; } } else { @@ -327,6 +330,20 @@ foreach ($parts as $header) { $fvalue .= $v; if ($v = $MESSAGE->headers->cc) $fvalue .= (!empty($fvalue) ? $separator : '') . $v; + // Use Sender header (#1489011) + if (($v = $MESSAGE->headers->get('Sender', false)) && strpos($v, '-bounces@') === false) + $fvalue .= (!empty($fvalue) ? $separator : '') . $v; + + // 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); + + if (count($replyto) && !count(array_diff($to, $replyto)) && count(array_diff($from, $to))) { + $fvalue .= (!empty($fvalue) ? $separator : '') . $v; + } + } } } else if (in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) { @@ -386,7 +403,7 @@ function rcmail_compose_headers($attrib) { global $MESSAGE; - list($form_start, $form_end) = get_form_tags($attrib); + list($form_start,) = get_form_tags($attrib); $out = ''; $part = strtolower($attrib['part']); @@ -450,7 +467,7 @@ function rcmail_compose_headers($attrib) function rcmail_compose_header_from($attrib) { - global $MESSAGE, $OUTPUT, $RCMAIL, $compose_mode; + global $MESSAGE, $OUTPUT, $RCMAIL, $COMPOSE, $compose_mode; // pass the following attributes to the form class $field_attrib = array('name' => '_from'); @@ -461,7 +478,8 @@ function rcmail_compose_header_from($attrib) if (count($MESSAGE->identities)) { $a_signatures = array(); - $separator = $RCMAIL->config->get('sig_above') + $identities = array(); + $separator = intval($RCMAIL->config->get('reply_mode')) > 0 && ($compose_mode == RCUBE_COMPOSE_REPLY || $compose_mode == RCUBE_COMPOSE_FORWARD) ? '---' : '-- '; $field_attrib['onchange'] = JS_OBJECT_NAME.".change_identity(this)"; @@ -498,12 +516,21 @@ function rcmail_compose_header_from($attrib) $a_signatures[$identity_id]['text'] = $text; $a_signatures[$identity_id]['html'] = $html; } + + // add bcc and reply-to + if (!empty($sql_arr['reply-to'])) { + $identities[$identity_id]['replyto'] = $sql_arr['reply-to']; + } + if (!empty($sql_arr['bcc'])) { + $identities[$identity_id]['bcc'] = $sql_arr['bcc']; + } } - $out = $select_from->show($MESSAGE->compose['from']); + $out = $select_from->show((int)$MESSAGE->compose['from']); // add signatures to client $OUTPUT->set_env('signatures', $a_signatures); + $OUTPUT->set_env('identities', $identities); } // no identities, display text input field else { @@ -553,7 +580,7 @@ function rcmail_message_is_html() function rcmail_prepare_message_body() { - global $RCMAIL, $MESSAGE, $COMPOSE, $compose_mode, $LINE_LENGTH, $HTML_MODE; + global $RCMAIL, $MESSAGE, $COMPOSE, $compose_mode, $HTML_MODE; // use posted message body if (!empty($_POST['_message'])) { @@ -571,16 +598,33 @@ function rcmail_prepare_message_body() rcmail_write_forward_attachments(); } // reply/edit/draft/forward - else if ($compose_mode && ($compose_mode != RCUBE_COMPOSE_REPLY || $RCMAIL->config->get('reply_mode') != -1)) { - $isHtml = rcmail_compose_editor_mode(); + else if ($compose_mode && ($compose_mode != RCUBE_COMPOSE_REPLY || intval($RCMAIL->config->get('reply_mode')) != -1)) { + $isHtml = rcmail_compose_editor_mode(); + $messages = array(); if (!empty($MESSAGE->parts)) { + // collect IDs of message/rfc822 parts + if ($compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT) { + foreach ($MESSAGE->attachments as $part) { + if ($part->mimetype == 'message/rfc822') { + $messages[] = $part->mime_id; + } + } + } + foreach ($MESSAGE->parts as $part) { // skip no-content and attachment parts (#1488557) if ($part->type != 'content' || !$part->size || $MESSAGE->is_attachment($part)) { continue; } + // skip all content parts inside the message/rfc822 part in DRAFT/EDIT mode + foreach ($messages as $mimeid) { + if (strpos($part->mime_id, $mimeid . '.') === 0) { + continue 2; + } + } + if ($part_body = rcmail_compose_part_body($part, $isHtml)) { $body .= ($body ? ($isHtml ? '<br/>' : "\n") : '') . $part_body; } @@ -626,7 +670,7 @@ function rcmail_prepare_message_body() function rcmail_compose_part_body($part, $isHtml = false) { - global $RCMAIL, $MESSAGE, $compose_mode; + global $RCMAIL, $MESSAGE, $LINE_LENGTH, $compose_mode; // Check if we have enough memory to handle the message in it // #1487424: we need up to 10x more memory than the body @@ -663,6 +707,11 @@ function rcmail_compose_part_body($part, $isHtml = false) $body = rcmail_remove_signature($body); } } + + if ($part->ctype_parameters['format'] == 'flowed') { + $body = rcube_mime::unfold_flowed($body); + } + // add HTML formatting $body = rcmail_plain_body($body); if ($body) { @@ -702,7 +751,7 @@ function rcmail_compose_part_body($part, $isHtml = false) function rcmail_compose_body($attrib) { - global $RCMAIL, $CONFIG, $OUTPUT, $MESSAGE, $compose_mode, $LINE_LENGTH, $HTML_MODE, $MESSAGE_BODY; + global $RCMAIL, $CONFIG, $OUTPUT, $MESSAGE, $compose_mode, $HTML_MODE, $MESSAGE_BODY; list($form_start, $form_end) = get_form_tags($attrib); unset($attrib['form']); @@ -886,8 +935,7 @@ function rcmail_create_forward_body($body, $bodyIsHtml) if (!isset($COMPOSE['forward_attachments']) && is_array($MESSAGE->mime_parts)) $cid_map = rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml); - $date = format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long')); - $charset = $RCMAIL->output->get_charset(); + $date = format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long')); if (!$bodyIsHtml) { $prefix = "\n\n\n-------- " . rcube_label('originalmessage') . " --------\n"; @@ -941,7 +989,7 @@ function rcmail_create_forward_body($body, $bodyIsHtml) function rcmail_create_draft_body($body, $bodyIsHtml) { - global $MESSAGE, $OUTPUT, $COMPOSE; + global $MESSAGE, $COMPOSE; /** * add attachments @@ -989,39 +1037,50 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml) global $RCMAIL, $COMPOSE, $compose_mode; $loaded_attachments = array(); - foreach ((array)$COMPOSE['attachments'] as $id => $attachment) { + foreach ((array)$COMPOSE['attachments'] as $attachment) { $loaded_attachments[$attachment['name'] . $attachment['mimetype']] = $attachment; } - $cid_map = $messages = array(); + $cid_map = array(); + $messages = array(); + foreach ((array)$message->mime_parts as $pid => $part) { if ($part->disposition == 'attachment' || ($part->disposition == 'inline' && $bodyIsHtml) || $part->filename) { - if (($part->ctype_primary == 'message' && $bodyIsHtml) || $part->ctype_primary == 'multipart') { + // skip parts that aren't valid attachments + if ($part->ctype_primary == 'multipart' || $part->mimetype == 'application/ms-tnef') { continue; } - if ($part->mimetype == 'application/ms-tnef') { + // skip message attachments in reply mode + if ($part->ctype_primary == 'message' && $compose_mode == RCUBE_COMPOSE_REPLY) { continue; } - // skip inline images when forwarding in plain text - if ($part->content_id && !$bodyIsHtml && $compose_mode == RCUBE_COMPOSE_FORWARD) { + // skip inline images when forwarding in text mode + if ($part->content_id && $part->disposition == 'inline' && !$bodyIsHtml && $compose_mode == RCUBE_COMPOSE_FORWARD) { continue; } - $skip = false; + // skip message/rfc822 attachments on forwards (#1489214) + // Thunderbird when forwarding in inline mode displays such attachments + // and skips any attachments from inside of such part, this however + // skipped e.g. images used in HTML body or other attachments. So, + // better to skip .eml attachments but not their content (included files). if ($part->mimetype == 'message/rfc822') { + if ($compose_mode == RCUBE_COMPOSE_FORWARD) { + continue; + } $messages[] = $part->mime_id; - } else if ($messages) { + } + else if ($compose_mode != RCUBE_COMPOSE_FORWARD) { // skip attachments included in message/rfc822 attachment (#1486487) foreach ($messages as $mimeid) - if (strpos($part->mime_id, $mimeid.'.') === 0) { - $skip = true; - break; + if (strpos($part->mime_id, $mimeid . '.') === 0) { + continue 2; } } - if (!$skip && (($attachment = $loaded_attachments[rcmail_attachment_name($part) . $part->mimetype]) - || ($attachment = rcmail_save_attachment($message, $pid)))) { + if (($attachment = $loaded_attachments[rcmail_attachment_name($part) . $part->mimetype]) + || ($attachment = rcmail_save_attachment($message, $pid))) { $COMPOSE['attachments'][$attachment['id']] = $attachment; if ($bodyIsHtml && ($part->content_id || $part->content_location)) { $url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s', @@ -1074,7 +1133,7 @@ function rcmail_write_forward_attachments() $names = array(); $loaded_attachments = array(); - foreach ((array)$COMPOSE['attachments'] as $id => $attachment) { + foreach ((array)$COMPOSE['attachments'] as $attachment) { $loaded_attachments[$attachment['name'] . $attachment['mimetype']] = $attachment; } @@ -1209,10 +1268,11 @@ function rcmail_save_image($path, $mimetype='') // handle attachments in memory $data = file_get_contents($path); + $name = rcmail_basename($path); $attachment = array( 'group' => $COMPOSE['id'], - 'name' => rcmail_basename($path), + 'name' => $name, 'mimetype' => $mimetype ? $mimetype : rc_mime_content_type($path, $name), 'data' => $data, 'size' => strlen($data), @@ -1482,7 +1542,7 @@ function rcmail_editor_selector($attrib) $select->add(Q(rcube_label('plaintoggle')), 'plain'); return $select->show($useHtml ? 'html' : 'plain'); - +/* foreach ($choices as $value => $text) { $attrib['id'] = '_' . $value; $attrib['value'] = $value; @@ -1490,6 +1550,7 @@ function rcmail_editor_selector($attrib) } return $selector; +*/ } diff --git a/program/steps/mail/copy.inc b/program/steps/mail/copy.inc index a72378b0e..876657485 100644 --- a/program/steps/mail/copy.inc +++ b/program/steps/mail/copy.inc @@ -24,10 +24,10 @@ if (!$OUTPUT->ajax_call) return; // move messages -if (!empty($_POST['_uid']) && !empty($_POST['_target_mbox'])) { - $uids = get_input_value('_uid', RCUBE_INPUT_POST); +if (!empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) { + $uids = get_input_value('_uid', RCUBE_INPUT_POST); $target = get_input_value('_target_mbox', RCUBE_INPUT_POST, true); - $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true); + $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true); $copied = $RCMAIL->storage->copy_message($uids, $target, $mbox); @@ -47,7 +47,7 @@ if (!empty($_POST['_uid']) && !empty($_POST['_target_mbox'])) { } // unknown action or missing query param else { - exit; + $OUTPUT->show_message('internalerror', 'error'); } // send response diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index da01e6cbf..ae23d4a6d 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -120,7 +120,7 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') { if (!$OUTPUT->ajax_call) $OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash', 'movingmessage', 'copyingmessage', 'deletingmessage', 'markingmessage', - 'copy', 'move', 'quota'); + 'copy', 'move', 'quota', 'replyall', 'replylist', 'importwait'); $pagetitle = $RCMAIL->localize_foldername($RCMAIL->storage->mod_folder($mbox_name), true); $pagetitle = str_replace($delimiter, " \xC2\xBB ", $pagetitle); @@ -128,6 +128,40 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') { $OUTPUT->set_pagetitle($pagetitle); } +// register UI objects +$OUTPUT->add_handlers(array( + 'mailboxlist' => 'rcmail_mailbox_list', + 'messages' => 'rcmail_message_list', + 'messagecountdisplay' => 'rcmail_messagecount_display', + 'quotadisplay' => 'rcmail_quota_display', + 'mailboxname' => 'rcmail_mailbox_name_display', + 'messageheaders' => 'rcmail_message_headers', + 'messagefullheaders' => 'rcmail_message_full_headers', + 'messagebody' => 'rcmail_message_body', + 'messagecontentframe' => 'rcmail_messagecontent_frame', + 'messageimportform' => 'rcmail_message_import_form', + 'searchfilter' => 'rcmail_search_filter', + 'searchform' => array($OUTPUT, 'search_form'), +)); + +// register action aliases +$RCMAIL->register_action_map(array( + 'refresh' => 'check_recent.inc', + 'preview' => 'show.inc', + 'print' => 'show.inc', + 'move' => 'move_del.inc', + 'delete' => 'move_del.inc', + 'send' => 'sendmail.inc', + 'expunge' => 'folders.inc', + 'purge' => 'folders.inc', + 'remove-attachment' => 'attachments.inc', + 'display-attachment' => 'attachments.inc', + 'upload' => 'attachments.inc', + 'group-expand' => 'autocomplete.inc', +)); + + + /** * Returns 'to' if current folder is configured Sent or Drafts * or their subfolders, otherwise returns 'from'. @@ -224,7 +258,7 @@ function rcmail_message_list($attrib) if (!in_array('threads', $a_show_cols)) array_unshift($a_show_cols, 'threads'); - $skin_path = $_SESSION['skin_path'] = $CONFIG['skin_path']; + $_SESSION['skin_path'] = $CONFIG['skin_path']; // set client env $OUTPUT->add_gui_object('messagelist', $attrib['id']); @@ -236,15 +270,13 @@ function rcmail_message_list($attrib) $OUTPUT->include_script('list.js'); - $thead = ''; - foreach (rcmail_message_list_head($attrib, $a_show_cols) as $cell) - $thead .= html::tag('td', array('class' => $cell['className'], 'id' => $cell['id']), $cell['html']); + $table = new html_table($attrib); + if (!$attrib['noheader']) { + foreach (rcmail_message_list_head($attrib, $a_show_cols) as $cell) + $table->add_header(array('class' => $cell['className'], 'id' => $cell['id']), $cell['html']); + } - return html::tag('table', - $attrib, - html::tag('thead', null, html::tag('tr', null, $thead)) . - html::tag('tbody', null, ''), - array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary')); + return $table->show(); } @@ -291,7 +323,7 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $a_show_cols=null $thead = $head_replace ? rcmail_message_list_head($_SESSION['list_attrib'], $a_show_cols) : NULL; // get name of smart From/To column in folder context - if (($f = array_search('fromto', $a_show_cols)) !== false) { + if (array_search('fromto', $a_show_cols) !== false) { $smart_col = rcmail_message_list_smart_column_name(); } @@ -307,7 +339,7 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $a_show_cols=null } // loop through message headers - foreach ($a_headers as $n => $header) { + foreach ($a_headers as $header) { if (empty($header)) continue; @@ -381,7 +413,6 @@ function rcmail_message_list_head($attrib, $a_show_cols) global $RCMAIL; $skin_path = $_SESSION['skin_path']; - $image_tag = html::img(array('src' => "%s%s", 'alt' => "%s")); // check to see if we have some settings for sorting $sort_col = $_SESSION['sort_col']; @@ -417,7 +448,7 @@ function rcmail_message_list_head($attrib, $a_show_cols) $cells = array(); // get name of smart From/To column in folder context - if (($f = array_search('fromto', $a_show_cols)) !== false) { + if (array_search('fromto', $a_show_cols) !== false) { $smart_col = rcmail_message_list_smart_column_name(); } @@ -738,8 +769,13 @@ function rcmail_print_body($part, $p = array()) unset($data['body']); // plaintext postprocessing - if ($part->ctype_secondary == 'plain') - $body = rcmail_plain_body($body, $part->ctype_parameters['format'] == 'flowed'); + 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); + } // allow post-processing of the message body $data = $RCMAIL->plugins->exec_hook('message_part_after', @@ -753,11 +789,10 @@ function rcmail_print_body($part, $p = array()) * Handle links and citation marks in plain text message * * @param string Plain text string - * @param boolean Text uses format=flowed * * @return string Formatted HTML string */ -function rcmail_plain_body($body, $flowed=false) +function rcmail_plain_body($body) { global $RCMAIL; @@ -782,53 +817,17 @@ function rcmail_plain_body($body, $flowed=false) 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]; - } - else if ($flowed) { - // previous line is flowed - if (isset($body[$last]) && $body[$n] - && $body[$last][strlen($body[$last])-1] == ' ') { - // merge lines - $body[$last] .= $body[$n]; - unset($body[$n]); - } - else { - $last = $n; - } + $last = $n; } } else { $q = 0; - if ($flowed) { - // sig separator - line is fixed - if ($body[$n] == '-- ') { - $last = $last_sig = $n; - } - else { - // remove space-stuffing - if ($body[$n][0] == ' ') - $body[$n] = substr($body[$n], 1); - - // previous line is flowed? - if (isset($body[$last]) && $body[$n] - && $last !== $last_sig - && $body[$last][strlen($body[$last])-1] == ' ' - ) { - $body[$last] .= $body[$n]; - unset($body[$n]); - } - else { - $last = $n; - } - } - if ($quote_level > 0) - $body[$last] = $replacer->get_replacement($replacer->add( - str_repeat('</blockquote>', $quote_level))) . $body[$last]; - } - else if ($quote_level > 0) + if ($quote_level > 0) $body[$n] = $replacer->get_replacement($replacer->add( str_repeat('</blockquote>', $quote_level))) . $body[$n]; } @@ -898,8 +897,8 @@ function rcmail_washtml_callback($tagname, $attrib, $content, $washtml) * return table with message headers */ function rcmail_message_headers($attrib, $headers=null) - { - global $OUTPUT, $MESSAGE, $PRINT_MODE, $RCMAIL; +{ + global $MESSAGE, $PRINT_MODE, $RCMAIL; static $sa_attrib; // keep header table attrib @@ -937,7 +936,7 @@ function rcmail_message_headers($attrib, $headers=null) $value = $headers[$hkey]; else if ($headers['others'][$hkey]) $value = $headers['others'][$hkey]; - else + else if (!$attrib['valueof']) continue; if (in_array($hkey, $exclude_headers)) @@ -1084,7 +1083,7 @@ function rcmail_message_body($attrib) $header_attrib[$regs[1]] = $value; if (!empty($MESSAGE->parts)) { - foreach ($MESSAGE->parts as $i => $part) { + foreach ($MESSAGE->parts as $part) { if ($part->type == 'headers') { $out .= html::div('message-partheaders', rcmail_message_headers(sizeof($header_attrib) ? $header_attrib : null, $part->headers)); } @@ -1196,7 +1195,7 @@ function rcmail_message_body($attrib) html::a($show_link + array('class' => 'image-link', 'style' => sprintf('width:%dpx', $thumbnail_size)), html::img(array( 'class' => 'image-thumbnail', - 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, true) . '&_thumb=1', + 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, 'image') . '&_thumb=1', 'title' => $attach_prop->filename, 'alt' => $attach_prop->filename, 'style' => sprintf('max-width:%dpx; max-height:%dpx', $thumbnail_size, $thumbnail_size), @@ -1216,7 +1215,7 @@ function rcmail_message_body($attrib) html::tag('legend', 'image-filename', Q($attach_prop->filename)) . html::p(array('align' => "center"), html::img(array( - 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, true), + 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, 'image'), 'title' => $attach_prop->filename, 'alt' => $attach_prop->filename, ))) @@ -1442,7 +1441,8 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null, $c = count($a_parts); $j = 0; $out = ''; - $allvalues = array(); + $allvalues = array(); + $show_email = $RCMAIL->config->get('message_show_email'); if ($addicon && !isset($_SESSION['writeable_abook'])) { $_SESSION['writeable_abook'] = $RCMAIL->get_address_sources(true) ? true : false; @@ -1453,9 +1453,10 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null, $name = $part['name']; $mailto = $part['mailto']; $string = $part['string']; + $valid = check_email($mailto, false); // phishing email prevention (#1488981), e.g. "valid@email.addr <phishing@email.addr>" - if ($name && $name != $mailto && strpos($name, '@')) { + if (!$show_email && $valid && $name && $name != $mailto && strpos($name, '@')) { $name = ''; } @@ -1471,15 +1472,23 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null, // for printing we display all addresses continue; } - else if (check_email($part['mailto'], false)) { + else if ($valid) { if ($linked) { - $address = html::a(array( - 'href' => 'mailto:'.$mailto, - 'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($mailto)), - 'title' => $mailto, - 'class' => "rcmContactAddress", - ), - Q($name ? $name : $mailto)); + $attrs = array( + 'href' => 'mailto:' . $mailto, + 'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($mailto)), + 'class' => "rcmContactAddress", + ); + + if ($show_email && $name && $mailto) { + $content = Q($name ? sprintf('%s <%s>', $name, $mailto) : $mailto); + } + else { + $content = Q($name ? $name : $mailto); + $attrs['title'] = $mailto; + } + + $address = html::a($attrs, $content); } else { $address = html::span(array('title' => $mailto, 'class' => "rcmContactAddress"), @@ -1504,7 +1513,7 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null, if ($name) $address .= Q($name); if ($mailto) - $address .= (strlen($address) ? ' ' : '') . sprintf('<%s>', Q($mailto)); + $address = trim($address . ' ' . Q($name ? sprintf('<%s>', $mailto) : $mailto)); } $address = html::span('adr', $address); @@ -1543,11 +1552,11 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null, /** * Wrap text to a given number of characters per line * but respect the mail quotation of replies messages (>). - * Finally add another quotation level by prpending the lines + * Finally add another quotation level by prepending the lines * with > * * @param string Text to wrap - * @param int The line width + * @param int The line width * @return string The wrapped text */ function rcmail_wrap_and_quote($text, $length = 72) @@ -1563,7 +1572,7 @@ function rcmail_wrap_and_quote($text, $length = 72) $line = '>' . rtrim($line); else if (mb_strlen($line) > $max) { $newline = ''; - foreach(explode("\n", rc_wordwrap($line, $length - 2)) as $l) { + foreach (explode("\n", rc_wordwrap($line, $length - 2)) as $l) { if (strlen($l)) $newline .= '> ' . $l . "\n"; else @@ -1606,45 +1615,6 @@ function rcmail_draftinfo_decode($str) } -function rcmail_message_part_controls($attrib) -{ - global $MESSAGE, $RCMAIL; - - $part = asciiwords(get_input_value('_part', RCUBE_INPUT_GPC)); - if (!is_object($MESSAGE) || !is_array($MESSAGE->parts) || !($_GET['_uid'] && $_GET['_part']) || !$MESSAGE->mime_parts[$part]) - return ''; - - $part = $MESSAGE->mime_parts[$part]; - $table = new html_table(array('cols' => 3)); - - $filename = rcmail_attachment_name($part); - - if (!empty($filename)) { - $table->add('title', Q(rcube_label('filename'))); - $table->add('header', Q($filename)); - $table->add('download-link', html::a(array('href' => './?'.str_replace('_frame=', '_download=', $_SERVER['QUERY_STRING'])), Q(rcube_label('download')))); - } - - $table->add('title', Q(rcube_label('filesize'))); - $table->add('header', Q($RCMAIL->message_part_size($part))); - - return $table->show($attrib); -} - - -function rcmail_message_part_frame($attrib) -{ - global $MESSAGE; - - $part = $MESSAGE->mime_parts[asciiwords(get_input_value('_part', RCUBE_INPUT_GPC))]; - $ctype_primary = strtolower($part->ctype_primary); - - $attrib['src'] = './?' . str_replace('_frame=', ($ctype_primary=='text' ? '_embed=' : '_preload='), $_SERVER['QUERY_STRING']); - - return html::iframe($attrib); -} - - /** * clear message composing settings */ @@ -1732,8 +1702,7 @@ function rcmail_send_mdn($message, &$smtp_error) $sent = rcmail_deliver_message($compose, $identity['email'], $mailto, $smtp_error, $body_file, $options); - if ($sent) - { + if ($sent) { $RCMAIL->storage->set_flag($message->uid, 'MDNSENT'); return true; } @@ -1814,9 +1783,12 @@ function rcmail_identity_select($MESSAGE, $identities = null, $compose_mode = 'r // Try Return-Path if ($from_idx === null && ($return_path = $MESSAGE->headers->others['return-path'])) { foreach ($identities as $idx => $ident) { - if (strpos($return_path, str_replace('@', '=', $ident['email_ascii']).'@') !== false) { - $from_idx = $idx; - break; + $ident = str_replace('@', '=', $ident['email_ascii']) . '@'; + foreach ((array)$return_path as $path) { + if (strpos($path, $ident) !== false) { + $from_idx = $idx; + break 2; + } } } } @@ -1851,8 +1823,7 @@ function rcmail_fix_mimetype($name) // application/pdf.A520491B_3BF7_494D_8855_7FAC2C6C0608 if (preg_match('/^application\/pdf.+/', $name)) $name = 'application/pdf'; - - // treat image/pjpeg as image/jpeg + // treat image/pjpeg (image/pjpg, image/jpg) as image/jpeg (#1489097) else if (preg_match('/^image\/p?jpe?g$/', $name)) $name = 'image/jpeg'; @@ -1899,13 +1870,15 @@ function rcmail_search_filter($attrib) $attrib['onchange'] = JS_OBJECT_NAME.'.filter_mailbox(this.value)'; - /* - RFC3501 (6.4.4): 'ALL', 'RECENT', - 'ANSWERED', 'DELETED', 'FLAGGED', 'SEEN', - 'UNANSWERED', 'UNDELETED', 'UNFLAGGED', 'UNSEEN', - 'NEW', // = (RECENT UNSEEN) - 'OLD' // = NOT RECENT - */ + // Content-Type values of messages with attachments + // the same as in app.js:add_message_row() + $ctypes = array('application/', 'multipart/m', 'multipart/signed', 'multipart/report'); + + // Build search string of "with attachment" filter + $attachment = str_repeat(' OR', count($ctypes)-1); + foreach ($ctypes as $type) { + $attachment .= ' HEADER Content-Type ' . rcube_imap_generic::escape($type); + } $select_filter = new html_select($attrib); $select_filter->add(rcube_label('all'), 'ALL'); @@ -1916,6 +1889,7 @@ function rcmail_search_filter($attrib) $select_filter->add(rcube_label('deleted'), 'DELETED'); $select_filter->add(rcube_label('undeleted'), 'UNDELETED'); } + $select_filter->add(rcube_label('withattachment'), $attachment); $select_filter->add(rcube_label('priority').': '.rcube_label('highest'), 'HEADER X-PRIORITY 1'); $select_filter->add(rcube_label('priority').': '.rcube_label('high'), 'HEADER X-PRIORITY 2'); $select_filter->add(rcube_label('priority').': '.rcube_label('normal'), 'NOT HEADER X-PRIORITY 1 NOT HEADER X-PRIORITY 2 NOT HEADER X-PRIORITY 4 NOT HEADER X-PRIORITY 5'); @@ -1945,35 +1919,37 @@ function rcmail_message_error($uid=null) $RCMAIL->output->send('messageerror'); } -// register UI objects -$OUTPUT->add_handlers(array( - 'mailboxlist' => 'rcmail_mailbox_list', - 'messages' => 'rcmail_message_list', - 'messagecountdisplay' => 'rcmail_messagecount_display', - 'quotadisplay' => 'rcmail_quota_display', - 'mailboxname' => 'rcmail_mailbox_name_display', - 'messageheaders' => 'rcmail_message_headers', - 'messagefullheaders' => 'rcmail_message_full_headers', - 'messagebody' => 'rcmail_message_body', - 'messagecontentframe' => 'rcmail_messagecontent_frame', - 'messagepartframe' => 'rcmail_message_part_frame', - 'messagepartcontrols' => 'rcmail_message_part_controls', - 'searchfilter' => 'rcmail_search_filter', - 'searchform' => array($OUTPUT, 'search_form'), -)); +function rcmail_message_import_form($attrib = array()) +{ + global $OUTPUT; -// register action aliases -$RCMAIL->register_action_map(array( - 'refresh' => 'check_recent.inc', - 'preview' => 'show.inc', - 'print' => 'show.inc', - 'moveto' => 'move_del.inc', - 'delete' => 'move_del.inc', - 'send' => 'sendmail.inc', - 'expunge' => 'folders.inc', - 'purge' => 'folders.inc', - 'remove-attachment' => 'attachments.inc', - 'display-attachment' => 'attachments.inc', - 'upload' => 'attachments.inc', - 'group-expand' => 'autocomplete.inc', -)); + // set defaults + $attrib += array('id' => 'rcmImportform', 'buttons' => 'yes'); + + // Get filesize, enable upload progress bar + $max_filesize = rcube_upload_init(); + + $button = new html_inputfield(array('type' => 'button')); + $fileinput = new html_inputfield(array( + 'type' => 'file', + 'name' => '_file[]', + 'size' => $attrib['attachmentfieldsize'], + 'multiple' => 'multiple', + 'accept' => ".eml, .mbox, message/rfc822, text/*", + )); + + $out = html::div($attrib, + $OUTPUT->form_tag(array('id' => $attrib['id'].'Frm', 'method' => 'post', 'enctype' => 'multipart/form-data'), + html::tag('input', array('type' => 'hidden', 'name' => '_unlock', 'value' => '')) . + html::div(null, $fileinput->show()) . + html::div('hint', rcube_label(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize)))) . + (get_boolean($attrib['buttons']) ? html::div('buttons', + $button->show(rcube_label('close'), array('class' => 'button', 'onclick' => "$('#$attrib[id]').hide()")) . ' ' . + $button->show(rcube_label('upload'), array('class' => 'button mainaction', 'onclick' => JS_OBJECT_NAME . ".command('import-messages', this.form)")) + ) : '') + ) + ); + + $OUTPUT->add_gui_object('importform', $attrib['id'].'Frm'); + return $out; +} diff --git a/program/steps/mail/get.inc b/program/steps/mail/get.inc index 23dc22b7c..a27e788a3 100644 --- a/program/steps/mail/get.inc +++ b/program/steps/mail/get.inc @@ -22,7 +22,7 @@ // show loading page if (!empty($_GET['_preload'])) { - $url = preg_replace('/([&?]+)_preload=/', '\\1_embed=', $_SERVER['REQUEST_URI']); + $url = preg_replace('/([&?]+)_preload=/', '\\1_mimewarning=1&_embed=', $_SERVER['REQUEST_URI']); $message = rcube_label('loadingdata'); header('Content-Type: text/html; charset=' . RCMAIL_CHARSET); @@ -38,19 +38,34 @@ ob_end_clean(); // similar code as in program/steps/mail/show.inc if (!empty($_GET['_uid'])) { + $uid = get_input_value('_uid', RCUBE_INPUT_GET); $RCMAIL->config->set('prefer_html', true); - $MESSAGE = new rcube_message(get_input_value('_uid', RCUBE_INPUT_GET)); + $MESSAGE = new rcube_message($uid); } // check connection status check_storage_status(); +$part_id = get_input_value('_part', RCUBE_INPUT_GPC); + // show part page if (!empty($_GET['_frame'])) { - if (($part_id = get_input_value('_part', RCUBE_INPUT_GPC)) && ($part = $MESSAGE->mime_parts[$part_id])) { - $OUTPUT->set_pagetitle(rcmail_attachment_name($part)); + if ($part_id && ($part = $MESSAGE->mime_parts[$part_id])) { + $filename = rcmail_attachment_name($part); + $OUTPUT->set_pagetitle($filename); } + // register UI objects + $OUTPUT->add_handlers(array( + 'messagepartframe' => 'rcmail_message_part_frame', + 'messagepartcontrols' => 'rcmail_message_part_controls', + )); + + $OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder()); + $OUTPUT->set_env('uid', $uid); + $OUTPUT->set_env('part', $part_id); + $OUTPUT->set_env('filename', $filename); + $OUTPUT->send('messagepart'); exit; } @@ -62,9 +77,10 @@ else if ($_GET['_thumb']) { $thumbnail_size = $RCMAIL->config->get('image_thumbnail_size', 240); $temp_dir = $RCMAIL->config->get('temp_dir'); list(,$ext) = explode('/', $part->mimetype); - $cache_basename = $temp_dir . '/' . md5($MESSAGE->headers->messageID . $part->mime_id . ':' . $RCMAIL->user->ID . ':' . $thumbnail_size); - $cache_file = $cache_basename . '.' . $ext; $mimetype = $part->mimetype; + $file_ident = $MESSAGE->headers->messageID . ':' . $part->mime_id . ':' . $part->size . ':' . $part->mimetype; + $cache_basename = $temp_dir . '/' . md5($file_ident . ':' . $RCMAIL->user->ID . ':' . $thumbnail_size); + $cache_file = $cache_basename . '.' . $ext; // render thumbnail image if not done yet if (!is_file($cache_file)) { @@ -91,12 +107,9 @@ else if ($_GET['_thumb']) { exit; } -else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) { - - if ($part = $MESSAGE->mime_parts[$pid]) { - $ctype_primary = strtolower($part->ctype_primary); - $ctype_secondary = strtolower($part->ctype_secondary); - $mimetype = sprintf('%s/%s', $ctype_primary, $ctype_secondary); +else if (strlen($part_id)) { + if ($part = $MESSAGE->mime_parts[$part_id]) { + $mimetype = rcmail_fix_mimetype($part->mimetype); // allow post-processing of the message body $plugin = $RCMAIL->plugins->exec_hook('message_part_get', @@ -106,7 +119,7 @@ else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) { exit; // overwrite modified vars from plugin - $mimetype = $plugin['mimetype']; + $mimetype = $plugin['mimetype']; $extensions = rcube_mime::get_mime_extensions($mimetype); if ($plugin['body']) @@ -118,7 +131,7 @@ else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) { $file_extension = strtolower(pathinfo($part->filename, PATHINFO_EXTENSION)); // 1. compare filename suffix with expected suffix derived from mimetype - $valid = $file_extension && in_array($file_extension, (array)$extensions); + $valid = $file_extension && in_array($file_extension, (array)$extensions) || !empty($_REQUEST['_mimeclass']); // 2. detect the real mimetype of the attachment part and compare it with the stated mimetype and filename extension if ($valid || !$file_extension || $mimetype == 'application/octet-stream' || $mimetype == 'text/plain') { @@ -145,6 +158,10 @@ else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) { $extensions = rcube_mime::get_mime_extensions($real_mimetype); $valid_extension = (!$file_extension || in_array($file_extension, (array)$extensions)); + // ignore filename extension if mimeclass matches (#1489029) + if (!empty($_REQUEST['_mimeclass']) && $real_ctype_primary == $_REQUEST['_mimeclass']) + $valid_extension = true; + // fix mimetype for images wrongly declared as octet-stream if ($mimetype == 'application/octet-stream' && strpos($real_mimetype, 'image/') === 0 && $valid_extension) $mimetype = $real_mimetype; @@ -157,22 +174,32 @@ else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) { // show warning if validity checks failed if (!$valid) { - $OUTPUT = new rcmail_html_page(); - $OUTPUT->write(html::tag('html', null, html::tag('body', 'embed', - html::div(array('class' => 'rcmail-inline-message rcmail-inline-warning'), - rcube_label(array( - 'name' => 'attachmentvalidationerror', - 'vars' => array( - 'expected' => $mimetype . ($file_extension ? "(.$file_extension)" : ''), - 'detected' => $real_mimetype . ($extensions[0] ? "(.$extensions[0])" : ''), + // send blocked.gif for expected images + if (empty($_REQUEST['_mimewarning']) && strpos($mimetype, 'image/') === 0) { + // Do not cache. Failure might be the result of a misconfiguration, thus real content should be returned once fixed. + $OUTPUT->nocacheing_headers(); + header("Content-Type: image/gif"); + header("Content-Transfer-Encoding: binary"); + readfile(INSTALL_PATH . 'program/resources/blocked.gif'); + } + else { // html warning with a button to load the file anyway + $OUTPUT = new rcmail_html_page(); + $OUTPUT->write(html::tag('html', null, html::tag('body', 'embed', + html::div(array('class' => 'rcmail-inline-message rcmail-inline-warning'), + rcube_label(array( + 'name' => 'attachmentvalidationerror', + 'vars' => array( + 'expected' => $mimetype . ($file_extension ? "(.$file_extension)" : ''), + 'detected' => $real_mimetype . ($extensions[0] ? "(.$extensions[0])" : ''), + ) + )) . + html::p(array('class' => 'rcmail-inline-buttons'), + html::tag('button', + array('onclick' => "location.href='" . $RCMAIL->url(array_merge($_GET, array('_nocheck' => 1))) . "'"), + rcube_label('showanyway'))) ) - )) . - html::p(array('class' => 'rcmail-inline-buttons'), - html::tag('button', - array('onclick' => "location.href='" . $RCMAIL->url(array_merge($_GET, array('_nocheck' => 1))) . "'"), - rcube_label('showanyway'))) - ) - ))); + ))); + } exit; } } @@ -202,7 +229,6 @@ else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) { header("Content-Type: text/$ctype_secondary; charset=" . ($part->charset ? $part->charset : RCMAIL_CHARSET)); } else { - $mimetype = rcmail_fix_mimetype($mimetype); header("Content-Type: $mimetype"); header("Content-Transfer-Encoding: binary"); } @@ -366,7 +392,9 @@ else { header('HTTP/1.1 404 Not Found'); exit; - +/** + * Handles nicely storage connection errors + */ function check_storage_status() { $error = rcmail::get_instance()->storage->get_error_code(); @@ -398,3 +426,49 @@ function check_storage_status() exit; } } + +/** + * Attachment properties table + */ +function rcmail_message_part_controls($attrib) +{ + global $MESSAGE, $RCMAIL; + + $part = asciiwords(get_input_value('_part', RCUBE_INPUT_GPC)); + if (!is_object($MESSAGE) || !is_array($MESSAGE->parts) + || !($_GET['_uid'] && $_GET['_part']) || !$MESSAGE->mime_parts[$part] + ) { + return ''; + } + + $part = $MESSAGE->mime_parts[$part]; + $table = new html_table(array('cols' => 2)); + + $table->add('title', Q(rcube_label('namex')).':'); + $table->add('header', Q(rcmail_attachment_name($part))); + + $table->add('title', Q(rcube_label('type')).':'); + $table->add('header', Q($part->mimetype)); + + $table->add('title', Q(rcube_label('size')).':'); + $table->add('header', Q($RCMAIL->message_part_size($part))); + + return $table->show($attrib); +} + +/** + * Attachment preview frame + */ +function rcmail_message_part_frame($attrib) +{ + global $MESSAGE, $RCMAIL; + + $part = $MESSAGE->mime_parts[asciiwords(get_input_value('_part', RCUBE_INPUT_GPC))]; + $ctype_primary = strtolower($part->ctype_primary); + + $attrib['src'] = './?' . str_replace('_frame=', ($ctype_primary=='text' ? '_embed=' : '_preload='), $_SERVER['QUERY_STRING']); + + $RCMAIL->output->add_gui_object('messagepartframe', $attrib['id']); + + return html::iframe($attrib); +} diff --git a/program/steps/mail/import.inc b/program/steps/mail/import.inc new file mode 100644 index 000000000..f7e7a3eb8 --- /dev/null +++ b/program/steps/mail/import.inc @@ -0,0 +1,105 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/steps/mail/import.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: | + | Save the uploaded file(s) as messages to the current IMAP folder | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ +*/ + +// clear all stored output properties (like scripts and env vars) +$OUTPUT->reset(); + +if (is_array($_FILES['_file'])) { + $imported = 0; + + foreach ((array)$_FILES['_file']['tmp_name'] as $i => $filepath) { + // Process uploaded file if there is no error + $err = $_FILES['_file']['error'][$i]; + + if (!$err) { + // check file content type first + list($mtype_primary,) = explode('/', rc_mime_content_type($filepath, $_FILES['_file']['name'][$i], $_FILES['_file']['type'][$i])); + if (!in_array($mtype_primary, array('text','message'))) { + $OUTPUT->show_message('importmessageerror', 'error'); + continue; + } + + // read the first few lines to detect header-like structure + $fp = fopen($filepath, 'r'); + do { $line = fgets($fp); } + while ($line !== false && trim($line) == ''); + + if (!preg_match('/^From\s+-/', $line) && !preg_match('/^[a-z-_]+:\s+.+/i', $line)) { + $OUTPUT->show_message('importmessageerror', 'error'); + continue; + } + + $message = $lastline = ''; + fseek($fp, 0); + while (($line = fgets($fp)) !== false) { + // importing mbox file, split by From - lines + if (preg_match('/^From\s+-/', $line) && $lastline == '') { + if (!empty($message)) { + if ($RCMAIL->storage->save_message(null, rtrim($message))) { + $imported++; + } + else { + rcube::raise_error("Failed to import message to " . $RCMAIL->storage->get_folder(), false, true); + } + $message = ''; + } + continue; + } + + $message .= $line; + $lastline = rtrim($line); + } + + if (!empty($message) && $RCMAIL->storage->save_message(null, rtrim($message))) { + $imported++; + } + } + + if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) { + $msg = rcube_label(array('name' => 'filesizeerror', 'vars' => array('size' => show_bytes(parse_bytes(ini_get('upload_max_filesize')))))); + } + else if ($err) { + $OUTPUT->show_message('fileuploaderror', 'error'); + } + } // end foreach + + if ($imported) { + $OUTPUT->show_message(rcube_label(array('name' => 'importmessagesuccess', 'nr' => $imported, 'vars' => array('nr' => $imported))), 'confirmation'); + $OUTPUT->command('command', 'list'); + } + else { + $OUTPUT->show_message('importmessageerror', '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 = rcube_label(array('name' => 'filesizeerror', 'vars' => array('size' => show_bytes(parse_bytes($maxsize))))); + else + $msg = rcube_label('fileuploaderror'); + + $OUTPUT->command('display_message', $msg, 'error'); +} + +// send html page with JS calls as response +$OUTPUT->send('iframe'); + diff --git a/program/steps/mail/list_contacts.inc b/program/steps/mail/list_contacts.inc index 7e3b349cd..dab146431 100644 --- a/program/steps/mail/list_contacts.inc +++ b/program/steps/mail/list_contacts.inc @@ -19,10 +19,10 @@ +-----------------------------------------------------------------------+ */ -$afields = $RCMAIL->config->get('contactlist_fields'); -$sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name'); -$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50)); -$page = max(1, intval($_GET['_page'])); +$afields = $RCMAIL->config->get('contactlist_fields'); +$addr_sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name'); +$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50)); +$list_page = max(1, intval($_GET['_page'])); // Use search result if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']])) { @@ -42,7 +42,7 @@ if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search while ($row = $result->next()) { $row['sourceid'] = $s; - $key = rcube_addressbook::compose_contact_key($row, $sort_col); + $key = rcube_addressbook::compose_contact_key($row, $addr_sort_col); $records[$key] = $row; } unset($result); @@ -53,7 +53,7 @@ if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search // create resultset object $count = count($records); - $first = ($page-1) * $page_size; + $first = ($list_page-1) * $page_size; $result = new rcube_result_set($count, $first); // we need only records for current page @@ -71,10 +71,13 @@ else { if ($CONTACTS && $CONTACTS->ready) { // set list properties $CONTACTS->set_pagesize($page_size); - $CONTACTS->set_page($page); + $CONTACTS->set_page($list_page); + if ($group_id = get_input_value('_gid', RCUBE_INPUT_GPC)) { + $CONTACTS->set_group($group_id); + } // list groups of this source (on page one) - if ($CONTACTS->groups && $CONTACTS->list_page == 1) { + else if ($CONTACTS->groups && $CONTACTS->list_page == 1) { foreach ($CONTACTS->list_groups() as $group) { $CONTACTS->reset(); $CONTACTS->set_group($group['ID']); @@ -89,6 +92,19 @@ else { 'contactgroup' => html::span(array('title' => $email), Q($group['name']))), 'group'); } } + // make virtual groups clickable to list their members + else if ($group_prop['virtual']) { + $row_id = 'G'.$group['ID']; + $OUTPUT->command('add_contact_row', $row_id, array( + 'contactgroup' => html::a(array( + 'href' => '#list', + 'rel' => $row['ID'], + 'title' => rcube_label('listgroup'), + 'onclick' => sprintf("return %s.command('pushgroup',{'source':'%s','id':'%s'},this,event)", JS_OBJECT_NAME, $source, $group['ID']), + ), Q($group['name']) . ' ' . html::span('action', '»'))), + 'group', + array('ID' => $group['ID'], 'name' => $group['name'], 'virtual' => true)); + } // show group with count else if (($result = $CONTACTS->count()) && $result->count) { $row_id = 'E'.$group['ID']; @@ -97,10 +113,12 @@ else { 'contactgroup' => Q($group['name'] . ' (' . intval($result->count) . ')')), 'group'); } } + + $CONTACTS->reset(); + $CONTACTS->set_group(0); } // get contacts for this user - $CONTACTS->set_group(0); $result = $CONTACTS->list_records($afields); } } @@ -118,10 +136,13 @@ else if (!empty($result) && $result->count > 0) { foreach ($emails as $i => $email) { $row_id = $row['ID'].$i; $jsresult[$row_id] = format_email_recipient($email, $name); + $classname = $row['_type'] == 'group' ? 'group' : 'person'; + $keyname = $row['_type'] == 'group' ? 'contactgroup' : 'contact'; + $OUTPUT->command('add_contact_row', $row_id, array( - 'contact' => html::span(array('title' => $email), Q($name ? $name : $email) . + $keyname => html::span(array('title' => $email), Q($name ? $name : $email) . ($name && count($emails) > 1 ? ' ' . html::span('email', Q($email)) : '') - )), 'person'); + )), $classname); } } } diff --git a/program/steps/mail/mark.inc b/program/steps/mail/mark.inc index c220fc5c4..dfc892ea1 100644 --- a/program/steps/mail/mark.inc +++ b/program/steps/mail/mark.inc @@ -113,7 +113,7 @@ if (($uids = get_input_value('_uid', RCUBE_INPUT_POST)) && ($flag = get_input_va $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count), $mbox); if ($threading) { - $count = get_input_value('_count', RCUBE_INPUT_POST); + $count = get_input_value('_count', RCUBE_INPUT_POST); } // add new rows from next page (if any) @@ -125,9 +125,9 @@ if (($uids = get_input_value('_uid', RCUBE_INPUT_POST)) && ($flag = get_input_va } } } - - $OUTPUT->send(); +} +else { + $OUTPUT->show_message('internalerror', 'error'); } -exit; - +$OUTPUT->send(); diff --git a/program/steps/mail/move_del.inc b/program/steps/mail/move_del.inc index 3fc6ac5a7..f15cd2460 100644 --- a/program/steps/mail/move_del.inc +++ b/program/steps/mail/move_del.inc @@ -29,7 +29,7 @@ $old_count = $RCMAIL->storage->count(NULL, $threading ? 'THREADS' : 'ALL'); $old_pages = ceil($old_count / $RCMAIL->storage->get_pagesize()); // move messages -if ($RCMAIL->action == 'moveto' && !empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) { +if ($RCMAIL->action == 'move' && !empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) { $count = sizeof(explode(',', ($uids = get_input_value('_uid', RCUBE_INPUT_POST)))); $target = get_input_value('_target_mbox', RCUBE_INPUT_POST, true); $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true); @@ -74,6 +74,8 @@ else if ($RCMAIL->action=='delete' && !empty($_POST['_uid'])) { } // unknown action or missing query param else { + $OUTPUT->show_message('internalerror', 'error'); + $OUTPUT->send(); exit; } @@ -124,7 +126,7 @@ else rcmail_set_unseen_count($mbox, $unseen_count); } - if ($RCMAIL->action == 'moveto' && strlen($target)) { + if ($RCMAIL->action == 'move' && strlen($target)) { rcmail_send_unread_count($target, true); } diff --git a/program/steps/mail/search_contacts.inc b/program/steps/mail/search_contacts.inc index 2e6bb12f8..6a30ad1f5 100644 --- a/program/steps/mail/search_contacts.inc +++ b/program/steps/mail/search_contacts.inc @@ -19,16 +19,15 @@ +-----------------------------------------------------------------------+ */ -$search = get_input_value('_q', RCUBE_INPUT_GPC, true); -$sources = $RCMAIL->get_address_sources(); -$search_mode = (int) $RCMAIL->config->get('addressbook_search_mode'); -$sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name'); -$afields = $RCMAIL->config->get('contactlist_fields'); +$search = get_input_value('_q', RCUBE_INPUT_GPC, true); +$sources = $RCMAIL->get_address_sources(); +$search_mode = (int) $RCMAIL->config->get('addressbook_search_mode'); +$addr_sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name'); +$afields = $RCMAIL->config->get('contactlist_fields'); +$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50)); +$records = array(); +$search_set = array(); -$page = 1; -$page_size = $RCMAIL->config->get('addressbook_pagesize', $RCMAIL->config->get('pagesize', 50)); - -$records = $search_set = array(); foreach ($sources as $s) { $source = $RCMAIL->get_address_book($s['id']); $source->set_page(1); @@ -46,7 +45,7 @@ foreach ($sources as $s) { while ($row = $result->next()) { $row['sourceid'] = $s['id']; - $key = rcube_addressbook::compose_contact_key($row, $sort_col); + $key = rcube_addressbook::compose_contact_key($row, $addr_sort_col); $records[$key] = $row; } diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index eb0ba89c6..cf22a2af9 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -255,6 +255,33 @@ function rcmail_email_input_format($mailto, $count=false, $check=true) } +function rcmail_generic_message_footer($isHtml) +{ + global $CONFIG; + + if ($isHtml && !empty($CONFIG['generic_message_footer_html'])) { + $file = $CONFIG['generic_message_footer_html']; + $html_footer = true; + } + else { + $file = $CONFIG['generic_message_footer']; + $html_footer = false; + } + + if ($file && realpath($file)) { + // sanity check + if (!preg_match('/\.(php|ini|conf)$/', $file) && strpos($file, '/etc/') === false) { + $footer = file_get_contents($file); + if ($isHtml && !$html_footer) + $footer = '<pre>' . $footer . '</pre>'; + return $footer; + } + } + + return false; +} + + /****** compose message ********/ if (strlen($_POST['_draft_saveid']) > 3) @@ -364,10 +391,6 @@ if (!empty($mailcc)) { if (!empty($mailbcc)) { $headers['Bcc'] = $mailbcc; } -if (!empty($identity_arr['bcc']) && stripos($headers['Bcc'], $identity_arr['bcc']) === false) { - $headers['Bcc'] = ($headers['Bcc'] ? $headers['Bcc'].', ' : '') . $identity_arr['bcc']; - $RECIPIENT_COUNT ++; -} if (($max_recipients = (int) $RCMAIL->config->get('max_recipients')) > 0) { if ($RECIPIENT_COUNT > $max_recipients) { @@ -385,9 +408,6 @@ if (!empty($identity_arr['organization'])) { if (!empty($_POST['_replyto'])) { $headers['Reply-To'] = rcmail_email_input_format(get_input_value('_replyto', RCUBE_INPUT_POST, TRUE, $message_charset)); } -else if (!empty($identity_arr['reply-to'])) { - $headers['Reply-To'] = rcmail_email_input_format($identity_arr['reply-to'], false, true); -} if (!empty($headers['Reply-To'])) { $headers['Mail-Reply-To'] = $headers['Reply-To']; } @@ -452,7 +472,7 @@ $isHtml = (bool) get_input_value('_is_html', RCUBE_INPUT_POST); $message_body = get_input_value('_message', RCUBE_INPUT_POST, TRUE, $message_charset); if ($isHtml) { - $font = rcube_fontdefs($RCMAIL->config->get('default_font', 'Verdana')); + $font = rcube_fontdefs($RCMAIL->config->get('default_font')); $bstyle = $font && is_string($font) ? " style='font-family: $font'" : ''; // append doctype and html/body wrappers @@ -466,7 +486,7 @@ if (!$savedraft) { $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; width:100%'; + $bstyle = 'padding-left:5px; border-left:#1010ff 2px solid; margin-left:5px'; $message_body = preg_replace('/<blockquote>/', '<blockquote type="cite" style="'.$bstyle.'">', $message_body); } @@ -490,19 +510,10 @@ if (!$savedraft) { } // generic footer for all messages - if ($isHtml && !empty($CONFIG['generic_message_footer_html'])) { - $footer = file_get_contents(realpath($CONFIG['generic_message_footer_html'])); - $footer = rcube_charset_convert($footer, RCMAIL_CHARSET, $message_charset); - } - else if (!empty($CONFIG['generic_message_footer'])) { - $footer = file_get_contents(realpath($CONFIG['generic_message_footer'])); + if ($footer = rcmail_generic_message_footer($isHtml)) { $footer = rcube_charset_convert($footer, RCMAIL_CHARSET, $message_charset); - if ($isHtml) - $footer = '<pre>'.$footer.'</pre>'; - } - - if ($footer) $message_body .= "\r\n" . $footer; + } } if ($isHtml) { @@ -820,6 +831,6 @@ else { if ($store_folder && !$saved) $OUTPUT->command('sent_successfully', 'error', rcube_label('errorsavingsent')); else - $OUTPUT->command('sent_successfully', 'confirmation', rcube_label('messagesent')); + $OUTPUT->command('sent_successfully', 'confirmation', rcube_label('messagesent'), $store_target); $OUTPUT->send('iframe'); } diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc index 552c180f5..59f4d55e1 100644 --- a/program/steps/mail/show.inc +++ b/program/steps/mail/show.inc @@ -109,14 +109,14 @@ if ($uid) { $OUTPUT->set_env('skip_deleted', true); if ($CONFIG['display_next']) $OUTPUT->set_env('display_next', true); - if ($MESSAGE->headers->others['list-post']) + if ($MESSAGE->headers->get('list-post', false)) $OUTPUT->set_env('list_post', true); if ($CONFIG['forward_attachment']) $OUTPUT->set_env('forward_attachment', true); if (!$OUTPUT->ajax_call) $OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash', - 'movingmessage', 'deletingmessage', 'markingmessage'); + 'movingmessage', 'deletingmessage', 'markingmessage', 'replyall', 'replylist'); $prefer_html = $RCMAIL->config->get('prefer_html'); if ($MESSAGE->has_html_part()) { @@ -228,11 +228,11 @@ function rcmail_remote_objects_msg() function rcmail_message_buttons() { - global $MESSAGE, $RCMAIL, $CONFIG; + global $RCMAIL; $mbox = $RCMAIL->storage->get_folder(); $delim = $RCMAIL->storage->get_hierarchy_delimiter(); - $dbox = $CONFIG['drafts_mbox']; + $dbox = $RCMAIL->config->get('drafts_mbox'); // the message is not a draft if ($mbox != $dbox && strpos($mbox, $dbox.$delim) !== 0) { @@ -275,9 +275,13 @@ function rcmail_contact_exists($email) if ($email) { // @TODO: search in all address books? $CONTACTS = $RCMAIL->get_address_book(-1, true); - $existing = $CONTACTS->search('email', $email, true, false); - if ($existing->count) - return true; + + if (is_object($CONTACTS)) { + $existing = $CONTACTS->search('email', $email, true, false); + if ($existing->count) { + return true; + } + } } return false; diff --git a/program/steps/settings/about.inc b/program/steps/settings/about.inc index 9b13402f1..0fdefddda 100644 --- a/program/steps/settings/about.inc +++ b/program/steps/settings/about.inc @@ -40,17 +40,28 @@ function rcmail_plugins_list($attrib) $attrib['id'] = 'rcmpluginlist'; $plugins = array_filter((array) $RCMAIL->config->get('plugins')); - $plugins = array_flip($plugins); + $plugin_info = array(); - foreach ($plugins as $name => $plugin) { - rcube_plugin_data($name, $plugins); + foreach ($plugins as $name) { + if ($info = $RCMAIL->plugins->get_info($name)) + $plugin_info[$name] = $info; } - if (empty($plugins)) { + // 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 (!isset($plugin_info[$req_name]) && ($req_info = $RCMAIL->plugins->get_info($req_name))) + $plugin_info[$req_name] = $req_info; + } + } + } + + if (empty($plugin_info)) { return ''; } - ksort($plugins, SORT_LOCALE_STRING); + ksort($plugin_info, SORT_LOCALE_STRING); $table = new html_table($attrib); @@ -60,8 +71,8 @@ function rcmail_plugins_list($attrib) $table->add_header('license', rcube_label('license')); $table->add_header('source', rcube_label('source')); - foreach ($plugins as $name => $data) { - $uri = $data['srcuri'] ? $data['srcuri'] : $data['uri']; + foreach ($plugin_info as $name => $data) { + $uri = $data['src_uri'] ? $data['src_uri'] : $data['uri']; if ($uri && stripos($uri, 'http') !== 0) { $uri = 'http://' . $uri; } @@ -78,48 +89,6 @@ function rcmail_plugins_list($attrib) return $table->show(); } -function rcube_plugin_data($name, &$plugins = array()) -{ - // XPaths of plugin metadata elements - $metadata = array( - 'name' => 'string(//rc:package/rc:name)', - 'version' => 'string(//rc:package/rc:version/rc:release)', - 'license' => 'string(//rc:package/rc:license)', - 'license_uri' => 'string(//rc:package/rc:license/@uri)', - 'srcuri' => 'string(//rc:package/rc:srcuri)', - 'uri' => 'string(//rc:package/rc:uri)', - ); - - $package = INSTALL_PATH . "/plugins/$name/package.xml"; - if (file_exists($package) && ($file = file_get_contents($package))) { - $doc = new DOMDocument(); - $doc->loadXML($file); - $xpath = new DOMXPath($doc); - $xpath->registerNamespace('rc', "http://pear.php.net/dtd/package-2.0"); - $data = array(); - - foreach ($metadata as $key => $path) { - $data[$key] = $xpath->evaluate($path); - } - - $plugins[$name] = $data; - - // dependent required plugins (can be used, but not included in config) - $deps = $xpath->evaluate('//rc:package/rc:dependencies/rc:required/rc:package/rc:name'); - $cnt = $deps->length; - - for ($i=0; $i<$cnt; $i++) { - $dn = $deps->item($i)->nodeValue; - if (!array_key_exists($dn, $plugins)) { - rcube_plugin_data($dn, $plugins); - } - } - } - else { - unset($plugins[$name]); - } -} - $OUTPUT->set_pagetitle(rcube_label('about')); diff --git a/program/steps/settings/edit_folder.inc b/program/steps/settings/edit_folder.inc index cd2372790..fdb38e602 100644 --- a/program/steps/settings/edit_folder.inc +++ b/program/steps/settings/edit_folder.inc @@ -78,7 +78,7 @@ function rcmail_folder_form($attrib) // Location (name) if ($options['protected']) { - $foldername = Q(str_replace($delimiter, ' » ', rcmail_localize_folderpath($mbox_imap))); + $foldername = str_replace($delimiter, ' » ', Q(rcmail_localize_folderpath($mbox_imap))); } else if ($options['norename']) { $foldername = Q($folder); diff --git a/program/steps/settings/edit_prefs.inc b/program/steps/settings/edit_prefs.inc index 971ed60b6..468e4994d 100644 --- a/program/steps/settings/edit_prefs.inc +++ b/program/steps/settings/edit_prefs.inc @@ -40,7 +40,7 @@ function rcmail_user_prefs_form($attrib) $out = $form_start; - foreach ($SECTIONS[$CURR_SECTION]['blocks'] as $idx => $block) { + foreach ($SECTIONS[$CURR_SECTION]['blocks'] as $block) { if (!empty($block['options'])) { $table = new html_table(array('cols' => 2)); diff --git a/program/steps/settings/folders.inc b/program/steps/settings/folders.inc index 0c7d9063f..6d116e7d2 100644 --- a/program/steps/settings/folders.inc +++ b/program/steps/settings/folders.inc @@ -232,16 +232,16 @@ function rcube_subscription_form($attrib) // add any necessary "virtual" parent folders if ($parent_folder && !isset($seen[$parent_folder])) { for ($i=1; $i<=$level; $i++) { - $ancestor_folder = join($delimiter, array_slice($foldersplit, 0, $i)); - if ($ancestor_folder && !$seen[$ancestor_folder]++) { - $ancestor_name = rcube_charset_convert($foldersplit[$i-1], 'UTF7-IMAP'); - $list_folders[] = array( + $ancestor_folder = join($delimiter, array_slice($foldersplit, 0, $i)); + if ($ancestor_folder && !$seen[$ancestor_folder]++) { + $ancestor_name = rcube_charset_convert($foldersplit[$i-1], 'UTF7-IMAP'); + $list_folders[] = array( 'id' => $ancestor_folder, 'name' => $ancestor_name, 'level' => $i-1, 'virtual' => true, ); - } + } } } @@ -283,7 +283,6 @@ function rcube_subscription_form($attrib) $noselect = false; $classes = array($i%2 ? 'even' : 'odd'); - $folder_js = Q($folder['id']); $folder_utf8 = rcube_charset_convert($folder['id'], 'UTF7-IMAP'); $display_folder = str_repeat(' ', $folder['level']) . Q($protected ? rcmail_localize_foldername($folder['id']) : $folder['name']); @@ -292,7 +291,8 @@ function rcube_subscription_form($attrib) $classes[] = 'virtual'; } - if (!$protected) { + // Check \Noselect flag (of existing folder) + if (!$protected && in_array($folder['id'], $a_unsubscribed)) { $attrs = $STORAGE->folder_attributes($folder['id']); $noselect = in_array('\\Noselect', $attrs); } @@ -394,7 +394,7 @@ function rcmail_rename_folder($oldname, $newname) $a_threaded = (array) $RCMAIL->config->get('message_threading', array()); $oldprefix = '/^' . preg_quote($oldname . $delimiter, '/') . '/'; - foreach ($a_threaded as $key => $val) { + foreach (array_keys($a_threaded) as $key) { if ($key == $oldname) { unset($a_threaded[$key]); $a_threaded[$newname] = true; diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc index 2f726c7e8..dbc9b3ce2 100644 --- a/program/steps/settings/func.inc +++ b/program/steps/settings/func.inc @@ -19,927 +19,1175 @@ +-----------------------------------------------------------------------+ */ -if (!$OUTPUT->ajax_call) - $OUTPUT->set_pagetitle(rcube_label('preferences')); - +if (!$OUTPUT->ajax_call) { + $OUTPUT->set_pagetitle(rcube_label('preferences')); +} // similar function as /steps/settings/identities.inc::rcmail_identity_frame() function rcmail_preferences_frame($attrib) { - global $OUTPUT; + global $OUTPUT; - if (!$attrib['id']) - $attrib['id'] = 'rcmprefsframe'; + if (!$attrib['id']) { + $attrib['id'] = 'rcmprefsframe'; + } - return $OUTPUT->frame($attrib, true); + return $OUTPUT->frame($attrib, true); } function rcmail_sections_list($attrib) { - global $RCMAIL; + global $RCMAIL; - // add id to message list table if not specified - if (!strlen($attrib['id'])) - $attrib['id'] = 'rcmsectionslist'; + // add id to message list table if not specified + if (!strlen($attrib['id'])) { + $attrib['id'] = 'rcmsectionslist'; + } - list($list, $cols) = rcmail_user_prefs(); + list($list, $cols) = rcmail_user_prefs(); - // create XHTML table - $out = rcube_table_output($attrib, $list, $cols, 'id'); + // create XHTML table + $out = rcube_table_output($attrib, $list, $cols, 'id'); - // set client env - $RCMAIL->output->add_gui_object('sectionslist', $attrib['id']); - $RCMAIL->output->include_script('list.js'); + // set client env + $RCMAIL->output->add_gui_object('sectionslist', $attrib['id']); + $RCMAIL->output->include_script('list.js'); - return $out; + return $out; } function rcmail_identities_list($attrib) { - global $OUTPUT, $RCMAIL; + global $OUTPUT, $RCMAIL; - // add id to message list table if not specified - if (!strlen($attrib['id'])) - $attrib['id'] = 'rcmIdentitiesList'; + // add id to message list table if not specified + if (!strlen($attrib['id'])) { + $attrib['id'] = 'rcmIdentitiesList'; + } - // get identities list and define 'mail' column - $list = $RCMAIL->user->list_identities(); - foreach ($list as $idx => $row) - $list[$idx]['mail'] = trim($row['name'] . ' <' . rcube_idn_to_utf8($row['email']) .'>'); + // get identities list and define 'mail' column + $list = $RCMAIL->user->list_identities(); + foreach ($list as $idx => $row) { + $list[$idx]['mail'] = trim($row['name'] . ' <' . rcube_idn_to_utf8($row['email']) .'>'); + } - // get all identites from DB and define list of cols to be displayed - $plugin = $RCMAIL->plugins->exec_hook('identities_list', array( - 'list' => $list, - 'cols' => array('mail'))); + // get all identites from DB and define list of cols to be displayed + $plugin = $RCMAIL->plugins->exec_hook('identities_list', array( + 'list' => $list, + 'cols' => array('mail') + )); - // @TODO: use <UL> instead of <TABLE> for identities list - // create XHTML table - $out = rcube_table_output($attrib, $plugin['list'], $plugin['cols'], 'identity_id'); + // @TODO: use <UL> instead of <TABLE> for identities list + // create XHTML table + $out = rcube_table_output($attrib, $plugin['list'], $plugin['cols'], 'identity_id'); - // set client env - $OUTPUT->add_gui_object('identitieslist', $attrib['id']); + // set client env + $OUTPUT->add_gui_object('identitieslist', $attrib['id']); - return $out; + return $out; } // similar function as in /steps/addressbook/edit.inc function get_form_tags($attrib, $action, $id = null, $hidden = null) { - global $EDIT_FORM, $RCMAIL; - - $form_start = $form_end = ''; - - if (empty($EDIT_FORM)) { - $request_key = $action . (isset($id) ? '.'.$id : ''); - $form_start = $RCMAIL->output->request_form(array( - 'name' => 'form', - 'method' => 'post', - 'task' => $RCMAIL->task, - 'action' => $action, - 'request' => $request_key, - 'noclose' => true - ) + $attrib); - - if (is_array($hidden)) { - $hiddenfields = new html_hiddenfield($hidden); - $form_start .= $hiddenfields->show(); - } + global $EDIT_FORM, $RCMAIL; + + $form_start = $form_end = ''; + + if (empty($EDIT_FORM)) { + $request_key = $action . (isset($id) ? '.'.$id : ''); + $form_start = $RCMAIL->output->request_form(array( + 'name' => 'form', + 'method' => 'post', + 'task' => $RCMAIL->task, + 'action' => $action, + 'request' => $request_key, + 'noclose' => true + ) + $attrib); + + if (is_array($hidden)) { + $hiddenfields = new html_hiddenfield($hidden); + $form_start .= $hiddenfields->show(); + } - $form_end = !strlen($attrib['form']) ? '</form>' : ''; + $form_end = !strlen($attrib['form']) ? '</form>' : ''; - $EDIT_FORM = !empty($attrib['form']) ? $attrib['form'] : 'form'; - $RCMAIL->output->add_gui_object('editform', $EDIT_FORM); - } + $EDIT_FORM = !empty($attrib['form']) ? $attrib['form'] : 'form'; + $RCMAIL->output->add_gui_object('editform', $EDIT_FORM); + } - return array($form_start, $form_end); + return array($form_start, $form_end); } -function rcmail_user_prefs($current=null) +function rcmail_user_prefs($current = null) { - global $RCMAIL; - - $sections['general'] = array('id' => 'general', 'section' => rcube_label('uisettings')); - $sections['mailbox'] = array('id' => 'mailbox', 'section' => rcube_label('mailboxview')); - $sections['mailview'] = array('id' => 'mailview','section' => rcube_label('messagesdisplaying')); - $sections['compose'] = array('id' => 'compose', 'section' => rcube_label('messagescomposition')); - $sections['addressbook'] = array('id' => 'addressbook','section' => rcube_label('addressbook')); - $sections['folders'] = array('id' => 'folders', 'section' => rcube_label('specialfolders')); - $sections['server'] = array('id' => 'server', 'section' => rcube_label('serversettings')); - - // hook + define list cols - $plugin = $RCMAIL->plugins->exec_hook('preferences_sections_list', - array('list' => $sections, 'cols' => array('section'))); - - $sections = $plugin['list']; - - $config = $RCMAIL->config->all(); - $no_override = array_flip($RCMAIL->config->get('dont_override', array())); - - foreach ($sections as $idx => $sect) { - - if ($current && $sect['id'] != $current) - continue; - - $blocks = array(); - - switch ($sect['id']) { - // general - case 'general': - - $blocks = array( - 'main' => array('name' => Q(rcube_label('mainoptions'))), - ); - - // language selection - if (!isset($no_override['language'])) { - $a_lang = $RCMAIL->list_languages(); - asort($a_lang); - - $field_id = 'rcmfd_lang'; - $select_lang = new html_select(array('name' => '_language', 'id' => $field_id)); - $select_lang->add(array_values($a_lang), array_keys($a_lang)); - - $blocks['main']['options']['language'] = array( - 'title' => html::label($field_id, Q(rcube_label('language'))), - 'content' => $select_lang->show($RCMAIL->user->language), - ); - } - - // timezone selection - if (!isset($no_override['timezone'])) { - $field_id = 'rcmfd_timezone'; - $select_timezone = new html_select(array('name' => '_timezone', 'id' => $field_id)); - $select_timezone->add(rcube_label('autodetect'), 'auto'); - - $zones = array(); - foreach (DateTimeZone::listIdentifiers() as $i => $tzs) { - try { - $tz = new DateTimeZone($tzs); - $date = new DateTime('2012-12-21', $tz); - $offset = $date->format('Z') + 45000; - $sortkey = sprintf('%06d.%s', $offset, $tzs); - $zones[$sortkey] = array($tzs, $date->format('P')); - } - catch (Exception $e) {} - } - - ksort($zones); - foreach ($zones as $zone) { - list($tzs, $offset) = $zone; - $select_timezone->add('(GMT ' . $offset . ') ' . strtr($tzs, '_', ' '), $tzs); - } - - $blocks['main']['options']['timezone'] = array( - 'title' => html::label($field_id, Q(rcube_label('timezone'))), - 'content' => $select_timezone->show((string)$config['timezone']), - ); - } - - // date/time formatting - if (!isset($no_override['time_format'])) { - $reftime = mktime(7,30,0); - $field_id = 'rcmfd_time_format'; - $select_time = new html_select(array('name' => '_time_format', 'id' => $field_id)); - foreach ((array)$RCMAIL->config->get('time_formats', array('G:i', 'H:i', 'g:i a', 'h:i A')) as $choice) - $select_time->add(date($choice, $reftime), $choice); - - $blocks['main']['options']['time_format'] = array( - 'title' => html::label($field_id, Q(rcube_label('timeformat'))), - 'content' => $select_time->show($RCMAIL->config->get('time_format')), - ); - } - - if (!isset($no_override['date_format'])) { - $refdate = mktime(12,30,0,7,24); - $field_id = 'rcmfd_date_format'; - $select_date = new html_select(array('name' => '_date_format', 'id' => $field_id)); - foreach ((array)$RCMAIL->config->get('date_formats', array('Y-m-d','d-m-Y','Y/m/d','m/d/Y','d/m/Y','d.m.Y','j.n.Y')) as $choice) - $select_date->add(date($choice, $refdate), $choice); - - $blocks['main']['options']['date_format'] = array( - 'title' => html::label($field_id, Q(rcube_label('dateformat'))), - 'content' => $select_date->show($config['date_format']), - ); - } + global $RCMAIL; - // MM: Show checkbox for toggling 'pretty dates' - if (!isset($no_override['prettydate'])) { - $field_id = 'rcmfd_prettydate'; - $input_prettydate = new html_checkbox(array('name' => '_pretty_date', 'id' => $field_id, 'value' => 1)); + $sections['general'] = array('id' => 'general', 'section' => rcube_label('uisettings')); + $sections['mailbox'] = array('id' => 'mailbox', 'section' => rcube_label('mailboxview')); + $sections['mailview'] = array('id' => 'mailview','section' => rcube_label('messagesdisplaying')); + $sections['compose'] = array('id' => 'compose', 'section' => rcube_label('messagescomposition')); + $sections['addressbook'] = array('id' => 'addressbook','section' => rcube_label('addressbook')); + $sections['folders'] = array('id' => 'folders', 'section' => rcube_label('specialfolders')); + $sections['server'] = array('id' => 'server', 'section' => rcube_label('serversettings')); - $blocks['main']['options']['prettydate'] = array( - 'title' => html::label($field_id, Q(rcube_label('prettydate'))), - 'content' => $input_prettydate->show($config['prettydate']?1:0), - ); - } + // hook + define list cols + $plugin = $RCMAIL->plugins->exec_hook('preferences_sections_list', + array('list' => $sections, 'cols' => array('section'))); - if (!isset($no_override['refresh_interval'])) { - $field_id = 'rcmfd_refresh_interval'; - $select_refresh_interval = new html_select(array('name' => '_refresh_interval', 'id' => $field_id)); + $sections = $plugin['list']; + $config = $RCMAIL->config->all(); + $no_override = array_flip((array)$RCMAIL->config->get('dont_override')); - $select_refresh_interval->add(rcube_label('never'), 0); - foreach (array(1, 3, 5, 10, 15, 30, 60) as $min) { - if (!$config['min_refresh_interval'] || $config['min_refresh_interval'] <= $min * 60) { - $label = rcube_label(array('name' => 'everynminutes', 'vars' => array('n' => $min))); - $select_refresh_interval->add($label, $min); + foreach ($sections as $idx => $sect) { + if ($current && $sect['id'] != $current) { + continue; } - } - $blocks['main']['options']['refresh_interval'] = array( - 'title' => html::label($field_id, Q(rcube_label('refreshinterval'))), - 'content' => $select_refresh_interval->show($config['refresh_interval']/60), - ); - } - - // show drop-down for available skins - if (!isset($no_override['skin'])) { - $skins = rcmail_get_skins(); - - if (count($skins) > 1) { - $field_id = 'rcmfd_skin'; - $input_skin = new html_radiobutton(array('name'=>'_skin')); - - $blocks['skin'] = array('name' => Q(rcube_label('skin')),); - - foreach($skins as $skin) { - $thumbnail = "./skins/$skin/thumbnail.png"; - if (!is_file($thumbnail)) - $thumbnail = './program/resources/blank.gif'; - - $skinname = ucfirst($skin); - $author_link = $license_link = ''; - $meta = @json_decode(@file_get_contents("./skins/$skin/meta.json"), true); - if (is_array($meta) && $meta['name']) { - $skinname = $meta['name']; - $author_link = $meta['url'] ? html::a(array('href' => $meta['url'], 'target' => '_blank'), Q($meta['author'])) : Q($meta['author']); - $license_link = $meta['license-url'] ? html::a(array('href' => $meta['license-url'], 'target' => '_blank'), Q($meta['license'])) : Q($meta['license']); - } - - $blocks['skin']['options'][$skin]['content'] = html::label(array('class' => 'skinselection'), - html::span('skinitem', $input_skin->show($config['skin'], array('value' => $skin, 'id' => $field_id.$skin))) . - html::span('skinitem', html::img(array('src' => $thumbnail, 'class' => 'skinthumbnail', 'alt' => $skin, 'width' => 64, 'height' => 64))) . - html::span('skinitem', html::span('skinname', Q($skinname)) . html::br() . - html::span('skinauthor', $author_link ? 'by ' . $author_link : '') . html::br() . - html::span('skinlicense', $license_link ? rcube_label('license').': ' . $license_link : '')) - ); + $blocks = array(); + + switch ($sect['id']) { + + // general + case 'general': + $blocks = array( + 'main' => array('name' => Q(rcube_label('mainoptions'))), + 'skin' => array('name' => Q(rcube_label('skin'))), + 'browser' => array('name' => Q(rcube_label('browseroptions'))), + ); + + // language selection + if (!isset($no_override['language'])) { + if (!$current) { + continue 2; + } + + $a_lang = $RCMAIL->list_languages(); + asort($a_lang); + + $field_id = 'rcmfd_lang'; + $select = new html_select(array('name' => '_language', 'id' => $field_id)); + $select->add(array_values($a_lang), array_keys($a_lang)); + + $blocks['main']['options']['language'] = array( + 'title' => html::label($field_id, Q(rcube_label('language'))), + 'content' => $select->show($RCMAIL->user->language), + ); + } + + // timezone selection + if (!isset($no_override['timezone'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_timezone'; + $select = new html_select(array('name' => '_timezone', 'id' => $field_id)); + $select->add(rcube_label('autodetect'), 'auto'); + + $zones = array(); + foreach (DateTimeZone::listIdentifiers() as $i => $tzs) { + try { + $tz = new DateTimeZone($tzs); + $date = new DateTime('2012-12-21', $tz); + $offset = $date->format('Z') + 45000; + $sortkey = sprintf('%06d.%s', $offset, $tzs); + $zones[$sortkey] = array($tzs, $date->format('P')); + } + catch (Exception $e) {} + } + + ksort($zones); + + foreach ($zones as $zone) { + list($tzs, $offset) = $zone; + $select->add('(GMT ' . $offset . ') ' . strtr($tzs, '_', ' '), $tzs); + } + + $blocks['main']['options']['timezone'] = array( + 'title' => html::label($field_id, Q(rcube_label('timezone'))), + 'content' => $select->show((string)$config['timezone']), + ); + } + + // date/time formatting + if (!isset($no_override['time_format'])) { + if (!$current) { + continue 2; + } + + $reftime = mktime(7,30,0); + $defaults = array('G:i', 'H:i', 'g:i a', 'h:i A'); + $formats = (array)$RCMAIL->config->get('time_formats', $defaults); + $field_id = 'rcmfd_time_format'; + $select = new html_select(array('name' => '_time_format', 'id' => $field_id)); + + foreach ($formats as $choice) { + $select->add(date($choice, $reftime), $choice); + } + + $blocks['main']['options']['time_format'] = array( + 'title' => html::label($field_id, Q(rcube_label('timeformat'))), + 'content' => $select->show($RCMAIL->config->get('time_format')), + ); + } + + if (!isset($no_override['date_format'])) { + if (!$current) { + continue 2; + } + + $refdate = mktime(12,30,0,7,24); + $defaults = array('Y-m-d','d-m-Y','Y/m/d','m/d/Y','d/m/Y','d.m.Y','j.n.Y'); + $formats = (array)$RCMAIL->config->get('date_formats', $defaults); + $field_id = 'rcmfd_date_format'; + $select = new html_select(array('name' => '_date_format', 'id' => $field_id)); + + foreach ($formats as $choice) { + $select->add(date($choice, $refdate), $choice); + } + + $blocks['main']['options']['date_format'] = array( + 'title' => html::label($field_id, Q(rcube_label('dateformat'))), + 'content' => $select->show($config['date_format']), + ); + } + + // Show checkbox for toggling 'pretty dates' + if (!isset($no_override['prettydate'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_prettydate'; + $input = new html_checkbox(array('name' => '_pretty_date', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['prettydate'] = array( + 'title' => html::label($field_id, Q(rcube_label('prettydate'))), + 'content' => $input->show($config['prettydate']?1:0), + ); + } + + if (!isset($no_override['refresh_interval'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_refresh_interval'; + $select = new html_select(array('name' => '_refresh_interval', 'id' => $field_id)); + + $select->add(rcube_label('never'), 0); + foreach (array(1, 3, 5, 10, 15, 30, 60) as $min) { + if (!$config['min_refresh_interval'] || $config['min_refresh_interval'] <= $min * 60) { + $label = rcube_label(array('name' => 'everynminutes', 'vars' => array('n' => $min))); + $select->add($label, $min); + } + } + + $blocks['main']['options']['refresh_interval'] = array( + 'title' => html::label($field_id, Q(rcube_label('refreshinterval'))), + 'content' => $select->show($config['refresh_interval']/60), + ); + } + + // show drop-down for available skins + if (!isset($no_override['skin'])) { + if (!$current) { + continue 2; + } + + $skins = rcmail_get_skins(); + + if (count($skins) > 1) { + $field_id = 'rcmfd_skin'; + $input = new html_radiobutton(array('name'=>'_skin')); + + foreach ($skins as $skin) { + $thumbnail = "./skins/$skin/thumbnail.png"; + if (!is_file($thumbnail)) + $thumbnail = './program/resources/blank.gif'; + + $skinname = ucfirst($skin); + $author_link = $license_link = ''; + $meta = @json_decode(@file_get_contents("./skins/$skin/meta.json"), true); + + if (is_array($meta) && $meta['name']) { + $skinname = $meta['name']; + $author_link = $meta['url'] ? html::a(array('href' => $meta['url'], 'target' => '_blank'), Q($meta['author'])) : Q($meta['author']); + $license_link = $meta['license-url'] ? html::a(array('href' => $meta['license-url'], 'target' => '_blank'), Q($meta['license'])) : Q($meta['license']); + } + + $blocks['skin']['options'][$skin]['content'] = html::label(array('class' => 'skinselection'), + html::span('skinitem', $input->show($config['skin'], array('value' => $skin, 'id' => $field_id.$skin))) . + html::span('skinitem', html::img(array('src' => $thumbnail, 'class' => 'skinthumbnail', 'alt' => $skin, 'width' => 64, 'height' => 64))) . + html::span('skinitem', html::span('skinname', Q($skinname)) . html::br() . + html::span('skinauthor', $author_link ? 'by ' . $author_link : '') . html::br() . + html::span('skinlicense', $license_link ? rcube_label('license').': ' . $license_link : '')) + ); + } + } + } + + // standard_windows option decides if new windows should be + // opened as popups or standard windows (which can be handled by browsers as tabs) + if (!isset($no_override['standard_windows'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_standard_windows'; + $checkbox = new html_checkbox(array('name' => '_standard_windows', 'id' => $field_id, 'value' => 1)); + + $blocks['browser']['options']['standard_windows'] = array( + 'title' => html::label($field_id, Q(rcube_label('standardwindows'))), + 'content' => $checkbox->show($config['standard_windows']?1:0), + ); + } + + if ($current) { + $product_name = $RCMAIL->config->get('product_name', 'Roundcube Webmail'); + $RCMAIL->output->add_script(sprintf("%s.check_protocol_handler('%s', '#mailtoprotohandler');", + JS_OBJECT_NAME, JQ($product_name)), 'foot'); + } + + $blocks['browser']['options']['mailtoprotohandler'] = array( + 'content' => html::a(array( + 'href' => '#', + 'id' => 'mailtoprotohandler'), Q(rcube_label('mailtoprotohandler'))), + ); + + break; + + // Mailbox view (mail screen) + case 'mailbox': + $blocks = array( + 'main' => array('name' => Q(rcube_label('mainoptions'))), + 'new_message' => array('name' => Q(rcube_label('newmessage'))), + ); + + // show config parameter for preview pane + if (!isset($no_override['preview_pane'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_preview'; + $input = new html_checkbox(array('name' => '_preview_pane', 'id' => $field_id, 'value' => 1, + 'onchange' => "$('#rcmfd_preview_pane_mark_read').prop('disabled', !this.checked)")); + + $blocks['main']['options']['preview_pane'] = array( + 'title' => html::label($field_id, Q(rcube_label('previewpane'))), + 'content' => $input->show($config['preview_pane']?1:0), + ); + } + + // show config parameter for preview pane auto mark as read delay + if (!isset($no_override['preview_pane_mark_read'])) { + if (!$current) { + continue 2; + } + + // apply default if config option is not set at all + $config['preview_pane_mark_read'] = $RCMAIL->config->get('preview_pane_mark_read', 0); + + $field_id = 'rcmfd_preview_pane_mark_read'; + $select = new html_select(array('name' => '_preview_pane_mark_read', 'id' => $field_id, + 'disabled' => $config['preview_pane']?0:1)); + + $select->add(rcube_label('never'), '-1'); + $select->add(rcube_label('immediately'), 0); + + foreach (array(5, 10, 20, 30) as $sec) { + $label = rcube_label(array('name' => 'afternseconds', 'vars' => array('n' => $sec))); + $select->add($label, $sec); + } + + $blocks['main']['options']['preview_pane_mark_read'] = array( + 'title' => html::label($field_id, Q(rcube_label('previewpanemarkread'))), + 'content' => $select->show(intval($config['preview_pane_mark_read'])), + ); + } + + if (!isset($no_override['mdn_requests'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_mdn_requests'; + $select = new html_select(array('name' => '_mdn_requests', 'id' => $field_id)); + $select->add(rcube_label('askuser'), 0); + $select->add(rcube_label('autosend'), 1); + $select->add(rcube_label('autosendknown'), 3); + $select->add(rcube_label('autosendknownignore'), 4); + $select->add(rcube_label('ignore'), 2); + + $blocks['main']['options']['mdn_requests'] = array( + 'title' => html::label($field_id, Q(rcube_label('mdnrequests'))), + 'content' => $select->show($config['mdn_requests']), + ); + } + + if (!isset($no_override['autoexpand_threads'])) { + if (!$current) { + continue 2; + } + + $storage = $RCMAIL->get_storage(); + $supported = $storage->get_capability('THREAD'); + + if ($supported) { + $field_id = 'rcmfd_autoexpand_threads'; + $select = new html_select(array('name' => '_autoexpand_threads', 'id' => $field_id)); + $select->add(rcube_label('never'), 0); + $select->add(rcube_label('do_expand'), 1); + $select->add(rcube_label('expand_only_unread'), 2); + + $blocks['main']['options']['autoexpand_threads'] = array( + 'title' => html::label($field_id, Q(rcube_label('autoexpand_threads'))), + 'content' => $select->show($config['autoexpand_threads']), + ); + } + } + + // show page size selection + if (!isset($no_override['mail_pagesize'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_mail_pagesize'; + $input = new html_inputfield(array('name' => '_mail_pagesize', 'id' => $field_id, 'size' => 5)); + $size = intval($config['mail_pagesize'] ? $config['mail_pagesize'] : $config['pagesize']); + + $blocks['main']['options']['pagesize'] = array( + 'title' => html::label($field_id, Q(rcube_label('pagesize'))), + 'content' => $input->show($size ? $size : 50), + ); + } + + if (!isset($no_override['check_all_folders'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_check_all_folders'; + $input = new html_checkbox(array('name' => '_check_all_folders', 'id' => $field_id, 'value' => 1)); + + $blocks['new_message']['options']['check_all_folders'] = array( + 'title' => html::label($field_id, Q(rcube_label('checkallfolders'))), + 'content' => $input->show($config['check_all_folders']?1:0), + ); + } + break; + + // Message viewing + case 'mailview': + $blocks = array( + 'main' => array('name' => Q(rcube_label('mainoptions'))), + ); + + // show checkbox to open message view in new window + if (!isset($no_override['message_extwin'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_message_extwin'; + $input = new html_checkbox(array('name' => '_message_extwin', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['message_extwin'] = array( + 'title' => html::label($field_id, Q(rcube_label('showinextwin'))), + 'content' => $input->show($config['message_extwin']?1:0), + ); + } + + // show checkbox to show email instead of name + if (!isset($no_override['message_show_email'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_message_show_email'; + $input = new html_checkbox(array('name' => '_message_show_email', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['message_show_email'] = array( + 'title' => html::label($field_id, Q(rcube_label('showemail'))), + 'content' => $input->show($config['message_show_email']?1:0), + ); + } + + // show checkbox for HTML/plaintext messages + if (!isset($no_override['prefer_html'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_htmlmsg'; + $input = new html_checkbox(array('name' => '_prefer_html', 'id' => $field_id, 'value' => 1, + 'onchange' => "$('#rcmfd_show_images').prop('disabled', !this.checked).val(0)")); + + $blocks['main']['options']['prefer_html'] = array( + 'title' => html::label($field_id, Q(rcube_label('preferhtml'))), + 'content' => $input->show($config['prefer_html']?1:0), + ); + } + + if (!isset($no_override['default_charset'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_default_charset'; + + $blocks['main']['options']['default_charset'] = array( + 'title' => html::label($field_id, Q(rcube_label('defaultcharset'))), + 'content' => $RCMAIL->output->charset_selector(array( + 'name' => '_default_charset', 'selected' => $config['default_charset'] + ))); + } + + if (!isset($no_override['show_images'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_show_images'; + $input = new html_select(array('name' => '_show_images', 'id' => $field_id, + 'disabled' => !$config['prefer_html'])); + + $input->add(rcube_label('never'), 0); + $input->add(rcube_label('fromknownsenders'), 1); + $input->add(rcube_label('always'), 2); + + $blocks['main']['options']['show_images'] = array( + 'title' => html::label($field_id, Q(rcube_label('showremoteimages'))), + 'content' => $input->show($config['prefer_html'] ? $config['show_images'] : 0), + ); + } + + if (!isset($no_override['inline_images'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_inline_images'; + $input = new html_checkbox(array('name' => '_inline_images', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['inline_images'] = array( + 'title' => html::label($field_id, Q(rcube_label('showinlineimages'))), + 'content' => $input->show($config['inline_images']?1:0), + ); + } + + // "display after delete" checkbox + if (!isset($no_override['display_next'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_displaynext'; + $input = new html_checkbox(array('name' => '_display_next', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['display_next'] = array( + 'title' => html::label($field_id, Q(rcube_label('displaynext'))), + 'content' => $input->show($config['display_next']?1:0), + ); + } + break; + + // Mail composition + case 'compose': + $blocks = array( + 'main' => array('name' => Q(rcube_label('mainoptions'))), + 'sig' => array('name' => Q(rcube_label('signatureoptions'))), + 'spellcheck' => array('name' => Q(rcube_label('spellcheckoptions'))), + ); + + // show checkbox to compose messages in a new window + if (!isset($no_override['compose_extwin'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfdcompose_extwin'; + $input = new html_checkbox(array('name' => '_compose_extwin', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['compose_extwin'] = array( + 'title' => html::label($field_id, Q(rcube_label('composeextwin'))), + 'content' => $input->show($config['compose_extwin']?1:0), + ); + } + + if (!isset($no_override['htmleditor'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_htmleditor'; + $select = new html_select(array('name' => '_htmleditor', 'id' => $field_id)); + + $select->add(rcube_label('never'), 0); + $select->add(rcube_label('always'), 1); + $select->add(rcube_label('htmlonreply'), 2); + $select->add(rcube_label('htmlonreplyandforward'), 3); + + $blocks['main']['options']['htmleditor'] = array( + 'title' => html::label($field_id, Q(rcube_label('htmleditor'))), + 'content' => $select->show(intval($config['htmleditor'])), + ); + } + + if (!isset($no_override['draft_autosave'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_autosave'; + $select = new html_select(array('name' => '_draft_autosave', 'id' => $field_id, 'disabled' => empty($config['drafts_mbox']))); + + $select->add(rcube_label('never'), 0); + foreach (array(1, 3, 5, 10) as $i => $min) { + $label = rcube_label(array('name' => 'everynminutes', 'vars' => array('n' => $min))); + $select->add($label, $min*60); + } + + $blocks['main']['options']['draft_autosave'] = array( + 'title' => html::label($field_id, Q(rcube_label('autosavedraft'))), + 'content' => $select->show($config['draft_autosave']), + ); + } + + if (!isset($no_override['mime_param_folding'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_param_folding'; + $select = new html_select(array('name' => '_mime_param_folding', 'id' => $field_id)); + + $select->add(rcube_label('2231folding'), 0); + $select->add(rcube_label('miscfolding'), 1); + $select->add(rcube_label('2047folding'), 2); + + $blocks['main']['options']['mime_param_folding'] = array( + 'advanced' => true, + 'title' => html::label($field_id, Q(rcube_label('mimeparamfolding'))), + 'content' => $select->show($config['mime_param_folding']), + ); + } + + if (!isset($no_override['force_7bit'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_force_7bit'; + $input = new html_checkbox(array('name' => '_force_7bit', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['force_7bit'] = array( + 'advanced' => true, + 'title' => html::label($field_id, Q(rcube_label('force7bit'))), + 'content' => $input->show($config['force_7bit']?1:0), + ); + } + + if (!isset($no_override['mdn_default'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_mdn_default'; + $input = new html_checkbox(array('name' => '_mdn_default', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['mdn_default'] = array( + 'title' => html::label($field_id, Q(rcube_label('reqmdn'))), + 'content' => $input->show($config['mdn_default']?1:0), + ); + } + + if (!isset($no_override['dsn_default'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_dsn_default'; + $input = new html_checkbox(array('name' => '_dsn_default', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['dsn_default'] = array( + 'title' => html::label($field_id, Q(rcube_label('reqdsn'))), + 'content' => $input->show($config['dsn_default']?1:0), + ); + } + + if (!isset($no_override['reply_same_folder'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_reply_same_folder'; + $input = new html_checkbox(array('name' => '_reply_same_folder', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['reply_same_folder'] = array( + 'title' => html::label($field_id, Q(rcube_label('replysamefolder'))), + 'content' => $input->show($config['reply_same_folder']?1:0), + ); + } + + if (!isset($no_override['reply_mode'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_reply_mode'; + $select = new html_select(array('name' => '_reply_mode', 'id' => $field_id)); + + $select->add(rcube_label('replyempty'), -1); + $select->add(rcube_label('replybottomposting'), 0); + $select->add(rcube_label('replytopposting'), 1); + + $blocks['main']['options']['reply_mode'] = array( + 'title' => html::label($field_id, Q(rcube_label('whenreplying'))), + 'content' => $select->show(intval($config['reply_mode'])), + ); + } + + if (!isset($no_override['spellcheck_before_send']) && $config['enable_spellcheck']) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_spellcheck_before_send'; + $input = new html_checkbox(array('name' => '_spellcheck_before_send', 'id' => $field_id, 'value' => 1)); + + $blocks['spellcheck']['options']['spellcheck_before_send'] = array( + 'title' => html::label($field_id, Q(rcube_label('spellcheckbeforesend'))), + 'content' => $input->show($config['spellcheck_before_send']?1:0), + ); + } + + if ($config['enable_spellcheck']) { + if (!$current) { + continue 2; + } + + foreach (array('syms', 'nums', 'caps') as $key) { + $key = 'spellcheck_ignore_'.$key; + if (!isset($no_override[$key])) { + $input = new html_checkbox(array('name' => '_'.$key, 'id' => 'rcmfd_'.$key, 'value' => 1)); + + $blocks['spellcheck']['options'][$key] = array( + 'title' => html::label($field_id, Q(rcube_label(str_replace('_', '', $key)))), + 'content' => $input->show($config[$key]?1:0), + ); + } + } + } + + if (!isset($no_override['show_sig'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_show_sig'; + $select = new html_select(array('name' => '_show_sig', 'id' => $field_id)); + + $select->add(rcube_label('never'), 0); + $select->add(rcube_label('always'), 1); + $select->add(rcube_label('newmessageonly'), 2); + $select->add(rcube_label('replyandforwardonly'), 3); + + $blocks['sig']['options']['show_sig'] = array( + 'title' => html::label($field_id, Q(rcube_label('autoaddsignature'))), + 'content' => $select->show($RCMAIL->config->get('show_sig', 1)), + ); + } + + if (!isset($no_override['strip_existing_sig'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_strip_existing_sig'; + $input = new html_checkbox(array('name' => '_strip_existing_sig', 'id' => $field_id, 'value' => 1)); + + $blocks['sig']['options']['strip_existing_sig'] = array( + 'title' => html::label($field_id, Q(rcube_label('replyremovesignature'))), + 'content' => $input->show($config['strip_existing_sig']?1:0), + ); + } + + if (!isset($no_override['forward_attachment'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_forward_attachment'; + $select = new html_select(array('name' => '_forward_attachment', 'id' => $field_id)); + + $select->add(rcube_label('inline'), 0); + $select->add(rcube_label('asattachment'), 1); + + $blocks['main']['options']['forward_attachment'] = array( + 'title' => html::label($field_id, Q(rcube_label('forwardmode'))), + 'content' => $select->show(intval($config['forward_attachment'])), + ); + } + + if (!isset($no_override['default_font'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_default_font'; + $fonts = rcube_fontdefs(); + $selected = $config['default_font']; + + $select = '<select name="_default_font" id="'.$field_id.'">'; + $select .= '<option value=""' . (!$selected ? ' selected="selected"' : '') . '>---</option>'; + foreach ($fonts as $fname => $font) { + $select .= '<option value="'.$fname.'"' + . ($fname == $selected ? ' selected="selected"' : '') + . ' style=\'font-family: ' . $font . '\'>' + . Q($fname) . '</option>'; + } + $select .= '</select>'; + + $blocks['main']['options']['default_font'] = array( + 'title' => html::label($field_id, Q(rcube_label('defaultfont'))), + 'content' => $select + ); + } + break; + + // Addressbook config + case 'addressbook': + $blocks = array( + 'main' => array('name' => Q(rcube_label('mainoptions'))), + ); + + if (!isset($no_override['default_addressbook']) + && (!$current || ($books = $RCMAIL->get_address_sources(true, true))) + ) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_default_addressbook'; + $select = new html_select(array('name' => '_default_addressbook', 'id' => $field_id)); + + foreach ($books as $book) { + $select->add(html_entity_decode($book['name'], ENT_COMPAT, 'UTF-8'), $book['id']); + } + + $blocks['main']['options']['default_addressbook'] = array( + 'title' => html::label($field_id, Q(rcube_label('defaultabook'))), + 'content' => $select->show($config['default_addressbook']), + ); + } + + // show addressbook listing mode selection + if (!isset($no_override['addressbook_name_listing'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_addressbook_name_listing'; + $select = new html_select(array('name' => '_addressbook_name_listing', 'id' => $field_id)); + + $select->add(rcube_label('name'), 0); + $select->add(rcube_label('firstname') . ' ' . rcube_label('surname'), 1); + $select->add(rcube_label('surname') . ' ' . rcube_label('firstname'), 2); + $select->add(rcube_label('surname') . ', ' . rcube_label('firstname'), 3); + + $blocks['main']['options']['list_name_listing'] = array( + 'title' => html::label($field_id, Q(rcube_label('listnamedisplay'))), + 'content' => $select->show($config['addressbook_name_listing']), + ); + } + + // show addressbook sort column + if (!isset($no_override['addressbook_sort_col'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_addressbook_sort_col'; + $select = new html_select(array('name' => '_addressbook_sort_col', 'id' => $field_id)); + + $select->add(rcube_label('name'), 'name'); + $select->add(rcube_label('firstname'), 'firstname'); + $select->add(rcube_label('surname'), 'surname'); + + $blocks['main']['options']['sort_col'] = array( + 'title' => html::label($field_id, Q(rcube_label('listsorting'))), + 'content' => $select->show($config['addressbook_sort_col']), + ); + } + + // show addressbook page size selection + if (!isset($no_override['addressbook_pagesize'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_addressbook_pagesize'; + $input = new html_inputfield(array('name' => '_addressbook_pagesize', 'id' => $field_id, 'size' => 5)); + $size = intval($config['addressbook_pagesize'] ? $config['addressbook_pagesize'] : $config['pagesize']); + + $blocks['main']['options']['pagesize'] = array( + 'title' => html::label($field_id, Q(rcube_label('pagesize'))), + 'content' => $input->show($size ? $size : 50), + ); + } + + if (!isset($no_override['autocomplete_single'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_autocomplete_single'; + $checkbox = new html_checkbox(array('name' => '_autocomplete_single', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['autocomplete_single'] = array( + 'title' => html::label($field_id, Q(rcube_label('autocompletesingle'))), + 'content' => $checkbox->show($config['autocomplete_single']?1:0), + ); + } + break; + + // Special IMAP folders + case 'folders': + $blocks = array( + 'main' => array('name' => Q(rcube_label('mainoptions'))), + ); + + if (!isset($no_override['show_real_foldernames'])) { + if (!$current) { + continue 2; + } + + $field_id = 'show_real_foldernames'; + $input = new html_checkbox(array('name' => '_show_real_foldernames', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['show_real_foldernames'] = array( + 'title' => html::label($field_id, Q(rcube_label('show_real_foldernames'))), + 'content' => $input->show($config['show_real_foldernames']?1:0), + ); + } + + // Configure special folders + if (!isset($no_override['default_folders']) && $current) { + $select = rcmail_mailbox_select(array( + 'noselection' => '---', + 'realnames' => true, + 'maxlength' => 30, + 'folder_filter' => 'mail', + 'folder_rights' => 'w', + // #1486114, #1488279 + 'onchange' => "if ($(this).val() == 'INBOX') $(this).val('')", + )); + } + + if (!isset($no_override['drafts_mbox'])) { + if (!$current) { + continue 2; + } + + $blocks['main']['options']['drafts_mbox'] = array( + 'title' => Q(rcube_label('drafts')), + 'content' => $select->show($config['drafts_mbox'], array('name' => "_drafts_mbox")), + ); + } + + if (!isset($no_override['sent_mbox'])) { + if (!$current) { + continue 2; + } + + $blocks['main']['options']['sent_mbox'] = array( + 'title' => Q(rcube_label('sent')), + 'content' => $select->show($config['sent_mbox'], array('name' => "_sent_mbox")), + ); + } + + if (!isset($no_override['junk_mbox'])) { + if (!$current) { + continue 2; + } + + $blocks['main']['options']['junk_mbox'] = array( + 'title' => Q(rcube_label('junk')), + 'content' => $select->show($config['junk_mbox'], array('name' => "_junk_mbox")), + ); + } + + if (!isset($no_override['trash_mbox'])) { + if (!$current) { + continue 2; + } + + $blocks['main']['options']['trash_mbox'] = array( + 'title' => Q(rcube_label('trash')), + 'content' => $select->show($config['trash_mbox'], array('name' => "_trash_mbox")), + ); + } + break; + + // Server settings + case 'server': + $blocks = array( + 'main' => array('name' => Q(rcube_label('mainoptions'))), + 'maintenance' => array('name' => Q(rcube_label('maintenance'))), + ); + + if (!isset($no_override['read_when_deleted'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_read_deleted'; + $input = new html_checkbox(array('name' => '_read_when_deleted', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['read_when_deleted'] = array( + 'title' => html::label($field_id, Q(rcube_label('readwhendeleted'))), + 'content' => $input->show($config['read_when_deleted']?1:0), + ); + } + + if (!isset($no_override['flag_for_deletion'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_flag_for_deletion'; + $input = new html_checkbox(array('name' => '_flag_for_deletion', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['flag_for_deletion'] = array( + 'title' => html::label($field_id, Q(rcube_label('flagfordeletion'))), + 'content' => $input->show($config['flag_for_deletion']?1:0), + ); + } + + // don't show deleted messages + if (!isset($no_override['skip_deleted'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_skip_deleted'; + $input = new html_checkbox(array('name' => '_skip_deleted', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['skip_deleted'] = array( + 'title' => html::label($field_id, Q(rcube_label('skipdeleted'))), + 'content' => $input->show($config['skip_deleted']?1:0), + ); + } + + if (!isset($no_override['delete_always'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_delete_always'; + $input = new html_checkbox(array('name' => '_delete_always', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['delete_always'] = array( + 'title' => html::label($field_id, Q(rcube_label('deletealways'))), + 'content' => $input->show($config['delete_always']?1:0), + ); + } + + if (!isset($no_override['delete_junk'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_delete_junk'; + $input = new html_checkbox(array('name' => '_delete_junk', 'id' => $field_id, 'value' => 1)); + + $blocks['main']['options']['delete_junk'] = array( + 'title' => html::label($field_id, Q(rcube_label('deletejunk'))), + 'content' => $input->show($config['delete_junk']?1:0), + ); + } + + // Trash purging on logout + if (!isset($no_override['logout_purge'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_logout_purge'; + $input = new html_checkbox(array('name' => '_logout_purge', 'id' => $field_id, 'value' => 1)); + + $blocks['maintenance']['options']['logout_purge'] = array( + 'title' => html::label($field_id, Q(rcube_label('logoutclear'))), + 'content' => $input->show($config['logout_purge']?1:0), + ); + } + + // INBOX compacting on logout + if (!isset($no_override['logout_expunge'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_logout_expunge'; + $input = new html_checkbox(array('name' => '_logout_expunge', 'id' => $field_id, 'value' => 1)); + + $blocks['maintenance']['options']['logout_expunge'] = array( + 'title' => html::label($field_id, Q(rcube_label('logoutcompact'))), + 'content' => $input->show($config['logout_expunge']?1:0), + ); + } } - } - } - - $product_name = $RCMAIL->config->get('product_name', 'Roundcube Webmail'); - $RCMAIL->output->add_script(sprintf("%s.check_protocol_handler('%s', '#mailtoprotohandler');", - JS_OBJECT_NAME, JQ($product_name)), 'foot'); - - $blocks['browser'] = array( - 'name' => Q(rcube_label('browseroptions')), - 'options' => array('mailtoprotohandler' => array( - 'content' => html::a(array( - 'href' => '#', - 'id' => 'mailtoprotohandler'), Q(rcube_label('mailtoprotohandler'))), - )), - ); - - break; - - // Mailbox view (mail screen) - case 'mailbox': - - $blocks = array( - 'main' => array('name' => Q(rcube_label('mainoptions'))), - 'new_message' => array('name' => Q(rcube_label('newmessage'))), - ); - - // show config parameter for preview pane - if (!isset($no_override['preview_pane'])) { - $field_id = 'rcmfd_preview'; - $input_preview = new html_checkbox(array('name' => '_preview_pane', 'id' => $field_id, 'value' => 1, - 'onchange' => "$('#rcmfd_preview_pane_mark_read').prop('disabled', !this.checked)")); - - $blocks['main']['options']['preview_pane'] = array( - 'title' => html::label($field_id, Q(rcube_label('previewpane'))), - 'content' => $input_preview->show($config['preview_pane']?1:0), - ); - } - - // show config parameter for preview pane auto mark as read delay - if (!isset($no_override['preview_pane_mark_read'])) { - // apply default if config option is not set at all - $config['preview_pane_mark_read'] = $RCMAIL->config->get('preview_pane_mark_read', 0); - - $field_id = 'rcmfd_preview_pane_mark_read'; - $select_delay = new html_select(array('name' => '_preview_pane_mark_read', 'id' => $field_id, - 'disabled' => $config['preview_pane']?0:1)); - - $select_delay->add(rcube_label('never'), '-1'); - $select_delay->add(rcube_label('immediately'), 0); - foreach(array(5, 10, 20, 30) as $sec) - $select_delay->add(rcube_label(array('name' => 'afternseconds', 'vars' => array('n' => $sec))), $sec); - - $blocks['main']['options']['preview_pane_mark_read'] = array( - 'title' => html::label($field_id, Q(rcube_label('previewpanemarkread'))), - 'content' => $select_delay->show(intval($config['preview_pane_mark_read'])), - ); - } - - if (!isset($no_override['mdn_requests'])) { - $field_id = 'rcmfd_mdn_requests'; - $select_mdn_requests = new html_select(array('name' => '_mdn_requests', 'id' => $field_id)); - $select_mdn_requests->add(rcube_label('askuser'), 0); - $select_mdn_requests->add(rcube_label('autosend'), 1); - $select_mdn_requests->add(rcube_label('autosendknown'), 3); - $select_mdn_requests->add(rcube_label('autosendknownignore'), 4); - $select_mdn_requests->add(rcube_label('ignore'), 2); - - $blocks['main']['options']['mdn_requests'] = array( - 'title' => html::label($field_id, Q(rcube_label('mdnrequests'))), - 'content' => $select_mdn_requests->show($config['mdn_requests']), - ); - } - - $storage = $RCMAIL->get_storage(); - $threading_supported = $storage->get_capability('THREAD'); - - if (!isset($no_override['autoexpand_threads']) && $threading_supported) { - $field_id = 'rcmfd_autoexpand_threads'; - $select_autoexpand_threads = new html_select(array('name' => '_autoexpand_threads', 'id' => $field_id)); - $select_autoexpand_threads->add(rcube_label('never'), 0); - $select_autoexpand_threads->add(rcube_label('do_expand'), 1); - $select_autoexpand_threads->add(rcube_label('expand_only_unread'), 2); - - $blocks['main']['options']['autoexpand_threads'] = array( - 'title' => html::label($field_id, Q(rcube_label('autoexpand_threads'))), - 'content' => $select_autoexpand_threads->show($config['autoexpand_threads']), - ); - } - - // show page size selection - if (!isset($no_override['mail_pagesize'])) { - $field_id = 'rcmfd_mail_pagesize'; - $input_pagesize = new html_inputfield(array('name' => '_mail_pagesize', 'id' => $field_id, 'size' => 5)); - - $size = intval($config['mail_pagesize'] ? $config['mail_pagesize'] : $config['pagesize']); - - $blocks['main']['options']['pagesize'] = array( - 'title' => html::label($field_id, Q(rcube_label('pagesize'))), - 'content' => $input_pagesize->show($size ? $size : 50), - ); - } - if (!isset($no_override['check_all_folders'])) { - $field_id = 'rcmfd_check_all_folders'; - $input_check_all = new html_checkbox(array('name' => '_check_all_folders', 'id' => $field_id, 'value' => 1)); - - $blocks['new_message']['options']['check_all_folders'] = array( - 'title' => html::label($field_id, Q(rcube_label('checkallfolders'))), - 'content' => $input_check_all->show($config['check_all_folders']?1:0), - ); - } - - break; - - // Message viewing - case 'mailview': - - $blocks = array( - 'main' => array('name' => Q(rcube_label('mainoptions'))), - ); - - // show checkbox to open message view in new window - if (!isset($no_override['message_extwin'])) { - $field_id = 'rcmfd_message_extwin'; - $input_msgextwin = new html_checkbox(array('name' => '_message_extwin', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['message_extwin'] = array( - 'title' => html::label($field_id, Q(rcube_label('showinextwin'))), - 'content' => $input_msgextwin->show($config['message_extwin']?1:0), - ); - } - - // show checkbox for HTML/plaintext messages - if (!isset($no_override['prefer_html'])) { - $field_id = 'rcmfd_htmlmsg'; - $input_preferhtml = new html_checkbox(array('name' => '_prefer_html', 'id' => $field_id, 'value' => 1, - 'onchange' => "$('#rcmfd_show_images').prop('disabled', !this.checked).val(0)")); - - $blocks['main']['options']['prefer_html'] = array( - 'title' => html::label($field_id, Q(rcube_label('preferhtml'))), - 'content' => $input_preferhtml->show($config['prefer_html']?1:0), - ); - } - - if (!isset($no_override['default_charset'])) { - $field_id = 'rcmfd_default_charset'; - - $blocks['main']['options']['default_charset'] = array( - 'title' => html::label($field_id, Q(rcube_label('defaultcharset'))), - 'content' => $RCMAIL->output->charset_selector(array( - 'name' => '_default_charset', 'selected' => $config['default_charset'] - )) - ); - } - - if (!isset($no_override['show_images'])) { - $field_id = 'rcmfd_show_images'; - $input_show_images = new html_select(array('name' => '_show_images', 'id' => $field_id, - 'disabled' => !$config['prefer_html'])); - $input_show_images->add(rcube_label('never'), 0); - $input_show_images->add(rcube_label('fromknownsenders'), 1); - $input_show_images->add(rcube_label('always'), 2); - - $blocks['main']['options']['show_images'] = array( - 'title' => html::label($field_id, Q(rcube_label('showremoteimages'))), - 'content' => $input_show_images->show($config['prefer_html'] ? $config['show_images'] : 0), - ); - } - - if (!isset($no_override['inline_images'])) { - $field_id = 'rcmfd_inline_images'; - $input_inline_images = new html_checkbox(array('name' => '_inline_images', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['inline_images'] = array( - 'title' => html::label($field_id, Q(rcube_label('showinlineimages'))), - 'content' => $input_inline_images->show($config['inline_images']?1:0), - ); - } - - // "display after delete" checkbox - if (!isset($no_override['display_next'])) { - $field_id = 'rcmfd_displaynext'; - $input_displaynext = new html_checkbox(array('name' => '_display_next', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['display_next'] = array( - 'title' => html::label($field_id, Q(rcube_label('displaynext'))), - 'content' => $input_displaynext->show($config['display_next']?1:0), - ); - } - - break; - - // Mail composition - case 'compose': - - $blocks = array( - 'main' => array('name' => Q(rcube_label('mainoptions'))), - 'sig' => array('name' => Q(rcube_label('signatureoptions'))), - 'spellcheck' => array('name' => Q(rcube_label('spellcheckoptions'))), - ); - - // show checkbox to compose messages in a new window - if (!isset($no_override['compose_extwin'])) { - $field_id = 'rcmfdcompose_extwin'; - $input_compextwin = new html_checkbox(array('name' => '_compose_extwin', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['compose_extwin'] = array( - 'title' => html::label($field_id, Q(rcube_label('composeextwin'))), - 'content' => $input_compextwin->show($config['compose_extwin']?1:0), - ); - } - - if (!isset($no_override['htmleditor'])) { - $field_id = 'rcmfd_htmleditor'; - $select_htmleditor = new html_select(array('name' => '_htmleditor', 'id' => $field_id)); - $select_htmleditor->add(rcube_label('never'), 0); - $select_htmleditor->add(rcube_label('always'), 1); - $select_htmleditor->add(rcube_label('htmlonreply'), 2); - $select_htmleditor->add(rcube_label('htmlonreplyandforward'), 3); - - $blocks['main']['options']['htmleditor'] = array( - 'title' => html::label($field_id, Q(rcube_label('htmleditor'))), - 'content' => $select_htmleditor->show(intval($config['htmleditor'])), - ); - } - - if (!isset($no_override['draft_autosave'])) { - $field_id = 'rcmfd_autosave'; - $select_autosave = new html_select(array('name' => '_draft_autosave', 'id' => $field_id, 'disabled' => empty($config['drafts_mbox']))); - $select_autosave->add(rcube_label('never'), 0); - foreach (array(1, 3, 5, 10) as $i => $min) - $select_autosave->add(rcube_label(array('name' => 'everynminutes', 'vars' => array('n' => $min))), $min*60); - - $blocks['main']['options']['draft_autosave'] = array( - 'title' => html::label($field_id, Q(rcube_label('autosavedraft'))), - 'content' => $select_autosave->show($config['draft_autosave']), - ); - } - - if (!isset($no_override['mime_param_folding'])) { - $field_id = 'rcmfd_param_folding'; - $select_param_folding = new html_select(array('name' => '_mime_param_folding', 'id' => $field_id)); - $select_param_folding->add(rcube_label('2231folding'), 0); - $select_param_folding->add(rcube_label('miscfolding'), 1); - $select_param_folding->add(rcube_label('2047folding'), 2); - - $blocks['main']['options']['mime_param_folding'] = array( - 'advanced' => true, - 'title' => html::label($field_id, Q(rcube_label('mimeparamfolding'))), - 'content' => $select_param_folding->show($config['mime_param_folding']), - ); - } - if (!isset($no_override['force_7bit'])) { - $field_id = 'rcmfd_force_7bit'; - $input_7bit = new html_checkbox(array('name' => '_force_7bit', 'id' => $field_id, 'value' => 1)); + $found = false; + $data = $RCMAIL->plugins->exec_hook('preferences_list', + array('section' => $sect['id'], 'blocks' => $blocks, 'current' => $current)); - $blocks['main']['options']['force_7bit'] = array( - 'title' => html::label($field_id, Q(rcube_label('force7bit'))), - 'content' => $input_7bit->show($config['force_7bit']?1:0), - ); - } - - if (!isset($no_override['mdn_default'])) { - $field_id = 'rcmfd_mdn_default'; - $input_mdn = new html_checkbox(array('name' => '_mdn_default', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['mdn_default'] = array( - 'title' => html::label($field_id, Q(rcube_label('reqmdn'))), - 'content' => $input_mdn->show($config['mdn_default']?1:0), - ); - } - - if (!isset($no_override['dsn_default'])) { - $field_id = 'rcmfd_dsn_default'; - $input_dsn = new html_checkbox(array('name' => '_dsn_default', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['dsn_default'] = array( - 'title' => html::label($field_id, Q(rcube_label('reqdsn'))), - 'content' => $input_dsn->show($config['dsn_default']?1:0), - ); - } - - if (!isset($no_override['reply_same_folder'])) { - $field_id = 'rcmfd_reply_same_folder'; - $input_reply_same_folder = new html_checkbox(array('name' => '_reply_same_folder', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['reply_same_folder'] = array( - 'title' => html::label($field_id, Q(rcube_label('replysamefolder'))), - 'content' => $input_reply_same_folder->show($config['reply_same_folder']?1:0), - ); - } - - if (!isset($no_override['reply_mode'])) { - $field_id = 'rcmfd_reply_mode'; - $select_replymode = new html_select(array('name' => '_reply_mode', 'id' => $field_id, - 'onchange' => "\$('#rcmfd_sig_above').attr('disabled',this.selectedIndex<2)")); - $select_replymode->add(rcube_label('replyempty'), -1); - $select_replymode->add(rcube_label('replybottomposting'), 0); - $select_replymode->add(rcube_label('replytopposting'), 1); - - $blocks['main']['options']['reply_mode'] = array( - 'title' => html::label($field_id, Q(rcube_label('whenreplying'))), - 'content' => $select_replymode->show(intval($config['reply_mode'])), - ); - } - - if (!isset($no_override['spellcheck_before_send']) && $config['enable_spellcheck']) { - $field_id = 'rcmfd_spellcheck_before_send'; - $input_spellcheck = new html_checkbox(array('name' => '_spellcheck_before_send', 'id' => $field_id, 'value' => 1)); - - $blocks['spellcheck']['options']['spellcheck_before_send'] = array( - 'title' => html::label($field_id, Q(rcube_label('spellcheckbeforesend'))), - 'content' => $input_spellcheck->show($config['spellcheck_before_send']?1:0), - ); - } - - if ($config['enable_spellcheck']) { - foreach (array('syms', 'nums', 'caps') as $key) { - $key = 'spellcheck_ignore_'.$key; - if (!isset($no_override[$key])) { - $input_spellcheck = new html_checkbox(array('name' => '_'.$key, 'id' => 'rcmfd_'.$key, 'value' => 1)); - - $blocks['spellcheck']['options'][$key] = array( - 'title' => html::label($field_id, Q(rcube_label(str_replace('_', '', $key)))), - 'content' => $input_spellcheck->show($config[$key]?1:0), - ); + // create output + foreach ($data['blocks'] as $block) { + if (!empty($block['content']) || !empty($block['options'])) { + $found = true; + break; + } } - } - } - if (!isset($no_override['show_sig'])) { - $field_id = 'rcmfd_show_sig'; - $select_show_sig = new html_select(array('name' => '_show_sig', 'id' => $field_id)); - $select_show_sig->add(rcube_label('never'), 0); - $select_show_sig->add(rcube_label('always'), 1); - $select_show_sig->add(rcube_label('newmessageonly'), 2); - $select_show_sig->add(rcube_label('replyandforwardonly'), 3); - - $blocks['sig']['options']['show_sig'] = array( - 'title' => html::label($field_id, Q(rcube_label('autoaddsignature'))), - 'content' => $select_show_sig->show($RCMAIL->config->get('show_sig', 1)), - ); + if (!$found) + unset($sections[$idx]); + else + $sections[$idx]['blocks'] = $data['blocks']; } - if (!isset($no_override['sig_above'])) { - $field_id = 'rcmfd_sig_above'; - $select_sigabove = new html_select(array('name' => '_sig_above', 'id' => $field_id, 'disabled' => $config['reply_mode'] < 1)); - $select_sigabove->add(rcube_label('belowquote'), 0); - $select_sigabove->add(rcube_label('abovequote'), 1); - - $blocks['sig']['options']['sig_above'] = array( - 'title' => html::label($field_id, Q(rcube_label('replysignaturepos'))), - 'content' => $select_sigabove->show($config['sig_above']?1:0), - ); - } - - if (!isset($no_override['strip_existing_sig'])) { - $field_id = 'rcmfd_strip_existing_sig'; - $input_stripexistingsig = new html_checkbox(array('name' => '_strip_existing_sig', 'id' => $field_id, 'value' => 1)); - - $blocks['sig']['options']['strip_existing_sig'] = array( - 'title' => html::label($field_id, Q(rcube_label('replyremovesignature'))), - 'content' => $input_stripexistingsig->show($config['strip_existing_sig']?1:0), - ); - } - - if (!isset($no_override['forward_attachment'])) { - $field_id = 'rcmfd_forward_attachment'; - $select = new html_select(array('name' => '_forward_attachment', 'id' => $field_id)); - $select->add(rcube_label('inline'), 0); - $select->add(rcube_label('asattachment'), 1); - - $blocks['main']['options']['forward_attachment'] = array( - 'title' => html::label($field_id, Q(rcube_label('forwardmode'))), - 'content' => $select->show(intval($config['forward_attachment'])), - ); - } - - if (!isset($no_override['default_font'])) { - $field_id = 'rcmfd_default_font'; - $fonts = rcube_fontdefs(); - $default_font = $config['default_font'] ? $config['default_font'] : 'Verdana'; - - $select = '<select name="_default_font" id="'.$field_id.'">'; - foreach ($fonts as $fname => $font) - $select .= '<option value="'.$fname.'"' - . ($fname == $default_font ? ' selected="selected"' : '') - . ' style=\'font-family: ' . $font . '\'>' - . Q($fname) . '</option>'; - $select .= '</select>'; - - $blocks['main']['options']['default_font'] = array( - 'title' => html::label($field_id, Q(rcube_label('defaultfont'))), - 'content' => $select - ); - } - - break; - - - // Addressbook config - case 'addressbook': - - $blocks = array( - 'main' => array('name' => Q(rcube_label('mainoptions'))), - ); - - if (!isset($no_override['default_addressbook']) - && ($books = $RCMAIL->get_address_sources(true, true)) - ) { - $field_id = 'rcmfd_default_addressbook'; - $select_abook = new html_select(array('name' => '_default_addressbook', 'id' => $field_id)); - - foreach ($books as $book) { - $select_abook->add(html_entity_decode($book['name'], ENT_COMPAT, 'UTF-8'), $book['id']); - } - - $blocks['main']['options']['default_addressbook'] = array( - 'title' => html::label($field_id, Q(rcube_label('defaultabook'))), - 'content' => $select_abook->show($config['default_addressbook']), - ); - } - - // show addressbook listing mode selection - if (!isset($no_override['addressbook_name_listing'])) { - $field_id = 'rcmfd_addressbook_name_listing'; - $select_listing = new html_select(array('name' => '_addressbook_name_listing', 'id' => $field_id)); - $select_listing->add(rcube_label('name'), 0); - $select_listing->add(rcube_label('firstname') . ' ' . rcube_label('surname'), 1); - $select_listing->add(rcube_label('surname') . ' ' . rcube_label('firstname'), 2); - $select_listing->add(rcube_label('surname') . ', ' . rcube_label('firstname'), 3); - - $blocks['main']['options']['list_name_listing'] = array( - 'title' => html::label($field_id, Q(rcube_label('listnamedisplay'))), - 'content' => $select_listing->show($config['addressbook_name_listing']), - ); - } - - // show addressbook sort column - if (!isset($no_override['addressbook_sort_col'])) { - $field_id = 'rcmfd_addressbook_sort_col'; - $select_sort = new html_select(array('name' => '_addressbook_sort_col', 'id' => $field_id)); - $select_sort->add(rcube_label('name'), 'name'); - $select_sort->add(rcube_label('firstname'), 'firstname'); - $select_sort->add(rcube_label('surname'), 'surname'); - - $blocks['main']['options']['sort_col'] = array( - 'title' => html::label($field_id, Q(rcube_label('listsorting'))), - 'content' => $select_sort->show($config['addressbook_sort_col']), - ); - } - - // show addressbook page size selection - if (!isset($no_override['addressbook_pagesize'])) { - $field_id = 'rcmfd_addressbook_pagesize'; - $input_pagesize = new html_inputfield(array('name' => '_addressbook_pagesize', 'id' => $field_id, 'size' => 5)); - - $size = intval($config['addressbook_pagesize'] ? $config['addressbook_pagesize'] : $config['pagesize']); - - $blocks['main']['options']['pagesize'] = array( - 'title' => html::label($field_id, Q(rcube_label('pagesize'))), - 'content' => $input_pagesize->show($size ? $size : 50), - ); - } - - if (!isset($no_override['autocomplete_single'])) { - $field_id = 'rcmfd_autocomplete_single'; - $checkbox = new html_checkbox(array('name' => '_autocomplete_single', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['autocomplete_single'] = array( - 'title' => html::label($field_id, Q(rcube_label('autocompletesingle'))), - 'content' => $checkbox->show($config['autocomplete_single']?1:0), - ); - } - - break; - - // Special IMAP folders - case 'folders': - - $blocks = array( - 'main' => array('name' => Q(rcube_label('mainoptions'))), - ); - - // Configure special folders - if (!isset($no_override['default_folders'])) { - // load folders list only when needed - if ($current) { - $select = rcmail_mailbox_select(array( - 'noselection' => '---', - 'realnames' => true, - 'maxlength' => 30, - 'folder_filter' => 'mail', - 'folder_rights' => 'w', - // #1486114, #1488279 - 'onchange' => "if ($(this).val() == 'INBOX') $(this).val('')", - )); - } - else // dummy select - $select = new html_select(); - - if (!isset($no_override['drafts_mbox'])) - $blocks['main']['options']['drafts_mbox'] = array( - 'title' => Q(rcube_label('drafts')), - 'content' => $select->show($config['drafts_mbox'], array('name' => "_drafts_mbox")), - ); - - if (!isset($no_override['sent_mbox'])) - $blocks['main']['options']['sent_mbox'] = array( - 'title' => Q(rcube_label('sent')), - 'content' => $select->show($config['sent_mbox'], array('name' => "_sent_mbox")), - ); - - if (!isset($no_override['junk_mbox'])) - $blocks['main']['options']['junk_mbox'] = array( - 'title' => Q(rcube_label('junk')), - 'content' => $select->show($config['junk_mbox'], array('name' => "_junk_mbox")), - ); - - if (!isset($no_override['trash_mbox'])) - $blocks['main']['options']['trash_mbox'] = array( - 'title' => Q(rcube_label('trash')), - 'content' => $select->show($config['trash_mbox'], array('name' => "_trash_mbox")), - ); - } - - break; - - // Server settings - case 'server': - - $blocks = array( - 'main' => array('name' => Q(rcube_label('mainoptions'))), - 'maintenance' => array('name' => Q(rcube_label('maintenance'))), - ); - - if (!isset($no_override['read_when_deleted'])) { - $field_id = 'rcmfd_read_deleted'; - $input_readdeleted = new html_checkbox(array('name' => '_read_when_deleted', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['read_when_deleted'] = array( - 'title' => html::label($field_id, Q(rcube_label('readwhendeleted'))), - 'content' => $input_readdeleted->show($config['read_when_deleted']?1:0), - ); - } - - if (!isset($no_override['flag_for_deletion'])) { - $field_id = 'rcmfd_flag_for_deletion'; - $input_flagfordeletion = new html_checkbox(array('name' => '_flag_for_deletion', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['flag_for_deletion'] = array( - 'title' => html::label($field_id, Q(rcube_label('flagfordeletion'))), - 'content' => $input_flagfordeletion->show($config['flag_for_deletion']?1:0), - ); - } - - // don't show deleted messages - if (!isset($no_override['skip_deleted'])) { - $field_id = 'rcmfd_skip_deleted'; - $input_purge = new html_checkbox(array('name' => '_skip_deleted', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['skip_deleted'] = array( - 'title' => html::label($field_id, Q(rcube_label('skipdeleted'))), - 'content' => $input_purge->show($config['skip_deleted']?1:0), - ); - } - - if (!isset($no_override['delete_always'])) { - $field_id = 'rcmfd_delete_always'; - $input_delete_always = new html_checkbox(array('name' => '_delete_always', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['delete_always'] = array( - 'title' => html::label($field_id, Q(rcube_label('deletealways'))), - 'content' => $input_delete_always->show($config['delete_always']?1:0), - ); - } - - if (!isset($no_override['delete_junk'])) { - $field_id = 'rcmfd_delete_junk'; - $input_delete_junk = new html_checkbox(array('name' => '_delete_junk', 'id' => $field_id, 'value' => 1)); - - $blocks['main']['options']['delete_junk'] = array( - 'title' => html::label($field_id, Q(rcube_label('deletejunk'))), - 'content' => $input_delete_junk->show($config['delete_junk']?1:0), - ); - } - - // Trash purging on logout - if (!isset($no_override['logout_purge'])) { - $field_id = 'rcmfd_logout_purge'; - $input_purge = new html_checkbox(array('name' => '_logout_purge', 'id' => $field_id, 'value' => 1)); - - $blocks['maintenance']['options']['logout_purge'] = array( - 'title' => html::label($field_id, Q(rcube_label('logoutclear'))), - 'content' => $input_purge->show($config['logout_purge']?1:0), - ); - } - - // INBOX compacting on logout - if (!isset($no_override['logout_expunge'])) { - $field_id = 'rcmfd_logout_expunge'; - $input_expunge = new html_checkbox(array('name' => '_logout_expunge', 'id' => $field_id, 'value' => 1)); - - $blocks['maintenance']['options']['logout_expunge'] = array( - 'title' => html::label($field_id, Q(rcube_label('logoutcompact'))), - 'content' => $input_expunge->show($config['logout_expunge']?1:0), - ); - } - - break; - } - - $data = $RCMAIL->plugins->exec_hook('preferences_list', array('section' => $sect['id'], 'blocks' => $blocks)); - $found = false; - - // create output - foreach ($data['blocks'] as $block) { - if (!empty($block['content']) || !empty($block['options'])) { - $found = true; - break; - } - } - - if (!$found) - unset($sections[$idx]); - else - $sections[$idx]['blocks'] = $data['blocks']; - } - - return array($sections, $plugin['cols']); + return array($sections, $plugin['cols']); } function rcmail_get_skins() { - $path = 'skins'; - $skins = array(); - - $dir = opendir($path); + $path = RCUBE_INSTALL_PATH . 'skins'; + $skins = array(); + $dir = opendir($path); - if (!$dir) - return false; + if (!$dir) { + return false; + } - while (($file = readdir($dir)) !== false) - { - $filename = $path.'/'.$file; - if (!preg_match('/^\./', $file) && is_dir($filename) && is_readable($filename)) - $skins[] = $file; - } + while (($file = readdir($dir)) !== false) { + $filename = $path.'/'.$file; + if (!preg_match('/^\./', $file) && is_dir($filename) && is_readable($filename)) { + $skins[] = $file; + } + } - closedir($dir); + closedir($dir); - return $skins; + return $skins; } @@ -989,9 +1237,9 @@ function rcmail_update_folder_row($name, $oldname=null, $subscribe=false, $class // register UI objects $OUTPUT->add_handlers(array( - 'prefsframe' => 'rcmail_preferences_frame', - 'sectionslist' => 'rcmail_sections_list', - 'identitieslist' => 'rcmail_identities_list', + 'prefsframe' => 'rcmail_preferences_frame', + 'sectionslist' => 'rcmail_sections_list', + 'identitieslist' => 'rcmail_identities_list', )); // register action aliases diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc index 5daab0d24..19edb41d4 100644 --- a/program/steps/settings/save_prefs.inc +++ b/program/steps/settings/save_prefs.inc @@ -34,6 +34,7 @@ switch ($CURR_SECTION) 'time_format' => isset($_POST['_time_format']) ? get_input_value('_time_format', RCUBE_INPUT_POST) : ($CONFIG['time_format'] ? $CONFIG['time_format'] : 'H:i'), 'prettydate' => isset($_POST['_pretty_date']) ? TRUE : FALSE, 'refresh_interval' => isset($_POST['_refresh_interval']) ? intval($_POST['_refresh_interval'])*60 : $CONFIG['refresh_interval'], + 'standard_windows' => isset($_POST['_standard_windows']) ? TRUE : FALSE, 'skin' => isset($_POST['_skin']) ? get_input_value('_skin', RCUBE_INPUT_POST) : $CONFIG['skin'], ); @@ -60,6 +61,7 @@ switch ($CURR_SECTION) case 'mailview': $a_user_prefs = array( 'message_extwin' => intval($_POST['_message_extwin']), + 'message_show_email' => isset($_POST['_message_show_email']) ? TRUE : FALSE, 'prefer_html' => isset($_POST['_prefer_html']) ? TRUE : FALSE, 'inline_images' => isset($_POST['_inline_images']) ? TRUE : FALSE, 'show_images' => isset($_POST['_show_images']) ? intval($_POST['_show_images']) : 0, @@ -86,7 +88,6 @@ switch ($CURR_SECTION) 'show_sig' => isset($_POST['_show_sig']) ? intval($_POST['_show_sig']) : 1, 'reply_mode' => isset($_POST['_reply_mode']) ? intval($_POST['_reply_mode']) : 0, 'strip_existing_sig' => isset($_POST['_strip_existing_sig']), - 'sig_above' => !empty($_POST['_sig_above']) && $_POST['_reply_mode'] > 0, 'default_font' => get_input_value('_default_font', RCUBE_INPUT_POST), 'forward_attachment' => !empty($_POST['_forward_attachment']), ); @@ -119,6 +120,8 @@ switch ($CURR_SECTION) case 'folders': $a_user_prefs = array( + 'show_real_foldernames' => + isset($_POST['_show_real_foldernames']) ? TRUE : FALSE, 'drafts_mbox' => get_input_value('_drafts_mbox', RCUBE_INPUT_POST, true), 'sent_mbox' => get_input_value('_sent_mbox', RCUBE_INPUT_POST, true), 'junk_mbox' => get_input_value('_junk_mbox', RCUBE_INPUT_POST, true), @@ -158,7 +161,7 @@ switch ($CURR_SECTION) $a_user_prefs['timezone'] = (string) $a_user_prefs['timezone']; if (isset($a_user_prefs['refresh_interval']) && !empty($CONFIG['min_refresh_interval'])) { - if ($a_user_prefs['refresh_interval'] > $CONFIG['min_refresh_interval']) { + if ($a_user_prefs['refresh_interval'] < $CONFIG['min_refresh_interval']) { $a_user_prefs['refresh_interval'] = $CONFIG['min_refresh_interval']; } } diff --git a/program/steps/utils/save_pref.inc b/program/steps/utils/save_pref.inc index b550ad7ef..7def8733d 100644 --- a/program/steps/utils/save_pref.inc +++ b/program/steps/utils/save_pref.inc @@ -21,6 +21,22 @@ $name = get_input_value('_name', RCUBE_INPUT_POST); $value = get_input_value('_value', RCUBE_INPUT_POST); +$whitelist = array( + 'preview_pane', + 'list_cols', + 'collapsed_folders', + 'collapsed_abooks', +); + +if (!in_array($name, array_merge($whitelist, $RCMAIL->plugins->allowed_prefs))) { + raise_error(array('code' => 500, 'type' => 'php', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => sprintf("Hack attempt detected (user: %s)", $RCMAIL->get_user_name())), + true, false); + + $OUTPUT->reset(); + $OUTPUT->send(); +} // save preference value $RCMAIL->user->save_prefs(array($name => $value)); diff --git a/program/steps/utils/spell.inc b/program/steps/utils/spell.inc index a0dd35d27..38e4ca285 100644 --- a/program/steps/utils/spell.inc +++ b/program/steps/utils/spell.inc @@ -42,6 +42,13 @@ else { $result = $spellchecker->get_xml(); } +if ($err = $spellchecker->error()) { + rcube::raise_error(array('code' => 500, 'type' => 'php', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => sprintf("Spell check engine error: " . $err)), + true, false); +} + // set response length header("Content-Length: " . strlen($result)); diff --git a/program/steps/utils/spell_html.inc b/program/steps/utils/spell_html.inc index 861e4ba48..96b41e230 100644 --- a/program/steps/utils/spell_html.inc +++ b/program/steps/utils/spell_html.inc @@ -46,6 +46,11 @@ else if ($request['method'] == 'learnWord') { } if ($error = $spellchecker->error()) { + rcube::raise_error(array('code' => 500, 'type' => 'php', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => sprintf("Spell check engine error: " . $error)), + true, false); + echo '{"error":{"errstr":"' . addslashes($error) . '","errfile":"","errline":null,"errcontext":"","level":"FATAL"}}'; exit; } |